| author | |
| committer | |
| log | cad75a7106cadd971f4cdc0ec4f3ee0fbe2adf09 |
| tree | 21c6cdcc1cfc63135e851e929882170032744bae |
| parent | ccbfd60e32be0412ed12f7d3bfd979dfc5c69e94 |
| parent | cb7c6e391872d2922a688c77def805883b69eba8 |
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 | 153 | fetch-depth: 0 |
| 154 | 154 | - name: Build and Test |
| 155 | 155 | run: sh ci/s390x-linux-debug.sh |
| 156 | timeout-minutes: 420 | |
| 156 | timeout-minutes: 480 | |
| 157 | 157 | s390x-linux-release: |
| 158 | 158 | runs-on: [self-hosted, s390x-linux] |
| 159 | 159 | steps: |
| ... | ... | @@ -174,7 +174,7 @@ jobs: |
| 174 | 174 | fetch-depth: 0 |
| 175 | 175 | - name: Build and Test |
| 176 | 176 | run: sh ci/x86_64-freebsd-debug.sh |
| 177 | timeout-minutes: 120 | |
| 177 | timeout-minutes: 1440 | |
| 178 | 178 | x86_64-freebsd-release: |
| 179 | 179 | runs-on: [self-hosted, x86_64-freebsd] |
| 180 | 180 | steps: |
| ... | ... | @@ -184,7 +184,7 @@ jobs: |
| 184 | 184 | fetch-depth: 0 |
| 185 | 185 | - name: Build and Test |
| 186 | 186 | run: sh ci/x86_64-freebsd-release.sh |
| 187 | timeout-minutes: 120 | |
| 187 | timeout-minutes: 1440 | |
| 188 | 188 | |
| 189 | 189 | x86_64-linux-debug: |
| 190 | 190 | runs-on: [self-hosted, x86_64-linux] |
CMakeLists.txt+8-13| ... | ... | @@ -358,6 +358,8 @@ set(ZIG_STAGE2_SOURCES |
| 358 | 358 | src/codegen/c/type/render_defs.zig |
| 359 | 359 | src/codegen/llvm.zig |
| 360 | 360 | src/codegen/llvm/bindings.zig |
| 361 | src/codegen/loongarch/abi.zig | |
| 362 | src/codegen/s390x/abi.zig | |
| 361 | 363 | src/crash_report.zig |
| 362 | 364 | src/dev.zig |
| 363 | 365 | src/libs/freebsd.zig |
| ... | ... | @@ -600,24 +602,17 @@ if(MSVC) |
| 600 | 602 | set(ZIG2_COMPILE_FLAGS "/Od") |
| 601 | 603 | set(ZIG2_LINK_FLAGS "/STACK:16777216 /FORCE:MULTIPLE") |
| 602 | 604 | else() |
| 603 | set(ZIG_WASM2C_COMPILE_FLAGS "-std=c99 -O2") | |
| 604 | set(ZIG1_COMPILE_FLAGS "-std=c99 -Os -fno-strict-aliasing") | |
| 605 | set(ZIG2_COMPILE_FLAGS "-std=c99 -O0 -fno-sanitize=undefined -fno-stack-protector -fno-strict-aliasing") | |
| 605 | set(ZIG_WASM2C_COMPILE_FLAGS "-std=c99") | |
| 606 | set(ZIG1_COMPILE_FLAGS "-std=c99 -Oz -fno-strict-aliasing") | |
| 607 | set(ZIG2_COMPILE_FLAGS "-std=c99 -Oz -fno-sanitize=undefined -fno-stack-protector -fno-strict-aliasing") | |
| 608 | if(CMAKE_C_COMPILER_ID STREQUAL "Clang" AND ZIG_HOST_TARGET_ARCH STREQUAL "s390x") | |
| 609 | string(REPLACE -Oz -O0 ZIG2_COMPILE_FLAGS "${ZIG2_COMPILE_FLAGS}") # llvm 22 assertion failure | |
| 610 | endif() | |
| 606 | 611 | # Must match the condition in build.zig. |
| 607 | 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 | 613 | set(ZIG1_COMPILE_FLAGS "${ZIG1_COMPILE_FLAGS} -ffunction-sections -fdata-sections") |
| 609 | 614 | set(ZIG2_COMPILE_FLAGS "${ZIG2_COMPILE_FLAGS} -ffunction-sections -fdata-sections") |
| 610 | 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 | 616 | if (CMAKE_C_COMPILER_ID STREQUAL "GNU") |
| 622 | 617 | # Prevent GCC from miscompiling 'zig2.c'. See also 'GCC_BUG_119085_PRESENT' workaround details in 'bootstrap.c'. |
| 623 | 618 | if ( |
bootstrap.c+2-2| ... | ... | @@ -56,7 +56,7 @@ static void panic(const char *reason) { |
| 56 | 56 | #define GCC_BUG_119085_PRESENT 0 |
| 57 | 57 | #endif |
| 58 | 58 | |
| 59 | #if defined(__WIN32__) | |
| 59 | #if defined(_WIN32) | |
| 60 | 60 | #error TODO write the functionality for executing child process into this build script |
| 61 | 61 | #else |
| 62 | 62 | |
| ... | ... | @@ -99,7 +99,7 @@ static void print_and_run(const char **argv) { |
| 99 | 99 | static const char *get_host_os(void) { |
| 100 | 100 | const char *host_os = getenv("ZIG_HOST_TARGET_OS"); |
| 101 | 101 | if (host_os != NULL) return host_os; |
| 102 | #if defined(__WIN32__) | |
| 102 | #if defined(_WIN32) | |
| 103 | 103 | return "windows"; |
| 104 | 104 | #elif defined(__APPLE__) |
| 105 | 105 | return "macos"; |
build.zig+11-11| ... | ... | @@ -207,7 +207,7 @@ pub fn build(b: *std.Build) !void { |
| 207 | 207 | |
| 208 | 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 | 209 | if (strip == true) break :blk @as(u32, 0); |
| 210 | if (optimize != .Debug) break :blk 0; | |
| 210 | if (optimize != .debug) break :blk 0; | |
| 211 | 211 | break :blk 4; |
| 212 | 212 | }; |
| 213 | 213 | |
| ... | ... | @@ -256,7 +256,7 @@ pub fn build(b: *std.Build) !void { |
| 256 | 256 | exe.root_module.link_libc = true; |
| 257 | 257 | } |
| 258 | 258 | |
| 259 | const is_debug = optimize == .Debug; | |
| 259 | const is_debug = optimize == .debug; | |
| 260 | 260 | const enable_debug_extensions = b.option(bool, "debug-extensions", "Enable commands and options useful for debugging the compiler") orelse is_debug; |
| 261 | 261 | const enable_logging = b.option(bool, "log", "Enable debug logging with --debug-log") orelse is_debug; |
| 262 | 262 | |
| ... | ... | @@ -403,8 +403,8 @@ pub fn build(b: *std.Build) !void { |
| 403 | 403 | if (tracy) |tracy_dir| { |
| 404 | 404 | const tracy_mod = b.createModule(.{ |
| 405 | 405 | .target = target, |
| 406 | // Always build Tracy in ReleaseFast so that it doesn't make Debug compiler builds unusable. | |
| 407 | .optimize = .ReleaseFast, | |
| 406 | // Always build Tracy in ReleaseFast so that it doesn't make -Odebug compiler builds unusable. | |
| 407 | .optimize = .fast, | |
| 408 | 408 | .root_source_file = null, |
| 409 | 409 | .link_libc = true, |
| 410 | 410 | .link_libcpp = true, |
| ... | ... | @@ -434,19 +434,19 @@ pub fn build(b: *std.Build) !void { |
| 434 | 434 | var chosen_opt_modes_buf: [4]std.lang.OptimizeMode = undefined; |
| 435 | 435 | var chosen_mode_index: usize = 0; |
| 436 | 436 | if (!skip_debug) { |
| 437 | chosen_opt_modes_buf[chosen_mode_index] = .Debug; | |
| 437 | chosen_opt_modes_buf[chosen_mode_index] = .debug; | |
| 438 | 438 | chosen_mode_index += 1; |
| 439 | 439 | } |
| 440 | 440 | if (!skip_release_safe) { |
| 441 | chosen_opt_modes_buf[chosen_mode_index] = .ReleaseSafe; | |
| 441 | chosen_opt_modes_buf[chosen_mode_index] = .safe; | |
| 442 | 442 | chosen_mode_index += 1; |
| 443 | 443 | } |
| 444 | 444 | if (!skip_release_fast) { |
| 445 | chosen_opt_modes_buf[chosen_mode_index] = .ReleaseFast; | |
| 445 | chosen_opt_modes_buf[chosen_mode_index] = .fast; | |
| 446 | 446 | chosen_mode_index += 1; |
| 447 | 447 | } |
| 448 | 448 | if (!skip_release_small) { |
| 449 | chosen_opt_modes_buf[chosen_mode_index] = .ReleaseSmall; | |
| 449 | chosen_opt_modes_buf[chosen_mode_index] = .small; | |
| 450 | 450 | chosen_mode_index += 1; |
| 451 | 451 | } |
| 452 | 452 | const optimize_modes = chosen_opt_modes_buf[0..chosen_mode_index]; |
| ... | ... | @@ -622,7 +622,7 @@ pub fn build(b: *std.Build) !void { |
| 622 | 622 | .use_llvm = use_llvm, |
| 623 | 623 | .use_lld = use_llvm, |
| 624 | 624 | .zig_lib_dir = b.path("lib"), |
| 625 | .max_rss = 2_700_000_000, | |
| 625 | .max_rss = 3_000_000_000, | |
| 626 | 626 | }); |
| 627 | 627 | if (link_libc) { |
| 628 | 628 | unit_tests.root_module.link_libc = true; |
| ... | ... | @@ -763,9 +763,8 @@ fn addWasiUpdateStep(b: *std.Build, version: [:0]const u8) !void { |
| 763 | 763 | .optimize = .ReleaseSmall, |
| 764 | 764 | .target = b.resolveTargetQuery(std.Target.Query.parse(.{ |
| 765 | 765 | .arch_os_abi = "wasm32-wasi", |
| 766 | // * `extended_const` is not supported by the `wasm-opt` version in CI. | |
| 767 | 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 | 768 | }) catch unreachable), |
| 770 | 769 | }); |
| 771 | 770 | |
| ... | ... | @@ -809,6 +808,7 @@ fn addWasiUpdateStep(b: *std.Build, version: [:0]const u8) !void { |
| 809 | 808 | "-Oz", |
| 810 | 809 | "--enable-bulk-memory", |
| 811 | 810 | "--enable-mutable-globals", |
| 811 | "--enable-extended-const", | |
| 812 | 812 | "--enable-nontrapping-float-to-int", |
| 813 | 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 | 46 | stage3-debug/bin/zig build test docs \ |
| 47 | 47 | --maxrss ${ZSF_MAX_RSS:-0} \ |
| 48 | 48 | -Dstatic-llvm \ |
| 49 | -Dskip-spirv \ | |
| 50 | -Dskip-wasm \ | |
| 51 | -Dskip-linux \ | |
| 52 | -Dskip-netbsd \ | |
| 53 | -Dskip-openbsd \ | |
| 54 | -Dskip-windows \ | |
| 55 | -Dskip-darwin \ | |
| 49 | -Dskip-non-native \ | |
| 56 | 50 | --search-prefix "$PREFIX" \ |
| 57 | 51 | --test-timeout 2m |
| 58 | 52 |
ci/x86_64-freebsd-release.sh+1-7| ... | ... | @@ -46,13 +46,7 @@ export ZIG_LIB_DIR="$PWD/../lib" |
| 46 | 46 | stage3-release/bin/zig build test docs \ |
| 47 | 47 | --maxrss ${ZSF_MAX_RSS:-0} \ |
| 48 | 48 | -Dstatic-llvm \ |
| 49 | -Dskip-spirv \ | |
| 50 | -Dskip-wasm \ | |
| 51 | -Dskip-linux \ | |
| 52 | -Dskip-netbsd \ | |
| 53 | -Dskip-openbsd \ | |
| 54 | -Dskip-windows \ | |
| 55 | -Dskip-darwin \ | |
| 49 | -Dskip-non-native \ | |
| 56 | 50 | --search-prefix "$PREFIX" \ |
| 57 | 51 | --test-timeout 2m |
| 58 | 52 |
ci/x86_64-linux-debug.sh+1-1| ... | ... | @@ -44,7 +44,7 @@ ninja install |
| 44 | 44 | |
| 45 | 45 | # Must be done after zig cc is finished. |
| 46 | 46 | export ZIG_LIB_DIR="$PWD/../lib" |
| 47 | export ZIG_DEBUG_MAKER=1 | |
| 47 | export ZIG_DEBUG_CMD=1 | |
| 48 | 48 | |
| 49 | 49 | # simultaneously test building self-hosted without LLVM and with 32-bit arm |
| 50 | 50 | stage3-debug/bin/zig build \ |
doc/langref.html.in+6-2| ... | ... | @@ -1119,6 +1119,10 @@ |
| 1119 | 1119 | otherwise the optimizer figures out all the values at compile-time, |
| 1120 | 1120 | which operates in strict mode.</p> |
| 1121 | 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 | |
| 1124 | optimized = 0.001 | |
| 1125 | strict = 0.0009765625{#end_shell_samp#} | |
| 1122 | 1126 | |
| 1123 | 1127 | {#see_also|@setFloatMode|Division by Zero#} |
| 1124 | 1128 | {#header_close#} |
| ... | ... | @@ -5848,7 +5852,7 @@ fn cmpxchgWeakButNotAtomic(comptime T: type, ptr: *T, expected_value: T, new_val |
| 5848 | 5852 | {#header_open|@Union#} |
| 5849 | 5853 | <pre>{#syntax#}@Union( |
| 5850 | 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 | 5856 | comptime ArgType: ?type, |
| 5853 | 5857 | comptime field_names: []const []const u8, |
| 5854 | 5858 | comptime field_types: *const [field_names.len]type, |
| ... | ... | @@ -7499,7 +7503,7 @@ fn readU32Be() u32 {} |
| 7499 | 7503 | <pre>{#syntax#}errdefer{#endsyntax#}</pre> |
| 7500 | 7504 | </th> |
| 7501 | 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 | 7507 | <ul> |
| 7504 | 7508 | <li>See also {#link|errdefer#}</li> |
| 7505 | 7509 | </ul> |
doc/langref/test_packed_structs.zig-1| ... | ... | @@ -1,5 +1,4 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | const native_endian = @import("builtin").target.cpu.arch.endian(); | |
| 3 | 2 | const expectEqual = std.testing.expectEqual; |
| 4 | 3 | |
| 5 | 4 | const 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 | 84 | defer gpa.free(slowest_decls); |
| 85 | 85 | |
| 86 | 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 | 88 | file_out.* = .{ |
| 89 | 89 | .name = trailing[0..i], |
| 90 | 90 | .ns_sema = 0, |
| ... | ... | @@ -95,7 +95,7 @@ pub fn compileResultMessage(msg_bytes: []u8) error{ OutOfMemory, WriteFailed }!v |
| 95 | 95 | } |
| 96 | 96 | |
| 97 | 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 | 99 | const file_idx = std.mem.readInt(u32, trailing[i..][1..5], .little); |
| 100 | 100 | const sema_count = std.mem.readInt(u32, trailing[i..][5..9], .little); |
| 101 | 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 | 258 | defer table_html.deinit(gpa); |
| 259 | 259 | |
| 260 | 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 | 262 | const test_name = trailing[offset..][0..test_name_len]; |
| 263 | 263 | offset += test_name_len + 1; |
| 264 | 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 | 59 | } |
| 60 | 60 | |
| 61 | 61 | const safety = switch (builtin.mode) { |
| 62 | .Debug, .ReleaseSafe => true, | |
| 63 | .ReleaseFast, .ReleaseSmall => false, | |
| 62 | .debug, .safe => true, | |
| 63 | .fast, .small => false, | |
| 64 | 64 | }; |
| 65 | 65 | const max_addr_bits = switch (safety) { |
| 66 | 66 | true => 48, // Ensures space for Canary bits. |
lib/compiler/Maker.zig+339-78| ... | ... | @@ -11,6 +11,7 @@ const File = std.Io.File; |
| 11 | 11 | const Io = std.Io; |
| 12 | 12 | const Dir = std.Io.Dir; |
| 13 | 13 | const Path = std.Build.Cache.Path; |
| 14 | const Reader = std.Io.Reader; | |
| 14 | 15 | const Writer = std.Io.Writer; |
| 15 | 16 | const assert = std.debug.assert; |
| 16 | 17 | const fatal = std.process.fatal; |
| ... | ... | @@ -19,6 +20,8 @@ const log = std.log; |
| 19 | 20 | const mem = std.mem; |
| 20 | 21 | const process = std.process; |
| 21 | 22 | const Color = std.zig.Color; |
| 23 | const Client = std.zig.Client; | |
| 24 | const Server = std.zig.Server; | |
| 22 | 25 | const EnvVar = std.zig.EnvVar; |
| 23 | 26 | const default_local_zig_cache_basename = std.zig.default_local_zig_cache_basename; |
| 24 | 27 | const stringToEnum = std.meta.stringToEnum; |
| ... | ... | @@ -51,10 +54,14 @@ max_rss_mutex: Io.Mutex, |
| 51 | 54 | skip_oom_steps: bool, |
| 52 | 55 | unit_test_timeout_ns: ?u64, |
| 53 | 56 | watch: bool, |
| 57 | protocol_server: ?*AvoidableServer, | |
| 58 | protocol_server_mutex: Io.Mutex, | |
| 54 | 59 | web_server: ?*AvoidableWebServer, |
| 55 | 60 | /// Allocated into `gpa`. |
| 56 | 61 | memory_blocked_steps: std.ArrayList(Configuration.Step.Index), |
| 57 | 62 | /// Allocated into `gpa`. |
| 63 | initial_steps: std.array_hash_map.Auto(Configuration.Step.Index, void), | |
| 64 | /// Allocated into `gpa`. | |
| 58 | 65 | step_stack: std.array_hash_map.Auto(Configuration.Step.Index, void), |
| 59 | 66 | pkg_config: PkgConfig, |
| 60 | 67 | |
| ... | ... | @@ -67,12 +74,13 @@ var stdio_buffer_allocation: [256]u8 = undefined; |
| 67 | 74 | var stdout_writer_allocation: Io.File.Writer = undefined; |
| 68 | 75 | var debug_maker_leaks: bool = false; |
| 69 | 76 | |
| 77 | const AvoidableServer = if (builtin.single_threaded) void else Server; | |
| 70 | 78 | const AvoidableWebServer = if (builtin.single_threaded) void else WebServer; |
| 71 | 79 | |
| 72 | const is_debug_mode = builtin.mode == .Debug; | |
| 80 | const is_debug_mode = builtin.mode == .debug; | |
| 73 | 81 | const use_safe_allocator = switch (builtin.mode) { |
| 74 | .Debug, .ReleaseSafe => true, | |
| 75 | .ReleaseFast, .ReleaseSmall => false, | |
| 82 | .debug, .safe => true, | |
| 83 | .fast, .small => false, | |
| 76 | 84 | }; |
| 77 | 85 | |
| 78 | 86 | const InstallPaths = struct { |
| ... | ... | @@ -216,6 +224,7 @@ pub fn main(init: process.Init.Minimal) !void { |
| 216 | 224 | var watch = false; |
| 217 | 225 | var fuzz: ?Fuzz.Mode = null; |
| 218 | 226 | var debounce_interval_ms: u16 = 50; |
| 227 | var listen: bool = false; | |
| 219 | 228 | var webui_listen: ?Io.net.IpAddress = null; |
| 220 | 229 | var debug_pkg_config = false; |
| 221 | 230 | var run_args: ?[]const []const u8 = null; |
| ... | ... | @@ -242,6 +251,12 @@ pub fn main(init: process.Init.Minimal) !void { |
| 242 | 251 | } |
| 243 | 252 | } |
| 244 | 253 | |
| 254 | if (EnvVar.ZIG_BUILD_SUMMARY.get(&graph.environ_map)) |str| { | |
| 255 | if (stringToEnum(Summary, str)) |value| { | |
| 256 | summary = value; | |
| 257 | } | |
| 258 | } | |
| 259 | ||
| 245 | 260 | try configure_argv.ensureUnusedCapacity(arena, 16); |
| 246 | 261 | try cached_passthru_configure.ensureUnusedCapacity(arena, 16); |
| 247 | 262 | |
| ... | ... | @@ -416,6 +431,8 @@ pub fn main(init: process.Init.Minimal) !void { |
| 416 | 431 | next_arg, err, |
| 417 | 432 | }); |
| 418 | 433 | }; |
| 434 | } else if (mem.eql(u8, arg, "--listen=-")) { | |
| 435 | listen = true; | |
| 419 | 436 | } else if (mem.eql(u8, arg, "--webui")) { |
| 420 | 437 | if (webui_listen == null) webui_listen = .{ .ip6 = .loopback(0) }; |
| 421 | 438 | } else if (mem.startsWith(u8, arg, "--webui=")) { |
| ... | ... | @@ -553,7 +570,7 @@ pub fn main(init: process.Init.Minimal) !void { |
| 553 | 570 | } |
| 554 | 571 | |
| 555 | 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); | |
| 557 | 574 | |
| 558 | 575 | process.raiseFileDescriptorLimit(); |
| 559 | 576 | |
| ... | ... | @@ -631,20 +648,31 @@ pub fn main(init: process.Init.Minimal) !void { |
| 631 | 648 | .sub_path = "zig-out", |
| 632 | 649 | }; |
| 633 | 650 | |
| 634 | const install_lib_path: Path = if (override_lib_dir) |cwd_relative| .{ | |
| 635 | .root_dir = .cwd(), | |
| 636 | .sub_path = cwd_relative, | |
| 637 | } else try install_prefix_path.join(arena, "lib"); | |
| 651 | // These three overrides are meant to be relative to the install prefix, | |
| 652 | // not current working directory, unless absolute paths are used. | |
| 653 | const install_lib_path: Path = if (override_lib_dir) |lib_dir| | |
| 654 | if (Dir.path.isAbsolute(lib_dir)) .{ | |
| 655 | .root_dir = .cwd(), | |
| 656 | .sub_path = lib_dir, | |
| 657 | } else try install_prefix_path.join(arena, lib_dir) | |
| 658 | else | |
| 659 | try install_prefix_path.join(arena, "lib"); | |
| 638 | 660 | |
| 639 | const install_bin_path: Path = if (override_bin_dir) |cwd_relative| .{ | |
| 640 | .root_dir = .cwd(), | |
| 641 | .sub_path = cwd_relative, | |
| 642 | } else try install_prefix_path.join(arena, "bin"); | |
| 661 | const install_bin_path: Path = if (override_bin_dir) |bin_dir| | |
| 662 | if (Dir.path.isAbsolute(bin_dir)) .{ | |
| 663 | .root_dir = .cwd(), | |
| 664 | .sub_path = bin_dir, | |
| 665 | } else try install_prefix_path.join(arena, bin_dir) | |
| 666 | else | |
| 667 | try install_prefix_path.join(arena, "bin"); | |
| 643 | 668 | |
| 644 | const install_include_path: Path = if (override_include_dir) |cwd_relative| .{ | |
| 645 | .root_dir = .cwd(), | |
| 646 | .sub_path = cwd_relative, | |
| 647 | } else try install_prefix_path.join(arena, "include"); | |
| 669 | const install_include_path: Path = if (override_include_dir) |include_dir| | |
| 670 | if (Dir.path.isAbsolute(include_dir)) .{ | |
| 671 | .root_dir = .cwd(), | |
| 672 | .sub_path = include_dir, | |
| 673 | } else try install_prefix_path.join(arena, include_dir) | |
| 674 | else | |
| 675 | try install_prefix_path.join(arena, "include"); | |
| 648 | 676 | |
| 649 | 677 | const now = Io.Clock.Timestamp.now(io, .awake); |
| 650 | 678 | |
| ... | ... | @@ -661,6 +689,25 @@ pub fn main(init: process.Init.Minimal) !void { |
| 661 | 689 | break :ws &web_server_allocation; |
| 662 | 690 | } else null; |
| 663 | 691 | |
| 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 | 711 | while (true) { |
| 665 | 712 | // If this fails, we can still start the server and wait for user |
| 666 | 713 | // to request a rebuild. If it returns error.FailedButCacheIntact |
| ... | ... | @@ -731,16 +778,25 @@ pub fn main(init: process.Init.Minimal) !void { |
| 731 | 778 | |
| 732 | 779 | .watch = watch, |
| 733 | 780 | .web_server = web_server, |
| 781 | .protocol_server = protocol_server, | |
| 782 | .protocol_server_mutex = .init, | |
| 734 | 783 | .memory_blocked_steps = .empty, |
| 784 | .initial_steps = .empty, | |
| 735 | 785 | .step_stack = .empty, |
| 736 | 786 | .pkg_config = .{ .debug = debug_pkg_config }, |
| 737 | 787 | |
| 738 | 788 | .error_style = error_style, |
| 739 | 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 | 797 | defer { |
| 743 | 798 | maker.memory_blocked_steps.deinit(gpa); |
| 799 | maker.initial_steps.deinit(gpa); | |
| 744 | 800 | maker.step_stack.deinit(gpa); |
| 745 | 801 | } |
| 746 | 802 | |
| ... | ... | @@ -749,7 +805,91 @@ pub fn main(init: process.Init.Minimal) !void { |
| 749 | 805 | maker.max_rss_is_default = true; |
| 750 | 806 | } |
| 751 | 807 | |
| 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 | 893 | error.DependencyLoopDetected, error.InsufficientMemory => { |
| 754 | 894 | // TODO handle DependencyLoopDetected as error.FailedButCacheIntact |
| 755 | 895 | // and handle InsufficientMemory as error.AlreadyReported |
| ... | ... | @@ -774,18 +914,7 @@ pub fn main(init: process.Init.Minimal) !void { |
| 774 | 914 | error.WriteFailed => return stderr.file_writer.err.?, |
| 775 | 915 | }; |
| 776 | 916 | }) { |
| 777 | if (web_server) |ws| ws.startBuild(); | |
| 778 | ||
| 779 | try maker.makeStepNames(step_names.items, main_progress_node, fuzz); | |
| 780 | ||
| 781 | if (web_server) |ws| { | |
| 782 | if (fuzz) |mode| if (mode != .forever) fatal( | |
| 783 | "error: limited fuzzing is not implemented yet for --webui", | |
| 784 | .{}, | |
| 785 | ); | |
| 786 | ||
| 787 | ws.finishBuild(.{ .fuzz = fuzz != null }); | |
| 788 | } | |
| 917 | try maker.makeSteps(main_progress_node, fuzz); | |
| 789 | 918 | |
| 790 | 919 | if (web_server) |ws| { |
| 791 | 920 | const c = &scanned_config.configuration; |
| ... | ... | @@ -850,6 +979,9 @@ pub fn main(init: process.Init.Minimal) !void { |
| 850 | 979 | _ = io.lockStderr(&.{}, graph.stderr_mode) catch {}; |
| 851 | 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 | 985 | if (watch and can_fs_watch) { |
| 854 | 986 | fatal("(zig build system) TODO set up fs watching even when build.zig compilation fails", .{}); |
| 855 | 987 | } else { |
| ... | ... | @@ -1330,7 +1462,7 @@ fn configure(graph: *Graph, options: ConfigureOptions) !ScannedConfig { |
| 1330 | 1462 | if (config_man) |man| for (configuration.path_deps) |path_dep| { |
| 1331 | 1463 | switch (path_dep.flags.mode) { |
| 1332 | 1464 | .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 | 1466 | .metadata => {}, // TODO |
| 1335 | 1467 | } |
| 1336 | 1468 | }; |
| ... | ... | @@ -1433,7 +1565,6 @@ fn cmdFetch(gpa: Allocator, graph: *Graph, args: []const []const u8) !void { |
| 1433 | 1565 | |
| 1434 | 1566 | const color: Color = Color.settingFromEnvironment(environ_map); |
| 1435 | 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 | 1568 | var override_local_cache_dir: ?[]const u8 = EnvVar.ZIG_LOCAL_CACHE_DIR.get(environ_map); |
| 1438 | 1569 | var override_pkg_dir: ?[]const u8 = EnvVar.ZIG_LOCAL_PKG_DIR.get(environ_map); |
| 1439 | 1570 | var debug_hash: bool = false; |
| ... | ... | @@ -1449,8 +1580,6 @@ fn cmdFetch(gpa: Allocator, graph: *Graph, args: []const []const u8) !void { |
| 1449 | 1580 | if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) { |
| 1450 | 1581 | try Io.File.stdout().writeStreamingAll(io, usage_fetch); |
| 1451 | 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 | 1583 | } else if (mem.eql(u8, arg, "--cache-dir")) { |
| 1455 | 1584 | override_local_cache_dir = nextArgOrFatal(args, &arg_i); |
| 1456 | 1585 | } else if (mem.eql(u8, arg, "--pkg-dir")) { |
| ... | ... | @@ -1730,7 +1859,6 @@ const usage_fetch = |
| 1730 | 1859 | \\ |
| 1731 | 1860 | \\Options: |
| 1732 | 1861 | \\ -h, --help Print this help and exit |
| 1733 | \\ --global-cache-dir [path] Override path to global Zig cache directory | |
| 1734 | 1862 | \\ --cache-dir [path] Override path to local cache directory |
| 1735 | 1863 | \\ --pkg-dir [path] Override path to local package directory |
| 1736 | 1864 | \\ --debug-hash Print verbose hash information to stdout |
| ... | ... | @@ -1991,7 +2119,7 @@ fn markFailedStepsDirty(maker: *Maker) void { |
| 1991 | 2119 | for (all_steps) |step_index| { |
| 1992 | 2120 | const step = maker.stepByIndex(step_index); |
| 1993 | 2121 | switch (step.state) { |
| 1994 | .dependency_failure, .failure, .skipped => _ = maker.invalidateResult(step), | |
| 2122 | .dependency_failure, .dependency_skipped, .failure, .skipped => _ = maker.invalidateResult(step), | |
| 1995 | 2123 | else => continue, |
| 1996 | 2124 | } |
| 1997 | 2125 | } |
| ... | ... | @@ -2020,11 +2148,37 @@ pub fn stepByIndex(maker: *const Maker, i: Configuration.Step.Index) *Step { |
| 2020 | 2148 | return &maker.steps[@backingInt(i)]; |
| 2021 | 2149 | } |
| 2022 | 2150 | |
| 2023 | fn prepare(maker: *Maker, step_names: []const []const u8) !void { | |
| 2151 | fn 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 | ||
| 2176 | fn prepare(maker: *Maker, step_indices: []const Configuration.Step.Index) !void { | |
| 2024 | 2177 | const gpa = maker.gpa; |
| 2025 | 2178 | const graph = maker.graph; |
| 2026 | 2179 | const arena = graph.arena; |
| 2027 | 2180 | const seed: u32 = graph.random_seed; |
| 2181 | const initial_steps = &maker.initial_steps; | |
| 2028 | 2182 | const step_stack = &maker.step_stack; |
| 2029 | 2183 | const c = &maker.scanned_config.configuration; |
| 2030 | 2184 | |
| ... | ... | @@ -2033,18 +2187,15 @@ fn prepare(maker: *Maker, step_names: []const []const u8) !void { |
| 2033 | 2187 | step.* = .{ .extended = .init(step_index.ptr(c).flags(c).tag) }; |
| 2034 | 2188 | } |
| 2035 | 2189 | |
| 2036 | if (step_names.len == 0) { | |
| 2037 | try step_stack.put(gpa, c.default_step, {}); | |
| 2038 | } else { | |
| 2039 | try step_stack.ensureUnusedCapacity(gpa, step_names.len); | |
| 2040 | for (0..step_names.len) |i| { | |
| 2041 | const step_name = step_names[step_names.len - i - 1]; | |
| 2042 | const s = maker.scanned_config.top_level_steps.get(step_name) orelse { | |
| 2043 | log.info("to list available steps: zig build -l", .{}); | |
| 2044 | fatal("no such step: {s}", .{step_name}); | |
| 2045 | }; | |
| 2046 | step_stack.putAssumeCapacity(s, {}); | |
| 2047 | } | |
| 2190 | try initial_steps.ensureUnusedCapacity(gpa, step_indices.len); | |
| 2191 | try step_stack.ensureUnusedCapacity(gpa, step_indices.len); | |
| 2192 | ||
| 2193 | initial_steps.clearRetainingCapacity(); | |
| 2194 | step_stack.clearRetainingCapacity(); | |
| 2195 | ||
| 2196 | for (step_indices) |step| { | |
| 2197 | initial_steps.putAssumeCapacity(step, {}); | |
| 2198 | step_stack.putAssumeCapacity(step, {}); | |
| 2048 | 2199 | } |
| 2049 | 2200 | |
| 2050 | 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 | 2236 | } |
| 2086 | 2237 | } |
| 2087 | 2238 | if (any_problems) { |
| 2239 | log.info("use --skip-oom-steps to proceed, skipping memory limited steps", .{}); | |
| 2088 | 2240 | if (maker.max_rss_is_default) { |
| 2089 | 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 | 2245 | } |
| 2094 | 2246 | } |
| 2095 | 2247 | |
| 2096 | fn makeStepNames( | |
| 2248 | fn makeSteps( | |
| 2097 | 2249 | maker: *Maker, |
| 2098 | step_names: []const []const u8, | |
| 2099 | 2250 | parent_progress_node: std.Progress.Node, |
| 2100 | 2251 | fuzz: ?Fuzz.Mode, |
| 2101 | 2252 | ) !void { |
| ... | ... | @@ -2106,6 +2257,12 @@ fn makeStepNames( |
| 2106 | 2257 | const top_level_steps = &maker.scanned_config.top_level_steps; |
| 2107 | 2258 | const c = &maker.scanned_config.configuration; |
| 2108 | 2259 | |
| 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 | 2267 | // Collect the initial set of tasks (those with no outstanding dependencies) into a buffer, |
| 2111 | 2268 | // 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 | 2288 | try group.await(io); |
| 2132 | 2289 | } |
| 2133 | 2290 | |
| 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 | 2304 | assert(maker.memory_blocked_steps.items.len == 0); |
| 2135 | 2305 | |
| 2136 | 2306 | var test_pass_count: usize = 0; |
| ... | ... | @@ -2164,7 +2334,7 @@ fn makeStepNames( |
| 2164 | 2334 | .precheck_unstarted => unreachable, |
| 2165 | 2335 | .precheck_started => unreachable, |
| 2166 | 2336 | .precheck_done => unreachable, |
| 2167 | .dependency_failure => pending_count += 1, | |
| 2337 | .dependency_failure, .dependency_skipped => pending_count += 1, | |
| 2168 | 2338 | .success => success_count += 1, |
| 2169 | 2339 | .skipped, .skipped_oom => skipped_count += 1, |
| 2170 | 2340 | .failure => { |
| ... | ... | @@ -2283,7 +2453,7 @@ fn makeStepNames( |
| 2283 | 2453 | defer step_stack_copy.deinit(gpa); |
| 2284 | 2454 | |
| 2285 | 2455 | var print_node: PrintNode = .{ .parent = null }; |
| 2286 | if (step_names.len == 0) { | |
| 2456 | if (maker.initial_steps.count() == 0) { | |
| 2287 | 2457 | print_node.last = true; |
| 2288 | 2458 | printTreeStep(maker, c.default_step, t, &print_node, &step_stack_copy) catch |err| switch (err) { |
| 2289 | 2459 | error.Canceled => |e| return e, |
| ... | ... | @@ -2291,10 +2461,10 @@ fn makeStepNames( |
| 2291 | 2461 | }; |
| 2292 | 2462 | } else { |
| 2293 | 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 | 2465 | while (i > 0) { |
| 2296 | 2466 | i -= 1; |
| 2297 | const step_index = top_level_steps.get(step_names[i]).?; | |
| 2467 | const step_index = maker.initial_steps.keys()[i]; | |
| 2298 | 2468 | const step = maker.stepByIndex(step_index); |
| 2299 | 2469 | const found = switch (maker.summary) { |
| 2300 | 2470 | .all, .line, .none => unreachable, |
| ... | ... | @@ -2305,8 +2475,7 @@ fn makeStepNames( |
| 2305 | 2475 | } |
| 2306 | 2476 | break :blk top_level_steps.count(); |
| 2307 | 2477 | }; |
| 2308 | for (step_names, 0..) |step_name, i| { | |
| 2309 | const step_index = top_level_steps.get(step_name).?; | |
| 2478 | for (maker.initial_steps.keys(), 0..) |step_index, i| { | |
| 2310 | 2479 | print_node.last = i + 1 == last_index; |
| 2311 | 2480 | printTreeStep(maker, step_index, t, &print_node, &step_stack_copy) catch |err| switch (err) { |
| 2312 | 2481 | error.Canceled => |e| return e, |
| ... | ... | @@ -2317,7 +2486,7 @@ fn makeStepNames( |
| 2317 | 2486 | w.writeByte('\n') catch {}; |
| 2318 | 2487 | } |
| 2319 | 2488 | |
| 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; | |
| 2321 | 2490 | |
| 2322 | 2491 | const code: u8 = code: { |
| 2323 | 2492 | if (failure_count == 0) break :code 0; // success |
| ... | ... | @@ -2392,6 +2561,15 @@ fn makeStep( |
| 2392 | 2561 | defer step_prog_node.end(); |
| 2393 | 2562 | |
| 2394 | 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 | } | |
| 2395 | 2573 | |
| 2396 | 2574 | const new_state: Step.State = for (deps) |dep_index| { |
| 2397 | 2575 | const dep_make_step = maker.stepByIndex(dep_index); |
| ... | ... | @@ -2402,10 +2580,14 @@ fn makeStep( |
| 2402 | 2580 | |
| 2403 | 2581 | .failure, |
| 2404 | 2582 | .dependency_failure, |
| 2405 | .skipped_oom, | |
| 2406 | 2583 | => break .dependency_failure, |
| 2407 | 2584 | |
| 2408 | .success, .skipped => {}, | |
| 2585 | .dependency_skipped, | |
| 2586 | .skipped_oom, | |
| 2587 | .skipped, | |
| 2588 | => break .dependency_skipped, | |
| 2589 | ||
| 2590 | .success => {}, | |
| 2409 | 2591 | } |
| 2410 | 2592 | } else if (Step.make(step_index, maker, step_prog_node)) state: { |
| 2411 | 2593 | break :state .success; |
| ... | ... | @@ -2417,25 +2599,46 @@ fn makeStep( |
| 2417 | 2599 | |
| 2418 | 2600 | @atomicStore(Step.State, &make_step.state, new_state, .monotonic); |
| 2419 | 2601 | |
| 2420 | switch (new_state) { | |
| 2602 | const success = switch (new_state) { | |
| 2421 | 2603 | .precheck_unstarted => unreachable, |
| 2422 | 2604 | .precheck_started => unreachable, |
| 2423 | 2605 | .precheck_done => unreachable, |
| 2424 | 2606 | |
| 2425 | 2607 | .failure, |
| 2426 | 2608 | .dependency_failure, |
| 2609 | .dependency_skipped, | |
| 2427 | 2610 | .skipped_oom, |
| 2428 | => { | |
| 2429 | if (maker.web_server) |ws| ws.updateStepStatus(step_index, .failure); | |
| 2430 | std.Progress.setStatus(.failure_working); | |
| 2431 | }, | |
| 2611 | .skipped, | |
| 2612 | => false, | |
| 2432 | 2613 | |
| 2433 | 2614 | .success, |
| 2434 | .skipped, | |
| 2435 | => { | |
| 2436 | if (maker.web_server) |ws| ws.updateStepStatus(step_index, .success); | |
| 2437 | }, | |
| 2615 | => true, | |
| 2616 | }; | |
| 2617 | ||
| 2618 | if (maker.web_server) |ws| { | |
| 2619 | ws.updateStepStatus(step_index, if (success) .success else .failure); | |
| 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 | } |
| 2440 | 2643 | |
| 2441 | 2644 | // No matter the result, we want to display error/warning messages. |
| ... | ... | @@ -2468,7 +2671,7 @@ fn makeStep( |
| 2468 | 2671 | maker.available_rss += max_rss; |
| 2469 | 2672 | dispatch_set.ensureUnusedCapacity(gpa, maker.memory_blocked_steps.items.len) catch |
| 2470 | 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 | 2675 | const candidate_max_rss = candidate_index.ptr(c).max_rss.toBytes(); |
| 2473 | 2676 | if (maker.available_rss < candidate_max_rss) break; |
| 2474 | 2677 | assert(maker.memory_blocked_steps.pop() == candidate_index); |
| ... | ... | @@ -2579,6 +2782,12 @@ fn printStepStatus(maker: *Maker, step_index: Configuration.Step.Index, stderr: |
| 2579 | 2782 | try stderr.setColor(.reset); |
| 2580 | 2783 | }, |
| 2581 | 2784 | |
| 2785 | .dependency_skipped => { | |
| 2786 | try stderr.setColor(.dim); | |
| 2787 | try writer.writeAll(" transitive skip\n"); | |
| 2788 | try stderr.setColor(.reset); | |
| 2789 | }, | |
| 2790 | ||
| 2582 | 2791 | .success => { |
| 2583 | 2792 | try stderr.setColor(.green); |
| 2584 | 2793 | if (s.result_cached) { |
| ... | ... | @@ -2825,6 +3034,7 @@ fn constructGraphAndCheckForDependencyLoop( |
| 2825 | 3034 | |
| 2826 | 3035 | // These don't happen until we actually run the step graph. |
| 2827 | 3036 | .dependency_failure => unreachable, |
| 3037 | .dependency_skipped => unreachable, | |
| 2828 | 3038 | .success => unreachable, |
| 2829 | 3039 | .failure => unreachable, |
| 2830 | 3040 | .skipped => unreachable, |
| ... | ... | @@ -2912,7 +3122,7 @@ pub fn printErrorMessages( |
| 2912 | 3122 | try stderr.setColor(.red); |
| 2913 | 3123 | try writer.writeAll("error:"); |
| 2914 | 3124 | try stderr.setColor(.reset); |
| 2915 | if (std.mem.indexOfScalar(u8, msg, '\n') == null) { | |
| 3125 | if (std.mem.findScalar(u8, msg, '\n') == null) { | |
| 2916 | 3126 | try writer.print(" {s}\n", .{msg}); |
| 2917 | 3127 | } else switch (multiline_errors) { |
| 2918 | 3128 | .indent => { |
| ... | ... | @@ -2990,6 +3200,50 @@ fn cleanTmpFiles(maker: *Maker, steps: []const Configuration.Step.Index) void { |
| 2990 | 3200 | } |
| 2991 | 3201 | } |
| 2992 | 3202 | |
| 3203 | fn 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 | ||
| 3218 | fn 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 | ||
| 2993 | 3247 | fn initStdoutWriter(io: Io) *Writer { |
| 2994 | 3248 | stdout_writer_allocation = Io.File.stdout().writerStreaming(io, &stdio_buffer_allocation); |
| 2995 | 3249 | return &stdout_writer_allocation.interface; |
| ... | ... | @@ -3071,17 +3325,19 @@ pub fn packagePath( |
| 3071 | 3325 | ) Allocator.Error!Path { |
| 3072 | 3326 | const c = &maker.scanned_config.configuration; |
| 3073 | 3327 | const graph = maker.graph; |
| 3074 | const package = package_index.get(c) orelse return .{ | |
| 3328 | ||
| 3329 | if (package_index == .root) return .{ | |
| 3075 | 3330 | .root_dir = graph.build_root_directory, |
| 3076 | 3331 | .sub_path = sub_path, |
| 3077 | 3332 | }; |
| 3333 | ||
| 3078 | 3334 | // Currently, neither configurer nor Maker is aware of the standard zig |
| 3079 | 3335 | // package path, and the root path is stored as a bare string rather than |
| 3080 | 3336 | // relative to a known base directory. Without changing that, we must |
| 3081 | 3337 | // construct a cwd relative path here. |
| 3082 | 3338 | return .{ |
| 3083 | 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 | } |
| 3087 | 3343 | |
| ... | ... | @@ -3687,7 +3943,12 @@ const Templates = struct { |
| 3687 | 3943 | } |
| 3688 | 3944 | }; |
| 3689 | 3945 | |
| 3690 | fn confPathDepToCachePath(graph: *const Graph, c: *const Configuration, path_dep: Configuration.PathDep) Path { | |
| 3946 | fn confPathDepToCachePath( | |
| 3947 | arena: Allocator, | |
| 3948 | graph: *const Graph, | |
| 3949 | c: *const Configuration, | |
| 3950 | path_dep: Configuration.PathDep, | |
| 3951 | ) Allocator.Error!Path { | |
| 3691 | 3952 | const sub_path = path_dep.sub.slice(c); |
| 3692 | 3953 | return switch (path_dep.flags.base) { |
| 3693 | 3954 | .cwd => .{ |
| ... | ... | @@ -3703,11 +3964,11 @@ fn confPathDepToCachePath(graph: *const Graph, c: *const Configuration, path_dep |
| 3703 | 3964 | .sub_path = sub_path, |
| 3704 | 3965 | }, |
| 3705 | 3966 | .build_root => .{ |
| 3706 | .root_dir = switch (path_dep.pkg.unwrap().?) { | |
| 3707 | .root => graph.build_root_directory, | |
| 3708 | _ => @panic("TODO"), | |
| 3967 | .root_dir = graph.build_root_directory, | |
| 3968 | .sub_path = switch (path_dep.pkg.unwrap().?) { | |
| 3969 | .root => sub_path, | |
| 3970 | else => |index| try Dir.path.join(arena, &.{ index.ptr(c).root_path.slice(c), sub_path }), | |
| 3709 | 3971 | }, |
| 3710 | .sub_path = sub_path, | |
| 3711 | 3972 | }, |
| 3712 | 3973 | .zig_lib => .{ |
| 3713 | 3974 | .root_dir = graph.zig_lib_directory, |
lib/compiler/Maker/Fetch.zig+3-3| ... | ... | @@ -1164,7 +1164,7 @@ const FileType = enum { |
| 1164 | 1164 | if (cd_header[value_start] != '=') return null; |
| 1165 | 1165 | value_start += 1; |
| 1166 | 1166 | |
| 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 | 1168 | if (cd_header[value_end - 1] == '\"') { |
| 1169 | 1169 | value_end -= 1; |
| 1170 | 1170 | } |
| ... | ... | @@ -1344,7 +1344,7 @@ fn unpackResource( |
| 1344 | 1344 | return f.fail(f.location_tok, try eb.addString("missing 'Content-Type' header")); |
| 1345 | 1345 | |
| 1346 | 1346 | // 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 | 1348 | const mime_type = content_type[0..mime_type_end]; |
| 1349 | 1349 | |
| 1350 | 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 | 1455 | |
| 1456 | 1456 | var diagnostics: std.tar.Diagnostics = .{ .allocator = arena }; |
| 1457 | 1457 | |
| 1458 | std.tar.pipeToFileSystem(io, out_dir, reader, .{ | |
| 1458 | std.tar.extract(io, out_dir, reader, .{ | |
| 1459 | 1459 | .diagnostics = &diagnostics, |
| 1460 | 1460 | .strip_components = 0, |
| 1461 | 1461 | .mode_mode = .ignore, |
lib/compiler/Maker/Fetch/git.zig+6-6| ... | ... | @@ -336,7 +336,7 @@ pub const Repository = struct { |
| 336 | 336 | fn next(iterator: *TreeIterator) !?Entry { |
| 337 | 337 | if (iterator.pos == iterator.data.len) return null; |
| 338 | 338 | |
| 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 | 340 | const mode: packed struct { |
| 341 | 341 | permission: u9, |
| 342 | 342 | unused: u3, |
| ... | ... | @@ -351,7 +351,7 @@ pub const Repository = struct { |
| 351 | 351 | }; |
| 352 | 352 | iterator.pos = mode_end + 1; |
| 353 | 353 | |
| 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 | 355 | const name = iterator.data[iterator.pos..name_end :0]; |
| 356 | 356 | iterator.pos = name_end + 1; |
| 357 | 357 | |
| ... | ... | @@ -823,7 +823,7 @@ pub const Session = struct { |
| 823 | 823 | value: ?[]const u8 = null, |
| 824 | 824 | |
| 825 | 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 | 827 | .{ .key = data[0..separator_pos], .value = data[separator_pos + 1 ..] } |
| 828 | 828 | else |
| 829 | 829 | .{ .key = data }; |
| ... | ... | @@ -941,17 +941,17 @@ pub const Session = struct { |
| 941 | 941 | .flush => return null, |
| 942 | 942 | .data => |data| { |
| 943 | 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 | 945 | const oid = Oid.parse(it.format, data[0..oid_sep_pos]) catch return error.InvalidRefPacket; |
| 946 | 946 | |
| 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 | 948 | const name = ref_data[oid_sep_pos + 1 .. name_sep_pos]; |
| 949 | 949 | |
| 950 | 950 | var symref_target: ?[]const u8 = null; |
| 951 | 951 | var peeled: ?Oid = null; |
| 952 | 952 | var last_sep_pos = name_sep_pos; |
| 953 | 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 | 955 | const attribute = ref_data[last_sep_pos + 1 .. next_sep_pos]; |
| 956 | 956 | if (mem.startsWith(u8, attribute, "symref-target:")) { |
| 957 | 957 | symref_target = attribute["symref-target:".len..]; |
lib/compiler/Maker/PkgConfig.zig+2| ... | ... | @@ -63,6 +63,8 @@ pub fn run( |
| 63 | 63 | } |
| 64 | 64 | } |
| 65 | 65 | |
| 66 | step.clearFailedCommand(maker.gpa); | |
| 67 | ||
| 66 | 68 | return parsed; |
| 67 | 69 | } |
| 68 | 70 |
lib/compiler/Maker/ScannedConfig.zig+63-5| ... | ... | @@ -12,10 +12,6 @@ top_level_steps: std.array_hash_map.String(Configuration.Step.Index), |
| 12 | 12 | path: std.Build.Cache.Path, |
| 13 | 13 | |
| 14 | 14 | pub 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 | 15 | const c = &sc.configuration; |
| 20 | 16 | var serializer: Serializer = .{ .writer = w }; |
| 21 | 17 | var s = try serializer.beginStruct(.{}); |
| ... | ... | @@ -45,6 +41,69 @@ pub fn print(sc: *const ScannedConfig, w: *Writer) Writer.Error!void { |
| 45 | 41 | try tf.end(); |
| 46 | 42 | } |
| 47 | 43 | |
| 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 | 107 | try s.end(); |
| 49 | 108 | } |
| 50 | 109 | |
| ... | ... | @@ -341,7 +400,6 @@ pub fn printUsage(sc: *const ScannedConfig, graph: *Graph, w: *Writer) !void { |
| 341 | 400 | \\ --error-limit [num] Set the maximum amount of distinct error values |
| 342 | 401 | \\ --build-file [file] Override path to build.zig |
| 343 | 402 | \\ --cache-dir [path] Override path to local Zig cache directory |
| 344 | \\ --global-cache-dir [path] Override path to global Zig cache directory | |
| 345 | 403 | \\ --zig-lib=[arg] Override path to Zig lib directory |
| 346 | 404 | \\ --seed [integer] For shuffling dependency traversal order (default: random) |
| 347 | 405 | \\ --cache-poison[=mode] Override configuration caching behavior |
lib/compiler/Maker/Step.zig+13-8| ... | ... | @@ -163,6 +163,9 @@ pub const State = enum { |
| 163 | 163 | /// be re-evaluated. |
| 164 | 164 | precheck_done, |
| 165 | 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 | 169 | success, |
| 167 | 170 | failure, |
| 168 | 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 | 564 | var result: ?Path = null; |
| 562 | 565 | var eos_err: error{EndOfStream}!void = {}; |
| 563 | 566 | |
| 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 | }; | |
| 565 | 571 | |
| 566 | 572 | while (true) { |
| 567 | const Header = std.zig.Server.Message.Header; | |
| 568 | const header = stdout.interface.takeStruct(Header, .little) catch |err| switch (err) { | |
| 569 | error.EndOfStream => break, | |
| 570 | error.ReadFailed => return stdout.err.?, | |
| 571 | }; | |
| 572 | const body = stdout.interface.take(header.bytes_len) catch |err| switch (err) { | |
| 573 | const header = client.receiveMessageWithMultiReader(&zp.multi_reader, .none) catch |err| switch (err) { | |
| 574 | error.Timeout => unreachable, | |
| 573 | 575 | error.EndOfStream => |e| { |
| 576 | if (client.in.bufferedLen() == 0) break; | |
| 574 | 577 | // Better to report the crash with stderr below, but we set |
| 575 | 578 | // this in case the child exits successfully while violating |
| 576 | 579 | // this protocol. |
| 577 | 580 | eos_err = e; |
| 578 | 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 | 587 | switch (header.tag) { |
| 583 | 588 | .zig_version => { |
| 584 | 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 | 215 | try addBool(gpa, zig_args, "-ffuzz", fuzz); |
| 216 | 216 | |
| 217 | 217 | { |
| 218 | var is_linking_libc = conf_comp.flags3.is_linking_libc; | |
| 219 | var is_linking_libcpp = conf_comp.flags3.is_linking_libcpp; | |
| 218 | var is_linking_libc = false; | |
| 219 | var is_linking_libcpp = false; | |
| 220 | 220 | |
| 221 | 221 | // Stores system libraries that have already been seen for at least one |
| 222 | 222 | // 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 | 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 | 122 | .blank => { |
| 97 | 123 | renderBlank(conf, &aw.writer, value_pairs, &value_map, include_path, include_guard_override) catch |err| switch (err) { |
| 98 | 124 | error.WriteFailed => return error.OutOfMemory, |
| ... | ... | @@ -370,6 +396,62 @@ fn renderCmake( |
| 370 | 396 | if (any_errors) return error.MakeFailed; |
| 371 | 397 | } |
| 372 | 398 | |
| 399 | fn 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 | ||
| 373 | 455 | fn renderBlank( |
| 374 | 456 | conf: *const Configuration, |
| 375 | 457 | w: *Writer, |
| ... | ... | @@ -432,6 +514,28 @@ fn renderValueC(conf: *const Configuration, w: *Writer, newline: []const u8, nam |
| 432 | 514 | } |
| 433 | 515 | } |
| 434 | 516 | |
| 517 | fn 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 | ||
| 435 | 539 | fn renderValueCIdent(w: *Writer, newline: []const u8, name: []const u8, ident: []const u8) Writer.Error!void { |
| 436 | 540 | try w.print("#define {s}", .{name}); |
| 437 | 541 | if (ident.len > 0) { |
| ... | ... | @@ -628,3 +732,36 @@ fn expandVariablesCmake( |
| 628 | 732 | |
| 629 | 733 | return result.toOwnedSliceAssert(); |
| 630 | 734 | } |
| 735 | ||
| 736 | fn 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 | 64 | } |
| 65 | 65 | } |
| 66 | 66 | |
| 67 | for (conf_run.preopen_names.slice, conf_run.preopen_paths.slice) |name, path| { | |
| 68 | man.hash.addBytesZ(name.slice(conf)); | |
| 69 | const cwd_path = try maker.resolveLazyPathIndex(arena, path, run_index); | |
| 67 | for (conf_run.preopens.slice) |preopen| { | |
| 68 | man.hash.addBytesZ(preopen.name.slice(conf)); | |
| 69 | const cwd_path = try maker.resolveLazyPathIndex(arena, preopen.path, run_index); | |
| 70 | 70 | man.hash.addBytes(try cwd_path.toString(arena)); |
| 71 | 71 | } |
| 72 | 72 | |
| ... | ... | @@ -187,6 +187,11 @@ pub fn make( |
| 187 | 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 | } |
| 192 | 197 | |
| ... | ... | @@ -351,6 +356,29 @@ pub fn make( |
| 351 | 356 | step.clearFailedCommand(gpa); |
| 352 | 357 | } |
| 353 | 358 | |
| 359 | fn 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 | 382 | /// Reads stdout of a Zig test process until a termination condition is reached: |
| 355 | 383 | /// * A write fails, indicating the child unexpectedly closed stdin |
| 356 | 384 | /// * A test (or a response from the test runner) times out |
| ... | ... | @@ -384,13 +412,23 @@ fn waitZigTest( |
| 384 | 412 | var sub_prog_node: ?std.Progress.Node = null; |
| 385 | 413 | defer if (sub_prog_node) |n| n.end(); |
| 386 | 414 | |
| 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 | 425 | if (opt_metadata.*) |*md| { |
| 388 | 426 | // 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 | 428 | } else { |
| 391 | 429 | // Running unit tests normally |
| 392 | 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 | } |
| 395 | 433 | |
| 396 | 434 | var active_test_index: ?u32 = null; |
| ... | ... | @@ -410,10 +448,6 @@ fn waitZigTest( |
| 410 | 448 | .raw = .fromNanoseconds(ns), |
| 411 | 449 | } else null; |
| 412 | 450 | |
| 413 | const stdout = multi_reader.reader(0); | |
| 414 | const stderr = multi_reader.reader(1); | |
| 415 | const Header = std.zig.Server.Message.Header; | |
| 416 | ||
| 417 | 451 | while (true) { |
| 418 | 452 | const timeout: Io.Timeout = t: { |
| 419 | 453 | const opt_duration = if (active_test_index == null) response_timeout else test_timeout; |
| ... | ... | @@ -421,46 +455,20 @@ fn waitZigTest( |
| 421 | 455 | break :t .{ .deadline = last_update.addDuration(duration) }; |
| 422 | 456 | }; |
| 423 | 457 | |
| 424 | // This block is exited when `stdout` contains enough bytes for a `Header`. | |
| 425 | header_ready: { | |
| 426 | if (stdout.buffered().len >= @sizeOf(Header)) { | |
| 427 | // We already have one, no need to poll! | |
| 428 | break :header_ready; | |
| 429 | } | |
| 430 | ||
| 431 | multi_reader.fill(64, timeout) catch |err| switch (err) { | |
| 432 | error.Timeout => return .{ .timeout = .{ | |
| 433 | .active_test_index = active_test_index, | |
| 434 | .ns_elapsed = @intCast(last_update.untilNow(io).raw.nanoseconds), | |
| 435 | } }, | |
| 436 | error.EndOfStream => return .{ .no_poll = .{ | |
| 437 | .active_test_index = active_test_index, | |
| 438 | .ns_elapsed = @intCast(last_update.untilNow(io).raw.nanoseconds), | |
| 439 | } }, | |
| 440 | else => |e| return e, | |
| 441 | }; | |
| 442 | ||
| 443 | continue; | |
| 444 | } | |
| 445 | // There is definitely a header available now -- read it. | |
| 446 | const header = stdout.takeStruct(Header, .little) catch unreachable; | |
| 447 | ||
| 448 | while (stdout.buffered().len < header.bytes_len) { | |
| 449 | multi_reader.fill(64, timeout) catch |err| switch (err) { | |
| 450 | error.Timeout => return .{ .timeout = .{ | |
| 451 | .active_test_index = active_test_index, | |
| 452 | .ns_elapsed = @intCast(last_update.untilNow(io).raw.nanoseconds), | |
| 453 | } }, | |
| 454 | error.EndOfStream => return .{ .no_poll = .{ | |
| 455 | .active_test_index = active_test_index, | |
| 456 | .ns_elapsed = @intCast(last_update.untilNow(io).raw.nanoseconds), | |
| 457 | } }, | |
| 458 | else => |e| return e, | |
| 459 | }; | |
| 460 | } | |
| 461 | ||
| 462 | const body = stdout.take(header.bytes_len) catch unreachable; | |
| 458 | const header = client.receiveMessageWithMultiReader(multi_reader, timeout) catch |err| switch (err) { | |
| 459 | error.Timeout => return .{ .timeout = .{ | |
| 460 | .active_test_index = active_test_index, | |
| 461 | .ns_elapsed = @intCast(last_update.untilNow(io).raw.nanoseconds), | |
| 462 | } }, | |
| 463 | error.EndOfStream => return .{ .no_poll = .{ | |
| 464 | .active_test_index = active_test_index, | |
| 465 | .ns_elapsed = @intCast(last_update.untilNow(io).raw.nanoseconds), | |
| 466 | } }, | |
| 467 | else => |e| return e, | |
| 468 | }; | |
| 469 | const body = client.in.take(header.bytes_len) catch unreachable; | |
| 463 | 470 | var body_r: std.Io.Reader = .fixed(body); |
| 471 | ||
| 464 | 472 | switch (header.tag) { |
| 465 | 473 | .zig_version => { |
| 466 | 474 | if (!std.mem.eql(u8, builtin.zig_version_string, body)) return step.fail( |
| ... | ... | @@ -500,7 +508,7 @@ fn waitZigTest( |
| 500 | 508 | active_test_index = null; |
| 501 | 509 | last_update = .now(io, .awake); |
| 502 | 510 | |
| 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 | 513 | .test_started => { |
| 506 | 514 | active_test_index = opt_metadata.*.?.next_index - 1; |
| ... | ... | @@ -551,7 +559,7 @@ fn waitZigTest( |
| 551 | 559 | md.ns_per_test[tr_hdr.index] = @intCast(last_update.durationTo(now).raw.nanoseconds); |
| 552 | 560 | last_update = now; |
| 553 | 561 | |
| 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 | 564 | else => {}, // ignore other messages |
| 557 | 565 | } |
| ... | ... | @@ -575,7 +583,7 @@ const FuzzTestRunner = struct { |
| 575 | 583 | |
| 576 | 584 | const Instance = struct { |
| 577 | 585 | child: process.Child, |
| 578 | message: std.ArrayListAligned(u8, .@"4"), | |
| 586 | message: std.array_list.Aligned(u8, .@"4"), | |
| 579 | 587 | broadcast_written: usize, |
| 580 | 588 | stderr: std.ArrayList(u8), |
| 581 | 589 | stdin_vec: [1][]u8, |
| ... | ... | @@ -697,17 +705,18 @@ const FuzzTestRunner = struct { |
| 697 | 705 | |
| 698 | 706 | for (0.., f.instances) |id, *instance| { |
| 699 | 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 | 713 | (switch (f.ctx.fuzz.mode) { |
| 701 | .forever => sendRunFuzzTestMessage( | |
| 702 | io, | |
| 703 | instance.child.stdin.?, | |
| 714 | .forever => client.serveRunFuzzTestMessage( | |
| 704 | 715 | run.fuzz_tests.items, |
| 705 | 716 | .forever, |
| 706 | 717 | id32, |
| 707 | 718 | ), |
| 708 | .limit => |limit| sendRunFuzzTestMessage( | |
| 709 | io, | |
| 710 | instance.child.stdin.?, | |
| 719 | .limit => |limit| client.serveRunFuzzTestMessage( | |
| 711 | 720 | run.fuzz_tests.items, |
| 712 | 721 | .iterations, |
| 713 | 722 | limit.amount, |
| ... | ... | @@ -1315,7 +1324,7 @@ pub const CachedTestMetadata = struct { |
| 1315 | 1324 | } |
| 1316 | 1325 | }; |
| 1317 | 1326 | |
| 1318 | fn requestNextTest(io: Io, in: Io.File, metadata: *TestMetadata, sub_prog_node: *?std.Progress.Node) !void { | |
| 1327 | fn requestNextTest(client: *std.zig.Client, metadata: *TestMetadata, sub_prog_node: *?std.Progress.Node) !void { | |
| 1319 | 1328 | while (metadata.next_index < metadata.names.len) { |
| 1320 | 1329 | const i = metadata.next_index; |
| 1321 | 1330 | metadata.next_index += 1; |
| ... | ... | @@ -1326,76 +1335,11 @@ fn requestNextTest(io: Io, in: Io.File, metadata: *TestMetadata, sub_prog_node: |
| 1326 | 1335 | if (sub_prog_node.*) |n| n.end(); |
| 1327 | 1336 | sub_prog_node.* = metadata.prog_node.start(name, 0); |
| 1328 | 1337 | |
| 1329 | try sendRunTestMessage(io, in, .run_test, i); | |
| 1338 | try client.serveRunTest(i); | |
| 1330 | 1339 | return; |
| 1331 | 1340 | } else { |
| 1332 | 1341 | metadata.next_index = std.math.maxInt(u32); // indicate that all tests are done |
| 1333 | try sendMessage(io, in, .exit); | |
| 1334 | } | |
| 1335 | } | |
| 1336 | ||
| 1337 | fn 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 | ||
| 1348 | fn 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 | ||
| 1362 | fn sendRunFuzzTestMessage( | |
| 1363 | io: Io, | |
| 1364 | file: Io.File, | |
| 1365 | test_names: []const []const u8, | |
| 1366 | kind: std.Build.abi.fuzz.LimitKind, | |
| 1367 | amount_or_instance: u64, | |
| 1368 | ) !void { | |
| 1369 | const header: std.zig.Client.Message.Header = .{ | |
| 1370 | .tag = .start_fuzzing, | |
| 1371 | .bytes_len = 1 + 8 + 4 + count: { | |
| 1372 | var c: u32 = @intCast(test_names.len * 4); | |
| 1373 | for (test_names) |name| { | |
| 1374 | c += @intCast(name.len); | |
| 1375 | } | |
| 1376 | break :count c; | |
| 1377 | }, | |
| 1378 | }; | |
| 1379 | var w = file.writerStreaming(io, &.{}); | |
| 1380 | w.interface.writeStruct(header, .little) catch |err| switch (err) { | |
| 1381 | error.WriteFailed => return w.err.?, | |
| 1382 | }; | |
| 1383 | w.interface.writeByte(@backingInt(kind)) catch |err| switch (err) { | |
| 1384 | error.WriteFailed => return w.err.?, | |
| 1385 | }; | |
| 1386 | w.interface.writeInt(u64, amount_or_instance, .little) catch |err| switch (err) { | |
| 1387 | error.WriteFailed => return w.err.?, | |
| 1388 | }; | |
| 1389 | w.interface.writeInt(u32, @intCast(test_names.len), .little) catch |err| switch (err) { | |
| 1390 | error.WriteFailed => return w.err.?, | |
| 1391 | }; | |
| 1392 | for (test_names) |test_name| { | |
| 1393 | w.interface.writeInt(u32, @intCast(test_name.len), .little) catch |err| switch (err) { | |
| 1394 | error.WriteFailed => return w.err.?, | |
| 1395 | }; | |
| 1396 | w.interface.writeAll(test_name) catch |err| switch (err) { | |
| 1397 | error.WriteFailed => return w.err.?, | |
| 1398 | }; | |
| 1342 | try client.serveBodylessMessage(.exit); | |
| 1399 | 1343 | } |
| 1400 | 1344 | } |
| 1401 | 1345 | |
| ... | ... | @@ -1619,6 +1563,11 @@ pub fn rerunInFuzzMode( |
| 1619 | 1563 | .output_file => unreachable, |
| 1620 | 1564 | .output_directory => unreachable, |
| 1621 | 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 | } |
| 1624 | 1573 | |
| ... | ... | @@ -1917,14 +1866,14 @@ fn runCommand( |
| 1917 | 1866 | }, |
| 1918 | 1867 | .wasmtime => |bin_name| { |
| 1919 | 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 | 1870 | interp_argv.appendAssumeCapacity(bin_name); |
| 1922 | 1871 | interp_argv.appendAssumeCapacity("--dir=."); |
| 1923 | for (conf_run.preopen_names.slice, conf_run.preopen_paths.slice) |name, lazy_path| { | |
| 1924 | const path = try maker.resolveLazyPath(arena, lazy_path.get(conf), run_index); | |
| 1872 | for (conf_run.preopens.slice) |preopen| { | |
| 1873 | const path = try maker.resolveLazyPath(arena, preopen.path.get(conf), run_index); | |
| 1925 | 1874 | path.root_dir.handle.createDirPath(io, path.subPathOrDot()) catch |e| |
| 1926 | 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 | 1878 | // Wasmtime doeesn't inherit environment variables from the parent process |
| 1930 | 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 | 2153 | } |
| 2205 | 2154 | |
| 2206 | 2155 | fn 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 | 2157 | line_begin + 1 |
| 2209 | 2158 | else |
| 2210 | 2159 | 0; |
| ... | ... | @@ -2285,25 +2234,35 @@ fn spawnChildAndCollect( |
| 2285 | 2234 | assert(conf_run.flags.stdio != .inherit); |
| 2286 | 2235 | break :s .pipe; |
| 2287 | 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 | 2238 | .inherit => .inherit, |
| 2290 | 2239 | .check => .ignore, |
| 2291 | 2240 | .zig_test => .pipe, |
| 2292 | 2241 | }, |
| 2293 | 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 | 2244 | .inherit => .inherit, |
| 2296 | 2245 | .check => if (checksContainStdout(&conf_run)) .pipe else .ignore, |
| 2297 | 2246 | .zig_test => .pipe, |
| 2298 | 2247 | }, |
| 2299 | 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, | |
| 2301 | .inherit => .inherit, | |
| 2249 | .infer_from_args => if (maker.protocol_server == null and has_side_effects) .inherit else .pipe, | |
| 2250 | .inherit => if (maker.protocol_server == null) .inherit else .pipe, | |
| 2302 | 2251 | .check => .pipe, |
| 2303 | 2252 | .zig_test => .pipe, |
| 2304 | 2253 | }, |
| 2305 | 2254 | }; |
| 2306 | 2255 | |
| 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 | 2266 | if (conf_run.flags.stdio == .zig_test) { |
| 2308 | 2267 | try setColorEnvironmentVariables(&conf_run, environ_map, graph.stderr_mode.?); |
| 2309 | 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 | 49 | |
| 50 | 50 | const opt: ?OptimizeMode = switch (conf_tc.flags.optimize) { |
| 51 | 51 | .debug, .default => null, // Skip since it's the default |
| 52 | .safe => .ReleaseSafe, | |
| 53 | .fast => .ReleaseFast, | |
| 54 | .small => .ReleaseSmall, | |
| 52 | .safe => .safe, | |
| 53 | .fast => .fast, | |
| 54 | .small => .small, | |
| 55 | 55 | }; |
| 56 | 56 | if (opt) |o| argv.appendAssumeCapacity(try arena.print("-O{t}", .{o})); |
| 57 | 57 |
lib/compiler/Maker/WebServer.zig+1-1| ... | ... | @@ -501,7 +501,7 @@ fn serveRequest(ws: *WebServer, req: *http.Server.Request) !void { |
| 501 | 501 | if (mem.eql(u8, target, "/main.js")) return serveLibFile(ws, req, "build-web/main.js", "application/javascript"); |
| 502 | 502 | if (mem.eql(u8, target, "/style.css")) return serveLibFile(ws, req, "build-web/style.css", "text/css"); |
| 503 | 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); | |
| 505 | 505 | |
| 506 | 506 | if (ws.fuzz) |*fuzz| { |
| 507 | 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 | 1601 | var list: std.ArrayList(u8) = .{ |
| 1602 | 1602 | .items = contents[0..i], |
| 1603 | 1603 | .capacity = contents.len, |
| 1604 | .pointer_stability = .{}, | |
| 1604 | 1605 | }; |
| 1605 | 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 | 510 | |
| 511 | 511 | pub fn templateIndex(w: *std.Io.Writer, fmt: []const u8, template: []const u8) std.Io.Writer.Error!usize { |
| 512 | 512 | const i = std.mem.indexOf(u8, fmt, template) orelse { |
| 513 | if (@import("builtin").mode == .Debug) { | |
| 513 | if (@import("builtin").mode == .debug) { | |
| 514 | 514 | std.debug.panic("template `{s}` not found in format string `{s}`", .{ template, fmt }); |
| 515 | 515 | } |
| 516 | 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 | 1559 | } |
| 1560 | 1560 | |
| 1561 | 1561 | pub fn cCharSignedness(target: *const Target) std.builtin.Signedness { |
| 1562 | return target.toZigTarget().cCharSignedness(); | |
| 1562 | return target.toZigTarget().cCharSignedness().?; | |
| 1563 | 1563 | } |
| 1564 | 1564 | |
| 1565 | 1565 | pub 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 | } |
| 1568 | 1568 | |
| 1569 | 1569 | pub 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 | } |
| 1572 | 1572 | |
| 1573 | 1573 | pub 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 | 40 | defer threaded.deinit(); |
| 41 | 41 | const io = threaded.io(); |
| 42 | 42 | |
| 43 | const fast_exit = @import("builtin").mode != .Debug; | |
| 43 | const fast_exit = @import("builtin").mode != .debug; | |
| 44 | 44 | |
| 45 | 45 | const args = init.args.toSlice(arena) catch { |
| 46 | 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 | 83 | if (mem.cutPrefix(u8, arg, "-D")) |option_contents| { |
| 84 | 84 | if (option_contents.len == 0) |
| 85 | 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 | 87 | const option_name = option_contents[0..name_end]; |
| 88 | 88 | const option_value = option_contents[name_end + 1 ..]; |
| 89 | 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 | 214 | if (listen) { |
| 215 | 215 | var stdin_reader = Io.File.stdin().reader(io, &stdin_buffer); |
| 216 | 216 | var stdout_writer = Io.File.stdout().writer(io, &stdout_buffer); |
| 217 | var server = try Server.init(.{ | |
| 217 | var server: Server = .{ | |
| 218 | 218 | .in = &stdin_reader.interface, |
| 219 | 219 | .out = &stdout_writer.interface, |
| 220 | .zig_version = builtin.zig_version_string, | |
| 221 | }); | |
| 220 | }; | |
| 221 | try server.serveStringMessage(.zig_version, builtin.zig_version_string); | |
| 222 | 222 | |
| 223 | 223 | var seen_update = false; |
| 224 | 224 | while (true) { |
| ... | ... | @@ -435,13 +435,13 @@ const BinaryElfOutput = struct { |
| 435 | 435 | |
| 436 | 436 | var program_headers = elf_hdr.iterateProgramHeaders(in); |
| 437 | 437 | while (try program_headers.next()) |phdr| { |
| 438 | if (phdr.p_type == elf.PT_LOAD) { | |
| 438 | if (phdr.type == .LOAD) { | |
| 439 | 439 | const newSegment = try allocator.create(BinaryElfSegment); |
| 440 | 440 | |
| 441 | newSegment.physicalAddress = phdr.p_paddr; | |
| 442 | newSegment.virtualAddress = phdr.p_vaddr; | |
| 443 | newSegment.fileSize = @intCast(phdr.p_filesz); | |
| 444 | newSegment.elfOffset = phdr.p_offset; | |
| 441 | newSegment.physicalAddress = phdr.paddr; | |
| 442 | newSegment.virtualAddress = phdr.vaddr; | |
| 443 | newSegment.fileSize = @intCast(phdr.filesz); | |
| 444 | newSegment.elfOffset = phdr.offset; | |
| 445 | 445 | newSegment.binaryOffset = 0; |
| 446 | 446 | newSegment.firstSection = null; |
| 447 | 447 | |
| ... | ... | @@ -495,8 +495,8 @@ const BinaryElfOutput = struct { |
| 495 | 495 | return self; |
| 496 | 496 | } |
| 497 | 497 | |
| 498 | fn sectionWithinSegment(section: *BinaryElfSection, segment: elf.Elf64_Phdr) bool { | |
| 499 | return segment.p_offset <= section.elfOffset and (segment.p_offset + segment.p_filesz) >= (section.elfOffset + section.fileSize); | |
| 498 | fn sectionWithinSegment(section: *BinaryElfSection, segment: elf.Elf64.Phdr) bool { | |
| 499 | return segment.offset <= section.elfOffset and (segment.offset + segment.filesz) >= (section.elfOffset + section.fileSize); | |
| 500 | 500 | } |
| 501 | 501 | |
| 502 | 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 | 400 | file_path, |
| 401 | 401 | gpa, |
| 402 | 402 | .limited(std.math.maxInt(u32)), |
| 403 | .fromByteUnits(1), | |
| 403 | .@"1", | |
| 404 | 404 | 0, |
| 405 | 405 | ) catch |err| { |
| 406 | 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 | 540 | // This currently only checks for NUL bytes, but it should probably also check for |
| 541 | 541 | // platform-specific invalid characters like '*', '?', '"', '<', '>', '|' (Windows) |
| 542 | 542 | // 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 | 544 | return self.addErrorDetailsAndFail(.{ |
| 545 | 545 | .err = .invalid_filename, |
| 546 | 546 | .token = node.filename.getFirstToken(), |
| ... | ... | @@ -2919,11 +2919,11 @@ fn validateSearchPath(path: []const u8) error{BadPathName}!void { |
| 2919 | 2919 | var component_iterator = std.fs.path.componentIterator(path); |
| 2920 | 2920 | while (component_iterator.next()) |component| { |
| 2921 | 2921 | // 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 | 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 | 1056 | comptime { |
| 1057 | 1057 | const info = @typeInfo(Arch).@"enum"; |
| 1058 | 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 | 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 | 506 | // We know that the token slice is a well-formed #pragma code_page(N), so |
| 507 | 507 | // we can skip to the first ( and then get the number that follows |
| 508 | 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 | 510 | while (std.ascii.isWhitespace(token_slice[number_start])) { |
| 511 | 511 | number_start += 1; |
| 512 | 512 | } |
lib/compiler/resinator/parse.zig+1-1| ... | ... | @@ -1277,7 +1277,7 @@ pub const Parser = struct { |
| 1277 | 1277 | }, |
| 1278 | 1278 | else => unreachable, |
| 1279 | 1279 | } |
| 1280 | @compileError("unreachable"); | |
| 1280 | comptime unreachable; | |
| 1281 | 1281 | } |
| 1282 | 1282 | |
| 1283 | 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 | 538 | defer allocator.free(filename); |
| 539 | 539 | |
| 540 | 540 | // \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; | |
| 542 | 542 | |
| 543 | 543 | current_mapping.line_num = linenum; |
| 544 | 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 | 142 | { |
| 143 | 143 | try serveDocsFile(request, context, "docs/main.js", "application/javascript"); |
| 144 | 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 | 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 | 148 | } else if (std.mem.eql(u8, request.head.target, "/sources.tar") or |
| 149 | 149 | std.mem.eql(u8, request.head.target, "/debug/sources.tar")) |
| 150 | 150 | { |
| ... | ... | @@ -346,29 +346,39 @@ fn buildWasmBinary( |
| 346 | 346 | multi_reader.init(gpa, io, multi_reader_buffer.toStreams(), &.{ child.stdout.?, child.stderr.? }); |
| 347 | 347 | defer multi_reader.deinit(); |
| 348 | 348 | |
| 349 | try sendMessage(io, child.stdin.?, .update); | |
| 350 | try sendMessage(io, child.stdin.?, .exit); | |
| 349 | const stdout = multi_reader.reader(0); | |
| 350 | ||
| 351 | var stdin_buffer: [256]u8 = undefined; | |
| 352 | var stdin_writer = child.stdin.?.writerStreaming(io, &stdin_buffer); | |
| 353 | ||
| 354 | var client: std.zig.Client = .{ | |
| 355 | .in = stdout, | |
| 356 | .out = &stdin_writer.interface, | |
| 357 | }; | |
| 358 | ||
| 359 | try client.serveMessageHeader(.{ .tag = .update, .bytes_len = 0 }); | |
| 360 | try client.serveMessageHeader(.{ .tag = .exit, .bytes_len = 0 }); | |
| 361 | try client.out.flush(); | |
| 351 | 362 | |
| 352 | 363 | var result: ?Cache.Path = null; |
| 353 | 364 | var result_error_bundle = std.zig.ErrorBundle.empty; |
| 354 | 365 | |
| 355 | const stdout = multi_reader.fileReader(0); | |
| 356 | const MessageHeader = std.zig.Server.Message.Header; | |
| 357 | ||
| 358 | 366 | var eos_err: error{EndOfStream}!void = {}; |
| 359 | 367 | |
| 360 | 368 | while (true) { |
| 361 | const header = stdout.interface.takeStruct(MessageHeader, .little) catch |err| switch (err) { | |
| 362 | error.EndOfStream => break, | |
| 363 | error.ReadFailed => return stdout.err.?, | |
| 364 | }; | |
| 365 | const body = stdout.interface.take(header.bytes_len) catch |err| switch (err) { | |
| 369 | const header = client.receiveMessageWithMultiReader(&multi_reader, .none) catch |err| switch (err) { | |
| 370 | error.Timeout => unreachable, | |
| 366 | 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 | 376 | eos_err = e; |
| 368 | 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; | |
| 372 | 382 | |
| 373 | 383 | switch (header.tag) { |
| 374 | 384 | .zig_version => { |
| ... | ... | @@ -435,17 +445,6 @@ fn buildWasmBinary( |
| 435 | 445 | }; |
| 436 | 446 | } |
| 437 | 447 | |
| 438 | fn 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 | ||
| 449 | 448 | fn openBrowserTab(io: Io, url: []const u8) !void { |
| 450 | 449 | // Until https://github.com/ziglang/zig/issues/19205 is implemented, we |
| 451 | 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 | 78 | @disableInstrumentation(); |
| 79 | 79 | stdin_reader = .initStreaming(.stdin(), runner_threaded_io, &stdin_buffer); |
| 80 | 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 | 82 | .in = &stdin_reader.interface, |
| 83 | 83 | .out = &stdout_writer.interface, |
| 84 | .zig_version = builtin.zig_version_string, | |
| 85 | }); | |
| 84 | }; | |
| 85 | try server.serveStringMessage(.zig_version, builtin.zig_version_string); | |
| 86 | 86 | |
| 87 | 87 | while (true) { |
| 88 | 88 | const hdr = try server.receiveMessage(); |
| ... | ... | @@ -91,24 +91,23 @@ fn mainServer(init: std.process.Init.Minimal) !void { |
| 91 | 91 | return std.process.exit(0); |
| 92 | 92 | }, |
| 93 | 93 | .query_test_metadata => { |
| 94 | testing.allocator_instance = .init(std.heap.page_allocator, .{}); | |
| 95 | defer if (testing.allocator_instance.deinit() != 0) { | |
| 96 | @panic("internal test runner memory leak"); | |
| 97 | }; | |
| 94 | var sa: std.heap.SafeAllocator = .init(std.heap.page_allocator, .{}); | |
| 95 | defer if (sa.deinit() != 0) @panic("internal test runner memory leak"); | |
| 96 | const gpa = sa.allocator(); | |
| 98 | 97 | |
| 99 | 98 | var string_bytes: std.ArrayList(u8) = .empty; |
| 100 | defer string_bytes.deinit(testing.allocator); | |
| 101 | try string_bytes.append(testing.allocator, 0); // Reserve 0 for null. | |
| 99 | defer string_bytes.deinit(gpa); | |
| 100 | try string_bytes.append(gpa, 0); // Reserve 0 for null. | |
| 102 | 101 | |
| 103 | 102 | const test_fns = builtin.test_functions; |
| 104 | const names = try testing.allocator.alloc(u32, test_fns.len); | |
| 105 | defer testing.allocator.free(names); | |
| 106 | const expected_panic_msgs = try testing.allocator.alloc(u32, test_fns.len); | |
| 107 | defer testing.allocator.free(expected_panic_msgs); | |
| 103 | const names = try gpa.alloc(u32, test_fns.len); | |
| 104 | defer gpa.free(names); | |
| 105 | const expected_panic_msgs = try gpa.alloc(u32, test_fns.len); | |
| 106 | defer gpa.free(expected_panic_msgs); | |
| 108 | 107 | |
| 109 | 108 | for (test_fns, names, expected_panic_msgs) |test_fn, *name, *expected_panic_msg| { |
| 110 | 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 | 111 | string_bytes.appendSliceAssumeCapacity(test_fn.name); |
| 113 | 112 | string_bytes.appendAssumeCapacity(0); |
| 114 | 113 | expected_panic_msg.* = 0; |
| ... | ... | @@ -377,6 +376,7 @@ pub fn mainSimple() anyerror!void { |
| 377 | 376 | else => false, |
| 378 | 377 | }; |
| 379 | 378 | |
| 379 | testing.allocator_instance = .init(std.heap.page_allocator, .{}); | |
| 380 | 380 | testing.io_instance = .init(testing.allocator, .{}); |
| 381 | 381 | |
| 382 | 382 | var passed: u64 = 0; |
lib/compiler/translate-c/MacroTranslator.zig+1-1| ... | ... | @@ -361,7 +361,7 @@ fn parseCNumLit(mt: *MacroTranslator) ParseError!ZigNode { |
| 361 | 361 | return error.ParseError; |
| 362 | 362 | }, |
| 363 | 363 | }); |
| 364 | if (bytes.getLast().? == '.') { | |
| 364 | if (bytes.last().? == '.') { | |
| 365 | 365 | bytes.appendAssumeCapacity('0'); |
| 366 | 366 | } else if (mem.findAny(u8, bytes.items, ".eEpP") == null) { |
| 367 | 367 | bytes.appendSliceAssumeCapacity(".0"); |
lib/compiler/translate-c/main.zig+1-1| ... | ... | @@ -9,7 +9,7 @@ const compiler_util = @import("../util.zig"); |
| 9 | 9 | |
| 10 | 10 | const Translator = @import("Translator.zig"); |
| 11 | 11 | |
| 12 | const fast_exit = @import("builtin").mode != .Debug; | |
| 12 | const fast_exit = @import("builtin").mode != .debug; | |
| 13 | 13 | |
| 14 | 14 | pub fn main(init: process.Init) u8 { |
| 15 | 15 | const gpa = init.gpa; |
lib/compiler_rt.zig+193-177| ... | ... | @@ -1,4 +1,5 @@ |
| 1 | 1 | const builtin = @import("builtin"); |
| 2 | const compiler_rt = @This(); | |
| 2 | 3 | const ofmt_c = builtin.object_format == .c; |
| 3 | 4 | const native_endian = builtin.cpu.arch.endian(); |
| 4 | 5 | |
| ... | ... | @@ -84,144 +85,17 @@ comptime { |
| 84 | 85 | // Float routines |
| 85 | 86 | // conversion |
| 86 | 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 | 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 | 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 | 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"); | |
| 190 | 91 | |
| 191 | 92 | // comparison |
| 192 | 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"); | |
| 202 | 94 | |
| 203 | 95 | // arithmetic |
| 204 | 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 | 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"); | |
| 223 | 98 | |
| 224 | _ = @import("compiler_rt/divhf3.zig"); | |
| 225 | 99 | _ = @import("compiler_rt/divsf3.zig"); |
| 226 | 100 | _ = @import("compiler_rt/divdf3.zig"); |
| 227 | 101 | _ = @import("compiler_rt/divxf3.zig"); |
| ... | ... | @@ -235,25 +109,17 @@ comptime { |
| 235 | 109 | symbol(&__negsf2, "__negsf2"); |
| 236 | 110 | symbol(&__negdf2, "__negdf2"); |
| 237 | 111 | } |
| 238 | if (want_ppc_abi) symbol(&__negtf2, "__negkf2"); | |
| 239 | symbol(&__negtf2, "__negtf2"); | |
| 112 | if (want_ppc_abi) { | |
| 113 | symbol(&__negtf2, "__negkf2"); | |
| 114 | } else { | |
| 115 | symbol(&__negtf2, "__negtf2"); | |
| 116 | } | |
| 240 | 117 | symbol(&__negxf2, "__negxf2"); |
| 241 | 118 | |
| 242 | 119 | // other |
| 243 | 120 | _ = @import("compiler_rt/powiXf2.zig"); |
| 244 | 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 | 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"); | |
| 257 | 123 | |
| 258 | 124 | // Math routines. Alphabetically sorted. |
| 259 | 125 | _ = @import("compiler_rt/cos.zig"); |
| ... | ... | @@ -279,7 +145,7 @@ comptime { |
| 279 | 145 | _ = @import("compiler_rt/divmodei4.zig"); |
| 280 | 146 | _ = @import("compiler_rt/udivmodei4.zig"); |
| 281 | 147 | |
| 282 | _ = @import("compiler_rt/limb64.zig"); | |
| 148 | if (builtin.cpu.arch.isWasm()) _ = @import("compiler_rt/limb64.zig"); | |
| 283 | 149 | |
| 284 | 150 | // extra |
| 285 | 151 | _ = @import("compiler_rt/os_version_check.zig"); |
| ... | ... | @@ -290,7 +156,7 @@ comptime { |
| 290 | 156 | _ = @import("compiler_rt/clear_cache.zig"); |
| 291 | 157 | _ = @import("compiler_rt/hexagon.zig"); |
| 292 | 158 | |
| 293 | if (@import("builtin").object_format != .c) { | |
| 159 | if (builtin.object_format != .c) { | |
| 294 | 160 | if (builtin.zig_backend != .stage2_aarch64) _ = @import("compiler_rt/atomics.zig"); |
| 295 | 161 | _ = @import("compiler_rt/stack_probe.zig"); |
| 296 | 162 | |
| ... | ... | @@ -302,7 +168,6 @@ comptime { |
| 302 | 168 | _ = @import("compiler_rt/memcpy.zig"); |
| 303 | 169 | if (!ofmt_c) { |
| 304 | 170 | symbol(&memset, "memset"); |
| 305 | symbol(&__memset, "__memset"); | |
| 306 | 171 | } |
| 307 | 172 | _ = @import("compiler_rt/memmove.zig"); |
| 308 | 173 | symbol(&memcmp, "memcmp"); |
| ... | ... | @@ -367,10 +232,7 @@ pub const want_aeabi = switch (builtin.abi) { |
| 367 | 232 | .gnueabihf, |
| 368 | 233 | .android, |
| 369 | 234 | .androideabi, |
| 370 | => switch (builtin.cpu.arch) { | |
| 371 | .arm, .armeb, .thumb, .thumbeb => true, | |
| 372 | else => false, | |
| 373 | }, | |
| 235 | => builtin.cpu.arch.isArm(), | |
| 374 | 236 | else => false, |
| 375 | 237 | }; |
| 376 | 238 | |
| ... | ... | @@ -444,19 +306,108 @@ pub const gnu_f16_abi = switch (builtin.cpu.arch) { |
| 444 | 306 | pub const want_sparc64_abi = builtin.cpu.arch == .sparc64; |
| 445 | 307 | pub const want_sparc32_abi = builtin.cpu.arch == .sparc; |
| 446 | 308 | |
| 447 | pub fn F16T(comptime OtherType: type) type { | |
| 448 | return switch (builtin.cpu.arch) { | |
| 449 | .x86, .x86_64 => if (builtin.target.os.tag.isDarwin()) switch (OtherType) { | |
| 450 | // Starting with LLVM 16, Darwin uses different abi for f16 | |
| 451 | // depending on the type of the other return/argument..??? | |
| 452 | f32, f64 => u16, | |
| 453 | f80, f128 => f16, | |
| 454 | else => unreachable, | |
| 455 | } else f16, | |
| 456 | else => f16, | |
| 309 | /// For operations converting between `f16` and another floating point type. | |
| 310 | pub fn f16Conv(comptime OtherType: type) type { | |
| 311 | switch (std.zig.target.compilerRtFloatAbi(&builtin.target, 16)) { | |
| 312 | .hard => {}, | |
| 313 | .soft => return softFloatAbi(f16), | |
| 314 | } | |
| 315 | if (builtin.cpu.arch.isX86() and builtin.os.tag.isDarwin()) switch (OtherType) { | |
| 316 | else => unreachable, | |
| 317 | // Starting with LLVM 16, Darwin uses different abi for f16 | |
| 318 | // depending on the type of the other return/argument..??? | |
| 319 | f32, f64 => return softFloatAbi(f16), | |
| 320 | f80, f128 => {}, | |
| 321 | }; | |
| 322 | return hardFloatAbi(f16); | |
| 323 | } | |
| 324 | pub const @"f16" = switch (std.zig.target.compilerRtFloatAbi(&builtin.target, 16)) { | |
| 325 | .hard => hardFloatAbi(f16), | |
| 326 | .soft => softFloatAbi(f16), | |
| 327 | }; | |
| 328 | pub const @"f32" = switch (std.zig.target.compilerRtFloatAbi(&builtin.target, 32)) { | |
| 329 | .hard => hardFloatAbi(f32), | |
| 330 | .soft => softFloatAbi(f32), | |
| 331 | }; | |
| 332 | pub const @"f64" = switch (std.zig.target.compilerRtFloatAbi(&builtin.target, 64)) { | |
| 333 | .hard => hardFloatAbi(f64), | |
| 334 | .soft => softFloatAbi(f64), | |
| 335 | }; | |
| 336 | pub 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 | }; | |
| 352 | pub 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 | }; | |
| 371 | fn 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 | } | |
| 383 | fn 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 | } | |
| 395 | fn 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 | } |
| 459 | 406 | |
| 407 | pub fn Complex(comptime Float: type) type { | |
| 408 | return struct { real: Float, imag: Float }; | |
| 409 | } | |
| 410 | ||
| 460 | 411 | pub fn wideMultiply(comptime Z: type, a: Z, b: Z, hi: *Z, lo: *Z) void { |
| 461 | 412 | switch (Z) { |
| 462 | 413 | u16 => { |
| ... | ... | @@ -589,31 +540,31 @@ pub inline fn fneg(a: anytype) @TypeOf(a) { |
| 589 | 540 | return @bitCast(negated); |
| 590 | 541 | } |
| 591 | 542 | |
| 592 | fn __negxf2(a: f80) callconv(.c) f80 { | |
| 593 | return fneg(a); | |
| 543 | fn __neghf2(a: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { | |
| 544 | return compiler_rt.f16.toAbi(fneg(compiler_rt.f16.fromAbi(a))); | |
| 594 | 545 | } |
| 595 | 546 | |
| 596 | fn __neghf2(a: f16) callconv(.c) f16 { | |
| 597 | return fneg(a); | |
| 547 | fn __negsf2(a: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.Abi { | |
| 548 | return compiler_rt.f32.toAbi(fneg(compiler_rt.f32.fromAbi(a))); | |
| 598 | 549 | } |
| 599 | 550 | |
| 600 | fn __negdf2(a: f64) callconv(.c) f64 { | |
| 601 | return fneg(a); | |
| 551 | fn __negdf2(a: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { | |
| 552 | return compiler_rt.f64.toAbi(fneg(compiler_rt.f64.fromAbi(a))); | |
| 602 | 553 | } |
| 603 | 554 | |
| 604 | fn __aeabi_dneg(a: f64) callconv(.{ .arm_aapcs = .{} }) f64 { | |
| 605 | return fneg(a); | |
| 555 | fn __negxf2(a: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.Abi { | |
| 556 | return compiler_rt.f80.toAbi(fneg(compiler_rt.f80.fromAbi(a))); | |
| 606 | 557 | } |
| 607 | 558 | |
| 608 | fn __negtf2(a: f128) callconv(.c) f128 { | |
| 609 | return fneg(a); | |
| 559 | fn __negtf2(a: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { | |
| 560 | return compiler_rt.f128.toAbi(fneg(compiler_rt.f128.fromAbi(a))); | |
| 610 | 561 | } |
| 611 | 562 | |
| 612 | fn __negsf2(a: f32) callconv(.c) f32 { | |
| 563 | fn __aeabi_fneg(a: f32) callconv(.{ .arm_aapcs = .{} }) f32 { | |
| 613 | 564 | return fneg(a); |
| 614 | 565 | } |
| 615 | 566 | |
| 616 | fn __aeabi_fneg(a: f32) callconv(.{ .arm_aapcs = .{} }) f32 { | |
| 567 | fn __aeabi_dneg(a: f64) callconv(.{ .arm_aapcs = .{} }) f64 { | |
| 617 | 568 | return fneg(a); |
| 618 | 569 | } |
| 619 | 570 | |
| ... | ... | @@ -650,14 +601,80 @@ inline fn negXi2(comptime T: type, a: T) T { |
| 650 | 601 | return -a; |
| 651 | 602 | } |
| 652 | 603 | |
| 653 | pub fn memset(dest: ?[*]u8, c: u8, len: usize) callconv(.c) ?[*]u8 { | |
| 654 | @setRuntimeSafety(false); | |
| 604 | fn memsetSmallPowerOf2(d: [*]u8, b: u8, comptime size: usize) void { | |
| 605 | if (size > @sizeOf(usize)) { | |
| 606 | d[0..size].* = @splat(b); | |
| 607 | } else { | |
| 608 | const T = @Int(.unsigned, 8 * size); | |
| 609 | var splatted: T = 0; // Setting this to undefined causes a memset call and thus infinite recursion in Debug test-compiler-rt. | |
| 610 | @as(*[size]u8, @ptrCast(&splatted)).* = @splat(b); | |
| 611 | @as(*align(1) T, @ptrCast(d)).* = splatted; | |
| 612 | } | |
| 613 | } | |
| 614 | ||
| 615 | fn 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 | ||
| 637 | fn 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 | ||
| 670 | fn smallMemset(dest: ?[*]u8, c: c_int, len: usize) callconv(.c) ?[*]u8 { | |
| 671 | const b: u8 = @truncate(@as(c_uint, @bitCast(c))); | |
| 655 | 672 | |
| 656 | 673 | if (len != 0) { |
| 657 | 674 | var d = dest.?; |
| 658 | 675 | var n = len; |
| 659 | 676 | while (true) { |
| 660 | d[0] = c; | |
| 677 | d[0] = b; | |
| 661 | 678 | n -= 1; |
| 662 | 679 | if (n == 0) break; |
| 663 | 680 | d += 1; |
| ... | ... | @@ -667,11 +684,10 @@ pub fn memset(dest: ?[*]u8, c: u8, len: usize) callconv(.c) ?[*]u8 { |
| 667 | 684 | return dest; |
| 668 | 685 | } |
| 669 | 686 | |
| 670 | pub fn __memset(dest: ?[*]u8, c: u8, n: usize, dest_n: usize) callconv(.c) ?[*]u8 { | |
| 671 | if (dest_n < n) | |
| 672 | @panic("buffer overflow"); | |
| 673 | return memset(dest, c, n); | |
| 674 | } | |
| 687 | pub const memset = if (builtin.optimize == .small) | |
| 688 | smallMemset | |
| 689 | else | |
| 690 | fastMemset; | |
| 675 | 691 | |
| 676 | 692 | pub fn bcmp(vl: [*]allowzero const u8, vr: [*]allowzero const u8, n: usize) callconv(.c) c_int { |
| 677 | 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 | 14 | const sign: ST = a >> N - 1; |
| 15 | 15 | x +%= sign; |
| 16 | 16 | x ^= sign; |
| 17 | if (x < 0) | |
| 18 | @panic("compiler_rt absv: overflow"); | |
| 17 | if (x < 0) @panic("integer overflow"); | |
| 19 | 18 | return x; |
| 20 | 19 | } |
| 21 | 20 |
lib/compiler_rt/absvdi2.zig+3-2| ... | ... | @@ -1,5 +1,6 @@ |
| 1 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 2 | const absv = @import("./absv.zig").absv; | |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = compiler_rt.symbol; | |
| 3 | const absv = @import("absv.zig").absv; | |
| 3 | 4 | |
| 4 | 5 | comptime { |
| 5 | 6 | symbol(&__absvdi2, "__absvdi2"); |
lib/compiler_rt/absvsi2.zig+1-1| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | const compiler_rt = @import("../compiler_rt.zig"); |
| 2 | 2 | const symbol = compiler_rt.symbol; |
| 3 | const absv = @import("./absv.zig").absv; | |
| 3 | const absv = @import("absv.zig").absv; | |
| 4 | 4 | |
| 5 | 5 | comptime { |
| 6 | 6 | symbol(&__absvsi2, "__absvsi2"); |
lib/compiler_rt/absvti2.zig+3-2| ... | ... | @@ -1,5 +1,6 @@ |
| 1 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 2 | const absv = @import("./absv.zig").absv; | |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = compiler_rt.symbol; | |
| 3 | const absv = @import("absv.zig").absv; | |
| 3 | 4 | |
| 4 | 5 | comptime { |
| 5 | 6 | symbol(&__absvti2, "__absvti2"); |
lib/compiler_rt/adddf3.zig deleted-19| ... | ... | @@ -1,19 +0,0 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const addf3 = @import("./addf3.zig").addf3; | |
| 3 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 4 | ||
| 5 | comptime { | |
| 6 | if (compiler_rt.want_aeabi) { | |
| 7 | symbol(&__aeabi_dadd, "__aeabi_dadd"); | |
| 8 | } else { | |
| 9 | symbol(&__adddf3, "__adddf3"); | |
| 10 | } | |
| 11 | } | |
| 12 | ||
| 13 | fn __adddf3(a: f64, b: f64) callconv(.c) f64 { | |
| 14 | return addf3(f64, a, b); | |
| 15 | } | |
| 16 | ||
| 17 | fn __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 | 1 | const std = @import("std"); |
| 2 | 2 | const math = std.math; |
| 3 | 3 | const compiler_rt = @import("../compiler_rt.zig"); |
| 4 | const symbol = compiler_rt.symbol; | |
| 4 | 5 | const normalize = compiler_rt.normalize; |
| 5 | 6 | |
| 7 | comptime { | |
| 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 | ||
| 28 | fn __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 | } | |
| 31 | pub fn add_f16(a: f16, b: f16) f16 { | |
| 32 | return addf3(f16, a, b); | |
| 33 | } | |
| 34 | ||
| 35 | fn __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 | } | |
| 38 | fn __aeabi_fadd(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) f32 { | |
| 39 | return add_f32(a, b); | |
| 40 | } | |
| 41 | pub fn add_f32(a: f32, b: f32) f32 { | |
| 42 | return addf3(f32, a, b); | |
| 43 | } | |
| 44 | ||
| 45 | fn __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 | } | |
| 48 | fn __aeabi_dadd(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) f64 { | |
| 49 | return add_f64(a, b); | |
| 50 | } | |
| 51 | pub fn add_f64(a: f64, b: f64) f64 { | |
| 52 | return addf3(f64, a, b); | |
| 53 | } | |
| 54 | ||
| 55 | fn __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 | } | |
| 58 | pub fn add_f80(a: f80, b: f80) f80 { | |
| 59 | return addf3(f80, a, b); | |
| 60 | } | |
| 61 | ||
| 62 | fn __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 | } | |
| 65 | fn _Qp_add(c: *f128, a: *f128, b: *f128) callconv(.c) void { | |
| 66 | c.* = add_f128(a.*, b.*); | |
| 67 | } | |
| 68 | pub fn add_f128(a: f128, b: f128) f128 { | |
| 69 | return addf3(f128, a, b); | |
| 70 | } | |
| 71 | ||
| 72 | comptime { | |
| 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 | ||
| 93 | fn __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 | } | |
| 96 | pub fn sub_f16(a: f16, b: f16) f16 { | |
| 97 | return add_f16(a, compiler_rt.fneg(b)); | |
| 98 | } | |
| 99 | ||
| 100 | fn __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 | } | |
| 103 | fn __aeabi_fsub(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) f32 { | |
| 104 | return sub_f32(a, b); | |
| 105 | } | |
| 106 | pub fn sub_f32(a: f32, b: f32) f32 { | |
| 107 | return add_f32(a, compiler_rt.fneg(b)); | |
| 108 | } | |
| 109 | ||
| 110 | fn __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 | } | |
| 113 | fn __aeabi_dsub(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) f64 { | |
| 114 | return sub_f64(a, b); | |
| 115 | } | |
| 116 | pub fn sub_f64(a: f64, b: f64) f64 { | |
| 117 | return add_f64(a, compiler_rt.fneg(b)); | |
| 118 | } | |
| 119 | ||
| 120 | fn __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 | } | |
| 123 | pub fn sub_f80(a: f80, b: f80) f80 { | |
| 124 | return add_f80(a, compiler_rt.fneg(b)); | |
| 125 | } | |
| 126 | ||
| 127 | fn __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 | } | |
| 130 | fn _Qp_sub(c: *f128, a: *const f128, b: *const f128) callconv(.c) void { | |
| 131 | c.* = sub_f128(a.*, b.*); | |
| 132 | } | |
| 133 | pub fn sub_f128(a: f128, b: f128) f128 { | |
| 134 | return add_f128(a, compiler_rt.fneg(b)); | |
| 135 | } | |
| 136 | ||
| 6 | 137 | /// Ported from: |
| 7 | 138 | /// |
| 8 | 139 | /// https://github.com/llvm/llvm-project/blob/02d85149a05cb1f6dc49f0ba7a2ceca53718ae17/compiler-rt/lib/builtins/fp_add_impl.inc |
| 9 | pub inline fn addf3(comptime T: type, a: T, b: T) T { | |
| 140 | inline fn addf3(comptime T: type, a: T, b: T) T { | |
| 10 | 141 | const bits = @typeInfo(T).float.bits; |
| 11 | 142 | const Z = @Int(.unsigned, bits); |
| 12 | 143 |
lib/compiler_rt/addf3_test.zig+7-6| ... | ... | @@ -8,12 +8,13 @@ const builtin = @import("builtin"); |
| 8 | 8 | const math = std.math; |
| 9 | 9 | const qnan128: f128 = @bitCast(@as(u128, 0x7fff800000000000) << 64); |
| 10 | 10 | |
| 11 | const __addtf3 = @import("addtf3.zig").__addtf3; | |
| 12 | const __addxf3 = @import("addxf3.zig").__addxf3; | |
| 13 | const __subtf3 = @import("subtf3.zig").__subtf3; | |
| 11 | const impl = @import("addf3.zig"); | |
| 12 | const add_f128 = impl.add_f128; | |
| 13 | const add_f80 = impl.add_f80; | |
| 14 | const sub_f128 = impl.sub_f128; | |
| 14 | 15 | |
| 15 | 16 | fn 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); | |
| 17 | 18 | |
| 18 | 19 | const rep: u128 = @bitCast(x); |
| 19 | 20 | const hi: u64 = @intCast(rep >> 64); |
| ... | ... | @@ -52,7 +53,7 @@ test "addtf3" { |
| 52 | 53 | } |
| 53 | 54 | |
| 54 | 55 | fn 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); | |
| 56 | 57 | |
| 57 | 58 | const rep: u128 = @bitCast(x); |
| 58 | 59 | const hi: u64 = @intCast(rep >> 64); |
| ... | ... | @@ -91,7 +92,7 @@ test "subtf3" { |
| 91 | 92 | const qnan80: f80 = @bitCast(@as(u80, @bitCast(math.nan(f80))) | (1 << (math.floatFractionalBits(f80) - 1))); |
| 92 | 93 | |
| 93 | 94 | fn test__addxf3(a: f80, b: f80, expected: u80) !void { |
| 94 | const x = __addxf3(a, b); | |
| 95 | const x = add_f80(a, b); | |
| 95 | 96 | const rep: u80 = @bitCast(x); |
| 96 | 97 | |
| 97 | 98 | if (rep == expected) |
lib/compiler_rt/addhf3.zig deleted-11| ... | ... | @@ -1,11 +0,0 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = compiler_rt.symbol; | |
| 3 | const addf3 = @import("./addf3.zig").addf3; | |
| 4 | ||
| 5 | comptime { | |
| 6 | symbol(&__addhf3, "__addhf3"); | |
| 7 | } | |
| 8 | ||
| 9 | fn __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 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const addf3 = @import("./addf3.zig").addf3; | |
| 3 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 4 | ||
| 5 | comptime { | |
| 6 | if (compiler_rt.want_aeabi) { | |
| 7 | symbol(&__aeabi_fadd, "__aeabi_fadd"); | |
| 8 | } else { | |
| 9 | symbol(&__addsf3, "__addsf3"); | |
| 10 | } | |
| 11 | } | |
| 12 | ||
| 13 | fn __addsf3(a: f32, b: f32) callconv(.c) f32 { | |
| 14 | return addf3(f32, a, b); | |
| 15 | } | |
| 16 | ||
| 17 | fn __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 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = compiler_rt.symbol; | |
| 3 | const addf3 = @import("./addf3.zig").addf3; | |
| 4 | ||
| 5 | comptime { | |
| 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 | ||
| 16 | pub fn __addtf3(a: f128, b: f128) callconv(.c) f128 { | |
| 17 | return addf3(f128, a, b); | |
| 18 | } | |
| 19 | ||
| 20 | fn _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 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = compiler_rt.symbol; | |
| 2 | 3 | const testing = @import("std").testing; |
| 3 | 4 | |
| 4 | 5 | comptime { |
| ... | ... | @@ -9,7 +10,7 @@ pub fn __addvdi3(a: i64, b: i64) callconv(.c) i64 { |
| 9 | 10 | const sum = a +% b; |
| 10 | 11 | // Overflow occurred iff both operands have the same sign, and the sign of the sum does |
| 11 | 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 | 14 | return sum; |
| 14 | 15 | } |
| 15 | 16 |
lib/compiler_rt/addvsi3.zig+1-1| ... | ... | @@ -10,7 +10,7 @@ pub fn __addvsi3(a: i32, b: i32) callconv(.c) i32 { |
| 10 | 10 | const sum = a +% b; |
| 11 | 11 | // Overflow occurred iff both operands have the same sign, and the sign of the sum does |
| 12 | 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 | 14 | return sum; |
| 15 | 15 | } |
| 16 | 16 |
lib/compiler_rt/addxf3.zig deleted-11| ... | ... | @@ -1,11 +0,0 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = compiler_rt.symbol; | |
| 3 | const addf3 = @import("./addf3.zig").addf3; | |
| 4 | ||
| 5 | comptime { | |
| 6 | symbol(&__addxf3, "__addxf3"); | |
| 7 | } | |
| 8 | ||
| 9 | pub 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 | 5 | const std = @import("std"); |
| 6 | 6 | |
| 7 | 7 | const compiler_rt = @import("../compiler_rt.zig"); |
| 8 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 8 | const symbol = compiler_rt.symbol; | |
| 9 | 9 | |
| 10 | 10 | // This parameter is true iff the target architecture supports the bare minimum |
| 11 | 11 | // to implement the atomic load/store intrinsics. |
lib/compiler_rt/aulldiv.zig+1-1| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | const builtin = @import("builtin"); |
| 2 | 2 | |
| 3 | 3 | const compiler_rt = @import("../compiler_rt.zig"); |
| 4 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 4 | const symbol = compiler_rt.symbol; | |
| 5 | 5 | |
| 6 | 6 | comptime { |
| 7 | 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 | |
| 3 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 4 | const comparef = @import("./comparef.zig"); | |
| 5 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 6 | ||
| 7 | comptime { | |
| 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`. | |
| 27 | fn __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." | |
| 33 | pub 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. | |
| 40 | pub 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. | |
| 47 | pub 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." | |
| 53 | pub fn __ltdf2(a: f64, b: f64) callconv(.c) i32 { | |
| 54 | return __cmpdf2(a, b); | |
| 55 | } | |
| 56 | ||
| 57 | fn __aeabi_dcmpeq(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 { | |
| 58 | return @intFromBool(comparef.cmpf2(f64, comparef.LE, a, b) == .Equal); | |
| 59 | } | |
| 60 | ||
| 61 | fn __aeabi_dcmplt(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 { | |
| 62 | return @intFromBool(comparef.cmpf2(f64, comparef.LE, a, b) == .Less); | |
| 63 | } | |
| 64 | ||
| 65 | fn __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 | |
| 3 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 4 | const comparef = @import("./comparef.zig"); | |
| 5 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 6 | ||
| 7 | comptime { | |
| 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`. | |
| 43 | fn __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." | |
| 49 | fn __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. | |
| 56 | fn __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. | |
| 63 | fn __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." | |
| 69 | fn __lttf2(a: f128, b: f128) callconv(.c) i32 { | |
| 70 | return __cmptf2(a, b); | |
| 71 | } | |
| 72 | ||
| 73 | const SparcFCMP = enum(i32) { | |
| 74 | Equal = 0, | |
| 75 | Less = 1, | |
| 76 | Greater = 2, | |
| 77 | Unordered = 3, | |
| 78 | }; | |
| 79 | ||
| 80 | fn _Qp_cmp(a: *const f128, b: *const f128) callconv(.c) i32 { | |
| 81 | return @backingInt(comparef.cmpf2(f128, SparcFCMP, a.*, b.*)); | |
| 82 | } | |
| 83 | ||
| 84 | fn _Qp_feq(a: *const f128, b: *const f128) callconv(.c) bool { | |
| 85 | return @as(SparcFCMP, @fromBackingInt(@intCast(_Qp_cmp(a, b)))) == .Equal; | |
| 86 | } | |
| 87 | ||
| 88 | fn _Qp_fne(a: *const f128, b: *const f128) callconv(.c) bool { | |
| 89 | return @as(SparcFCMP, @fromBackingInt(@intCast(_Qp_cmp(a, b)))) != .Equal; | |
| 90 | } | |
| 91 | ||
| 92 | fn _Qp_flt(a: *const f128, b: *const f128) callconv(.c) bool { | |
| 93 | return @as(SparcFCMP, @fromBackingInt(@intCast(_Qp_cmp(a, b)))) == .Less; | |
| 94 | } | |
| 95 | ||
| 96 | fn _Qp_fgt(a: *const f128, b: *const f128) callconv(.c) bool { | |
| 97 | return @as(SparcFCMP, @fromBackingInt(@intCast(_Qp_cmp(a, b)))) == .Greater; | |
| 98 | } | |
| 99 | ||
| 100 | fn _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 | ||
| 107 | fn _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 | ||
| 114 | fn _Q_cmp(a: f128, b: f128) callconv(.c) i32 { | |
| 115 | return @backingInt(comparef.cmpf2(f128, SparcFCMP, a, b)); | |
| 116 | } | |
| 117 | ||
| 118 | fn _Q_feq(a: f128, b: f128) callconv(.c) bool { | |
| 119 | return @as(SparcFCMP, @fromBackingInt(@intCast(_Q_cmp(a, b)))) == .Equal; | |
| 120 | } | |
| 121 | ||
| 122 | fn _Q_fne(a: f128, b: f128) callconv(.c) bool { | |
| 123 | return @as(SparcFCMP, @fromBackingInt(@intCast(_Q_cmp(a, b)))) != .Equal; | |
| 124 | } | |
| 125 | ||
| 126 | fn _Q_flt(a: f128, b: f128) callconv(.c) bool { | |
| 127 | return @as(SparcFCMP, @fromBackingInt(@intCast(_Q_cmp(a, b)))) == .Less; | |
| 128 | } | |
| 129 | ||
| 130 | fn _Q_fgt(a: f128, b: f128) callconv(.c) bool { | |
| 131 | return @as(SparcFCMP, @fromBackingInt(@intCast(_Q_cmp(a, b)))) == .Greater; | |
| 132 | } | |
| 133 | ||
| 134 | fn _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 | ||
| 141 | fn _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 | |
| 3 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 4 | const symbol = compiler_rt.symbol; | |
| 5 | const comparef = @import("./comparef.zig"); | |
| 6 | ||
| 7 | comptime { | |
| 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`. | |
| 21 | fn __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." | |
| 27 | fn __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. | |
| 34 | fn __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. | |
| 41 | fn __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." | |
| 47 | fn __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 | 5 | const std = @import("std"); |
| 6 | 6 | const builtin = @import("builtin"); |
| 7 | 7 | |
| 8 | const __eqdf2 = @import("./cmpdf2.zig").__eqdf2; | |
| 9 | const __ledf2 = @import("./cmpdf2.zig").__ledf2; | |
| 10 | const __ltdf2 = @import("./cmpdf2.zig").__ltdf2; | |
| 11 | const __nedf2 = @import("./cmpdf2.zig").__nedf2; | |
| 8 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 12 | 9 | |
| 13 | const __gedf2 = @import("./gedf2.zig").__gedf2; | |
| 14 | const __gtdf2 = @import("./gedf2.zig").__gtdf2; | |
| 15 | ||
| 16 | const __unorddf2 = @import("./unorddf2.zig").__unorddf2; | |
| 17 | ||
| 18 | const 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 | ||
| 30 | fn 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 | } | |
| 10 | const impl = @import("comparef.zig"); | |
| 11 | const Order = impl.Order; | |
| 12 | const cmp_f64 = impl.cmp_f64; | |
| 13 | const unord_f64 = impl.unord_f64; | |
| 54 | 14 | |
| 55 | 15 | const arguments = [_]f64{ |
| 56 | 16 | std.math.nan(f64), |
| ... | ... | @@ -73,36 +33,20 @@ const arguments = [_]f64{ |
| 73 | 33 | std.math.inf(f64), |
| 74 | 34 | }; |
| 75 | 35 | |
| 76 | fn generateVector(comptime a: f64, comptime b: f64) TestVector { | |
| 77 | const leResult = if (a < b) -1 else if (a == b) 0 else 1; | |
| 78 | const geResult = if (a > b) 1 else if (a == b) 0 else -1; | |
| 79 | const unResult = if (a != a or b != b) 1 else 0; | |
| 80 | return TestVector{ | |
| 81 | .a = a, | |
| 82 | .b = b, | |
| 83 | .eqReference = leResult, | |
| 84 | .geReference = geResult, | |
| 85 | .gtReference = geResult, | |
| 86 | .leReference = leResult, | |
| 87 | .ltReference = leResult, | |
| 88 | .neReference = leResult, | |
| 89 | .unReference = unResult, | |
| 90 | }; | |
| 91 | } | |
| 92 | ||
| 93 | const test_vectors = init: { | |
| 94 | @setEvalBranchQuota(10000); | |
| 95 | var vectors: [arguments.len * arguments.len]TestVector = undefined; | |
| 36 | test "compare f64" { | |
| 96 | 37 | for (arguments[0..], 0..) |arg_i, i| { |
| 97 | 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 | ||
| 104 | test "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 | const builtin = @import("builtin"); | |
| 1 | 2 | const std = @import("std"); |
| 2 | 3 | |
| 3 | 4 | const compiler_rt = @import("../compiler_rt.zig"); |
| 4 | 5 | const symbol = compiler_rt.symbol; |
| 5 | 6 | |
| 6 | comptime { | |
| 7 | if (compiler_rt.want_aeabi) { | |
| 8 | symbol(&__aeabi_fcmpun, "__aeabi_fcmpun"); | |
| 9 | } else { | |
| 10 | symbol(&__unordsf2, "__unordsf2"); | |
| 11 | } | |
| 12 | ||
| 13 | symbol(&__unordxf2, "__unordxf2"); | |
| 7 | const Unordered = if (builtin.cpu.arch == .avr) | |
| 8 | i8 | |
| 9 | else if (builtin.cpu.arch.isAARCH64()) | |
| 10 | i32 | |
| 11 | else if (builtin.target.cTypeBitSize(.long).? >= builtin.target.ptrBitWidth()) | |
| 12 | c_long | |
| 13 | else | |
| 14 | c_longlong; | |
| 15 | pub const Order = enum(Unordered) { lt = -1, eq = 0, gt = 1 }; | |
| 16 | const SparcOrder = enum(i32) { eq = 0, lt = 1, gt = 2, un = 3 }; | |
| 14 | 17 | |
| 15 | symbol(&__eqhf2, "__eqhf2"); | |
| 16 | symbol(&__nehf2, "__nehf2"); | |
| 17 | symbol(&__lehf2, "__lehf2"); | |
| 18 | comptime { | |
| 18 | 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"); | |
| 20 | 27 | |
| 21 | 28 | if (compiler_rt.want_aeabi) { |
| 22 | 29 | symbol(&__aeabi_fcmpeq, "__aeabi_fcmpeq"); |
| 23 | 30 | symbol(&__aeabi_fcmplt, "__aeabi_fcmplt"); |
| 24 | 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 | 42 | } else { |
| 26 | symbol(&__eqsf2, "__eqsf2"); | |
| 27 | symbol(&__nesf2, "__nesf2"); | |
| 28 | symbol(&__lesf2, "__lesf2"); | |
| 29 | 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 | } |
| 32 | 61 | |
| 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 | 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 | 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 | ||
| 40 | pub fn __unordhf2(a: f16, b: f16) callconv(.c) i32 { | |
| 41 | return unordcmp(f16, a, b); | |
| 42 | 105 | } |
| 43 | 106 | |
| 44 | pub fn __unordtf2(a: f128, b: f128) callconv(.c) i32 { | |
| 45 | return unordcmp(f128, a, b); | |
| 107 | fn __cmphf2(a: compiler_rt.f16.Abi, b: compiler_rt.f16.Abi) callconv(.c) Order { | |
| 108 | return cmp_f16(compiler_rt.f16.fromAbi(a), compiler_rt.f16.fromAbi(b)) orelse .gt; | |
| 46 | 109 | } |
| 47 | ||
| 48 | /// "These functions calculate a <=> b. That is, if a is less than b, they return -1; | |
| 49 | /// if a is greater than b, they return 1; and if a and b are equal they return 0. | |
| 50 | /// If either argument is NaN they return 1..." | |
| 51 | /// | |
| 52 | /// Note that this matches the definition of `__lesf2`, `__eqsf2`, `__nesf2`, `__cmpsf2`, | |
| 53 | /// and `__ltsf2`. | |
| 54 | fn __cmpsf2(a: f32, b: f32) callconv(.c) i32 { | |
| 55 | return @backingInt(cmpf2(f32, LE, a, b)); | |
| 110 | fn __gehf2(a: compiler_rt.f16.Abi, b: compiler_rt.f16.Abi) callconv(.c) Order { | |
| 111 | return cmp_f16(compiler_rt.f16.fromAbi(a), compiler_rt.f16.fromAbi(b)) orelse .lt; | |
| 56 | 112 | } |
| 57 | ||
| 58 | /// "These functions return a value less than or equal to zero if neither argument is NaN, | |
| 59 | /// and a is less than or equal to b." | |
| 60 | pub fn __lesf2(a: f32, b: f32) callconv(.c) i32 { | |
| 61 | return __cmpsf2(a, b); | |
| 113 | fn __unordhf2(a: compiler_rt.f16.Abi, b: compiler_rt.f16.Abi) callconv(.c) Unordered { | |
| 114 | return @intFromBool(unord_f16(compiler_rt.f16.fromAbi(a), compiler_rt.f16.fromAbi(b))); | |
| 62 | 115 | } |
| 63 | ||
| 64 | /// "These functions return zero if neither argument is NaN, and a and b are equal." | |
| 65 | /// Note that due to some kind of historical accident, __eqsf2 and __nesf2 are defined | |
| 66 | /// to have the same return value. | |
| 67 | pub fn __eqsf2(a: f32, b: f32) callconv(.c) i32 { | |
| 68 | return __cmpsf2(a, b); | |
| 116 | pub fn cmp_f16(a: f16, b: f16) ?Order { | |
| 117 | return cmpf2(f16, a, b); | |
| 69 | 118 | } |
| 70 | ||
| 71 | /// "These functions return a nonzero value if either argument is NaN, or if a and b are unequal." | |
| 72 | /// Note that due to some kind of historical accident, __eqsf2 and __nesf2 are defined | |
| 73 | /// to have the same return value. | |
| 74 | pub fn __nesf2(a: f32, b: f32) callconv(.c) i32 { | |
| 75 | return __cmpsf2(a, b); | |
| 119 | pub fn unord_f16(a: f16, b: f16) bool { | |
| 120 | return unord(f16, a, b); | |
| 76 | 121 | } |
| 77 | 122 | |
| 78 | /// "These functions return a value less than zero if neither argument is NaN, and a | |
| 79 | /// is strictly less than b." | |
| 80 | pub fn __ltsf2(a: f32, b: f32) callconv(.c) i32 { | |
| 81 | return __cmpsf2(a, b); | |
| 123 | fn __cmpsf2(a: compiler_rt.f32.Abi, b: compiler_rt.f32.Abi) callconv(.c) Order { | |
| 124 | return cmp_f32(compiler_rt.f32.fromAbi(a), compiler_rt.f32.fromAbi(b)) orelse .gt; | |
| 82 | 125 | } |
| 83 | ||
| 84 | 126 | fn __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 | ||
| 88 | 129 | fn __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 | ||
| 92 | 132 | fn __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 | } |
| 95 | ||
| 96 | /// "These functions calculate a <=> b. That is, if a is less than b, they return -1; | |
| 97 | /// if a is greater than b, they return 1; and if a and b are equal they return 0. | |
| 98 | /// If either argument is NaN they return 1..." | |
| 99 | /// | |
| 100 | /// Note that this matches the definition of `__lehf2`, `__eqhf2`, `__nehf2`, `__cmphf2`, | |
| 101 | /// and `__lthf2`. | |
| 102 | fn __cmphf2(a: f16, b: f16) callconv(.c) i32 { | |
| 103 | return @backingInt(cmpf2(f16, LE, a, b)); | |
| 135 | fn __gesf2(a: compiler_rt.f32.Abi, b: compiler_rt.f32.Abi) callconv(.c) Order { | |
| 136 | return cmp_f32(compiler_rt.f32.fromAbi(a), compiler_rt.f32.fromAbi(b)) orelse .lt; | |
| 104 | 137 | } |
| 105 | ||
| 106 | /// "These functions return a value less than or equal to zero if neither argument is NaN, | |
| 107 | /// and a is less than or equal to b." | |
| 108 | fn __lehf2(a: f16, b: f16) callconv(.c) i32 { | |
| 109 | return __cmphf2(a, b); | |
| 138 | fn __aeabi_fcmpge(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 { | |
| 139 | return @intFromBool(cmp_f32(a, b) orelse .lt != .lt); | |
| 110 | 140 | } |
| 111 | ||
| 112 | /// "These functions return zero if neither argument is NaN, and a and b are equal." | |
| 113 | /// Note that due to some kind of historical accident, __eqhf2 and __nehf2 are defined | |
| 114 | /// to have the same return value. | |
| 115 | fn __eqhf2(a: f16, b: f16) callconv(.c) i32 { | |
| 116 | return __cmphf2(a, b); | |
| 141 | fn __aeabi_fcmpgt(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 { | |
| 142 | return @intFromBool(cmp_f32(a, b) == .gt); | |
| 117 | 143 | } |
| 118 | ||
| 119 | /// "These functions return a nonzero value if either argument is NaN, or if a and b are unequal." | |
| 120 | /// Note that due to some kind of historical accident, __eqhf2 and __nehf2 are defined | |
| 121 | /// to have the same return value. | |
| 122 | fn __nehf2(a: f16, b: f16) callconv(.c) i32 { | |
| 123 | return __cmphf2(a, b); | |
| 144 | fn __unordsf2(a: compiler_rt.f32.Abi, b: compiler_rt.f32.Abi) callconv(.c) Unordered { | |
| 145 | return @intFromBool(unord_f32(compiler_rt.f32.fromAbi(a), compiler_rt.f32.fromAbi(b))); | |
| 124 | 146 | } |
| 125 | ||
| 126 | /// "These functions return a value less than zero if neither argument is NaN, and a | |
| 127 | /// is strictly less than b." | |
| 128 | fn __lthf2(a: f16, b: f16) callconv(.c) i32 { | |
| 129 | return __cmphf2(a, b); | |
| 147 | fn __aeabi_fcmpun(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 { | |
| 148 | return @intFromBool(unord_f32(a, b)); | |
| 130 | 149 | } |
| 131 | ||
| 132 | fn __unordxf2(a: f80, b: f80) callconv(.c) i32 { | |
| 133 | return unordcmp(f80, a, b); | |
| 150 | pub fn cmp_f32(a: f32, b: f32) ?Order { | |
| 151 | return cmpf2(f32, a, b); | |
| 152 | } | |
| 153 | pub fn unord_f32(a: f32, b: f32) bool { | |
| 154 | return unord(f32, a, b); | |
| 134 | 155 | } |
| 135 | 156 | |
| 136 | pub fn __unordsf2(a: f32, b: f32) callconv(.c) i32 { | |
| 137 | return unordcmp(f32, a, b); | |
| 157 | fn __cmpdf2(a: compiler_rt.f64.Abi, b: compiler_rt.f64.Abi) callconv(.c) Order { | |
| 158 | return cmp_f64(compiler_rt.f64.fromAbi(a), compiler_rt.f64.fromAbi(b)) orelse .gt; | |
| 159 | } | |
| 160 | fn __aeabi_dcmpeq(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 { | |
| 161 | return @intFromBool(cmp_f64(a, b) == .eq); | |
| 162 | } | |
| 163 | fn __aeabi_dcmplt(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 { | |
| 164 | return @intFromBool(cmp_f64(a, b) == .lt); | |
| 165 | } | |
| 166 | fn __aeabi_dcmple(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 { | |
| 167 | return @intFromBool(cmp_f64(a, b) orelse .gt != .gt); | |
| 168 | } | |
| 169 | fn __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 | } | |
| 172 | fn __aeabi_dcmpge(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 { | |
| 173 | return @intFromBool(cmp_f64(a, b) orelse .lt != .lt); | |
| 174 | } | |
| 175 | fn __aeabi_dcmpgt(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 { | |
| 176 | return @intFromBool(cmp_f64(a, b) == .gt); | |
| 177 | } | |
| 178 | fn __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 | } | |
| 181 | fn __aeabi_dcmpun(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 { | |
| 182 | return @intFromBool(unord_f64(a, b)); | |
| 183 | } | |
| 184 | pub fn cmp_f64(a: f64, b: f64) ?Order { | |
| 185 | return cmpf2(f64, a, b); | |
| 186 | } | |
| 187 | pub fn unord_f64(a: f64, b: f64) bool { | |
| 188 | return unord(f64, a, b); | |
| 138 | 189 | } |
| 139 | 190 | |
| 140 | fn __aeabi_fcmpun(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 { | |
| 141 | return unordcmp(f32, a, b); | |
| 191 | fn __cmpxf2(a: compiler_rt.f80.Abi, b: compiler_rt.f80.Abi) callconv(.c) Order { | |
| 192 | return cmp_f80(compiler_rt.f80.fromAbi(a), compiler_rt.f80.fromAbi(b)) orelse .gt; | |
| 193 | } | |
| 194 | fn __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 | } |
| 197 | fn __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 | } | |
| 200 | pub 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; | |
| 143 | 207 | |
| 144 | pub const LE = enum(i32) { | |
| 145 | Less = -1, | |
| 146 | Equal = 0, | |
| 147 | Greater = 1, | |
| 208 | // If either a or b is NaN, they are unordered. | |
| 209 | if ((a_rep.exp & special_exp == special_exp and a_rep.fraction ^ int_bit != 0) or | |
| 210 | (b_rep.exp & special_exp == special_exp and b_rep.fraction ^ int_bit != 0)) | |
| 211 | return null; | |
| 148 | 212 | |
| 149 | const Unordered: LE = .Greater; | |
| 150 | }; | |
| 213 | // If a and b are both zeros, they are equal. | |
| 214 | if ((a_rep.fraction | b_rep.fraction) | ((a_rep.exp | b_rep.exp) & special_exp) == 0) | |
| 215 | return .eq; | |
| 151 | 216 | |
| 152 | pub const GE = enum(i32) { | |
| 153 | Less = -1, | |
| 154 | Equal = 0, | |
| 155 | Greater = 1, | |
| 217 | if (@intFromBool(a_rep.exp == b_rep.exp) & @intFromBool(a_rep.fraction == b_rep.fraction) != 0) { | |
| 218 | return .eq; | |
| 219 | } else if (a_rep.exp & sign_bit != b_rep.exp & sign_bit) { | |
| 220 | // signs are different | |
| 221 | if (@as(i16, @bitCast(a_rep.exp)) < @as(i16, @bitCast(b_rep.exp))) { | |
| 222 | return .lt; | |
| 223 | } else { | |
| 224 | return .gt; | |
| 225 | } | |
| 226 | } else { | |
| 227 | const a_fraction = a_rep.fraction | (@as(u80, a_rep.exp) << sig_bits); | |
| 228 | const b_fraction = b_rep.fraction | (@as(u80, b_rep.exp) << sig_bits); | |
| 229 | if ((a_fraction < b_fraction) == (a_rep.exp & sign_bit == 0)) { | |
| 230 | return .lt; | |
| 231 | } else { | |
| 232 | return .gt; | |
| 233 | } | |
| 234 | } | |
| 235 | } | |
| 236 | pub fn unord_f80(a: f80, b: f80) bool { | |
| 237 | return unord(f80, a, b); | |
| 238 | } | |
| 156 | 239 | |
| 157 | const Unordered: GE = .Less; | |
| 158 | }; | |
| 240 | fn __cmptf2(a: compiler_rt.f128.Abi, b: compiler_rt.f128.Abi) callconv(.c) Order { | |
| 241 | return cmp_f128(compiler_rt.f128.fromAbi(a), compiler_rt.f128.fromAbi(b)) orelse .gt; | |
| 242 | } | |
| 243 | fn __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 | } | |
| 246 | fn __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 | } | |
| 249 | fn _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 | } | |
| 256 | fn _Qp_feq(a: *const f128, b: *const f128) callconv(.c) i32 { | |
| 257 | return @intFromBool(cmp_f128(a.*, b.*) == .eq); | |
| 258 | } | |
| 259 | fn _Qp_fne(a: *const f128, b: *const f128) callconv(.c) i32 { | |
| 260 | return @intFromBool(cmp_f128(a.*, b.*) != .eq); | |
| 261 | } | |
| 262 | fn _Qp_flt(a: *const f128, b: *const f128) callconv(.c) i32 { | |
| 263 | return @intFromBool(cmp_f128(a.*, b.*) == .lt); | |
| 264 | } | |
| 265 | fn _Qp_fle(a: *const f128, b: *const f128) callconv(.c) i32 { | |
| 266 | return @intFromBool((cmp_f128(a.*, b.*) orelse .gt) != .gt); | |
| 267 | } | |
| 268 | fn _Qp_fgt(a: *const f128, b: *const f128) callconv(.c) i32 { | |
| 269 | return @intFromBool(cmp_f128(a.*, b.*) == .gt); | |
| 270 | } | |
| 271 | fn _Qp_fge(a: *const f128, b: *const f128) callconv(.c) i32 { | |
| 272 | return @intFromBool((cmp_f128(a.*, b.*) orelse .lt) != .lt); | |
| 273 | } | |
| 274 | fn _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 | } | |
| 281 | fn _Q_feq(a: f128, b: f128) callconv(.c) i32 { | |
| 282 | return @intFromBool(cmp_f128(a, b) == .eq); | |
| 283 | } | |
| 284 | fn _Q_fne(a: f128, b: f128) callconv(.c) i32 { | |
| 285 | return @intFromBool(cmp_f128(a, b) != .eq); | |
| 286 | } | |
| 287 | fn _Q_flt(a: f128, b: f128) callconv(.c) i32 { | |
| 288 | return @intFromBool(cmp_f128(a, b) == .lt); | |
| 289 | } | |
| 290 | fn _Q_fle(a: f128, b: f128) callconv(.c) i32 { | |
| 291 | return @intFromBool((cmp_f128(a, b) orelse .gt) != .gt); | |
| 292 | } | |
| 293 | fn _Q_fgt(a: f128, b: f128) callconv(.c) i32 { | |
| 294 | return @intFromBool(cmp_f128(a, b) == .gt); | |
| 295 | } | |
| 296 | fn _Q_fge(a: f128, b: f128) callconv(.c) i32 { | |
| 297 | return @intFromBool((cmp_f128(a, b) orelse .lt) != .lt); | |
| 298 | } | |
| 299 | pub fn cmp_f128(a: f128, b: f128) ?Order { | |
| 300 | return cmpf2(f128, a, b); | |
| 301 | } | |
| 302 | pub fn unord_f128(a: f128, b: f128) bool { | |
| 303 | return unord(f128, a, b); | |
| 304 | } | |
| 159 | 305 | |
| 160 | pub inline fn cmpf2(comptime T: type, comptime RT: type, a: T, b: T) RT { | |
| 306 | inline fn cmpf2(comptime T: type, a: T, b: T) ?Order { | |
| 161 | 307 | const bits = @typeInfo(T).float.bits; |
| 162 | 308 | const srep_t = @Int(.signed, bits); |
| 163 | 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 | 321 | const bAbs = @as(rep_t, @bitCast(bInt)) & absMask; |
| 176 | 322 | |
| 177 | 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; | |
| 179 | 325 | |
| 180 | 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; | |
| 182 | 328 | |
| 183 | 329 | // If at least one of a and b is positive, we get the same result comparing |
| 184 | 330 | // a and b as signed integers as we would with a floating-point compare. |
| 185 | 331 | if ((aInt & bInt) >= 0) { |
| 186 | 332 | if (aInt < bInt) { |
| 187 | return .Less; | |
| 333 | return .lt; | |
| 188 | 334 | } else if (aInt == bInt) { |
| 189 | return .Equal; | |
| 190 | } else return .Greater; | |
| 335 | return .eq; | |
| 336 | } else return .gt; | |
| 191 | 337 | } else { |
| 192 | 338 | // Otherwise, both are negative, so we need to flip the sense of the |
| 193 | 339 | // comparison to get the correct result. (This assumes a twos- or ones- |
| 194 | 340 | // complement integer representation; if integers are represented in a |
| 195 | 341 | // sign-magnitude representation, then this flip is incorrect). |
| 196 | 342 | if (aInt > bInt) { |
| 197 | return .Less; | |
| 343 | return .lt; | |
| 198 | 344 | } else if (aInt == bInt) { |
| 199 | return .Equal; | |
| 200 | } else return .Greater; | |
| 345 | return .eq; | |
| 346 | } else return .gt; | |
| 201 | 347 | } |
| 202 | 348 | } |
| 203 | 349 | |
| 204 | pub inline fn cmp_f80(comptime RT: type, a: f80, b: f80) RT { | |
| 205 | const a_rep = std.math.F80.fromFloat(a); | |
| 206 | const b_rep = std.math.F80.fromFloat(b); | |
| 207 | const sig_bits = std.math.floatMantissaBits(f80); | |
| 208 | const int_bit = 0x8000000000000000; | |
| 209 | const sign_bit = 0x8000; | |
| 210 | const special_exp = 0x7FFF; | |
| 211 | ||
| 212 | // If either a or b is NaN, they are unordered. | |
| 213 | if ((a_rep.exp & special_exp == special_exp and a_rep.fraction ^ int_bit != 0) or | |
| 214 | (b_rep.exp & special_exp == special_exp and b_rep.fraction ^ int_bit != 0)) | |
| 215 | return RT.Unordered; | |
| 216 | ||
| 217 | // If a and b are both zeros, they are equal. | |
| 218 | if ((a_rep.fraction | b_rep.fraction) | ((a_rep.exp | b_rep.exp) & special_exp) == 0) | |
| 219 | return .Equal; | |
| 220 | ||
| 221 | if (@intFromBool(a_rep.exp == b_rep.exp) & @intFromBool(a_rep.fraction == b_rep.fraction) != 0) { | |
| 222 | return .Equal; | |
| 223 | } else if (a_rep.exp & sign_bit != b_rep.exp & sign_bit) { | |
| 224 | // signs are different | |
| 225 | if (@as(i16, @bitCast(a_rep.exp)) < @as(i16, @bitCast(b_rep.exp))) { | |
| 226 | return .Less; | |
| 227 | } else { | |
| 228 | return .Greater; | |
| 229 | } | |
| 230 | } else { | |
| 231 | const a_fraction = a_rep.fraction | (@as(u80, a_rep.exp) << sig_bits); | |
| 232 | const b_fraction = b_rep.fraction | (@as(u80, b_rep.exp) << sig_bits); | |
| 233 | if ((a_fraction < b_fraction) == (a_rep.exp & sign_bit == 0)) { | |
| 234 | return .Less; | |
| 235 | } else { | |
| 236 | return .Greater; | |
| 237 | } | |
| 238 | } | |
| 239 | } | |
| 240 | ||
| 241 | test "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 | } | |
| 350 | test cmp_f80 { | |
| 351 | try std.testing.expect(cmp_f80(1.0, 1.0) == .eq); | |
| 352 | try std.testing.expect(cmp_f80(0.0, -0.0) == .eq); | |
| 353 | try std.testing.expect(cmp_f80(2.0, 4.0) == .lt); | |
| 354 | try std.testing.expect(cmp_f80(2.0, -4.0) == .gt); | |
| 355 | try std.testing.expect(cmp_f80(-2.0, -4.0) == .gt); | |
| 356 | try std.testing.expect(cmp_f80(-2.0, 4.0) == .lt); | |
| 250 | 357 | } |
| 251 | 358 | |
| 252 | pub inline fn unordcmp(comptime T: type, a: T, b: T) i32 { | |
| 359 | inline fn unord(comptime T: type, a: T, b: T) bool { | |
| 253 | 360 | const rep_t = @Int(.unsigned, @typeInfo(T).float.bits); |
| 254 | 361 | |
| 255 | 362 | const significandBits = std.math.floatMantissaBits(T); |
| ... | ... | @@ -261,7 +368,7 @@ pub inline fn unordcmp(comptime T: type, a: T, b: T) i32 { |
| 261 | 368 | const aAbs: rep_t = @as(rep_t, @bitCast(a)) & absMask; |
| 262 | 369 | const bAbs: rep_t = @as(rep_t, @bitCast(b)) & absMask; |
| 263 | 370 | |
| 264 | return @intFromBool(aAbs > infRep or bAbs > infRep); | |
| 371 | return aAbs > infRep or bAbs > infRep; | |
| 265 | 372 | } |
| 266 | 373 | |
| 267 | 374 | test { |
lib/compiler_rt/comparesf2_test.zig+17-73| ... | ... | @@ -5,52 +5,12 @@ |
| 5 | 5 | const std = @import("std"); |
| 6 | 6 | const builtin = @import("builtin"); |
| 7 | 7 | |
| 8 | const __eqsf2 = @import("./comparef.zig").__eqsf2; | |
| 9 | const __lesf2 = @import("./comparef.zig").__lesf2; | |
| 10 | const __ltsf2 = @import("./comparef.zig").__ltsf2; | |
| 11 | const __nesf2 = @import("./comparef.zig").__nesf2; | |
| 8 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 12 | 9 | |
| 13 | const __gesf2 = @import("./gesf2.zig").__gesf2; | |
| 14 | const __gtsf2 = @import("./gesf2.zig").__gtsf2; | |
| 15 | ||
| 16 | const __unordsf2 = @import("./comparef.zig").__unordsf2; | |
| 17 | ||
| 18 | const 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 | ||
| 30 | fn 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 | } | |
| 10 | const impl = @import("comparef.zig"); | |
| 11 | const Order = impl.Order; | |
| 12 | const cmp_f32 = impl.cmp_f32; | |
| 13 | const unord_f32 = impl.unord_f32; | |
| 54 | 14 | |
| 55 | 15 | const arguments = [_]f32{ |
| 56 | 16 | std.math.nan(f32), |
| ... | ... | @@ -73,36 +33,20 @@ const arguments = [_]f32{ |
| 73 | 33 | std.math.inf(f32), |
| 74 | 34 | }; |
| 75 | 35 | |
| 76 | fn generateVector(comptime a: f32, comptime b: f32) TestVector { | |
| 77 | const leResult = if (a < b) -1 else if (a == b) 0 else 1; | |
| 78 | const geResult = if (a > b) 1 else if (a == b) 0 else -1; | |
| 79 | const unResult = if (a != a or b != b) 1 else 0; | |
| 80 | return TestVector{ | |
| 81 | .a = a, | |
| 82 | .b = b, | |
| 83 | .eqReference = leResult, | |
| 84 | .geReference = geResult, | |
| 85 | .gtReference = geResult, | |
| 86 | .leReference = leResult, | |
| 87 | .ltReference = leResult, | |
| 88 | .neReference = leResult, | |
| 89 | .unReference = unResult, | |
| 90 | }; | |
| 91 | } | |
| 92 | ||
| 93 | const test_vectors = init: { | |
| 94 | @setEvalBranchQuota(10000); | |
| 95 | var vectors: [arguments.len * arguments.len]TestVector = undefined; | |
| 36 | test "compare f32" { | |
| 96 | 37 | for (arguments[0..], 0..) |arg_i, i| { |
| 97 | 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 | ||
| 104 | test "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 | 13 | const expectApproxEqAbs = std.testing.expectApproxEqAbs; |
| 14 | 14 | |
| 15 | 15 | const compiler_rt = @import("../compiler_rt.zig"); |
| 16 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 16 | const symbol = compiler_rt.symbol; | |
| 17 | 17 | const trig = @import("trig.zig"); |
| 18 | 18 | const rem_pio2 = @import("rem_pio2.zig").rem_pio2; |
| 19 | 19 | const rem_pio2f = @import("rem_pio2f.zig").rem_pio2f; |
| 20 | 20 | const rem_pio2l = @import("rem_pio2l.zig").rem_pio2l; |
| 21 | 21 | |
| 22 | 22 | comptime { |
| 23 | symbol(&cosh, "__cosh"); | |
| 24 | symbol(&cosl, "__cosl"); | |
| 23 | symbol(&__cosh, "__cosh"); | |
| 25 | 24 | symbol(&cosf, "cosf"); |
| 26 | 25 | symbol(&cos, "cos"); |
| 27 | symbol(&cosx, "__cosx"); | |
| 28 | if (compiler_rt.want_ppc_abi) { | |
| 29 | symbol(&cosq, "cosf128"); | |
| 30 | } | |
| 31 | symbol(&cosq, "cosq"); | |
| 26 | symbol(&__cosx, "__cosx"); | |
| 27 | symbol(&cosq, "cosf128"); | |
| 32 | 28 | symbol(&cosl, "cosl"); |
| 29 | symbol(&cosl, "__cosl"); // required by musl | |
| 33 | 30 | } |
| 34 | 31 | |
| 35 | pub fn cosh(a: f16) callconv(.c) f16 { | |
| 32 | fn __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 | } | |
| 35 | pub fn cos_f16(x: f16) f16 { | |
| 36 | 36 | // TODO: more efficient implementation |
| 37 | return @floatCast(cosf(a)); | |
| 37 | return @floatCast(cos_f32(x)); | |
| 38 | 38 | } |
| 39 | 39 | |
| 40 | pub fn cosf(x: f32) callconv(.c) f32 { | |
| 40 | fn 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 | } | |
| 43 | pub fn cos_f32(x: f32) f32 { | |
| 41 | 44 | // Small multiples of pi/2 rounded to double precision. |
| 42 | 45 | const c1pio2: f64 = 1.0 * math.pi / 2.0; // 0x3FF921FB, 0x54442D18 |
| 43 | 46 | const c2pio2: f64 = 2.0 * math.pi / 2.0; // 0x400921FB, 0x54442D18 |
| ... | ... | @@ -94,7 +97,10 @@ pub fn cosf(x: f32) callconv(.c) f32 { |
| 94 | 97 | }; |
| 95 | 98 | } |
| 96 | 99 | |
| 97 | pub fn cos(x: f64) callconv(.c) f64 { | |
| 100 | fn 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 | } | |
| 103 | pub fn cos_f64(x: f64) f64 { | |
| 98 | 104 | var ix = @as(u64, @bitCast(x)) >> 32; |
| 99 | 105 | ix &= 0x7fffffff; |
| 100 | 106 | |
| ... | ... | @@ -123,7 +129,10 @@ pub fn cos(x: f64) callconv(.c) f64 { |
| 123 | 129 | }; |
| 124 | 130 | } |
| 125 | 131 | |
| 126 | pub fn cosx(x: f80) callconv(.c) f80 { | |
| 132 | fn __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 | } | |
| 135 | pub fn cos_f80(x: f80) f80 { | |
| 127 | 136 | const se = ld.signExponent(x) & 0x7fff; |
| 128 | 137 | if (se == 0x7fff) { |
| 129 | 138 | return x - x; |
| ... | ... | @@ -147,7 +156,10 @@ pub fn cosx(x: f80) callconv(.c) f80 { |
| 147 | 156 | }; |
| 148 | 157 | } |
| 149 | 158 | |
| 150 | pub fn cosq(x: f128) callconv(.c) f128 { | |
| 159 | fn 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 | } | |
| 162 | pub fn cos_f128(x: f128) f128 { | |
| 151 | 163 | const se = ld.signExponent(x) & 0x7fff; |
| 152 | 164 | if (se == 0x7fff) { |
| 153 | 165 | return x - x; |
| ... | ... | @@ -173,20 +185,21 @@ pub fn cosq(x: f128) callconv(.c) f128 { |
| 173 | 185 | |
| 174 | 186 | pub fn cosl(x: c_longdouble) callconv(.c) c_longdouble { |
| 175 | 187 | switch (@typeInfo(c_longdouble).float.bits) { |
| 176 | 64 => return cos(x), | |
| 177 | 80 => return cosx(x), | |
| 178 | 128 => return cosq(x), | |
| 179 | else => @compileError("unreachable"), | |
| 188 | 64 => return cos_f64(x), | |
| 189 | 80 => return cos_f80(x), | |
| 190 | 128 => return cos_f128(x), | |
| 191 | else => comptime unreachable, | |
| 180 | 192 | } |
| 181 | 193 | } |
| 182 | 194 | |
| 183 | 195 | fn testCosSpecial(comptime T: type) !void { |
| 184 | 196 | const f = switch (T) { |
| 185 | f32 => cosf, | |
| 186 | f64 => cos, | |
| 187 | f80 => cosx, | |
| 188 | f128 => cosq, | |
| 189 | else => @compileError("unimplemented"), | |
| 197 | f16 => cos_f16, | |
| 198 | f32 => cos_f32, | |
| 199 | f64 => cos_f64, | |
| 200 | f80 => cos_f80, | |
| 201 | f128 => cos_f128, | |
| 202 | else => comptime unreachable, | |
| 190 | 203 | }; |
| 191 | 204 | |
| 192 | 205 | try expect(f(0.0) == 1.0); |
| ... | ... | @@ -198,13 +211,13 @@ fn testCosSpecial(comptime T: type) !void { |
| 198 | 211 | |
| 199 | 212 | test "cos32.normal" { |
| 200 | 213 | const epsilon = math.floatEps(f32); |
| 201 | try expectApproxEqAbs(@as(f32, 1.0), cosf(0.0), epsilon); | |
| 202 | try expectApproxEqAbs(@as(f32, 0.9800666), cosf(0.2), epsilon); | |
| 203 | try expectApproxEqAbs(@as(f32, 0.6276231), cosf(0.8923), epsilon); | |
| 204 | try expectApproxEqAbs(@as(f32, 0.0707372), cosf(1.5), epsilon); | |
| 205 | try expectApproxEqAbs(@as(f32, 0.0707372), cosf(-1.5), epsilon); | |
| 206 | try expectApproxEqAbs(@as(f32, 0.96913195), cosf(37.45), epsilon); | |
| 207 | try expectApproxEqAbs(@as(f32, 0.40079966), cosf(89.123), epsilon); | |
| 214 | try expectApproxEqAbs(@as(f32, 1.0), cos_f32(0.0), epsilon); | |
| 215 | try expectApproxEqAbs(@as(f32, 0.9800666), cos_f32(0.2), epsilon); | |
| 216 | try expectApproxEqAbs(@as(f32, 0.6276231), cos_f32(0.8923), epsilon); | |
| 217 | try expectApproxEqAbs(@as(f32, 0.0707372), cos_f32(1.5), epsilon); | |
| 218 | try expectApproxEqAbs(@as(f32, 0.0707372), cos_f32(-1.5), epsilon); | |
| 219 | try expectApproxEqAbs(@as(f32, 0.96913195), cos_f32(37.45), epsilon); | |
| 220 | try expectApproxEqAbs(@as(f32, 0.40079966), cos_f32(89.123), epsilon); | |
| 208 | 221 | } |
| 209 | 222 | |
| 210 | 223 | test "cos32.special" { |
| ... | ... | @@ -213,13 +226,13 @@ test "cos32.special" { |
| 213 | 226 | |
| 214 | 227 | test "cos64.normal" { |
| 215 | 228 | const epsilon = math.floatEps(f64); |
| 216 | try expectApproxEqAbs(@as(f64, 1.0), cos(0.0), epsilon); | |
| 217 | try expectApproxEqAbs(@as(f64, 0.9800665778412416), cos(0.2), epsilon); | |
| 218 | try expectApproxEqAbs(@as(f64, 0.6276230983360804), cos(0.8923), epsilon); | |
| 219 | try expectApproxEqAbs(@as(f64, 0.0707372016677029), cos(1.5), epsilon); | |
| 220 | try expectApproxEqAbs(@as(f64, 0.0707372016677029), cos(-1.5), epsilon); | |
| 221 | try expectApproxEqAbs(@as(f64, 0.9691317730707778), cos(37.45), epsilon); | |
| 222 | try expectApproxEqAbs(@as(f64, 0.4008006809354791), cos(89.123), epsilon); | |
| 229 | try expectApproxEqAbs(@as(f64, 1.0), cos_f64(0.0), epsilon); | |
| 230 | try expectApproxEqAbs(@as(f64, 0.9800665778412416), cos_f64(0.2), epsilon); | |
| 231 | try expectApproxEqAbs(@as(f64, 0.6276230983360804), cos_f64(0.8923), epsilon); | |
| 232 | try expectApproxEqAbs(@as(f64, 0.0707372016677029), cos_f64(1.5), epsilon); | |
| 233 | try expectApproxEqAbs(@as(f64, 0.0707372016677029), cos_f64(-1.5), epsilon); | |
| 234 | try expectApproxEqAbs(@as(f64, 0.9691317730707778), cos_f64(37.45), epsilon); | |
| 235 | try expectApproxEqAbs(@as(f64, 0.4008006809354791), cos_f64(89.123), epsilon); | |
| 223 | 236 | } |
| 224 | 237 | |
| 225 | 238 | test "cos64.special" { |
| ... | ... | @@ -228,13 +241,13 @@ test "cos64.special" { |
| 228 | 241 | |
| 229 | 242 | test "cos80.normal" { |
| 230 | 243 | const epsilon = math.floatEps(f80); |
| 231 | try expectApproxEqAbs(@as(f80, 1.0), cosx(0.0), epsilon); | |
| 232 | try expectApproxEqAbs(@as(f80, 0.98006657784124163112419651674816888), cosx(0.2), epsilon); | |
| 233 | try expectApproxEqAbs(@as(f80, 0.62762309833608037003563995939286067), cosx(0.8923), epsilon); | |
| 234 | try expectApproxEqAbs(@as(f80, 0.070737201667702910088189851434268747), cosx(1.5), epsilon); | |
| 235 | try expectApproxEqAbs(@as(f80, 0.070737201667702910088189851434268747), cosx(-1.5), epsilon); | |
| 236 | try expectApproxEqAbs(@as(f80, 0.9691317730707771246), cosx(37.45), epsilon); | |
| 237 | try expectApproxEqAbs(@as(f80, 0.4008006809354834001), cosx(89.123), epsilon); | |
| 244 | try expectApproxEqAbs(@as(f80, 1.0), cos_f80(0.0), epsilon); | |
| 245 | try expectApproxEqAbs(@as(f80, 0.98006657784124163112419651674816888), cos_f80(0.2), epsilon); | |
| 246 | try expectApproxEqAbs(@as(f80, 0.62762309833608037003563995939286067), cos_f80(0.8923), epsilon); | |
| 247 | try expectApproxEqAbs(@as(f80, 0.070737201667702910088189851434268747), cos_f80(1.5), epsilon); | |
| 248 | try expectApproxEqAbs(@as(f80, 0.070737201667702910088189851434268747), cos_f80(-1.5), epsilon); | |
| 249 | try expectApproxEqAbs(@as(f80, 0.9691317730707771246), cos_f80(37.45), epsilon); | |
| 250 | try expectApproxEqAbs(@as(f80, 0.4008006809354834001), cos_f80(89.123), epsilon); | |
| 238 | 251 | } |
| 239 | 252 | |
| 240 | 253 | test "cos80.special" { |
| ... | ... | @@ -243,13 +256,13 @@ test "cos80.special" { |
| 243 | 256 | |
| 244 | 257 | test "cos128.normal" { |
| 245 | 258 | const epsilon = math.floatEps(f128); |
| 246 | try expectApproxEqAbs(@as(f128, 1.0), cosq(0.0), epsilon); | |
| 247 | try expectApproxEqAbs(@as(f128, 0.98006657784124163112419651674816888), cosq(0.2), epsilon); | |
| 248 | try expectApproxEqAbs(@as(f128, 0.62762309833608037003563995939286067), cosq(0.8923), epsilon); | |
| 249 | try expectApproxEqAbs(@as(f128, 0.070737201667702910088189851434268747), cosq(1.5), epsilon); | |
| 250 | try expectApproxEqAbs(@as(f128, 0.070737201667702910088189851434268747), cosq(-1.5), epsilon); | |
| 251 | try expectApproxEqAbs(@as(f128, 0.96913177307077712443149563847233230), cosq(37.45), epsilon); | |
| 252 | try expectApproxEqAbs(@as(f128, 0.40080068093548339848199454493704702), cosq(89.123), epsilon); | |
| 259 | try expectApproxEqAbs(@as(f128, 1.0), cos_f128(0.0), epsilon); | |
| 260 | try expectApproxEqAbs(@as(f128, 0.98006657784124163112419651674816888), cos_f128(0.2), epsilon); | |
| 261 | try expectApproxEqAbs(@as(f128, 0.62762309833608037003563995939286067), cos_f128(0.8923), epsilon); | |
| 262 | try expectApproxEqAbs(@as(f128, 0.070737201667702910088189851434268747), cos_f128(1.5), epsilon); | |
| 263 | try expectApproxEqAbs(@as(f128, 0.070737201667702910088189851434268747), cos_f128(-1.5), epsilon); | |
| 264 | try expectApproxEqAbs(@as(f128, 0.96913177307077712443149563847233230), cos_f128(37.45), epsilon); | |
| 265 | try expectApproxEqAbs(@as(f128, 0.40080068093548339848199454493704702), cos_f128(89.123), epsilon); | |
| 253 | 266 | } |
| 254 | 267 | |
| 255 | 268 | test "cos128.special" { |
lib/compiler_rt/count0bits.zig+2-1| ... | ... | @@ -1,6 +1,7 @@ |
| 1 | 1 | const builtin = @import("builtin"); |
| 2 | 2 | const std = @import("std"); |
| 3 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 3 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 4 | const symbol = compiler_rt.symbol; | |
| 4 | 5 | |
| 5 | 6 | comptime { |
| 6 | 7 | symbol(&__clzsi2, "__clzsi2"); |
lib/compiler_rt/divc3.zig+78-5| ... | ... | @@ -7,12 +7,81 @@ const maxInt = std.math.maxInt; |
| 7 | 7 | const minInt = std.math.minInt; |
| 8 | 8 | const isFinite = std.math.isFinite; |
| 9 | 9 | const copysign = std.math.copysign; |
| 10 | const Complex = @import("mulc3.zig").Complex; | |
| 10 | ||
| 11 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 12 | const symbol = compiler_rt.symbol; | |
| 13 | const Complex = compiler_rt.Complex; | |
| 14 | ||
| 15 | comptime { | |
| 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 | ||
| 29 | fn __divhc3(lhs_real: compiler_rt.f16.Abi, lhs_imag: compiler_rt.f16.Abi, rhs_real: compiler_rt.f16.Abi, rhs_imag: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.complex.Abi { | |
| 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 | } | |
| 35 | pub fn div_cf16(a: Complex(f16), b: Complex(f16)) Complex(f16) { | |
| 36 | return divc3(f16, a, b); | |
| 37 | } | |
| 38 | ||
| 39 | fn __divsc3(lhs_real: compiler_rt.f32.Abi, lhs_imag: compiler_rt.f32.Abi, rhs_real: compiler_rt.f32.Abi, rhs_imag: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.complex.Abi { | |
| 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 | } | |
| 45 | pub fn div_cf32(a: Complex(f32), b: Complex(f32)) Complex(f32) { | |
| 46 | return divc3(f32, a, b); | |
| 47 | } | |
| 48 | ||
| 49 | fn __divdc3(lhs_real: compiler_rt.f64.Abi, lhs_imag: compiler_rt.f64.Abi, rhs_real: compiler_rt.f64.Abi, rhs_imag: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.complex.Abi { | |
| 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 | } | |
| 55 | pub fn div_cf64(a: Complex(f64), b: Complex(f64)) Complex(f64) { | |
| 56 | return divc3(f64, a, b); | |
| 57 | } | |
| 58 | ||
| 59 | fn __divxc3(lhs_real: compiler_rt.f80.Abi, lhs_imag: compiler_rt.f80.Abi, rhs_real: compiler_rt.f80.Abi, rhs_imag: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.complex.Abi { | |
| 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 | } | |
| 65 | pub fn div_cf80(a: Complex(f80), b: Complex(f80)) Complex(f80) { | |
| 66 | return divc3(f80, a, b); | |
| 67 | } | |
| 68 | ||
| 69 | fn __divtc3(lhs_real: compiler_rt.f128.Abi, lhs_imag: compiler_rt.f128.Abi, rhs_real: compiler_rt.f128.Abi, rhs_imag: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.complex.Abi { | |
| 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 | } | |
| 75 | pub fn div_cf128(a: Complex(f128), b: Complex(f128)) Complex(f128) { | |
| 76 | return divc3(f128, a, b); | |
| 77 | } | |
| 11 | 78 | |
| 12 | 79 | /// Implementation based on Annex G of C17 Standard (N2176) |
| 13 | pub inline fn divc3(comptime T: type, a: T, b: T, c_in: T, d_in: T) Complex(T) { | |
| 14 | var c = c_in; | |
| 15 | var d = d_in; | |
| 80 | inline fn divc3(comptime T: type, lhs: Complex(T), rhs: Complex(T)) Complex(T) { | |
| 81 | const a = lhs.real; | |
| 82 | const b = lhs.imag; | |
| 83 | var c = rhs.real; | |
| 84 | var d = rhs.imag; | |
| 16 | 85 | |
| 17 | 86 | // logbw used to prevent under/over-flow |
| 18 | 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 | 92 | break :b logbw; |
| 24 | 93 | } else 0; |
| 25 | 94 | const denom = c * c + d * d; |
| 26 | const result = Complex(T){ | |
| 95 | const result: Complex(T) = .{ | |
| 27 | 96 | .real = scalbn((a * c + b * d) / denom, -ilogbw), |
| 28 | 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 | 127 | |
| 59 | 128 | return result; |
| 60 | 129 | } |
| 130 | ||
| 131 | test { | |
| 132 | _ = @import("divc3_test.zig"); | |
| 133 | } |
lib/compiler_rt/divc3_test.zig+28-51| ... | ... | @@ -2,76 +2,53 @@ const std = @import("std"); |
| 2 | 2 | const math = std.math; |
| 3 | 3 | const expect = std.testing.expect; |
| 4 | 4 | |
| 5 | const Complex = @import("./mulc3.zig").Complex; | |
| 6 | const __divhc3 = @import("./divhc3.zig").__divhc3; | |
| 7 | const __divsc3 = @import("./divsc3.zig").__divsc3; | |
| 8 | const __divdc3 = @import("./divdc3.zig").__divdc3; | |
| 9 | const __divxc3 = @import("./divxc3.zig").__divxc3; | |
| 10 | const __divtc3 = @import("./divtc3.zig").__divtc3; | |
| 5 | const Complex = @import("../compiler_rt.zig").Complex; | |
| 6 | ||
| 7 | const impl = @import("divc3.zig"); | |
| 8 | const div_cf16 = impl.div_cf16; | |
| 9 | const div_cf32 = impl.div_cf32; | |
| 10 | const div_cf64 = impl.div_cf64; | |
| 11 | const div_cf80 = impl.div_cf80; | |
| 12 | const div_cf128 = impl.div_cf128; | |
| 11 | 13 | |
| 12 | 14 | test "divc3" { |
| 13 | try testDiv(f16, __divhc3); | |
| 14 | try testDiv(f32, __divsc3); | |
| 15 | try testDiv(f64, __divdc3); | |
| 16 | try testDiv(f80, __divxc3); | |
| 17 | try testDiv(f128, __divtc3); | |
| 15 | try testDiv(f16, div_cf16); | |
| 16 | try testDiv(f32, div_cf32); | |
| 17 | try testDiv(f64, div_cf64); | |
| 18 | try testDiv(f80, div_cf80); | |
| 19 | try testDiv(f128, div_cf128); | |
| 18 | 20 | } |
| 19 | 21 | |
| 20 | fn testDiv(comptime T: type, comptime f: fn (T, T, T, T) callconv(.c) Complex(T)) !void { | |
| 22 | fn testDiv(comptime T: type, comptime f: fn (Complex(T), Complex(T)) Complex(T)) !void { | |
| 21 | 23 | { |
| 22 | const a: T = 1.0; | |
| 23 | const b: T = 0.0; | |
| 24 | const c: T = -1.0; | |
| 25 | const d: T = 0.0; | |
| 26 | ||
| 27 | const result = f(a, b, c, d); | |
| 24 | const result = f(.{ .real = 1.0, .imag = 0.0 }, .{ .real = -1.0, .imag = 0.0 }); | |
| 28 | 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; | |
| 33 | const b: T = 0.0; | |
| 34 | const c: T = -4.0; | |
| 35 | const d: T = 0.0; | |
| 36 | ||
| 37 | const result = f(a, b, c, d); | |
| 29 | const result = f(.{ .real = 1.0, .imag = 0.0 }, .{ .real = -4.0, .imag = 0.0 }); | |
| 38 | 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 | 34 | // if the first operand is an infinity and the second operand is a finite number, then the |
| 43 | // result of the / operator is an infinity; | |
| 44 | const a: T = -math.inf(T); | |
| 45 | const b: T = 0.0; | |
| 46 | const c: T = -4.0; | |
| 47 | const d: T = 1.0; | |
| 48 | ||
| 49 | const result = f(a, b, c, d); | |
| 50 | try expect(result.real == math.inf(T)); | |
| 51 | try expect(result.imag == math.inf(T)); | |
| 35 | // resultult of the / operator is an infinity; | |
| 36 | const result = f(.{ .real = -math.inf(T), .imag = 0.0 }, .{ .real = -4.0, .imag = 1.0 }); | |
| 37 | try expect(math.isPositiveInf(result.real)); | |
| 38 | try expect(math.isPositiveInf(result.imag)); | |
| 52 | 39 | } |
| 53 | 40 | { |
| 54 | 41 | // if the first operand is a finite number and the second operand is an infinity, then the |
| 55 | 42 | // result of the / operator is a zero; |
| 56 | const a: T = 17.2; | |
| 57 | const b: T = 0.0; | |
| 58 | const c: T = -math.inf(T); | |
| 59 | const d: T = 0.0; | |
| 60 | ||
| 61 | const result = f(a, b, c, d); | |
| 62 | try expect(result.real == -0.0); | |
| 63 | try expect(result.imag == 0.0); | |
| 43 | const result = f(.{ .real = 17.2, .imag = 0.0 }, .{ .real = -math.inf(T), .imag = 0.0 }); | |
| 44 | try expect(math.isNegativeZero(result.real)); | |
| 45 | try expect(math.isNegativeZero(result.imag)); | |
| 64 | 46 | } |
| 65 | 47 | { |
| 66 | 48 | // if the first operand is a nonzero finite number or an infinity and the second operand is |
| 67 | 49 | // a zero, then the result of the / operator is an infinity |
| 68 | const a: T = 1.1; | |
| 69 | const b: T = 0.1; | |
| 70 | const c: T = 0.0; | |
| 71 | const d: T = 0.0; | |
| 72 | ||
| 73 | const result = f(a, b, c, d); | |
| 74 | try expect(result.real == math.inf(T)); | |
| 75 | try expect(result.imag == math.inf(T)); | |
| 50 | const result = f(.{ .real = 1.1, .imag = 0.1 }, .{ .real = 0.0, .imag = 0.0 }); | |
| 51 | try expect(math.isPositiveInf(result.real)); | |
| 52 | try expect(math.isPositiveInf(result.imag)); | |
| 76 | 53 | } |
| 77 | 54 | } |
lib/compiler_rt/divdc3.zig deleted-13| ... | ... | @@ -1,13 +0,0 @@ |
| 1 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 2 | const divc3 = @import("./divc3.zig"); | |
| 3 | const Complex = @import("./mulc3.zig").Complex; | |
| 4 | ||
| 5 | comptime { | |
| 6 | if (@import("builtin").zig_backend != .stage2_c) { | |
| 7 | symbol(&__divdc3, "__divdc3"); | |
| 8 | } | |
| 9 | } | |
| 10 | ||
| 11 | pub 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 | 17 | } |
| 18 | 18 | } |
| 19 | 19 | |
| 20 | pub fn __divdf3(a: f64, b: f64) callconv(.c) f64 { | |
| 21 | return div(a, b); | |
| 20 | fn __divdf3(a: compiler_rt.f64.Abi, b: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.Abi { | |
| 21 | return compiler_rt.f64.toAbi(div_f64(compiler_rt.f64.fromAbi(a), compiler_rt.f64.fromAbi(b))); | |
| 22 | 22 | } |
| 23 | 23 | |
| 24 | 24 | fn __aeabi_ddiv(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) f64 { |
| 25 | return div(a, b); | |
| 25 | return div_f64(a, b); | |
| 26 | 26 | } |
| 27 | 27 | |
| 28 | inline fn div(a: f64, b: f64) f64 { | |
| 28 | pub fn div_f64(a: f64, b: f64) f64 { | |
| 29 | 29 | const Z = @Int(.unsigned, 64); |
| 30 | 30 | const SignedZ = @Int(.signed, 64); |
| 31 | 31 |
lib/compiler_rt/divdf3_test.zig+2-2| ... | ... | @@ -6,7 +6,7 @@ const std = @import("std"); |
| 6 | 6 | const math = std.math; |
| 7 | 7 | const testing = std.testing; |
| 8 | 8 | |
| 9 | const __divdf3 = @import("divdf3.zig").__divdf3; | |
| 9 | const div_f64 = @import("divdf3.zig").div_f64; | |
| 10 | 10 | |
| 11 | 11 | const nanRep: u64 = @as(u64, @bitCast(math.nan(f64))); |
| 12 | 12 | const infRep: u64 = @as(u64, @bitCast(math.inf(f64))); |
| ... | ... | @@ -30,7 +30,7 @@ fn compareResultD(result: f64, expected: u64) bool { |
| 30 | 30 | } |
| 31 | 31 | |
| 32 | 32 | fn test__divdf3(a: f64, b: f64, expected: u64) !void { |
| 33 | const x = __divdf3(a, b); | |
| 33 | const x = div_f64(a, b); | |
| 34 | 34 | const ret = compareResultD(x, expected); |
| 35 | 35 | try testing.expect(ret == true); |
| 36 | 36 | } |
lib/compiler_rt/divhc3.zig deleted-14| ... | ... | @@ -1,14 +0,0 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = compiler_rt.symbol; | |
| 3 | const divc3 = @import("./divc3.zig"); | |
| 4 | const Complex = @import("./mulc3.zig").Complex; | |
| 5 | ||
| 6 | comptime { | |
| 7 | if (@import("builtin").zig_backend != .stage2_c) { | |
| 8 | symbol(&__divhc3, "__divhc3"); | |
| 9 | } | |
| 10 | } | |
| 11 | ||
| 12 | pub 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 @@ |
| 1 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 2 | const divsf3 = @import("./divsf3.zig"); | |
| 3 | ||
| 4 | comptime { | |
| 5 | symbol(&__divhf3, "__divhf3"); | |
| 6 | } | |
| 7 | ||
| 8 | pub 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 | 5 | |
| 6 | 6 | const compiler_rt = @import("../compiler_rt.zig"); |
| 7 | 7 | const udivmod = @import("udivmodei4.zig").divmod; |
| 8 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 8 | const symbol = compiler_rt.symbol; | |
| 9 | 9 | |
| 10 | 10 | comptime { |
| 11 | 11 | symbol(&__divei4, "__divei4"); |
lib/compiler_rt/divsc3.zig deleted-13| ... | ... | @@ -1,13 +0,0 @@ |
| 1 | const divc3 = @import("./divc3.zig"); | |
| 2 | const Complex = @import("./mulc3.zig").Complex; | |
| 3 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 4 | ||
| 5 | comptime { | |
| 6 | if (@import("builtin").zig_backend != .stage2_c) { | |
| 7 | symbol(&__divsc3, "__divsc3"); | |
| 8 | } | |
| 9 | } | |
| 10 | ||
| 11 | pub 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 | 9 | const normalize = compiler_rt.normalize; |
| 10 | 10 | |
| 11 | 11 | comptime { |
| 12 | symbol(&__divhf3, "__divhf3"); | |
| 12 | 13 | if (compiler_rt.want_aeabi) { |
| 13 | 14 | symbol(&__aeabi_fdiv, "__aeabi_fdiv"); |
| 14 | 15 | } else { |
| ... | ... | @@ -16,15 +17,23 @@ comptime { |
| 16 | 17 | } |
| 17 | 18 | } |
| 18 | 19 | |
| 19 | pub fn __divsf3(a: f32, b: f32) callconv(.c) f32 { | |
| 20 | return div(a, b); | |
| 20 | fn __divhf3(a: compiler_rt.f16.Abi, b: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.Abi { | |
| 21 | return compiler_rt.f16.toAbi(div_f16(compiler_rt.f16.fromAbi(a), compiler_rt.f16.fromAbi(b))); | |
| 22 | } | |
| 23 | pub fn div_f16(a: f16, b: f16) f16 { | |
| 24 | // TODO: more efficient implementation | |
| 25 | return @floatCast(div_f32(a, b)); | |
| 26 | } | |
| 27 | ||
| 28 | fn __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 | } |
| 22 | 31 | |
| 23 | 32 | fn __aeabi_fdiv(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) f32 { |
| 24 | return div(a, b); | |
| 33 | return div_f32(a, b); | |
| 25 | 34 | } |
| 26 | 35 | |
| 27 | inline fn div(a: f32, b: f32) f32 { | |
| 36 | pub fn div_f32(a: f32, b: f32) f32 { | |
| 28 | 37 | const Z = @Int(.unsigned, 32); |
| 29 | 38 | |
| 30 | 39 | const significandBits = std.math.floatMantissaBits(f32); |
lib/compiler_rt/divsf3_test.zig+2-2| ... | ... | @@ -6,7 +6,7 @@ const std = @import("std"); |
| 6 | 6 | const math = std.math; |
| 7 | 7 | const testing = std.testing; |
| 8 | 8 | |
| 9 | const __divsf3 = @import("divsf3.zig").__divsf3; | |
| 9 | const div_f32 = @import("divsf3.zig").div_f32; | |
| 10 | 10 | |
| 11 | 11 | const nanRep: u32 = @as(u32, @bitCast(math.nan(f32))); |
| 12 | 12 | const infRep: u32 = @as(u32, @bitCast(math.inf(f32))); |
| ... | ... | @@ -30,7 +30,7 @@ fn compareResultF(result: f32, expected: u32) bool { |
| 30 | 30 | } |
| 31 | 31 | |
| 32 | 32 | fn test__divsf3(a: f32, b: f32, expected: u32) !void { |
| 33 | const x = __divsf3(a, b); | |
| 33 | const x = div_f32(a, b); | |
| 34 | 34 | const ret = compareResultF(x, expected); |
| 35 | 35 | try testing.expect(ret == true); |
| 36 | 36 | } |
lib/compiler_rt/divtc3.zig deleted-16| ... | ... | @@ -1,16 +0,0 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const divc3 = @import("./divc3.zig"); | |
| 3 | const Complex = @import("./mulc3.zig").Complex; | |
| 4 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 5 | ||
| 6 | comptime { | |
| 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 | ||
| 14 | pub 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 | 13 | symbol(&_Qp_div, "_Qp_div"); |
| 14 | 14 | } else if (compiler_rt.want_sparc32_abi) { |
| 15 | 15 | symbol(&__divtf3, "_Q_div"); |
| 16 | } else { | |
| 17 | symbol(&__divtf3, "__divtf3"); | |
| 16 | 18 | } |
| 17 | symbol(&__divtf3, "__divtf3"); | |
| 18 | 19 | } |
| 19 | 20 | |
| 20 | pub fn __divtf3(a: f128, b: f128) callconv(.c) f128 { | |
| 21 | return div(a, b); | |
| 21 | fn __divtf3(a: compiler_rt.f128.Abi, b: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.Abi { | |
| 22 | return compiler_rt.f128.toAbi(div_f128(compiler_rt.f128.fromAbi(a), compiler_rt.f128.fromAbi(b))); | |
| 22 | 23 | } |
| 23 | 24 | |
| 24 | 25 | fn _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 | } |
| 27 | 28 | |
| 28 | inline fn div(a: f128, b: f128) f128 { | |
| 29 | pub fn div_f128(a: f128, b: f128) f128 { | |
| 29 | 30 | const Z = @Int(.unsigned, 128); |
| 30 | 31 | |
| 31 | 32 | const significandBits = std.math.floatMantissaBits(f128); |
lib/compiler_rt/divtf3_test.zig+2-2| ... | ... | @@ -2,7 +2,7 @@ const std = @import("std"); |
| 2 | 2 | const math = std.math; |
| 3 | 3 | const testing = std.testing; |
| 4 | 4 | |
| 5 | const __divtf3 = @import("divtf3.zig").__divtf3; | |
| 5 | const div_f128 = @import("divtf3.zig").div_f128; | |
| 6 | 6 | |
| 7 | 7 | fn compareResultLD(result: f128, expectedHi: u64, expectedLo: u64) bool { |
| 8 | 8 | const rep: u128 = @bitCast(result); |
| ... | ... | @@ -24,7 +24,7 @@ fn compareResultLD(result: f128, expectedHi: u64, expectedLo: u64) bool { |
| 24 | 24 | } |
| 25 | 25 | |
| 26 | 26 | fn 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 | 28 | const ret = compareResultLD(x, expectedHi, expectedLo); |
| 29 | 29 | try testing.expect(ret == true); |
| 30 | 30 | } |
lib/compiler_rt/divxc3.zig deleted-13| ... | ... | @@ -1,13 +0,0 @@ |
| 1 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 2 | const divc3 = @import("./divc3.zig"); | |
| 3 | const Complex = @import("./mulc3.zig").Complex; | |
| 4 | ||
| 5 | comptime { | |
| 6 | if (@import("builtin").zig_backend != .stage2_c) { | |
| 7 | symbol(&__divxc3, "__divxc3"); | |
| 8 | } | |
| 9 | } | |
| 10 | ||
| 11 | pub 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 | 11 | symbol(&__divxf3, "__divxf3"); |
| 12 | 12 | } |
| 13 | 13 | |
| 14 | pub fn __divxf3(a: f80, b: f80) callconv(.c) f80 { | |
| 14 | fn __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 | } | |
| 17 | pub fn div_f80(a: f80, b: f80) f80 { | |
| 15 | 18 | const T = f80; |
| 16 | 19 | const Z = @Int(.unsigned, @bitSizeOf(T)); |
| 17 | 20 |
lib/compiler_rt/divxf3_test.zig+3-3| ... | ... | @@ -2,7 +2,7 @@ const std = @import("std"); |
| 2 | 2 | const math = std.math; |
| 3 | 3 | const testing = std.testing; |
| 4 | 4 | |
| 5 | const __divxf3 = @import("divxf3.zig").__divxf3; | |
| 5 | const div_f80 = @import("divxf3.zig").div_f80; | |
| 6 | 6 | |
| 7 | 7 | const nanRep: u80 = @as(u80, @bitCast(math.nan(f80))); |
| 8 | 8 | const infRep: u80 = @as(u80, @bitCast(math.inf(f80))); |
| ... | ... | @@ -19,14 +19,14 @@ fn compareResult(result: f80, expected: u80) bool { |
| 19 | 19 | } |
| 20 | 20 | |
| 21 | 21 | fn expect__divxf3_result(a: f80, b: f80, expected: u80) !void { |
| 22 | const x = __divxf3(a, b); | |
| 22 | const x = div_f80(a, b); | |
| 23 | 23 | const ret = compareResult(x, expected); |
| 24 | 24 | try testing.expect(ret == true); |
| 25 | 25 | } |
| 26 | 26 | |
| 27 | 27 | fn test__divxf3(a: f80, b: f80) !void { |
| 28 | 28 | const integerBit = 1 << math.floatFractionalBits(f80); |
| 29 | const x = __divxf3(a, b); | |
| 29 | const x = div_f80(a, b); | |
| 30 | 30 | |
| 31 | 31 | // Next float (assuming normal, non-zero result) |
| 32 | 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 | 14 | const expectEqual = std.testing.expectEqual; |
| 15 | 15 | |
| 16 | 16 | const compiler_rt = @import("../compiler_rt.zig"); |
| 17 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 17 | const symbol = compiler_rt.symbol; | |
| 18 | 18 | |
| 19 | 19 | comptime { |
| 20 | 20 | symbol(&__exph, "__exph"); |
| 21 | 21 | symbol(&expf, "expf"); |
| 22 | 22 | symbol(&exp, "exp"); |
| 23 | 23 | symbol(&__expx, "__expx"); |
| 24 | if (compiler_rt.want_ppc_abi) { | |
| 25 | symbol(&expq, "expf128"); | |
| 26 | } | |
| 27 | symbol(&expq, "expq"); | |
| 24 | symbol(&expq, "expf128"); | |
| 28 | 25 | symbol(&expl, "expl"); |
| 29 | 26 | } |
| 30 | 27 | |
| 31 | pub fn __exph(a: f16) callconv(.c) f16 { | |
| 28 | fn __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 | } | |
| 31 | pub fn exp_f16(x: f16) f16 { | |
| 32 | 32 | // TODO: more efficient implementation |
| 33 | return @floatCast(expf(a)); | |
| 33 | return @floatCast(exp_f32(x)); | |
| 34 | 34 | } |
| 35 | 35 | |
| 36 | pub fn expf(x_: f32) callconv(.c) f32 { | |
| 36 | fn 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 | } | |
| 39 | pub fn exp_f32(x_: f32) f32 { | |
| 37 | 40 | const half = [_]f32{ 0.5, -0.5 }; |
| 38 | 41 | const ln2hi = 6.9314575195e-1; |
| 39 | 42 | const ln2lo = 1.4286067653e-6; |
| ... | ... | @@ -108,7 +111,10 @@ pub fn expf(x_: f32) callconv(.c) f32 { |
| 108 | 111 | } |
| 109 | 112 | } |
| 110 | 113 | |
| 111 | pub fn exp(x_: f64) callconv(.c) f64 { | |
| 114 | fn 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 | } | |
| 117 | pub fn exp_f64(x_: f64) f64 { | |
| 112 | 118 | const half = [_]f64{ 0.5, -0.5 }; |
| 113 | 119 | const ln2hi: f64 = 6.93147180369123816490e-01; |
| 114 | 120 | const ln2lo: f64 = 1.90821492927058770002e-10; |
| ... | ... | @@ -189,116 +195,121 @@ pub fn exp(x_: f64) callconv(.c) f64 { |
| 189 | 195 | } |
| 190 | 196 | } |
| 191 | 197 | |
| 192 | pub fn __expx(a: f80) callconv(.c) f80 { | |
| 198 | fn __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 | } | |
| 201 | pub fn exp_f80(x: f80) f80 { | |
| 193 | 202 | // TODO: more efficient implementation |
| 194 | return @floatCast(expq(a)); | |
| 203 | return @floatCast(exp_f128(x)); | |
| 195 | 204 | } |
| 196 | 205 | |
| 197 | const expq = @import("exp_f128.zig").exp; | |
| 206 | fn 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 | } | |
| 209 | pub const exp_f128 = @import("exp_f128.zig").exp; | |
| 198 | 210 | |
| 199 | 211 | pub fn expl(x: c_longdouble) callconv(.c) c_longdouble { |
| 200 | 212 | switch (@typeInfo(c_longdouble).float.bits) { |
| 201 | 64 => return exp(x), | |
| 202 | 80 => return __expx(x), | |
| 203 | 128 => return expq(x), | |
| 204 | else => @compileError("unreachable"), | |
| 213 | 64 => return exp_f64(x), | |
| 214 | 80 => return exp_f80(x), | |
| 215 | 128 => return exp_f128(x), | |
| 216 | else => comptime unreachable, | |
| 205 | 217 | } |
| 206 | 218 | } |
| 207 | 219 | |
| 208 | 220 | test "expf() special" { |
| 209 | try expectEqual(expf(0.0), 1.0); | |
| 210 | try expectEqual(expf(-0.0), 1.0); | |
| 211 | try expectEqual(expf(1.0), math.e); | |
| 212 | try expectEqual(expf(math.ln2), 2.0); | |
| 213 | try expectEqual(expf(math.inf(f32)), math.inf(f32)); | |
| 214 | try expect(math.isPositiveZero(expf(-math.inf(f32)))); | |
| 215 | try expect(math.isNan(expf(math.nan(f32)))); | |
| 216 | try expect(math.isNan(expf(math.snan(f32)))); | |
| 221 | try expectEqual(exp_f32(0.0), 1.0); | |
| 222 | try expectEqual(exp_f32(-0.0), 1.0); | |
| 223 | try expectEqual(exp_f32(1.0), math.e); | |
| 224 | try expectEqual(exp_f32(math.ln2), 2.0); | |
| 225 | try expectEqual(exp_f32(math.inf(f32)), math.inf(f32)); | |
| 226 | try expect(math.isPositiveZero(exp_f32(-math.inf(f32)))); | |
| 227 | try expect(math.isNan(exp_f32(math.nan(f32)))); | |
| 228 | try expect(math.isNan(exp_f32(math.snan(f32)))); | |
| 217 | 229 | } |
| 218 | 230 | |
| 219 | 231 | test "expf() sanity" { |
| 220 | try expectEqual(expf(-0x1.0223a0p+3), 0x1.490320p-12); | |
| 221 | try expectEqual(expf(0x1.161868p+2), 0x1.34712ap+6); | |
| 222 | try expectEqual(expf(-0x1.0c34b4p+3), 0x1.e06b1ap-13); | |
| 223 | try expectEqual(expf(-0x1.a206f0p+2), 0x1.7dd484p-10); | |
| 224 | try expectEqual(expf(0x1.288bbcp+3), 0x1.4abc80p+13); | |
| 225 | try expectEqual(expf(0x1.52efd0p-1), 0x1.f04a9cp+0); | |
| 226 | try expectEqual(expf(-0x1.a05cc8p-2), 0x1.54f1e0p-1); | |
| 227 | try expectEqual(expf(0x1.1f9efap-1), 0x1.c0f628p+0); | |
| 228 | try expectEqual(expf(0x1.8c5db0p-1), 0x1.1599b2p+1); | |
| 229 | try expectEqual(expf(-0x1.5b86eap-1), 0x1.03b572p-1); | |
| 230 | try expectEqual(expf(-0x1.57f25cp+2), 0x1.2fbea2p-8); | |
| 231 | try expectEqual(expf(0x1.c7d310p+3), 0x1.76eefp+20); | |
| 232 | try expectEqual(expf(0x1.19be70p+4), 0x1.52d3dep+25); | |
| 233 | try expectEqual(expf(-0x1.ab6d70p+3), 0x1.a88adep-20); | |
| 234 | try expectEqual(expf(-0x1.5ac18ep+2), 0x1.22b328p-8); | |
| 235 | try expectEqual(expf(-0x1.925982p-1), 0x1.d2acc0p-2); | |
| 236 | try expectEqual(expf(0x1.7221cep+3), 0x1.9c2ceap+16); | |
| 237 | try expectEqual(expf(0x1.11a0d4p+4), 0x1.980ee6p+24); | |
| 238 | try expectEqual(expf(-0x1.ae41a2p+1), 0x1.1c28d0p-5); | |
| 239 | try expectEqual(expf(-0x1.329154p+4), 0x1.47ef94p-28); | |
| 232 | try expectEqual(exp_f32(-0x1.0223a0p+3), 0x1.490320p-12); | |
| 233 | try expectEqual(exp_f32(0x1.161868p+2), 0x1.34712ap+6); | |
| 234 | try expectEqual(exp_f32(-0x1.0c34b4p+3), 0x1.e06b1ap-13); | |
| 235 | try expectEqual(exp_f32(-0x1.a206f0p+2), 0x1.7dd484p-10); | |
| 236 | try expectEqual(exp_f32(0x1.288bbcp+3), 0x1.4abc80p+13); | |
| 237 | try expectEqual(exp_f32(0x1.52efd0p-1), 0x1.f04a9cp+0); | |
| 238 | try expectEqual(exp_f32(-0x1.a05cc8p-2), 0x1.54f1e0p-1); | |
| 239 | try expectEqual(exp_f32(0x1.1f9efap-1), 0x1.c0f628p+0); | |
| 240 | try expectEqual(exp_f32(0x1.8c5db0p-1), 0x1.1599b2p+1); | |
| 241 | try expectEqual(exp_f32(-0x1.5b86eap-1), 0x1.03b572p-1); | |
| 242 | try expectEqual(exp_f32(-0x1.57f25cp+2), 0x1.2fbea2p-8); | |
| 243 | try expectEqual(exp_f32(0x1.c7d310p+3), 0x1.76eefp+20); | |
| 244 | try expectEqual(exp_f32(0x1.19be70p+4), 0x1.52d3dep+25); | |
| 245 | try expectEqual(exp_f32(-0x1.ab6d70p+3), 0x1.a88adep-20); | |
| 246 | try expectEqual(exp_f32(-0x1.5ac18ep+2), 0x1.22b328p-8); | |
| 247 | try expectEqual(exp_f32(-0x1.925982p-1), 0x1.d2acc0p-2); | |
| 248 | try expectEqual(exp_f32(0x1.7221cep+3), 0x1.9c2ceap+16); | |
| 249 | try expectEqual(exp_f32(0x1.11a0d4p+4), 0x1.980ee6p+24); | |
| 250 | try expectEqual(exp_f32(-0x1.ae41a2p+1), 0x1.1c28d0p-5); | |
| 251 | try expectEqual(exp_f32(-0x1.329154p+4), 0x1.47ef94p-28); | |
| 240 | 252 | } |
| 241 | 253 | |
| 242 | 254 | test "expf() boundary" { |
| 243 | try expectEqual(expf(0x1.62e42ep+6), 0x1.ffff08p+127); // The last value before the result gets infinite | |
| 244 | try expectEqual(expf(0x1.62e430p+6), math.inf(f32)); // The first value that gives inf | |
| 245 | try expectEqual(expf(0x1.fffffep+127), math.inf(f32)); // Max input value | |
| 246 | try expectEqual(expf(0x1p-149), 1.0); // Min positive input value | |
| 247 | try expectEqual(expf(-0x1p-149), 1.0); // Min negative input value | |
| 248 | try expectEqual(expf(0x1p-126), 1.0); // First positive subnormal input | |
| 249 | try expectEqual(expf(-0x1p-126), 1.0); // First negative subnormal input | |
| 250 | try expectEqual(expf(-0x1.9fe368p+6), 0x1p-149); // The last value before the result flushes to zero | |
| 251 | try expectEqual(expf(-0x1.9fe36ap+6), 0.0); // The first value at which the result flushes to zero | |
| 252 | try expectEqual(expf(-0x1.5d589ep+6), 0x1.00004cp-126); // The last value before the result flushes to subnormal | |
| 253 | try expectEqual(expf(-0x1.5d58a0p+6), 0x1.ffff98p-127); // The first value for which the result flushes to subnormal | |
| 254 | ||
| 255 | try expectEqual(exp_f32(0x1.62e42ep+6), 0x1.ffff08p+127); // The last value before the result gets infinite | |
| 256 | try expectEqual(exp_f32(0x1.62e430p+6), math.inf(f32)); // The first value that gives inf | |
| 257 | try expectEqual(exp_f32(0x1.fffffep+127), math.inf(f32)); // Max input value | |
| 258 | try expectEqual(exp_f32(0x1p-149), 1.0); // Min positive input value | |
| 259 | try expectEqual(exp_f32(-0x1p-149), 1.0); // Min negative input value | |
| 260 | try expectEqual(exp_f32(0x1p-126), 1.0); // First positive subnormal input | |
| 261 | try expectEqual(exp_f32(-0x1p-126), 1.0); // First negative subnormal input | |
| 262 | try expectEqual(exp_f32(-0x1.9fe368p+6), 0x1p-149); // The last value before the result flushes to zero | |
| 263 | try expectEqual(exp_f32(-0x1.9fe36ap+6), 0.0); // The first value at which the result flushes to zero | |
| 264 | try expectEqual(exp_f32(-0x1.5d589ep+6), 0x1.00004cp-126); // The last value before the result flushes to subnormal | |
| 265 | try expectEqual(exp_f32(-0x1.5d58a0p+6), 0x1.ffff98p-127); // The first value for which the result flushes to subnormal | |
| 255 | 266 | } |
| 256 | 267 | |
| 257 | 268 | test "exp() special" { |
| 258 | try expectEqual(exp(0.0), 1.0); | |
| 259 | try expectEqual(exp(-0.0), 1.0); | |
| 269 | try expectEqual(exp_f64(0.0), 1.0); | |
| 270 | try expectEqual(exp_f64(-0.0), 1.0); | |
| 260 | 271 | // TODO: Accuracy error - off in the last bit in 64-bit, disagreeing with GCC |
| 261 | 272 | // try expectEqual(exp(1.0), math.e); |
| 262 | try expectEqual(exp(math.ln2), 2.0); | |
| 263 | try expectEqual(exp(math.inf(f64)), math.inf(f64)); | |
| 264 | try expect(math.isPositiveZero(exp(-math.inf(f64)))); | |
| 265 | try expect(math.isNan(exp(math.nan(f64)))); | |
| 266 | try expect(math.isNan(exp(math.snan(f64)))); | |
| 273 | try expectEqual(exp_f64(math.ln2), 2.0); | |
| 274 | try expectEqual(exp_f64(math.inf(f64)), math.inf(f64)); | |
| 275 | try expect(math.isPositiveZero(exp_f64(-math.inf(f64)))); | |
| 276 | try expect(math.isNan(exp_f64(math.nan(f64)))); | |
| 277 | try expect(math.isNan(exp_f64(math.snan(f64)))); | |
| 267 | 278 | } |
| 268 | 279 | |
| 269 | 280 | test "exp() sanity" { |
| 270 | try expectEqual(exp(-0x1.02239f3c6a8f1p+3), 0x1.490327ea61235p-12); | |
| 271 | try expectEqual(exp(0x1.161868e18bc67p+2), 0x1.34712ed238c04p+6); | |
| 272 | try expectEqual(exp(-0x1.0c34b3e01e6e7p+3), 0x1.e06b1b6c18e64p-13); | |
| 273 | try expectEqual(exp(-0x1.a206f0a19dcc4p+2), 0x1.7dd47f810e68cp-10); | |
| 274 | try expectEqual(exp(0x1.288bbb0d6a1e6p+3), 0x1.4abc77496e07ep+13); | |
| 275 | try expectEqual(exp(0x1.52efd0cd80497p-1), 0x1.f04a9c1080500p+0); | |
| 276 | try expectEqual(exp(-0x1.a05cc754481d1p-2), 0x1.54f1e0fd3ea0dp-1); | |
| 277 | try expectEqual(exp(0x1.1f9ef934745cbp-1), 0x1.c0f6266a6a547p+0); | |
| 278 | try expectEqual(exp(0x1.8c5db097f7442p-1), 0x1.1599b1d4a25fbp+1); | |
| 279 | try expectEqual(exp(-0x1.5b86ea8118a0ep-1), 0x1.03b5728a00229p-1); | |
| 280 | try expectEqual(exp(-0x1.57f25b2b5006dp+2), 0x1.2fbea6a01cab9p-8); | |
| 281 | try expectEqual(exp(0x1.c7d30fb825911p+3), 0x1.76eeed45a0634p+20); | |
| 282 | try expectEqual(exp(0x1.19be709de7505p+4), 0x1.52d3eb7be6844p+25); | |
| 283 | try expectEqual(exp(-0x1.ab6d6fba96889p+3), 0x1.a88ae12f985d6p-20); | |
| 284 | try expectEqual(exp(-0x1.5ac18e27084ddp+2), 0x1.22b327da9cca6p-8); | |
| 285 | try expectEqual(exp(-0x1.925981b093c41p-1), 0x1.d2acc046b55f7p-2); | |
| 286 | try expectEqual(exp(0x1.7221cd18455f5p+3), 0x1.9c2cde8699cfbp+16); | |
| 287 | try expectEqual(exp(0x1.11a0d4a51b239p+4), 0x1.980ef612ff182p+24); | |
| 288 | try expectEqual(exp(-0x1.ae41a1079de4dp+1), 0x1.1c28d16bb3222p-5); | |
| 289 | try expectEqual(exp(-0x1.329153103b871p+4), 0x1.47efa6ddd0d22p-28); | |
| 281 | try expectEqual(exp_f64(-0x1.02239f3c6a8f1p+3), 0x1.490327ea61235p-12); | |
| 282 | try expectEqual(exp_f64(0x1.161868e18bc67p+2), 0x1.34712ed238c04p+6); | |
| 283 | try expectEqual(exp_f64(-0x1.0c34b3e01e6e7p+3), 0x1.e06b1b6c18e64p-13); | |
| 284 | try expectEqual(exp_f64(-0x1.a206f0a19dcc4p+2), 0x1.7dd47f810e68cp-10); | |
| 285 | try expectEqual(exp_f64(0x1.288bbb0d6a1e6p+3), 0x1.4abc77496e07ep+13); | |
| 286 | try expectEqual(exp_f64(0x1.52efd0cd80497p-1), 0x1.f04a9c1080500p+0); | |
| 287 | try expectEqual(exp_f64(-0x1.a05cc754481d1p-2), 0x1.54f1e0fd3ea0dp-1); | |
| 288 | try expectEqual(exp_f64(0x1.1f9ef934745cbp-1), 0x1.c0f6266a6a547p+0); | |
| 289 | try expectEqual(exp_f64(0x1.8c5db097f7442p-1), 0x1.1599b1d4a25fbp+1); | |
| 290 | try expectEqual(exp_f64(-0x1.5b86ea8118a0ep-1), 0x1.03b5728a00229p-1); | |
| 291 | try expectEqual(exp_f64(-0x1.57f25b2b5006dp+2), 0x1.2fbea6a01cab9p-8); | |
| 292 | try expectEqual(exp_f64(0x1.c7d30fb825911p+3), 0x1.76eeed45a0634p+20); | |
| 293 | try expectEqual(exp_f64(0x1.19be709de7505p+4), 0x1.52d3eb7be6844p+25); | |
| 294 | try expectEqual(exp_f64(-0x1.ab6d6fba96889p+3), 0x1.a88ae12f985d6p-20); | |
| 295 | try expectEqual(exp_f64(-0x1.5ac18e27084ddp+2), 0x1.22b327da9cca6p-8); | |
| 296 | try expectEqual(exp_f64(-0x1.925981b093c41p-1), 0x1.d2acc046b55f7p-2); | |
| 297 | try expectEqual(exp_f64(0x1.7221cd18455f5p+3), 0x1.9c2cde8699cfbp+16); | |
| 298 | try expectEqual(exp_f64(0x1.11a0d4a51b239p+4), 0x1.980ef612ff182p+24); | |
| 299 | try expectEqual(exp_f64(-0x1.ae41a1079de4dp+1), 0x1.1c28d16bb3222p-5); | |
| 300 | try expectEqual(exp_f64(-0x1.329153103b871p+4), 0x1.47efa6ddd0d22p-28); | |
| 290 | 301 | } |
| 291 | 302 | |
| 292 | 303 | test "exp() boundary" { |
| 293 | try expectEqual(exp(0x1.62e42fefa39efp+9), 0x1.fffffffffff2ap+1023); // The last value before the result gets infinite | |
| 294 | try expectEqual(exp(0x1.62e42fefa39f0p+9), math.inf(f64)); // The first value that gives inf | |
| 295 | try expectEqual(exp(0x1.fffffffffffffp+1023), math.inf(f64)); // Max input value | |
| 296 | try expectEqual(exp(0x1p-1074), 1.0); // Min positive input value | |
| 297 | try expectEqual(exp(-0x1p-1074), 1.0); // Min negative input value | |
| 298 | try expectEqual(exp(0x1p-1022), 1.0); // First positive subnormal input | |
| 299 | try expectEqual(exp(-0x1p-1022), 1.0); // First negative subnormal input | |
| 300 | try expectEqual(exp(-0x1.74910d52d3051p+9), 0x1p-1074); // The last value before the result flushes to zero | |
| 301 | try expectEqual(exp(-0x1.74910d52d3052p+9), 0.0); // The first value at which the result flushes to zero | |
| 302 | try expectEqual(exp(-0x1.6232bdd7abcd2p+9), 0x1.000000000007cp-1022); // The last value before the result flushes to subnormal | |
| 303 | try expectEqual(exp(-0x1.6232bdd7abcd3p+9), 0x1.ffffffffffcf8p-1023); // The first value for which the result flushes to subnormal | |
| 304 | try expectEqual(exp_f64(0x1.62e42fefa39efp+9), 0x1.fffffffffff2ap+1023); // The last value before the result gets infinite | |
| 305 | try expectEqual(exp_f64(0x1.62e42fefa39f0p+9), math.inf(f64)); // The first value that gives inf | |
| 306 | try expectEqual(exp_f64(0x1.fffffffffffffp+1023), math.inf(f64)); // Max input value | |
| 307 | try expectEqual(exp_f64(0x1p-1074), 1.0); // Min positive input value | |
| 308 | try expectEqual(exp_f64(-0x1p-1074), 1.0); // Min negative input value | |
| 309 | try expectEqual(exp_f64(0x1p-1022), 1.0); // First positive subnormal input | |
| 310 | try expectEqual(exp_f64(-0x1p-1022), 1.0); // First negative subnormal input | |
| 311 | try expectEqual(exp_f64(-0x1.74910d52d3051p+9), 0x1p-1074); // The last value before the result flushes to zero | |
| 312 | try expectEqual(exp_f64(-0x1.74910d52d3052p+9), 0.0); // The first value at which the result flushes to zero | |
| 313 | try expectEqual(exp_f64(-0x1.6232bdd7abcd2p+9), 0x1.000000000007cp-1022); // The last value before the result flushes to subnormal | |
| 314 | try expectEqual(exp_f64(-0x1.6232bdd7abcd3p+9), 0x1.ffffffffffcf8p-1023); // The first value for which the result flushes to subnormal | |
| 304 | 315 | } |
lib/compiler_rt/exp2.zig+85-73| ... | ... | @@ -19,19 +19,22 @@ comptime { |
| 19 | 19 | symbol(&exp2f, "exp2f"); |
| 20 | 20 | symbol(&exp2, "exp2"); |
| 21 | 21 | symbol(&__exp2x, "__exp2x"); |
| 22 | if (compiler_rt.want_ppc_abi) { | |
| 23 | symbol(&exp2q, "exp2f128"); | |
| 24 | } | |
| 25 | symbol(&exp2q, "exp2q"); | |
| 22 | symbol(&exp2q, "exp2f128"); | |
| 26 | 23 | symbol(&exp2l, "exp2l"); |
| 27 | 24 | } |
| 28 | 25 | |
| 29 | pub fn __exp2h(x: f16) callconv(.c) f16 { | |
| 26 | fn __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 | } | |
| 29 | pub fn exp2_f16(x: f16) f16 { | |
| 30 | 30 | // TODO: more efficient implementation |
| 31 | return @floatCast(exp2f(x)); | |
| 31 | return @floatCast(exp2_f32(x)); | |
| 32 | 32 | } |
| 33 | 33 | |
| 34 | pub fn exp2f(x: f32) callconv(.c) f32 { | |
| 34 | fn 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 | } | |
| 37 | pub fn exp2_f32(x: f32) f32 { | |
| 35 | 38 | const tblsiz: u32 = @intCast(exp2ft.len); |
| 36 | 39 | const redux: f32 = 0x1.8p23 / @as(f32, @floatFromInt(tblsiz)); |
| 37 | 40 | const P1: f32 = 0x1.62e430p-1; |
| ... | ... | @@ -88,7 +91,10 @@ pub fn exp2f(x: f32) callconv(.c) f32 { |
| 88 | 91 | return @floatCast(r * uk); |
| 89 | 92 | } |
| 90 | 93 | |
| 91 | pub fn exp2(x: f64) callconv(.c) f64 { | |
| 94 | fn 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 | } | |
| 97 | pub fn exp2_f64(x: f64) f64 { | |
| 92 | 98 | const tblsiz: u32 = @intCast(exp2dt.len / 2); |
| 93 | 99 | const redux: f64 = 0x1.8p52 / @as(f64, @floatFromInt(tblsiz)); |
| 94 | 100 | const P1: f64 = 0x1.62e42fefa39efp-1; |
| ... | ... | @@ -156,19 +162,25 @@ pub fn exp2(x: f64) callconv(.c) f64 { |
| 156 | 162 | return math.scalbn(r, ik); |
| 157 | 163 | } |
| 158 | 164 | |
| 159 | pub fn __exp2x(x: f80) callconv(.c) f80 { | |
| 165 | fn __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 | } | |
| 168 | pub fn exp2_f80(x: f80) f80 { | |
| 160 | 169 | // TODO: more efficient implementation |
| 161 | return @floatCast(exp2q(x)); | |
| 170 | return @floatCast(exp2_f128(x)); | |
| 162 | 171 | } |
| 163 | 172 | |
| 164 | pub const exp2q = @import("exp_f128.zig").exp2; | |
| 173 | fn 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 | } | |
| 176 | pub const exp2_f128 = @import("exp_f128.zig").exp2; | |
| 165 | 177 | |
| 166 | 178 | pub fn exp2l(x: c_longdouble) callconv(.c) c_longdouble { |
| 167 | 179 | switch (@typeInfo(c_longdouble).float.bits) { |
| 168 | 64 => return exp2(x), | |
| 169 | 80 => return __exp2x(x), | |
| 170 | 128 => return exp2q(x), | |
| 171 | else => @compileError("unreachable"), | |
| 180 | 64 => return exp2_f64(x), | |
| 181 | 80 => return exp2_f80(x), | |
| 182 | 128 => return exp2_f128(x), | |
| 183 | else => comptime unreachable, | |
| 172 | 184 | } |
| 173 | 185 | } |
| 174 | 186 | |
| ... | ... | @@ -452,77 +464,77 @@ const exp2dt = [_]f64{ |
| 452 | 464 | }; |
| 453 | 465 | |
| 454 | 466 | test "exp2f() special" { |
| 455 | try expectEqual(exp2f(0.0), 1.0); | |
| 456 | try expectEqual(exp2f(-0.0), 1.0); | |
| 457 | try expectEqual(exp2f(1.0), 2.0); | |
| 458 | try expectEqual(exp2f(-1.0), 0.5); | |
| 459 | try expectEqual(exp2f(math.inf(f32)), math.inf(f32)); | |
| 460 | try expect(math.isPositiveZero(exp2f(-math.inf(f32)))); | |
| 461 | try expect(math.isNan(exp2f(math.nan(f32)))); | |
| 462 | try expect(math.isNan(exp2f(math.snan(f32)))); | |
| 467 | try expectEqual(exp2_f32(0.0), 1.0); | |
| 468 | try expectEqual(exp2_f32(-0.0), 1.0); | |
| 469 | try expectEqual(exp2_f32(1.0), 2.0); | |
| 470 | try expectEqual(exp2_f32(-1.0), 0.5); | |
| 471 | try expectEqual(exp2_f32(math.inf(f32)), math.inf(f32)); | |
| 472 | try expect(math.isPositiveZero(exp2_f32(-math.inf(f32)))); | |
| 473 | try expect(math.isNan(exp2_f32(math.nan(f32)))); | |
| 474 | try expect(math.isNan(exp2_f32(math.snan(f32)))); | |
| 463 | 475 | } |
| 464 | 476 | |
| 465 | 477 | test "exp2f() sanity" { |
| 466 | try expectEqual(exp2f(-0x1.0223a0p+3), 0x1.e8d134p-9); | |
| 467 | try expectEqual(exp2f(0x1.161868p+2), 0x1.453672p+4); | |
| 468 | try expectEqual(exp2f(-0x1.0c34b4p+3), 0x1.890ca0p-9); | |
| 469 | try expectEqual(exp2f(-0x1.a206f0p+2), 0x1.622d4ep-7); | |
| 470 | try expectEqual(exp2f(0x1.288bbcp+3), 0x1.340ecep+9); | |
| 471 | try expectEqual(exp2f(0x1.52efd0p-1), 0x1.950eeep+0); | |
| 472 | try expectEqual(exp2f(-0x1.a05cc8p-2), 0x1.824056p-1); | |
| 473 | try expectEqual(exp2f(0x1.1f9efap-1), 0x1.79dfa2p+0); | |
| 474 | try expectEqual(exp2f(0x1.8c5db0p-1), 0x1.b5ceacp+0); | |
| 475 | try expectEqual(exp2f(-0x1.5b86eap-1), 0x1.3fd8bap-1); | |
| 478 | try expectEqual(exp2_f32(-0x1.0223a0p+3), 0x1.e8d134p-9); | |
| 479 | try expectEqual(exp2_f32(0x1.161868p+2), 0x1.453672p+4); | |
| 480 | try expectEqual(exp2_f32(-0x1.0c34b4p+3), 0x1.890ca0p-9); | |
| 481 | try expectEqual(exp2_f32(-0x1.a206f0p+2), 0x1.622d4ep-7); | |
| 482 | try expectEqual(exp2_f32(0x1.288bbcp+3), 0x1.340ecep+9); | |
| 483 | try expectEqual(exp2_f32(0x1.52efd0p-1), 0x1.950eeep+0); | |
| 484 | try expectEqual(exp2_f32(-0x1.a05cc8p-2), 0x1.824056p-1); | |
| 485 | try expectEqual(exp2_f32(0x1.1f9efap-1), 0x1.79dfa2p+0); | |
| 486 | try expectEqual(exp2_f32(0x1.8c5db0p-1), 0x1.b5ceacp+0); | |
| 487 | try expectEqual(exp2_f32(-0x1.5b86eap-1), 0x1.3fd8bap-1); | |
| 476 | 488 | } |
| 477 | 489 | |
| 478 | 490 | test "exp2f() boundary" { |
| 479 | try expectEqual(exp2f(0x1.fffffep+6), 0x1.ffff4ep+127); // The last value before the result gets infinite | |
| 480 | try expectEqual(exp2f(0x1p+7), math.inf(f32)); // The first value that gives infinite result | |
| 481 | try expectEqual(exp2f(-0x1.2bccccp+7), 0x1p-149); // The last value before the result flushes to zero | |
| 482 | try expectEqual(exp2f(-0x1.2cp+7), 0); // The first value at which the result flushes to zero | |
| 483 | try expectEqual(exp2f(-0x1.f8p+6), 0x1p-126); // The last value before the result flushes to subnormal | |
| 484 | try expectEqual(exp2f(-0x1.f80002p+6), 0x1.ffff50p-127); // The first value for which the result flushes to subnormal | |
| 485 | try expectEqual(exp2f(0x1.fffffep+127), math.inf(f32)); // Max input value | |
| 486 | try expectEqual(exp2f(0x1p-149), 1); // Min positive input value | |
| 487 | try expectEqual(exp2f(-0x1p-149), 1); // Min negative input value | |
| 488 | try expectEqual(exp2f(0x1p-126), 1); // First positive subnormal input | |
| 489 | try expectEqual(exp2f(-0x1p-126), 1); // First negative subnormal input | |
| 491 | try expectEqual(exp2_f32(0x1.fffffep+6), 0x1.ffff4ep+127); // The last value before the result gets infinite | |
| 492 | try expectEqual(exp2_f32(0x1p+7), math.inf(f32)); // The first value that gives infinite result | |
| 493 | try expectEqual(exp2_f32(-0x1.2bccccp+7), 0x1p-149); // The last value before the result flushes to zero | |
| 494 | try expectEqual(exp2_f32(-0x1.2cp+7), 0); // The first value at which the result flushes to zero | |
| 495 | try expectEqual(exp2_f32(-0x1.f8p+6), 0x1p-126); // The last value before the result flushes to subnormal | |
| 496 | try expectEqual(exp2_f32(-0x1.f80002p+6), 0x1.ffff50p-127); // The first value for which the result flushes to subnormal | |
| 497 | try expectEqual(exp2_f32(0x1.fffffep+127), math.inf(f32)); // Max input value | |
| 498 | try expectEqual(exp2_f32(0x1p-149), 1); // Min positive input value | |
| 499 | try expectEqual(exp2_f32(-0x1p-149), 1); // Min negative input value | |
| 500 | try expectEqual(exp2_f32(0x1p-126), 1); // First positive subnormal input | |
| 501 | try expectEqual(exp2_f32(-0x1p-126), 1); // First negative subnormal input | |
| 490 | 502 | } |
| 491 | 503 | |
| 492 | 504 | test "exp2() special" { |
| 493 | try expectEqual(exp2(0.0), 1.0); | |
| 494 | try expectEqual(exp2(-0.0), 1.0); | |
| 495 | try expectEqual(exp2(1.0), 2.0); | |
| 496 | try expectEqual(exp2(-1.0), 0.5); | |
| 497 | try expectEqual(exp2(math.inf(f64)), math.inf(f64)); | |
| 498 | try expect(math.isPositiveZero(exp2(-math.inf(f64)))); | |
| 499 | try expect(math.isNan(exp2(math.nan(f64)))); | |
| 500 | try expect(math.isNan(exp2(math.snan(f64)))); | |
| 505 | try expectEqual(exp2_f64(0.0), 1.0); | |
| 506 | try expectEqual(exp2_f64(-0.0), 1.0); | |
| 507 | try expectEqual(exp2_f64(1.0), 2.0); | |
| 508 | try expectEqual(exp2_f64(-1.0), 0.5); | |
| 509 | try expectEqual(exp2_f64(math.inf(f64)), math.inf(f64)); | |
| 510 | try expect(math.isPositiveZero(exp2_f64(-math.inf(f64)))); | |
| 511 | try expect(math.isNan(exp2_f64(math.nan(f64)))); | |
| 512 | try expect(math.isNan(exp2_f64(math.snan(f64)))); | |
| 501 | 513 | } |
| 502 | 514 | |
| 503 | 515 | test "exp2() sanity" { |
| 504 | try expectEqual(exp2(-0x1.02239f3c6a8f1p+3), 0x1.e8d13c396f452p-9); | |
| 505 | try expectEqual(exp2(0x1.161868e18bc67p+2), 0x1.4536746bb6f12p+4); | |
| 506 | try expectEqual(exp2(-0x1.0c34b3e01e6e7p+3), 0x1.890ca0c00b9a2p-9); | |
| 507 | try expectEqual(exp2(-0x1.a206f0a19dcc4p+2), 0x1.622d4b0ebc6c1p-7); | |
| 508 | try expectEqual(exp2(0x1.288bbb0d6a1e6p+3), 0x1.340ec7f3e607ep+9); | |
| 509 | try expectEqual(exp2(0x1.52efd0cd80497p-1), 0x1.950eef4bc5451p+0); | |
| 510 | try expectEqual(exp2(-0x1.a05cc754481d1p-2), 0x1.824056efc687cp-1); | |
| 511 | try expectEqual(exp2(0x1.1f9ef934745cbp-1), 0x1.79dfa14ab121ep+0); | |
| 512 | try expectEqual(exp2(0x1.8c5db097f7442p-1), 0x1.b5cead2247372p+0); | |
| 513 | try expectEqual(exp2(-0x1.5b86ea8118a0ep-1), 0x1.3fd8ba33216b9p-1); | |
| 516 | try expectEqual(exp2_f64(-0x1.02239f3c6a8f1p+3), 0x1.e8d13c396f452p-9); | |
| 517 | try expectEqual(exp2_f64(0x1.161868e18bc67p+2), 0x1.4536746bb6f12p+4); | |
| 518 | try expectEqual(exp2_f64(-0x1.0c34b3e01e6e7p+3), 0x1.890ca0c00b9a2p-9); | |
| 519 | try expectEqual(exp2_f64(-0x1.a206f0a19dcc4p+2), 0x1.622d4b0ebc6c1p-7); | |
| 520 | try expectEqual(exp2_f64(0x1.288bbb0d6a1e6p+3), 0x1.340ec7f3e607ep+9); | |
| 521 | try expectEqual(exp2_f64(0x1.52efd0cd80497p-1), 0x1.950eef4bc5451p+0); | |
| 522 | try expectEqual(exp2_f64(-0x1.a05cc754481d1p-2), 0x1.824056efc687cp-1); | |
| 523 | try expectEqual(exp2_f64(0x1.1f9ef934745cbp-1), 0x1.79dfa14ab121ep+0); | |
| 524 | try expectEqual(exp2_f64(0x1.8c5db097f7442p-1), 0x1.b5cead2247372p+0); | |
| 525 | try expectEqual(exp2_f64(-0x1.5b86ea8118a0ep-1), 0x1.3fd8ba33216b9p-1); | |
| 514 | 526 | } |
| 515 | 527 | |
| 516 | 528 | test "exp2() boundary" { |
| 517 | try expectEqual(exp2(0x1.fffffffffffffp+9), 0x1.ffffffffffd3ap+1023); // The last value before the result gets infinite | |
| 518 | try expectEqual(exp2(0x1p+10), math.inf(f64)); // The first value that gives infinite result | |
| 519 | try expectEqual(exp2(-0x1.0cbffffffffffp+10), 0x1p-1074); // The last value before the result flushes to zero | |
| 520 | try expectEqual(exp2(-0x1.0ccp+10), 0); // The first value at which the result flushes to zero | |
| 521 | try expectEqual(exp2(-0x1.ffp+9), 0x1p-1022); // The last value before the result flushes to subnormal | |
| 522 | try expectEqual(exp2(-0x1.ff00000000001p+9), 0x1.ffffffffffd3ap-1023); // The first value for which the result flushes to subnormal | |
| 523 | try expectEqual(exp2(0x1.fffffffffffffp+1023), math.inf(f64)); // Max input value | |
| 524 | try expectEqual(exp2(0x1p-1074), 1); // Min positive input value | |
| 525 | try expectEqual(exp2(-0x1p-1074), 1); // Min negative input value | |
| 526 | try expectEqual(exp2(0x1p-1022), 1); // First positive subnormal input | |
| 527 | try expectEqual(exp2(-0x1p-1022), 1); // First negative subnormal input | |
| 529 | try expectEqual(exp2_f64(0x1.fffffffffffffp+9), 0x1.ffffffffffd3ap+1023); // The last value before the result gets infinite | |
| 530 | try expectEqual(exp2_f64(0x1p+10), math.inf(f64)); // The first value that gives infinite result | |
| 531 | try expectEqual(exp2_f64(-0x1.0cbffffffffffp+10), 0x1p-1074); // The last value before the result flushes to zero | |
| 532 | try expectEqual(exp2_f64(-0x1.0ccp+10), 0); // The first value at which the result flushes to zero | |
| 533 | try expectEqual(exp2_f64(-0x1.ffp+9), 0x1p-1022); // The last value before the result flushes to subnormal | |
| 534 | try expectEqual(exp2_f64(-0x1.ff00000000001p+9), 0x1.ffffffffffd3ap-1023); // The first value for which the result flushes to subnormal | |
| 535 | try expectEqual(exp2_f64(0x1.fffffffffffffp+1023), math.inf(f64)); // Max input value | |
| 536 | try expectEqual(exp2_f64(0x1p-1074), 1); // Min positive input value | |
| 537 | try expectEqual(exp2_f64(-0x1p-1074), 1); // Min negative input value | |
| 538 | try expectEqual(exp2_f64(0x1p-1022), 1); // First positive subnormal input | |
| 539 | try expectEqual(exp2_f64(-0x1p-1022), 1); // First negative subnormal input | |
| 528 | 540 | } |
lib/compiler_rt/exp_f128.zig+2-2| ... | ... | @@ -26,7 +26,7 @@ const exp_f128 = @This(); |
| 26 | 26 | const std = @import("std"); |
| 27 | 27 | const math = std.math; |
| 28 | 28 | |
| 29 | pub fn exp(x: f128) callconv(.c) f128 { | |
| 29 | pub fn exp(x: f128) f128 { | |
| 30 | 30 | if (!math.isFinite(x)) { |
| 31 | 31 | if (math.isNan(x)) { |
| 32 | 32 | if (math.isSignalNan(x)) math.raiseInvalid(); |
| ... | ... | @@ -91,7 +91,7 @@ fn expPoly(r_hi: f128, r_lo: f128) f128 { |
| 91 | 91 | } |
| 92 | 92 | |
| 93 | 93 | /// Computes 2^x |
| 94 | pub fn exp2(x: f128) callconv(.c) f128 { | |
| 94 | pub fn exp2(x: f128) f128 { | |
| 95 | 95 | if (!math.isFinite(x)) { |
| 96 | 96 | if (math.isNan(x)) { |
| 97 | 97 | if (math.isSignalNan(x)) math.raiseInvalid(); |
lib/compiler_rt/extenddftf2.zig deleted-22| ... | ... | @@ -1,22 +0,0 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const extendf = @import("./extendf.zig").extendf; | |
| 3 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 4 | ||
| 5 | comptime { | |
| 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 | ||
| 16 | pub fn __extenddftf2(a: f64) callconv(.c) f128 { | |
| 17 | return extendf(f128, f64, @as(u64, @bitCast(a))); | |
| 18 | } | |
| 19 | ||
| 20 | fn _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 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = compiler_rt.symbol; | |
| 3 | const extend_f80 = @import("./extendf.zig").extend_f80; | |
| 4 | ||
| 5 | comptime { | |
| 6 | symbol(&__extenddfxf2, "__extenddfxf2"); | |
| 7 | } | |
| 8 | ||
| 9 | pub 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 | 1 | const std = @import("std"); |
| 2 | 2 | |
| 3 | pub inline fn extendf( | |
| 4 | comptime dst_t: type, | |
| 5 | comptime src_t: type, | |
| 6 | a: @Int(.unsigned, @typeInfo(src_t).float.bits), | |
| 7 | ) dst_t { | |
| 3 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 4 | const symbol = compiler_rt.symbol; | |
| 5 | ||
| 6 | comptime { | |
| 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 | ||
| 59 | fn __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 | } | |
| 62 | fn __aeabi_h2f(a: u16) callconv(.{ .arm_aapcs = .{} }) u32 { | |
| 63 | return @bitCast(f32_floatCast_f16(@bitCast(a))); | |
| 64 | } | |
| 65 | pub fn f32_floatCast_f16(a: f16) f32 { | |
| 66 | return extendf(f32, f16, a); | |
| 67 | } | |
| 68 | ||
| 69 | fn __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 | } | |
| 72 | pub fn f64_floatCast_f16(a: f16) f64 { | |
| 73 | return extendf(f64, f16, a); | |
| 74 | } | |
| 75 | ||
| 76 | fn __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 | } | |
| 79 | pub fn f80_floatCast_f16(a: f16) f80 { | |
| 80 | return extend_f80(f16, a); | |
| 81 | } | |
| 82 | ||
| 83 | fn __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 | } | |
| 86 | pub fn f128_floatCast_f16(a: f16) f128 { | |
| 87 | return extendf(f128, f16, a); | |
| 88 | } | |
| 89 | ||
| 90 | fn __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 | } | |
| 93 | fn __aeabi_f2d(a: f32) callconv(.{ .arm_aapcs = .{} }) f64 { | |
| 94 | return f64_floatCast_f32(a); | |
| 95 | } | |
| 96 | pub fn f64_floatCast_f32(a: f32) f64 { | |
| 97 | return extendf(f64, f32, a); | |
| 98 | } | |
| 99 | ||
| 100 | fn __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 | } | |
| 103 | pub fn f80_floatCast_f32(a: f32) f80 { | |
| 104 | return extend_f80(f32, a); | |
| 105 | } | |
| 106 | ||
| 107 | pub 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 | } | |
| 110 | fn _Qp_stoq(c: *f128, a: f32) callconv(.c) void { | |
| 111 | c.* = f128_floatCast_f32(a); | |
| 112 | } | |
| 113 | pub fn f128_floatCast_f32(a: f32) f128 { | |
| 114 | return extendf(f128, f32, a); | |
| 115 | } | |
| 116 | ||
| 117 | fn __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 | } | |
| 120 | pub fn f80_floatCast_f64(a: f64) f80 { | |
| 121 | return extend_f80(f64, a); | |
| 122 | } | |
| 123 | ||
| 124 | fn __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 | } | |
| 127 | fn _Qp_dtoq(c: *f128, a: f64) callconv(.c) void { | |
| 128 | c.* = f128_floatCast_f64(a); | |
| 129 | } | |
| 130 | pub fn f128_floatCast_f64(a: f64) f128 { | |
| 131 | return extendf(f128, f64, a); | |
| 132 | } | |
| 133 | ||
| 134 | fn __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 | } | |
| 137 | pub 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 | ||
| 172 | inline fn extendf(comptime dst_t: type, comptime src_t: type, f: src_t) dst_t { | |
| 8 | 173 | const src_rep_t = @Int(.unsigned, @typeInfo(src_t).float.bits); |
| 9 | 174 | const dst_rep_t = @Int(.unsigned, @typeInfo(dst_t).float.bits); |
| 10 | 175 | const srcSigBits = std.math.floatMantissaBits(src_t); |
| ... | ... | @@ -31,6 +196,7 @@ pub inline fn extendf( |
| 31 | 196 | |
| 32 | 197 | const dstMinNormal: dst_rep_t = @as(dst_rep_t, 1) << dstSigBits; |
| 33 | 198 | |
| 199 | const a: src_rep_t = @bitCast(f); | |
| 34 | 200 | // Break a into a sign and representation of the absolute value |
| 35 | 201 | const aRep: src_rep_t = @bitCast(a); |
| 36 | 202 | const aAbs: src_rep_t = aRep & srcAbsMask; |
| ... | ... | @@ -66,11 +232,11 @@ pub inline fn extendf( |
| 66 | 232 | } |
| 67 | 233 | |
| 68 | 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 | 236 | return @bitCast(result); |
| 71 | 237 | } |
| 72 | 238 | |
| 73 | pub inline fn extend_f80(comptime src_t: type, a: @Int(.unsigned, @typeInfo(src_t).float.bits)) f80 { | |
| 239 | inline fn extend_f80(comptime src_t: type, f: src_t) f80 { | |
| 74 | 240 | const src_rep_t = @Int(.unsigned, @typeInfo(src_t).float.bits); |
| 75 | 241 | const src_sig_bits = std.math.floatMantissaBits(src_t); |
| 76 | 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 | 258 | |
| 93 | 259 | var dst: std.math.F80 = undefined; |
| 94 | 260 | |
| 261 | const a: src_rep_t = @bitCast(f); | |
| 95 | 262 | // Break a into a sign and representation of the absolute value |
| 96 | 263 | const a_abs = a & src_abs_mask; |
| 97 | 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 | 1 | const builtin = @import("builtin"); |
| 2 | ||
| 3 | 2 | const std = @import("std"); |
| 4 | const math = std.math; | |
| 3 | const testing = std.testing; | |
| 4 | ||
| 5 | const impl = @import("extendf.zig"); | |
| 6 | ||
| 7 | const f32_floatCast_f16 = impl.f32_floatCast_f16; | |
| 8 | const f64_floatCast_f16 = impl.f64_floatCast_f16; | |
| 9 | const f80_floatCast_f16 = impl.f80_floatCast_f16; | |
| 10 | const f128_floatCast_f16 = impl.f128_floatCast_f16; | |
| 11 | ||
| 12 | const f64_floatCast_f32 = impl.f64_floatCast_f32; | |
| 13 | const f80_floatCast_f32 = impl.f80_floatCast_f32; | |
| 14 | const f128_floatCast_f32 = impl.f128_floatCast_f32; | |
| 5 | 15 | |
| 6 | const __extendhfsf2 = @import("extendhfsf2.zig").__extendhfsf2; | |
| 7 | const __extendhftf2 = @import("extendhftf2.zig").__extendhftf2; | |
| 8 | const __extendsftf2 = @import("extendsftf2.zig").__extendsftf2; | |
| 9 | const __extenddftf2 = @import("extenddftf2.zig").__extenddftf2; | |
| 10 | const __extenddfxf2 = @import("extenddfxf2.zig").__extenddfxf2; | |
| 11 | const F16T = @import("../compiler_rt.zig").F16T; | |
| 16 | const f80_floatCast_f64 = impl.f80_floatCast_f64; | |
| 17 | const f128_floatCast_f64 = impl.f128_floatCast_f64; | |
| 12 | 18 | |
| 13 | fn test__extenddfxf2(a: f64, expected: u80) !void { | |
| 14 | const x = __extenddfxf2(a); | |
| 19 | const f128_floatCast_f80 = impl.f128_floatCast_f80; | |
| 20 | ||
| 21 | fn test_f80_floatCast_f64(a: f64, expected: u80) !void { | |
| 22 | const x = f80_floatCast_f64(a); | |
| 15 | 23 | |
| 16 | 24 | const rep: u80 = @bitCast(x); |
| 17 | 25 | if (rep == expected) |
| 18 | 26 | return; |
| 19 | ||
| 20 | 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 | 29 | return; |
| 23 | ||
| 24 | @panic("__extenddfxf2 test failure"); | |
| 30 | return error.TestFailure; | |
| 25 | 31 | } |
| 26 | 32 | |
| 27 | fn test__extenddftf2(a: f64, expected_hi: u64, expected_lo: u64) !void { | |
| 28 | const x = __extenddftf2(a); | |
| 33 | fn test_f128_floatCast_f64(a: f64, expected_hi: u64, expected_lo: u64) !void { | |
| 34 | const x = f128_floatCast_f64(a); | |
| 29 | 35 | |
| 30 | 36 | const rep: u128 = @bitCast(x); |
| 31 | 37 | const hi: u64 = @intCast(rep >> 64); |
| ... | ... | @@ -33,7 +39,6 @@ fn test__extenddftf2(a: f64, expected_hi: u64, expected_lo: u64) !void { |
| 33 | 39 | |
| 34 | 40 | if (hi == expected_hi and lo == expected_lo) |
| 35 | 41 | return; |
| 36 | ||
| 37 | 42 | // test other possible NaN representation(signal NaN) |
| 38 | 43 | if (expected_hi == 0x7fff800000000000 and expected_lo == 0x0) { |
| 39 | 44 | if ((hi & 0x7fff000000000000) == 0x7fff000000000000 and |
| ... | ... | @@ -42,12 +47,11 @@ fn test__extenddftf2(a: f64, expected_hi: u64, expected_lo: u64) !void { |
| 42 | 47 | return; |
| 43 | 48 | } |
| 44 | 49 | } |
| 45 | ||
| 46 | @panic("__extenddftf2 test failure"); | |
| 50 | return error.TestFailure; | |
| 47 | 51 | } |
| 48 | 52 | |
| 49 | fn test__extendhfsf2(a: u16, expected: u32) !void { | |
| 50 | const x = __extendhfsf2(@as(F16T(f32), @bitCast(a))); | |
| 53 | fn test_f32_floatCast_f16(a: u16, expected: u32) !void { | |
| 54 | const x = f32_floatCast_f16(@bitCast(a)); | |
| 51 | 55 | const rep: u32 = @bitCast(x); |
| 52 | 56 | |
| 53 | 57 | if (rep == expected) { |
| ... | ... | @@ -58,12 +62,11 @@ fn test__extendhfsf2(a: u16, expected: u32) !void { |
| 58 | 62 | return; |
| 59 | 63 | } |
| 60 | 64 | } |
| 61 | ||
| 62 | 65 | return error.TestFailure; |
| 63 | 66 | } |
| 64 | 67 | |
| 65 | fn test__extendsftf2(a: f32, expected_hi: u64, expected_lo: u64) !void { | |
| 66 | const x = __extendsftf2(a); | |
| 68 | fn test_f128_floatCast_f32(a: f32, expected_hi: u64, expected_lo: u64) !void { | |
| 69 | const x = f128_floatCast_f32(a); | |
| 67 | 70 | |
| 68 | 71 | const rep: u128 = @bitCast(x); |
| 69 | 72 | const hi: u64 = @intCast(rep >> 64); |
| ... | ... | @@ -71,7 +74,6 @@ fn test__extendsftf2(a: f32, expected_hi: u64, expected_lo: u64) !void { |
| 71 | 74 | |
| 72 | 75 | if (hi == expected_hi and lo == expected_lo) |
| 73 | 76 | return; |
| 74 | ||
| 75 | 77 | // test other possible NaN representation(signal NaN) |
| 76 | 78 | if (expected_hi == 0x7fff800000000000 and expected_lo == 0x0) { |
| 77 | 79 | if ((hi & 0x7fff000000000000) == 0x7fff000000000000 and |
| ... | ... | @@ -80,111 +82,108 @@ fn test__extendsftf2(a: f32, expected_hi: u64, expected_lo: u64) !void { |
| 80 | 82 | return; |
| 81 | 83 | } |
| 82 | 84 | } |
| 83 | ||
| 84 | 85 | return error.TestFailure; |
| 85 | 86 | } |
| 86 | 87 | |
| 87 | test "extenddfxf2" { | |
| 88 | test f80_floatCast_f64 { | |
| 88 | 89 | // qNaN |
| 89 | try test__extenddfxf2(makeQNaN64(), 0x7fffc000000000000000); | |
| 90 | try test_f80_floatCast_f64(makeQNaN64(), 0x7fffc000000000000000); | |
| 90 | 91 | |
| 91 | 92 | // NaN |
| 92 | try test__extenddfxf2(makeNaN64(0x7100000000000), 0x7fffe080000000000000); | |
| 93 | try test_f80_floatCast_f64(makeNaN64(0x7100000000000), 0x7fffe080000000000000); | |
| 93 | 94 | // This is bad? |
| 94 | 95 | |
| 95 | 96 | // inf |
| 96 | try test__extenddfxf2(makeInf64(), 0x7fff8000000000000000); | |
| 97 | try test_f80_floatCast_f64(makeInf64(), 0x7fff8000000000000000); | |
| 97 | 98 | |
| 98 | 99 | // zero |
| 99 | try test__extenddfxf2(0.0, 0x0); | |
| 100 | try test_f80_floatCast_f64(0.0, 0x0); | |
| 100 | 101 | |
| 101 | try test__extenddfxf2(0x0.a3456789abcdefp+6, 0x4004a3456789abcdf000); | |
| 102 | try test_f80_floatCast_f64(0x0.a3456789abcdefp+6, 0x4004a3456789abcdf000); | |
| 102 | 103 | |
| 103 | try test__extenddfxf2(0x0.edcba987654321fp-8, 0x3ff6edcba98765432000); | |
| 104 | try test_f80_floatCast_f64(0x0.edcba987654321fp-8, 0x3ff6edcba98765432000); | |
| 104 | 105 | |
| 105 | try test__extenddfxf2(0x0.a3456789abcdefp+46, 0x402ca3456789abcdf000); | |
| 106 | try test_f80_floatCast_f64(0x0.a3456789abcdefp+46, 0x402ca3456789abcdf000); | |
| 106 | 107 | |
| 107 | try test__extenddfxf2(0x0.edcba987654321fp-44, 0x3fd2edcba98765432000); | |
| 108 | try test_f80_floatCast_f64(0x0.edcba987654321fp-44, 0x3fd2edcba98765432000); | |
| 108 | 109 | |
| 109 | 110 | // subnormal |
| 110 | try test__extenddfxf2(0x1.8000000000001p-1022, 0x3c01c000000000000800); | |
| 111 | try test__extenddfxf2(0x1.8000000000002p-1023, 0x3c00c000000000001000); | |
| 111 | try test_f80_floatCast_f64(0x1.8000000000001p-1022, 0x3c01c000000000000800); | |
| 112 | try test_f80_floatCast_f64(0x1.8000000000002p-1023, 0x3c00c000000000001000); | |
| 112 | 113 | } |
| 113 | 114 | |
| 114 | test "extenddftf2" { | |
| 115 | if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; | |
| 116 | ||
| 115 | test f128_floatCast_f64 { | |
| 117 | 116 | // qNaN |
| 118 | try test__extenddftf2(makeQNaN64(), 0x7fff800000000000, 0x0); | |
| 117 | try test_f128_floatCast_f64(makeQNaN64(), 0x7fff800000000000, 0x0); | |
| 119 | 118 | |
| 120 | 119 | // NaN |
| 121 | try test__extenddftf2(makeNaN64(0x7100000000000), 0x7fff710000000000, 0x0); | |
| 120 | try test_f128_floatCast_f64(makeNaN64(0x7100000000000), 0x7fff710000000000, 0x0); | |
| 122 | 121 | |
| 123 | 122 | // inf |
| 124 | try test__extenddftf2(makeInf64(), 0x7fff000000000000, 0x0); | |
| 123 | try test_f128_floatCast_f64(makeInf64(), 0x7fff000000000000, 0x0); | |
| 125 | 124 | |
| 126 | 125 | // zero |
| 127 | try test__extenddftf2(0.0, 0x0, 0x0); | |
| 126 | try test_f128_floatCast_f64(0.0, 0x0, 0x0); | |
| 128 | 127 | |
| 129 | try test__extenddftf2(0x1.23456789abcdefp+5, 0x400423456789abcd, 0xf000000000000000); | |
| 128 | try test_f128_floatCast_f64(0x1.23456789abcdefp+5, 0x400423456789abcd, 0xf000000000000000); | |
| 130 | 129 | |
| 131 | try test__extenddftf2(0x1.edcba987654321fp-9, 0x3ff6edcba9876543, 0x2000000000000000); | |
| 130 | try test_f128_floatCast_f64(0x1.edcba987654321fp-9, 0x3ff6edcba9876543, 0x2000000000000000); | |
| 132 | 131 | |
| 133 | try test__extenddftf2(0x1.23456789abcdefp+45, 0x402c23456789abcd, 0xf000000000000000); | |
| 132 | try test_f128_floatCast_f64(0x1.23456789abcdefp+45, 0x402c23456789abcd, 0xf000000000000000); | |
| 134 | 133 | |
| 135 | try test__extenddftf2(0x1.edcba987654321fp-45, 0x3fd2edcba9876543, 0x2000000000000000); | |
| 134 | try test_f128_floatCast_f64(0x1.edcba987654321fp-45, 0x3fd2edcba9876543, 0x2000000000000000); | |
| 136 | 135 | |
| 137 | 136 | // subnormal |
| 138 | try test__extenddftf2(0x1.8p-1022, 0x3c01800000000000, 0x0); | |
| 139 | try test__extenddftf2(0x1.8p-1023, 0x3c00800000000000, 0x0); | |
| 137 | try test_f128_floatCast_f64(0x1.8p-1022, 0x3c01800000000000, 0x0); | |
| 138 | try test_f128_floatCast_f64(0x1.8p-1023, 0x3c00800000000000, 0x0); | |
| 140 | 139 | } |
| 141 | 140 | |
| 142 | test "extendhfsf2" { | |
| 143 | try test__extendhfsf2(0x7e00, 0x7fc00000); // qNaN | |
| 144 | try test__extendhfsf2(0x7f00, 0x7fe00000); // sNaN | |
| 141 | test f32_floatCast_f16 { | |
| 142 | try test_f32_floatCast_f16(0x7e00, 0x7fc00000); // qNaN | |
| 143 | try test_f32_floatCast_f16(0x7f00, 0x7fe00000); // sNaN | |
| 145 | 144 | // On x86 the NaN becomes quiet because the return is pushed on the x87 |
| 146 | 145 | // stack due to ABI requirements |
| 147 | 146 | if (builtin.target.cpu.arch != .x86 and builtin.target.os.tag == .windows) |
| 148 | try test__extendhfsf2(0x7c01, 0x7f802000); // sNaN | |
| 147 | try test_f32_floatCast_f16(0x7c01, 0x7f802000); // sNaN | |
| 149 | 148 | |
| 150 | try test__extendhfsf2(0, 0); // 0 | |
| 151 | try test__extendhfsf2(0x8000, 0x80000000); // -0 | |
| 149 | try test_f32_floatCast_f16(0, 0); // 0 | |
| 150 | try test_f32_floatCast_f16(0x8000, 0x80000000); // -0 | |
| 152 | 151 | |
| 153 | try test__extendhfsf2(0x7c00, 0x7f800000); // inf | |
| 154 | try test__extendhfsf2(0xfc00, 0xff800000); // -inf | |
| 152 | try test_f32_floatCast_f16(0x7c00, 0x7f800000); // inf | |
| 153 | try test_f32_floatCast_f16(0xfc00, 0xff800000); // -inf | |
| 155 | 154 | |
| 156 | try test__extendhfsf2(0x0001, 0x33800000); // denormal (min), 2**-24 | |
| 157 | try test__extendhfsf2(0x8001, 0xb3800000); // denormal (min), -2**-24 | |
| 155 | try test_f32_floatCast_f16(0x0001, 0x33800000); // denormal (min), 2**-24 | |
| 156 | try test_f32_floatCast_f16(0x8001, 0xb3800000); // denormal (min), -2**-24 | |
| 158 | 157 | |
| 159 | try test__extendhfsf2(0x03ff, 0x387fc000); // denormal (max), 2**-14 - 2**-24 | |
| 160 | try test__extendhfsf2(0x83ff, 0xb87fc000); // denormal (max), -2**-14 + 2**-24 | |
| 158 | try test_f32_floatCast_f16(0x03ff, 0x387fc000); // denormal (max), 2**-14 - 2**-24 | |
| 159 | try test_f32_floatCast_f16(0x83ff, 0xb87fc000); // denormal (max), -2**-14 + 2**-24 | |
| 161 | 160 | |
| 162 | try test__extendhfsf2(0x0400, 0x38800000); // normal (min), 2**-14 | |
| 163 | try test__extendhfsf2(0x8400, 0xb8800000); // normal (min), -2**-14 | |
| 161 | try test_f32_floatCast_f16(0x0400, 0x38800000); // normal (min), 2**-14 | |
| 162 | try test_f32_floatCast_f16(0x8400, 0xb8800000); // normal (min), -2**-14 | |
| 164 | 163 | |
| 165 | try test__extendhfsf2(0x7bff, 0x477fe000); // normal (max), 65504 | |
| 166 | try test__extendhfsf2(0xfbff, 0xc77fe000); // normal (max), -65504 | |
| 164 | try test_f32_floatCast_f16(0x7bff, 0x477fe000); // normal (max), 65504 | |
| 165 | try test_f32_floatCast_f16(0xfbff, 0xc77fe000); // normal (max), -65504 | |
| 167 | 166 | |
| 168 | try test__extendhfsf2(0x3c01, 0x3f802000); // normal, 1 + 2**-10 | |
| 169 | try test__extendhfsf2(0xbc01, 0xbf802000); // normal, -1 - 2**-10 | |
| 167 | try test_f32_floatCast_f16(0x3c01, 0x3f802000); // normal, 1 + 2**-10 | |
| 168 | try test_f32_floatCast_f16(0xbc01, 0xbf802000); // normal, -1 - 2**-10 | |
| 170 | 169 | |
| 171 | try test__extendhfsf2(0x3555, 0x3eaaa000); // normal, approx. 1/3 | |
| 172 | try test__extendhfsf2(0xb555, 0xbeaaa000); // normal, approx. -1/3 | |
| 170 | try test_f32_floatCast_f16(0x3555, 0x3eaaa000); // normal, approx. 1/3 | |
| 171 | try test_f32_floatCast_f16(0xb555, 0xbeaaa000); // normal, approx. -1/3 | |
| 173 | 172 | } |
| 174 | 173 | |
| 175 | test "extendsftf2" { | |
| 174 | test f128_floatCast_f32 { | |
| 176 | 175 | // qNaN |
| 177 | try test__extendsftf2(makeQNaN32(), 0x7fff800000000000, 0x0); | |
| 176 | try test_f128_floatCast_f32(makeQNaN32(), 0x7fff800000000000, 0x0); | |
| 178 | 177 | // NaN |
| 179 | try test__extendsftf2(makeNaN32(0x410000), 0x7fff820000000000, 0x0); | |
| 178 | try test_f128_floatCast_f32(makeNaN32(0x410000), 0x7fff820000000000, 0x0); | |
| 180 | 179 | // inf |
| 181 | try test__extendsftf2(makeInf32(), 0x7fff000000000000, 0x0); | |
| 180 | try test_f128_floatCast_f32(makeInf32(), 0x7fff000000000000, 0x0); | |
| 182 | 181 | // zero |
| 183 | try test__extendsftf2(0.0, 0x0, 0x0); | |
| 184 | try test__extendsftf2(0x1.23456p+5, 0x4004234560000000, 0x0); | |
| 185 | try test__extendsftf2(0x1.edcbap-9, 0x3ff6edcba0000000, 0x0); | |
| 186 | try test__extendsftf2(0x1.23456p+45, 0x402c234560000000, 0x0); | |
| 187 | try test__extendsftf2(0x1.edcbap-45, 0x3fd2edcba0000000, 0x0); | |
| 182 | try test_f128_floatCast_f32(0.0, 0x0, 0x0); | |
| 183 | try test_f128_floatCast_f32(0x1.23456p+5, 0x4004234560000000, 0x0); | |
| 184 | try test_f128_floatCast_f32(0x1.edcbap-9, 0x3ff6edcba0000000, 0x0); | |
| 185 | try test_f128_floatCast_f32(0x1.23456p+45, 0x402c234560000000, 0x0); | |
| 186 | try test_f128_floatCast_f32(0x1.edcbap-45, 0x3fd2edcba0000000, 0x0); | |
| 188 | 187 | } |
| 189 | 188 | |
| 190 | 189 | fn makeQNaN64() f64 { |
| ... | ... | @@ -211,8 +210,8 @@ fn makeInf32() f32 { |
| 211 | 210 | return @bitCast(@as(u32, 0x7f800000)); |
| 212 | 211 | } |
| 213 | 212 | |
| 214 | fn test__extendhftf2(a: u16, expected_hi: u64, expected_lo: u64) !void { | |
| 215 | const x = __extendhftf2(@as(F16T(f128), @bitCast(a))); | |
| 213 | fn test_f128_floatCast_f16(a: u16, expected_hi: u64, expected_lo: u64) !void { | |
| 214 | const x = f128_floatCast_f16(@bitCast(a)); | |
| 216 | 215 | |
| 217 | 216 | const rep: u128 = @bitCast(x); |
| 218 | 217 | const hi: u64 = @intCast(rep >> 64); |
| ... | ... | @@ -233,26 +232,26 @@ fn test__extendhftf2(a: u16, expected_hi: u64, expected_lo: u64) !void { |
| 233 | 232 | return error.TestFailure; |
| 234 | 233 | } |
| 235 | 234 | |
| 236 | test "extendhftf2" { | |
| 235 | test f128_floatCast_f16 { | |
| 237 | 236 | // qNaN |
| 238 | try test__extendhftf2(0x7e00, 0x7fff800000000000, 0x0); | |
| 237 | try test_f128_floatCast_f16(0x7e00, 0x7fff800000000000, 0x0); | |
| 239 | 238 | // NaN |
| 240 | try test__extendhftf2(0x7d00, 0x7fff400000000000, 0x0); | |
| 239 | try test_f128_floatCast_f16(0x7d00, 0x7fff400000000000, 0x0); | |
| 241 | 240 | // inf |
| 242 | try test__extendhftf2(0x7c00, 0x7fff000000000000, 0x0); | |
| 243 | try test__extendhftf2(0xfc00, 0xffff000000000000, 0x0); | |
| 241 | try test_f128_floatCast_f16(0x7c00, 0x7fff000000000000, 0x0); | |
| 242 | try test_f128_floatCast_f16(0xfc00, 0xffff000000000000, 0x0); | |
| 244 | 243 | // zero |
| 245 | try test__extendhftf2(0x0000, 0x0000000000000000, 0x0); | |
| 246 | try test__extendhftf2(0x8000, 0x8000000000000000, 0x0); | |
| 244 | try test_f128_floatCast_f16(0x0000, 0x0000000000000000, 0x0); | |
| 245 | try test_f128_floatCast_f16(0x8000, 0x8000000000000000, 0x0); | |
| 247 | 246 | // denormal |
| 248 | try test__extendhftf2(0x0010, 0x3feb000000000000, 0x0); | |
| 249 | try test__extendhftf2(0x0001, 0x3fe7000000000000, 0x0); | |
| 250 | try test__extendhftf2(0x8001, 0xbfe7000000000000, 0x0); | |
| 247 | try test_f128_floatCast_f16(0x0010, 0x3feb000000000000, 0x0); | |
| 248 | try test_f128_floatCast_f16(0x0001, 0x3fe7000000000000, 0x0); | |
| 249 | try test_f128_floatCast_f16(0x8001, 0xbfe7000000000000, 0x0); | |
| 251 | 250 | |
| 252 | 251 | // pi |
| 253 | try test__extendhftf2(0x4248, 0x4000920000000000, 0x0); | |
| 254 | try test__extendhftf2(0xc248, 0xc000920000000000, 0x0); | |
| 252 | try test_f128_floatCast_f16(0x4248, 0x4000920000000000, 0x0); | |
| 253 | try test_f128_floatCast_f16(0xc248, 0xc000920000000000, 0x0); | |
| 255 | 254 | |
| 256 | try test__extendhftf2(0x508c, 0x4004230000000000, 0x0); | |
| 257 | try test__extendhftf2(0x1bb7, 0x3ff6edc000000000, 0x0); | |
| 255 | try test_f128_floatCast_f16(0x508c, 0x4004230000000000, 0x0); | |
| 256 | try test_f128_floatCast_f16(0x1bb7, 0x3ff6edc000000000, 0x0); | |
| 258 | 257 | } |
lib/compiler_rt/extendhfdf2.zig deleted-11| ... | ... | @@ -1,11 +0,0 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 3 | const extendf = @import("./extendf.zig").extendf; | |
| 4 | ||
| 5 | comptime { | |
| 6 | symbol(&__extendhfdf2, "__extendhfdf2"); | |
| 7 | } | |
| 8 | ||
| 9 | pub 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 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const extendf = @import("./extendf.zig").extendf; | |
| 3 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 4 | ||
| 5 | comptime { | |
| 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 | ||
| 14 | pub fn __extendhfsf2(a: compiler_rt.F16T(f32)) callconv(.c) f32 { | |
| 15 | return extendf(f32, f16, @as(u16, @bitCast(a))); | |
| 16 | } | |
| 17 | ||
| 18 | fn __gnu_h2f_ieee(a: compiler_rt.F16T(f32)) callconv(.c) f32 { | |
| 19 | return extendf(f32, f16, @as(u16, @bitCast(a))); | |
| 20 | } | |
| 21 | ||
| 22 | fn __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 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = compiler_rt.symbol; | |
| 3 | const extendf = @import("./extendf.zig").extendf; | |
| 4 | ||
| 5 | comptime { | |
| 6 | symbol(&__extendhftf2, "__extendhftf2"); | |
| 7 | } | |
| 8 | ||
| 9 | pub 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 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = compiler_rt.symbol; | |
| 3 | const extend_f80 = @import("./extendf.zig").extend_f80; | |
| 4 | ||
| 5 | comptime { | |
| 6 | symbol(&__extendhfxf2, "__extendhfxf2"); | |
| 7 | } | |
| 8 | ||
| 9 | fn __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 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = compiler_rt.symbol; | |
| 3 | const extendf = @import("./extendf.zig").extendf; | |
| 4 | ||
| 5 | comptime { | |
| 6 | if (compiler_rt.want_aeabi) { | |
| 7 | symbol(&__aeabi_f2d, "__aeabi_f2d"); | |
| 8 | } else { | |
| 9 | symbol(&__extendsfdf2, "__extendsfdf2"); | |
| 10 | } | |
| 11 | } | |
| 12 | ||
| 13 | fn __extendsfdf2(a: f32) callconv(.c) f64 { | |
| 14 | return extendf(f64, f32, @as(u32, @bitCast(a))); | |
| 15 | } | |
| 16 | ||
| 17 | fn __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 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = compiler_rt.symbol; | |
| 3 | const extendf = @import("./extendf.zig").extendf; | |
| 4 | ||
| 5 | comptime { | |
| 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 | ||
| 16 | pub fn __extendsftf2(a: f32) callconv(.c) f128 { | |
| 17 | return extendf(f128, f32, @as(u32, @bitCast(a))); | |
| 18 | } | |
| 19 | ||
| 20 | fn _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 @@ |
| 1 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 2 | const extend_f80 = @import("./extendf.zig").extend_f80; | |
| 3 | ||
| 4 | comptime { | |
| 5 | symbol(&__extendsfxf2, "__extendsfxf2"); | |
| 6 | } | |
| 7 | ||
| 8 | fn __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 @@ |
| 1 | const std = @import("std"); | |
| 2 | ||
| 3 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 4 | ||
| 5 | comptime { | |
| 6 | symbol(&__extendxftf2, "__extendxftf2"); | |
| 7 | } | |
| 8 | ||
| 9 | fn __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 | 9 | symbol(&fabsf, "fabsf"); |
| 10 | 10 | symbol(&fabs, "fabs"); |
| 11 | 11 | symbol(&__fabsx, "__fabsx"); |
| 12 | if (compiler_rt.want_ppc_abi) { | |
| 13 | symbol(&fabsq, "fabsf128"); | |
| 14 | } | |
| 15 | symbol(&fabsq, "fabsq"); | |
| 12 | symbol(&fabsq, "fabsf128"); | |
| 16 | 13 | symbol(&fabsl, "fabsl"); |
| 17 | 14 | } |
| 18 | 15 | |
| 19 | pub fn __fabsh(a: f16) callconv(.c) f16 { | |
| 16 | fn __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 | } | |
| 19 | pub fn fabs_f16(a: f16) f16 { | |
| 20 | 20 | return generic_fabs(a); |
| 21 | 21 | } |
| 22 | 22 | |
| 23 | pub fn fabsf(a: f32) callconv(.c) f32 { | |
| 23 | fn 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 | } | |
| 26 | pub fn fabs_f32(a: f32) f32 { | |
| 24 | 27 | return generic_fabs(a); |
| 25 | 28 | } |
| 26 | 29 | |
| 27 | pub fn fabs(a: f64) callconv(.c) f64 { | |
| 30 | fn 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 | } | |
| 33 | pub fn fabs_f64(a: f64) f64 { | |
| 28 | 34 | return generic_fabs(a); |
| 29 | 35 | } |
| 30 | 36 | |
| 31 | pub fn __fabsx(a: f80) callconv(.c) f80 { | |
| 37 | fn __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 | } | |
| 40 | pub fn fabs_f80(a: f80) f80 { | |
| 32 | 41 | return generic_fabs(a); |
| 33 | 42 | } |
| 34 | 43 | |
| 35 | pub fn fabsq(a: f128) callconv(.c) f128 { | |
| 44 | fn 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 | } | |
| 47 | pub fn fabs_f128(a: f128) f128 { | |
| 36 | 48 | return generic_fabs(a); |
| 37 | 49 | } |
| 38 | 50 | |
| 39 | 51 | pub fn fabsl(x: c_longdouble) callconv(.c) c_longdouble { |
| 40 | 52 | switch (@typeInfo(c_longdouble).float.bits) { |
| 41 | 64 => return fabs(x), | |
| 42 | 80 => return __fabsx(x), | |
| 43 | 128 => return fabsq(x), | |
| 44 | else => @compileError("unreachable"), | |
| 53 | 64 => return fabs_f64(x), | |
| 54 | 80 => return fabs_f80(x), | |
| 55 | 128 => return fabs_f128(x), | |
| 56 | else => comptime unreachable, | |
| 45 | 57 | } |
| 46 | 58 | } |
| 47 | 59 |
lib/compiler_rt/fixdfdi.zig deleted-23| ... | ... | @@ -1,23 +0,0 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 3 | const symbol = compiler_rt.symbol; | |
| 4 | const intFromFloat = @import("./int_from_float.zig").intFromFloat; | |
| 5 | ||
| 6 | comptime { | |
| 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 | ||
| 17 | pub fn __fixdfdi(a: f64) callconv(.c) i64 { | |
| 18 | return intFromFloat(i64, a); | |
| 19 | } | |
| 20 | ||
| 21 | fn __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 @@ |
| 1 | const std = @import("std"); | |
| 2 | const builtin = @import("builtin"); | |
| 3 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 4 | const symbol = compiler_rt.symbol; | |
| 5 | const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat; | |
| 6 | ||
| 7 | comptime { | |
| 8 | symbol(&__fixdfei, "__fixdfei"); | |
| 9 | } | |
| 10 | ||
| 11 | pub 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 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const intFromFloat = @import("./int_from_float.zig").intFromFloat; | |
| 3 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 4 | ||
| 5 | comptime { | |
| 6 | if (compiler_rt.want_aeabi) { | |
| 7 | symbol(&__aeabi_d2iz, "__aeabi_d2iz"); | |
| 8 | } else { | |
| 9 | symbol(&__fixdfsi, "__fixdfsi"); | |
| 10 | } | |
| 11 | } | |
| 12 | ||
| 13 | pub fn __fixdfsi(a: f64) callconv(.c) i32 { | |
| 14 | return intFromFloat(i32, a); | |
| 15 | } | |
| 16 | ||
| 17 | fn __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 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const intFromFloat = @import("./int_from_float.zig").intFromFloat; | |
| 3 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 4 | ||
| 5 | comptime { | |
| 6 | symbol(&__fixdfti, "__fixdfti"); | |
| 7 | } | |
| 8 | ||
| 9 | pub fn __fixdfti(a: f64) callconv(.c) i128 { | |
| 10 | return intFromFloat(i128, a); | |
| 11 | } |
lib/compiler_rt/fixhfei.zig deleted-14| ... | ... | @@ -1,14 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | const builtin = @import("builtin"); | |
| 3 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 4 | const symbol = compiler_rt.symbol; | |
| 5 | const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat; | |
| 6 | ||
| 7 | comptime { | |
| 8 | symbol(&__fixhfei, "__fixhfei"); | |
| 9 | } | |
| 10 | ||
| 11 | pub 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 @@ |
| 1 | const std = @import("std"); | |
| 2 | const math = std.math; | |
| 3 | const testing = std.testing; | |
| 4 | ||
| 5 | const fixint = @import("fixint.zig").fixint; | |
| 6 | ||
| 7 | fn 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 | ||
| 12 | test "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 | ||
| 32 | test "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 | ||
| 53 | test "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 | ||
| 78 | test "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 | ||
| 102 | test "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 | ||
| 127 | test "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 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 3 | const intFromFloat = @import("./int_from_float.zig").intFromFloat; | |
| 4 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 5 | ||
| 6 | comptime { | |
| 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 | ||
| 17 | pub fn __fixsfdi(a: f32) callconv(.c) i64 { | |
| 18 | return intFromFloat(i64, a); | |
| 19 | } | |
| 20 | ||
| 21 | fn __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 @@ |
| 1 | const std = @import("std"); | |
| 2 | const builtin = @import("builtin"); | |
| 3 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 4 | const symbol = compiler_rt.symbol; | |
| 5 | const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat; | |
| 6 | ||
| 7 | comptime { | |
| 8 | symbol(&__fixsfei, "__fixsfei"); | |
| 9 | } | |
| 10 | ||
| 11 | pub 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 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = compiler_rt.symbol; | |
| 3 | const intFromFloat = @import("./int_from_float.zig").intFromFloat; | |
| 4 | ||
| 5 | comptime { | |
| 6 | if (compiler_rt.want_aeabi) { | |
| 7 | symbol(&__aeabi_f2iz, "__aeabi_f2iz"); | |
| 8 | } else { | |
| 9 | symbol(&__fixsfsi, "__fixsfsi"); | |
| 10 | } | |
| 11 | } | |
| 12 | ||
| 13 | pub fn __fixsfsi(a: f32) callconv(.c) i32 { | |
| 14 | return intFromFloat(i32, a); | |
| 15 | } | |
| 16 | ||
| 17 | fn __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 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 3 | const symbol = compiler_rt.symbol; | |
| 4 | const intFromFloat = @import("./int_from_float.zig").intFromFloat; | |
| 5 | ||
| 6 | comptime { | |
| 7 | symbol(&__fixsfti, "__fixsfti"); | |
| 8 | } | |
| 9 | ||
| 10 | pub fn __fixsfti(a: f32) callconv(.c) i128 { | |
| 11 | return intFromFloat(i128, a); | |
| 12 | } |
lib/compiler_rt/fixtfdi.zig deleted-22| ... | ... | @@ -1,22 +0,0 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const intFromFloat = @import("./int_from_float.zig").intFromFloat; | |
| 3 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 4 | ||
| 5 | comptime { | |
| 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 | ||
| 16 | pub fn __fixtfdi(a: f128) callconv(.c) i64 { | |
| 17 | return intFromFloat(i64, a); | |
| 18 | } | |
| 19 | ||
| 20 | fn _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 @@ |
| 1 | const std = @import("std"); | |
| 2 | const builtin = @import("builtin"); | |
| 3 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 4 | const symbol = compiler_rt.symbol; | |
| 5 | const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat; | |
| 6 | ||
| 7 | comptime { | |
| 8 | symbol(&__fixtfei, "__fixtfei"); | |
| 9 | } | |
| 10 | ||
| 11 | pub 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 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 3 | const intFromFloat = @import("./int_from_float.zig").intFromFloat; | |
| 4 | ||
| 5 | comptime { | |
| 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 | ||
| 16 | pub fn __fixtfsi(a: f128) callconv(.c) i32 { | |
| 17 | return intFromFloat(i32, a); | |
| 18 | } | |
| 19 | ||
| 20 | fn _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 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const intFromFloat = @import("./int_from_float.zig").intFromFloat; | |
| 3 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 4 | ||
| 5 | comptime { | |
| 6 | if (compiler_rt.want_ppc_abi) | |
| 7 | symbol(&__fixtfti, "__fixkfti"); | |
| 8 | symbol(&__fixtfti, "__fixtfti"); | |
| 9 | } | |
| 10 | ||
| 11 | pub fn __fixtfti(a: f128) callconv(.c) i128 { | |
| 12 | return intFromFloat(i128, a); | |
| 13 | } |
lib/compiler_rt/fixunsdfdi.zig deleted-23| ... | ... | @@ -1,23 +0,0 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 3 | const symbol = compiler_rt.symbol; | |
| 4 | const intFromFloat = @import("./int_from_float.zig").intFromFloat; | |
| 5 | ||
| 6 | comptime { | |
| 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 | ||
| 17 | pub fn __fixunsdfdi(a: f64) callconv(.c) u64 { | |
| 18 | return intFromFloat(u64, a); | |
| 19 | } | |
| 20 | ||
| 21 | fn __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 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | ||
| 3 | const std = @import("std"); | |
| 4 | ||
| 5 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 6 | const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat; | |
| 7 | ||
| 8 | comptime { | |
| 9 | symbol(&__fixunsdfei, "__fixunsdfei"); | |
| 10 | } | |
| 11 | ||
| 12 | pub 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 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = compiler_rt.symbol; | |
| 3 | const intFromFloat = @import("./int_from_float.zig").intFromFloat; | |
| 4 | ||
| 5 | comptime { | |
| 6 | if (compiler_rt.want_aeabi) { | |
| 7 | symbol(&__aeabi_d2uiz, "__aeabi_d2uiz"); | |
| 8 | } else { | |
| 9 | symbol(&__fixunsdfsi, "__fixunsdfsi"); | |
| 10 | } | |
| 11 | } | |
| 12 | ||
| 13 | pub fn __fixunsdfsi(a: f64) callconv(.c) u32 { | |
| 14 | return intFromFloat(u32, a); | |
| 15 | } | |
| 16 | ||
| 17 | fn __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 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 3 | const intFromFloat = @import("./int_from_float.zig").intFromFloat; | |
| 4 | ||
| 5 | comptime { | |
| 6 | symbol(&__fixunsdfti, "__fixunsdfti"); | |
| 7 | } | |
| 8 | ||
| 9 | pub fn __fixunsdfti(a: f64) callconv(.c) u128 { | |
| 10 | return intFromFloat(u128, a); | |
| 11 | } |
lib/compiler_rt/fixunshfdi.zig deleted-10| ... | ... | @@ -1,10 +0,0 @@ |
| 1 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 2 | const intFromFloat = @import("./int_from_float.zig").intFromFloat; | |
| 3 | ||
| 4 | comptime { | |
| 5 | symbol(&__fixunshfdi, "__fixunshfdi"); | |
| 6 | } | |
| 7 | ||
| 8 | fn __fixunshfdi(a: f16) callconv(.c) u64 { | |
| 9 | return intFromFloat(u64, a); | |
| 10 | } |
lib/compiler_rt/fixunshfei.zig deleted-15| ... | ... | @@ -1,15 +0,0 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | ||
| 3 | const std = @import("std"); | |
| 4 | ||
| 5 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 6 | const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat; | |
| 7 | ||
| 8 | comptime { | |
| 9 | symbol(&__fixunshfei, "__fixunshfei"); | |
| 10 | } | |
| 11 | ||
| 12 | pub 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 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = compiler_rt.symbol; | |
| 3 | const intFromFloat = @import("./int_from_float.zig").intFromFloat; | |
| 4 | ||
| 5 | comptime { | |
| 6 | symbol(&__fixunshfsi, "__fixunshfsi"); | |
| 7 | } | |
| 8 | ||
| 9 | fn __fixunshfsi(a: f16) callconv(.c) u32 { | |
| 10 | return intFromFloat(u32, a); | |
| 11 | } |
lib/compiler_rt/fixunshfti.zig deleted-11| ... | ... | @@ -1,11 +0,0 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const intFromFloat = @import("./int_from_float.zig").intFromFloat; | |
| 3 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 4 | ||
| 5 | comptime { | |
| 6 | symbol(&__fixunshfti, "__fixunshfti"); | |
| 7 | } | |
| 8 | ||
| 9 | pub fn __fixunshfti(a: f16) callconv(.c) u128 { | |
| 10 | return intFromFloat(u128, a); | |
| 11 | } |
lib/compiler_rt/fixunssfdi.zig deleted-23| ... | ... | @@ -1,23 +0,0 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 3 | const symbol = compiler_rt.symbol; | |
| 4 | const intFromFloat = @import("./int_from_float.zig").intFromFloat; | |
| 5 | ||
| 6 | comptime { | |
| 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 | ||
| 17 | pub fn __fixunssfdi(a: f32) callconv(.c) u64 { | |
| 18 | return intFromFloat(u64, a); | |
| 19 | } | |
| 20 | ||
| 21 | fn __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 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | ||
| 3 | const std = @import("std"); | |
| 4 | ||
| 5 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 6 | const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat; | |
| 7 | ||
| 8 | comptime { | |
| 9 | symbol(&__fixunssfei, "__fixunssfei"); | |
| 10 | } | |
| 11 | ||
| 12 | pub 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 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = compiler_rt.symbol; | |
| 3 | const intFromFloat = @import("./int_from_float.zig").intFromFloat; | |
| 4 | ||
| 5 | comptime { | |
| 6 | if (compiler_rt.want_aeabi) { | |
| 7 | symbol(&__aeabi_f2uiz, "__aeabi_f2uiz"); | |
| 8 | } else { | |
| 9 | symbol(&__fixunssfsi, "__fixunssfsi"); | |
| 10 | } | |
| 11 | } | |
| 12 | ||
| 13 | pub fn __fixunssfsi(a: f32) callconv(.c) u32 { | |
| 14 | return intFromFloat(u32, a); | |
| 15 | } | |
| 16 | ||
| 17 | fn __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 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 3 | const intFromFloat = @import("./int_from_float.zig").intFromFloat; | |
| 4 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 5 | ||
| 6 | comptime { | |
| 7 | symbol(&__fixunssfti, "__fixunssfti"); | |
| 8 | } | |
| 9 | ||
| 10 | pub fn __fixunssfti(a: f32) callconv(.c) u128 { | |
| 11 | return intFromFloat(u128, a); | |
| 12 | } |
lib/compiler_rt/fixunstfdi.zig deleted-22| ... | ... | @@ -1,22 +0,0 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = compiler_rt.symbol; | |
| 3 | const intFromFloat = @import("./int_from_float.zig").intFromFloat; | |
| 4 | ||
| 5 | comptime { | |
| 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 | ||
| 16 | pub fn __fixunstfdi(a: f128) callconv(.c) u64 { | |
| 17 | return intFromFloat(u64, a); | |
| 18 | } | |
| 19 | ||
| 20 | fn _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 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | ||
| 3 | const std = @import("std"); | |
| 4 | ||
| 5 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 6 | const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat; | |
| 7 | ||
| 8 | comptime { | |
| 9 | symbol(&__fixunstfei, "__fixunstfei"); | |
| 10 | } | |
| 11 | ||
| 12 | pub 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 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = compiler_rt.symbol; | |
| 3 | const intFromFloat = @import("./int_from_float.zig").intFromFloat; | |
| 4 | ||
| 5 | comptime { | |
| 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 | ||
| 16 | pub fn __fixunstfsi(a: f128) callconv(.c) u32 { | |
| 17 | return intFromFloat(u32, a); | |
| 18 | } | |
| 19 | ||
| 20 | fn _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 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 3 | const symbol = compiler_rt.symbol; | |
| 4 | const intFromFloat = @import("./int_from_float.zig").intFromFloat; | |
| 5 | ||
| 6 | comptime { | |
| 7 | if (compiler_rt.want_ppc_abi) | |
| 8 | symbol(&__fixunstfti, "__fixunskfti"); | |
| 9 | symbol(&__fixunstfti, "__fixunstfti"); | |
| 10 | } | |
| 11 | ||
| 12 | pub fn __fixunstfti(a: f128) callconv(.c) u128 { | |
| 13 | return intFromFloat(u128, a); | |
| 14 | } |
lib/compiler_rt/fixunsxfdi.zig deleted-10| ... | ... | @@ -1,10 +0,0 @@ |
| 1 | const intFromFloat = @import("./int_from_float.zig").intFromFloat; | |
| 2 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 3 | ||
| 4 | comptime { | |
| 5 | symbol(&__fixunsxfdi, "__fixunsxfdi"); | |
| 6 | } | |
| 7 | ||
| 8 | fn __fixunsxfdi(a: f80) callconv(.c) u64 { | |
| 9 | return intFromFloat(u64, a); | |
| 10 | } |
lib/compiler_rt/fixunsxfei.zig deleted-13| ... | ... | @@ -1,13 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | const builtin = @import("builtin"); | |
| 3 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 4 | const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat; | |
| 5 | ||
| 6 | comptime { | |
| 7 | symbol(&__fixunsxfei, "__fixunsxfei"); | |
| 8 | } | |
| 9 | ||
| 10 | pub 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 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = compiler_rt.symbol; | |
| 3 | const intFromFloat = @import("./int_from_float.zig").intFromFloat; | |
| 4 | ||
| 5 | comptime { | |
| 6 | symbol(&__fixunsxfsi, "__fixunsxfsi"); | |
| 7 | } | |
| 8 | ||
| 9 | fn __fixunsxfsi(a: f80) callconv(.c) u32 { | |
| 10 | return intFromFloat(u32, a); | |
| 11 | } |
lib/compiler_rt/fixunsxfti.zig deleted-12| ... | ... | @@ -1,12 +0,0 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 3 | const symbol = compiler_rt.symbol; | |
| 4 | const intFromFloat = @import("./int_from_float.zig").intFromFloat; | |
| 5 | ||
| 6 | comptime { | |
| 7 | symbol(&__fixunsxfti, "__fixunsxfti"); | |
| 8 | } | |
| 9 | ||
| 10 | pub fn __fixunsxfti(a: f80) callconv(.c) u128 { | |
| 11 | return intFromFloat(u128, a); | |
| 12 | } |
lib/compiler_rt/fixxfdi.zig deleted-10| ... | ... | @@ -1,10 +0,0 @@ |
| 1 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 2 | const intFromFloat = @import("./int_from_float.zig").intFromFloat; | |
| 3 | ||
| 4 | comptime { | |
| 5 | symbol(&__fixxfdi, "__fixxfdi"); | |
| 6 | } | |
| 7 | ||
| 8 | fn __fixxfdi(a: f80) callconv(.c) i64 { | |
| 9 | return intFromFloat(i64, a); | |
| 10 | } |
lib/compiler_rt/fixxfei.zig deleted-14| ... | ... | @@ -1,14 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | const builtin = @import("builtin"); | |
| 3 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 4 | const symbol = compiler_rt.symbol; | |
| 5 | const bigIntFromFloat = @import("int_from_float.zig").bigIntFromFloat; | |
| 6 | ||
| 7 | comptime { | |
| 8 | symbol(&__fixxfei, "__fixxfei"); | |
| 9 | } | |
| 10 | ||
| 11 | pub 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 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = compiler_rt.symbol; | |
| 3 | const intFromFloat = @import("./int_from_float.zig").intFromFloat; | |
| 4 | ||
| 5 | comptime { | |
| 6 | symbol(&__fixxfsi, "__fixxfsi"); | |
| 7 | } | |
| 8 | ||
| 9 | fn __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 | const builtin = @import("builtin"); | |
| 1 | 2 | const std = @import("std"); |
| 2 | 3 | const math = std.math; |
| 3 | 4 | |
| 4 | pub fn floatFromInt(comptime T: type, x: anytype) T { | |
| 5 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 6 | const symbol = compiler_rt.symbol; | |
| 7 | ||
| 8 | comptime { | |
| 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 | ||
| 67 | fn __floatsihf(a: i32) callconv(.c) compiler_rt.f16.Abi { | |
| 68 | return compiler_rt.f16.toAbi(f16_floatFromInt_i32(a)); | |
| 69 | } | |
| 70 | pub fn f16_floatFromInt_i32(a: i32) f16 { | |
| 71 | return floatFromInt(f16, a); | |
| 72 | } | |
| 73 | ||
| 74 | fn __floatdihf(a: i64) callconv(.c) compiler_rt.f16.Abi { | |
| 75 | return compiler_rt.f16.toAbi(f16_floatFromInt_i64(a)); | |
| 76 | } | |
| 77 | pub fn f16_floatFromInt_i64(a: i64) f16 { | |
| 78 | return floatFromInt(f16, a); | |
| 79 | } | |
| 80 | ||
| 81 | fn __floattihf(a: i128) callconv(.c) compiler_rt.f16.Abi { | |
| 82 | return compiler_rt.f16.toAbi(f16_floatFromInt_i128(a)); | |
| 83 | } | |
| 84 | pub fn f16_floatFromInt_i128(a: i128) f16 { | |
| 85 | return floatFromInt(f16, a); | |
| 86 | } | |
| 87 | ||
| 88 | fn __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 | } | |
| 92 | pub fn f16_floatFromInt_signed(a: []const u8) f16 { | |
| 93 | return floatFromBigInt(f16, .signed, @ptrCast(@alignCast(a))); | |
| 94 | } | |
| 95 | ||
| 96 | fn __floatsisf(a: i32) callconv(.c) compiler_rt.f32.Abi { | |
| 97 | return compiler_rt.f32.toAbi(f32_floatFromInt_i32(a)); | |
| 98 | } | |
| 99 | fn __aeabi_i2f(a: i32) callconv(.{ .arm_aapcs = .{} }) f32 { | |
| 100 | return f32_floatFromInt_i32(a); | |
| 101 | } | |
| 102 | pub fn f32_floatFromInt_i32(a: i32) f32 { | |
| 103 | return floatFromInt(f32, a); | |
| 104 | } | |
| 105 | ||
| 106 | fn __floatdisf(a: i64) callconv(.c) compiler_rt.f32.Abi { | |
| 107 | return compiler_rt.f32.toAbi(f32_floatFromInt_i64(a)); | |
| 108 | } | |
| 109 | fn __aeabi_l2f(a: i64) callconv(.{ .arm_aapcs = .{} }) f32 { | |
| 110 | return f32_floatFromInt_i64(a); | |
| 111 | } | |
| 112 | pub fn f32_floatFromInt_i64(a: i64) f32 { | |
| 113 | return floatFromInt(f32, a); | |
| 114 | } | |
| 115 | ||
| 116 | fn __floattisf(a: i128) callconv(.c) compiler_rt.f32.Abi { | |
| 117 | return compiler_rt.f32.toAbi(f32_floatFromInt_i128(a)); | |
| 118 | } | |
| 119 | pub fn f32_floatFromInt_i128(a: i128) f32 { | |
| 120 | return floatFromInt(f32, a); | |
| 121 | } | |
| 122 | ||
| 123 | fn __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 | } | |
| 127 | pub fn f32_floatFromInt_signed(a: []const u8) f32 { | |
| 128 | return floatFromBigInt(f32, .signed, @ptrCast(@alignCast(a))); | |
| 129 | } | |
| 130 | ||
| 131 | fn __floatsidf(a: i32) callconv(.c) compiler_rt.f64.Abi { | |
| 132 | return compiler_rt.f64.toAbi(f64_floatFromInt_i32(a)); | |
| 133 | } | |
| 134 | fn __aeabi_i2d(a: i32) callconv(.{ .arm_aapcs = .{} }) f64 { | |
| 135 | return f64_floatFromInt_i32(a); | |
| 136 | } | |
| 137 | pub fn f64_floatFromInt_i32(a: i32) f64 { | |
| 138 | return floatFromInt(f64, a); | |
| 139 | } | |
| 140 | ||
| 141 | fn __floatdidf(a: i64) callconv(.c) compiler_rt.f64.Abi { | |
| 142 | return compiler_rt.f64.toAbi(f64_floatFromInt_i64(a)); | |
| 143 | } | |
| 144 | fn __aeabi_l2d(a: i64) callconv(.{ .arm_aapcs = .{} }) f64 { | |
| 145 | return f64_floatFromInt_i64(a); | |
| 146 | } | |
| 147 | pub fn f64_floatFromInt_i64(a: i64) f64 { | |
| 148 | return floatFromInt(f64, a); | |
| 149 | } | |
| 150 | ||
| 151 | fn __floattidf(a: i128) callconv(.c) compiler_rt.f64.Abi { | |
| 152 | return compiler_rt.f64.toAbi(f64_floatFromInt_i128(a)); | |
| 153 | } | |
| 154 | pub fn f64_floatFromInt_i128(a: i128) f64 { | |
| 155 | return floatFromInt(f64, a); | |
| 156 | } | |
| 157 | ||
| 158 | fn __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 | } | |
| 162 | pub fn f64_floatFromInt_signed(a: []const u8) f64 { | |
| 163 | return floatFromBigInt(f64, .signed, @ptrCast(@alignCast(a))); | |
| 164 | } | |
| 165 | ||
| 166 | fn __floatsixf(a: i32) callconv(.c) compiler_rt.f80.Abi { | |
| 167 | return compiler_rt.f80.toAbi(f80_floatFromInt_i32(a)); | |
| 168 | } | |
| 169 | pub fn f80_floatFromInt_i32(a: i32) f80 { | |
| 170 | return floatFromInt(f80, a); | |
| 171 | } | |
| 172 | ||
| 173 | fn __floatdixf(a: i64) callconv(.c) compiler_rt.f80.Abi { | |
| 174 | return compiler_rt.f80.toAbi(f80_floatFromInt_i64(a)); | |
| 175 | } | |
| 176 | pub fn f80_floatFromInt_i64(a: i64) f80 { | |
| 177 | return floatFromInt(f80, a); | |
| 178 | } | |
| 179 | ||
| 180 | fn __floattixf(a: i128) callconv(.c) compiler_rt.f80.Abi { | |
| 181 | return compiler_rt.f80.toAbi(f80_floatFromInt_i128(a)); | |
| 182 | } | |
| 183 | pub fn f80_floatFromInt_i128(a: i128) f80 { | |
| 184 | return floatFromInt(f80, a); | |
| 185 | } | |
| 186 | ||
| 187 | fn __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 | } | |
| 191 | pub fn f80_floatFromInt_signed(a: []const u8) f80 { | |
| 192 | return floatFromBigInt(f80, .signed, @ptrCast(@alignCast(a))); | |
| 193 | } | |
| 194 | ||
| 195 | fn __floatsitf(a: i32) callconv(.c) compiler_rt.f128.Abi { | |
| 196 | return compiler_rt.f128.toAbi(f128_floatFromInt_i32(a)); | |
| 197 | } | |
| 198 | fn _Qp_itoq(c: *f128, a: i32) callconv(.c) void { | |
| 199 | c.* = f128_floatFromInt_i32(a); | |
| 200 | } | |
| 201 | pub fn f128_floatFromInt_i32(a: i32) f128 { | |
| 202 | return floatFromInt(f128, a); | |
| 203 | } | |
| 204 | ||
| 205 | fn __floatditf(a: i64) callconv(.c) compiler_rt.f128.Abi { | |
| 206 | return compiler_rt.f128.toAbi(f128_floatFromInt_i64(a)); | |
| 207 | } | |
| 208 | fn _Qp_xtoq(c: *f128, a: i64) callconv(.c) void { | |
| 209 | c.* = f128_floatFromInt_i64(a); | |
| 210 | } | |
| 211 | pub fn f128_floatFromInt_i64(a: i64) f128 { | |
| 212 | return floatFromInt(f128, a); | |
| 213 | } | |
| 214 | ||
| 215 | fn __floattitf(a: i128) callconv(.c) compiler_rt.f128.Abi { | |
| 216 | return compiler_rt.f128.toAbi(f128_floatFromInt_i128(a)); | |
| 217 | } | |
| 218 | fn __floattitf_x86(a: f128) callconv(.c) compiler_rt.f128.Abi { | |
| 219 | return compiler_rt.f128.toAbi(f128_floatFromInt_i128(@bitCast(a))); | |
| 220 | } | |
| 221 | pub fn f128_floatFromInt_i128(a: i128) f128 { | |
| 222 | return floatFromInt(f128, a); | |
| 223 | } | |
| 224 | ||
| 225 | fn __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 | } | |
| 229 | pub fn f128_floatFromInt_signed(a: []const u8) f128 { | |
| 230 | return floatFromBigInt(f128, .signed, @ptrCast(@alignCast(a))); | |
| 231 | } | |
| 232 | ||
| 233 | comptime { | |
| 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 | ||
| 301 | fn __floatunsihf(a: u32) callconv(.c) compiler_rt.f16.Abi { | |
| 302 | return compiler_rt.f16.toAbi(f16_floatFromInt_u32(a)); | |
| 303 | } | |
| 304 | pub fn f16_floatFromInt_u32(a: u32) f16 { | |
| 305 | return floatFromInt(f16, a); | |
| 306 | } | |
| 307 | ||
| 308 | fn __floatundihf(a: u64) callconv(.c) compiler_rt.f16.Abi { | |
| 309 | return compiler_rt.f16.toAbi(f16_floatFromInt_u64(a)); | |
| 310 | } | |
| 311 | pub fn f16_floatFromInt_u64(a: u64) f16 { | |
| 312 | return floatFromInt(f16, a); | |
| 313 | } | |
| 314 | ||
| 315 | fn __floatuntihf(a: u128) callconv(.c) compiler_rt.f16.Abi { | |
| 316 | return compiler_rt.f16.toAbi(f16_floatFromInt_u128(a)); | |
| 317 | } | |
| 318 | pub fn f16_floatFromInt_u128(a: u128) f16 { | |
| 319 | return floatFromInt(f16, a); | |
| 320 | } | |
| 321 | ||
| 322 | fn __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 | } | |
| 326 | pub fn f16_floatFromInt_unsigned(a: []const u8) f16 { | |
| 327 | return floatFromBigInt(f16, .unsigned, @ptrCast(@alignCast(a))); | |
| 328 | } | |
| 329 | ||
| 330 | fn __floatunsisf(a: u32) callconv(.c) compiler_rt.f32.Abi { | |
| 331 | return compiler_rt.f32.toAbi(f32_floatFromInt_u32(a)); | |
| 332 | } | |
| 333 | fn __aeabi_ui2f(a: u32) callconv(.{ .arm_aapcs = .{} }) f32 { | |
| 334 | return f32_floatFromInt_u32(a); | |
| 335 | } | |
| 336 | pub fn f32_floatFromInt_u32(a: u32) f32 { | |
| 337 | return floatFromInt(f32, a); | |
| 338 | } | |
| 339 | ||
| 340 | fn __floatundisf(a: u64) callconv(.c) compiler_rt.f32.Abi { | |
| 341 | return compiler_rt.f32.toAbi(f32_floatFromInt_u64(a)); | |
| 342 | } | |
| 343 | fn __aeabi_ul2f(a: u64) callconv(.{ .arm_aapcs = .{} }) f32 { | |
| 344 | return f32_floatFromInt_u64(a); | |
| 345 | } | |
| 346 | pub fn f32_floatFromInt_u64(a: u64) f32 { | |
| 347 | return floatFromInt(f32, a); | |
| 348 | } | |
| 349 | ||
| 350 | fn __floatuntisf(a: u128) callconv(.c) compiler_rt.f32.Abi { | |
| 351 | return compiler_rt.f32.toAbi(f32_floatFromInt_u128(a)); | |
| 352 | } | |
| 353 | pub fn f32_floatFromInt_u128(a: u128) f32 { | |
| 354 | return floatFromInt(f32, a); | |
| 355 | } | |
| 356 | ||
| 357 | fn __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 | } | |
| 361 | pub fn f32_floatFromInt_unsigned(a: []const u8) f32 { | |
| 362 | return floatFromBigInt(f32, .unsigned, @ptrCast(@alignCast(a))); | |
| 363 | } | |
| 364 | ||
| 365 | fn __floatunsidf(a: u32) callconv(.c) compiler_rt.f64.Abi { | |
| 366 | return compiler_rt.f64.toAbi(f64_floatFromInt_u32(a)); | |
| 367 | } | |
| 368 | fn __aeabi_ui2d(a: u32) callconv(.{ .arm_aapcs = .{} }) f64 { | |
| 369 | return f64_floatFromInt_u32(a); | |
| 370 | } | |
| 371 | pub fn f64_floatFromInt_u32(a: u32) f64 { | |
| 372 | return floatFromInt(f64, a); | |
| 373 | } | |
| 374 | ||
| 375 | fn __floatundidf(a: u64) callconv(.c) compiler_rt.f64.Abi { | |
| 376 | return compiler_rt.f64.toAbi(f64_floatFromInt_u64(a)); | |
| 377 | } | |
| 378 | fn __aeabi_ul2d(a: u64) callconv(.{ .arm_aapcs = .{} }) f64 { | |
| 379 | return f64_floatFromInt_u64(a); | |
| 380 | } | |
| 381 | pub fn f64_floatFromInt_u64(a: u64) f64 { | |
| 382 | return floatFromInt(f64, a); | |
| 383 | } | |
| 384 | ||
| 385 | fn __floatuntidf(a: u128) callconv(.c) compiler_rt.f64.Abi { | |
| 386 | return compiler_rt.f64.toAbi(f64_floatFromInt_u128(a)); | |
| 387 | } | |
| 388 | pub fn f64_floatFromInt_u128(a: u128) f64 { | |
| 389 | return floatFromInt(f64, a); | |
| 390 | } | |
| 391 | ||
| 392 | fn __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 | } | |
| 396 | pub fn f64_floatFromInt_unsigned(a: []const u8) f64 { | |
| 397 | return floatFromBigInt(f64, .unsigned, @ptrCast(@alignCast(a))); | |
| 398 | } | |
| 399 | ||
| 400 | fn __floatunsixf(a: u32) callconv(.c) compiler_rt.f80.Abi { | |
| 401 | return compiler_rt.f80.toAbi(f80_floatFromInt_u32(a)); | |
| 402 | } | |
| 403 | pub fn f80_floatFromInt_u32(a: u32) f80 { | |
| 404 | return floatFromInt(f80, a); | |
| 405 | } | |
| 406 | ||
| 407 | fn __floatundixf(a: u64) callconv(.c) compiler_rt.f80.Abi { | |
| 408 | return compiler_rt.f80.toAbi(f80_floatFromInt_u64(a)); | |
| 409 | } | |
| 410 | pub fn f80_floatFromInt_u64(a: u64) f80 { | |
| 411 | return floatFromInt(f80, a); | |
| 412 | } | |
| 413 | ||
| 414 | fn __floatuntixf(a: u128) callconv(.c) compiler_rt.f80.Abi { | |
| 415 | return compiler_rt.f80.toAbi(f80_floatFromInt_u128(a)); | |
| 416 | } | |
| 417 | pub fn f80_floatFromInt_u128(a: u128) f80 { | |
| 418 | return floatFromInt(f80, a); | |
| 419 | } | |
| 420 | ||
| 421 | fn __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 | } | |
| 425 | pub fn f80_floatFromInt_unsigned(a: []const u8) f80 { | |
| 426 | return floatFromBigInt(f80, .unsigned, @ptrCast(@alignCast(a))); | |
| 427 | } | |
| 428 | ||
| 429 | fn __floatunsitf(a: u32) callconv(.c) compiler_rt.f128.Abi { | |
| 430 | return compiler_rt.f128.toAbi(f128_floatFromInt_u32(a)); | |
| 431 | } | |
| 432 | fn _Qp_uitoq(c: *f128, a: u32) callconv(.c) void { | |
| 433 | c.* = f128_floatFromInt_u32(a); | |
| 434 | } | |
| 435 | pub fn f128_floatFromInt_u32(a: u32) f128 { | |
| 436 | return floatFromInt(f128, a); | |
| 437 | } | |
| 438 | ||
| 439 | fn __floatunditf(a: u64) callconv(.c) compiler_rt.f128.Abi { | |
| 440 | return compiler_rt.f128.toAbi(f128_floatFromInt_u64(a)); | |
| 441 | } | |
| 442 | fn _Qp_uxtoq(c: *f128, a: u64) callconv(.c) void { | |
| 443 | c.* = f128_floatFromInt_u64(a); | |
| 444 | } | |
| 445 | pub fn f128_floatFromInt_u64(a: u64) f128 { | |
| 446 | return floatFromInt(f128, a); | |
| 447 | } | |
| 448 | ||
| 449 | fn __floatuntitf(a: u128) callconv(.c) compiler_rt.f128.Abi { | |
| 450 | return compiler_rt.f128.toAbi(f128_floatFromInt_u128(a)); | |
| 451 | } | |
| 452 | fn __floatuntitf_x86(a: f128) callconv(.c) compiler_rt.f128.Abi { | |
| 453 | return compiler_rt.f128.toAbi(f128_floatFromInt_u128(@bitCast(a))); | |
| 454 | } | |
| 455 | fn __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 | } | |
| 460 | pub fn f128_floatFromInt_u128(a: u128) f128 { | |
| 461 | return floatFromInt(f128, a); | |
| 462 | } | |
| 463 | ||
| 464 | fn __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 | } | |
| 468 | pub fn f128_floatFromInt_unsigned(a: []const u8) f128 { | |
| 469 | return floatFromBigInt(f128, .unsigned, @ptrCast(@alignCast(a))); | |
| 470 | } | |
| 471 | ||
| 472 | inline fn floatFromInt(comptime T: type, x: anytype) T { | |
| 5 | 473 | if (x == 0) return 0; |
| 6 | 474 | |
| 7 | 475 | // Various constants whose values follow from the type parameters. |
| ... | ... | @@ -53,7 +521,7 @@ pub fn floatFromInt(comptime T: type, x: anytype) T { |
| 53 | 521 | return @bitCast(sign_bit | result); |
| 54 | 522 | } |
| 55 | 523 | |
| 56 | const endian = @import("builtin").cpu.arch.endian(); | |
| 524 | const endian = builtin.cpu.arch.endian(); | |
| 57 | 525 | inline fn limb(limbs: []const u32, index: usize) u32 { |
| 58 | 526 | return switch (endian) { |
| 59 | 527 | .little => limbs[index], |
| ... | ... | @@ -61,11 +529,11 @@ inline fn limb(limbs: []const u32, index: usize) u32 { |
| 61 | 529 | }; |
| 62 | 530 | } |
| 63 | 531 | |
| 64 | pub inline fn floatFromBigInt(comptime T: type, comptime signedness: std.builtin.Signedness, x: []const u32) T { | |
| 532 | inline fn floatFromBigInt(comptime T: type, comptime signedness: std.lang.Signedness, x: []const u32) T { | |
| 65 | 533 | switch (x.len) { |
| 66 | 534 | 0 => return 0, |
| 67 | 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 | 537 | .little => x[0..limbs_len].*, |
| 70 | 538 | .big => switch (limbs_len) { |
| 71 | 539 | 1 => .{x[0]}, |
lib/compiler_rt/float_from_int_test.zig+757-733| ... | ... | @@ -2,571 +2,593 @@ const std = @import("std"); |
| 2 | 2 | const testing = std.testing; |
| 3 | 3 | const math = std.math; |
| 4 | 4 | |
| 5 | const __floatunsihf = @import("floatunsihf.zig").__floatunsihf; | |
| 6 | ||
| 7 | // Conversion to f32 | |
| 8 | const __floatsisf = @import("floatsisf.zig").__floatsisf; | |
| 9 | const __floatunsisf = @import("floatunsisf.zig").__floatunsisf; | |
| 10 | const __floatdisf = @import("floatdisf.zig").__floatdisf; | |
| 11 | const __floatundisf = @import("floatundisf.zig").__floatundisf; | |
| 12 | const __floattisf = @import("floattisf.zig").__floattisf; | |
| 13 | const __floatuntisf = @import("floatuntisf.zig").__floatuntisf; | |
| 14 | const __floateisf = @import("floateisf.zig").__floateisf; | |
| 15 | const __floatuneisf = @import("floatuneisf.zig").__floatuneisf; | |
| 16 | ||
| 17 | // Conversion to f64 | |
| 18 | const __floatsidf = @import("floatsidf.zig").__floatsidf; | |
| 19 | const __floatunsidf = @import("floatunsidf.zig").__floatunsidf; | |
| 20 | const __floatdidf = @import("floatdidf.zig").__floatdidf; | |
| 21 | const __floatundidf = @import("floatundidf.zig").__floatundidf; | |
| 22 | const __floattidf = @import("floattidf.zig").__floattidf; | |
| 23 | const __floatuntidf = @import("floatuntidf.zig").__floatuntidf; | |
| 24 | ||
| 25 | // Conversion to f128 | |
| 26 | const __floatsitf = @import("floatsitf.zig").__floatsitf; | |
| 27 | const __floatunsitf = @import("floatunsitf.zig").__floatunsitf; | |
| 28 | const __floatditf = @import("floatditf.zig").__floatditf; | |
| 29 | const __floatunditf = @import("floatunditf.zig").__floatunditf; | |
| 30 | const __floattitf = @import("floattitf.zig").__floattitf; | |
| 31 | const __floatuntitf = @import("floatuntitf.zig").__floatuntitf; | |
| 32 | ||
| 33 | fn test__floatsisf(a: i32, expected: u32) !void { | |
| 34 | const r = __floatsisf(a); | |
| 5 | const impl = @import("float_from_int.zig"); | |
| 6 | ||
| 7 | const f16_floatFromInt_i32 = impl.f16_floatFromInt_i32; | |
| 8 | const f16_floatFromInt_u32 = impl.f16_floatFromInt_u32; | |
| 9 | const f16_floatFromInt_i64 = impl.f16_floatFromInt_i64; | |
| 10 | const f16_floatFromInt_u64 = impl.f16_floatFromInt_u64; | |
| 11 | const f16_floatFromInt_i128 = impl.f16_floatFromInt_i128; | |
| 12 | const f16_floatFromInt_u128 = impl.f16_floatFromInt_u128; | |
| 13 | const f16_floatFromInt_signed = impl.f16_floatFromInt_signed; | |
| 14 | const f16_floatFromInt_unsigned = impl.f16_floatFromInt_unsigned; | |
| 15 | ||
| 16 | const f32_floatFromInt_i32 = impl.f32_floatFromInt_i32; | |
| 17 | const f32_floatFromInt_u32 = impl.f32_floatFromInt_u32; | |
| 18 | const f32_floatFromInt_i64 = impl.f32_floatFromInt_i64; | |
| 19 | const f32_floatFromInt_u64 = impl.f32_floatFromInt_u64; | |
| 20 | const f32_floatFromInt_i128 = impl.f32_floatFromInt_i128; | |
| 21 | const f32_floatFromInt_u128 = impl.f32_floatFromInt_u128; | |
| 22 | const f32_floatFromInt_signed = impl.f32_floatFromInt_signed; | |
| 23 | const f32_floatFromInt_unsigned = impl.f32_floatFromInt_unsigned; | |
| 24 | ||
| 25 | const f64_floatFromInt_i32 = impl.f64_floatFromInt_i32; | |
| 26 | const f64_floatFromInt_u32 = impl.f64_floatFromInt_u32; | |
| 27 | const f64_floatFromInt_i64 = impl.f64_floatFromInt_i64; | |
| 28 | const f64_floatFromInt_u64 = impl.f64_floatFromInt_u64; | |
| 29 | const f64_floatFromInt_i128 = impl.f64_floatFromInt_i128; | |
| 30 | const f64_floatFromInt_u128 = impl.f64_floatFromInt_u128; | |
| 31 | const f64_floatFromInt_signed = impl.f64_floatFromInt_signed; | |
| 32 | const f64_floatFromInt_unsigned = impl.f64_floatFromInt_unsigned; | |
| 33 | ||
| 34 | const f80_floatFromInt_i32 = impl.f80_floatFromInt_i32; | |
| 35 | const f80_floatFromInt_u32 = impl.f80_floatFromInt_u32; | |
| 36 | const f80_floatFromInt_i64 = impl.f80_floatFromInt_i64; | |
| 37 | const f80_floatFromInt_u64 = impl.f80_floatFromInt_u64; | |
| 38 | const f80_floatFromInt_i128 = impl.f80_floatFromInt_i128; | |
| 39 | const f80_floatFromInt_u128 = impl.f80_floatFromInt_u128; | |
| 40 | const f80_floatFromInt_signed = impl.f80_floatFromInt_signed; | |
| 41 | const f80_floatFromInt_unsigned = impl.f80_floatFromInt_unsigned; | |
| 42 | ||
| 43 | const f128_floatFromInt_i32 = impl.f128_floatFromInt_i32; | |
| 44 | const f128_floatFromInt_u32 = impl.f128_floatFromInt_u32; | |
| 45 | const f128_floatFromInt_i64 = impl.f128_floatFromInt_i64; | |
| 46 | const f128_floatFromInt_u64 = impl.f128_floatFromInt_u64; | |
| 47 | const f128_floatFromInt_i128 = impl.f128_floatFromInt_i128; | |
| 48 | const f128_floatFromInt_u128 = impl.f128_floatFromInt_u128; | |
| 49 | const f128_floatFromInt_signed = impl.f128_floatFromInt_signed; | |
| 50 | const f128_floatFromInt_unsigned = impl.f128_floatFromInt_unsigned; | |
| 51 | ||
| 52 | fn test_f32_floatFromInt_i32(a: i32, expected: u32) !void { | |
| 53 | const r = f32_floatFromInt_i32(a); | |
| 35 | 54 | try std.testing.expect(@as(u32, @bitCast(r)) == expected); |
| 36 | 55 | } |
| 37 | 56 | |
| 38 | fn test_one_floatunsisf(a: u32, expected: u32) !void { | |
| 39 | const r = __floatunsisf(a); | |
| 57 | fn test_f32_floatFromInt_u32(a: u32, expected: u32) !void { | |
| 58 | const r = f32_floatFromInt_u32(a); | |
| 40 | 59 | try std.testing.expect(@as(u32, @bitCast(r)) == expected); |
| 41 | 60 | } |
| 42 | 61 | |
| 43 | test "floatsisf" { | |
| 44 | try test__floatsisf(0, 0x00000000); | |
| 45 | try test__floatsisf(1, 0x3f800000); | |
| 46 | try test__floatsisf(-1, 0xbf800000); | |
| 47 | try test__floatsisf(0x7FFFFFFF, 0x4f000000); | |
| 48 | try test__floatsisf(@bitCast(@as(u32, @intCast(0x80000000))), 0xcf000000); | |
| 62 | test f32_floatFromInt_i32 { | |
| 63 | try test_f32_floatFromInt_i32(0, 0x00000000); | |
| 64 | try test_f32_floatFromInt_i32(1, 0x3f800000); | |
| 65 | try test_f32_floatFromInt_i32(-1, 0xbf800000); | |
| 66 | try test_f32_floatFromInt_i32(0x7FFFFFFF, 0x4f000000); | |
| 67 | try test_f32_floatFromInt_i32(@bitCast(@as(u32, @intCast(0x80000000))), 0xcf000000); | |
| 68 | ||
| 69 | try testing.expect(f32_floatFromInt_i32(math.minInt(i32)) == math.minInt(i32)); | |
| 49 | 70 | } |
| 50 | 71 | |
| 51 | test "floatunsisf" { | |
| 72 | test f32_floatFromInt_u32 { | |
| 52 | 73 | // Test the produced bit pattern |
| 53 | try test_one_floatunsisf(0, 0); | |
| 54 | try test_one_floatunsisf(1, 0x3f800000); | |
| 55 | try test_one_floatunsisf(0x7FFFFFFF, 0x4f000000); | |
| 56 | try test_one_floatunsisf(0x80000000, 0x4f000000); | |
| 57 | try test_one_floatunsisf(0xFFFFFFFF, 0x4f800000); | |
| 74 | try test_f32_floatFromInt_u32(0, 0); | |
| 75 | try test_f32_floatFromInt_u32(1, 0x3f800000); | |
| 76 | try test_f32_floatFromInt_u32(0x7FFFFFFF, 0x4f000000); | |
| 77 | try test_f32_floatFromInt_u32(0x80000000, 0x4f000000); | |
| 78 | try test_f32_floatFromInt_u32(0xFFFFFFFF, 0x4f800000); | |
| 79 | ||
| 80 | try testing.expect(f32_floatFromInt_u32(0) == 0.0); | |
| 81 | try testing.expect(f32_floatFromInt_u32(math.maxInt(u24)) == math.maxInt(u24)); | |
| 82 | try testing.expect(f32_floatFromInt_u32(math.maxInt(u24) + 1) == math.maxInt(u24) + 1); // 0x100_0000 - Exact | |
| 83 | try testing.expect(f32_floatFromInt_u32(math.maxInt(u24) + 2) == math.maxInt(u24) + 1); // 0x100_0001 - Tie: Rounds down to even | |
| 84 | try testing.expect(f32_floatFromInt_u32(math.maxInt(u24) + 3) == math.maxInt(u24) + 3); // 0x100_0002 - Exact | |
| 85 | try testing.expect(f32_floatFromInt_u32(math.maxInt(u24) + 4) == math.maxInt(u24) + 5); // 0x100_0003 - Tie: Rounds up to even | |
| 86 | try testing.expect(f32_floatFromInt_u32(math.maxInt(u24) + 5) == math.maxInt(u24) + 5); // 0x100_0004 - Exact | |
| 87 | try testing.expect(f32_floatFromInt_u32(math.maxInt(u32)) == math.maxInt(u32) + 1); | |
| 88 | } | |
| 89 | ||
| 90 | fn test_f32_floatFromInt_i64(a: i64, expected: f32) !void { | |
| 91 | const x = f32_floatFromInt_i64(a); | |
| 92 | try testing.expect(x == expected); | |
| 58 | 93 | } |
| 59 | 94 | |
| 60 | fn test__floatdisf(a: i64, expected: f32) !void { | |
| 61 | const x = __floatdisf(a); | |
| 95 | fn test_f32_floatFromInt_u64(a: u64, expected: f32) !void { | |
| 96 | const x = f32_floatFromInt_u64(a); | |
| 62 | 97 | try testing.expect(x == expected); |
| 63 | 98 | } |
| 64 | 99 | |
| 65 | fn test__floatundisf(a: u64, expected: f32) !void { | |
| 66 | try std.testing.expectEqual(expected, __floatundisf(a)); | |
| 67 | } | |
| 68 | ||
| 69 | test "floatdisf" { | |
| 70 | try test__floatdisf(0, 0.0); | |
| 71 | try test__floatdisf(1, 1.0); | |
| 72 | try test__floatdisf(2, 2.0); | |
| 73 | try test__floatdisf(-1, -1.0); | |
| 74 | try test__floatdisf(-2, -2.0); | |
| 75 | try test__floatdisf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); | |
| 76 | try test__floatdisf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); | |
| 77 | try test__floatdisf(@bitCast(@as(u64, 0x8000008000000000)), -0x1.FFFFFEp+62); | |
| 78 | try test__floatdisf(@bitCast(@as(u64, 0x8000010000000000)), -0x1.FFFFFCp+62); | |
| 79 | try test__floatdisf(@bitCast(@as(u64, 0x8000000000000000)), -0x1.000000p+63); | |
| 80 | try test__floatdisf(@bitCast(@as(u64, 0x8000000000000001)), -0x1.000000p+63); | |
| 81 | try test__floatdisf(0x0007FB72E8000000, 0x1.FEDCBAp+50); | |
| 82 | try test__floatdisf(0x0007FB72EA000000, 0x1.FEDCBAp+50); | |
| 83 | try test__floatdisf(0x0007FB72EB000000, 0x1.FEDCBAp+50); | |
| 84 | try test__floatdisf(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50); | |
| 85 | try test__floatdisf(0x0007FB72EC000000, 0x1.FEDCBCp+50); | |
| 86 | try test__floatdisf(0x0007FB72E8000001, 0x1.FEDCBAp+50); | |
| 87 | try test__floatdisf(0x0007FB72E6000000, 0x1.FEDCBAp+50); | |
| 88 | try test__floatdisf(0x0007FB72E7000000, 0x1.FEDCBAp+50); | |
| 89 | try test__floatdisf(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50); | |
| 90 | try test__floatdisf(0x0007FB72E4000001, 0x1.FEDCBAp+50); | |
| 91 | try test__floatdisf(0x0007FB72E4000000, 0x1.FEDCB8p+50); | |
| 92 | } | |
| 93 | ||
| 94 | test "floatundisf" { | |
| 95 | try test__floatundisf(0, 0.0); | |
| 96 | try test__floatundisf(1, 1.0); | |
| 97 | try test__floatundisf(2, 2.0); | |
| 98 | try test__floatundisf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); | |
| 99 | try test__floatundisf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); | |
| 100 | try test__floatundisf(0x8000008000000000, 0x1p+63); | |
| 101 | try test__floatundisf(0x8000010000000000, 0x1.000002p+63); | |
| 102 | try test__floatundisf(0x8000000000000000, 0x1p+63); | |
| 103 | try test__floatundisf(0x8000000000000001, 0x1p+63); | |
| 104 | try test__floatundisf(0xFFFFFFFFFFFFFFFE, 0x1p+64); | |
| 105 | try test__floatundisf(0xFFFFFFFFFFFFFFFF, 0x1p+64); | |
| 106 | try test__floatundisf(0x0007FB72E8000000, 0x1.FEDCBAp+50); | |
| 107 | try test__floatundisf(0x0007FB72EA000000, 0x1.FEDCBAp+50); | |
| 108 | try test__floatundisf(0x0007FB72EB000000, 0x1.FEDCBAp+50); | |
| 109 | try test__floatundisf(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50); | |
| 110 | try test__floatundisf(0x0007FB72EC000000, 0x1.FEDCBCp+50); | |
| 111 | try test__floatundisf(0x0007FB72E8000001, 0x1.FEDCBAp+50); | |
| 112 | try test__floatundisf(0x0007FB72E6000000, 0x1.FEDCBAp+50); | |
| 113 | try test__floatundisf(0x0007FB72E7000000, 0x1.FEDCBAp+50); | |
| 114 | try test__floatundisf(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50); | |
| 115 | try test__floatundisf(0x0007FB72E4000001, 0x1.FEDCBAp+50); | |
| 116 | try test__floatundisf(0x0007FB72E4000000, 0x1.FEDCB8p+50); | |
| 117 | } | |
| 118 | ||
| 119 | fn test__floattisf(a: i128, expected: f32) !void { | |
| 120 | const x = __floattisf(a); | |
| 100 | test f32_floatFromInt_i64 { | |
| 101 | try test_f32_floatFromInt_i64(0, 0.0); | |
| 102 | try test_f32_floatFromInt_i64(1, 1.0); | |
| 103 | try test_f32_floatFromInt_i64(2, 2.0); | |
| 104 | try test_f32_floatFromInt_i64(-1, -1.0); | |
| 105 | try test_f32_floatFromInt_i64(-2, -2.0); | |
| 106 | try test_f32_floatFromInt_i64(0x7FFFFF8000000000, 0x1.FFFFFEp+62); | |
| 107 | try test_f32_floatFromInt_i64(0x7FFFFF0000000000, 0x1.FFFFFCp+62); | |
| 108 | try test_f32_floatFromInt_i64(@bitCast(@as(u64, 0x8000008000000000)), -0x1.FFFFFEp+62); | |
| 109 | try test_f32_floatFromInt_i64(@bitCast(@as(u64, 0x8000010000000000)), -0x1.FFFFFCp+62); | |
| 110 | try test_f32_floatFromInt_i64(@bitCast(@as(u64, 0x8000000000000000)), -0x1.000000p+63); | |
| 111 | try test_f32_floatFromInt_i64(@bitCast(@as(u64, 0x8000000000000001)), -0x1.000000p+63); | |
| 112 | try test_f32_floatFromInt_i64(0x0007FB72E8000000, 0x1.FEDCBAp+50); | |
| 113 | try test_f32_floatFromInt_i64(0x0007FB72EA000000, 0x1.FEDCBAp+50); | |
| 114 | try test_f32_floatFromInt_i64(0x0007FB72EB000000, 0x1.FEDCBAp+50); | |
| 115 | try test_f32_floatFromInt_i64(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50); | |
| 116 | try test_f32_floatFromInt_i64(0x0007FB72EC000000, 0x1.FEDCBCp+50); | |
| 117 | try test_f32_floatFromInt_i64(0x0007FB72E8000001, 0x1.FEDCBAp+50); | |
| 118 | try test_f32_floatFromInt_i64(0x0007FB72E6000000, 0x1.FEDCBAp+50); | |
| 119 | try test_f32_floatFromInt_i64(0x0007FB72E7000000, 0x1.FEDCBAp+50); | |
| 120 | try test_f32_floatFromInt_i64(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50); | |
| 121 | try test_f32_floatFromInt_i64(0x0007FB72E4000001, 0x1.FEDCBAp+50); | |
| 122 | try test_f32_floatFromInt_i64(0x0007FB72E4000000, 0x1.FEDCB8p+50); | |
| 123 | } | |
| 124 | ||
| 125 | test f32_floatFromInt_u64 { | |
| 126 | try test_f32_floatFromInt_u64(0, 0.0); | |
| 127 | try test_f32_floatFromInt_u64(1, 1.0); | |
| 128 | try test_f32_floatFromInt_u64(2, 2.0); | |
| 129 | try test_f32_floatFromInt_u64(0x7FFFFF8000000000, 0x1.FFFFFEp+62); | |
| 130 | try test_f32_floatFromInt_u64(0x7FFFFF0000000000, 0x1.FFFFFCp+62); | |
| 131 | try test_f32_floatFromInt_u64(0x8000008000000000, 0x1p+63); | |
| 132 | try test_f32_floatFromInt_u64(0x8000010000000000, 0x1.000002p+63); | |
| 133 | try test_f32_floatFromInt_u64(0x8000000000000000, 0x1p+63); | |
| 134 | try test_f32_floatFromInt_u64(0x8000000000000001, 0x1p+63); | |
| 135 | try test_f32_floatFromInt_u64(0xFFFFFFFFFFFFFFFE, 0x1p+64); | |
| 136 | try test_f32_floatFromInt_u64(0xFFFFFFFFFFFFFFFF, 0x1p+64); | |
| 137 | try test_f32_floatFromInt_u64(0x0007FB72E8000000, 0x1.FEDCBAp+50); | |
| 138 | try test_f32_floatFromInt_u64(0x0007FB72EA000000, 0x1.FEDCBAp+50); | |
| 139 | try test_f32_floatFromInt_u64(0x0007FB72EB000000, 0x1.FEDCBAp+50); | |
| 140 | try test_f32_floatFromInt_u64(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50); | |
| 141 | try test_f32_floatFromInt_u64(0x0007FB72EC000000, 0x1.FEDCBCp+50); | |
| 142 | try test_f32_floatFromInt_u64(0x0007FB72E8000001, 0x1.FEDCBAp+50); | |
| 143 | try test_f32_floatFromInt_u64(0x0007FB72E6000000, 0x1.FEDCBAp+50); | |
| 144 | try test_f32_floatFromInt_u64(0x0007FB72E7000000, 0x1.FEDCBAp+50); | |
| 145 | try test_f32_floatFromInt_u64(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50); | |
| 146 | try test_f32_floatFromInt_u64(0x0007FB72E4000001, 0x1.FEDCBAp+50); | |
| 147 | try test_f32_floatFromInt_u64(0x0007FB72E4000000, 0x1.FEDCB8p+50); | |
| 148 | } | |
| 149 | ||
| 150 | fn test_f32_floatFromInt_i128(a: i128, expected: f32) !void { | |
| 151 | const x = f32_floatFromInt_i128(a); | |
| 121 | 152 | try testing.expect(x == expected); |
| 122 | 153 | } |
| 123 | 154 | |
| 124 | fn test__floatuntisf(a: u128, expected: f32) !void { | |
| 125 | const x = __floatuntisf(a); | |
| 155 | fn test_f32_floatFromInt_u128(a: u128, expected: f32) !void { | |
| 156 | const x = f32_floatFromInt_u128(a); | |
| 126 | 157 | try testing.expect(x == expected); |
| 127 | 158 | } |
| 128 | 159 | |
| 129 | test "floattisf" { | |
| 130 | try test__floattisf(0, 0.0); | |
| 160 | test f32_floatFromInt_i128 { | |
| 161 | try test_f32_floatFromInt_i128(0, 0.0); | |
| 131 | 162 | |
| 132 | try test__floattisf(1, 1.0); | |
| 133 | try test__floattisf(2, 2.0); | |
| 134 | try test__floattisf(-1, -1.0); | |
| 135 | try test__floattisf(-2, -2.0); | |
| 163 | try test_f32_floatFromInt_i128(1, 1.0); | |
| 164 | try test_f32_floatFromInt_i128(2, 2.0); | |
| 165 | try test_f32_floatFromInt_i128(-1, -1.0); | |
| 166 | try test_f32_floatFromInt_i128(-2, -2.0); | |
| 136 | 167 | |
| 137 | try test__floattisf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); | |
| 138 | try test__floattisf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); | |
| 168 | try test_f32_floatFromInt_i128(0x7FFFFF8000000000, 0x1.FFFFFEp+62); | |
| 169 | try test_f32_floatFromInt_i128(0x7FFFFF0000000000, 0x1.FFFFFCp+62); | |
| 139 | 170 | |
| 140 | try test__floattisf(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000008000000000), -0x1.FFFFFEp+62); | |
| 141 | try test__floattisf(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000010000000000), -0x1.FFFFFCp+62); | |
| 171 | try test_f32_floatFromInt_i128(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000008000000000), -0x1.FFFFFEp+62); | |
| 172 | try test_f32_floatFromInt_i128(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000010000000000), -0x1.FFFFFCp+62); | |
| 142 | 173 | |
| 143 | try test__floattisf(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000000000000000), -0x1.000000p+63); | |
| 144 | try test__floattisf(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000000000000001), -0x1.000000p+63); | |
| 174 | try test_f32_floatFromInt_i128(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000000000000000), -0x1.000000p+63); | |
| 175 | try test_f32_floatFromInt_i128(make_ti(0xFFFFFFFFFFFFFFFF, 0x8000000000000001), -0x1.000000p+63); | |
| 145 | 176 | |
| 146 | try test__floattisf(0x0007FB72E8000000, 0x1.FEDCBAp+50); | |
| 177 | try test_f32_floatFromInt_i128(0x0007FB72E8000000, 0x1.FEDCBAp+50); | |
| 147 | 178 | |
| 148 | try test__floattisf(0x0007FB72EA000000, 0x1.FEDCBAp+50); | |
| 149 | try test__floattisf(0x0007FB72EB000000, 0x1.FEDCBAp+50); | |
| 150 | try test__floattisf(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50); | |
| 151 | try test__floattisf(0x0007FB72EC000000, 0x1.FEDCBCp+50); | |
| 152 | try test__floattisf(0x0007FB72E8000001, 0x1.FEDCBAp+50); | |
| 179 | try test_f32_floatFromInt_i128(0x0007FB72EA000000, 0x1.FEDCBAp+50); | |
| 180 | try test_f32_floatFromInt_i128(0x0007FB72EB000000, 0x1.FEDCBAp+50); | |
| 181 | try test_f32_floatFromInt_i128(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50); | |
| 182 | try test_f32_floatFromInt_i128(0x0007FB72EC000000, 0x1.FEDCBCp+50); | |
| 183 | try test_f32_floatFromInt_i128(0x0007FB72E8000001, 0x1.FEDCBAp+50); | |
| 153 | 184 | |
| 154 | try test__floattisf(0x0007FB72E6000000, 0x1.FEDCBAp+50); | |
| 155 | try test__floattisf(0x0007FB72E7000000, 0x1.FEDCBAp+50); | |
| 156 | try test__floattisf(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50); | |
| 157 | try test__floattisf(0x0007FB72E4000001, 0x1.FEDCBAp+50); | |
| 158 | try test__floattisf(0x0007FB72E4000000, 0x1.FEDCB8p+50); | |
| 185 | try test_f32_floatFromInt_i128(0x0007FB72E6000000, 0x1.FEDCBAp+50); | |
| 186 | try test_f32_floatFromInt_i128(0x0007FB72E7000000, 0x1.FEDCBAp+50); | |
| 187 | try test_f32_floatFromInt_i128(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50); | |
| 188 | try test_f32_floatFromInt_i128(0x0007FB72E4000001, 0x1.FEDCBAp+50); | |
| 189 | try test_f32_floatFromInt_i128(0x0007FB72E4000000, 0x1.FEDCB8p+50); | |
| 159 | 190 | |
| 160 | try test__floattisf(make_ti(0x0007FB72E8000000, 0), 0x1.FEDCBAp+114); | |
| 191 | try test_f32_floatFromInt_i128(make_ti(0x0007FB72E8000000, 0), 0x1.FEDCBAp+114); | |
| 161 | 192 | |
| 162 | try test__floattisf(make_ti(0x0007FB72EA000000, 0), 0x1.FEDCBAp+114); | |
| 163 | try test__floattisf(make_ti(0x0007FB72EB000000, 0), 0x1.FEDCBAp+114); | |
| 164 | try test__floattisf(make_ti(0x0007FB72EBFFFFFF, 0), 0x1.FEDCBAp+114); | |
| 165 | try test__floattisf(make_ti(0x0007FB72EC000000, 0), 0x1.FEDCBCp+114); | |
| 166 | try test__floattisf(make_ti(0x0007FB72E8000001, 0), 0x1.FEDCBAp+114); | |
| 193 | try test_f32_floatFromInt_i128(make_ti(0x0007FB72EA000000, 0), 0x1.FEDCBAp+114); | |
| 194 | try test_f32_floatFromInt_i128(make_ti(0x0007FB72EB000000, 0), 0x1.FEDCBAp+114); | |
| 195 | try test_f32_floatFromInt_i128(make_ti(0x0007FB72EBFFFFFF, 0), 0x1.FEDCBAp+114); | |
| 196 | try test_f32_floatFromInt_i128(make_ti(0x0007FB72EC000000, 0), 0x1.FEDCBCp+114); | |
| 197 | try test_f32_floatFromInt_i128(make_ti(0x0007FB72E8000001, 0), 0x1.FEDCBAp+114); | |
| 167 | 198 | |
| 168 | try test__floattisf(make_ti(0x0007FB72E6000000, 0), 0x1.FEDCBAp+114); | |
| 169 | try test__floattisf(make_ti(0x0007FB72E7000000, 0), 0x1.FEDCBAp+114); | |
| 170 | try test__floattisf(make_ti(0x0007FB72E7FFFFFF, 0), 0x1.FEDCBAp+114); | |
| 171 | try test__floattisf(make_ti(0x0007FB72E4000001, 0), 0x1.FEDCBAp+114); | |
| 172 | try test__floattisf(make_ti(0x0007FB72E4000000, 0), 0x1.FEDCB8p+114); | |
| 199 | try test_f32_floatFromInt_i128(make_ti(0x0007FB72E6000000, 0), 0x1.FEDCBAp+114); | |
| 200 | try test_f32_floatFromInt_i128(make_ti(0x0007FB72E7000000, 0), 0x1.FEDCBAp+114); | |
| 201 | try test_f32_floatFromInt_i128(make_ti(0x0007FB72E7FFFFFF, 0), 0x1.FEDCBAp+114); | |
| 202 | try test_f32_floatFromInt_i128(make_ti(0x0007FB72E4000001, 0), 0x1.FEDCBAp+114); | |
| 203 | try test_f32_floatFromInt_i128(make_ti(0x0007FB72E4000000, 0), 0x1.FEDCB8p+114); | |
| 173 | 204 | } |
| 174 | 205 | |
| 175 | test "floatuntisf" { | |
| 176 | try test__floatuntisf(0, 0.0); | |
| 206 | test f32_floatFromInt_u128 { | |
| 207 | try test_f32_floatFromInt_u128(0, 0.0); | |
| 177 | 208 | |
| 178 | try test__floatuntisf(1, 1.0); | |
| 179 | try test__floatuntisf(2, 2.0); | |
| 180 | try test__floatuntisf(20, 20.0); | |
| 209 | try test_f32_floatFromInt_u128(1, 1.0); | |
| 210 | try test_f32_floatFromInt_u128(2, 2.0); | |
| 211 | try test_f32_floatFromInt_u128(20, 20.0); | |
| 181 | 212 | |
| 182 | try test__floatuntisf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); | |
| 183 | try test__floatuntisf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); | |
| 213 | try test_f32_floatFromInt_u128(0x7FFFFF8000000000, 0x1.FFFFFEp+62); | |
| 214 | try test_f32_floatFromInt_u128(0x7FFFFF0000000000, 0x1.FFFFFCp+62); | |
| 184 | 215 | |
| 185 | try test__floatuntisf(make_uti(0x8000008000000000, 0), 0x1.000001p+127); | |
| 186 | try test__floatuntisf(make_uti(0x8000000000000800, 0), 0x1.0p+127); | |
| 187 | try test__floatuntisf(make_uti(0x8000010000000000, 0), 0x1.000002p+127); | |
| 216 | try test_f32_floatFromInt_u128(make_uti(0x8000008000000000, 0), 0x1.000001p+127); | |
| 217 | try test_f32_floatFromInt_u128(make_uti(0x8000000000000800, 0), 0x1.0p+127); | |
| 218 | try test_f32_floatFromInt_u128(make_uti(0x8000010000000000, 0), 0x1.000002p+127); | |
| 188 | 219 | |
| 189 | try test__floatuntisf(make_uti(0x8000000000000000, 0), 0x1.000000p+127); | |
| 220 | try test_f32_floatFromInt_u128(make_uti(0x8000000000000000, 0), 0x1.000000p+127); | |
| 190 | 221 | |
| 191 | try test__floatuntisf(0x0007FB72E8000000, 0x1.FEDCBAp+50); | |
| 222 | try test_f32_floatFromInt_u128(0x0007FB72E8000000, 0x1.FEDCBAp+50); | |
| 192 | 223 | |
| 193 | try test__floatuntisf(0x0007FB72EA000000, 0x1.FEDCBA8p+50); | |
| 194 | try test__floatuntisf(0x0007FB72EB000000, 0x1.FEDCBACp+50); | |
| 224 | try test_f32_floatFromInt_u128(0x0007FB72EA000000, 0x1.FEDCBA8p+50); | |
| 225 | try test_f32_floatFromInt_u128(0x0007FB72EB000000, 0x1.FEDCBACp+50); | |
| 195 | 226 | |
| 196 | try test__floatuntisf(0x0007FB72EC000000, 0x1.FEDCBBp+50); | |
| 227 | try test_f32_floatFromInt_u128(0x0007FB72EC000000, 0x1.FEDCBBp+50); | |
| 197 | 228 | |
| 198 | try test__floatuntisf(0x0007FB72E6000000, 0x1.FEDCB98p+50); | |
| 199 | try test__floatuntisf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); | |
| 200 | try test__floatuntisf(0x0007FB72E4000000, 0x1.FEDCB9p+50); | |
| 229 | try test_f32_floatFromInt_u128(0x0007FB72E6000000, 0x1.FEDCB98p+50); | |
| 230 | try test_f32_floatFromInt_u128(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); | |
| 231 | try test_f32_floatFromInt_u128(0x0007FB72E4000000, 0x1.FEDCB9p+50); | |
| 201 | 232 | |
| 202 | try test__floatuntisf(0xFFFFFFFFFFFFFFFE, 0x1p+64); | |
| 203 | try test__floatuntisf(0xFFFFFFFFFFFFFFFF, 0x1p+64); | |
| 233 | try test_f32_floatFromInt_u128(0xFFFFFFFFFFFFFFFE, 0x1p+64); | |
| 234 | try test_f32_floatFromInt_u128(0xFFFFFFFFFFFFFFFF, 0x1p+64); | |
| 204 | 235 | |
| 205 | try test__floatuntisf(0x0007FB72E8000000, 0x1.FEDCBAp+50); | |
| 236 | try test_f32_floatFromInt_u128(0x0007FB72E8000000, 0x1.FEDCBAp+50); | |
| 206 | 237 | |
| 207 | try test__floatuntisf(0x0007FB72EA000000, 0x1.FEDCBAp+50); | |
| 208 | try test__floatuntisf(0x0007FB72EB000000, 0x1.FEDCBAp+50); | |
| 209 | try test__floatuntisf(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50); | |
| 210 | try test__floatuntisf(0x0007FB72EC000000, 0x1.FEDCBCp+50); | |
| 211 | try test__floatuntisf(0x0007FB72E8000001, 0x1.FEDCBAp+50); | |
| 238 | try test_f32_floatFromInt_u128(0x0007FB72EA000000, 0x1.FEDCBAp+50); | |
| 239 | try test_f32_floatFromInt_u128(0x0007FB72EB000000, 0x1.FEDCBAp+50); | |
| 240 | try test_f32_floatFromInt_u128(0x0007FB72EBFFFFFF, 0x1.FEDCBAp+50); | |
| 241 | try test_f32_floatFromInt_u128(0x0007FB72EC000000, 0x1.FEDCBCp+50); | |
| 242 | try test_f32_floatFromInt_u128(0x0007FB72E8000001, 0x1.FEDCBAp+50); | |
| 212 | 243 | |
| 213 | try test__floatuntisf(0x0007FB72E6000000, 0x1.FEDCBAp+50); | |
| 214 | try test__floatuntisf(0x0007FB72E7000000, 0x1.FEDCBAp+50); | |
| 215 | try test__floatuntisf(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50); | |
| 216 | try test__floatuntisf(0x0007FB72E4000001, 0x1.FEDCBAp+50); | |
| 217 | try test__floatuntisf(0x0007FB72E4000000, 0x1.FEDCB8p+50); | |
| 244 | try test_f32_floatFromInt_u128(0x0007FB72E6000000, 0x1.FEDCBAp+50); | |
| 245 | try test_f32_floatFromInt_u128(0x0007FB72E7000000, 0x1.FEDCBAp+50); | |
| 246 | try test_f32_floatFromInt_u128(0x0007FB72E7FFFFFF, 0x1.FEDCBAp+50); | |
| 247 | try test_f32_floatFromInt_u128(0x0007FB72E4000001, 0x1.FEDCBAp+50); | |
| 248 | try test_f32_floatFromInt_u128(0x0007FB72E4000000, 0x1.FEDCB8p+50); | |
| 218 | 249 | |
| 219 | try test__floatuntisf(make_uti(0x0000000000001FED, 0xCB90000000000001), 0x1.FEDCBAp+76); | |
| 220 | try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBA0000000000000), 0x1.FEDCBAp+76); | |
| 221 | try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBAFFFFFFFFFFFFF), 0x1.FEDCBAp+76); | |
| 222 | try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBB0000000000000), 0x1.FEDCBCp+76); | |
| 223 | try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBB0000000000001), 0x1.FEDCBCp+76); | |
| 224 | try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBBFFFFFFFFFFFFF), 0x1.FEDCBCp+76); | |
| 225 | try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBC0000000000000), 0x1.FEDCBCp+76); | |
| 226 | try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBC0000000000001), 0x1.FEDCBCp+76); | |
| 227 | try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBD0000000000000), 0x1.FEDCBCp+76); | |
| 228 | try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBD0000000000001), 0x1.FEDCBEp+76); | |
| 229 | try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBDFFFFFFFFFFFFF), 0x1.FEDCBEp+76); | |
| 230 | try test__floatuntisf(make_uti(0x0000000000001FED, 0xCBE0000000000000), 0x1.FEDCBEp+76); | |
| 250 | try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCB90000000000001), 0x1.FEDCBAp+76); | |
| 251 | try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBA0000000000000), 0x1.FEDCBAp+76); | |
| 252 | try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBAFFFFFFFFFFFFF), 0x1.FEDCBAp+76); | |
| 253 | try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBB0000000000000), 0x1.FEDCBCp+76); | |
| 254 | try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBB0000000000001), 0x1.FEDCBCp+76); | |
| 255 | try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBBFFFFFFFFFFFFF), 0x1.FEDCBCp+76); | |
| 256 | try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBC0000000000000), 0x1.FEDCBCp+76); | |
| 257 | try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBC0000000000001), 0x1.FEDCBCp+76); | |
| 258 | try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBD0000000000000), 0x1.FEDCBCp+76); | |
| 259 | try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBD0000000000001), 0x1.FEDCBEp+76); | |
| 260 | try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBDFFFFFFFFFFFFF), 0x1.FEDCBEp+76); | |
| 261 | try test_f32_floatFromInt_u128(make_uti(0x0000000000001FED, 0xCBE0000000000000), 0x1.FEDCBEp+76); | |
| 231 | 262 | |
| 232 | 263 | // 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 | } |
| 235 | 266 | |
| 236 | fn test_floateisf(expected: u32, comptime T: type, a: T) !void { | |
| 267 | fn test_f32_floatFromInt(expected: u32, comptime T: type, a: T) !void { | |
| 237 | 268 | const int = @typeInfo(T).int; |
| 238 | 269 | const r = switch (int.signedness) { |
| 239 | .signed => __floateisf, | |
| 240 | .unsigned => __floatuneisf, | |
| 241 | }(@ptrCast(&a), int.bits); | |
| 270 | .signed => f32_floatFromInt_signed, | |
| 271 | .unsigned => f32_floatFromInt_unsigned, | |
| 272 | }(@ptrCast(&a)); | |
| 242 | 273 | try testing.expect(expected == @as(u32, @bitCast(r))); |
| 243 | 274 | } |
| 244 | 275 | |
| 245 | test "floateisf" { | |
| 246 | try test_floateisf(0xFF000000, i256, -1 << 127); | |
| 247 | try test_floateisf(0xFF000000, i256, -math.maxInt(u127)); | |
| 248 | try test_floateisf(0xDF012347, i256, -0x8123468100000000); | |
| 249 | try test_floateisf(0xDF012347, i256, -0x8123468000000001); | |
| 250 | try test_floateisf(0xDF012346, i256, -0x8123468000000000); | |
| 251 | try test_floateisf(0xDF012346, i256, -0x8123458100000000); | |
| 252 | try test_floateisf(0xDF012346, i256, -0x8123458000000001); | |
| 253 | try test_floateisf(0xDF012346, i256, -0x8123458000000000); | |
| 254 | try test_floateisf(0xDF012345, i256, -0x8123456789ABCDEF); | |
| 255 | try test_floateisf(0xBF800000, i256, -1); | |
| 256 | try test_floateisf(0x00000000, i256, 0); | |
| 257 | try test_floateisf(0x5F012345, i256, 0x8123456789ABCDEF); | |
| 258 | try test_floateisf(0x5F012346, i256, 0x8123458000000000); | |
| 259 | try test_floateisf(0x5F012346, i256, 0x8123458000000001); | |
| 260 | try test_floateisf(0x5F012346, i256, 0x8123458100000000); | |
| 261 | try test_floateisf(0x5F012346, i256, 0x8123468000000000); | |
| 262 | try test_floateisf(0x5F012347, i256, 0x8123468000000001); | |
| 263 | try test_floateisf(0x5F012347, i256, 0x8123468100000000); | |
| 264 | try test_floateisf(0x7F000000, i256, math.maxInt(u127)); | |
| 265 | try test_floateisf(0x7F000000, i256, 1 << 127); | |
| 266 | } | |
| 267 | ||
| 268 | test "floatuneisf" { | |
| 269 | try test_floateisf(0x00000000, u256, 0); | |
| 270 | try test_floateisf(0x5F012345, u256, 0x8123456789ABCDEF); | |
| 271 | try test_floateisf(0x5F012346, u256, 0x8123458000000000); | |
| 272 | try test_floateisf(0x5F012346, u256, 0x8123458000000001); | |
| 273 | try test_floateisf(0x5F012346, u256, 0x8123458080000000); | |
| 274 | try test_floateisf(0x5F012346, u256, 0x8123468000000000); | |
| 275 | try test_floateisf(0x5F012347, u256, 0x8123468000000001); | |
| 276 | try test_floateisf(0x5F012347, u256, 0x8123468080000000); | |
| 277 | try test_floateisf(0x7F000000, u256, math.maxInt(u127)); | |
| 278 | try test_floateisf(0x7F000000, u256, 1 << 127); | |
| 279 | try test_floateisf(0x7F800000, u256, math.maxInt(u256)); | |
| 280 | } | |
| 281 | ||
| 282 | fn test_one_floatsidf(a: i32, expected: u64) !void { | |
| 283 | const r = __floatsidf(a); | |
| 276 | test f32_floatFromInt_signed { | |
| 277 | try test_f32_floatFromInt(0xFF000000, i256, -1 << 127); | |
| 278 | try test_f32_floatFromInt(0xFF000000, i256, -math.maxInt(u127)); | |
| 279 | try test_f32_floatFromInt(0xDF012347, i256, -0x8123468100000000); | |
| 280 | try test_f32_floatFromInt(0xDF012347, i256, -0x8123468000000001); | |
| 281 | try test_f32_floatFromInt(0xDF012346, i256, -0x8123468000000000); | |
| 282 | try test_f32_floatFromInt(0xDF012346, i256, -0x8123458100000000); | |
| 283 | try test_f32_floatFromInt(0xDF012346, i256, -0x8123458000000001); | |
| 284 | try test_f32_floatFromInt(0xDF012346, i256, -0x8123458000000000); | |
| 285 | try test_f32_floatFromInt(0xDF012345, i256, -0x8123456789ABCDEF); | |
| 286 | try test_f32_floatFromInt(0xBF800000, i256, -1); | |
| 287 | try test_f32_floatFromInt(0x00000000, i256, 0); | |
| 288 | try test_f32_floatFromInt(0x5F012345, i256, 0x8123456789ABCDEF); | |
| 289 | try test_f32_floatFromInt(0x5F012346, i256, 0x8123458000000000); | |
| 290 | try test_f32_floatFromInt(0x5F012346, i256, 0x8123458000000001); | |
| 291 | try test_f32_floatFromInt(0x5F012346, i256, 0x8123458100000000); | |
| 292 | try test_f32_floatFromInt(0x5F012346, i256, 0x8123468000000000); | |
| 293 | try test_f32_floatFromInt(0x5F012347, i256, 0x8123468000000001); | |
| 294 | try test_f32_floatFromInt(0x5F012347, i256, 0x8123468100000000); | |
| 295 | try test_f32_floatFromInt(0x7F000000, i256, math.maxInt(u127)); | |
| 296 | try test_f32_floatFromInt(0x7F000000, i256, 1 << 127); | |
| 297 | } | |
| 298 | ||
| 299 | test f32_floatFromInt_unsigned { | |
| 300 | try test_f32_floatFromInt(0x00000000, u256, 0); | |
| 301 | try test_f32_floatFromInt(0x5F012345, u256, 0x8123456789ABCDEF); | |
| 302 | try test_f32_floatFromInt(0x5F012346, u256, 0x8123458000000000); | |
| 303 | try test_f32_floatFromInt(0x5F012346, u256, 0x8123458000000001); | |
| 304 | try test_f32_floatFromInt(0x5F012346, u256, 0x8123458080000000); | |
| 305 | try test_f32_floatFromInt(0x5F012346, u256, 0x8123468000000000); | |
| 306 | try test_f32_floatFromInt(0x5F012347, u256, 0x8123468000000001); | |
| 307 | try test_f32_floatFromInt(0x5F012347, u256, 0x8123468080000000); | |
| 308 | try test_f32_floatFromInt(0x7F000000, u256, math.maxInt(u127)); | |
| 309 | try test_f32_floatFromInt(0x7F000000, u256, 1 << 127); | |
| 310 | try test_f32_floatFromInt(0x7F800000, u256, math.maxInt(u256)); | |
| 311 | } | |
| 312 | ||
| 313 | fn test_f64_floatFromInt_i32(a: i32, expected: u64) !void { | |
| 314 | const r = f64_floatFromInt_i32(a); | |
| 284 | 315 | try std.testing.expect(@as(u64, @bitCast(r)) == expected); |
| 285 | 316 | } |
| 286 | 317 | |
| 287 | fn test_one_floatunsidf(a: u32, expected: u64) !void { | |
| 288 | const r = __floatunsidf(a); | |
| 318 | fn test_f64_floatFromInt_u32(a: u32, expected: u64) !void { | |
| 319 | const r = f64_floatFromInt_u32(a); | |
| 289 | 320 | try std.testing.expect(@as(u64, @bitCast(r)) == expected); |
| 290 | 321 | } |
| 291 | 322 | |
| 292 | test "floatsidf" { | |
| 293 | try test_one_floatsidf(0, 0x0000000000000000); | |
| 294 | try test_one_floatsidf(1, 0x3ff0000000000000); | |
| 295 | try test_one_floatsidf(-1, 0xbff0000000000000); | |
| 296 | try test_one_floatsidf(0x7FFFFFFF, 0x41dfffffffc00000); | |
| 297 | try test_one_floatsidf(@bitCast(@as(u32, @intCast(0x80000000))), 0xc1e0000000000000); | |
| 323 | test f64_floatFromInt_i32 { | |
| 324 | try test_f64_floatFromInt_i32(0, 0x0000000000000000); | |
| 325 | try test_f64_floatFromInt_i32(1, 0x3ff0000000000000); | |
| 326 | try test_f64_floatFromInt_i32(-1, 0xbff0000000000000); | |
| 327 | try test_f64_floatFromInt_i32(0x7FFFFFFF, 0x41dfffffffc00000); | |
| 328 | try test_f64_floatFromInt_i32(@bitCast(@as(u32, @intCast(0x80000000))), 0xc1e0000000000000); | |
| 298 | 329 | } |
| 299 | 330 | |
| 300 | test "floatunsidf" { | |
| 301 | try test_one_floatunsidf(0, 0x0000000000000000); | |
| 302 | try test_one_floatunsidf(1, 0x3ff0000000000000); | |
| 303 | try test_one_floatunsidf(0x7FFFFFFF, 0x41dfffffffc00000); | |
| 304 | try test_one_floatunsidf(@intCast(0x80000000), 0x41e0000000000000); | |
| 305 | try test_one_floatunsidf(@intCast(0xFFFFFFFF), 0x41efffffffe00000); | |
| 331 | test f64_floatFromInt_u32 { | |
| 332 | try test_f64_floatFromInt_u32(0, 0x0000000000000000); | |
| 333 | try test_f64_floatFromInt_u32(1, 0x3ff0000000000000); | |
| 334 | try test_f64_floatFromInt_u32(0x7FFFFFFF, 0x41dfffffffc00000); | |
| 335 | try test_f64_floatFromInt_u32(@intCast(0x80000000), 0x41e0000000000000); | |
| 336 | try test_f64_floatFromInt_u32(@intCast(0xFFFFFFFF), 0x41efffffffe00000); | |
| 306 | 337 | } |
| 307 | 338 | |
| 308 | fn test__floatdidf(a: i64, expected: f64) !void { | |
| 309 | const r = __floatdidf(a); | |
| 339 | fn test_f64_floatFromInt_i64(a: i64, expected: f64) !void { | |
| 340 | const r = f64_floatFromInt_i64(a); | |
| 310 | 341 | try testing.expect(r == expected); |
| 311 | 342 | } |
| 312 | 343 | |
| 313 | fn test__floatundidf(a: u64, expected: f64) !void { | |
| 314 | const r = __floatundidf(a); | |
| 344 | fn test_f64_floatFromInt_u64(a: u64, expected: f64) !void { | |
| 345 | const r = f64_floatFromInt_u64(a); | |
| 315 | 346 | try testing.expect(r == expected); |
| 316 | 347 | } |
| 317 | 348 | |
| 318 | test "floatdidf" { | |
| 319 | try test__floatdidf(0, 0.0); | |
| 320 | try test__floatdidf(1, 1.0); | |
| 321 | try test__floatdidf(2, 2.0); | |
| 322 | try test__floatdidf(20, 20.0); | |
| 323 | try test__floatdidf(-1, -1.0); | |
| 324 | try test__floatdidf(-2, -2.0); | |
| 325 | try test__floatdidf(-20, -20.0); | |
| 326 | try test__floatdidf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); | |
| 327 | try test__floatdidf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62); | |
| 328 | try test__floatdidf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); | |
| 329 | try test__floatdidf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62); | |
| 330 | try test__floatdidf(@bitCast(@as(u64, @intCast(0x8000008000000000))), -0x1.FFFFFEp+62); | |
| 331 | try test__floatdidf(@bitCast(@as(u64, @intCast(0x8000000000000800))), -0x1.FFFFFFFFFFFFEp+62); | |
| 332 | try test__floatdidf(@bitCast(@as(u64, @intCast(0x8000010000000000))), -0x1.FFFFFCp+62); | |
| 333 | try test__floatdidf(@bitCast(@as(u64, @intCast(0x8000000000001000))), -0x1.FFFFFFFFFFFFCp+62); | |
| 334 | try test__floatdidf(@bitCast(@as(u64, @intCast(0x8000000000000000))), -0x1.000000p+63); | |
| 335 | try test__floatdidf(@bitCast(@as(u64, @intCast(0x8000000000000001))), -0x1.000000p+63); // 0x8000000000000001 | |
| 336 | try test__floatdidf(0x0007FB72E8000000, 0x1.FEDCBAp+50); | |
| 337 | try test__floatdidf(0x0007FB72EA000000, 0x1.FEDCBA8p+50); | |
| 338 | try test__floatdidf(0x0007FB72EB000000, 0x1.FEDCBACp+50); | |
| 339 | try test__floatdidf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50); | |
| 340 | try test__floatdidf(0x0007FB72EC000000, 0x1.FEDCBBp+50); | |
| 341 | try test__floatdidf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50); | |
| 342 | try test__floatdidf(0x0007FB72E6000000, 0x1.FEDCB98p+50); | |
| 343 | try test__floatdidf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); | |
| 344 | try test__floatdidf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50); | |
| 345 | try test__floatdidf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50); | |
| 346 | try test__floatdidf(0x0007FB72E4000000, 0x1.FEDCB9p+50); | |
| 347 | try test__floatdidf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57); | |
| 348 | try test__floatdidf(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57); | |
| 349 | try test__floatdidf(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57); | |
| 350 | try test__floatdidf(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57); | |
| 351 | try test__floatdidf(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57); | |
| 352 | try test__floatdidf(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57); | |
| 353 | try test__floatdidf(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57); | |
| 354 | try test__floatdidf(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57); | |
| 355 | try test__floatdidf(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57); | |
| 356 | try test__floatdidf(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57); | |
| 357 | try test__floatdidf(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57); | |
| 358 | try test__floatdidf(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57); | |
| 359 | try test__floatdidf(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57); | |
| 360 | try test__floatdidf(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57); | |
| 361 | try test__floatdidf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57); | |
| 362 | } | |
| 363 | ||
| 364 | test "floatundidf" { | |
| 365 | try test__floatundidf(0, 0.0); | |
| 366 | try test__floatundidf(1, 1.0); | |
| 367 | try test__floatundidf(2, 2.0); | |
| 368 | try test__floatundidf(20, 20.0); | |
| 369 | try test__floatundidf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); | |
| 370 | try test__floatundidf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62); | |
| 371 | try test__floatundidf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); | |
| 372 | try test__floatundidf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62); | |
| 373 | try test__floatundidf(0x8000008000000000, 0x1.000001p+63); | |
| 374 | try test__floatundidf(0x8000000000000800, 0x1.0000000000001p+63); | |
| 375 | try test__floatundidf(0x8000010000000000, 0x1.000002p+63); | |
| 376 | try test__floatundidf(0x8000000000001000, 0x1.0000000000002p+63); | |
| 377 | try test__floatundidf(0x8000000000000000, 0x1p+63); | |
| 378 | try test__floatundidf(0x8000000000000001, 0x1p+63); | |
| 379 | try test__floatundidf(0x0007FB72E8000000, 0x1.FEDCBAp+50); | |
| 380 | try test__floatundidf(0x0007FB72EA000000, 0x1.FEDCBA8p+50); | |
| 381 | try test__floatundidf(0x0007FB72EB000000, 0x1.FEDCBACp+50); | |
| 382 | try test__floatundidf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50); | |
| 383 | try test__floatundidf(0x0007FB72EC000000, 0x1.FEDCBBp+50); | |
| 384 | try test__floatundidf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50); | |
| 385 | try test__floatundidf(0x0007FB72E6000000, 0x1.FEDCB98p+50); | |
| 386 | try test__floatundidf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); | |
| 387 | try test__floatundidf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50); | |
| 388 | try test__floatundidf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50); | |
| 389 | try test__floatundidf(0x0007FB72E4000000, 0x1.FEDCB9p+50); | |
| 390 | try test__floatundidf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57); | |
| 391 | try test__floatundidf(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57); | |
| 392 | try test__floatundidf(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57); | |
| 393 | try test__floatundidf(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57); | |
| 394 | try test__floatundidf(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57); | |
| 395 | try test__floatundidf(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57); | |
| 396 | try test__floatundidf(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57); | |
| 397 | try test__floatundidf(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57); | |
| 398 | try test__floatundidf(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57); | |
| 399 | try test__floatundidf(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57); | |
| 400 | try test__floatundidf(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57); | |
| 401 | try test__floatundidf(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57); | |
| 402 | try test__floatundidf(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57); | |
| 403 | try test__floatundidf(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57); | |
| 404 | try test__floatundidf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57); | |
| 405 | } | |
| 406 | ||
| 407 | fn test__floattidf(a: i128, expected: f64) !void { | |
| 408 | const x = __floattidf(a); | |
| 349 | test f64_floatFromInt_i64 { | |
| 350 | try test_f64_floatFromInt_i64(0, 0.0); | |
| 351 | try test_f64_floatFromInt_i64(1, 1.0); | |
| 352 | try test_f64_floatFromInt_i64(2, 2.0); | |
| 353 | try test_f64_floatFromInt_i64(20, 20.0); | |
| 354 | try test_f64_floatFromInt_i64(-1, -1.0); | |
| 355 | try test_f64_floatFromInt_i64(-2, -2.0); | |
| 356 | try test_f64_floatFromInt_i64(-20, -20.0); | |
| 357 | try test_f64_floatFromInt_i64(0x7FFFFF8000000000, 0x1.FFFFFEp+62); | |
| 358 | try test_f64_floatFromInt_i64(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62); | |
| 359 | try test_f64_floatFromInt_i64(0x7FFFFF0000000000, 0x1.FFFFFCp+62); | |
| 360 | try test_f64_floatFromInt_i64(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62); | |
| 361 | try test_f64_floatFromInt_i64(@bitCast(@as(u64, @intCast(0x8000008000000000))), -0x1.FFFFFEp+62); | |
| 362 | try test_f64_floatFromInt_i64(@bitCast(@as(u64, @intCast(0x8000000000000800))), -0x1.FFFFFFFFFFFFEp+62); | |
| 363 | try test_f64_floatFromInt_i64(@bitCast(@as(u64, @intCast(0x8000010000000000))), -0x1.FFFFFCp+62); | |
| 364 | try test_f64_floatFromInt_i64(@bitCast(@as(u64, @intCast(0x8000000000001000))), -0x1.FFFFFFFFFFFFCp+62); | |
| 365 | try test_f64_floatFromInt_i64(@bitCast(@as(u64, @intCast(0x8000000000000000))), -0x1.000000p+63); | |
| 366 | try test_f64_floatFromInt_i64(@bitCast(@as(u64, @intCast(0x8000000000000001))), -0x1.000000p+63); // 0x8000000000000001 | |
| 367 | try test_f64_floatFromInt_i64(0x0007FB72E8000000, 0x1.FEDCBAp+50); | |
| 368 | try test_f64_floatFromInt_i64(0x0007FB72EA000000, 0x1.FEDCBA8p+50); | |
| 369 | try test_f64_floatFromInt_i64(0x0007FB72EB000000, 0x1.FEDCBACp+50); | |
| 370 | try test_f64_floatFromInt_i64(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50); | |
| 371 | try test_f64_floatFromInt_i64(0x0007FB72EC000000, 0x1.FEDCBBp+50); | |
| 372 | try test_f64_floatFromInt_i64(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50); | |
| 373 | try test_f64_floatFromInt_i64(0x0007FB72E6000000, 0x1.FEDCB98p+50); | |
| 374 | try test_f64_floatFromInt_i64(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); | |
| 375 | try test_f64_floatFromInt_i64(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50); | |
| 376 | try test_f64_floatFromInt_i64(0x0007FB72E4000001, 0x1.FEDCB90000004p+50); | |
| 377 | try test_f64_floatFromInt_i64(0x0007FB72E4000000, 0x1.FEDCB9p+50); | |
| 378 | try test_f64_floatFromInt_i64(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57); | |
| 379 | try test_f64_floatFromInt_i64(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57); | |
| 380 | try test_f64_floatFromInt_i64(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57); | |
| 381 | try test_f64_floatFromInt_i64(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57); | |
| 382 | try test_f64_floatFromInt_i64(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57); | |
| 383 | try test_f64_floatFromInt_i64(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57); | |
| 384 | try test_f64_floatFromInt_i64(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57); | |
| 385 | try test_f64_floatFromInt_i64(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57); | |
| 386 | try test_f64_floatFromInt_i64(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57); | |
| 387 | try test_f64_floatFromInt_i64(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57); | |
| 388 | try test_f64_floatFromInt_i64(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57); | |
| 389 | try test_f64_floatFromInt_i64(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57); | |
| 390 | try test_f64_floatFromInt_i64(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57); | |
| 391 | try test_f64_floatFromInt_i64(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57); | |
| 392 | try test_f64_floatFromInt_i64(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57); | |
| 393 | } | |
| 394 | ||
| 395 | test f64_floatFromInt_u64 { | |
| 396 | try test_f64_floatFromInt_u64(0, 0.0); | |
| 397 | try test_f64_floatFromInt_u64(1, 1.0); | |
| 398 | try test_f64_floatFromInt_u64(2, 2.0); | |
| 399 | try test_f64_floatFromInt_u64(20, 20.0); | |
| 400 | try test_f64_floatFromInt_u64(0x7FFFFF8000000000, 0x1.FFFFFEp+62); | |
| 401 | try test_f64_floatFromInt_u64(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62); | |
| 402 | try test_f64_floatFromInt_u64(0x7FFFFF0000000000, 0x1.FFFFFCp+62); | |
| 403 | try test_f64_floatFromInt_u64(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62); | |
| 404 | try test_f64_floatFromInt_u64(0x8000008000000000, 0x1.000001p+63); | |
| 405 | try test_f64_floatFromInt_u64(0x8000000000000800, 0x1.0000000000001p+63); | |
| 406 | try test_f64_floatFromInt_u64(0x8000010000000000, 0x1.000002p+63); | |
| 407 | try test_f64_floatFromInt_u64(0x8000000000001000, 0x1.0000000000002p+63); | |
| 408 | try test_f64_floatFromInt_u64(0x8000000000000000, 0x1p+63); | |
| 409 | try test_f64_floatFromInt_u64(0x8000000000000001, 0x1p+63); | |
| 410 | try test_f64_floatFromInt_u64(0x0007FB72E8000000, 0x1.FEDCBAp+50); | |
| 411 | try test_f64_floatFromInt_u64(0x0007FB72EA000000, 0x1.FEDCBA8p+50); | |
| 412 | try test_f64_floatFromInt_u64(0x0007FB72EB000000, 0x1.FEDCBACp+50); | |
| 413 | try test_f64_floatFromInt_u64(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50); | |
| 414 | try test_f64_floatFromInt_u64(0x0007FB72EC000000, 0x1.FEDCBBp+50); | |
| 415 | try test_f64_floatFromInt_u64(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50); | |
| 416 | try test_f64_floatFromInt_u64(0x0007FB72E6000000, 0x1.FEDCB98p+50); | |
| 417 | try test_f64_floatFromInt_u64(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); | |
| 418 | try test_f64_floatFromInt_u64(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50); | |
| 419 | try test_f64_floatFromInt_u64(0x0007FB72E4000001, 0x1.FEDCB90000004p+50); | |
| 420 | try test_f64_floatFromInt_u64(0x0007FB72E4000000, 0x1.FEDCB9p+50); | |
| 421 | try test_f64_floatFromInt_u64(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57); | |
| 422 | try test_f64_floatFromInt_u64(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57); | |
| 423 | try test_f64_floatFromInt_u64(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57); | |
| 424 | try test_f64_floatFromInt_u64(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57); | |
| 425 | try test_f64_floatFromInt_u64(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57); | |
| 426 | try test_f64_floatFromInt_u64(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57); | |
| 427 | try test_f64_floatFromInt_u64(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57); | |
| 428 | try test_f64_floatFromInt_u64(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57); | |
| 429 | try test_f64_floatFromInt_u64(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57); | |
| 430 | try test_f64_floatFromInt_u64(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57); | |
| 431 | try test_f64_floatFromInt_u64(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57); | |
| 432 | try test_f64_floatFromInt_u64(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57); | |
| 433 | try test_f64_floatFromInt_u64(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57); | |
| 434 | try test_f64_floatFromInt_u64(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57); | |
| 435 | try test_f64_floatFromInt_u64(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57); | |
| 436 | } | |
| 437 | ||
| 438 | fn test_f64_floatFromInt_i128(a: i128, expected: f64) !void { | |
| 439 | const x = f64_floatFromInt_i128(a); | |
| 409 | 440 | try testing.expect(x == expected); |
| 410 | 441 | } |
| 411 | 442 | |
| 412 | fn test__floatuntidf(a: u128, expected: f64) !void { | |
| 413 | const x = __floatuntidf(a); | |
| 443 | fn test_f64_floatFromInt_u128(a: u128, expected: f64) !void { | |
| 444 | const x = f64_floatFromInt_u128(a); | |
| 414 | 445 | try testing.expect(x == expected); |
| 415 | 446 | } |
| 416 | 447 | |
| 417 | test "floattidf" { | |
| 418 | try test__floattidf(0, 0.0); | |
| 419 | ||
| 420 | try test__floattidf(1, 1.0); | |
| 421 | try test__floattidf(2, 2.0); | |
| 422 | try test__floattidf(20, 20.0); | |
| 423 | try test__floattidf(-1, -1.0); | |
| 424 | try test__floattidf(-2, -2.0); | |
| 425 | try test__floattidf(-20, -20.0); | |
| 426 | ||
| 427 | try test__floattidf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); | |
| 428 | try test__floattidf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62); | |
| 429 | try test__floattidf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); | |
| 430 | try test__floattidf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62); | |
| 431 | ||
| 432 | try test__floattidf(make_ti(0x8000008000000000, 0), -0x1.FFFFFEp+126); | |
| 433 | try test__floattidf(make_ti(0x8000000000000800, 0), -0x1.FFFFFFFFFFFFEp+126); | |
| 434 | try test__floattidf(make_ti(0x8000010000000000, 0), -0x1.FFFFFCp+126); | |
| 435 | try test__floattidf(make_ti(0x8000000000001000, 0), -0x1.FFFFFFFFFFFFCp+126); | |
| 436 | ||
| 437 | try test__floattidf(make_ti(0x8000000000000000, 0), -0x1.000000p+127); | |
| 438 | try test__floattidf(make_ti(0x8000000000000001, 0), -0x1.000000p+127); | |
| 439 | ||
| 440 | try test__floattidf(0x0007FB72E8000000, 0x1.FEDCBAp+50); | |
| 441 | ||
| 442 | try test__floattidf(0x0007FB72EA000000, 0x1.FEDCBA8p+50); | |
| 443 | try test__floattidf(0x0007FB72EB000000, 0x1.FEDCBACp+50); | |
| 444 | try test__floattidf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50); | |
| 445 | try test__floattidf(0x0007FB72EC000000, 0x1.FEDCBBp+50); | |
| 446 | try test__floattidf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50); | |
| 447 | ||
| 448 | try test__floattidf(0x0007FB72E6000000, 0x1.FEDCB98p+50); | |
| 449 | try test__floattidf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); | |
| 450 | try test__floattidf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50); | |
| 451 | try test__floattidf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50); | |
| 452 | try test__floattidf(0x0007FB72E4000000, 0x1.FEDCB9p+50); | |
| 453 | ||
| 454 | try test__floattidf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57); | |
| 455 | try test__floattidf(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57); | |
| 456 | try test__floattidf(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57); | |
| 457 | try test__floattidf(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57); | |
| 458 | try test__floattidf(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57); | |
| 459 | try test__floattidf(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57); | |
| 460 | try test__floattidf(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57); | |
| 461 | try test__floattidf(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57); | |
| 462 | try test__floattidf(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57); | |
| 463 | try test__floattidf(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57); | |
| 464 | try test__floattidf(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57); | |
| 465 | try test__floattidf(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57); | |
| 466 | try test__floattidf(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57); | |
| 467 | try test__floattidf(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57); | |
| 468 | try test__floattidf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57); | |
| 469 | ||
| 470 | try test__floattidf(make_ti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121); | |
| 471 | try test__floattidf(make_ti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496Dp+121); | |
| 472 | try test__floattidf(make_ti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496Ep+121); | |
| 473 | try test__floattidf(make_ti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496Ep+121); | |
| 474 | try test__floattidf(make_ti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496Ep+121); | |
| 475 | try test__floattidf(make_ti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496Ep+121); | |
| 476 | try test__floattidf(make_ti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496Ep+121); | |
| 477 | try test__floattidf(make_ti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496Ep+121); | |
| 478 | try test__floattidf(make_ti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496Ep+121); | |
| 479 | try test__floattidf(make_ti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496Ep+121); | |
| 480 | try test__floattidf(make_ti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496Ep+121); | |
| 481 | try test__floattidf(make_ti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496Fp+121); | |
| 482 | try test__floattidf(make_ti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496Fp+121); | |
| 483 | try test__floattidf(make_ti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496Fp+121); | |
| 484 | try test__floattidf(make_ti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121); | |
| 485 | } | |
| 486 | ||
| 487 | test "floatuntidf" { | |
| 488 | try test__floatuntidf(0, 0.0); | |
| 489 | ||
| 490 | try test__floatuntidf(1, 1.0); | |
| 491 | try test__floatuntidf(2, 2.0); | |
| 492 | try test__floatuntidf(20, 20.0); | |
| 493 | ||
| 494 | try test__floatuntidf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); | |
| 495 | try test__floatuntidf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62); | |
| 496 | try test__floatuntidf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); | |
| 497 | try test__floatuntidf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62); | |
| 498 | ||
| 499 | try test__floatuntidf(make_uti(0x8000008000000000, 0), 0x1.000001p+127); | |
| 500 | try test__floatuntidf(make_uti(0x8000000000000800, 0), 0x1.0000000000001p+127); | |
| 501 | try test__floatuntidf(make_uti(0x8000010000000000, 0), 0x1.000002p+127); | |
| 502 | try test__floatuntidf(make_uti(0x8000000000001000, 0), 0x1.0000000000002p+127); | |
| 503 | ||
| 504 | try test__floatuntidf(make_uti(0x8000000000000000, 0), 0x1.000000p+127); | |
| 505 | try test__floatuntidf(make_uti(0x8000000000000001, 0), 0x1.0000000000000002p+127); | |
| 506 | ||
| 507 | try test__floatuntidf(0x0007FB72E8000000, 0x1.FEDCBAp+50); | |
| 508 | ||
| 509 | try test__floatuntidf(0x0007FB72EA000000, 0x1.FEDCBA8p+50); | |
| 510 | try test__floatuntidf(0x0007FB72EB000000, 0x1.FEDCBACp+50); | |
| 511 | try test__floatuntidf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50); | |
| 512 | try test__floatuntidf(0x0007FB72EC000000, 0x1.FEDCBBp+50); | |
| 513 | try test__floatuntidf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50); | |
| 514 | ||
| 515 | try test__floatuntidf(0x0007FB72E6000000, 0x1.FEDCB98p+50); | |
| 516 | try test__floatuntidf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); | |
| 517 | try test__floatuntidf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50); | |
| 518 | try test__floatuntidf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50); | |
| 519 | try test__floatuntidf(0x0007FB72E4000000, 0x1.FEDCB9p+50); | |
| 520 | ||
| 521 | try test__floatuntidf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57); | |
| 522 | try test__floatuntidf(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57); | |
| 523 | try test__floatuntidf(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57); | |
| 524 | try test__floatuntidf(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57); | |
| 525 | try test__floatuntidf(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57); | |
| 526 | try test__floatuntidf(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57); | |
| 527 | try test__floatuntidf(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57); | |
| 528 | try test__floatuntidf(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57); | |
| 529 | try test__floatuntidf(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57); | |
| 530 | try test__floatuntidf(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57); | |
| 531 | try test__floatuntidf(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57); | |
| 532 | try test__floatuntidf(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57); | |
| 533 | try test__floatuntidf(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57); | |
| 534 | try test__floatuntidf(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57); | |
| 535 | try test__floatuntidf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57); | |
| 536 | ||
| 537 | try test__floatuntidf(make_uti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121); | |
| 538 | try test__floatuntidf(make_uti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496Dp+121); | |
| 539 | try test__floatuntidf(make_uti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496Ep+121); | |
| 540 | try test__floatuntidf(make_uti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496Ep+121); | |
| 541 | try test__floatuntidf(make_uti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496Ep+121); | |
| 542 | try test__floatuntidf(make_uti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496Ep+121); | |
| 543 | try test__floatuntidf(make_uti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496Ep+121); | |
| 544 | try test__floatuntidf(make_uti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496Ep+121); | |
| 545 | try test__floatuntidf(make_uti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496Ep+121); | |
| 546 | try test__floatuntidf(make_uti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496Ep+121); | |
| 547 | try test__floatuntidf(make_uti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496Ep+121); | |
| 548 | try test__floatuntidf(make_uti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496Fp+121); | |
| 549 | try test__floatuntidf(make_uti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496Fp+121); | |
| 550 | try test__floatuntidf(make_uti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496Fp+121); | |
| 551 | try test__floatuntidf(make_uti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121); | |
| 552 | } | |
| 553 | ||
| 554 | fn test__floatsitf(a: i32, expected: u128) !void { | |
| 555 | const r = __floatsitf(a); | |
| 448 | test f64_floatFromInt_i128 { | |
| 449 | try test_f64_floatFromInt_i128(0, 0.0); | |
| 450 | ||
| 451 | try test_f64_floatFromInt_i128(1, 1.0); | |
| 452 | try test_f64_floatFromInt_i128(2, 2.0); | |
| 453 | try test_f64_floatFromInt_i128(20, 20.0); | |
| 454 | try test_f64_floatFromInt_i128(-1, -1.0); | |
| 455 | try test_f64_floatFromInt_i128(-2, -2.0); | |
| 456 | try test_f64_floatFromInt_i128(-20, -20.0); | |
| 457 | ||
| 458 | try test_f64_floatFromInt_i128(0x7FFFFF8000000000, 0x1.FFFFFEp+62); | |
| 459 | try test_f64_floatFromInt_i128(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62); | |
| 460 | try test_f64_floatFromInt_i128(0x7FFFFF0000000000, 0x1.FFFFFCp+62); | |
| 461 | try test_f64_floatFromInt_i128(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62); | |
| 462 | ||
| 463 | try test_f64_floatFromInt_i128(make_ti(0x8000008000000000, 0), -0x1.FFFFFEp+126); | |
| 464 | try test_f64_floatFromInt_i128(make_ti(0x8000000000000800, 0), -0x1.FFFFFFFFFFFFEp+126); | |
| 465 | try test_f64_floatFromInt_i128(make_ti(0x8000010000000000, 0), -0x1.FFFFFCp+126); | |
| 466 | try test_f64_floatFromInt_i128(make_ti(0x8000000000001000, 0), -0x1.FFFFFFFFFFFFCp+126); | |
| 467 | ||
| 468 | try test_f64_floatFromInt_i128(make_ti(0x8000000000000000, 0), -0x1.000000p+127); | |
| 469 | try test_f64_floatFromInt_i128(make_ti(0x8000000000000001, 0), -0x1.000000p+127); | |
| 470 | ||
| 471 | try test_f64_floatFromInt_i128(0x0007FB72E8000000, 0x1.FEDCBAp+50); | |
| 472 | ||
| 473 | try test_f64_floatFromInt_i128(0x0007FB72EA000000, 0x1.FEDCBA8p+50); | |
| 474 | try test_f64_floatFromInt_i128(0x0007FB72EB000000, 0x1.FEDCBACp+50); | |
| 475 | try test_f64_floatFromInt_i128(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50); | |
| 476 | try test_f64_floatFromInt_i128(0x0007FB72EC000000, 0x1.FEDCBBp+50); | |
| 477 | try test_f64_floatFromInt_i128(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50); | |
| 478 | ||
| 479 | try test_f64_floatFromInt_i128(0x0007FB72E6000000, 0x1.FEDCB98p+50); | |
| 480 | try test_f64_floatFromInt_i128(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); | |
| 481 | try test_f64_floatFromInt_i128(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50); | |
| 482 | try test_f64_floatFromInt_i128(0x0007FB72E4000001, 0x1.FEDCB90000004p+50); | |
| 483 | try test_f64_floatFromInt_i128(0x0007FB72E4000000, 0x1.FEDCB9p+50); | |
| 484 | ||
| 485 | try test_f64_floatFromInt_i128(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57); | |
| 486 | try test_f64_floatFromInt_i128(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57); | |
| 487 | try test_f64_floatFromInt_i128(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57); | |
| 488 | try test_f64_floatFromInt_i128(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57); | |
| 489 | try test_f64_floatFromInt_i128(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57); | |
| 490 | try test_f64_floatFromInt_i128(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57); | |
| 491 | try test_f64_floatFromInt_i128(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57); | |
| 492 | try test_f64_floatFromInt_i128(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57); | |
| 493 | try test_f64_floatFromInt_i128(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57); | |
| 494 | try test_f64_floatFromInt_i128(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57); | |
| 495 | try test_f64_floatFromInt_i128(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57); | |
| 496 | try test_f64_floatFromInt_i128(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57); | |
| 497 | try test_f64_floatFromInt_i128(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57); | |
| 498 | try test_f64_floatFromInt_i128(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57); | |
| 499 | try test_f64_floatFromInt_i128(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57); | |
| 500 | ||
| 501 | try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121); | |
| 502 | try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496Dp+121); | |
| 503 | try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496Ep+121); | |
| 504 | try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496Ep+121); | |
| 505 | try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496Ep+121); | |
| 506 | try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496Ep+121); | |
| 507 | try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496Ep+121); | |
| 508 | try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496Ep+121); | |
| 509 | try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496Ep+121); | |
| 510 | try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496Ep+121); | |
| 511 | try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496Ep+121); | |
| 512 | try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496Fp+121); | |
| 513 | try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496Fp+121); | |
| 514 | try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496Fp+121); | |
| 515 | try test_f64_floatFromInt_i128(make_ti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121); | |
| 516 | } | |
| 517 | ||
| 518 | test f64_floatFromInt_u128 { | |
| 519 | try test_f64_floatFromInt_u128(0, 0.0); | |
| 520 | ||
| 521 | try test_f64_floatFromInt_u128(1, 1.0); | |
| 522 | try test_f64_floatFromInt_u128(2, 2.0); | |
| 523 | try test_f64_floatFromInt_u128(20, 20.0); | |
| 524 | ||
| 525 | try test_f64_floatFromInt_u128(0x7FFFFF8000000000, 0x1.FFFFFEp+62); | |
| 526 | try test_f64_floatFromInt_u128(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62); | |
| 527 | try test_f64_floatFromInt_u128(0x7FFFFF0000000000, 0x1.FFFFFCp+62); | |
| 528 | try test_f64_floatFromInt_u128(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62); | |
| 529 | ||
| 530 | try test_f64_floatFromInt_u128(make_uti(0x8000008000000000, 0), 0x1.000001p+127); | |
| 531 | try test_f64_floatFromInt_u128(make_uti(0x8000000000000800, 0), 0x1.0000000000001p+127); | |
| 532 | try test_f64_floatFromInt_u128(make_uti(0x8000010000000000, 0), 0x1.000002p+127); | |
| 533 | try test_f64_floatFromInt_u128(make_uti(0x8000000000001000, 0), 0x1.0000000000002p+127); | |
| 534 | ||
| 535 | try test_f64_floatFromInt_u128(make_uti(0x8000000000000000, 0), 0x1.000000p+127); | |
| 536 | try test_f64_floatFromInt_u128(make_uti(0x8000000000000001, 0), 0x1.0000000000000002p+127); | |
| 537 | ||
| 538 | try test_f64_floatFromInt_u128(0x0007FB72E8000000, 0x1.FEDCBAp+50); | |
| 539 | ||
| 540 | try test_f64_floatFromInt_u128(0x0007FB72EA000000, 0x1.FEDCBA8p+50); | |
| 541 | try test_f64_floatFromInt_u128(0x0007FB72EB000000, 0x1.FEDCBACp+50); | |
| 542 | try test_f64_floatFromInt_u128(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50); | |
| 543 | try test_f64_floatFromInt_u128(0x0007FB72EC000000, 0x1.FEDCBBp+50); | |
| 544 | try test_f64_floatFromInt_u128(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50); | |
| 545 | ||
| 546 | try test_f64_floatFromInt_u128(0x0007FB72E6000000, 0x1.FEDCB98p+50); | |
| 547 | try test_f64_floatFromInt_u128(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); | |
| 548 | try test_f64_floatFromInt_u128(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50); | |
| 549 | try test_f64_floatFromInt_u128(0x0007FB72E4000001, 0x1.FEDCB90000004p+50); | |
| 550 | try test_f64_floatFromInt_u128(0x0007FB72E4000000, 0x1.FEDCB9p+50); | |
| 551 | ||
| 552 | try test_f64_floatFromInt_u128(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57); | |
| 553 | try test_f64_floatFromInt_u128(0x023479FD0E092DA1, 0x1.1A3CFE870496Dp+57); | |
| 554 | try test_f64_floatFromInt_u128(0x023479FD0E092DB0, 0x1.1A3CFE870496Ep+57); | |
| 555 | try test_f64_floatFromInt_u128(0x023479FD0E092DB8, 0x1.1A3CFE870496Ep+57); | |
| 556 | try test_f64_floatFromInt_u128(0x023479FD0E092DB6, 0x1.1A3CFE870496Ep+57); | |
| 557 | try test_f64_floatFromInt_u128(0x023479FD0E092DBF, 0x1.1A3CFE870496Ep+57); | |
| 558 | try test_f64_floatFromInt_u128(0x023479FD0E092DC1, 0x1.1A3CFE870496Ep+57); | |
| 559 | try test_f64_floatFromInt_u128(0x023479FD0E092DC7, 0x1.1A3CFE870496Ep+57); | |
| 560 | try test_f64_floatFromInt_u128(0x023479FD0E092DC8, 0x1.1A3CFE870496Ep+57); | |
| 561 | try test_f64_floatFromInt_u128(0x023479FD0E092DCF, 0x1.1A3CFE870496Ep+57); | |
| 562 | try test_f64_floatFromInt_u128(0x023479FD0E092DD0, 0x1.1A3CFE870496Ep+57); | |
| 563 | try test_f64_floatFromInt_u128(0x023479FD0E092DD1, 0x1.1A3CFE870496Fp+57); | |
| 564 | try test_f64_floatFromInt_u128(0x023479FD0E092DD8, 0x1.1A3CFE870496Fp+57); | |
| 565 | try test_f64_floatFromInt_u128(0x023479FD0E092DDF, 0x1.1A3CFE870496Fp+57); | |
| 566 | try test_f64_floatFromInt_u128(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57); | |
| 567 | ||
| 568 | try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121); | |
| 569 | try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496Dp+121); | |
| 570 | try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496Ep+121); | |
| 571 | try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496Ep+121); | |
| 572 | try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496Ep+121); | |
| 573 | try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496Ep+121); | |
| 574 | try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496Ep+121); | |
| 575 | try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496Ep+121); | |
| 576 | try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496Ep+121); | |
| 577 | try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496Ep+121); | |
| 578 | try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496Ep+121); | |
| 579 | try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496Fp+121); | |
| 580 | try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496Fp+121); | |
| 581 | try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496Fp+121); | |
| 582 | try test_f64_floatFromInt_u128(make_uti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121); | |
| 583 | } | |
| 584 | ||
| 585 | fn test_f128_floatFromInt_i32(a: i32, expected: u128) !void { | |
| 586 | const r = f128_floatFromInt_i32(a); | |
| 556 | 587 | try std.testing.expect(@as(u128, @bitCast(r)) == expected); |
| 557 | 588 | } |
| 558 | 589 | |
| 559 | test "floatsitf" { | |
| 560 | try test__floatsitf(0, 0); | |
| 561 | try test__floatsitf(0x7FFFFFFF, 0x401dfffffffc00000000000000000000); | |
| 562 | try test__floatsitf(0x12345678, 0x401b2345678000000000000000000000); | |
| 563 | try test__floatsitf(-0x12345678, 0xc01b2345678000000000000000000000); | |
| 564 | try test__floatsitf(@bitCast(@as(u32, @intCast(0xffffffff))), 0xbfff0000000000000000000000000000); | |
| 565 | try test__floatsitf(@bitCast(@as(u32, @intCast(0x80000000))), 0xc01e0000000000000000000000000000); | |
| 566 | } | |
| 567 | ||
| 568 | fn test__floatunsitf(a: u32, expected_hi: u64, expected_lo: u64) !void { | |
| 569 | const x = __floatunsitf(a); | |
| 590 | fn test_f128_floatFromInt_u32(a: u32, expected_hi: u64, expected_lo: u64) !void { | |
| 591 | const x = f128_floatFromInt_u32(a); | |
| 570 | 592 | |
| 571 | 593 | const x_repr: u128 = @bitCast(x); |
| 572 | 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 | 603 | return; |
| 582 | 604 | } |
| 583 | 605 | } |
| 606 | return error.TestFailure; | |
| 607 | } | |
| 584 | 608 | |
| 585 | @panic("__floatunsitf test failure"); | |
| 609 | test 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 | } |
| 587 | 617 | |
| 588 | test "floatunsitf" { | |
| 589 | try test__floatunsitf(0x7fffffff, 0x401dfffffffc0000, 0x0); | |
| 590 | try test__floatunsitf(0, 0x0, 0x0); | |
| 591 | try test__floatunsitf(0xffffffff, 0x401efffffffe0000, 0x0); | |
| 592 | try test__floatunsitf(0x12345678, 0x401b234567800000, 0x0); | |
| 618 | test f128_floatFromInt_u32 { | |
| 619 | try test_f128_floatFromInt_u32(0x7fffffff, 0x401dfffffffc0000, 0x0); | |
| 620 | try test_f128_floatFromInt_u32(0, 0x0, 0x0); | |
| 621 | try test_f128_floatFromInt_u32(0xffffffff, 0x401efffffffe0000, 0x0); | |
| 622 | try test_f128_floatFromInt_u32(0x12345678, 0x401b234567800000, 0x0); | |
| 593 | 623 | } |
| 594 | 624 | |
| 595 | fn test__floatditf(a: i64, expected: f128) !void { | |
| 596 | const x = __floatditf(a); | |
| 625 | fn test_f128_floatFromInt_i64(a: i64, expected: f128) !void { | |
| 626 | const x = f128_floatFromInt_i64(a); | |
| 597 | 627 | try testing.expect(x == expected); |
| 598 | 628 | } |
| 599 | 629 | |
| 600 | fn test__floatunditf(a: u64, expected_hi: u64, expected_lo: u64) !void { | |
| 601 | const x = __floatunditf(a); | |
| 630 | fn test_f128_floatFromInt_u64(a: u64, expected_hi: u64, expected_lo: u64) !void { | |
| 631 | const x = f128_floatFromInt_u64(a); | |
| 602 | 632 | |
| 603 | 633 | const x_repr: u128 = @bitCast(x); |
| 604 | 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 | 643 | return; |
| 614 | 644 | } |
| 615 | 645 | } |
| 616 | ||
| 617 | @panic("__floatunditf test failure"); | |
| 618 | } | |
| 619 | ||
| 620 | test "floatditf" { | |
| 621 | try test__floatditf(0x7fffffffffffffff, make_tf(0x403dffffffffffff, 0xfffc000000000000)); | |
| 622 | try test__floatditf(0x123456789abcdef1, make_tf(0x403b23456789abcd, 0xef10000000000000)); | |
| 623 | try test__floatditf(0x2, make_tf(0x4000000000000000, 0x0)); | |
| 624 | try test__floatditf(0x1, make_tf(0x3fff000000000000, 0x0)); | |
| 625 | try test__floatditf(0x0, make_tf(0x0, 0x0)); | |
| 626 | try test__floatditf(@bitCast(@as(u64, 0xffffffffffffffff)), make_tf(0xbfff000000000000, 0x0)); | |
| 627 | try test__floatditf(@bitCast(@as(u64, 0xfffffffffffffffe)), make_tf(0xc000000000000000, 0x0)); | |
| 628 | try test__floatditf(-0x123456789abcdef1, make_tf(0xc03b23456789abcd, 0xef10000000000000)); | |
| 629 | try test__floatditf(@bitCast(@as(u64, 0x8000000000000000)), make_tf(0xc03e000000000000, 0x0)); | |
| 630 | } | |
| 631 | ||
| 632 | test "floatunditf" { | |
| 633 | try test__floatunditf(0xffffffffffffffff, 0x403effffffffffff, 0xfffe000000000000); | |
| 634 | try test__floatunditf(0xfffffffffffffffe, 0x403effffffffffff, 0xfffc000000000000); | |
| 635 | try test__floatunditf(0x8000000000000000, 0x403e000000000000, 0x0); | |
| 636 | try test__floatunditf(0x7fffffffffffffff, 0x403dffffffffffff, 0xfffc000000000000); | |
| 637 | try test__floatunditf(0x123456789abcdef1, 0x403b23456789abcd, 0xef10000000000000); | |
| 638 | try test__floatunditf(0x2, 0x4000000000000000, 0x0); | |
| 639 | try test__floatunditf(0x1, 0x3fff000000000000, 0x0); | |
| 640 | try test__floatunditf(0x0, 0x0, 0x0); | |
| 641 | } | |
| 642 | ||
| 643 | fn test__floattitf(a: i128, expected: f128) !void { | |
| 644 | const x = __floattitf(a); | |
| 646 | return error.TestFailure; | |
| 647 | } | |
| 648 | ||
| 649 | test f128_floatFromInt_i64 { | |
| 650 | try test_f128_floatFromInt_i64(0x7fffffffffffffff, make_tf(0x403dffffffffffff, 0xfffc000000000000)); | |
| 651 | try test_f128_floatFromInt_i64(0x123456789abcdef1, make_tf(0x403b23456789abcd, 0xef10000000000000)); | |
| 652 | try test_f128_floatFromInt_i64(0x2, make_tf(0x4000000000000000, 0x0)); | |
| 653 | try test_f128_floatFromInt_i64(0x1, make_tf(0x3fff000000000000, 0x0)); | |
| 654 | try test_f128_floatFromInt_i64(0x0, make_tf(0x0, 0x0)); | |
| 655 | try test_f128_floatFromInt_i64(@bitCast(@as(u64, 0xffffffffffffffff)), make_tf(0xbfff000000000000, 0x0)); | |
| 656 | try test_f128_floatFromInt_i64(@bitCast(@as(u64, 0xfffffffffffffffe)), make_tf(0xc000000000000000, 0x0)); | |
| 657 | try test_f128_floatFromInt_i64(-0x123456789abcdef1, make_tf(0xc03b23456789abcd, 0xef10000000000000)); | |
| 658 | try test_f128_floatFromInt_i64(@bitCast(@as(u64, 0x8000000000000000)), make_tf(0xc03e000000000000, 0x0)); | |
| 659 | } | |
| 660 | ||
| 661 | test f128_floatFromInt_u64 { | |
| 662 | try test_f128_floatFromInt_u64(0xffffffffffffffff, 0x403effffffffffff, 0xfffe000000000000); | |
| 663 | try test_f128_floatFromInt_u64(0xfffffffffffffffe, 0x403effffffffffff, 0xfffc000000000000); | |
| 664 | try test_f128_floatFromInt_u64(0x8000000000000000, 0x403e000000000000, 0x0); | |
| 665 | try test_f128_floatFromInt_u64(0x7fffffffffffffff, 0x403dffffffffffff, 0xfffc000000000000); | |
| 666 | try test_f128_floatFromInt_u64(0x123456789abcdef1, 0x403b23456789abcd, 0xef10000000000000); | |
| 667 | try test_f128_floatFromInt_u64(0x2, 0x4000000000000000, 0x0); | |
| 668 | try test_f128_floatFromInt_u64(0x1, 0x3fff000000000000, 0x0); | |
| 669 | try test_f128_floatFromInt_u64(0x0, 0x0, 0x0); | |
| 670 | } | |
| 671 | ||
| 672 | fn test_f128_floatFromInt_i128(a: i128, expected: f128) !void { | |
| 673 | const x = f128_floatFromInt_i128(a); | |
| 645 | 674 | try testing.expect(x == expected); |
| 646 | 675 | } |
| 647 | 676 | |
| 648 | fn test__floatuntitf(a: u128, expected: f128) !void { | |
| 649 | const x = __floatuntitf(a); | |
| 677 | fn test_f128_floatFromInt_u128(a: u128, expected: f128) !void { | |
| 678 | const x = f128_floatFromInt_u128(a); | |
| 650 | 679 | try testing.expect(x == expected); |
| 651 | 680 | } |
| 652 | 681 | |
| 653 | test "floattitf" { | |
| 654 | try test__floattitf(0, 0.0); | |
| 655 | ||
| 656 | try test__floattitf(1, 1.0); | |
| 657 | try test__floattitf(2, 2.0); | |
| 658 | try test__floattitf(20, 20.0); | |
| 659 | try test__floattitf(-1, -1.0); | |
| 660 | try test__floattitf(-2, -2.0); | |
| 661 | try test__floattitf(-20, -20.0); | |
| 662 | ||
| 663 | try test__floattitf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); | |
| 664 | try test__floattitf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62); | |
| 665 | try test__floattitf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); | |
| 666 | try test__floattitf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62); | |
| 667 | ||
| 668 | try test__floattitf(make_ti(0x8000008000000000, 0), -0x1.FFFFFEp+126); | |
| 669 | try test__floattitf(make_ti(0x8000000000000800, 0), -0x1.FFFFFFFFFFFFEp+126); | |
| 670 | try test__floattitf(make_ti(0x8000010000000000, 0), -0x1.FFFFFCp+126); | |
| 671 | try test__floattitf(make_ti(0x8000000000001000, 0), -0x1.FFFFFFFFFFFFCp+126); | |
| 672 | ||
| 673 | try test__floattitf(make_ti(0x8000000000000000, 0), -0x1.000000p+127); | |
| 674 | try test__floattitf(make_ti(0x8000000000000001, 0), -0x1.FFFFFFFFFFFFFFFCp+126); | |
| 675 | ||
| 676 | try test__floattitf(0x0007FB72E8000000, 0x1.FEDCBAp+50); | |
| 677 | ||
| 678 | try test__floattitf(0x0007FB72EA000000, 0x1.FEDCBA8p+50); | |
| 679 | try test__floattitf(0x0007FB72EB000000, 0x1.FEDCBACp+50); | |
| 680 | try test__floattitf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50); | |
| 681 | try test__floattitf(0x0007FB72EC000000, 0x1.FEDCBBp+50); | |
| 682 | try test__floattitf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50); | |
| 683 | ||
| 684 | try test__floattitf(0x0007FB72E6000000, 0x1.FEDCB98p+50); | |
| 685 | try test__floattitf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); | |
| 686 | try test__floattitf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50); | |
| 687 | try test__floattitf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50); | |
| 688 | try test__floattitf(0x0007FB72E4000000, 0x1.FEDCB9p+50); | |
| 689 | ||
| 690 | try test__floattitf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57); | |
| 691 | try test__floattitf(0x023479FD0E092DA1, 0x1.1A3CFE870496D08p+57); | |
| 692 | try test__floattitf(0x023479FD0E092DB0, 0x1.1A3CFE870496D8p+57); | |
| 693 | try test__floattitf(0x023479FD0E092DB8, 0x1.1A3CFE870496DCp+57); | |
| 694 | try test__floattitf(0x023479FD0E092DB6, 0x1.1A3CFE870496DBp+57); | |
| 695 | try test__floattitf(0x023479FD0E092DBF, 0x1.1A3CFE870496DF8p+57); | |
| 696 | try test__floattitf(0x023479FD0E092DC1, 0x1.1A3CFE870496E08p+57); | |
| 697 | try test__floattitf(0x023479FD0E092DC7, 0x1.1A3CFE870496E38p+57); | |
| 698 | try test__floattitf(0x023479FD0E092DC8, 0x1.1A3CFE870496E4p+57); | |
| 699 | try test__floattitf(0x023479FD0E092DCF, 0x1.1A3CFE870496E78p+57); | |
| 700 | try test__floattitf(0x023479FD0E092DD0, 0x1.1A3CFE870496E8p+57); | |
| 701 | try test__floattitf(0x023479FD0E092DD1, 0x1.1A3CFE870496E88p+57); | |
| 702 | try test__floattitf(0x023479FD0E092DD8, 0x1.1A3CFE870496ECp+57); | |
| 703 | try test__floattitf(0x023479FD0E092DDF, 0x1.1A3CFE870496EF8p+57); | |
| 704 | try test__floattitf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57); | |
| 705 | ||
| 706 | try test__floattitf(make_ti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121); | |
| 707 | try test__floattitf(make_ti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496D08p+121); | |
| 708 | try test__floattitf(make_ti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496D8p+121); | |
| 709 | try test__floattitf(make_ti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496DCp+121); | |
| 710 | try test__floattitf(make_ti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496DBp+121); | |
| 711 | try test__floattitf(make_ti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496DF8p+121); | |
| 712 | try test__floattitf(make_ti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496E08p+121); | |
| 713 | try test__floattitf(make_ti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496E38p+121); | |
| 714 | try test__floattitf(make_ti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496E4p+121); | |
| 715 | try test__floattitf(make_ti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496E78p+121); | |
| 716 | try test__floattitf(make_ti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496E8p+121); | |
| 717 | try test__floattitf(make_ti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496E88p+121); | |
| 718 | try test__floattitf(make_ti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496ECp+121); | |
| 719 | try test__floattitf(make_ti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496EF8p+121); | |
| 720 | try test__floattitf(make_ti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121); | |
| 721 | ||
| 722 | try test__floattitf(make_ti(0, 0xFFFFFFFFFFFFFFFF), 0x1.FFFFFFFFFFFFFFFEp+63); | |
| 723 | ||
| 724 | try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC2801), 0x1.23456789ABCDEF0123456789ABC3p+124); | |
| 725 | try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC3000), 0x1.23456789ABCDEF0123456789ABC3p+124); | |
| 726 | try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC37FF), 0x1.23456789ABCDEF0123456789ABC3p+124); | |
| 727 | try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC3800), 0x1.23456789ABCDEF0123456789ABC4p+124); | |
| 728 | try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC4000), 0x1.23456789ABCDEF0123456789ABC4p+124); | |
| 729 | try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC47FF), 0x1.23456789ABCDEF0123456789ABC4p+124); | |
| 730 | try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC4800), 0x1.23456789ABCDEF0123456789ABC4p+124); | |
| 731 | try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC4801), 0x1.23456789ABCDEF0123456789ABC5p+124); | |
| 732 | try test__floattitf(make_ti(0x123456789ABCDEF0, 0x123456789ABC57FF), 0x1.23456789ABCDEF0123456789ABC5p+124); | |
| 733 | } | |
| 734 | ||
| 735 | test "floatuntitf" { | |
| 736 | try test__floatuntitf(0, 0.0); | |
| 737 | ||
| 738 | try test__floatuntitf(1, 1.0); | |
| 739 | try test__floatuntitf(2, 2.0); | |
| 740 | try test__floatuntitf(20, 20.0); | |
| 741 | ||
| 742 | try test__floatuntitf(0x7FFFFF8000000000, 0x1.FFFFFEp+62); | |
| 743 | try test__floatuntitf(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62); | |
| 744 | try test__floatuntitf(0x7FFFFF0000000000, 0x1.FFFFFCp+62); | |
| 745 | try test__floatuntitf(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62); | |
| 746 | try test__floatuntitf(0x7FFFFFFFFFFFFFFF, 0xF.FFFFFFFFFFFFFFEp+59); | |
| 747 | try test__floatuntitf(0xFFFFFFFFFFFFFFFE, 0xF.FFFFFFFFFFFFFFEp+60); | |
| 748 | try test__floatuntitf(0xFFFFFFFFFFFFFFFF, 0xF.FFFFFFFFFFFFFFFp+60); | |
| 749 | ||
| 750 | try test__floatuntitf(0x8000008000000000, 0x8.000008p+60); | |
| 751 | try test__floatuntitf(0x8000000000000800, 0x8.0000000000008p+60); | |
| 752 | try test__floatuntitf(0x8000010000000000, 0x8.00001p+60); | |
| 753 | try test__floatuntitf(0x8000000000001000, 0x8.000000000001p+60); | |
| 754 | ||
| 755 | try test__floatuntitf(0x8000000000000000, 0x8p+60); | |
| 756 | try test__floatuntitf(0x8000000000000001, 0x8.000000000000001p+60); | |
| 757 | ||
| 758 | try test__floatuntitf(0x0007FB72E8000000, 0x1.FEDCBAp+50); | |
| 759 | ||
| 760 | try test__floatuntitf(0x0007FB72EA000000, 0x1.FEDCBA8p+50); | |
| 761 | try test__floatuntitf(0x0007FB72EB000000, 0x1.FEDCBACp+50); | |
| 762 | try test__floatuntitf(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50); | |
| 763 | try test__floatuntitf(0x0007FB72EC000000, 0x1.FEDCBBp+50); | |
| 764 | try test__floatuntitf(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50); | |
| 765 | ||
| 766 | try test__floatuntitf(0x0007FB72E6000000, 0x1.FEDCB98p+50); | |
| 767 | try test__floatuntitf(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); | |
| 768 | try test__floatuntitf(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50); | |
| 769 | try test__floatuntitf(0x0007FB72E4000001, 0x1.FEDCB90000004p+50); | |
| 770 | try test__floatuntitf(0x0007FB72E4000000, 0x1.FEDCB9p+50); | |
| 771 | ||
| 772 | try test__floatuntitf(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57); | |
| 773 | try test__floatuntitf(0x023479FD0E092DA1, 0x1.1A3CFE870496D08p+57); | |
| 774 | try test__floatuntitf(0x023479FD0E092DB0, 0x1.1A3CFE870496D8p+57); | |
| 775 | try test__floatuntitf(0x023479FD0E092DB8, 0x1.1A3CFE870496DCp+57); | |
| 776 | try test__floatuntitf(0x023479FD0E092DB6, 0x1.1A3CFE870496DBp+57); | |
| 777 | try test__floatuntitf(0x023479FD0E092DBF, 0x1.1A3CFE870496DF8p+57); | |
| 778 | try test__floatuntitf(0x023479FD0E092DC1, 0x1.1A3CFE870496E08p+57); | |
| 779 | try test__floatuntitf(0x023479FD0E092DC7, 0x1.1A3CFE870496E38p+57); | |
| 780 | try test__floatuntitf(0x023479FD0E092DC8, 0x1.1A3CFE870496E4p+57); | |
| 781 | try test__floatuntitf(0x023479FD0E092DCF, 0x1.1A3CFE870496E78p+57); | |
| 782 | try test__floatuntitf(0x023479FD0E092DD0, 0x1.1A3CFE870496E8p+57); | |
| 783 | try test__floatuntitf(0x023479FD0E092DD1, 0x1.1A3CFE870496E88p+57); | |
| 784 | try test__floatuntitf(0x023479FD0E092DD8, 0x1.1A3CFE870496ECp+57); | |
| 785 | try test__floatuntitf(0x023479FD0E092DDF, 0x1.1A3CFE870496EF8p+57); | |
| 786 | try test__floatuntitf(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57); | |
| 787 | ||
| 788 | try test__floatuntitf(make_uti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121); | |
| 789 | try test__floatuntitf(make_uti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496D08p+121); | |
| 790 | try test__floatuntitf(make_uti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496D8p+121); | |
| 791 | try test__floatuntitf(make_uti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496DCp+121); | |
| 792 | try test__floatuntitf(make_uti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496DBp+121); | |
| 793 | try test__floatuntitf(make_uti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496DF8p+121); | |
| 794 | try test__floatuntitf(make_uti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496E08p+121); | |
| 795 | try test__floatuntitf(make_uti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496E38p+121); | |
| 796 | try test__floatuntitf(make_uti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496E4p+121); | |
| 797 | try test__floatuntitf(make_uti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496E78p+121); | |
| 798 | try test__floatuntitf(make_uti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496E8p+121); | |
| 799 | try test__floatuntitf(make_uti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496E88p+121); | |
| 800 | try test__floatuntitf(make_uti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496ECp+121); | |
| 801 | try test__floatuntitf(make_uti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496EF8p+121); | |
| 802 | try test__floatuntitf(make_uti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121); | |
| 803 | ||
| 804 | try test__floatuntitf(make_uti(0, 0xFFFFFFFFFFFFFFFF), 0x1.FFFFFFFFFFFFFFFEp+63); | |
| 805 | ||
| 806 | try test__floatuntitf(make_uti(0xFFFFFFFFFFFFFFFF, 0x0000000000000000), 0x1.FFFFFFFFFFFFFFFEp+127); | |
| 807 | try test__floatuntitf(make_uti(0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF), 0x1.0000000000000000p+128); | |
| 808 | ||
| 809 | try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC2801), 0x1.23456789ABCDEF0123456789ABC3p+124); | |
| 810 | try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC3000), 0x1.23456789ABCDEF0123456789ABC3p+124); | |
| 811 | try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC37FF), 0x1.23456789ABCDEF0123456789ABC3p+124); | |
| 812 | try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC3800), 0x1.23456789ABCDEF0123456789ABC4p+124); | |
| 813 | try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC4000), 0x1.23456789ABCDEF0123456789ABC4p+124); | |
| 814 | try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC47FF), 0x1.23456789ABCDEF0123456789ABC4p+124); | |
| 815 | try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC4800), 0x1.23456789ABCDEF0123456789ABC4p+124); | |
| 816 | try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC4801), 0x1.23456789ABCDEF0123456789ABC5p+124); | |
| 817 | try test__floatuntitf(make_uti(0x123456789ABCDEF0, 0x123456789ABC57FF), 0x1.23456789ABCDEF0123456789ABC5p+124); | |
| 682 | test f128_floatFromInt_i128 { | |
| 683 | try test_f128_floatFromInt_i128(0, 0.0); | |
| 684 | ||
| 685 | try test_f128_floatFromInt_i128(1, 1.0); | |
| 686 | try test_f128_floatFromInt_i128(2, 2.0); | |
| 687 | try test_f128_floatFromInt_i128(20, 20.0); | |
| 688 | try test_f128_floatFromInt_i128(-1, -1.0); | |
| 689 | try test_f128_floatFromInt_i128(-2, -2.0); | |
| 690 | try test_f128_floatFromInt_i128(-20, -20.0); | |
| 691 | ||
| 692 | try test_f128_floatFromInt_i128(0x7FFFFF8000000000, 0x1.FFFFFEp+62); | |
| 693 | try test_f128_floatFromInt_i128(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62); | |
| 694 | try test_f128_floatFromInt_i128(0x7FFFFF0000000000, 0x1.FFFFFCp+62); | |
| 695 | try test_f128_floatFromInt_i128(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62); | |
| 696 | ||
| 697 | try test_f128_floatFromInt_i128(make_ti(0x8000008000000000, 0), -0x1.FFFFFEp+126); | |
| 698 | try test_f128_floatFromInt_i128(make_ti(0x8000000000000800, 0), -0x1.FFFFFFFFFFFFEp+126); | |
| 699 | try test_f128_floatFromInt_i128(make_ti(0x8000010000000000, 0), -0x1.FFFFFCp+126); | |
| 700 | try test_f128_floatFromInt_i128(make_ti(0x8000000000001000, 0), -0x1.FFFFFFFFFFFFCp+126); | |
| 701 | ||
| 702 | try test_f128_floatFromInt_i128(make_ti(0x8000000000000000, 0), -0x1.000000p+127); | |
| 703 | try test_f128_floatFromInt_i128(make_ti(0x8000000000000001, 0), -0x1.FFFFFFFFFFFFFFFCp+126); | |
| 704 | ||
| 705 | try test_f128_floatFromInt_i128(0x0007FB72E8000000, 0x1.FEDCBAp+50); | |
| 706 | ||
| 707 | try test_f128_floatFromInt_i128(0x0007FB72EA000000, 0x1.FEDCBA8p+50); | |
| 708 | try test_f128_floatFromInt_i128(0x0007FB72EB000000, 0x1.FEDCBACp+50); | |
| 709 | try test_f128_floatFromInt_i128(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50); | |
| 710 | try test_f128_floatFromInt_i128(0x0007FB72EC000000, 0x1.FEDCBBp+50); | |
| 711 | try test_f128_floatFromInt_i128(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50); | |
| 712 | ||
| 713 | try test_f128_floatFromInt_i128(0x0007FB72E6000000, 0x1.FEDCB98p+50); | |
| 714 | try test_f128_floatFromInt_i128(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); | |
| 715 | try test_f128_floatFromInt_i128(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50); | |
| 716 | try test_f128_floatFromInt_i128(0x0007FB72E4000001, 0x1.FEDCB90000004p+50); | |
| 717 | try test_f128_floatFromInt_i128(0x0007FB72E4000000, 0x1.FEDCB9p+50); | |
| 718 | ||
| 719 | try test_f128_floatFromInt_i128(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57); | |
| 720 | try test_f128_floatFromInt_i128(0x023479FD0E092DA1, 0x1.1A3CFE870496D08p+57); | |
| 721 | try test_f128_floatFromInt_i128(0x023479FD0E092DB0, 0x1.1A3CFE870496D8p+57); | |
| 722 | try test_f128_floatFromInt_i128(0x023479FD0E092DB8, 0x1.1A3CFE870496DCp+57); | |
| 723 | try test_f128_floatFromInt_i128(0x023479FD0E092DB6, 0x1.1A3CFE870496DBp+57); | |
| 724 | try test_f128_floatFromInt_i128(0x023479FD0E092DBF, 0x1.1A3CFE870496DF8p+57); | |
| 725 | try test_f128_floatFromInt_i128(0x023479FD0E092DC1, 0x1.1A3CFE870496E08p+57); | |
| 726 | try test_f128_floatFromInt_i128(0x023479FD0E092DC7, 0x1.1A3CFE870496E38p+57); | |
| 727 | try test_f128_floatFromInt_i128(0x023479FD0E092DC8, 0x1.1A3CFE870496E4p+57); | |
| 728 | try test_f128_floatFromInt_i128(0x023479FD0E092DCF, 0x1.1A3CFE870496E78p+57); | |
| 729 | try test_f128_floatFromInt_i128(0x023479FD0E092DD0, 0x1.1A3CFE870496E8p+57); | |
| 730 | try test_f128_floatFromInt_i128(0x023479FD0E092DD1, 0x1.1A3CFE870496E88p+57); | |
| 731 | try test_f128_floatFromInt_i128(0x023479FD0E092DD8, 0x1.1A3CFE870496ECp+57); | |
| 732 | try test_f128_floatFromInt_i128(0x023479FD0E092DDF, 0x1.1A3CFE870496EF8p+57); | |
| 733 | try test_f128_floatFromInt_i128(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57); | |
| 734 | ||
| 735 | try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121); | |
| 736 | try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496D08p+121); | |
| 737 | try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496D8p+121); | |
| 738 | try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496DCp+121); | |
| 739 | try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496DBp+121); | |
| 740 | try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496DF8p+121); | |
| 741 | try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496E08p+121); | |
| 742 | try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496E38p+121); | |
| 743 | try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496E4p+121); | |
| 744 | try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496E78p+121); | |
| 745 | try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496E8p+121); | |
| 746 | try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496E88p+121); | |
| 747 | try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496ECp+121); | |
| 748 | try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496EF8p+121); | |
| 749 | try test_f128_floatFromInt_i128(make_ti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121); | |
| 750 | ||
| 751 | try test_f128_floatFromInt_i128(make_ti(0, 0xFFFFFFFFFFFFFFFF), 0x1.FFFFFFFFFFFFFFFEp+63); | |
| 752 | ||
| 753 | try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC2801), 0x1.23456789ABCDEF0123456789ABC3p+124); | |
| 754 | try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC3000), 0x1.23456789ABCDEF0123456789ABC3p+124); | |
| 755 | try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC37FF), 0x1.23456789ABCDEF0123456789ABC3p+124); | |
| 756 | try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC3800), 0x1.23456789ABCDEF0123456789ABC4p+124); | |
| 757 | try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC4000), 0x1.23456789ABCDEF0123456789ABC4p+124); | |
| 758 | try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC47FF), 0x1.23456789ABCDEF0123456789ABC4p+124); | |
| 759 | try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC4800), 0x1.23456789ABCDEF0123456789ABC4p+124); | |
| 760 | try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC4801), 0x1.23456789ABCDEF0123456789ABC5p+124); | |
| 761 | try test_f128_floatFromInt_i128(make_ti(0x123456789ABCDEF0, 0x123456789ABC57FF), 0x1.23456789ABCDEF0123456789ABC5p+124); | |
| 762 | } | |
| 763 | ||
| 764 | test f128_floatFromInt_u128 { | |
| 765 | try test_f128_floatFromInt_u128(0, 0.0); | |
| 766 | ||
| 767 | try test_f128_floatFromInt_u128(1, 1.0); | |
| 768 | try test_f128_floatFromInt_u128(2, 2.0); | |
| 769 | try test_f128_floatFromInt_u128(20, 20.0); | |
| 770 | ||
| 771 | try test_f128_floatFromInt_u128(0x7FFFFF8000000000, 0x1.FFFFFEp+62); | |
| 772 | try test_f128_floatFromInt_u128(0x7FFFFFFFFFFFF800, 0x1.FFFFFFFFFFFFEp+62); | |
| 773 | try test_f128_floatFromInt_u128(0x7FFFFF0000000000, 0x1.FFFFFCp+62); | |
| 774 | try test_f128_floatFromInt_u128(0x7FFFFFFFFFFFF000, 0x1.FFFFFFFFFFFFCp+62); | |
| 775 | try test_f128_floatFromInt_u128(0x7FFFFFFFFFFFFFFF, 0xF.FFFFFFFFFFFFFFEp+59); | |
| 776 | try test_f128_floatFromInt_u128(0xFFFFFFFFFFFFFFFE, 0xF.FFFFFFFFFFFFFFEp+60); | |
| 777 | try test_f128_floatFromInt_u128(0xFFFFFFFFFFFFFFFF, 0xF.FFFFFFFFFFFFFFFp+60); | |
| 778 | ||
| 779 | try test_f128_floatFromInt_u128(0x8000008000000000, 0x8.000008p+60); | |
| 780 | try test_f128_floatFromInt_u128(0x8000000000000800, 0x8.0000000000008p+60); | |
| 781 | try test_f128_floatFromInt_u128(0x8000010000000000, 0x8.00001p+60); | |
| 782 | try test_f128_floatFromInt_u128(0x8000000000001000, 0x8.000000000001p+60); | |
| 783 | ||
| 784 | try test_f128_floatFromInt_u128(0x8000000000000000, 0x8p+60); | |
| 785 | try test_f128_floatFromInt_u128(0x8000000000000001, 0x8.000000000000001p+60); | |
| 786 | ||
| 787 | try test_f128_floatFromInt_u128(0x0007FB72E8000000, 0x1.FEDCBAp+50); | |
| 788 | ||
| 789 | try test_f128_floatFromInt_u128(0x0007FB72EA000000, 0x1.FEDCBA8p+50); | |
| 790 | try test_f128_floatFromInt_u128(0x0007FB72EB000000, 0x1.FEDCBACp+50); | |
| 791 | try test_f128_floatFromInt_u128(0x0007FB72EBFFFFFF, 0x1.FEDCBAFFFFFFCp+50); | |
| 792 | try test_f128_floatFromInt_u128(0x0007FB72EC000000, 0x1.FEDCBBp+50); | |
| 793 | try test_f128_floatFromInt_u128(0x0007FB72E8000001, 0x1.FEDCBA0000004p+50); | |
| 794 | ||
| 795 | try test_f128_floatFromInt_u128(0x0007FB72E6000000, 0x1.FEDCB98p+50); | |
| 796 | try test_f128_floatFromInt_u128(0x0007FB72E7000000, 0x1.FEDCB9Cp+50); | |
| 797 | try test_f128_floatFromInt_u128(0x0007FB72E7FFFFFF, 0x1.FEDCB9FFFFFFCp+50); | |
| 798 | try test_f128_floatFromInt_u128(0x0007FB72E4000001, 0x1.FEDCB90000004p+50); | |
| 799 | try test_f128_floatFromInt_u128(0x0007FB72E4000000, 0x1.FEDCB9p+50); | |
| 800 | ||
| 801 | try test_f128_floatFromInt_u128(0x023479FD0E092DC0, 0x1.1A3CFE870496Ep+57); | |
| 802 | try test_f128_floatFromInt_u128(0x023479FD0E092DA1, 0x1.1A3CFE870496D08p+57); | |
| 803 | try test_f128_floatFromInt_u128(0x023479FD0E092DB0, 0x1.1A3CFE870496D8p+57); | |
| 804 | try test_f128_floatFromInt_u128(0x023479FD0E092DB8, 0x1.1A3CFE870496DCp+57); | |
| 805 | try test_f128_floatFromInt_u128(0x023479FD0E092DB6, 0x1.1A3CFE870496DBp+57); | |
| 806 | try test_f128_floatFromInt_u128(0x023479FD0E092DBF, 0x1.1A3CFE870496DF8p+57); | |
| 807 | try test_f128_floatFromInt_u128(0x023479FD0E092DC1, 0x1.1A3CFE870496E08p+57); | |
| 808 | try test_f128_floatFromInt_u128(0x023479FD0E092DC7, 0x1.1A3CFE870496E38p+57); | |
| 809 | try test_f128_floatFromInt_u128(0x023479FD0E092DC8, 0x1.1A3CFE870496E4p+57); | |
| 810 | try test_f128_floatFromInt_u128(0x023479FD0E092DCF, 0x1.1A3CFE870496E78p+57); | |
| 811 | try test_f128_floatFromInt_u128(0x023479FD0E092DD0, 0x1.1A3CFE870496E8p+57); | |
| 812 | try test_f128_floatFromInt_u128(0x023479FD0E092DD1, 0x1.1A3CFE870496E88p+57); | |
| 813 | try test_f128_floatFromInt_u128(0x023479FD0E092DD8, 0x1.1A3CFE870496ECp+57); | |
| 814 | try test_f128_floatFromInt_u128(0x023479FD0E092DDF, 0x1.1A3CFE870496EF8p+57); | |
| 815 | try test_f128_floatFromInt_u128(0x023479FD0E092DE0, 0x1.1A3CFE870496Fp+57); | |
| 816 | ||
| 817 | try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DC0, 0), 0x1.1A3CFE870496Ep+121); | |
| 818 | try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DA1, 1), 0x1.1A3CFE870496D08p+121); | |
| 819 | try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DB0, 2), 0x1.1A3CFE870496D8p+121); | |
| 820 | try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DB8, 3), 0x1.1A3CFE870496DCp+121); | |
| 821 | try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DB6, 4), 0x1.1A3CFE870496DBp+121); | |
| 822 | try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DBF, 5), 0x1.1A3CFE870496DF8p+121); | |
| 823 | try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DC1, 6), 0x1.1A3CFE870496E08p+121); | |
| 824 | try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DC7, 7), 0x1.1A3CFE870496E38p+121); | |
| 825 | try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DC8, 8), 0x1.1A3CFE870496E4p+121); | |
| 826 | try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DCF, 9), 0x1.1A3CFE870496E78p+121); | |
| 827 | try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DD0, 0), 0x1.1A3CFE870496E8p+121); | |
| 828 | try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DD1, 11), 0x1.1A3CFE870496E88p+121); | |
| 829 | try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DD8, 12), 0x1.1A3CFE870496ECp+121); | |
| 830 | try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DDF, 13), 0x1.1A3CFE870496EF8p+121); | |
| 831 | try test_f128_floatFromInt_u128(make_uti(0x023479FD0E092DE0, 14), 0x1.1A3CFE870496Fp+121); | |
| 832 | ||
| 833 | try test_f128_floatFromInt_u128(make_uti(0, 0xFFFFFFFFFFFFFFFF), 0x1.FFFFFFFFFFFFFFFEp+63); | |
| 834 | ||
| 835 | try test_f128_floatFromInt_u128(make_uti(0xFFFFFFFFFFFFFFFF, 0x0000000000000000), 0x1.FFFFFFFFFFFFFFFEp+127); | |
| 836 | try test_f128_floatFromInt_u128(make_uti(0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF), 0x1.0000000000000000p+128); | |
| 837 | ||
| 838 | try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC2801), 0x1.23456789ABCDEF0123456789ABC3p+124); | |
| 839 | try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC3000), 0x1.23456789ABCDEF0123456789ABC3p+124); | |
| 840 | try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC37FF), 0x1.23456789ABCDEF0123456789ABC3p+124); | |
| 841 | try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC3800), 0x1.23456789ABCDEF0123456789ABC4p+124); | |
| 842 | try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC4000), 0x1.23456789ABCDEF0123456789ABC4p+124); | |
| 843 | try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC47FF), 0x1.23456789ABCDEF0123456789ABC4p+124); | |
| 844 | try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC4800), 0x1.23456789ABCDEF0123456789ABC4p+124); | |
| 845 | try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC4801), 0x1.23456789ABCDEF0123456789ABC5p+124); | |
| 846 | try test_f128_floatFromInt_u128(make_uti(0x123456789ABCDEF0, 0x123456789ABC57FF), 0x1.23456789ABCDEF0123456789ABC5p+124); | |
| 818 | 847 | } |
| 819 | 848 | |
| 820 | 849 | fn make_ti(high: u64, low: u64) i128 { |
| ... | ... | @@ -838,45 +867,40 @@ fn make_tf(high: u64, low: u64) f128 { |
| 838 | 867 | return @bitCast(result); |
| 839 | 868 | } |
| 840 | 869 | |
| 841 | test "conversion to f16" { | |
| 842 | try testing.expect(__floatunsihf(@as(u32, 0)) == 0.0); | |
| 843 | try testing.expect(__floatunsihf(@as(u32, 1)) == 1.0); | |
| 844 | try testing.expect(__floatunsihf(@as(u32, 65504)) == 65504); | |
| 845 | try testing.expect(__floatunsihf(@as(u32, 65504 + (1 << 4))) == math.inf(f16)); | |
| 846 | } | |
| 847 | ||
| 848 | test "conversion to f32" { | |
| 849 | try testing.expect(__floatunsisf(@as(u32, 0)) == 0.0); | |
| 850 | try testing.expect(__floatunsisf(@as(u32, math.maxInt(u32))) != 1.0); | |
| 851 | try testing.expect(__floatsisf(@as(i32, math.minInt(i32))) != 1.0); | |
| 852 | try testing.expect(__floatunsisf(@as(u32, math.maxInt(u24))) == math.maxInt(u24)); | |
| 853 | try testing.expect(__floatunsisf(@as(u32, math.maxInt(u24)) + 1) == math.maxInt(u24) + 1); // 0x100_0000 - Exact | |
| 854 | try testing.expect(__floatunsisf(@as(u32, math.maxInt(u24)) + 2) == math.maxInt(u24) + 1); // 0x100_0001 - Tie: Rounds down to even | |
| 855 | try testing.expect(__floatunsisf(@as(u32, math.maxInt(u24)) + 3) == math.maxInt(u24) + 3); // 0x100_0002 - Exact | |
| 856 | try testing.expect(__floatunsisf(@as(u32, math.maxInt(u24)) + 4) == math.maxInt(u24) + 5); // 0x100_0003 - Tie: Rounds up to even | |
| 857 | try testing.expect(__floatunsisf(@as(u32, math.maxInt(u24)) + 5) == math.maxInt(u24) + 5); // 0x100_0004 - Exact | |
| 858 | } | |
| 859 | ||
| 860 | test "conversion to f80" { | |
| 861 | const floatFromInt = @import("./float_from_int.zig").floatFromInt; | |
| 862 | ||
| 863 | try testing.expect(floatFromInt(f80, @as(i80, -12)) == -12); | |
| 864 | try testing.expect(@as(u80, @intFromFloat(floatFromInt(f80, @as(u64, math.maxInt(u64)) + 0))) == math.maxInt(u64) + 0); | |
| 865 | try testing.expect(@as(u80, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u64)) + 1))) == math.maxInt(u64) + 1); | |
| 866 | ||
| 867 | try testing.expect(floatFromInt(f80, @as(u32, 0)) == 0.0); | |
| 868 | try testing.expect(floatFromInt(f80, @as(u32, 1)) == 1.0); | |
| 869 | try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u32, math.maxInt(u24)) + 0))) == math.maxInt(u24)); | |
| 870 | try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u64)) + 0))) == math.maxInt(u64)); | |
| 871 | try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u64)) + 1))) == math.maxInt(u64) + 1); // Exact | |
| 872 | try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u64)) + 2))) == math.maxInt(u64) + 1); // Rounds down | |
| 873 | try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u64)) + 3))) == math.maxInt(u64) + 3); // Tie - Exact | |
| 874 | try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u64)) + 4))) == math.maxInt(u64) + 5); // Rounds up | |
| 875 | ||
| 876 | try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u65)) + 0))) == math.maxInt(u65) + 1); // Rounds up | |
| 877 | try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u65)) + 1))) == math.maxInt(u65) + 1); // Exact | |
| 878 | try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u65)) + 2))) == math.maxInt(u65) + 1); // Rounds down | |
| 879 | try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u65)) + 3))) == math.maxInt(u65) + 1); // Tie - Rounds down | |
| 880 | try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u65)) + 4))) == math.maxInt(u65) + 5); // Rounds up | |
| 881 | try testing.expect(@as(u128, @intFromFloat(floatFromInt(f80, @as(u80, math.maxInt(u65)) + 5))) == math.maxInt(u65) + 5); // Exact | |
| 870 | test f16_floatFromInt_u32 { | |
| 871 | try testing.expect(f16_floatFromInt_u32(0) == 0.0); | |
| 872 | try testing.expect(f16_floatFromInt_u32(1) == 1.0); | |
| 873 | try testing.expect(f16_floatFromInt_u32(65504) == 65504); | |
| 874 | try testing.expect(f16_floatFromInt_u32(65504 + (1 << 4)) == math.inf(f16)); | |
| 875 | } | |
| 876 | ||
| 877 | test f80_floatFromInt_u32 { | |
| 878 | try testing.expect(f80_floatFromInt_u32(0) == 0.0); | |
| 879 | try testing.expect(f80_floatFromInt_u32(1) == 1.0); | |
| 880 | try testing.expect(f80_floatFromInt_u32(math.maxInt(u24) + 0) == math.maxInt(u24)); | |
| 881 | } | |
| 882 | ||
| 883 | test f80_floatFromInt_u64 { | |
| 884 | try testing.expect(f80_floatFromInt_u64(math.maxInt(u64) + 0) == math.maxInt(u64) + 0); | |
| 885 | } | |
| 886 | ||
| 887 | test f80_floatFromInt_i128 { | |
| 888 | try testing.expect(f80_floatFromInt_i128(-12) == -12); | |
| 889 | } | |
| 890 | ||
| 891 | test f80_floatFromInt_u128 { | |
| 892 | try testing.expect(f80_floatFromInt_u128(math.maxInt(u64) + 1) == math.maxInt(u64) + 1); | |
| 893 | ||
| 894 | try testing.expect(f80_floatFromInt_u128(math.maxInt(u64) + 0) == math.maxInt(u64)); | |
| 895 | try testing.expect(f80_floatFromInt_u128(math.maxInt(u64) + 1) == math.maxInt(u64) + 1); // Exact | |
| 896 | try testing.expect(f80_floatFromInt_u128(math.maxInt(u64) + 2) == math.maxInt(u64) + 1); // Rounds down | |
| 897 | try testing.expect(f80_floatFromInt_u128(math.maxInt(u64) + 3) == math.maxInt(u64) + 3); // Tie - Exact | |
| 898 | try testing.expect(f80_floatFromInt_u128(math.maxInt(u64) + 4) == math.maxInt(u64) + 5); // Rounds up | |
| 899 | ||
| 900 | try testing.expect(f80_floatFromInt_u128(math.maxInt(u65) + 0) == math.maxInt(u65) + 1); // Rounds up | |
| 901 | try testing.expect(f80_floatFromInt_u128(math.maxInt(u65) + 1) == math.maxInt(u65) + 1); // Exact | |
| 902 | try testing.expect(f80_floatFromInt_u128(math.maxInt(u65) + 2) == math.maxInt(u65) + 1); // Rounds down | |
| 903 | try testing.expect(f80_floatFromInt_u128(math.maxInt(u65) + 3) == math.maxInt(u65) + 1); // Tie - Rounds down | |
| 904 | try testing.expect(f80_floatFromInt_u128(math.maxInt(u65) + 4) == math.maxInt(u65) + 5); // Rounds up | |
| 905 | try testing.expect(f80_floatFromInt_u128(math.maxInt(u65) + 5) == math.maxInt(u65) + 5); // Exact | |
| 882 | 906 | } |
lib/compiler_rt/floatdidf.zig deleted-23| ... | ... | @@ -1,23 +0,0 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 3 | const symbol = compiler_rt.symbol; | |
| 4 | const floatFromInt = @import("./float_from_int.zig").floatFromInt; | |
| 5 | ||
| 6 | comptime { | |
| 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 | ||
| 17 | pub fn __floatdidf(a: i64) callconv(.c) f64 { | |
| 18 | return floatFromInt(f64, a); | |
| 19 | } | |
| 20 | ||
| 21 | fn __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 @@ |
| 1 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 2 | const floatFromInt = @import("./float_from_int.zig").floatFromInt; | |
| 3 | ||
| 4 | comptime { | |
| 5 | symbol(&__floatdihf, "__floatdihf"); | |
| 6 | } | |
| 7 | ||
| 8 | fn __floatdihf(a: i64) callconv(.c) f16 { | |
| 9 | return floatFromInt(f16, a); | |
| 10 | } |
lib/compiler_rt/floatdisf.zig deleted-22| ... | ... | @@ -1,22 +0,0 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 3 | const floatFromInt = @import("./float_from_int.zig").floatFromInt; | |
| 4 | ||
| 5 | comptime { | |
| 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 | ||
| 16 | pub fn __floatdisf(a: i64) callconv(.c) f32 { | |
| 17 | return floatFromInt(f32, a); | |
| 18 | } | |
| 19 | ||
| 20 | fn __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 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const floatFromInt = @import("./float_from_int.zig").floatFromInt; | |
| 3 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 4 | ||
| 5 | comptime { | |
| 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 | ||
| 16 | pub fn __floatditf(a: i64) callconv(.c) f128 { | |
| 17 | return floatFromInt(f128, a); | |
| 18 | } | |
| 19 | ||
| 20 | fn _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 @@ |
| 1 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 2 | const floatFromInt = @import("./float_from_int.zig").floatFromInt; | |
| 3 | ||
| 4 | comptime { | |
| 5 | symbol(&__floatdixf, "__floatdixf"); | |
| 6 | } | |
| 7 | ||
| 8 | fn __floatdixf(a: i64) callconv(.c) f80 { | |
| 9 | return floatFromInt(f80, a); | |
| 10 | } |
lib/compiler_rt/floateidf.zig deleted-15| ... | ... | @@ -1,15 +0,0 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | ||
| 3 | const std = @import("std"); | |
| 4 | ||
| 5 | const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt; | |
| 6 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 7 | ||
| 8 | comptime { | |
| 9 | symbol(&__floateidf, "__floateidf"); | |
| 10 | } | |
| 11 | ||
| 12 | pub 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 @@ |
| 1 | const std = @import("std"); | |
| 2 | const builtin = @import("builtin"); | |
| 3 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 4 | const symbol = compiler_rt.symbol; | |
| 5 | const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt; | |
| 6 | ||
| 7 | comptime { | |
| 8 | symbol(&__floateihf, "__floateihf"); | |
| 9 | } | |
| 10 | ||
| 11 | pub 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 @@ |
| 1 | const std = @import("std"); | |
| 2 | const builtin = @import("builtin"); | |
| 3 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 4 | const symbol = compiler_rt.symbol; | |
| 5 | const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt; | |
| 6 | ||
| 7 | comptime { | |
| 8 | symbol(&__floateisf, "__floateisf"); | |
| 9 | } | |
| 10 | ||
| 11 | pub 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 @@ |
| 1 | const std = @import("std"); | |
| 2 | const builtin = @import("builtin"); | |
| 3 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 4 | const symbol = compiler_rt.symbol; | |
| 5 | const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt; | |
| 6 | ||
| 7 | comptime { | |
| 8 | symbol(&__floateitf, "__floateitf"); | |
| 9 | } | |
| 10 | ||
| 11 | pub 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 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | ||
| 3 | const std = @import("std"); | |
| 4 | ||
| 5 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 6 | const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt; | |
| 7 | ||
| 8 | comptime { | |
| 9 | symbol(&__floateixf, "__floateixf"); | |
| 10 | } | |
| 11 | ||
| 12 | pub 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 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = compiler_rt.symbol; | |
| 3 | const floatFromInt = @import("./float_from_int.zig").floatFromInt; | |
| 4 | ||
| 5 | comptime { | |
| 6 | if (compiler_rt.want_aeabi) { | |
| 7 | symbol(&__aeabi_i2d, "__aeabi_i2d"); | |
| 8 | } else { | |
| 9 | symbol(&__floatsidf, "__floatsidf"); | |
| 10 | } | |
| 11 | } | |
| 12 | ||
| 13 | pub fn __floatsidf(a: i32) callconv(.c) f64 { | |
| 14 | return floatFromInt(f64, a); | |
| 15 | } | |
| 16 | ||
| 17 | fn __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 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = compiler_rt.symbol; | |
| 3 | const floatFromInt = @import("./float_from_int.zig").floatFromInt; | |
| 4 | ||
| 5 | comptime { | |
| 6 | symbol(&__floatsihf, "__floatsihf"); | |
| 7 | } | |
| 8 | ||
| 9 | fn __floatsihf(a: i32) callconv(.c) f16 { | |
| 10 | return floatFromInt(f16, a); | |
| 11 | } |
lib/compiler_rt/floatsisf.zig deleted-19| ... | ... | @@ -1,19 +0,0 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = compiler_rt.symbol; | |
| 3 | const floatFromInt = @import("./float_from_int.zig").floatFromInt; | |
| 4 | ||
| 5 | comptime { | |
| 6 | if (compiler_rt.want_aeabi) { | |
| 7 | symbol(&__aeabi_i2f, "__aeabi_i2f"); | |
| 8 | } else { | |
| 9 | symbol(&__floatsisf, "__floatsisf"); | |
| 10 | } | |
| 11 | } | |
| 12 | ||
| 13 | pub fn __floatsisf(a: i32) callconv(.c) f32 { | |
| 14 | return floatFromInt(f32, a); | |
| 15 | } | |
| 16 | ||
| 17 | fn __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 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = compiler_rt.symbol; | |
| 3 | const floatFromInt = @import("./float_from_int.zig").floatFromInt; | |
| 4 | ||
| 5 | comptime { | |
| 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 | ||
| 16 | pub fn __floatsitf(a: i32) callconv(.c) f128 { | |
| 17 | return floatFromInt(f128, a); | |
| 18 | } | |
| 19 | ||
| 20 | fn _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 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const floatFromInt = @import("./float_from_int.zig").floatFromInt; | |
| 3 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 4 | ||
| 5 | comptime { | |
| 6 | symbol(&__floatsixf, "__floatsixf"); | |
| 7 | } | |
| 8 | ||
| 9 | fn __floatsixf(a: i32) callconv(.c) f80 { | |
| 10 | return floatFromInt(f80, a); | |
| 11 | } |
lib/compiler_rt/floattidf.zig deleted-11| ... | ... | @@ -1,11 +0,0 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 3 | const floatFromInt = @import("./float_from_int.zig").floatFromInt; | |
| 4 | ||
| 5 | comptime { | |
| 6 | symbol(&__floattidf, "__floattidf"); | |
| 7 | } | |
| 8 | ||
| 9 | pub fn __floattidf(a: i128) callconv(.c) f64 { | |
| 10 | return floatFromInt(f64, a); | |
| 11 | } |
lib/compiler_rt/floattihf.zig deleted-12| ... | ... | @@ -1,12 +0,0 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 3 | const symbol = compiler_rt.symbol; | |
| 4 | const floatFromInt = @import("./float_from_int.zig").floatFromInt; | |
| 5 | ||
| 6 | comptime { | |
| 7 | symbol(&__floattihf, "__floattihf"); | |
| 8 | } | |
| 9 | ||
| 10 | pub fn __floattihf(a: i128) callconv(.c) f16 { | |
| 11 | return floatFromInt(f16, a); | |
| 12 | } |
lib/compiler_rt/floattisf.zig deleted-11| ... | ... | @@ -1,11 +0,0 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const floatFromInt = @import("./float_from_int.zig").floatFromInt; | |
| 3 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 4 | ||
| 5 | comptime { | |
| 6 | symbol(&__floattisf, "__floattisf"); | |
| 7 | } | |
| 8 | ||
| 9 | pub fn __floattisf(a: i128) callconv(.c) f32 { | |
| 10 | return floatFromInt(f32, a); | |
| 11 | } |
lib/compiler_rt/floattitf.zig deleted-13| ... | ... | @@ -1,13 +0,0 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 3 | const floatFromInt = @import("./float_from_int.zig").floatFromInt; | |
| 4 | ||
| 5 | comptime { | |
| 6 | if (compiler_rt.want_ppc_abi) | |
| 7 | symbol(&__floattitf, "__floattikf"); | |
| 8 | symbol(&__floattitf, "__floattitf"); | |
| 9 | } | |
| 10 | ||
| 11 | pub fn __floattitf(a: i128) callconv(.c) f128 { | |
| 12 | return floatFromInt(f128, a); | |
| 13 | } |
lib/compiler_rt/floattixf.zig deleted-12| ... | ... | @@ -1,12 +0,0 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 3 | const symbol = compiler_rt.symbol; | |
| 4 | const floatFromInt = @import("./float_from_int.zig").floatFromInt; | |
| 5 | ||
| 6 | comptime { | |
| 7 | symbol(&__floattixf, "__floattixf"); | |
| 8 | } | |
| 9 | ||
| 10 | pub fn __floattixf(a: i128) callconv(.c) f80 { | |
| 11 | return floatFromInt(f80, a); | |
| 12 | } |
lib/compiler_rt/floatundidf.zig deleted-22| ... | ... | @@ -1,22 +0,0 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const floatFromInt = @import("./float_from_int.zig").floatFromInt; | |
| 3 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 4 | ||
| 5 | comptime { | |
| 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 | ||
| 16 | pub fn __floatundidf(a: u64) callconv(.c) f64 { | |
| 17 | return floatFromInt(f64, a); | |
| 18 | } | |
| 19 | ||
| 20 | fn __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 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = compiler_rt.symbol; | |
| 3 | const floatFromInt = @import("./float_from_int.zig").floatFromInt; | |
| 4 | ||
| 5 | comptime { | |
| 6 | symbol(&__floatundihf, "__floatundihf"); | |
| 7 | } | |
| 8 | ||
| 9 | fn __floatundihf(a: u64) callconv(.c) f16 { | |
| 10 | return floatFromInt(f16, a); | |
| 11 | } |
lib/compiler_rt/floatundisf.zig deleted-23| ... | ... | @@ -1,23 +0,0 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 3 | const symbol = compiler_rt.symbol; | |
| 4 | const floatFromInt = @import("./float_from_int.zig").floatFromInt; | |
| 5 | ||
| 6 | comptime { | |
| 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 | ||
| 17 | pub fn __floatundisf(a: u64) callconv(.c) f32 { | |
| 18 | return floatFromInt(f32, a); | |
| 19 | } | |
| 20 | ||
| 21 | fn __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 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = compiler_rt.symbol; | |
| 3 | const floatFromInt = @import("./float_from_int.zig").floatFromInt; | |
| 4 | ||
| 5 | comptime { | |
| 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 | ||
| 16 | pub fn __floatunditf(a: u64) callconv(.c) f128 { | |
| 17 | return floatFromInt(f128, a); | |
| 18 | } | |
| 19 | ||
| 20 | fn _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 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = compiler_rt.symbol; | |
| 3 | const floatFromInt = @import("./float_from_int.zig").floatFromInt; | |
| 4 | ||
| 5 | comptime { | |
| 6 | symbol(&__floatundixf, "__floatundixf"); | |
| 7 | } | |
| 8 | ||
| 9 | fn __floatundixf(a: u64) callconv(.c) f80 { | |
| 10 | return floatFromInt(f80, a); | |
| 11 | } |
lib/compiler_rt/floatuneidf.zig deleted-14| ... | ... | @@ -1,14 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | const builtin = @import("builtin"); | |
| 3 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 4 | const symbol = compiler_rt.symbol; | |
| 5 | const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt; | |
| 6 | ||
| 7 | comptime { | |
| 8 | symbol(&__floatuneidf, "__floatuneidf"); | |
| 9 | } | |
| 10 | ||
| 11 | pub 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 @@ |
| 1 | const std = @import("std"); | |
| 2 | const builtin = @import("builtin"); | |
| 3 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 4 | const symbol = compiler_rt.symbol; | |
| 5 | const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt; | |
| 6 | ||
| 7 | comptime { | |
| 8 | symbol(&__floatuneihf, "__floatuneihf"); | |
| 9 | } | |
| 10 | ||
| 11 | pub 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 @@ |
| 1 | const std = @import("std"); | |
| 2 | const builtin = @import("builtin"); | |
| 3 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 4 | const symbol = compiler_rt.symbol; | |
| 5 | const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt; | |
| 6 | ||
| 7 | comptime { | |
| 8 | symbol(&__floatuneisf, "__floatuneisf"); | |
| 9 | } | |
| 10 | ||
| 11 | pub 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 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | ||
| 3 | const std = @import("std"); | |
| 4 | ||
| 5 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 6 | const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt; | |
| 7 | ||
| 8 | comptime { | |
| 9 | symbol(&__floatuneitf, "__floatuneitf"); | |
| 10 | } | |
| 11 | ||
| 12 | pub 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 @@ |
| 1 | const std = @import("std"); | |
| 2 | const builtin = @import("builtin"); | |
| 3 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 4 | const symbol = compiler_rt.symbol; | |
| 5 | const floatFromBigInt = @import("float_from_int.zig").floatFromBigInt; | |
| 6 | ||
| 7 | comptime { | |
| 8 | symbol(&__floatuneixf, "__floatuneixf"); | |
| 9 | } | |
| 10 | ||
| 11 | pub 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 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = compiler_rt.symbol; | |
| 3 | const floatFromInt = @import("./float_from_int.zig").floatFromInt; | |
| 4 | ||
| 5 | comptime { | |
| 6 | if (compiler_rt.want_aeabi) { | |
| 7 | symbol(&__aeabi_ui2d, "__aeabi_ui2d"); | |
| 8 | } else { | |
| 9 | symbol(&__floatunsidf, "__floatunsidf"); | |
| 10 | } | |
| 11 | } | |
| 12 | ||
| 13 | pub fn __floatunsidf(a: u32) callconv(.c) f64 { | |
| 14 | return floatFromInt(f64, a); | |
| 15 | } | |
| 16 | ||
| 17 | fn __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 @@ |
| 1 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 2 | const floatFromInt = @import("./float_from_int.zig").floatFromInt; | |
| 3 | ||
| 4 | comptime { | |
| 5 | symbol(&__floatunsihf, "__floatunsihf"); | |
| 6 | } | |
| 7 | ||
| 8 | pub fn __floatunsihf(a: u32) callconv(.c) f16 { | |
| 9 | return floatFromInt(f16, a); | |
| 10 | } |
lib/compiler_rt/floatunsisf.zig deleted-19| ... | ... | @@ -1,19 +0,0 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const floatFromInt = @import("./float_from_int.zig").floatFromInt; | |
| 3 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 4 | ||
| 5 | comptime { | |
| 6 | if (compiler_rt.want_aeabi) { | |
| 7 | symbol(&__aeabi_ui2f, "__aeabi_ui2f"); | |
| 8 | } else { | |
| 9 | symbol(&__floatunsisf, "__floatunsisf"); | |
| 10 | } | |
| 11 | } | |
| 12 | ||
| 13 | pub fn __floatunsisf(a: u32) callconv(.c) f32 { | |
| 14 | return floatFromInt(f32, a); | |
| 15 | } | |
| 16 | ||
| 17 | fn __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 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const floatFromInt = @import("./float_from_int.zig").floatFromInt; | |
| 3 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 4 | ||
| 5 | comptime { | |
| 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 | ||
| 16 | pub fn __floatunsitf(a: u32) callconv(.c) f128 { | |
| 17 | return floatFromInt(f128, a); | |
| 18 | } | |
| 19 | ||
| 20 | fn _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 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = compiler_rt.symbol; | |
| 3 | const floatFromInt = @import("./float_from_int.zig").floatFromInt; | |
| 4 | ||
| 5 | comptime { | |
| 6 | symbol(&__floatunsixf, "__floatunsixf"); | |
| 7 | } | |
| 8 | ||
| 9 | fn __floatunsixf(a: u32) callconv(.c) f80 { | |
| 10 | return floatFromInt(f80, a); | |
| 11 | } |
lib/compiler_rt/floatuntidf.zig deleted-11| ... | ... | @@ -1,11 +0,0 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const floatFromInt = @import("./float_from_int.zig").floatFromInt; | |
| 3 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 4 | ||
| 5 | comptime { | |
| 6 | symbol(&__floatuntidf, "__floatuntidf"); | |
| 7 | } | |
| 8 | ||
| 9 | pub fn __floatuntidf(a: u128) callconv(.c) f64 { | |
| 10 | return floatFromInt(f64, a); | |
| 11 | } |
lib/compiler_rt/floatuntihf.zig deleted-11| ... | ... | @@ -1,11 +0,0 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 3 | const floatFromInt = @import("./float_from_int.zig").floatFromInt; | |
| 4 | ||
| 5 | comptime { | |
| 6 | symbol(&__floatuntihf, "__floatuntihf"); | |
| 7 | } | |
| 8 | ||
| 9 | pub fn __floatuntihf(a: u128) callconv(.c) f16 { | |
| 10 | return floatFromInt(f16, a); | |
| 11 | } |
lib/compiler_rt/floatuntisf.zig deleted-12| ... | ... | @@ -1,12 +0,0 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 3 | const symbol = compiler_rt.symbol; | |
| 4 | const floatFromInt = @import("./float_from_int.zig").floatFromInt; | |
| 5 | ||
| 6 | comptime { | |
| 7 | symbol(&__floatuntisf, "__floatuntisf"); | |
| 8 | } | |
| 9 | ||
| 10 | pub fn __floatuntisf(a: u128) callconv(.c) f32 { | |
| 11 | return floatFromInt(f32, a); | |
| 12 | } |
lib/compiler_rt/floatuntitf.zig deleted-13| ... | ... | @@ -1,13 +0,0 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const floatFromInt = @import("./float_from_int.zig").floatFromInt; | |
| 3 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 4 | ||
| 5 | comptime { | |
| 6 | if (compiler_rt.want_ppc_abi) | |
| 7 | symbol(&__floatuntitf, "__floatuntikf"); | |
| 8 | symbol(&__floatuntitf, "__floatuntitf"); | |
| 9 | } | |
| 10 | ||
| 11 | pub fn __floatuntitf(a: u128) callconv(.c) f128 { | |
| 12 | return floatFromInt(f128, a); | |
| 13 | } |
lib/compiler_rt/floatuntixf.zig deleted-12| ... | ... | @@ -1,12 +0,0 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 3 | const symbol = compiler_rt.symbol; | |
| 4 | const floatFromInt = @import("./float_from_int.zig").floatFromInt; | |
| 5 | ||
| 6 | comptime { | |
| 7 | symbol(&__floatuntixf, "__floatuntixf"); | |
| 8 | } | |
| 9 | ||
| 10 | pub 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 | 15 | const expect = std.testing.expect; |
| 16 | 16 | |
| 17 | 17 | const compiler_rt = @import("../compiler_rt.zig"); |
| 18 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 18 | const symbol = compiler_rt.symbol; | |
| 19 | 19 | |
| 20 | 20 | comptime { |
| 21 | 21 | // floor |
| ... | ... | @@ -23,10 +23,7 @@ comptime { |
| 23 | 23 | symbol(&floorf, "floorf"); |
| 24 | 24 | symbol(&floor, "floor"); |
| 25 | 25 | symbol(&__floorx, "__floorx"); |
| 26 | if (compiler_rt.want_ppc_abi) { | |
| 27 | symbol(&floorq, "floorf128"); | |
| 28 | } | |
| 29 | symbol(&floorq, "floorq"); | |
| 26 | symbol(&floorq, "floorf128"); | |
| 30 | 27 | symbol(&floorl, "floorl"); |
| 31 | 28 | |
| 32 | 29 | // ceil |
| ... | ... | @@ -34,59 +31,96 @@ comptime { |
| 34 | 31 | symbol(&ceilf, "ceilf"); |
| 35 | 32 | symbol(&ceil, "ceil"); |
| 36 | 33 | symbol(&__ceilx, "__ceilx"); |
| 37 | if (compiler_rt.want_ppc_abi) { | |
| 38 | symbol(&ceilq, "ceilf128"); | |
| 39 | } | |
| 40 | symbol(&ceilq, "ceilq"); | |
| 34 | symbol(&ceilq, "ceilf128"); | |
| 41 | 35 | symbol(&ceill, "ceill"); |
| 42 | 36 | } |
| 43 | 37 | |
| 44 | pub fn __floorh(x: f16) callconv(.c) f16 { | |
| 38 | fn __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 | } | |
| 41 | pub fn floor_f16(x: f16) f16 { | |
| 45 | 42 | return impl(f16, .floor, x); |
| 46 | 43 | } |
| 47 | 44 | |
| 48 | pub fn floorf(x: f32) callconv(.c) f32 { | |
| 45 | fn 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 | } | |
| 48 | pub fn floor_f32(x: f32) f32 { | |
| 49 | 49 | return impl(f32, .floor, x); |
| 50 | 50 | } |
| 51 | 51 | |
| 52 | pub fn floor(x: f64) callconv(.c) f64 { | |
| 52 | fn 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 | } | |
| 55 | pub fn floor_f64(x: f64) f64 { | |
| 53 | 56 | return impl(f64, .floor, x); |
| 54 | 57 | } |
| 55 | 58 | |
| 56 | pub fn __floorx(x: f80) callconv(.c) f80 { | |
| 59 | fn __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 | } | |
| 62 | pub fn floor_f80(x: f80) f80 { | |
| 57 | 63 | return impl(f80, .floor, x); |
| 58 | 64 | } |
| 59 | 65 | |
| 60 | pub fn floorq(x: f128) callconv(.c) f128 { | |
| 66 | fn 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 | } | |
| 69 | pub fn floor_f128(x: f128) f128 { | |
| 61 | 70 | return impl(f128, .floor, x); |
| 62 | 71 | } |
| 63 | 72 | |
| 64 | 73 | pub 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 | } |
| 67 | 81 | |
| 68 | pub fn __ceilh(x: f16) callconv(.c) f16 { | |
| 82 | fn __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 | } | |
| 85 | pub fn ceil_f16(x: f16) f16 { | |
| 69 | 86 | return impl(f16, .ceil, x); |
| 70 | 87 | } |
| 71 | 88 | |
| 72 | pub fn ceilf(x: f32) callconv(.c) f32 { | |
| 89 | fn 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 | } | |
| 92 | pub fn ceil_f32(x: f32) f32 { | |
| 73 | 93 | return impl(f32, .ceil, x); |
| 74 | 94 | } |
| 75 | 95 | |
| 76 | pub fn ceil(x: f64) callconv(.c) f64 { | |
| 96 | fn 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 | } | |
| 99 | pub fn ceil_f64(x: f64) f64 { | |
| 77 | 100 | return impl(f64, .ceil, x); |
| 78 | 101 | } |
| 79 | 102 | |
| 80 | pub fn __ceilx(x: f80) callconv(.c) f80 { | |
| 103 | fn __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 | } | |
| 106 | pub fn ceil_f80(x: f80) f80 { | |
| 81 | 107 | return impl(f80, .ceil, x); |
| 82 | 108 | } |
| 83 | 109 | |
| 84 | pub fn ceilq(x: f128) callconv(.c) f128 { | |
| 110 | fn 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 | } | |
| 113 | pub fn ceil_f128(x: f128) f128 { | |
| 85 | 114 | return impl(f128, .ceil, x); |
| 86 | 115 | } |
| 87 | 116 | |
| 88 | 117 | pub 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 | } |
| 91 | 125 | |
| 92 | 126 | 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 | } |
| 146 | 180 | |
| 147 | test "floor16" { | |
| 148 | try expect(__floorh(1.3) == 1.0); | |
| 149 | try expect(__floorh(-1.3) == -2.0); | |
| 150 | try expect(__floorh(0.2) == 0.0); | |
| 151 | } | |
| 152 | ||
| 153 | test "floor32" { | |
| 154 | try expect(floorf(1.3) == 1.0); | |
| 155 | try expect(floorf(-1.3) == -2.0); | |
| 156 | try expect(floorf(0.2) == 0.0); | |
| 157 | } | |
| 158 | ||
| 159 | test "floor64" { | |
| 160 | try expect(floor(1.3) == 1.0); | |
| 161 | try expect(floor(-1.3) == -2.0); | |
| 162 | try expect(floor(0.2) == 0.0); | |
| 163 | } | |
| 164 | ||
| 165 | test "floor80" { | |
| 166 | try expect(__floorx(1.3) == 1.0); | |
| 167 | try expect(__floorx(-1.3) == -2.0); | |
| 168 | try expect(__floorx(0.2) == 0.0); | |
| 169 | } | |
| 170 | ||
| 171 | test "floor128" { | |
| 172 | try expect(floorq(1.3) == 1.0); | |
| 173 | try expect(floorq(-1.3) == -2.0); | |
| 174 | try expect(floorq(0.2) == 0.0); | |
| 175 | } | |
| 176 | ||
| 177 | test "floor16.special" { | |
| 178 | try expect(__floorh(0.0) == 0.0); | |
| 179 | try expect(__floorh(-0.0) == -0.0); | |
| 180 | try expect(math.isPositiveInf(__floorh(math.inf(f16)))); | |
| 181 | try expect(math.isNegativeInf(__floorh(-math.inf(f16)))); | |
| 182 | try expect(math.isNan(__floorh(math.nan(f16)))); | |
| 183 | } | |
| 184 | ||
| 185 | test "floor32.special" { | |
| 186 | try expect(floorf(0.0) == 0.0); | |
| 187 | try expect(floorf(-0.0) == -0.0); | |
| 188 | try expect(math.isPositiveInf(floorf(math.inf(f32)))); | |
| 189 | try expect(math.isNegativeInf(floorf(-math.inf(f32)))); | |
| 190 | try expect(math.isNan(floorf(math.nan(f32)))); | |
| 191 | } | |
| 192 | ||
| 193 | test "floor64.special" { | |
| 194 | try expect(floor(0.0) == 0.0); | |
| 195 | try expect(floor(-0.0) == -0.0); | |
| 196 | try expect(math.isPositiveInf(floor(math.inf(f64)))); | |
| 197 | try expect(math.isNegativeInf(floor(-math.inf(f64)))); | |
| 198 | try expect(math.isNan(floor(math.nan(f64)))); | |
| 199 | } | |
| 200 | ||
| 201 | test "floor80.special" { | |
| 202 | try expect(__floorx(0.0) == 0.0); | |
| 203 | try expect(__floorx(-0.0) == -0.0); | |
| 204 | try expect(math.isPositiveInf(__floorx(math.inf(f80)))); | |
| 205 | try expect(math.isNegativeInf(__floorx(-math.inf(f80)))); | |
| 206 | try expect(math.isNan(__floorx(math.nan(f80)))); | |
| 207 | } | |
| 208 | ||
| 209 | test "floor128.special" { | |
| 210 | try expect(floorq(0.0) == 0.0); | |
| 211 | try expect(floorq(-0.0) == -0.0); | |
| 212 | try expect(math.isPositiveInf(floorq(math.inf(f128)))); | |
| 213 | try expect(math.isNegativeInf(floorq(-math.inf(f128)))); | |
| 214 | try expect(math.isNan(floorq(math.nan(f128)))); | |
| 215 | } | |
| 216 | ||
| 217 | test "ceil16" { | |
| 218 | try expect(__ceilh(1.3) == 2.0); | |
| 219 | try expect(__ceilh(-1.3) == -1.0); | |
| 220 | try expect(__ceilh(0.2) == 1.0); | |
| 221 | } | |
| 222 | ||
| 223 | test "ceil32" { | |
| 224 | try expect(ceilf(1.3) == 2.0); | |
| 225 | try expect(ceilf(-1.3) == -1.0); | |
| 226 | try expect(ceilf(0.2) == 1.0); | |
| 227 | } | |
| 228 | ||
| 229 | test "ceil64" { | |
| 230 | try expect(ceil(1.3) == 2.0); | |
| 231 | try expect(ceil(-1.3) == -1.0); | |
| 232 | try expect(ceil(0.2) == 1.0); | |
| 233 | } | |
| 234 | ||
| 235 | test "ceil80" { | |
| 236 | try expect(__ceilx(1.3) == 2.0); | |
| 237 | try expect(__ceilx(-1.3) == -1.0); | |
| 238 | try expect(__ceilx(0.2) == 1.0); | |
| 239 | } | |
| 240 | ||
| 241 | test "ceil128" { | |
| 242 | try expect(ceilq(1.3) == 2.0); | |
| 243 | try expect(ceilq(-1.3) == -1.0); | |
| 244 | try expect(ceilq(0.2) == 1.0); | |
| 245 | } | |
| 246 | ||
| 247 | test "ceil16.special" { | |
| 248 | try expect(__ceilh(0.0) == 0.0); | |
| 249 | try expect(__ceilh(-0.0) == -0.0); | |
| 250 | try expect(math.isPositiveInf(__ceilh(math.inf(f16)))); | |
| 251 | try expect(math.isNegativeInf(__ceilh(-math.inf(f16)))); | |
| 252 | try expect(math.isNan(__ceilh(math.nan(f16)))); | |
| 253 | } | |
| 254 | ||
| 255 | test "ceil32.special" { | |
| 256 | try expect(ceilf(0.0) == 0.0); | |
| 257 | try expect(ceilf(-0.0) == -0.0); | |
| 258 | try expect(math.isPositiveInf(ceilf(math.inf(f32)))); | |
| 259 | try expect(math.isNegativeInf(ceilf(-math.inf(f32)))); | |
| 260 | try expect(math.isNan(ceilf(math.nan(f32)))); | |
| 261 | } | |
| 262 | ||
| 263 | test "ceil64.special" { | |
| 264 | try expect(ceil(0.0) == 0.0); | |
| 265 | try expect(ceil(-0.0) == -0.0); | |
| 266 | try expect(math.isPositiveInf(ceil(math.inf(f64)))); | |
| 267 | try expect(math.isNegativeInf(ceil(-math.inf(f64)))); | |
| 268 | try expect(math.isNan(ceil(math.nan(f64)))); | |
| 269 | } | |
| 270 | ||
| 271 | test "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 | ||
| 279 | test "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)))); | |
| 181 | test floor_f16 { | |
| 182 | try expect(floor_f16(1.3) == 1.0); | |
| 183 | try expect(floor_f16(-1.3) == -2.0); | |
| 184 | try expect(floor_f16(-0.2) == -1.0); | |
| 185 | try expect(math.isPositiveZero(floor_f16(0.2))); | |
| 186 | try expect(math.isPositiveZero(floor_f16(0.0))); | |
| 187 | try expect(math.isNegativeZero(floor_f16(-0.0))); | |
| 188 | try expect(math.isPositiveInf(floor_f16(math.inf(f16)))); | |
| 189 | try expect(math.isNegativeInf(floor_f16(-math.inf(f16)))); | |
| 190 | try expect(math.isNan(floor_f16(math.nan(f16)))); | |
| 191 | } | |
| 192 | ||
| 193 | test floor_f32 { | |
| 194 | try expect(floor_f32(1.3) == 1.0); | |
| 195 | try expect(floor_f32(-1.3) == -2.0); | |
| 196 | try expect(floor_f32(-0.2) == -1.0); | |
| 197 | try expect(math.isPositiveZero(floor_f32(0.2))); | |
| 198 | try expect(math.isPositiveZero(floor_f32(0.0))); | |
| 199 | try expect(math.isNegativeZero(floor_f32(-0.0))); | |
| 200 | try expect(math.isPositiveInf(floor_f32(math.inf(f32)))); | |
| 201 | try expect(math.isNegativeInf(floor_f32(-math.inf(f32)))); | |
| 202 | try expect(math.isNan(floor_f32(math.nan(f32)))); | |
| 203 | } | |
| 204 | ||
| 205 | test floor_f64 { | |
| 206 | try expect(floor_f64(1.3) == 1.0); | |
| 207 | try expect(floor_f64(-1.3) == -2.0); | |
| 208 | try expect(floor_f64(-0.2) == -1.0); | |
| 209 | try expect(math.isPositiveZero(floor_f64(0.2))); | |
| 210 | try expect(math.isPositiveZero(floor_f64(0.0))); | |
| 211 | try expect(math.isNegativeZero(floor_f64(-0.0))); | |
| 212 | try expect(math.isPositiveInf(floor_f64(math.inf(f64)))); | |
| 213 | try expect(math.isNegativeInf(floor_f64(-math.inf(f64)))); | |
| 214 | try expect(math.isNan(floor_f64(math.nan(f64)))); | |
| 215 | } | |
| 216 | ||
| 217 | test floor_f80 { | |
| 218 | try expect(floor_f80(1.3) == 1.0); | |
| 219 | try expect(floor_f80(-1.3) == -2.0); | |
| 220 | try expect(floor_f80(-0.2) == -1.0); | |
| 221 | try expect(math.isPositiveZero(floor_f80(0.2))); | |
| 222 | try expect(math.isPositiveZero(floor_f80(0.0))); | |
| 223 | try expect(math.isNegativeZero(floor_f80(-0.0))); | |
| 224 | try expect(math.isPositiveInf(floor_f80(math.inf(f80)))); | |
| 225 | try expect(math.isNegativeInf(floor_f80(-math.inf(f80)))); | |
| 226 | try expect(math.isNan(floor_f80(math.nan(f80)))); | |
| 227 | } | |
| 228 | ||
| 229 | test floor_f128 { | |
| 230 | try expect(floor_f128(1.3) == 1.0); | |
| 231 | try expect(floor_f128(-1.3) == -2.0); | |
| 232 | try expect(floor_f128(-0.2) == -1.0); | |
| 233 | try expect(math.isPositiveZero(floor_f128(0.2))); | |
| 234 | try expect(math.isPositiveZero(floor_f128(0.0))); | |
| 235 | try expect(math.isNegativeZero(floor_f128(-0.0))); | |
| 236 | try expect(math.isPositiveInf(floor_f128(math.inf(f128)))); | |
| 237 | try expect(math.isNegativeInf(floor_f128(-math.inf(f128)))); | |
| 238 | try expect(math.isNan(floor_f128(math.nan(f128)))); | |
| 239 | } | |
| 240 | ||
| 241 | test ceil_f16 { | |
| 242 | try expect(ceil_f16(1.3) == 2.0); | |
| 243 | try expect(ceil_f16(-1.3) == -1.0); | |
| 244 | try expect(ceil_f16(0.2) == 1.0); | |
| 245 | try expect(math.isNegativeZero(ceil_f16(-0.2))); | |
| 246 | try expect(math.isPositiveZero(ceil_f16(0.0))); | |
| 247 | try expect(math.isNegativeZero(ceil_f16(-0.0))); | |
| 248 | try expect(math.isPositiveInf(ceil_f16(math.inf(f16)))); | |
| 249 | try expect(math.isNegativeInf(ceil_f16(-math.inf(f16)))); | |
| 250 | try expect(math.isNan(ceil_f16(math.nan(f16)))); | |
| 251 | } | |
| 252 | ||
| 253 | test ceil_f32 { | |
| 254 | try expect(ceil_f32(1.3) == 2.0); | |
| 255 | try expect(ceil_f32(-1.3) == -1.0); | |
| 256 | try expect(ceil_f32(0.2) == 1.0); | |
| 257 | try expect(math.isNegativeZero(ceil_f32(-0.2))); | |
| 258 | try expect(math.isPositiveZero(ceil_f32(0.0))); | |
| 259 | try expect(math.isNegativeZero(ceil_f32(-0.0))); | |
| 260 | try expect(math.isPositiveInf(ceil_f32(math.inf(f32)))); | |
| 261 | try expect(math.isNegativeInf(ceil_f32(-math.inf(f32)))); | |
| 262 | try expect(math.isNan(ceil_f32(math.nan(f32)))); | |
| 263 | } | |
| 264 | ||
| 265 | test ceil_f64 { | |
| 266 | try expect(ceil_f64(1.3) == 2.0); | |
| 267 | try expect(ceil_f64(-1.3) == -1.0); | |
| 268 | try expect(ceil_f64(0.2) == 1.0); | |
| 269 | try expect(math.isNegativeZero(ceil_f64(-0.2))); | |
| 270 | try expect(math.isPositiveZero(ceil_f64(0.0))); | |
| 271 | try expect(math.isNegativeZero(ceil_f64(-0.0))); | |
| 272 | try expect(math.isPositiveInf(ceil_f64(math.inf(f64)))); | |
| 273 | try expect(math.isNegativeInf(ceil_f64(-math.inf(f64)))); | |
| 274 | try expect(math.isNan(ceil_f64(math.nan(f64)))); | |
| 275 | } | |
| 276 | ||
| 277 | test ceil_f80 { | |
| 278 | try expect(ceil_f80(1.3) == 2.0); | |
| 279 | try expect(ceil_f80(-1.3) == -1.0); | |
| 280 | try expect(ceil_f80(0.2) == 1.0); | |
| 281 | try expect(math.isNegativeZero(ceil_f80(-0.2))); | |
| 282 | try expect(math.isPositiveZero(ceil_f80(0.0))); | |
| 283 | try expect(math.isNegativeZero(ceil_f80(-0.0))); | |
| 284 | try expect(math.isPositiveInf(ceil_f80(math.inf(f80)))); | |
| 285 | try expect(math.isNegativeInf(ceil_f80(-math.inf(f80)))); | |
| 286 | try expect(math.isNan(ceil_f80(math.nan(f80)))); | |
| 287 | } | |
| 288 | ||
| 289 | test ceil_f128 { | |
| 290 | try expect(ceil_f128(1.3) == 2.0); | |
| 291 | try expect(ceil_f128(-1.3) == -1.0); | |
| 292 | try expect(ceil_f128(0.2) == 1.0); | |
| 293 | try expect(math.isNegativeZero(ceil_f128(-0.2))); | |
| 294 | try expect(math.isPositiveZero(ceil_f128(0.0))); | |
| 295 | try expect(math.isNegativeZero(ceil_f128(-0.0))); | |
| 296 | try expect(math.isPositiveInf(ceil_f128(math.inf(f128)))); | |
| 297 | try expect(math.isNegativeInf(ceil_f128(-math.inf(f128)))); | |
| 298 | try expect(math.isNan(ceil_f128(math.nan(f128)))); | |
| 285 | 299 | } |
lib/compiler_rt/fma.zig+48-36| ... | ... | @@ -16,19 +16,22 @@ comptime { |
| 16 | 16 | symbol(&fmaf, "fmaf"); |
| 17 | 17 | symbol(&fma, "fma"); |
| 18 | 18 | symbol(&__fmax, "__fmax"); |
| 19 | if (compiler_rt.want_ppc_abi) { | |
| 20 | symbol(&fmaq, "fmaf128"); | |
| 21 | } | |
| 22 | symbol(&fmaq, "fmaq"); | |
| 19 | symbol(&fmaq, "fmaf128"); | |
| 23 | 20 | symbol(&fmal, "fmal"); |
| 24 | 21 | } |
| 25 | 22 | |
| 26 | pub fn __fmah(x: f16, y: f16, z: f16) callconv(.c) f16 { | |
| 23 | fn __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 | } | |
| 26 | pub fn fma_f16(x: f16, y: f16, z: f16) f16 { | |
| 27 | 27 | // TODO: more efficient implementation |
| 28 | return @floatCast(fmaf(x, y, z)); | |
| 28 | return @floatCast(fma_f32(x, y, z)); | |
| 29 | 29 | } |
| 30 | 30 | |
| 31 | pub fn fmaf(x: f32, y: f32, z: f32) callconv(.c) f32 { | |
| 31 | fn 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 | } | |
| 34 | pub fn fma_f32(x: f32, y: f32, z: f32) f32 { | |
| 32 | 35 | const xy = @as(f64, x) * y; |
| 33 | 36 | const xy_z = xy + z; |
| 34 | 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 | 45 | } |
| 43 | 46 | } |
| 44 | 47 | |
| 48 | fn 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 | 51 | /// NOTE: Upstream fma.c has been rewritten completely to raise fp exceptions more accurately. |
| 46 | pub fn fma(x: f64, y: f64, z: f64) callconv(.c) f64 { | |
| 52 | pub fn fma_f64(x: f64, y: f64, z: f64) f64 { | |
| 47 | 53 | if (!math.isFinite(x) or !math.isFinite(y)) { |
| 48 | 54 | return x * y + z; |
| 49 | 55 | } |
| ... | ... | @@ -90,11 +96,17 @@ pub fn fma(x: f64, y: f64, z: f64) callconv(.c) f64 { |
| 90 | 96 | } |
| 91 | 97 | } |
| 92 | 98 | |
| 93 | pub fn __fmax(a: f80, b: f80, c: f80) callconv(.c) f80 { | |
| 99 | fn __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 | } | |
| 102 | pub fn fma_f80(a: f80, b: f80, c: f80) f80 { | |
| 94 | 103 | // TODO: more efficient implementation |
| 95 | return @floatCast(fmaq(a, b, c)); | |
| 104 | return @floatCast(fma_f128(a, b, c)); | |
| 96 | 105 | } |
| 97 | 106 | |
| 107 | fn 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 | 110 | /// Fused multiply-add: Compute x * y + z with a single rounding error. |
| 99 | 111 | /// |
| 100 | 112 | /// 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 | 114 | /// |
| 103 | 115 | /// Dekker, T. A Floating-Point Technique for Extending the |
| 104 | 116 | /// Available Precision. Numer. Math. 18, 224-242 (1971). |
| 105 | pub fn fmaq(x: f128, y: f128, z: f128) callconv(.c) f128 { | |
| 117 | pub fn fma_f128(x: f128, y: f128, z: f128) f128 { | |
| 106 | 118 | if (!math.isFinite(x) or !math.isFinite(y)) { |
| 107 | 119 | return x * y + z; |
| 108 | 120 | } |
| ... | ... | @@ -151,10 +163,10 @@ pub fn fmaq(x: f128, y: f128, z: f128) callconv(.c) f128 { |
| 151 | 163 | |
| 152 | 164 | pub fn fmal(x: c_longdouble, y: c_longdouble, z: c_longdouble) callconv(.c) c_longdouble { |
| 153 | 165 | switch (@typeInfo(c_longdouble).float.bits) { |
| 154 | 64 => return fma(x, y, z), | |
| 155 | 80 => return __fmax(x, y, z), | |
| 156 | 128 => return fmaq(x, y, z), | |
| 157 | else => @compileError("unreachable"), | |
| 166 | 64 => return fma_f64(x, y, z), | |
| 167 | 80 => return fma_f80(x, y, z), | |
| 168 | 128 => return fma_f128(x, y, z), | |
| 169 | else => comptime unreachable, | |
| 158 | 170 | } |
| 159 | 171 | } |
| 160 | 172 | |
| ... | ... | @@ -316,35 +328,35 @@ fn dd_mul128(a: f128, b: f128) dd128 { |
| 316 | 328 | test "32" { |
| 317 | 329 | const epsilon = 0.000001; |
| 318 | 330 | |
| 319 | try expect(math.approxEqAbs(f32, fmaf(0.0, 5.0, 9.124), 9.124, epsilon)); | |
| 320 | try expect(math.approxEqAbs(f32, fmaf(0.2, 5.0, 9.124), 10.124, epsilon)); | |
| 321 | try expect(math.approxEqAbs(f32, fmaf(0.8923, 5.0, 9.124), 13.5855, epsilon)); | |
| 322 | try expect(math.approxEqAbs(f32, fmaf(1.5, 5.0, 9.124), 16.624, epsilon)); | |
| 323 | try expect(math.approxEqAbs(f32, fmaf(37.45, 5.0, 9.124), 196.374004, epsilon)); | |
| 324 | try expect(math.approxEqAbs(f32, fmaf(89.123, 5.0, 9.124), 454.739005, epsilon)); | |
| 325 | try expect(math.approxEqAbs(f32, fmaf(123123.234375, 5.0, 9.124), 615625.295875, epsilon)); | |
| 331 | try expect(math.approxEqAbs(f32, fma_f32(0.0, 5.0, 9.124), 9.124, epsilon)); | |
| 332 | try expect(math.approxEqAbs(f32, fma_f32(0.2, 5.0, 9.124), 10.124, epsilon)); | |
| 333 | try expect(math.approxEqAbs(f32, fma_f32(0.8923, 5.0, 9.124), 13.5855, epsilon)); | |
| 334 | try expect(math.approxEqAbs(f32, fma_f32(1.5, 5.0, 9.124), 16.624, epsilon)); | |
| 335 | try expect(math.approxEqAbs(f32, fma_f32(37.45, 5.0, 9.124), 196.374004, epsilon)); | |
| 336 | try expect(math.approxEqAbs(f32, fma_f32(89.123, 5.0, 9.124), 454.739005, epsilon)); | |
| 337 | try expect(math.approxEqAbs(f32, fma_f32(123123.234375, 5.0, 9.124), 615625.295875, epsilon)); | |
| 326 | 338 | } |
| 327 | 339 | |
| 328 | 340 | test "64" { |
| 329 | 341 | const epsilon = 0.000001; |
| 330 | 342 | |
| 331 | try expect(math.approxEqAbs(f64, fma(0.0, 5.0, 9.124), 9.124, epsilon)); | |
| 332 | try expect(math.approxEqAbs(f64, fma(0.2, 5.0, 9.124), 10.124, epsilon)); | |
| 333 | try expect(math.approxEqAbs(f64, fma(0.8923, 5.0, 9.124), 13.5855, epsilon)); | |
| 334 | try expect(math.approxEqAbs(f64, fma(1.5, 5.0, 9.124), 16.624, epsilon)); | |
| 335 | try expect(math.approxEqAbs(f64, fma(37.45, 5.0, 9.124), 196.374, epsilon)); | |
| 336 | try expect(math.approxEqAbs(f64, fma(89.123, 5.0, 9.124), 454.739, epsilon)); | |
| 337 | try expect(math.approxEqAbs(f64, fma(123123.234375, 5.0, 9.124), 615625.295875, epsilon)); | |
| 343 | try expect(math.approxEqAbs(f64, fma_f64(0.0, 5.0, 9.124), 9.124, epsilon)); | |
| 344 | try expect(math.approxEqAbs(f64, fma_f64(0.2, 5.0, 9.124), 10.124, epsilon)); | |
| 345 | try expect(math.approxEqAbs(f64, fma_f64(0.8923, 5.0, 9.124), 13.5855, epsilon)); | |
| 346 | try expect(math.approxEqAbs(f64, fma_f64(1.5, 5.0, 9.124), 16.624, epsilon)); | |
| 347 | try expect(math.approxEqAbs(f64, fma_f64(37.45, 5.0, 9.124), 196.374, epsilon)); | |
| 348 | try expect(math.approxEqAbs(f64, fma_f64(89.123, 5.0, 9.124), 454.739, epsilon)); | |
| 349 | try expect(math.approxEqAbs(f64, fma_f64(123123.234375, 5.0, 9.124), 615625.295875, epsilon)); | |
| 338 | 350 | } |
| 339 | 351 | |
| 340 | 352 | test "128" { |
| 341 | 353 | const epsilon = 0.000001; |
| 342 | 354 | |
| 343 | try expect(math.approxEqAbs(f128, fmaq(0.0, 5.0, 9.124), 9.124, epsilon)); | |
| 344 | try expect(math.approxEqAbs(f128, fmaq(0.2, 5.0, 9.124), 10.124, epsilon)); | |
| 345 | try expect(math.approxEqAbs(f128, fmaq(0.8923, 5.0, 9.124), 13.5855, epsilon)); | |
| 346 | try expect(math.approxEqAbs(f128, fmaq(1.5, 5.0, 9.124), 16.624, epsilon)); | |
| 347 | try expect(math.approxEqAbs(f128, fmaq(37.45, 5.0, 9.124), 196.374, epsilon)); | |
| 348 | try expect(math.approxEqAbs(f128, fmaq(89.123, 5.0, 9.124), 454.739, epsilon)); | |
| 349 | try expect(math.approxEqAbs(f128, fmaq(123123.234375, 5.0, 9.124), 615625.295875, epsilon)); | |
| 355 | try expect(math.approxEqAbs(f128, fma_f128(0.0, 5.0, 9.124), 9.124, epsilon)); | |
| 356 | try expect(math.approxEqAbs(f128, fma_f128(0.2, 5.0, 9.124), 10.124, epsilon)); | |
| 357 | try expect(math.approxEqAbs(f128, fma_f128(0.8923, 5.0, 9.124), 13.5855, epsilon)); | |
| 358 | try expect(math.approxEqAbs(f128, fma_f128(1.5, 5.0, 9.124), 16.624, epsilon)); | |
| 359 | try expect(math.approxEqAbs(f128, fma_f128(37.45, 5.0, 9.124), 196.374, epsilon)); | |
| 360 | try expect(math.approxEqAbs(f128, fma_f128(89.123, 5.0, 9.124), 454.739, epsilon)); | |
| 361 | try expect(math.approxEqAbs(f128, fma_f128(123123.234375, 5.0, 9.124), 615625.295875, epsilon)); | |
| 350 | 362 | } |
lib/compiler_rt/fmax.zig+25-13| ... | ... | @@ -10,39 +10,51 @@ comptime { |
| 10 | 10 | symbol(&fmaxf, "fmaxf"); |
| 11 | 11 | symbol(&fmax, "fmax"); |
| 12 | 12 | symbol(&__fmaxx, "__fmaxx"); |
| 13 | if (compiler_rt.want_ppc_abi) { | |
| 14 | symbol(&fmaxq, "fmaxf128"); | |
| 15 | } | |
| 16 | symbol(&fmaxq, "fmaxq"); | |
| 13 | symbol(&fmaxq, "fmaxf128"); | |
| 17 | 14 | symbol(&fmaxl, "fmaxl"); |
| 18 | 15 | } |
| 19 | 16 | |
| 20 | pub fn __fmaxh(x: f16, y: f16) callconv(.c) f16 { | |
| 17 | fn __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 | } | |
| 20 | pub fn fmax_f16(x: f16, y: f16) f16 { | |
| 21 | 21 | return generic_fmax(f16, x, y); |
| 22 | 22 | } |
| 23 | 23 | |
| 24 | pub fn fmaxf(x: f32, y: f32) callconv(.c) f32 { | |
| 24 | fn 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 | } | |
| 27 | pub fn fmax_f32(x: f32, y: f32) f32 { | |
| 25 | 28 | return generic_fmax(f32, x, y); |
| 26 | 29 | } |
| 27 | 30 | |
| 28 | pub fn fmax(x: f64, y: f64) callconv(.c) f64 { | |
| 31 | fn 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 | } | |
| 34 | pub fn fmax_f64(x: f64, y: f64) f64 { | |
| 29 | 35 | return generic_fmax(f64, x, y); |
| 30 | 36 | } |
| 31 | 37 | |
| 32 | pub fn __fmaxx(x: f80, y: f80) callconv(.c) f80 { | |
| 38 | fn __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 | } | |
| 41 | pub fn fmax_f80(x: f80, y: f80) f80 { | |
| 33 | 42 | return generic_fmax(f80, x, y); |
| 34 | 43 | } |
| 35 | 44 | |
| 36 | pub fn fmaxq(x: f128, y: f128) callconv(.c) f128 { | |
| 45 | fn 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 | } | |
| 48 | pub fn fmax_f128(x: f128, y: f128) f128 { | |
| 37 | 49 | return generic_fmax(f128, x, y); |
| 38 | 50 | } |
| 39 | 51 | |
| 40 | 52 | pub fn fmaxl(x: c_longdouble, y: c_longdouble) callconv(.c) c_longdouble { |
| 41 | 53 | switch (@typeInfo(c_longdouble).float.bits) { |
| 42 | 64 => return fmax(x, y), | |
| 43 | 80 => return __fmaxx(x, y), | |
| 44 | 128 => return fmaxq(x, y), | |
| 45 | else => @compileError("unreachable"), | |
| 54 | 64 => return fmax_f64(x, y), | |
| 55 | 80 => return fmax_f80(x, y), | |
| 56 | 128 => return fmax_f128(x, y), | |
| 57 | else => comptime unreachable, | |
| 46 | 58 | } |
| 47 | 59 | } |
| 48 | 60 |
lib/compiler_rt/fmin.zig+25-13| ... | ... | @@ -10,39 +10,51 @@ comptime { |
| 10 | 10 | symbol(&fminf, "fminf"); |
| 11 | 11 | symbol(&fmin, "fmin"); |
| 12 | 12 | symbol(&__fminx, "__fminx"); |
| 13 | if (compiler_rt.want_ppc_abi) { | |
| 14 | symbol(&fminq, "fminf128"); | |
| 15 | } | |
| 16 | symbol(&fminq, "fminq"); | |
| 13 | symbol(&fminq, "fminf128"); | |
| 17 | 14 | symbol(&fminl, "fminl"); |
| 18 | 15 | } |
| 19 | 16 | |
| 20 | pub fn __fminh(x: f16, y: f16) callconv(.c) f16 { | |
| 17 | fn __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 | } | |
| 20 | pub fn fmin_f16(x: f16, y: f16) f16 { | |
| 21 | 21 | return generic_fmin(f16, x, y); |
| 22 | 22 | } |
| 23 | 23 | |
| 24 | pub fn fminf(x: f32, y: f32) callconv(.c) f32 { | |
| 24 | fn 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 | } | |
| 27 | pub fn fmin_f32(x: f32, y: f32) f32 { | |
| 25 | 28 | return generic_fmin(f32, x, y); |
| 26 | 29 | } |
| 27 | 30 | |
| 28 | pub fn fmin(x: f64, y: f64) callconv(.c) f64 { | |
| 31 | fn 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 | } | |
| 34 | pub fn fmin_f64(x: f64, y: f64) f64 { | |
| 29 | 35 | return generic_fmin(f64, x, y); |
| 30 | 36 | } |
| 31 | 37 | |
| 32 | pub fn __fminx(x: f80, y: f80) callconv(.c) f80 { | |
| 38 | fn __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 | } | |
| 41 | pub fn fmin_f80(x: f80, y: f80) f80 { | |
| 33 | 42 | return generic_fmin(f80, x, y); |
| 34 | 43 | } |
| 35 | 44 | |
| 36 | pub fn fminq(x: f128, y: f128) callconv(.c) f128 { | |
| 45 | fn 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 | } | |
| 48 | pub fn fmin_f128(x: f128, y: f128) f128 { | |
| 37 | 49 | return generic_fmin(f128, x, y); |
| 38 | 50 | } |
| 39 | 51 | |
| 40 | 52 | pub fn fminl(x: c_longdouble, y: c_longdouble) callconv(.c) c_longdouble { |
| 41 | 53 | switch (@typeInfo(c_longdouble).float.bits) { |
| 42 | 64 => return fmin(x, y), | |
| 43 | 80 => return __fminx(x, y), | |
| 44 | 128 => return fminq(x, y), | |
| 45 | else => @compileError("unreachable"), | |
| 54 | 64 => return fmin_f64(x, y), | |
| 55 | 80 => return fmin_f80(x, y), | |
| 56 | 128 => return fmin_f128(x, y), | |
| 57 | else => comptime unreachable, | |
| 46 | 58 | } |
| 47 | 59 | } |
| 48 | 60 |
lib/compiler_rt/fmod.zig+50-38| ... | ... | @@ -12,29 +12,38 @@ comptime { |
| 12 | 12 | symbol(&fmodf, "fmodf"); |
| 13 | 13 | symbol(&fmod, "fmod"); |
| 14 | 14 | symbol(&__fmodx, "__fmodx"); |
| 15 | if (compiler_rt.want_ppc_abi) { | |
| 16 | symbol(&fmodq, "fmodf128"); | |
| 17 | } | |
| 18 | symbol(&fmodq, "fmodq"); | |
| 15 | symbol(&fmodq, "fmodf128"); | |
| 19 | 16 | symbol(&fmodl, "fmodl"); |
| 20 | 17 | } |
| 21 | 18 | |
| 22 | pub fn __fmodh(x: f16, y: f16) callconv(.c) f16 { | |
| 19 | fn __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 | } | |
| 22 | pub fn fmod_f16(x: f16, y: f16) f16 { | |
| 23 | 23 | // TODO: more efficient implementation |
| 24 | return @floatCast(fmodf(x, y)); | |
| 24 | return @floatCast(fmod_f32(x, y)); | |
| 25 | 25 | } |
| 26 | 26 | |
| 27 | pub fn fmodf(x: f32, y: f32) callconv(.c) f32 { | |
| 27 | fn 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 | } | |
| 30 | pub fn fmod_f32(x: f32, y: f32) f32 { | |
| 28 | 31 | return generic_fmod(f32, x, y); |
| 29 | 32 | } |
| 30 | 33 | |
| 31 | pub fn fmod(x: f64, y: f64) callconv(.c) f64 { | |
| 34 | fn 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 | } | |
| 37 | pub fn fmod_f64(x: f64, y: f64) f64 { | |
| 32 | 38 | return generic_fmod(f64, x, y); |
| 33 | 39 | } |
| 34 | 40 | |
| 41 | fn __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 | 44 | /// fmodx - floating modulo large, returns the remainder of division for f80 types |
| 36 | 45 | /// Logic and flow heavily inspired by MUSL fmodl for 113 mantissa digits |
| 37 | pub fn __fmodx(a: f80, b: f80) callconv(.c) f80 { | |
| 46 | pub fn fmod_f80(a: f80, b: f80) f80 { | |
| 38 | 47 | const T = f80; |
| 39 | 48 | const Z = @Int(.unsigned, @bitSizeOf(T)); |
| 40 | 49 | |
| ... | ... | @@ -130,9 +139,12 @@ pub fn __fmodx(a: f80, b: f80) callconv(.c) f80 { |
| 130 | 139 | } |
| 131 | 140 | } |
| 132 | 141 | |
| 142 | fn 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 | 145 | /// fmodq - floating modulo large, returns the remainder of division for f128 types |
| 134 | 146 | /// Logic and flow heavily inspired by MUSL fmodl for 113 mantissa digits |
| 135 | pub fn fmodq(a: f128, b: f128) callconv(.c) f128 { | |
| 147 | pub fn fmod_f128(a: f128, b: f128) f128 { | |
| 136 | 148 | var amod = a; |
| 137 | 149 | var bmod = b; |
| 138 | 150 | const aPtr_u64: [*]u64 = @ptrCast(&amod); |
| ... | ... | @@ -251,10 +263,10 @@ pub fn fmodq(a: f128, b: f128) callconv(.c) f128 { |
| 251 | 263 | |
| 252 | 264 | pub fn fmodl(a: c_longdouble, b: c_longdouble) callconv(.c) c_longdouble { |
| 253 | 265 | switch (@typeInfo(c_longdouble).float.bits) { |
| 254 | 64 => return fmod(a, b), | |
| 255 | 80 => return __fmodx(a, b), | |
| 256 | 128 => return fmodq(a, b), | |
| 257 | else => @compileError("unreachable"), | |
| 266 | 64 => return fmod_f64(a, b), | |
| 267 | 80 => return fmod_f80(a, b), | |
| 268 | 128 => return fmod_f128(a, b), | |
| 269 | else => comptime unreachable, | |
| 258 | 270 | } |
| 259 | 271 | } |
| 260 | 272 | |
| ... | ... | @@ -342,42 +354,42 @@ inline fn generic_fmod(comptime T: type, x: T, y: T) T { |
| 342 | 354 | return @bitCast(ux); |
| 343 | 355 | } |
| 344 | 356 | |
| 345 | test "fmodf" { | |
| 357 | test fmod_f32 { | |
| 346 | 358 | const nan_val = math.nan(f32); |
| 347 | 359 | const inf_val = math.inf(f32); |
| 348 | 360 | |
| 349 | try std.testing.expect(math.isNan(fmodf(nan_val, 1.0))); | |
| 350 | try std.testing.expect(math.isNan(fmodf(1.0, nan_val))); | |
| 351 | try std.testing.expect(math.isNan(fmodf(inf_val, 1.0))); | |
| 352 | try std.testing.expect(math.isNan(fmodf(0.0, 0.0))); | |
| 353 | try std.testing.expect(math.isNan(fmodf(1.0, 0.0))); | |
| 361 | try std.testing.expect(math.isNan(fmod_f32(nan_val, 1.0))); | |
| 362 | try std.testing.expect(math.isNan(fmod_f32(1.0, nan_val))); | |
| 363 | try std.testing.expect(math.isNan(fmod_f32(inf_val, 1.0))); | |
| 364 | try std.testing.expect(math.isNan(fmod_f32(0.0, 0.0))); | |
| 365 | try std.testing.expect(math.isNan(fmod_f32(1.0, 0.0))); | |
| 354 | 366 | |
| 355 | try std.testing.expectEqual(@as(f32, 0.0), fmodf(0.0, 2.0)); | |
| 356 | try std.testing.expectEqual(@as(f32, -0.0), fmodf(-0.0, 2.0)); | |
| 367 | try std.testing.expectEqual(@as(f32, 0.0), fmod_f32(0.0, 2.0)); | |
| 368 | try std.testing.expectEqual(@as(f32, -0.0), fmod_f32(-0.0, 2.0)); | |
| 357 | 369 | |
| 358 | try std.testing.expectEqual(@as(f32, -2.0), fmodf(-32.0, 10.0)); | |
| 359 | try std.testing.expectEqual(@as(f32, -2.0), fmodf(-32.0, -10.0)); | |
| 360 | try std.testing.expectEqual(@as(f32, 2.0), fmodf(32.0, 10.0)); | |
| 361 | try std.testing.expectEqual(@as(f32, 2.0), fmodf(32.0, -10.0)); | |
| 370 | try std.testing.expectEqual(@as(f32, -2.0), fmod_f32(-32.0, 10.0)); | |
| 371 | try std.testing.expectEqual(@as(f32, -2.0), fmod_f32(-32.0, -10.0)); | |
| 372 | try std.testing.expectEqual(@as(f32, 2.0), fmod_f32(32.0, 10.0)); | |
| 373 | try std.testing.expectEqual(@as(f32, 2.0), fmod_f32(32.0, -10.0)); | |
| 362 | 374 | } |
| 363 | 375 | |
| 364 | test "fmod" { | |
| 376 | test fmod_f64 { | |
| 365 | 377 | const nan_val = math.nan(f64); |
| 366 | 378 | const inf_val = math.inf(f64); |
| 367 | 379 | |
| 368 | try std.testing.expect(math.isNan(fmod(nan_val, 1.0))); | |
| 369 | try std.testing.expect(math.isNan(fmod(1.0, nan_val))); | |
| 370 | try std.testing.expect(math.isNan(fmod(inf_val, 1.0))); | |
| 371 | try std.testing.expect(math.isNan(fmod(0.0, 0.0))); | |
| 372 | try std.testing.expect(math.isNan(fmod(1.0, 0.0))); | |
| 380 | try std.testing.expect(math.isNan(fmod_f64(nan_val, 1.0))); | |
| 381 | try std.testing.expect(math.isNan(fmod_f64(1.0, nan_val))); | |
| 382 | try std.testing.expect(math.isNan(fmod_f64(inf_val, 1.0))); | |
| 383 | try std.testing.expect(math.isNan(fmod_f64(0.0, 0.0))); | |
| 384 | try std.testing.expect(math.isNan(fmod_f64(1.0, 0.0))); | |
| 373 | 385 | |
| 374 | try std.testing.expectEqual(@as(f64, 0.0), fmod(0.0, 2.0)); | |
| 375 | try std.testing.expectEqual(@as(f64, -0.0), fmod(-0.0, 2.0)); | |
| 386 | try std.testing.expectEqual(@as(f64, 0.0), fmod_f64(0.0, 2.0)); | |
| 387 | try std.testing.expectEqual(@as(f64, -0.0), fmod_f64(-0.0, 2.0)); | |
| 376 | 388 | |
| 377 | try std.testing.expectEqual(@as(f64, -2.0), fmod(-32.0, 10.0)); | |
| 378 | try std.testing.expectEqual(@as(f64, -2.0), fmod(-32.0, -10.0)); | |
| 379 | try std.testing.expectEqual(@as(f64, 2.0), fmod(32.0, 10.0)); | |
| 380 | try std.testing.expectEqual(@as(f64, 2.0), fmod(32.0, -10.0)); | |
| 389 | try std.testing.expectEqual(@as(f64, -2.0), fmod_f64(-32.0, 10.0)); | |
| 390 | try std.testing.expectEqual(@as(f64, -2.0), fmod_f64(-32.0, -10.0)); | |
| 391 | try std.testing.expectEqual(@as(f64, 2.0), fmod_f64(32.0, 10.0)); | |
| 392 | try std.testing.expectEqual(@as(f64, 2.0), fmod_f64(32.0, -10.0)); | |
| 381 | 393 | } |
| 382 | 394 | |
| 383 | 395 | test { |
lib/compiler_rt/fmodq_test.zig+32-32| ... | ... | @@ -1,52 +1,52 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | const fmod = @import("fmod.zig"); | |
| 2 | const fmod_f128 = @import("fmod.zig").fmod_f128; | |
| 3 | 3 | const testing = std.testing; |
| 4 | 4 | |
| 5 | fn test_fmodq(a: f128, b: f128, exp: f128) !void { | |
| 6 | const res = fmod.fmodq(a, b); | |
| 5 | fn test_fmod_f128(a: f128, b: f128, exp: f128) !void { | |
| 6 | const res = fmod_f128(a, b); | |
| 7 | 7 | try testing.expect(exp == res); |
| 8 | 8 | } |
| 9 | 9 | |
| 10 | fn test_fmodq_nans() !void { | |
| 11 | try testing.expect(std.math.isNan(fmod.fmodq(1.0, std.math.nan(f128)))); | |
| 12 | try testing.expect(std.math.isNan(fmod.fmodq(1.0, -std.math.nan(f128)))); | |
| 13 | try testing.expect(std.math.isNan(fmod.fmodq(std.math.nan(f128), 1.0))); | |
| 14 | try testing.expect(std.math.isNan(fmod.fmodq(-std.math.nan(f128), 1.0))); | |
| 10 | fn test_fmod_f128_nans() !void { | |
| 11 | try testing.expect(std.math.isNan(fmod_f128(1.0, std.math.nan(f128)))); | |
| 12 | try testing.expect(std.math.isNan(fmod_f128(1.0, -std.math.nan(f128)))); | |
| 13 | try testing.expect(std.math.isNan(fmod_f128(std.math.nan(f128), 1.0))); | |
| 14 | try testing.expect(std.math.isNan(fmod_f128(-std.math.nan(f128), 1.0))); | |
| 15 | 15 | } |
| 16 | 16 | |
| 17 | fn test_fmodq_infs() !void { | |
| 18 | try testing.expect(fmod.fmodq(1.0, std.math.inf(f128)) == 1.0); | |
| 19 | try testing.expect(fmod.fmodq(1.0, -std.math.inf(f128)) == 1.0); | |
| 20 | try testing.expect(std.math.isNan(fmod.fmodq(std.math.inf(f128), 1.0))); | |
| 21 | try testing.expect(std.math.isNan(fmod.fmodq(-std.math.inf(f128), 1.0))); | |
| 17 | fn test_fmod_f128_infs() !void { | |
| 18 | try testing.expect(fmod_f128(1.0, std.math.inf(f128)) == 1.0); | |
| 19 | try testing.expect(fmod_f128(1.0, -std.math.inf(f128)) == 1.0); | |
| 20 | try testing.expect(std.math.isNan(fmod_f128(std.math.inf(f128), 1.0))); | |
| 21 | try testing.expect(std.math.isNan(fmod_f128(-std.math.inf(f128), 1.0))); | |
| 22 | 22 | } |
| 23 | 23 | |
| 24 | test "fmodq" { | |
| 25 | try test_fmodq(6.8, 4.0, 2.8); | |
| 26 | try test_fmodq(6.8, -4.0, 2.8); | |
| 27 | try test_fmodq(-6.8, 4.0, -2.8); | |
| 28 | try test_fmodq(-6.8, -4.0, -2.8); | |
| 29 | try test_fmodq(3.0, 2.0, 1.0); | |
| 30 | try test_fmodq(-5.0, 3.0, -2.0); | |
| 31 | try test_fmodq(3.0, 2.0, 1.0); | |
| 32 | try test_fmodq(1.0, 2.0, 1.0); | |
| 33 | try test_fmodq(0.0, 1.0, 0.0); | |
| 34 | try test_fmodq(-0.0, 1.0, -0.0); | |
| 35 | try test_fmodq(7046119.0, 5558362.0, 1487757.0); | |
| 36 | try test_fmodq(9010357.0, 1957236.0, 1181413.0); | |
| 37 | try test_fmodq(5192296858534827628530496329220095, 10.0, 5.0); | |
| 38 | try test_fmodq(5192296858534827628530496329220095, 922337203681230954775807, 220474884073715748246157); | |
| 24 | test fmod_f128 { | |
| 25 | try test_fmod_f128(6.8, 4.0, 2.8); | |
| 26 | try test_fmod_f128(6.8, -4.0, 2.8); | |
| 27 | try test_fmod_f128(-6.8, 4.0, -2.8); | |
| 28 | try test_fmod_f128(-6.8, -4.0, -2.8); | |
| 29 | try test_fmod_f128(3.0, 2.0, 1.0); | |
| 30 | try test_fmod_f128(-5.0, 3.0, -2.0); | |
| 31 | try test_fmod_f128(3.0, 2.0, 1.0); | |
| 32 | try test_fmod_f128(1.0, 2.0, 1.0); | |
| 33 | try test_fmod_f128(0.0, 1.0, 0.0); | |
| 34 | try test_fmod_f128(-0.0, 1.0, -0.0); | |
| 35 | try test_fmod_f128(7046119.0, 5558362.0, 1487757.0); | |
| 36 | try test_fmod_f128(9010357.0, 1957236.0, 1181413.0); | |
| 37 | try test_fmod_f128(5192296858534827628530496329220095, 10.0, 5.0); | |
| 38 | try test_fmod_f128(5192296858534827628530496329220095, 922337203681230954775807, 220474884073715748246157); | |
| 39 | 39 | |
| 40 | 40 | // Denormals |
| 41 | 41 | const a1: f128 = 0xedcb34a235253948765432134674p-16494; |
| 42 | 42 | const b1: f128 = 0x5d2e38791cfbc0737402da5a9518p-16494; |
| 43 | 43 | const exp1: f128 = 0x336ec3affb2db8618e4e7d5e1c44p-16494; |
| 44 | try test_fmodq(a1, b1, exp1); | |
| 44 | try test_fmod_f128(a1, b1, exp1); | |
| 45 | 45 | const a2: f128 = 0x0.7654_3210_fdec_ba98_7654_3210_fdecp-16382; |
| 46 | 46 | const b2: f128 = 0x0.0012_fdac_bdef_1234_fdec_3222_1111p-16382; |
| 47 | 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); | |
| 49 | 49 | |
| 50 | try test_fmodq_nans(); | |
| 51 | try test_fmodq_infs(); | |
| 50 | try test_fmod_f128_nans(); | |
| 51 | try test_fmod_f128_infs(); | |
| 52 | 52 | } |
lib/compiler_rt/fmodx_test.zig+31-31| ... | ... | @@ -1,52 +1,52 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | 2 | const builtin = @import("builtin"); |
| 3 | const fmod = @import("fmod.zig"); | |
| 3 | const fmod_f80 = @import("fmod.zig").fmod_f80; | |
| 4 | 4 | const testing = std.testing; |
| 5 | 5 | |
| 6 | fn test_fmodx(a: f80, b: f80, exp: f80) !void { | |
| 7 | const res = fmod.__fmodx(a, b); | |
| 6 | fn test_fmod_f80(a: f80, b: f80, exp: f80) !void { | |
| 7 | const res = fmod_f80(a, b); | |
| 8 | 8 | try testing.expect(exp == res); |
| 9 | 9 | } |
| 10 | 10 | |
| 11 | fn test_fmodx_nans() !void { | |
| 12 | try testing.expect(std.math.isNan(fmod.__fmodx(1.0, std.math.nan(f80)))); | |
| 13 | try testing.expect(std.math.isNan(fmod.__fmodx(1.0, -std.math.nan(f80)))); | |
| 14 | try testing.expect(std.math.isNan(fmod.__fmodx(std.math.nan(f80), 1.0))); | |
| 15 | try testing.expect(std.math.isNan(fmod.__fmodx(-std.math.nan(f80), 1.0))); | |
| 11 | fn test_fmod_f80_nans() !void { | |
| 12 | try testing.expect(std.math.isNan(fmod_f80(1.0, std.math.nan(f80)))); | |
| 13 | try testing.expect(std.math.isNan(fmod_f80(1.0, -std.math.nan(f80)))); | |
| 14 | try testing.expect(std.math.isNan(fmod_f80(std.math.nan(f80), 1.0))); | |
| 15 | try testing.expect(std.math.isNan(fmod_f80(-std.math.nan(f80), 1.0))); | |
| 16 | 16 | } |
| 17 | 17 | |
| 18 | fn test_fmodx_infs() !void { | |
| 19 | try testing.expect(fmod.__fmodx(1.0, std.math.inf(f80)) == 1.0); | |
| 20 | try testing.expect(fmod.__fmodx(1.0, -std.math.inf(f80)) == 1.0); | |
| 21 | try testing.expect(std.math.isNan(fmod.__fmodx(std.math.inf(f80), 1.0))); | |
| 22 | try testing.expect(std.math.isNan(fmod.__fmodx(-std.math.inf(f80), 1.0))); | |
| 18 | fn test_fmod_f80_infs() !void { | |
| 19 | try testing.expect(fmod_f80(1.0, std.math.inf(f80)) == 1.0); | |
| 20 | try testing.expect(fmod_f80(1.0, -std.math.inf(f80)) == 1.0); | |
| 21 | try testing.expect(std.math.isNan(fmod_f80(std.math.inf(f80), 1.0))); | |
| 22 | try testing.expect(std.math.isNan(fmod_f80(-std.math.inf(f80), 1.0))); | |
| 23 | 23 | } |
| 24 | 24 | |
| 25 | test "fmodx" { | |
| 26 | try test_fmodx(6.4, 4.0, 2.4); | |
| 27 | try test_fmodx(6.4, -4.0, 2.4); | |
| 28 | try test_fmodx(-6.4, 4.0, -2.4); | |
| 29 | try test_fmodx(-6.4, -4.0, -2.4); | |
| 30 | try test_fmodx(3.0, 2.0, 1.0); | |
| 31 | try test_fmodx(-5.0, 3.0, -2.0); | |
| 32 | try test_fmodx(3.0, 2.0, 1.0); | |
| 33 | try test_fmodx(1.0, 2.0, 1.0); | |
| 34 | try test_fmodx(0.0, 1.0, 0.0); | |
| 35 | try test_fmodx(-0.0, 1.0, -0.0); | |
| 36 | try test_fmodx(7046119.0, 5558362.0, 1487757.0); | |
| 37 | try test_fmodx(9010357.0, 1957236.0, 1181413.0); | |
| 38 | try test_fmodx(9223372036854775807, 10.0, 7.0); | |
| 25 | test fmod_f80 { | |
| 26 | try test_fmod_f80(6.4, 4.0, 2.4); | |
| 27 | try test_fmod_f80(6.4, -4.0, 2.4); | |
| 28 | try test_fmod_f80(-6.4, 4.0, -2.4); | |
| 29 | try test_fmod_f80(-6.4, -4.0, -2.4); | |
| 30 | try test_fmod_f80(3.0, 2.0, 1.0); | |
| 31 | try test_fmod_f80(-5.0, 3.0, -2.0); | |
| 32 | try test_fmod_f80(3.0, 2.0, 1.0); | |
| 33 | try test_fmod_f80(1.0, 2.0, 1.0); | |
| 34 | try test_fmod_f80(0.0, 1.0, 0.0); | |
| 35 | try test_fmod_f80(-0.0, 1.0, -0.0); | |
| 36 | try test_fmod_f80(7046119.0, 5558362.0, 1487757.0); | |
| 37 | try test_fmod_f80(9010357.0, 1957236.0, 1181413.0); | |
| 38 | try test_fmod_f80(9223372036854775807, 10.0, 7.0); | |
| 39 | 39 | |
| 40 | 40 | // Denormals |
| 41 | 41 | const a1: f80 = 0x0.76e5_9a51_1a92_9ca4p-16381; |
| 42 | 42 | const b1: f80 = 0x0.2e97_1c3c_8e7d_e03ap-16381; |
| 43 | 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 | 45 | const a2: f80 = 0x0.76e5_9a51_1a92_9ca4p-16381; |
| 46 | 46 | const b2: f80 = 0x0.0e97_1c3c_8e7d_e03ap-16381; |
| 47 | 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); | |
| 49 | 49 | |
| 50 | try test_fmodx_nans(); | |
| 51 | try test_fmodx_infs(); | |
| 50 | try test_fmod_f80_nans(); | |
| 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 | |
| 3 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 4 | const comparef = @import("./comparef.zig"); | |
| 5 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 6 | ||
| 7 | comptime { | |
| 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." | |
| 19 | pub 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." | |
| 25 | pub fn __gtdf2(a: f64, b: f64) callconv(.c) i32 { | |
| 26 | return __gedf2(a, b); | |
| 27 | } | |
| 28 | ||
| 29 | fn __aeabi_dcmpge(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) i32 { | |
| 30 | return @intFromBool(comparef.cmpf2(f64, comparef.GE, a, b) != .Less); | |
| 31 | } | |
| 32 | ||
| 33 | fn __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 | |
| 3 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 4 | const comparef = @import("./comparef.zig"); | |
| 5 | ||
| 6 | comptime { | |
| 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." | |
| 13 | pub 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." | |
| 19 | pub 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 | |
| 3 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 4 | const symbol = compiler_rt.symbol; | |
| 5 | const comparef = @import("./comparef.zig"); | |
| 6 | ||
| 7 | comptime { | |
| 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." | |
| 19 | pub 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." | |
| 25 | pub fn __gtsf2(a: f32, b: f32) callconv(.c) i32 { | |
| 26 | return __gesf2(a, b); | |
| 27 | } | |
| 28 | ||
| 29 | fn __aeabi_fcmpge(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) i32 { | |
| 30 | return @intFromBool(comparef.cmpf2(f32, comparef.GE, a, b) != .Less); | |
| 31 | } | |
| 32 | ||
| 33 | fn __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 | |
| 3 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 4 | const symbol = compiler_rt.symbol; | |
| 5 | const comparef = @import("./comparef.zig"); | |
| 6 | ||
| 7 | comptime { | |
| 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." | |
| 18 | fn __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." | |
| 24 | fn __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 @@ |
| 1 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 2 | const comparef = @import("./comparef.zig"); | |
| 3 | ||
| 4 | comptime { | |
| 5 | symbol(&__gexf2, "__gexf2"); | |
| 6 | symbol(&__gtxf2, "__gtxf2"); | |
| 7 | } | |
| 8 | ||
| 9 | fn __gexf2(a: f80, b: f80) callconv(.c) i32 { | |
| 10 | return @backingInt(comparef.cmp_f80(comparef.GE, a, b)); | |
| 11 | } | |
| 12 | ||
| 13 | fn __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 | 36 | |
| 37 | 37 | pub fn __divmodti4(a: i128, b: i128, rem: *i128) callconv(.c) i128 { |
| 38 | 38 | const d = __divti3(a, b); |
| 39 | rem.* = a -% (d * b); | |
| 39 | rem.* = a - d *% b; | |
| 40 | 40 | return d; |
| 41 | 41 | } |
| 42 | 42 | |
| ... | ... | @@ -69,7 +69,7 @@ fn test_one_divmodti4(a: i128, b: i128, expected_q: i128, expected_r: i128) !voi |
| 69 | 69 | |
| 70 | 70 | pub fn __divmoddi4(a: i64, b: i64, rem: *i64) callconv(.c) i64 { |
| 71 | 71 | const d = __divdi3(a, b); |
| 72 | rem.* = a -% (d * b); | |
| 72 | rem.* = a - d *% b; | |
| 73 | 73 | return d; |
| 74 | 74 | } |
| 75 | 75 | |
| ... | ... | @@ -79,21 +79,20 @@ fn test_one_divmoddi4(a: i64, b: i64, expected_q: i64, expected_r: i64) !void { |
| 79 | 79 | try testing.expect(q == expected_q and r == expected_r); |
| 80 | 80 | } |
| 81 | 81 | |
| 82 | const cases__divmoddi4 = | |
| 83 | [_][4]i64{ | |
| 84 | [_]i64{ 0, 1, 0, 0 }, | |
| 85 | [_]i64{ 0, -1, 0, 0 }, | |
| 86 | [_]i64{ 2, 1, 2, 0 }, | |
| 87 | [_]i64{ 2, -1, -2, 0 }, | |
| 88 | [_]i64{ -2, 1, -2, 0 }, | |
| 89 | [_]i64{ -2, -1, 2, 0 }, | |
| 90 | [_]i64{ 7, 5, 1, 2 }, | |
| 91 | [_]i64{ -7, 5, -1, -2 }, | |
| 92 | [_]i64{ 19, 5, 3, 4 }, | |
| 93 | [_]i64{ 19, -5, -3, 4 }, | |
| 94 | [_]i64{ @as(i64, @bitCast(@as(u64, 0x8000000000000000))), 8, @as(i64, @bitCast(@as(u64, 0xf000000000000000))), 0 }, | |
| 95 | [_]i64{ @as(i64, @bitCast(@as(u64, 0x8000000000000007))), 8, @as(i64, @bitCast(@as(u64, 0xf000000000000001))), -1 }, | |
| 96 | }; | |
| 82 | const cases__divmoddi4 = [_][4]i64{ | |
| 83 | [_]i64{ 0, 1, 0, 0 }, | |
| 84 | [_]i64{ 0, -1, 0, 0 }, | |
| 85 | [_]i64{ 2, 1, 2, 0 }, | |
| 86 | [_]i64{ 2, -1, -2, 0 }, | |
| 87 | [_]i64{ -2, 1, -2, 0 }, | |
| 88 | [_]i64{ -2, -1, 2, 0 }, | |
| 89 | [_]i64{ 7, 5, 1, 2 }, | |
| 90 | [_]i64{ -7, 5, -1, -2 }, | |
| 91 | [_]i64{ 19, 5, 3, 4 }, | |
| 92 | [_]i64{ 19, -5, -3, 4 }, | |
| 93 | [_]i64{ @as(i64, @bitCast(@as(u64, 0x8000000000000000))), 8, @as(i64, @bitCast(@as(u64, 0xf000000000000000))), 0 }, | |
| 94 | [_]i64{ @as(i64, @bitCast(@as(u64, 0x8000000000000007))), 8, @as(i64, @bitCast(@as(u64, 0xf000000000000001))), -1 }, | |
| 95 | }; | |
| 97 | 96 | |
| 98 | 97 | test "test_divmoddi4" { |
| 99 | 98 | for (cases__divmoddi4) |case| { |
| ... | ... | @@ -105,10 +104,6 @@ pub fn __udivmoddi4(a: u64, b: u64, maybe_rem: ?*u64) callconv(.c) u64 { |
| 105 | 104 | return udivmod(u64, a, b, maybe_rem); |
| 106 | 105 | } |
| 107 | 106 | |
| 108 | test "test_udivmoddi4" { | |
| 109 | _ = @import("udivmoddi4_test.zig"); | |
| 110 | } | |
| 111 | ||
| 112 | 107 | pub fn __divdi3(a: i64, b: i64) callconv(.c) i64 { |
| 113 | 108 | // Set aside the sign of the quotient. |
| 114 | 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 | 204 | |
| 210 | 205 | pub fn __divmodsi4(a: i32, b: i32, rem: *i32) callconv(.c) i32 { |
| 211 | 206 | const d = __divsi3(a, b); |
| 212 | rem.* = a -% (d * b); | |
| 207 | rem.* = a - d *% b; | |
| 213 | 208 | return d; |
| 214 | 209 | } |
| 215 | 210 | |
| 216 | const cases__divmodsi4 = | |
| 217 | [_][4]i32{ | |
| 218 | [_]i32{ 0, 1, 0, 0 }, | |
| 219 | [_]i32{ 0, -1, 0, 0 }, | |
| 220 | [_]i32{ 2, 1, 2, 0 }, | |
| 221 | [_]i32{ 2, -1, -2, 0 }, | |
| 222 | [_]i32{ -2, 1, -2, 0 }, | |
| 223 | [_]i32{ -2, -1, 2, 0 }, | |
| 224 | [_]i32{ 7, 5, 1, 2 }, | |
| 225 | [_]i32{ -7, 5, -1, -2 }, | |
| 226 | [_]i32{ 19, 5, 3, 4 }, | |
| 227 | [_]i32{ 19, -5, -3, 4 }, | |
| 228 | [_]i32{ @bitCast(@as(u32, 0x80000000)), 8, @bitCast(@as(u32, 0xf0000000)), 0 }, | |
| 229 | [_]i32{ @bitCast(@as(u32, 0x80000007)), 8, @bitCast(@as(u32, 0xf0000001)), -1 }, | |
| 230 | }; | |
| 211 | const cases__divmodsi4 = [_][4]i32{ | |
| 212 | [_]i32{ 0, 1, 0, 0 }, | |
| 213 | [_]i32{ 0, -1, 0, 0 }, | |
| 214 | [_]i32{ 2, 1, 2, 0 }, | |
| 215 | [_]i32{ 2, -1, -2, 0 }, | |
| 216 | [_]i32{ -2, 1, -2, 0 }, | |
| 217 | [_]i32{ -2, -1, 2, 0 }, | |
| 218 | [_]i32{ 7, 5, 1, 2 }, | |
| 219 | [_]i32{ -7, 5, -1, -2 }, | |
| 220 | [_]i32{ 19, 5, 3, 4 }, | |
| 221 | [_]i32{ 19, -5, -3, 4 }, | |
| 222 | [_]i32{ @bitCast(@as(u32, 0x80000000)), 8, @bitCast(@as(u32, 0xf0000000)), 0 }, | |
| 223 | [_]i32{ @bitCast(@as(u32, 0x80000007)), 8, @bitCast(@as(u32, 0xf0000001)), -1 }, | |
| 224 | }; | |
| 231 | 225 | |
| 232 | 226 | fn test_one_divmodsi4(a: i32, b: i32, expected_q: i32, expected_r: i32) !void { |
| 233 | 227 | var r: i32 = undefined; |
| ... | ... | @@ -243,7 +237,7 @@ test "test_divmodsi4" { |
| 243 | 237 | |
| 244 | 238 | pub fn __udivmodsi4(a: u32, b: u32, rem: *u32) callconv(.c) u32 { |
| 245 | 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 | 241 | return d; |
| 248 | 242 | } |
| 249 | 243 | |
| ... | ... | @@ -486,7 +480,7 @@ fn test_one_udivsi3(a: u32, b: u32, expected_q: u32) !void { |
| 486 | 480 | } |
| 487 | 481 | |
| 488 | 482 | pub 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 | } |
| 491 | 485 | |
| 492 | 486 | test "test_modsi3" { |
| ... | ... | @@ -515,7 +509,7 @@ fn test_one_modsi3(a: i32, b: i32, expected_r: i32) !void { |
| 515 | 509 | } |
| 516 | 510 | |
| 517 | 511 | pub 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 | } |
| 520 | 514 | |
| 521 | 515 | test "test_umodsi3" { |
| ... | ... | @@ -663,3 +657,8 @@ fn test_one_umodsi3(a: u32, b: u32, expected_r: u32) !void { |
| 663 | 657 | const r: u32 = __umodsi3(a, b); |
| 664 | 658 | try testing.expect(r == expected_r); |
| 665 | 659 | } |
| 660 | ||
| 661 | test { | |
| 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 | const builtin = @import("builtin"); | |
| 1 | 2 | const std = @import("std"); |
| 2 | 3 | const math = std.math; |
| 3 | 4 | const Log2Int = std.math.Log2Int; |
| ... | ... | @@ -6,29 +7,532 @@ const compiler_rt = @import("../compiler_rt.zig"); |
| 6 | 7 | const symbol = compiler_rt.symbol; |
| 7 | 8 | |
| 8 | 9 | comptime { |
| 9 | symbol(&__fixxfti, "__fixxfti"); | |
| 10 | 10 | symbol(&__fixhfsi, "__fixhfsi"); |
| 11 | 11 | symbol(&__fixhfdi, "__fixhfdi"); |
| 12 | 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 | ||
| 66 | fn __fixhfsi(a: compiler_rt.f16.Abi) callconv(.c) i32 { | |
| 67 | return i32_intFromFloat_f16(compiler_rt.f16.fromAbi(a)); | |
| 68 | } | |
| 69 | pub fn i32_intFromFloat_f16(a: f16) i32 { | |
| 70 | return intFromFloat(i32, a); | |
| 71 | } | |
| 72 | ||
| 73 | fn __fixhfdi(a: compiler_rt.f16.Abi) callconv(.c) i64 { | |
| 74 | return i64_intFromFloat_f16(compiler_rt.f16.fromAbi(a)); | |
| 75 | } | |
| 76 | pub fn i64_intFromFloat_f16(a: f16) i64 { | |
| 77 | return intFromFloat(i64, a); | |
| 78 | } | |
| 79 | ||
| 80 | fn __fixhfti(a: compiler_rt.f16.Abi) callconv(.c) i128 { | |
| 81 | return i128_intFromFloat_f16(compiler_rt.f16.fromAbi(a)); | |
| 82 | } | |
| 83 | pub fn i128_intFromFloat_f16(a: f16) i128 { | |
| 84 | return intFromFloat(i128, a); | |
| 85 | } | |
| 86 | ||
| 87 | fn __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 | } | |
| 91 | pub fn signed_intFromFloat_f16(result: []u8, a: f16) void { | |
| 92 | bigIntFromFloat(.signed, @ptrCast(@alignCast(result)), a); | |
| 93 | } | |
| 94 | ||
| 95 | fn __fixsfsi(a: compiler_rt.f32.Abi) callconv(.c) i32 { | |
| 96 | return i32_intFromFloat_f32(compiler_rt.f32.fromAbi(a)); | |
| 97 | } | |
| 98 | fn __aeabi_f2iz(a: f32) callconv(.{ .arm_aapcs = .{} }) i32 { | |
| 99 | return i32_intFromFloat_f32(a); | |
| 100 | } | |
| 101 | pub fn i32_intFromFloat_f32(a: f32) i32 { | |
| 102 | return intFromFloat(i32, a); | |
| 103 | } | |
| 104 | ||
| 105 | fn __fixsfdi(a: compiler_rt.f32.Abi) callconv(.c) i64 { | |
| 106 | return i64_intFromFloat_f32(compiler_rt.f32.fromAbi(a)); | |
| 107 | } | |
| 108 | fn __aeabi_f2lz(a: f32) callconv(.{ .arm_aapcs = .{} }) i64 { | |
| 109 | return i64_intFromFloat_f32(a); | |
| 110 | } | |
| 111 | pub fn i64_intFromFloat_f32(a: f32) i64 { | |
| 112 | return intFromFloat(i64, a); | |
| 113 | } | |
| 114 | ||
| 115 | fn __fixsfti(a: compiler_rt.f32.Abi) callconv(.c) i128 { | |
| 116 | return i128_intFromFloat_f32(compiler_rt.f32.fromAbi(a)); | |
| 117 | } | |
| 118 | fn __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 | } | |
| 139 | pub fn i128_intFromFloat_f32(a: f32) i128 { | |
| 140 | return intFromFloat(i128, a); | |
| 141 | } | |
| 142 | ||
| 143 | fn __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 | } | |
| 147 | pub fn signed_intFromFloat_f32(result: []u8, a: f32) void { | |
| 148 | bigIntFromFloat(.signed, @ptrCast(@alignCast(result)), a); | |
| 149 | } | |
| 150 | ||
| 151 | fn __fixdfsi(a: compiler_rt.f64.Abi) callconv(.c) i32 { | |
| 152 | return i32_intFromFloat_f64(compiler_rt.f64.fromAbi(a)); | |
| 153 | } | |
| 154 | fn __aeabi_d2iz(a: f64) callconv(.{ .arm_aapcs = .{} }) i32 { | |
| 155 | return i32_intFromFloat_f64(a); | |
| 156 | } | |
| 157 | pub fn i32_intFromFloat_f64(a: f64) i32 { | |
| 158 | return intFromFloat(i32, a); | |
| 159 | } | |
| 160 | ||
| 161 | fn __fixdfdi(a: compiler_rt.f64.Abi) callconv(.c) i64 { | |
| 162 | return i64_intFromFloat_f64(compiler_rt.f64.fromAbi(a)); | |
| 163 | } | |
| 164 | fn __aeabi_d2lz(a: f64) callconv(.{ .arm_aapcs = .{} }) i64 { | |
| 165 | return i64_intFromFloat_f64(a); | |
| 166 | } | |
| 167 | pub fn i64_intFromFloat_f64(a: f64) i64 { | |
| 168 | return intFromFloat(i64, a); | |
| 13 | 169 | } |
| 14 | 170 | |
| 15 | pub fn __fixhfti(a: f16) callconv(.c) i128 { | |
| 171 | fn __fixdfti(a: compiler_rt.f64.Abi) callconv(.c) i128 { | |
| 172 | return i128_intFromFloat_f64(compiler_rt.f64.fromAbi(a)); | |
| 173 | } | |
| 174 | fn __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 | } | |
| 196 | pub fn i128_intFromFloat_f64(a: f64) i128 { | |
| 16 | 197 | return intFromFloat(i128, a); |
| 17 | 198 | } |
| 18 | 199 | |
| 19 | fn __fixhfdi(a: f16) callconv(.c) i64 { | |
| 200 | fn __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 | } | |
| 204 | pub fn signed_intFromFloat_f64(result: []u8, a: f64) void { | |
| 205 | bigIntFromFloat(.signed, @ptrCast(@alignCast(result)), a); | |
| 206 | } | |
| 207 | ||
| 208 | fn __fixxfsi(a: compiler_rt.f80.Abi) callconv(.c) i32 { | |
| 209 | return i32_intFromFloat_f80(compiler_rt.f80.fromAbi(a)); | |
| 210 | } | |
| 211 | pub fn i32_intFromFloat_f80(a: f80) i32 { | |
| 212 | return intFromFloat(i32, a); | |
| 213 | } | |
| 214 | ||
| 215 | fn __fixxfdi(a: compiler_rt.f80.Abi) callconv(.c) i64 { | |
| 216 | return i64_intFromFloat_f80(compiler_rt.f80.fromAbi(a)); | |
| 217 | } | |
| 218 | pub fn i64_intFromFloat_f80(a: f80) i64 { | |
| 20 | 219 | return intFromFloat(i64, a); |
| 21 | 220 | } |
| 22 | 221 | |
| 23 | fn __fixhfsi(a: f16) callconv(.c) i32 { | |
| 222 | fn __fixxfti(a: compiler_rt.f80.Abi) callconv(.c) i128 { | |
| 223 | return i128_intFromFloat_f80(compiler_rt.f80.fromAbi(a)); | |
| 224 | } | |
| 225 | pub fn i128_intFromFloat_f80(a: f80) i128 { | |
| 226 | return intFromFloat(i128, a); | |
| 227 | } | |
| 228 | ||
| 229 | fn __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 | } | |
| 233 | pub fn signed_intFromFloat_f80(result: []u8, a: f80) void { | |
| 234 | bigIntFromFloat(.signed, @ptrCast(@alignCast(result)), a); | |
| 235 | } | |
| 236 | ||
| 237 | fn __fixtfsi(a: compiler_rt.f128.Abi) callconv(.c) i32 { | |
| 238 | return i32_intFromFloat_f128(compiler_rt.f128.fromAbi(a)); | |
| 239 | } | |
| 240 | fn _Qp_qtoi(a: *const f128) callconv(.c) i32 { | |
| 241 | return i32_intFromFloat_f128(a.*); | |
| 242 | } | |
| 243 | pub fn i32_intFromFloat_f128(a: f128) i32 { | |
| 24 | 244 | return intFromFloat(i32, a); |
| 25 | 245 | } |
| 26 | 246 | |
| 27 | pub fn __fixxfti(a: f80) callconv(.c) i128 { | |
| 247 | fn __fixtfdi(a: compiler_rt.f128.Abi) callconv(.c) i64 { | |
| 248 | return i64_intFromFloat_f128(compiler_rt.f128.fromAbi(a)); | |
| 249 | } | |
| 250 | fn _Qp_qtox(a: *const f128) callconv(.c) i64 { | |
| 251 | return i64_intFromFloat_f128(a.*); | |
| 252 | } | |
| 253 | pub fn i64_intFromFloat_f128(a: f128) i64 { | |
| 254 | return intFromFloat(i64, a); | |
| 255 | } | |
| 256 | ||
| 257 | fn __fixtfti(a: compiler_rt.f128.Abi) callconv(.c) i128 { | |
| 258 | return i128_intFromFloat_f128(compiler_rt.f128.fromAbi(a)); | |
| 259 | } | |
| 260 | pub fn i128_intFromFloat_f128(a: f128) i128 { | |
| 28 | 261 | return intFromFloat(i128, a); |
| 29 | 262 | } |
| 30 | 263 | |
| 31 | pub inline fn intFromFloat(comptime I: type, a: anytype) I { | |
| 264 | fn __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 | } | |
| 268 | pub fn signed_intFromFloat_f128(result: []u8, a: f128) void { | |
| 269 | bigIntFromFloat(.signed, @ptrCast(@alignCast(result)), a); | |
| 270 | } | |
| 271 | ||
| 272 | comptime { | |
| 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 | ||
| 329 | fn __fixunshfsi(a: compiler_rt.f16.Abi) callconv(.c) u32 { | |
| 330 | return u32_intFromFloat_f16(compiler_rt.f16.fromAbi(a)); | |
| 331 | } | |
| 332 | pub fn u32_intFromFloat_f16(a: f16) u32 { | |
| 333 | return intFromFloat(u32, a); | |
| 334 | } | |
| 335 | ||
| 336 | fn __fixunshfdi(a: compiler_rt.f16.Abi) callconv(.c) u64 { | |
| 337 | return u64_intFromFloat_f16(compiler_rt.f16.fromAbi(a)); | |
| 338 | } | |
| 339 | pub fn u64_intFromFloat_f16(a: f16) u64 { | |
| 340 | return intFromFloat(u64, a); | |
| 341 | } | |
| 342 | ||
| 343 | fn __fixunshfti(a: compiler_rt.f16.Abi) callconv(.c) u128 { | |
| 344 | return u128_intFromFloat_f16(compiler_rt.f16.fromAbi(a)); | |
| 345 | } | |
| 346 | pub fn u128_intFromFloat_f16(a: f16) u128 { | |
| 347 | return intFromFloat(u128, a); | |
| 348 | } | |
| 349 | ||
| 350 | fn __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 | } | |
| 354 | pub fn unsigned_intFromFloat_f16(result: []u8, a: f16) void { | |
| 355 | bigIntFromFloat(.unsigned, @ptrCast(@alignCast(result)), a); | |
| 356 | } | |
| 357 | ||
| 358 | fn __fixunssfsi(a: compiler_rt.f32.Abi) callconv(.c) u32 { | |
| 359 | return u32_intFromFloat_f32(compiler_rt.f32.fromAbi(a)); | |
| 360 | } | |
| 361 | fn __aeabi_f2uiz(a: f32) callconv(.{ .arm_aapcs = .{} }) u32 { | |
| 362 | return u32_intFromFloat_f32(a); | |
| 363 | } | |
| 364 | pub fn u32_intFromFloat_f32(a: f32) u32 { | |
| 365 | return intFromFloat(u32, a); | |
| 366 | } | |
| 367 | ||
| 368 | fn __fixunssfdi(a: compiler_rt.f32.Abi) callconv(.c) u64 { | |
| 369 | return u64_intFromFloat_f32(compiler_rt.f32.fromAbi(a)); | |
| 370 | } | |
| 371 | fn __aeabi_f2ulz(a: f32) callconv(.{ .arm_aapcs = .{} }) u64 { | |
| 372 | return u64_intFromFloat_f32(a); | |
| 373 | } | |
| 374 | pub fn u64_intFromFloat_f32(a: f32) u64 { | |
| 375 | return intFromFloat(u64, a); | |
| 376 | } | |
| 377 | ||
| 378 | fn __fixunssfti(a: compiler_rt.f32.Abi) callconv(.c) u128 { | |
| 379 | return u128_intFromFloat_f32(compiler_rt.f32.fromAbi(a)); | |
| 380 | } | |
| 381 | fn __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 | } | |
| 402 | pub fn u128_intFromFloat_f32(a: f32) u128 { | |
| 403 | return intFromFloat(u128, a); | |
| 404 | } | |
| 405 | ||
| 406 | fn __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 | } | |
| 410 | pub fn unsigned_intFromFloat_f32(result: []u8, a: f32) void { | |
| 411 | bigIntFromFloat(.unsigned, @ptrCast(@alignCast(result)), a); | |
| 412 | } | |
| 413 | ||
| 414 | fn __fixunsdfsi(a: compiler_rt.f64.Abi) callconv(.c) u32 { | |
| 415 | return u32_intFromFloat_f64(compiler_rt.f64.fromAbi(a)); | |
| 416 | } | |
| 417 | fn __aeabi_d2uiz(a: f64) callconv(.{ .arm_aapcs = .{} }) u32 { | |
| 418 | return u32_intFromFloat_f64(a); | |
| 419 | } | |
| 420 | pub fn u32_intFromFloat_f64(a: f64) u32 { | |
| 421 | return intFromFloat(u32, a); | |
| 422 | } | |
| 423 | ||
| 424 | fn __fixunsdfdi(a: compiler_rt.f64.Abi) callconv(.c) u64 { | |
| 425 | return u64_intFromFloat_f64(compiler_rt.f64.fromAbi(a)); | |
| 426 | } | |
| 427 | fn __aeabi_d2ulz(a: f64) callconv(.{ .arm_aapcs = .{} }) u64 { | |
| 428 | return u64_intFromFloat_f64(a); | |
| 429 | } | |
| 430 | pub fn u64_intFromFloat_f64(a: f64) u64 { | |
| 431 | return intFromFloat(u64, a); | |
| 432 | } | |
| 433 | ||
| 434 | fn __fixunsdfti(a: compiler_rt.f64.Abi) callconv(.c) u128 { | |
| 435 | return u128_intFromFloat_f64(compiler_rt.f64.fromAbi(a)); | |
| 436 | } | |
| 437 | fn __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 | } | |
| 459 | pub fn u128_intFromFloat_f64(a: f64) u128 { | |
| 460 | return intFromFloat(u128, a); | |
| 461 | } | |
| 462 | ||
| 463 | fn __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 | } | |
| 467 | pub fn unsigned_intFromFloat_f64(result: []u8, a: f64) void { | |
| 468 | bigIntFromFloat(.unsigned, @ptrCast(@alignCast(result)), a); | |
| 469 | } | |
| 470 | ||
| 471 | fn __fixunsxfsi(a: compiler_rt.f80.Abi) callconv(.c) u32 { | |
| 472 | return u32_intFromFloat_f80(compiler_rt.f80.fromAbi(a)); | |
| 473 | } | |
| 474 | pub fn u32_intFromFloat_f80(a: f80) u32 { | |
| 475 | return intFromFloat(u32, a); | |
| 476 | } | |
| 477 | ||
| 478 | fn __fixunsxfdi(a: compiler_rt.f80.Abi) callconv(.c) u64 { | |
| 479 | return u64_intFromFloat_f80(compiler_rt.f80.fromAbi(a)); | |
| 480 | } | |
| 481 | pub fn u64_intFromFloat_f80(a: f80) u64 { | |
| 482 | return intFromFloat(u64, a); | |
| 483 | } | |
| 484 | ||
| 485 | fn __fixunsxfti(a: compiler_rt.f80.Abi) callconv(.c) u128 { | |
| 486 | return u128_intFromFloat_f80(compiler_rt.f80.fromAbi(a)); | |
| 487 | } | |
| 488 | pub fn u128_intFromFloat_f80(a: f80) u128 { | |
| 489 | return intFromFloat(u128, a); | |
| 490 | } | |
| 491 | ||
| 492 | fn __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 | } | |
| 496 | pub fn unsigned_intFromFloat_f80(result: []u8, a: f80) void { | |
| 497 | bigIntFromFloat(.unsigned, @ptrCast(@alignCast(result)), a); | |
| 498 | } | |
| 499 | ||
| 500 | fn __fixunstfsi(a: compiler_rt.f128.Abi) callconv(.c) u32 { | |
| 501 | return u32_intFromFloat_f128(compiler_rt.f128.fromAbi(a)); | |
| 502 | } | |
| 503 | fn _Qp_qtoui(a: *const f128) callconv(.c) u32 { | |
| 504 | return u32_intFromFloat_f128(a.*); | |
| 505 | } | |
| 506 | pub fn u32_intFromFloat_f128(a: f128) u32 { | |
| 507 | return intFromFloat(u32, a); | |
| 508 | } | |
| 509 | ||
| 510 | fn __fixunstfdi(a: compiler_rt.f128.Abi) callconv(.c) u64 { | |
| 511 | return u64_intFromFloat_f128(compiler_rt.f128.fromAbi(a)); | |
| 512 | } | |
| 513 | fn _Qp_qtoux(a: *const f128) callconv(.c) u64 { | |
| 514 | return u64_intFromFloat_f128(a.*); | |
| 515 | } | |
| 516 | pub fn u64_intFromFloat_f128(a: f128) u64 { | |
| 517 | return intFromFloat(u64, a); | |
| 518 | } | |
| 519 | ||
| 520 | fn __fixunstfti(a: compiler_rt.f128.Abi) callconv(.c) u128 { | |
| 521 | return u128_intFromFloat_f128(compiler_rt.f128.fromAbi(a)); | |
| 522 | } | |
| 523 | pub fn u128_intFromFloat_f128(a: f128) u128 { | |
| 524 | return intFromFloat(u128, a); | |
| 525 | } | |
| 526 | ||
| 527 | fn __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 | } | |
| 531 | pub fn unsigned_intFromFloat_f128(result: []u8, a: f128) void { | |
| 532 | bigIntFromFloat(.unsigned, @ptrCast(@alignCast(result)), a); | |
| 533 | } | |
| 534 | ||
| 535 | inline fn intFromFloat(comptime I: type, a: anytype) I { | |
| 32 | 536 | const F = @TypeOf(a); |
| 33 | 537 | const float_bits = @typeInfo(F).float.bits; |
| 34 | 538 | const int_bits = @typeInfo(I).int.bits; |
| ... | ... | @@ -76,13 +580,14 @@ pub inline fn intFromFloat(comptime I: type, a: anytype) I { |
| 76 | 580 | return result; |
| 77 | 581 | } |
| 78 | 582 | |
| 79 | pub inline fn bigIntFromFloat(comptime signedness: std.builtin.Signedness, result: []u32, a: anytype) void { | |
| 583 | inline fn bigIntFromFloat(comptime signedness: std.lang.Signedness, result: []u32, a: anytype) void { | |
| 584 | const endian = builtin.cpu.arch.endian(); | |
| 80 | 585 | switch (result.len) { |
| 81 | 586 | 0 => return, |
| 82 | 587 | inline 1...4 => |limbs_len| { |
| 83 | 588 | const I = @Int(signedness, 32 * limbs_len); |
| 84 | 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 | 591 | .little => low_to_high, |
| 87 | 592 | .big => switch (limbs_len) { |
| 88 | 593 | 1 => .{low_to_high[0]}, |
| ... | ... | @@ -111,7 +616,6 @@ pub inline fn bigIntFromFloat(comptime signedness: std.builtin.Signedness, resul |
| 111 | 616 | }); |
| 112 | 617 | switch (signedness) { |
| 113 | 618 | .signed => { |
| 114 | const endian = @import("builtin").cpu.arch.endian(); | |
| 115 | 619 | const exponent_limb = switch (endian) { |
| 116 | 620 | .little => exponent / 32, |
| 117 | 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 | 2 | const testing = std.testing; |
| 3 | 3 | const math = std.math; |
| 4 | 4 | |
| 5 | const __fixunshfti = @import("fixunshfti.zig").__fixunshfti; | |
| 6 | const __fixunsxfti = @import("fixunsxfti.zig").__fixunsxfti; | |
| 7 | ||
| 8 | // Conversion from f32 | |
| 9 | const __fixsfsi = @import("fixsfsi.zig").__fixsfsi; | |
| 10 | const __fixunssfsi = @import("fixunssfsi.zig").__fixunssfsi; | |
| 11 | const __fixsfdi = @import("fixsfdi.zig").__fixsfdi; | |
| 12 | const __fixunssfdi = @import("fixunssfdi.zig").__fixunssfdi; | |
| 13 | const __fixsfti = @import("fixsfti.zig").__fixsfti; | |
| 14 | const __fixunssfti = @import("fixunssfti.zig").__fixunssfti; | |
| 15 | const __fixsfei = @import("fixsfei.zig").__fixsfei; | |
| 16 | const __fixunssfei = @import("fixunssfei.zig").__fixunssfei; | |
| 17 | ||
| 18 | // Conversion from f64 | |
| 19 | const __fixdfsi = @import("fixdfsi.zig").__fixdfsi; | |
| 20 | const __fixunsdfsi = @import("fixunsdfsi.zig").__fixunsdfsi; | |
| 21 | const __fixdfdi = @import("fixdfdi.zig").__fixdfdi; | |
| 22 | const __fixunsdfdi = @import("fixunsdfdi.zig").__fixunsdfdi; | |
| 23 | const __fixdfti = @import("fixdfti.zig").__fixdfti; | |
| 24 | const __fixunsdfti = @import("fixunsdfti.zig").__fixunsdfti; | |
| 25 | const __fixdfei = @import("fixdfei.zig").__fixdfei; | |
| 26 | const __fixunsdfei = @import("fixunsdfei.zig").__fixunsdfei; | |
| 27 | ||
| 28 | // Conversion from f128 | |
| 29 | const __fixtfsi = @import("fixtfsi.zig").__fixtfsi; | |
| 30 | const __fixunstfsi = @import("fixunstfsi.zig").__fixunstfsi; | |
| 31 | const __fixtfdi = @import("fixtfdi.zig").__fixtfdi; | |
| 32 | const __fixunstfdi = @import("fixunstfdi.zig").__fixunstfdi; | |
| 33 | const __fixtfti = @import("fixtfti.zig").__fixtfti; | |
| 34 | const __fixunstfti = @import("fixunstfti.zig").__fixunstfti; | |
| 35 | ||
| 36 | fn test__fixsfsi(a: f32, expected: i32) !void { | |
| 37 | const x = __fixsfsi(a); | |
| 5 | const impl = @import("int_from_float.zig"); | |
| 6 | ||
| 7 | const i32_intFromFloat_f16 = impl.i32_intFromFloat_f16; | |
| 8 | const u32_intFromFloat_f16 = impl.u32_intFromFloat_f16; | |
| 9 | const i64_intFromFloat_f16 = impl.i64_intFromFloat_f16; | |
| 10 | const u64_intFromFloat_f16 = impl.u64_intFromFloat_f16; | |
| 11 | const i128_intFromFloat_f16 = impl.i128_intFromFloat_f16; | |
| 12 | const u128_intFromFloat_f16 = impl.u128_intFromFloat_f16; | |
| 13 | const signed_intFromFloat_f16 = impl.signed_intFromFloat_f16; | |
| 14 | const unsigned_intFromFloat_f16 = impl.unsigned_intFromFloat_f16; | |
| 15 | ||
| 16 | const i32_intFromFloat_f32 = impl.i32_intFromFloat_f32; | |
| 17 | const u32_intFromFloat_f32 = impl.u32_intFromFloat_f32; | |
| 18 | const i64_intFromFloat_f32 = impl.i64_intFromFloat_f32; | |
| 19 | const u64_intFromFloat_f32 = impl.u64_intFromFloat_f32; | |
| 20 | const i128_intFromFloat_f32 = impl.i128_intFromFloat_f32; | |
| 21 | const u128_intFromFloat_f32 = impl.u128_intFromFloat_f32; | |
| 22 | const signed_intFromFloat_f32 = impl.signed_intFromFloat_f32; | |
| 23 | const unsigned_intFromFloat_f32 = impl.unsigned_intFromFloat_f32; | |
| 24 | ||
| 25 | const i32_intFromFloat_f64 = impl.i32_intFromFloat_f64; | |
| 26 | const u32_intFromFloat_f64 = impl.u32_intFromFloat_f64; | |
| 27 | const i64_intFromFloat_f64 = impl.i64_intFromFloat_f64; | |
| 28 | const u64_intFromFloat_f64 = impl.u64_intFromFloat_f64; | |
| 29 | const i128_intFromFloat_f64 = impl.i128_intFromFloat_f64; | |
| 30 | const u128_intFromFloat_f64 = impl.u128_intFromFloat_f64; | |
| 31 | const signed_intFromFloat_f64 = impl.signed_intFromFloat_f64; | |
| 32 | const unsigned_intFromFloat_f64 = impl.unsigned_intFromFloat_f64; | |
| 33 | ||
| 34 | const i32_intFromFloat_f80 = impl.i32_intFromFloat_f80; | |
| 35 | const u32_intFromFloat_f80 = impl.u32_intFromFloat_f80; | |
| 36 | const i64_intFromFloat_f80 = impl.i64_intFromFloat_f80; | |
| 37 | const u64_intFromFloat_f80 = impl.u64_intFromFloat_f80; | |
| 38 | const i128_intFromFloat_f80 = impl.i128_intFromFloat_f80; | |
| 39 | const u128_intFromFloat_f80 = impl.u128_intFromFloat_f80; | |
| 40 | const signed_intFromFloat_f80 = impl.signed_intFromFloat_f80; | |
| 41 | const unsigned_intFromFloat_f80 = impl.unsigned_intFromFloat_f80; | |
| 42 | ||
| 43 | const i32_intFromFloat_f128 = impl.i32_intFromFloat_f128; | |
| 44 | const u32_intFromFloat_f128 = impl.u32_intFromFloat_f128; | |
| 45 | const i64_intFromFloat_f128 = impl.i64_intFromFloat_f128; | |
| 46 | const u64_intFromFloat_f128 = impl.u64_intFromFloat_f128; | |
| 47 | const i128_intFromFloat_f128 = impl.i128_intFromFloat_f128; | |
| 48 | const u128_intFromFloat_f128 = impl.u128_intFromFloat_f128; | |
| 49 | const signed_intFromFloat_f128 = impl.signed_intFromFloat_f128; | |
| 50 | const unsigned_intFromFloat_f128 = impl.unsigned_intFromFloat_f128; | |
| 51 | ||
| 52 | fn test_i32_intFromFloat_f32(a: f32, expected: i32) !void { | |
| 53 | const x = i32_intFromFloat_f32(a); | |
| 38 | 54 | try testing.expect(x == expected); |
| 39 | 55 | } |
| 40 | 56 | |
| 41 | fn test__fixunssfsi(a: f32, expected: u32) !void { | |
| 42 | const x = __fixunssfsi(a); | |
| 57 | fn test_u32_intFromFloat_f32(a: f32, expected: u32) !void { | |
| 58 | const x = u32_intFromFloat_f32(a); | |
| 43 | 59 | try testing.expect(x == expected); |
| 44 | 60 | } |
| 45 | 61 | |
| 46 | test "fixsfsi" { | |
| 47 | try test__fixsfsi(-math.floatMax(f32), math.minInt(i32)); | |
| 48 | ||
| 49 | try test__fixsfsi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32)); | |
| 50 | try test__fixsfsi(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000); | |
| 51 | ||
| 52 | try test__fixsfsi(-0x1.0000000000000p+127, -0x80000000); | |
| 53 | try test__fixsfsi(-0x1.FFFFFFFFFFFFFp+126, -0x80000000); | |
| 54 | try test__fixsfsi(-0x1.FFFFFFFFFFFFEp+126, -0x80000000); | |
| 55 | ||
| 56 | try test__fixsfsi(-0x1.0000000000001p+63, -0x80000000); | |
| 57 | try test__fixsfsi(-0x1.0000000000000p+63, -0x80000000); | |
| 58 | try test__fixsfsi(-0x1.FFFFFFFFFFFFFp+62, -0x80000000); | |
| 59 | try test__fixsfsi(-0x1.FFFFFFFFFFFFEp+62, -0x80000000); | |
| 60 | ||
| 61 | try test__fixsfsi(-0x1.FFFFFEp+62, -0x80000000); | |
| 62 | try test__fixsfsi(-0x1.FFFFFCp+62, -0x80000000); | |
| 63 | ||
| 64 | try test__fixsfsi(-0x1.000000p+31, -0x80000000); | |
| 65 | try test__fixsfsi(-0x1.FFFFFFp+30, -0x80000000); | |
| 66 | try test__fixsfsi(-0x1.FFFFFEp+30, -0x7FFFFF80); | |
| 67 | try test__fixsfsi(-0x1.FFFFFCp+30, -0x7FFFFF00); | |
| 68 | ||
| 69 | try test__fixsfsi(-2.01, -2); | |
| 70 | try test__fixsfsi(-2.0, -2); | |
| 71 | try test__fixsfsi(-1.99, -1); | |
| 72 | try test__fixsfsi(-1.0, -1); | |
| 73 | try test__fixsfsi(-0.99, 0); | |
| 74 | try test__fixsfsi(-0.5, 0); | |
| 75 | ||
| 76 | try test__fixsfsi(-math.floatMin(f32), 0); | |
| 77 | try test__fixsfsi(0.0, 0); | |
| 78 | try test__fixsfsi(math.floatMin(f32), 0); | |
| 79 | try test__fixsfsi(0.5, 0); | |
| 80 | try test__fixsfsi(0.99, 0); | |
| 81 | try test__fixsfsi(1.0, 1); | |
| 82 | try test__fixsfsi(1.5, 1); | |
| 83 | try test__fixsfsi(1.99, 1); | |
| 84 | try test__fixsfsi(2.0, 2); | |
| 85 | try test__fixsfsi(2.01, 2); | |
| 86 | ||
| 87 | try test__fixsfsi(0x1.FFFFFCp+30, 0x7FFFFF00); | |
| 88 | try test__fixsfsi(0x1.FFFFFEp+30, 0x7FFFFF80); | |
| 89 | try test__fixsfsi(0x1.FFFFFFp+30, 0x7FFFFFFF); | |
| 90 | try test__fixsfsi(0x1.000000p+31, 0x7FFFFFFF); | |
| 91 | ||
| 92 | try test__fixsfsi(0x1.FFFFFCp+62, 0x7FFFFFFF); | |
| 93 | try test__fixsfsi(0x1.FFFFFEp+62, 0x7FFFFFFF); | |
| 94 | ||
| 95 | try test__fixsfsi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF); | |
| 96 | try test__fixsfsi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF); | |
| 97 | try test__fixsfsi(0x1.0000000000000p+63, 0x7FFFFFFF); | |
| 98 | try test__fixsfsi(0x1.0000000000001p+63, 0x7FFFFFFF); | |
| 99 | ||
| 100 | try test__fixsfsi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF); | |
| 101 | try test__fixsfsi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF); | |
| 102 | try test__fixsfsi(0x1.0000000000000p+127, 0x7FFFFFFF); | |
| 103 | ||
| 104 | try test__fixsfsi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF); | |
| 105 | try test__fixsfsi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32)); | |
| 106 | ||
| 107 | try test__fixsfsi(math.floatMax(f32), math.maxInt(i32)); | |
| 62 | test i32_intFromFloat_f32 { | |
| 63 | try test_i32_intFromFloat_f32(-math.floatMax(f32), math.minInt(i32)); | |
| 64 | ||
| 65 | try test_i32_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32)); | |
| 66 | try test_i32_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000); | |
| 67 | ||
| 68 | try test_i32_intFromFloat_f32(-0x1.0000000000000p+127, -0x80000000); | |
| 69 | try test_i32_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+126, -0x80000000); | |
| 70 | try test_i32_intFromFloat_f32(-0x1.FFFFFFFFFFFFEp+126, -0x80000000); | |
| 71 | ||
| 72 | try test_i32_intFromFloat_f32(-0x1.0000000000001p+63, -0x80000000); | |
| 73 | try test_i32_intFromFloat_f32(-0x1.0000000000000p+63, -0x80000000); | |
| 74 | try test_i32_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+62, -0x80000000); | |
| 75 | try test_i32_intFromFloat_f32(-0x1.FFFFFFFFFFFFEp+62, -0x80000000); | |
| 76 | ||
| 77 | try test_i32_intFromFloat_f32(-0x1.FFFFFEp+62, -0x80000000); | |
| 78 | try test_i32_intFromFloat_f32(-0x1.FFFFFCp+62, -0x80000000); | |
| 79 | ||
| 80 | try test_i32_intFromFloat_f32(-0x1.000000p+31, -0x80000000); | |
| 81 | try test_i32_intFromFloat_f32(-0x1.FFFFFFp+30, -0x80000000); | |
| 82 | try test_i32_intFromFloat_f32(-0x1.FFFFFEp+30, -0x7FFFFF80); | |
| 83 | try test_i32_intFromFloat_f32(-0x1.FFFFFCp+30, -0x7FFFFF00); | |
| 84 | ||
| 85 | try test_i32_intFromFloat_f32(-2.01, -2); | |
| 86 | try test_i32_intFromFloat_f32(-2.0, -2); | |
| 87 | try test_i32_intFromFloat_f32(-1.99, -1); | |
| 88 | try test_i32_intFromFloat_f32(-1.0, -1); | |
| 89 | try test_i32_intFromFloat_f32(-0.99, 0); | |
| 90 | try test_i32_intFromFloat_f32(-0.5, 0); | |
| 91 | ||
| 92 | try test_i32_intFromFloat_f32(-math.floatMin(f32), 0); | |
| 93 | try test_i32_intFromFloat_f32(0.0, 0); | |
| 94 | try test_i32_intFromFloat_f32(math.floatMin(f32), 0); | |
| 95 | try test_i32_intFromFloat_f32(0.5, 0); | |
| 96 | try test_i32_intFromFloat_f32(0.99, 0); | |
| 97 | try test_i32_intFromFloat_f32(1.0, 1); | |
| 98 | try test_i32_intFromFloat_f32(1.5, 1); | |
| 99 | try test_i32_intFromFloat_f32(1.99, 1); | |
| 100 | try test_i32_intFromFloat_f32(2.0, 2); | |
| 101 | try test_i32_intFromFloat_f32(2.01, 2); | |
| 102 | ||
| 103 | try test_i32_intFromFloat_f32(0x1.FFFFFCp+30, 0x7FFFFF00); | |
| 104 | try test_i32_intFromFloat_f32(0x1.FFFFFEp+30, 0x7FFFFF80); | |
| 105 | try test_i32_intFromFloat_f32(0x1.FFFFFFp+30, 0x7FFFFFFF); | |
| 106 | try test_i32_intFromFloat_f32(0x1.000000p+31, 0x7FFFFFFF); | |
| 107 | ||
| 108 | try test_i32_intFromFloat_f32(0x1.FFFFFCp+62, 0x7FFFFFFF); | |
| 109 | try test_i32_intFromFloat_f32(0x1.FFFFFEp+62, 0x7FFFFFFF); | |
| 110 | ||
| 111 | try test_i32_intFromFloat_f32(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF); | |
| 112 | try test_i32_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF); | |
| 113 | try test_i32_intFromFloat_f32(0x1.0000000000000p+63, 0x7FFFFFFF); | |
| 114 | try test_i32_intFromFloat_f32(0x1.0000000000001p+63, 0x7FFFFFFF); | |
| 115 | ||
| 116 | try test_i32_intFromFloat_f32(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF); | |
| 117 | try test_i32_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF); | |
| 118 | try test_i32_intFromFloat_f32(0x1.0000000000000p+127, 0x7FFFFFFF); | |
| 119 | ||
| 120 | try test_i32_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF); | |
| 121 | try test_i32_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32)); | |
| 122 | ||
| 123 | try test_i32_intFromFloat_f32(math.floatMax(f32), math.maxInt(i32)); | |
| 108 | 124 | } |
| 109 | 125 | |
| 110 | test "fixunssfsi" { | |
| 111 | try test__fixunssfsi(0.0, 0); | |
| 112 | ||
| 113 | try test__fixunssfsi(0.5, 0); | |
| 114 | try test__fixunssfsi(0.99, 0); | |
| 115 | try test__fixunssfsi(1.0, 1); | |
| 116 | try test__fixunssfsi(1.5, 1); | |
| 117 | try test__fixunssfsi(1.99, 1); | |
| 118 | try test__fixunssfsi(2.0, 2); | |
| 119 | try test__fixunssfsi(2.01, 2); | |
| 120 | try test__fixunssfsi(-0.5, 0); | |
| 121 | try test__fixunssfsi(-0.99, 0); | |
| 122 | ||
| 123 | try test__fixunssfsi(-1.0, 0); | |
| 124 | try test__fixunssfsi(-1.5, 0); | |
| 125 | try test__fixunssfsi(-1.99, 0); | |
| 126 | try test__fixunssfsi(-2.0, 0); | |
| 127 | try test__fixunssfsi(-2.01, 0); | |
| 128 | ||
| 129 | try test__fixunssfsi(0x1.000000p+31, 0x80000000); | |
| 130 | try test__fixunssfsi(0x1.000000p+32, 0xFFFFFFFF); | |
| 131 | try test__fixunssfsi(0x1.FFFFFEp+31, 0xFFFFFF00); | |
| 132 | try test__fixunssfsi(0x1.FFFFFEp+30, 0x7FFFFF80); | |
| 133 | try test__fixunssfsi(0x1.FFFFFCp+30, 0x7FFFFF00); | |
| 134 | ||
| 135 | try test__fixunssfsi(-0x1.FFFFFEp+30, 0); | |
| 136 | try test__fixunssfsi(-0x1.FFFFFCp+30, 0); | |
| 126 | test u32_intFromFloat_f32 { | |
| 127 | try test_u32_intFromFloat_f32(0.0, 0); | |
| 128 | ||
| 129 | try test_u32_intFromFloat_f32(0.5, 0); | |
| 130 | try test_u32_intFromFloat_f32(0.99, 0); | |
| 131 | try test_u32_intFromFloat_f32(1.0, 1); | |
| 132 | try test_u32_intFromFloat_f32(1.5, 1); | |
| 133 | try test_u32_intFromFloat_f32(1.99, 1); | |
| 134 | try test_u32_intFromFloat_f32(2.0, 2); | |
| 135 | try test_u32_intFromFloat_f32(2.01, 2); | |
| 136 | try test_u32_intFromFloat_f32(-0.5, 0); | |
| 137 | try test_u32_intFromFloat_f32(-0.99, 0); | |
| 138 | ||
| 139 | try test_u32_intFromFloat_f32(-1.0, 0); | |
| 140 | try test_u32_intFromFloat_f32(-1.5, 0); | |
| 141 | try test_u32_intFromFloat_f32(-1.99, 0); | |
| 142 | try test_u32_intFromFloat_f32(-2.0, 0); | |
| 143 | try test_u32_intFromFloat_f32(-2.01, 0); | |
| 144 | ||
| 145 | try test_u32_intFromFloat_f32(0x1.000000p+31, 0x80000000); | |
| 146 | try test_u32_intFromFloat_f32(0x1.000000p+32, 0xFFFFFFFF); | |
| 147 | try test_u32_intFromFloat_f32(0x1.FFFFFEp+31, 0xFFFFFF00); | |
| 148 | try test_u32_intFromFloat_f32(0x1.FFFFFEp+30, 0x7FFFFF80); | |
| 149 | try test_u32_intFromFloat_f32(0x1.FFFFFCp+30, 0x7FFFFF00); | |
| 150 | ||
| 151 | try test_u32_intFromFloat_f32(-0x1.FFFFFEp+30, 0); | |
| 152 | try test_u32_intFromFloat_f32(-0x1.FFFFFCp+30, 0); | |
| 137 | 153 | } |
| 138 | 154 | |
| 139 | fn test__fixsfdi(a: f32, expected: i64) !void { | |
| 140 | const x = __fixsfdi(a); | |
| 155 | fn test_i64_intFromFloat_f32(a: f32, expected: i64) !void { | |
| 156 | const x = i64_intFromFloat_f32(a); | |
| 141 | 157 | try testing.expect(x == expected); |
| 142 | 158 | } |
| 143 | 159 | |
| 144 | fn test__fixunssfdi(a: f32, expected: u64) !void { | |
| 145 | const x = __fixunssfdi(a); | |
| 160 | fn test_u64_intFromFloat_f32(a: f32, expected: u64) !void { | |
| 161 | const x = u64_intFromFloat_f32(a); | |
| 146 | 162 | try testing.expect(x == expected); |
| 147 | 163 | } |
| 148 | 164 | |
| 149 | test "fixsfdi" { | |
| 150 | try test__fixsfdi(-math.floatMax(f32), math.minInt(i64)); | |
| 151 | ||
| 152 | try test__fixsfdi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64)); | |
| 153 | try test__fixsfdi(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000); | |
| 154 | ||
| 155 | try test__fixsfdi(-0x1.0000000000000p+127, -0x8000000000000000); | |
| 156 | try test__fixsfdi(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000); | |
| 157 | try test__fixsfdi(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000); | |
| 158 | ||
| 159 | try test__fixsfdi(-0x1.0000000000001p+63, -0x8000000000000000); | |
| 160 | try test__fixsfdi(-0x1.0000000000000p+63, -0x8000000000000000); | |
| 161 | try test__fixsfdi(-0x1.FFFFFFFFFFFFFp+62, -0x8000000000000000); | |
| 162 | try test__fixsfdi(-0x1.FFFFFFFFFFFFEp+62, -0x8000000000000000); | |
| 163 | ||
| 164 | try test__fixsfdi(-0x1.FFFFFFp+62, -0x8000000000000000); | |
| 165 | try test__fixsfdi(-0x1.FFFFFEp+62, -0x7fffff8000000000); | |
| 166 | try test__fixsfdi(-0x1.FFFFFCp+62, -0x7fffff0000000000); | |
| 167 | ||
| 168 | try test__fixsfdi(-2.01, -2); | |
| 169 | try test__fixsfdi(-2.0, -2); | |
| 170 | try test__fixsfdi(-1.99, -1); | |
| 171 | try test__fixsfdi(-1.0, -1); | |
| 172 | try test__fixsfdi(-0.99, 0); | |
| 173 | try test__fixsfdi(-0.5, 0); | |
| 174 | try test__fixsfdi(-math.floatMin(f32), 0); | |
| 175 | try test__fixsfdi(0.0, 0); | |
| 176 | try test__fixsfdi(math.floatMin(f32), 0); | |
| 177 | try test__fixsfdi(0.5, 0); | |
| 178 | try test__fixsfdi(0.99, 0); | |
| 179 | try test__fixsfdi(1.0, 1); | |
| 180 | try test__fixsfdi(1.5, 1); | |
| 181 | try test__fixsfdi(1.99, 1); | |
| 182 | try test__fixsfdi(2.0, 2); | |
| 183 | try test__fixsfdi(2.01, 2); | |
| 184 | ||
| 185 | try test__fixsfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | |
| 186 | try test__fixsfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | |
| 187 | try test__fixsfdi(0x1.FFFFFFp+62, 0x7FFFFFFFFFFFFFFF); | |
| 188 | ||
| 189 | try test__fixsfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFFFFF); | |
| 190 | try test__fixsfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFFFF); | |
| 191 | try test__fixsfdi(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF); | |
| 192 | try test__fixsfdi(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF); | |
| 193 | ||
| 194 | try test__fixsfdi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF); | |
| 195 | try test__fixsfdi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF); | |
| 196 | try test__fixsfdi(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF); | |
| 197 | ||
| 198 | try test__fixsfdi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF); | |
| 199 | try test__fixsfdi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64)); | |
| 200 | ||
| 201 | try test__fixsfdi(math.floatMax(f32), math.maxInt(i64)); | |
| 165 | test i64_intFromFloat_f32 { | |
| 166 | try test_i64_intFromFloat_f32(-math.floatMax(f32), math.minInt(i64)); | |
| 167 | ||
| 168 | try test_i64_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64)); | |
| 169 | try test_i64_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000); | |
| 170 | ||
| 171 | try test_i64_intFromFloat_f32(-0x1.0000000000000p+127, -0x8000000000000000); | |
| 172 | try test_i64_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000); | |
| 173 | try test_i64_intFromFloat_f32(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000); | |
| 174 | ||
| 175 | try test_i64_intFromFloat_f32(-0x1.0000000000001p+63, -0x8000000000000000); | |
| 176 | try test_i64_intFromFloat_f32(-0x1.0000000000000p+63, -0x8000000000000000); | |
| 177 | try test_i64_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+62, -0x8000000000000000); | |
| 178 | try test_i64_intFromFloat_f32(-0x1.FFFFFFFFFFFFEp+62, -0x8000000000000000); | |
| 179 | ||
| 180 | try test_i64_intFromFloat_f32(-0x1.FFFFFFp+62, -0x8000000000000000); | |
| 181 | try test_i64_intFromFloat_f32(-0x1.FFFFFEp+62, -0x7fffff8000000000); | |
| 182 | try test_i64_intFromFloat_f32(-0x1.FFFFFCp+62, -0x7fffff0000000000); | |
| 183 | ||
| 184 | try test_i64_intFromFloat_f32(-2.01, -2); | |
| 185 | try test_i64_intFromFloat_f32(-2.0, -2); | |
| 186 | try test_i64_intFromFloat_f32(-1.99, -1); | |
| 187 | try test_i64_intFromFloat_f32(-1.0, -1); | |
| 188 | try test_i64_intFromFloat_f32(-0.99, 0); | |
| 189 | try test_i64_intFromFloat_f32(-0.5, 0); | |
| 190 | try test_i64_intFromFloat_f32(-math.floatMin(f32), 0); | |
| 191 | try test_i64_intFromFloat_f32(0.0, 0); | |
| 192 | try test_i64_intFromFloat_f32(math.floatMin(f32), 0); | |
| 193 | try test_i64_intFromFloat_f32(0.5, 0); | |
| 194 | try test_i64_intFromFloat_f32(0.99, 0); | |
| 195 | try test_i64_intFromFloat_f32(1.0, 1); | |
| 196 | try test_i64_intFromFloat_f32(1.5, 1); | |
| 197 | try test_i64_intFromFloat_f32(1.99, 1); | |
| 198 | try test_i64_intFromFloat_f32(2.0, 2); | |
| 199 | try test_i64_intFromFloat_f32(2.01, 2); | |
| 200 | ||
| 201 | try test_i64_intFromFloat_f32(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | |
| 202 | try test_i64_intFromFloat_f32(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | |
| 203 | try test_i64_intFromFloat_f32(0x1.FFFFFFp+62, 0x7FFFFFFFFFFFFFFF); | |
| 204 | ||
| 205 | try test_i64_intFromFloat_f32(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFFFFF); | |
| 206 | try test_i64_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFFFF); | |
| 207 | try test_i64_intFromFloat_f32(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF); | |
| 208 | try test_i64_intFromFloat_f32(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF); | |
| 209 | ||
| 210 | try test_i64_intFromFloat_f32(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF); | |
| 211 | try test_i64_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF); | |
| 212 | try test_i64_intFromFloat_f32(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF); | |
| 213 | ||
| 214 | try test_i64_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF); | |
| 215 | try test_i64_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64)); | |
| 216 | ||
| 217 | try test_i64_intFromFloat_f32(math.floatMax(f32), math.maxInt(i64)); | |
| 202 | 218 | } |
| 203 | 219 | |
| 204 | test "fixunssfdi" { | |
| 205 | try test__fixunssfdi(0.0, 0); | |
| 206 | ||
| 207 | try test__fixunssfdi(0.5, 0); | |
| 208 | try test__fixunssfdi(0.99, 0); | |
| 209 | try test__fixunssfdi(1.0, 1); | |
| 210 | try test__fixunssfdi(1.5, 1); | |
| 211 | try test__fixunssfdi(1.99, 1); | |
| 212 | try test__fixunssfdi(2.0, 2); | |
| 213 | try test__fixunssfdi(2.01, 2); | |
| 214 | try test__fixunssfdi(-0.5, 0); | |
| 215 | try test__fixunssfdi(-0.99, 0); | |
| 216 | ||
| 217 | try test__fixunssfdi(-1.0, 0); | |
| 218 | try test__fixunssfdi(-1.5, 0); | |
| 219 | try test__fixunssfdi(-1.99, 0); | |
| 220 | try test__fixunssfdi(-2.0, 0); | |
| 221 | try test__fixunssfdi(-2.01, 0); | |
| 222 | ||
| 223 | try test__fixunssfdi(0x1.FFFFFEp+63, 0xFFFFFF0000000000); | |
| 224 | try test__fixunssfdi(0x1.000000p+63, 0x8000000000000000); | |
| 225 | try test__fixunssfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | |
| 226 | try test__fixunssfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | |
| 227 | ||
| 228 | try test__fixunssfdi(-0x1.FFFFFEp+62, 0x0000000000000000); | |
| 229 | try test__fixunssfdi(-0x1.FFFFFCp+62, 0x0000000000000000); | |
| 220 | test u64_intFromFloat_f32 { | |
| 221 | try test_u64_intFromFloat_f32(0.0, 0); | |
| 222 | ||
| 223 | try test_u64_intFromFloat_f32(0.5, 0); | |
| 224 | try test_u64_intFromFloat_f32(0.99, 0); | |
| 225 | try test_u64_intFromFloat_f32(1.0, 1); | |
| 226 | try test_u64_intFromFloat_f32(1.5, 1); | |
| 227 | try test_u64_intFromFloat_f32(1.99, 1); | |
| 228 | try test_u64_intFromFloat_f32(2.0, 2); | |
| 229 | try test_u64_intFromFloat_f32(2.01, 2); | |
| 230 | try test_u64_intFromFloat_f32(-0.5, 0); | |
| 231 | try test_u64_intFromFloat_f32(-0.99, 0); | |
| 232 | ||
| 233 | try test_u64_intFromFloat_f32(-1.0, 0); | |
| 234 | try test_u64_intFromFloat_f32(-1.5, 0); | |
| 235 | try test_u64_intFromFloat_f32(-1.99, 0); | |
| 236 | try test_u64_intFromFloat_f32(-2.0, 0); | |
| 237 | try test_u64_intFromFloat_f32(-2.01, 0); | |
| 238 | ||
| 239 | try test_u64_intFromFloat_f32(0x1.FFFFFEp+63, 0xFFFFFF0000000000); | |
| 240 | try test_u64_intFromFloat_f32(0x1.000000p+63, 0x8000000000000000); | |
| 241 | try test_u64_intFromFloat_f32(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | |
| 242 | try test_u64_intFromFloat_f32(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | |
| 243 | ||
| 244 | try test_u64_intFromFloat_f32(-0x1.FFFFFEp+62, 0x0000000000000000); | |
| 245 | try test_u64_intFromFloat_f32(-0x1.FFFFFCp+62, 0x0000000000000000); | |
| 230 | 246 | } |
| 231 | 247 | |
| 232 | fn test__fixsfti(a: f32, expected: i128) !void { | |
| 233 | const x = __fixsfti(a); | |
| 248 | fn test_i128_intFromFloat_f32(a: f32, expected: i128) !void { | |
| 249 | const x = i128_intFromFloat_f32(a); | |
| 234 | 250 | try testing.expect(x == expected); |
| 235 | 251 | } |
| 236 | 252 | |
| 237 | fn test__fixunssfti(a: f32, expected: u128) !void { | |
| 238 | const x = __fixunssfti(a); | |
| 253 | fn test_u128_intFromFloat_f32(a: f32, expected: u128) !void { | |
| 254 | const x = u128_intFromFloat_f32(a); | |
| 239 | 255 | try testing.expect(x == expected); |
| 240 | 256 | } |
| 241 | 257 | |
| 242 | test "fixsfti" { | |
| 243 | try test__fixsfti(-math.floatMax(f32), math.minInt(i128)); | |
| 244 | ||
| 245 | try test__fixsfti(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128)); | |
| 246 | try test__fixsfti(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000); | |
| 247 | ||
| 248 | try test__fixsfti(-0x1.0000000000000p+127, -0x80000000000000000000000000000000); | |
| 249 | try test__fixsfti(-0x1.FFFFFFFFFFFFFp+126, -0x80000000000000000000000000000000); | |
| 250 | try test__fixsfti(-0x1.FFFFFFFFFFFFEp+126, -0x80000000000000000000000000000000); | |
| 251 | try test__fixsfti(-0x1.FFFFFF0000000p+126, -0x80000000000000000000000000000000); | |
| 252 | try test__fixsfti(-0x1.FFFFFE0000000p+126, -0x7FFFFF80000000000000000000000000); | |
| 253 | try test__fixsfti(-0x1.FFFFFC0000000p+126, -0x7FFFFF00000000000000000000000000); | |
| 254 | ||
| 255 | try test__fixsfti(-0x1.0000000000001p+63, -0x8000000000000000); | |
| 256 | try test__fixsfti(-0x1.0000000000000p+63, -0x8000000000000000); | |
| 257 | try test__fixsfti(-0x1.FFFFFFFFFFFFFp+62, -0x8000000000000000); | |
| 258 | try test__fixsfti(-0x1.FFFFFFFFFFFFEp+62, -0x8000000000000000); | |
| 259 | ||
| 260 | try test__fixsfti(-0x1.FFFFFFp+62, -0x8000000000000000); | |
| 261 | try test__fixsfti(-0x1.FFFFFEp+62, -0x7fffff8000000000); | |
| 262 | try test__fixsfti(-0x1.FFFFFCp+62, -0x7fffff0000000000); | |
| 263 | ||
| 264 | try test__fixsfti(-0x1.000000p+31, -0x80000000); | |
| 265 | try test__fixsfti(-0x1.FFFFFFp+30, -0x80000000); | |
| 266 | try test__fixsfti(-0x1.FFFFFEp+30, -0x7FFFFF80); | |
| 267 | try test__fixsfti(-0x1.FFFFFCp+30, -0x7FFFFF00); | |
| 268 | ||
| 269 | try test__fixsfti(-2.01, -2); | |
| 270 | try test__fixsfti(-2.0, -2); | |
| 271 | try test__fixsfti(-1.99, -1); | |
| 272 | try test__fixsfti(-1.0, -1); | |
| 273 | try test__fixsfti(-0.99, 0); | |
| 274 | try test__fixsfti(-0.5, 0); | |
| 275 | try test__fixsfti(-math.floatMin(f32), 0); | |
| 276 | try test__fixsfti(0.0, 0); | |
| 277 | try test__fixsfti(math.floatMin(f32), 0); | |
| 278 | try test__fixsfti(0.5, 0); | |
| 279 | try test__fixsfti(0.99, 0); | |
| 280 | try test__fixsfti(1.0, 1); | |
| 281 | try test__fixsfti(1.5, 1); | |
| 282 | try test__fixsfti(1.99, 1); | |
| 283 | try test__fixsfti(2.0, 2); | |
| 284 | try test__fixsfti(2.01, 2); | |
| 285 | ||
| 286 | try test__fixsfti(0x1.FFFFFCp+30, 0x7FFFFF00); | |
| 287 | try test__fixsfti(0x1.FFFFFEp+30, 0x7FFFFF80); | |
| 288 | try test__fixsfti(0x1.FFFFFFp+30, 0x80000000); | |
| 289 | try test__fixsfti(0x1.000000p+31, 0x80000000); | |
| 290 | ||
| 291 | try test__fixsfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | |
| 292 | try test__fixsfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | |
| 293 | try test__fixsfti(0x1.FFFFFFp+62, 0x8000000000000000); | |
| 294 | ||
| 295 | try test__fixsfti(0x1.FFFFFFFFFFFFEp+62, 0x8000000000000000); | |
| 296 | try test__fixsfti(0x1.FFFFFFFFFFFFFp+62, 0x8000000000000000); | |
| 297 | try test__fixsfti(0x1.0000000000000p+63, 0x8000000000000000); | |
| 298 | try test__fixsfti(0x1.0000000000001p+63, 0x8000000000000000); | |
| 299 | ||
| 300 | try test__fixsfti(0x1.FFFFFC0000000p+126, 0x7FFFFF00000000000000000000000000); | |
| 301 | try test__fixsfti(0x1.FFFFFE0000000p+126, 0x7FFFFF80000000000000000000000000); | |
| 302 | try test__fixsfti(0x1.FFFFFF0000000p+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | |
| 303 | try test__fixsfti(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | |
| 304 | try test__fixsfti(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | |
| 305 | try test__fixsfti(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | |
| 306 | ||
| 307 | try test__fixsfti(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | |
| 308 | try test__fixsfti(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128)); | |
| 309 | ||
| 310 | try test__fixsfti(math.floatMax(f32), math.maxInt(i128)); | |
| 258 | test i128_intFromFloat_f32 { | |
| 259 | try test_i128_intFromFloat_f32(-math.floatMax(f32), math.minInt(i128)); | |
| 260 | ||
| 261 | try test_i128_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128)); | |
| 262 | try test_i128_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000); | |
| 263 | ||
| 264 | try test_i128_intFromFloat_f32(-0x1.0000000000000p+127, -0x80000000000000000000000000000000); | |
| 265 | try test_i128_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+126, -0x80000000000000000000000000000000); | |
| 266 | try test_i128_intFromFloat_f32(-0x1.FFFFFFFFFFFFEp+126, -0x80000000000000000000000000000000); | |
| 267 | try test_i128_intFromFloat_f32(-0x1.FFFFFF0000000p+126, -0x80000000000000000000000000000000); | |
| 268 | try test_i128_intFromFloat_f32(-0x1.FFFFFE0000000p+126, -0x7FFFFF80000000000000000000000000); | |
| 269 | try test_i128_intFromFloat_f32(-0x1.FFFFFC0000000p+126, -0x7FFFFF00000000000000000000000000); | |
| 270 | ||
| 271 | try test_i128_intFromFloat_f32(-0x1.0000000000001p+63, -0x8000000000000000); | |
| 272 | try test_i128_intFromFloat_f32(-0x1.0000000000000p+63, -0x8000000000000000); | |
| 273 | try test_i128_intFromFloat_f32(-0x1.FFFFFFFFFFFFFp+62, -0x8000000000000000); | |
| 274 | try test_i128_intFromFloat_f32(-0x1.FFFFFFFFFFFFEp+62, -0x8000000000000000); | |
| 275 | ||
| 276 | try test_i128_intFromFloat_f32(-0x1.FFFFFFp+62, -0x8000000000000000); | |
| 277 | try test_i128_intFromFloat_f32(-0x1.FFFFFEp+62, -0x7fffff8000000000); | |
| 278 | try test_i128_intFromFloat_f32(-0x1.FFFFFCp+62, -0x7fffff0000000000); | |
| 279 | ||
| 280 | try test_i128_intFromFloat_f32(-0x1.000000p+31, -0x80000000); | |
| 281 | try test_i128_intFromFloat_f32(-0x1.FFFFFFp+30, -0x80000000); | |
| 282 | try test_i128_intFromFloat_f32(-0x1.FFFFFEp+30, -0x7FFFFF80); | |
| 283 | try test_i128_intFromFloat_f32(-0x1.FFFFFCp+30, -0x7FFFFF00); | |
| 284 | ||
| 285 | try test_i128_intFromFloat_f32(-2.01, -2); | |
| 286 | try test_i128_intFromFloat_f32(-2.0, -2); | |
| 287 | try test_i128_intFromFloat_f32(-1.99, -1); | |
| 288 | try test_i128_intFromFloat_f32(-1.0, -1); | |
| 289 | try test_i128_intFromFloat_f32(-0.99, 0); | |
| 290 | try test_i128_intFromFloat_f32(-0.5, 0); | |
| 291 | try test_i128_intFromFloat_f32(-math.floatMin(f32), 0); | |
| 292 | try test_i128_intFromFloat_f32(0.0, 0); | |
| 293 | try test_i128_intFromFloat_f32(math.floatMin(f32), 0); | |
| 294 | try test_i128_intFromFloat_f32(0.5, 0); | |
| 295 | try test_i128_intFromFloat_f32(0.99, 0); | |
| 296 | try test_i128_intFromFloat_f32(1.0, 1); | |
| 297 | try test_i128_intFromFloat_f32(1.5, 1); | |
| 298 | try test_i128_intFromFloat_f32(1.99, 1); | |
| 299 | try test_i128_intFromFloat_f32(2.0, 2); | |
| 300 | try test_i128_intFromFloat_f32(2.01, 2); | |
| 301 | ||
| 302 | try test_i128_intFromFloat_f32(0x1.FFFFFCp+30, 0x7FFFFF00); | |
| 303 | try test_i128_intFromFloat_f32(0x1.FFFFFEp+30, 0x7FFFFF80); | |
| 304 | try test_i128_intFromFloat_f32(0x1.FFFFFFp+30, 0x80000000); | |
| 305 | try test_i128_intFromFloat_f32(0x1.000000p+31, 0x80000000); | |
| 306 | ||
| 307 | try test_i128_intFromFloat_f32(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | |
| 308 | try test_i128_intFromFloat_f32(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | |
| 309 | try test_i128_intFromFloat_f32(0x1.FFFFFFp+62, 0x8000000000000000); | |
| 310 | ||
| 311 | try test_i128_intFromFloat_f32(0x1.FFFFFFFFFFFFEp+62, 0x8000000000000000); | |
| 312 | try test_i128_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+62, 0x8000000000000000); | |
| 313 | try test_i128_intFromFloat_f32(0x1.0000000000000p+63, 0x8000000000000000); | |
| 314 | try test_i128_intFromFloat_f32(0x1.0000000000001p+63, 0x8000000000000000); | |
| 315 | ||
| 316 | try test_i128_intFromFloat_f32(0x1.FFFFFC0000000p+126, 0x7FFFFF00000000000000000000000000); | |
| 317 | try test_i128_intFromFloat_f32(0x1.FFFFFE0000000p+126, 0x7FFFFF80000000000000000000000000); | |
| 318 | try test_i128_intFromFloat_f32(0x1.FFFFFF0000000p+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | |
| 319 | try test_i128_intFromFloat_f32(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | |
| 320 | try test_i128_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | |
| 321 | try test_i128_intFromFloat_f32(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | |
| 322 | ||
| 323 | try test_i128_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | |
| 324 | try test_i128_intFromFloat_f32(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128)); | |
| 325 | ||
| 326 | try test_i128_intFromFloat_f32(math.floatMax(f32), math.maxInt(i128)); | |
| 311 | 327 | } |
| 312 | 328 | |
| 313 | test "fixunssfti" { | |
| 314 | try test__fixunssfti(0.0, 0); | |
| 315 | ||
| 316 | try test__fixunssfti(0.5, 0); | |
| 317 | try test__fixunssfti(0.99, 0); | |
| 318 | try test__fixunssfti(1.0, 1); | |
| 319 | try test__fixunssfti(1.5, 1); | |
| 320 | try test__fixunssfti(1.99, 1); | |
| 321 | try test__fixunssfti(2.0, 2); | |
| 322 | try test__fixunssfti(2.01, 2); | |
| 323 | try test__fixunssfti(-0.5, 0); | |
| 324 | try test__fixunssfti(-0.99, 0); | |
| 325 | ||
| 326 | try test__fixunssfti(-1.0, 0); | |
| 327 | try test__fixunssfti(-1.5, 0); | |
| 328 | try test__fixunssfti(-1.99, 0); | |
| 329 | try test__fixunssfti(-2.0, 0); | |
| 330 | try test__fixunssfti(-2.01, 0); | |
| 331 | ||
| 332 | try test__fixunssfti(0x1.FFFFFEp+63, 0xFFFFFF0000000000); | |
| 333 | try test__fixunssfti(0x1.000000p+63, 0x8000000000000000); | |
| 334 | try test__fixunssfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | |
| 335 | try test__fixunssfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | |
| 336 | try test__fixunssfti(0x1.FFFFFEp+127, 0xFFFFFF00000000000000000000000000); | |
| 337 | try test__fixunssfti(0x1.000000p+127, 0x80000000000000000000000000000000); | |
| 338 | try test__fixunssfti(0x1.FFFFFEp+126, 0x7FFFFF80000000000000000000000000); | |
| 339 | try test__fixunssfti(0x1.FFFFFCp+126, 0x7FFFFF00000000000000000000000000); | |
| 340 | ||
| 341 | try test__fixunssfti(-0x1.FFFFFEp+62, 0x0000000000000000); | |
| 342 | try test__fixunssfti(-0x1.FFFFFCp+62, 0x0000000000000000); | |
| 343 | try test__fixunssfti(-0x1.FFFFFEp+126, 0x0000000000000000); | |
| 344 | try test__fixunssfti(-0x1.FFFFFCp+126, 0x0000000000000000); | |
| 345 | try test__fixunssfti(math.floatMax(f32), 0xffffff00000000000000000000000000); | |
| 346 | try test__fixunssfti(math.inf(f32), math.maxInt(u128)); | |
| 329 | test u128_intFromFloat_f32 { | |
| 330 | try test_u128_intFromFloat_f32(0.0, 0); | |
| 331 | ||
| 332 | try test_u128_intFromFloat_f32(0.5, 0); | |
| 333 | try test_u128_intFromFloat_f32(0.99, 0); | |
| 334 | try test_u128_intFromFloat_f32(1.0, 1); | |
| 335 | try test_u128_intFromFloat_f32(1.5, 1); | |
| 336 | try test_u128_intFromFloat_f32(1.99, 1); | |
| 337 | try test_u128_intFromFloat_f32(2.0, 2); | |
| 338 | try test_u128_intFromFloat_f32(2.01, 2); | |
| 339 | try test_u128_intFromFloat_f32(-0.5, 0); | |
| 340 | try test_u128_intFromFloat_f32(-0.99, 0); | |
| 341 | ||
| 342 | try test_u128_intFromFloat_f32(-1.0, 0); | |
| 343 | try test_u128_intFromFloat_f32(-1.5, 0); | |
| 344 | try test_u128_intFromFloat_f32(-1.99, 0); | |
| 345 | try test_u128_intFromFloat_f32(-2.0, 0); | |
| 346 | try test_u128_intFromFloat_f32(-2.01, 0); | |
| 347 | ||
| 348 | try test_u128_intFromFloat_f32(0x1.FFFFFEp+63, 0xFFFFFF0000000000); | |
| 349 | try test_u128_intFromFloat_f32(0x1.000000p+63, 0x8000000000000000); | |
| 350 | try test_u128_intFromFloat_f32(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | |
| 351 | try test_u128_intFromFloat_f32(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | |
| 352 | try test_u128_intFromFloat_f32(0x1.FFFFFEp+127, 0xFFFFFF00000000000000000000000000); | |
| 353 | try test_u128_intFromFloat_f32(0x1.000000p+127, 0x80000000000000000000000000000000); | |
| 354 | try test_u128_intFromFloat_f32(0x1.FFFFFEp+126, 0x7FFFFF80000000000000000000000000); | |
| 355 | try test_u128_intFromFloat_f32(0x1.FFFFFCp+126, 0x7FFFFF00000000000000000000000000); | |
| 356 | ||
| 357 | try test_u128_intFromFloat_f32(-0x1.FFFFFEp+62, 0x0000000000000000); | |
| 358 | try test_u128_intFromFloat_f32(-0x1.FFFFFCp+62, 0x0000000000000000); | |
| 359 | try test_u128_intFromFloat_f32(-0x1.FFFFFEp+126, 0x0000000000000000); | |
| 360 | try test_u128_intFromFloat_f32(-0x1.FFFFFCp+126, 0x0000000000000000); | |
| 361 | try test_u128_intFromFloat_f32(math.floatMax(f32), 0xffffff00000000000000000000000000); | |
| 362 | try test_u128_intFromFloat_f32(math.inf(f32), math.maxInt(u128)); | |
| 347 | 363 | } |
| 348 | 364 | |
| 349 | fn test_fixsfei(comptime T: type, expected: T, a: f32) !void { | |
| 365 | fn test_intFromFloat_f32(comptime T: type, expected: T, a: f32) !void { | |
| 350 | 366 | const int = @typeInfo(T).int; |
| 351 | 367 | var actual: T = undefined; |
| 352 | 368 | _ = switch (int.signedness) { |
| 353 | .signed => __fixsfei, | |
| 354 | .unsigned => __fixunssfei, | |
| 355 | }(@ptrCast(&actual), int.bits, a); | |
| 369 | .signed => signed_intFromFloat_f32, | |
| 370 | .unsigned => unsigned_intFromFloat_f32, | |
| 371 | }(@ptrCast(&actual), a); | |
| 356 | 372 | try testing.expect(expected == actual); |
| 357 | 373 | } |
| 358 | 374 | |
| 359 | test "fixsfei" { | |
| 360 | try test_fixsfei(i256, -1 << 127, -0x1p127); | |
| 361 | try test_fixsfei(i256, -1 << 100, -0x1p100); | |
| 362 | try test_fixsfei(i256, -1 << 50, -0x1p50); | |
| 363 | try test_fixsfei(i256, -1 << 1, -0x1p1); | |
| 364 | try test_fixsfei(i256, -1 << 0, -0x1p0); | |
| 365 | try test_fixsfei(i256, 0, 0); | |
| 366 | try test_fixsfei(i256, 1 << 0, 0x1p0); | |
| 367 | try test_fixsfei(i256, 1 << 1, 0x1p1); | |
| 368 | try test_fixsfei(i256, 1 << 50, 0x1p50); | |
| 369 | try test_fixsfei(i256, 1 << 100, 0x1p100); | |
| 370 | try test_fixsfei(i256, 1 << 127, 0x1p127); | |
| 375 | test signed_intFromFloat_f32 { | |
| 376 | try test_intFromFloat_f32(i256, -1 << 127, -0x1p127); | |
| 377 | try test_intFromFloat_f32(i256, -1 << 100, -0x1p100); | |
| 378 | try test_intFromFloat_f32(i256, -1 << 50, -0x1p50); | |
| 379 | try test_intFromFloat_f32(i256, -1 << 1, -0x1p1); | |
| 380 | try test_intFromFloat_f32(i256, -1 << 0, -0x1p0); | |
| 381 | try test_intFromFloat_f32(i256, 0, 0); | |
| 382 | try test_intFromFloat_f32(i256, 1 << 0, 0x1p0); | |
| 383 | try test_intFromFloat_f32(i256, 1 << 1, 0x1p1); | |
| 384 | try test_intFromFloat_f32(i256, 1 << 50, 0x1p50); | |
| 385 | try test_intFromFloat_f32(i256, 1 << 100, 0x1p100); | |
| 386 | try test_intFromFloat_f32(i256, 1 << 127, 0x1p127); | |
| 371 | 387 | } |
| 372 | 388 | |
| 373 | test "fixunsfei" { | |
| 374 | try test_fixsfei(u256, 0, 0); | |
| 375 | try test_fixsfei(u256, 1 << 0, 0x1p0); | |
| 376 | try test_fixsfei(u256, 1 << 1, 0x1p1); | |
| 377 | try test_fixsfei(u256, 1 << 50, 0x1p50); | |
| 378 | try test_fixsfei(u256, 1 << 100, 0x1p100); | |
| 379 | try test_fixsfei(u256, 1 << 127, 0x1p127); | |
| 389 | test unsigned_intFromFloat_f32 { | |
| 390 | try test_intFromFloat_f32(u256, 0, 0); | |
| 391 | try test_intFromFloat_f32(u256, 1 << 0, 0x1p0); | |
| 392 | try test_intFromFloat_f32(u256, 1 << 1, 0x1p1); | |
| 393 | try test_intFromFloat_f32(u256, 1 << 50, 0x1p50); | |
| 394 | try test_intFromFloat_f32(u256, 1 << 100, 0x1p100); | |
| 395 | try test_intFromFloat_f32(u256, 1 << 127, 0x1p127); | |
| 380 | 396 | } |
| 381 | 397 | |
| 382 | fn test__fixdfsi(a: f64, expected: i32) !void { | |
| 383 | const x = __fixdfsi(a); | |
| 398 | fn test_i32_intFromFloat_f64(a: f64, expected: i32) !void { | |
| 399 | const x = i32_intFromFloat_f64(a); | |
| 384 | 400 | try testing.expect(x == expected); |
| 385 | 401 | } |
| 386 | 402 | |
| 387 | fn test__fixunsdfsi(a: f64, expected: u32) !void { | |
| 388 | const x = __fixunsdfsi(a); | |
| 403 | fn test_u32_intFromFloat_f64(a: f64, expected: u32) !void { | |
| 404 | const x = u32_intFromFloat_f64(a); | |
| 389 | 405 | try testing.expect(x == expected); |
| 390 | 406 | } |
| 391 | 407 | |
| 392 | test "fixdfsi" { | |
| 393 | try test__fixdfsi(-math.floatMax(f64), math.minInt(i32)); | |
| 394 | ||
| 395 | try test__fixdfsi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32)); | |
| 396 | try test__fixdfsi(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000); | |
| 397 | ||
| 398 | try test__fixdfsi(-0x1.0000000000000p+127, -0x80000000); | |
| 399 | try test__fixdfsi(-0x1.FFFFFFFFFFFFFp+126, -0x80000000); | |
| 400 | try test__fixdfsi(-0x1.FFFFFFFFFFFFEp+126, -0x80000000); | |
| 401 | ||
| 402 | try test__fixdfsi(-0x1.0000000000001p+63, -0x80000000); | |
| 403 | try test__fixdfsi(-0x1.0000000000000p+63, -0x80000000); | |
| 404 | try test__fixdfsi(-0x1.FFFFFFFFFFFFFp+62, -0x80000000); | |
| 405 | try test__fixdfsi(-0x1.FFFFFFFFFFFFEp+62, -0x80000000); | |
| 406 | ||
| 407 | try test__fixdfsi(-0x1.FFFFFEp+62, -0x80000000); | |
| 408 | try test__fixdfsi(-0x1.FFFFFCp+62, -0x80000000); | |
| 409 | ||
| 410 | try test__fixdfsi(-0x1.000000p+31, -0x80000000); | |
| 411 | try test__fixdfsi(-0x1.FFFFFFp+30, -0x7FFFFFC0); | |
| 412 | try test__fixdfsi(-0x1.FFFFFEp+30, -0x7FFFFF80); | |
| 413 | ||
| 414 | try test__fixdfsi(-2.01, -2); | |
| 415 | try test__fixdfsi(-2.0, -2); | |
| 416 | try test__fixdfsi(-1.99, -1); | |
| 417 | try test__fixdfsi(-1.0, -1); | |
| 418 | try test__fixdfsi(-0.99, 0); | |
| 419 | try test__fixdfsi(-0.5, 0); | |
| 420 | try test__fixdfsi(-math.floatMin(f64), 0); | |
| 421 | try test__fixdfsi(0.0, 0); | |
| 422 | try test__fixdfsi(math.floatMin(f64), 0); | |
| 423 | try test__fixdfsi(0.5, 0); | |
| 424 | try test__fixdfsi(0.99, 0); | |
| 425 | try test__fixdfsi(1.0, 1); | |
| 426 | try test__fixdfsi(1.5, 1); | |
| 427 | try test__fixdfsi(1.99, 1); | |
| 428 | try test__fixdfsi(2.0, 2); | |
| 429 | try test__fixdfsi(2.01, 2); | |
| 430 | ||
| 431 | try test__fixdfsi(0x1.FFFFFEp+30, 0x7FFFFF80); | |
| 432 | try test__fixdfsi(0x1.FFFFFFp+30, 0x7FFFFFC0); | |
| 433 | try test__fixdfsi(0x1.000000p+31, 0x7FFFFFFF); | |
| 434 | ||
| 435 | try test__fixdfsi(0x1.FFFFFCp+62, 0x7FFFFFFF); | |
| 436 | try test__fixdfsi(0x1.FFFFFEp+62, 0x7FFFFFFF); | |
| 437 | ||
| 438 | try test__fixdfsi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF); | |
| 439 | try test__fixdfsi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF); | |
| 440 | try test__fixdfsi(0x1.0000000000000p+63, 0x7FFFFFFF); | |
| 441 | try test__fixdfsi(0x1.0000000000001p+63, 0x7FFFFFFF); | |
| 442 | ||
| 443 | try test__fixdfsi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF); | |
| 444 | try test__fixdfsi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF); | |
| 445 | try test__fixdfsi(0x1.0000000000000p+127, 0x7FFFFFFF); | |
| 446 | ||
| 447 | try test__fixdfsi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF); | |
| 448 | try test__fixdfsi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32)); | |
| 449 | ||
| 450 | try test__fixdfsi(math.floatMax(f64), math.maxInt(i32)); | |
| 408 | test i32_intFromFloat_f64 { | |
| 409 | try test_i32_intFromFloat_f64(-math.floatMax(f64), math.minInt(i32)); | |
| 410 | ||
| 411 | try test_i32_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32)); | |
| 412 | try test_i32_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000); | |
| 413 | ||
| 414 | try test_i32_intFromFloat_f64(-0x1.0000000000000p+127, -0x80000000); | |
| 415 | try test_i32_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+126, -0x80000000); | |
| 416 | try test_i32_intFromFloat_f64(-0x1.FFFFFFFFFFFFEp+126, -0x80000000); | |
| 417 | ||
| 418 | try test_i32_intFromFloat_f64(-0x1.0000000000001p+63, -0x80000000); | |
| 419 | try test_i32_intFromFloat_f64(-0x1.0000000000000p+63, -0x80000000); | |
| 420 | try test_i32_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+62, -0x80000000); | |
| 421 | try test_i32_intFromFloat_f64(-0x1.FFFFFFFFFFFFEp+62, -0x80000000); | |
| 422 | ||
| 423 | try test_i32_intFromFloat_f64(-0x1.FFFFFEp+62, -0x80000000); | |
| 424 | try test_i32_intFromFloat_f64(-0x1.FFFFFCp+62, -0x80000000); | |
| 425 | ||
| 426 | try test_i32_intFromFloat_f64(-0x1.000000p+31, -0x80000000); | |
| 427 | try test_i32_intFromFloat_f64(-0x1.FFFFFFp+30, -0x7FFFFFC0); | |
| 428 | try test_i32_intFromFloat_f64(-0x1.FFFFFEp+30, -0x7FFFFF80); | |
| 429 | ||
| 430 | try test_i32_intFromFloat_f64(-2.01, -2); | |
| 431 | try test_i32_intFromFloat_f64(-2.0, -2); | |
| 432 | try test_i32_intFromFloat_f64(-1.99, -1); | |
| 433 | try test_i32_intFromFloat_f64(-1.0, -1); | |
| 434 | try test_i32_intFromFloat_f64(-0.99, 0); | |
| 435 | try test_i32_intFromFloat_f64(-0.5, 0); | |
| 436 | try test_i32_intFromFloat_f64(-math.floatMin(f64), 0); | |
| 437 | try test_i32_intFromFloat_f64(0.0, 0); | |
| 438 | try test_i32_intFromFloat_f64(math.floatMin(f64), 0); | |
| 439 | try test_i32_intFromFloat_f64(0.5, 0); | |
| 440 | try test_i32_intFromFloat_f64(0.99, 0); | |
| 441 | try test_i32_intFromFloat_f64(1.0, 1); | |
| 442 | try test_i32_intFromFloat_f64(1.5, 1); | |
| 443 | try test_i32_intFromFloat_f64(1.99, 1); | |
| 444 | try test_i32_intFromFloat_f64(2.0, 2); | |
| 445 | try test_i32_intFromFloat_f64(2.01, 2); | |
| 446 | ||
| 447 | try test_i32_intFromFloat_f64(0x1.FFFFFEp+30, 0x7FFFFF80); | |
| 448 | try test_i32_intFromFloat_f64(0x1.FFFFFFp+30, 0x7FFFFFC0); | |
| 449 | try test_i32_intFromFloat_f64(0x1.000000p+31, 0x7FFFFFFF); | |
| 450 | ||
| 451 | try test_i32_intFromFloat_f64(0x1.FFFFFCp+62, 0x7FFFFFFF); | |
| 452 | try test_i32_intFromFloat_f64(0x1.FFFFFEp+62, 0x7FFFFFFF); | |
| 453 | ||
| 454 | try test_i32_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF); | |
| 455 | try test_i32_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF); | |
| 456 | try test_i32_intFromFloat_f64(0x1.0000000000000p+63, 0x7FFFFFFF); | |
| 457 | try test_i32_intFromFloat_f64(0x1.0000000000001p+63, 0x7FFFFFFF); | |
| 458 | ||
| 459 | try test_i32_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF); | |
| 460 | try test_i32_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF); | |
| 461 | try test_i32_intFromFloat_f64(0x1.0000000000000p+127, 0x7FFFFFFF); | |
| 462 | ||
| 463 | try test_i32_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF); | |
| 464 | try test_i32_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32)); | |
| 465 | ||
| 466 | try test_i32_intFromFloat_f64(math.floatMax(f64), math.maxInt(i32)); | |
| 451 | 467 | } |
| 452 | 468 | |
| 453 | test "fixunsdfsi" { | |
| 454 | try test__fixunsdfsi(0.0, 0); | |
| 455 | ||
| 456 | try test__fixunsdfsi(0.5, 0); | |
| 457 | try test__fixunsdfsi(0.99, 0); | |
| 458 | try test__fixunsdfsi(1.0, 1); | |
| 459 | try test__fixunsdfsi(1.5, 1); | |
| 460 | try test__fixunsdfsi(1.99, 1); | |
| 461 | try test__fixunsdfsi(2.0, 2); | |
| 462 | try test__fixunsdfsi(2.01, 2); | |
| 463 | try test__fixunsdfsi(-0.5, 0); | |
| 464 | try test__fixunsdfsi(-0.99, 0); | |
| 465 | try test__fixunsdfsi(-1.0, 0); | |
| 466 | try test__fixunsdfsi(-1.5, 0); | |
| 467 | try test__fixunsdfsi(-1.99, 0); | |
| 468 | try test__fixunsdfsi(-2.0, 0); | |
| 469 | try test__fixunsdfsi(-2.01, 0); | |
| 470 | ||
| 471 | try test__fixunsdfsi(0x1.000000p+31, 0x80000000); | |
| 472 | try test__fixunsdfsi(0x1.000000p+32, 0xFFFFFFFF); | |
| 473 | try test__fixunsdfsi(0x1.FFFFFEp+31, 0xFFFFFF00); | |
| 474 | try test__fixunsdfsi(0x1.FFFFFEp+30, 0x7FFFFF80); | |
| 475 | try test__fixunsdfsi(0x1.FFFFFCp+30, 0x7FFFFF00); | |
| 476 | ||
| 477 | try test__fixunsdfsi(-0x1.FFFFFEp+30, 0); | |
| 478 | try test__fixunsdfsi(-0x1.FFFFFCp+30, 0); | |
| 479 | ||
| 480 | try test__fixunsdfsi(0x1.FFFFFFFEp+31, 0xFFFFFFFF); | |
| 481 | try test__fixunsdfsi(0x1.FFFFFFFC00000p+30, 0x7FFFFFFF); | |
| 482 | try test__fixunsdfsi(0x1.FFFFFFF800000p+30, 0x7FFFFFFE); | |
| 469 | test u32_intFromFloat_f64 { | |
| 470 | try test_u32_intFromFloat_f64(0.0, 0); | |
| 471 | ||
| 472 | try test_u32_intFromFloat_f64(0.5, 0); | |
| 473 | try test_u32_intFromFloat_f64(0.99, 0); | |
| 474 | try test_u32_intFromFloat_f64(1.0, 1); | |
| 475 | try test_u32_intFromFloat_f64(1.5, 1); | |
| 476 | try test_u32_intFromFloat_f64(1.99, 1); | |
| 477 | try test_u32_intFromFloat_f64(2.0, 2); | |
| 478 | try test_u32_intFromFloat_f64(2.01, 2); | |
| 479 | try test_u32_intFromFloat_f64(-0.5, 0); | |
| 480 | try test_u32_intFromFloat_f64(-0.99, 0); | |
| 481 | try test_u32_intFromFloat_f64(-1.0, 0); | |
| 482 | try test_u32_intFromFloat_f64(-1.5, 0); | |
| 483 | try test_u32_intFromFloat_f64(-1.99, 0); | |
| 484 | try test_u32_intFromFloat_f64(-2.0, 0); | |
| 485 | try test_u32_intFromFloat_f64(-2.01, 0); | |
| 486 | ||
| 487 | try test_u32_intFromFloat_f64(0x1.000000p+31, 0x80000000); | |
| 488 | try test_u32_intFromFloat_f64(0x1.000000p+32, 0xFFFFFFFF); | |
| 489 | try test_u32_intFromFloat_f64(0x1.FFFFFEp+31, 0xFFFFFF00); | |
| 490 | try test_u32_intFromFloat_f64(0x1.FFFFFEp+30, 0x7FFFFF80); | |
| 491 | try test_u32_intFromFloat_f64(0x1.FFFFFCp+30, 0x7FFFFF00); | |
| 492 | ||
| 493 | try test_u32_intFromFloat_f64(-0x1.FFFFFEp+30, 0); | |
| 494 | try test_u32_intFromFloat_f64(-0x1.FFFFFCp+30, 0); | |
| 495 | ||
| 496 | try test_u32_intFromFloat_f64(0x1.FFFFFFFEp+31, 0xFFFFFFFF); | |
| 497 | try test_u32_intFromFloat_f64(0x1.FFFFFFFC00000p+30, 0x7FFFFFFF); | |
| 498 | try test_u32_intFromFloat_f64(0x1.FFFFFFF800000p+30, 0x7FFFFFFE); | |
| 483 | 499 | } |
| 484 | 500 | |
| 485 | fn test__fixdfdi(a: f64, expected: i64) !void { | |
| 486 | const x = __fixdfdi(a); | |
| 501 | fn test_i64_intFromFloat_f64(a: f64, expected: i64) !void { | |
| 502 | const x = i64_intFromFloat_f64(a); | |
| 487 | 503 | try testing.expect(x == expected); |
| 488 | 504 | } |
| 489 | 505 | |
| 490 | fn test__fixunsdfdi(a: f64, expected: u64) !void { | |
| 491 | const x = __fixunsdfdi(a); | |
| 506 | fn test_u64_intFromFloat_f64(a: f64, expected: u64) !void { | |
| 507 | const x = u64_intFromFloat_f64(a); | |
| 492 | 508 | try testing.expect(x == expected); |
| 493 | 509 | } |
| 494 | 510 | |
| 495 | test "fixdfdi" { | |
| 496 | try test__fixdfdi(-math.floatMax(f64), math.minInt(i64)); | |
| 497 | ||
| 498 | try test__fixdfdi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64)); | |
| 499 | try test__fixdfdi(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000); | |
| 500 | ||
| 501 | try test__fixdfdi(-0x1.0000000000000p+127, -0x8000000000000000); | |
| 502 | try test__fixdfdi(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000); | |
| 503 | try test__fixdfdi(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000); | |
| 504 | ||
| 505 | try test__fixdfdi(-0x1.0000000000001p+63, -0x8000000000000000); | |
| 506 | try test__fixdfdi(-0x1.0000000000000p+63, -0x8000000000000000); | |
| 507 | try test__fixdfdi(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00); | |
| 508 | try test__fixdfdi(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800); | |
| 509 | ||
| 510 | try test__fixdfdi(-0x1.FFFFFEp+62, -0x7fffff8000000000); | |
| 511 | try test__fixdfdi(-0x1.FFFFFCp+62, -0x7fffff0000000000); | |
| 512 | ||
| 513 | try test__fixdfdi(-2.01, -2); | |
| 514 | try test__fixdfdi(-2.0, -2); | |
| 515 | try test__fixdfdi(-1.99, -1); | |
| 516 | try test__fixdfdi(-1.0, -1); | |
| 517 | try test__fixdfdi(-0.99, 0); | |
| 518 | try test__fixdfdi(-0.5, 0); | |
| 519 | try test__fixdfdi(-math.floatMin(f64), 0); | |
| 520 | try test__fixdfdi(0.0, 0); | |
| 521 | try test__fixdfdi(math.floatMin(f64), 0); | |
| 522 | try test__fixdfdi(0.5, 0); | |
| 523 | try test__fixdfdi(0.99, 0); | |
| 524 | try test__fixdfdi(1.0, 1); | |
| 525 | try test__fixdfdi(1.5, 1); | |
| 526 | try test__fixdfdi(1.99, 1); | |
| 527 | try test__fixdfdi(2.0, 2); | |
| 528 | try test__fixdfdi(2.01, 2); | |
| 529 | ||
| 530 | try test__fixdfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | |
| 531 | try test__fixdfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | |
| 532 | ||
| 533 | try test__fixdfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); | |
| 534 | try test__fixdfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); | |
| 535 | try test__fixdfdi(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF); | |
| 536 | try test__fixdfdi(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF); | |
| 537 | ||
| 538 | try test__fixdfdi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF); | |
| 539 | try test__fixdfdi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF); | |
| 540 | try test__fixdfdi(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF); | |
| 541 | ||
| 542 | try test__fixdfdi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF); | |
| 543 | try test__fixdfdi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64)); | |
| 544 | ||
| 545 | try test__fixdfdi(math.floatMax(f64), math.maxInt(i64)); | |
| 511 | test i64_intFromFloat_f64 { | |
| 512 | try test_i64_intFromFloat_f64(-math.floatMax(f64), math.minInt(i64)); | |
| 513 | ||
| 514 | try test_i64_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64)); | |
| 515 | try test_i64_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000); | |
| 516 | ||
| 517 | try test_i64_intFromFloat_f64(-0x1.0000000000000p+127, -0x8000000000000000); | |
| 518 | try test_i64_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000); | |
| 519 | try test_i64_intFromFloat_f64(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000); | |
| 520 | ||
| 521 | try test_i64_intFromFloat_f64(-0x1.0000000000001p+63, -0x8000000000000000); | |
| 522 | try test_i64_intFromFloat_f64(-0x1.0000000000000p+63, -0x8000000000000000); | |
| 523 | try test_i64_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00); | |
| 524 | try test_i64_intFromFloat_f64(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800); | |
| 525 | ||
| 526 | try test_i64_intFromFloat_f64(-0x1.FFFFFEp+62, -0x7fffff8000000000); | |
| 527 | try test_i64_intFromFloat_f64(-0x1.FFFFFCp+62, -0x7fffff0000000000); | |
| 528 | ||
| 529 | try test_i64_intFromFloat_f64(-2.01, -2); | |
| 530 | try test_i64_intFromFloat_f64(-2.0, -2); | |
| 531 | try test_i64_intFromFloat_f64(-1.99, -1); | |
| 532 | try test_i64_intFromFloat_f64(-1.0, -1); | |
| 533 | try test_i64_intFromFloat_f64(-0.99, 0); | |
| 534 | try test_i64_intFromFloat_f64(-0.5, 0); | |
| 535 | try test_i64_intFromFloat_f64(-math.floatMin(f64), 0); | |
| 536 | try test_i64_intFromFloat_f64(0.0, 0); | |
| 537 | try test_i64_intFromFloat_f64(math.floatMin(f64), 0); | |
| 538 | try test_i64_intFromFloat_f64(0.5, 0); | |
| 539 | try test_i64_intFromFloat_f64(0.99, 0); | |
| 540 | try test_i64_intFromFloat_f64(1.0, 1); | |
| 541 | try test_i64_intFromFloat_f64(1.5, 1); | |
| 542 | try test_i64_intFromFloat_f64(1.99, 1); | |
| 543 | try test_i64_intFromFloat_f64(2.0, 2); | |
| 544 | try test_i64_intFromFloat_f64(2.01, 2); | |
| 545 | ||
| 546 | try test_i64_intFromFloat_f64(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | |
| 547 | try test_i64_intFromFloat_f64(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | |
| 548 | ||
| 549 | try test_i64_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); | |
| 550 | try test_i64_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); | |
| 551 | try test_i64_intFromFloat_f64(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF); | |
| 552 | try test_i64_intFromFloat_f64(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF); | |
| 553 | ||
| 554 | try test_i64_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF); | |
| 555 | try test_i64_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF); | |
| 556 | try test_i64_intFromFloat_f64(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF); | |
| 557 | ||
| 558 | try test_i64_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF); | |
| 559 | try test_i64_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64)); | |
| 560 | ||
| 561 | try test_i64_intFromFloat_f64(math.floatMax(f64), math.maxInt(i64)); | |
| 546 | 562 | } |
| 547 | 563 | |
| 548 | test "fixunsdfdi" { | |
| 549 | try test__fixunsdfdi(0.0, 0); | |
| 550 | try test__fixunsdfdi(0.5, 0); | |
| 551 | try test__fixunsdfdi(0.99, 0); | |
| 552 | try test__fixunsdfdi(1.0, 1); | |
| 553 | try test__fixunsdfdi(1.5, 1); | |
| 554 | try test__fixunsdfdi(1.99, 1); | |
| 555 | try test__fixunsdfdi(2.0, 2); | |
| 556 | try test__fixunsdfdi(2.01, 2); | |
| 557 | try test__fixunsdfdi(-0.5, 0); | |
| 558 | try test__fixunsdfdi(-0.99, 0); | |
| 559 | try test__fixunsdfdi(-1.0, 0); | |
| 560 | try test__fixunsdfdi(-1.5, 0); | |
| 561 | try test__fixunsdfdi(-1.99, 0); | |
| 562 | try test__fixunsdfdi(-2.0, 0); | |
| 563 | try test__fixunsdfdi(-2.01, 0); | |
| 564 | ||
| 565 | try test__fixunsdfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | |
| 566 | try test__fixunsdfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | |
| 567 | ||
| 568 | try test__fixunsdfdi(-0x1.FFFFFEp+62, 0); | |
| 569 | try test__fixunsdfdi(-0x1.FFFFFCp+62, 0); | |
| 570 | ||
| 571 | try test__fixunsdfdi(0x1.FFFFFFFFFFFFFp+63, 0xFFFFFFFFFFFFF800); | |
| 572 | try test__fixunsdfdi(0x1.0000000000000p+63, 0x8000000000000000); | |
| 573 | try test__fixunsdfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); | |
| 574 | try test__fixunsdfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); | |
| 575 | ||
| 576 | try test__fixunsdfdi(-0x1.FFFFFFFFFFFFFp+62, 0); | |
| 577 | try test__fixunsdfdi(-0x1.FFFFFFFFFFFFEp+62, 0); | |
| 564 | test u64_intFromFloat_f64 { | |
| 565 | try test_u64_intFromFloat_f64(0.0, 0); | |
| 566 | try test_u64_intFromFloat_f64(0.5, 0); | |
| 567 | try test_u64_intFromFloat_f64(0.99, 0); | |
| 568 | try test_u64_intFromFloat_f64(1.0, 1); | |
| 569 | try test_u64_intFromFloat_f64(1.5, 1); | |
| 570 | try test_u64_intFromFloat_f64(1.99, 1); | |
| 571 | try test_u64_intFromFloat_f64(2.0, 2); | |
| 572 | try test_u64_intFromFloat_f64(2.01, 2); | |
| 573 | try test_u64_intFromFloat_f64(-0.5, 0); | |
| 574 | try test_u64_intFromFloat_f64(-0.99, 0); | |
| 575 | try test_u64_intFromFloat_f64(-1.0, 0); | |
| 576 | try test_u64_intFromFloat_f64(-1.5, 0); | |
| 577 | try test_u64_intFromFloat_f64(-1.99, 0); | |
| 578 | try test_u64_intFromFloat_f64(-2.0, 0); | |
| 579 | try test_u64_intFromFloat_f64(-2.01, 0); | |
| 580 | ||
| 581 | try test_u64_intFromFloat_f64(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | |
| 582 | try test_u64_intFromFloat_f64(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | |
| 583 | ||
| 584 | try test_u64_intFromFloat_f64(-0x1.FFFFFEp+62, 0); | |
| 585 | try test_u64_intFromFloat_f64(-0x1.FFFFFCp+62, 0); | |
| 586 | ||
| 587 | try test_u64_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+63, 0xFFFFFFFFFFFFF800); | |
| 588 | try test_u64_intFromFloat_f64(0x1.0000000000000p+63, 0x8000000000000000); | |
| 589 | try test_u64_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); | |
| 590 | try test_u64_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); | |
| 591 | ||
| 592 | try test_u64_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+62, 0); | |
| 593 | try test_u64_intFromFloat_f64(-0x1.FFFFFFFFFFFFEp+62, 0); | |
| 578 | 594 | } |
| 579 | 595 | |
| 580 | fn test__fixdfti(a: f64, expected: i128) !void { | |
| 581 | const x = __fixdfti(a); | |
| 596 | fn test_i128_intFromFloat_f64(a: f64, expected: i128) !void { | |
| 597 | const x = i128_intFromFloat_f64(a); | |
| 582 | 598 | try testing.expect(x == expected); |
| 583 | 599 | } |
| 584 | 600 | |
| 585 | fn test__fixunsdfti(a: f64, expected: u128) !void { | |
| 586 | const x = __fixunsdfti(a); | |
| 601 | fn test_u128_intFromFloat_f64(a: f64, expected: u128) !void { | |
| 602 | const x = u128_intFromFloat_f64(a); | |
| 587 | 603 | try testing.expect(x == expected); |
| 588 | 604 | } |
| 589 | 605 | |
| 590 | test "fixdfti" { | |
| 591 | try test__fixdfti(-math.floatMax(f64), math.minInt(i128)); | |
| 592 | ||
| 593 | try test__fixdfti(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128)); | |
| 594 | try test__fixdfti(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000); | |
| 595 | ||
| 596 | try test__fixdfti(-0x1.0000000000000p+127, -0x80000000000000000000000000000000); | |
| 597 | try test__fixdfti(-0x1.FFFFFFFFFFFFFp+126, -0x7FFFFFFFFFFFFC000000000000000000); | |
| 598 | try test__fixdfti(-0x1.FFFFFFFFFFFFEp+126, -0x7FFFFFFFFFFFF8000000000000000000); | |
| 599 | ||
| 600 | try test__fixdfti(-0x1.0000000000001p+63, -0x8000000000000800); | |
| 601 | try test__fixdfti(-0x1.0000000000000p+63, -0x8000000000000000); | |
| 602 | try test__fixdfti(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00); | |
| 603 | try test__fixdfti(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800); | |
| 604 | ||
| 605 | try test__fixdfti(-0x1.FFFFFEp+62, -0x7fffff8000000000); | |
| 606 | try test__fixdfti(-0x1.FFFFFCp+62, -0x7fffff0000000000); | |
| 607 | ||
| 608 | try test__fixdfti(-2.01, -2); | |
| 609 | try test__fixdfti(-2.0, -2); | |
| 610 | try test__fixdfti(-1.99, -1); | |
| 611 | try test__fixdfti(-1.0, -1); | |
| 612 | try test__fixdfti(-0.99, 0); | |
| 613 | try test__fixdfti(-0.5, 0); | |
| 614 | try test__fixdfti(-math.floatMin(f64), 0); | |
| 615 | try test__fixdfti(0.0, 0); | |
| 616 | try test__fixdfti(math.floatMin(f64), 0); | |
| 617 | try test__fixdfti(0.5, 0); | |
| 618 | try test__fixdfti(0.99, 0); | |
| 619 | try test__fixdfti(1.0, 1); | |
| 620 | try test__fixdfti(1.5, 1); | |
| 621 | try test__fixdfti(1.99, 1); | |
| 622 | try test__fixdfti(2.0, 2); | |
| 623 | try test__fixdfti(2.01, 2); | |
| 624 | ||
| 625 | try test__fixdfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | |
| 626 | try test__fixdfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | |
| 627 | ||
| 628 | try test__fixdfti(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); | |
| 629 | try test__fixdfti(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); | |
| 630 | try test__fixdfti(0x1.0000000000000p+63, 0x8000000000000000); | |
| 631 | try test__fixdfti(0x1.0000000000001p+63, 0x8000000000000800); | |
| 632 | ||
| 633 | try test__fixdfti(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000); | |
| 634 | try test__fixdfti(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000); | |
| 635 | try test__fixdfti(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | |
| 636 | ||
| 637 | try test__fixdfti(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | |
| 638 | try test__fixdfti(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128)); | |
| 639 | ||
| 640 | try test__fixdfti(math.floatMax(f64), math.maxInt(i128)); | |
| 606 | test i128_intFromFloat_f64 { | |
| 607 | try test_i128_intFromFloat_f64(-math.floatMax(f64), math.minInt(i128)); | |
| 608 | ||
| 609 | try test_i128_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128)); | |
| 610 | try test_i128_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000); | |
| 611 | ||
| 612 | try test_i128_intFromFloat_f64(-0x1.0000000000000p+127, -0x80000000000000000000000000000000); | |
| 613 | try test_i128_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+126, -0x7FFFFFFFFFFFFC000000000000000000); | |
| 614 | try test_i128_intFromFloat_f64(-0x1.FFFFFFFFFFFFEp+126, -0x7FFFFFFFFFFFF8000000000000000000); | |
| 615 | ||
| 616 | try test_i128_intFromFloat_f64(-0x1.0000000000001p+63, -0x8000000000000800); | |
| 617 | try test_i128_intFromFloat_f64(-0x1.0000000000000p+63, -0x8000000000000000); | |
| 618 | try test_i128_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00); | |
| 619 | try test_i128_intFromFloat_f64(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800); | |
| 620 | ||
| 621 | try test_i128_intFromFloat_f64(-0x1.FFFFFEp+62, -0x7fffff8000000000); | |
| 622 | try test_i128_intFromFloat_f64(-0x1.FFFFFCp+62, -0x7fffff0000000000); | |
| 623 | ||
| 624 | try test_i128_intFromFloat_f64(-2.01, -2); | |
| 625 | try test_i128_intFromFloat_f64(-2.0, -2); | |
| 626 | try test_i128_intFromFloat_f64(-1.99, -1); | |
| 627 | try test_i128_intFromFloat_f64(-1.0, -1); | |
| 628 | try test_i128_intFromFloat_f64(-0.99, 0); | |
| 629 | try test_i128_intFromFloat_f64(-0.5, 0); | |
| 630 | try test_i128_intFromFloat_f64(-math.floatMin(f64), 0); | |
| 631 | try test_i128_intFromFloat_f64(0.0, 0); | |
| 632 | try test_i128_intFromFloat_f64(math.floatMin(f64), 0); | |
| 633 | try test_i128_intFromFloat_f64(0.5, 0); | |
| 634 | try test_i128_intFromFloat_f64(0.99, 0); | |
| 635 | try test_i128_intFromFloat_f64(1.0, 1); | |
| 636 | try test_i128_intFromFloat_f64(1.5, 1); | |
| 637 | try test_i128_intFromFloat_f64(1.99, 1); | |
| 638 | try test_i128_intFromFloat_f64(2.0, 2); | |
| 639 | try test_i128_intFromFloat_f64(2.01, 2); | |
| 640 | ||
| 641 | try test_i128_intFromFloat_f64(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | |
| 642 | try test_i128_intFromFloat_f64(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | |
| 643 | ||
| 644 | try test_i128_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); | |
| 645 | try test_i128_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); | |
| 646 | try test_i128_intFromFloat_f64(0x1.0000000000000p+63, 0x8000000000000000); | |
| 647 | try test_i128_intFromFloat_f64(0x1.0000000000001p+63, 0x8000000000000800); | |
| 648 | ||
| 649 | try test_i128_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000); | |
| 650 | try test_i128_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000); | |
| 651 | try test_i128_intFromFloat_f64(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | |
| 652 | ||
| 653 | try test_i128_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | |
| 654 | try test_i128_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128)); | |
| 655 | ||
| 656 | try test_i128_intFromFloat_f64(math.floatMax(f64), math.maxInt(i128)); | |
| 641 | 657 | } |
| 642 | 658 | |
| 643 | test "fixunsdfti" { | |
| 644 | try test__fixunsdfti(0.0, 0); | |
| 645 | ||
| 646 | try test__fixunsdfti(0.5, 0); | |
| 647 | try test__fixunsdfti(0.99, 0); | |
| 648 | try test__fixunsdfti(1.0, 1); | |
| 649 | try test__fixunsdfti(1.5, 1); | |
| 650 | try test__fixunsdfti(1.99, 1); | |
| 651 | try test__fixunsdfti(2.0, 2); | |
| 652 | try test__fixunsdfti(2.01, 2); | |
| 653 | try test__fixunsdfti(-0.5, 0); | |
| 654 | try test__fixunsdfti(-0.99, 0); | |
| 655 | try test__fixunsdfti(-1.0, 0); | |
| 656 | try test__fixunsdfti(-1.5, 0); | |
| 657 | try test__fixunsdfti(-1.99, 0); | |
| 658 | try test__fixunsdfti(-2.0, 0); | |
| 659 | try test__fixunsdfti(-2.01, 0); | |
| 660 | ||
| 661 | try test__fixunsdfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | |
| 662 | try test__fixunsdfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | |
| 663 | ||
| 664 | try test__fixunsdfti(-0x1.FFFFFEp+62, 0); | |
| 665 | try test__fixunsdfti(-0x1.FFFFFCp+62, 0); | |
| 666 | ||
| 667 | try test__fixunsdfti(0x1.FFFFFFFFFFFFFp+63, 0xFFFFFFFFFFFFF800); | |
| 668 | try test__fixunsdfti(0x1.0000000000000p+63, 0x8000000000000000); | |
| 669 | try test__fixunsdfti(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); | |
| 670 | try test__fixunsdfti(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); | |
| 671 | ||
| 672 | try test__fixunsdfti(0x1.FFFFFFFFFFFFFp+127, 0xFFFFFFFFFFFFF8000000000000000000); | |
| 673 | try test__fixunsdfti(0x1.0000000000000p+127, 0x80000000000000000000000000000000); | |
| 674 | try test__fixunsdfti(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000); | |
| 675 | try test__fixunsdfti(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000); | |
| 676 | try test__fixunsdfti(0x1.0000000000000p+128, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | |
| 677 | ||
| 678 | try test__fixunsdfti(-0x1.FFFFFFFFFFFFFp+62, 0); | |
| 679 | try test__fixunsdfti(-0x1.FFFFFFFFFFFFEp+62, 0); | |
| 659 | test u128_intFromFloat_f64 { | |
| 660 | try test_u128_intFromFloat_f64(0.0, 0); | |
| 661 | ||
| 662 | try test_u128_intFromFloat_f64(0.5, 0); | |
| 663 | try test_u128_intFromFloat_f64(0.99, 0); | |
| 664 | try test_u128_intFromFloat_f64(1.0, 1); | |
| 665 | try test_u128_intFromFloat_f64(1.5, 1); | |
| 666 | try test_u128_intFromFloat_f64(1.99, 1); | |
| 667 | try test_u128_intFromFloat_f64(2.0, 2); | |
| 668 | try test_u128_intFromFloat_f64(2.01, 2); | |
| 669 | try test_u128_intFromFloat_f64(-0.5, 0); | |
| 670 | try test_u128_intFromFloat_f64(-0.99, 0); | |
| 671 | try test_u128_intFromFloat_f64(-1.0, 0); | |
| 672 | try test_u128_intFromFloat_f64(-1.5, 0); | |
| 673 | try test_u128_intFromFloat_f64(-1.99, 0); | |
| 674 | try test_u128_intFromFloat_f64(-2.0, 0); | |
| 675 | try test_u128_intFromFloat_f64(-2.01, 0); | |
| 676 | ||
| 677 | try test_u128_intFromFloat_f64(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | |
| 678 | try test_u128_intFromFloat_f64(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | |
| 679 | ||
| 680 | try test_u128_intFromFloat_f64(-0x1.FFFFFEp+62, 0); | |
| 681 | try test_u128_intFromFloat_f64(-0x1.FFFFFCp+62, 0); | |
| 682 | ||
| 683 | try test_u128_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+63, 0xFFFFFFFFFFFFF800); | |
| 684 | try test_u128_intFromFloat_f64(0x1.0000000000000p+63, 0x8000000000000000); | |
| 685 | try test_u128_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); | |
| 686 | try test_u128_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); | |
| 687 | ||
| 688 | try test_u128_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+127, 0xFFFFFFFFFFFFF8000000000000000000); | |
| 689 | try test_u128_intFromFloat_f64(0x1.0000000000000p+127, 0x80000000000000000000000000000000); | |
| 690 | try test_u128_intFromFloat_f64(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000); | |
| 691 | try test_u128_intFromFloat_f64(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000); | |
| 692 | try test_u128_intFromFloat_f64(0x1.0000000000000p+128, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | |
| 693 | ||
| 694 | try test_u128_intFromFloat_f64(-0x1.FFFFFFFFFFFFFp+62, 0); | |
| 695 | try test_u128_intFromFloat_f64(-0x1.FFFFFFFFFFFFEp+62, 0); | |
| 680 | 696 | } |
| 681 | 697 | |
| 682 | fn test_fixdfei(comptime T: type, expected: T, a: f64) !void { | |
| 698 | fn test_intFromFloat_f64(comptime T: type, expected: T, a: f64) !void { | |
| 683 | 699 | const int = @typeInfo(T).int; |
| 684 | 700 | var actual: T = undefined; |
| 685 | 701 | _ = switch (int.signedness) { |
| 686 | .signed => __fixdfei, | |
| 687 | .unsigned => __fixunsdfei, | |
| 688 | }(@ptrCast(&actual), int.bits, a); | |
| 702 | .signed => signed_intFromFloat_f64, | |
| 703 | .unsigned => unsigned_intFromFloat_f64, | |
| 704 | }(@ptrCast(&actual), a); | |
| 689 | 705 | try testing.expect(expected == actual); |
| 690 | 706 | } |
| 691 | 707 | |
| 692 | test "fixdfei" { | |
| 693 | try test_fixdfei(i256, -1 << 255, -0x1p255); | |
| 694 | try test_fixdfei(i256, -1 << 127, -0x1p127); | |
| 695 | try test_fixdfei(i256, -1 << 100, -0x1p100); | |
| 696 | try test_fixdfei(i256, -1 << 50, -0x1p50); | |
| 697 | try test_fixdfei(i256, -1 << 1, -0x1p1); | |
| 698 | try test_fixdfei(i256, -1 << 0, -0x1p0); | |
| 699 | try test_fixdfei(i256, 0, 0); | |
| 700 | try test_fixdfei(i256, 1 << 0, 0x1p0); | |
| 701 | try test_fixdfei(i256, 1 << 1, 0x1p1); | |
| 702 | try test_fixdfei(i256, 1 << 50, 0x1p50); | |
| 703 | try test_fixdfei(i256, 1 << 100, 0x1p100); | |
| 704 | try test_fixdfei(i256, 1 << 127, 0x1p127); | |
| 705 | try test_fixdfei(i256, 1 << 254, 0x1p254); | |
| 708 | test signed_intFromFloat_f64 { | |
| 709 | try test_intFromFloat_f64(i256, -1 << 255, -0x1p255); | |
| 710 | try test_intFromFloat_f64(i256, -1 << 127, -0x1p127); | |
| 711 | try test_intFromFloat_f64(i256, -1 << 100, -0x1p100); | |
| 712 | try test_intFromFloat_f64(i256, -1 << 50, -0x1p50); | |
| 713 | try test_intFromFloat_f64(i256, -1 << 1, -0x1p1); | |
| 714 | try test_intFromFloat_f64(i256, -1 << 0, -0x1p0); | |
| 715 | try test_intFromFloat_f64(i256, 0, 0); | |
| 716 | try test_intFromFloat_f64(i256, 1 << 0, 0x1p0); | |
| 717 | try test_intFromFloat_f64(i256, 1 << 1, 0x1p1); | |
| 718 | try test_intFromFloat_f64(i256, 1 << 50, 0x1p50); | |
| 719 | try test_intFromFloat_f64(i256, 1 << 100, 0x1p100); | |
| 720 | try test_intFromFloat_f64(i256, 1 << 127, 0x1p127); | |
| 721 | try test_intFromFloat_f64(i256, 1 << 254, 0x1p254); | |
| 706 | 722 | } |
| 707 | 723 | |
| 708 | test "fixundfei" { | |
| 709 | try test_fixdfei(u256, 0, 0); | |
| 710 | try test_fixdfei(u256, 1 << 0, 0x1p0); | |
| 711 | try test_fixdfei(u256, 1 << 1, 0x1p1); | |
| 712 | try test_fixdfei(u256, 1 << 50, 0x1p50); | |
| 713 | try test_fixdfei(u256, 1 << 100, 0x1p100); | |
| 714 | try test_fixdfei(u256, 1 << 127, 0x1p127); | |
| 715 | try test_fixdfei(u256, 1 << 255, 0x1p255); | |
| 724 | test unsigned_intFromFloat_f64 { | |
| 725 | try test_intFromFloat_f64(u256, 0, 0); | |
| 726 | try test_intFromFloat_f64(u256, 1 << 0, 0x1p0); | |
| 727 | try test_intFromFloat_f64(u256, 1 << 1, 0x1p1); | |
| 728 | try test_intFromFloat_f64(u256, 1 << 50, 0x1p50); | |
| 729 | try test_intFromFloat_f64(u256, 1 << 100, 0x1p100); | |
| 730 | try test_intFromFloat_f64(u256, 1 << 127, 0x1p127); | |
| 731 | try test_intFromFloat_f64(u256, 1 << 255, 0x1p255); | |
| 716 | 732 | } |
| 717 | 733 | |
| 718 | fn test__fixtfsi(a: f128, expected: i32) !void { | |
| 719 | const x = __fixtfsi(a); | |
| 734 | fn test_i32_intFromFloat_f128(a: f128, expected: i32) !void { | |
| 735 | const x = i32_intFromFloat_f128(a); | |
| 720 | 736 | try testing.expect(x == expected); |
| 721 | 737 | } |
| 722 | 738 | |
| 723 | fn test__fixunstfsi(a: f128, expected: u32) !void { | |
| 724 | const x = __fixunstfsi(a); | |
| 739 | fn test_u32_intFromFloat_f128(a: f128, expected: u32) !void { | |
| 740 | const x = u32_intFromFloat_f128(a); | |
| 725 | 741 | try testing.expect(x == expected); |
| 726 | 742 | } |
| 727 | 743 | |
| 728 | test "fixtfsi" { | |
| 729 | try test__fixtfsi(-math.floatMax(f128), math.minInt(i32)); | |
| 730 | ||
| 731 | try test__fixtfsi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32)); | |
| 732 | try test__fixtfsi(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000); | |
| 733 | ||
| 734 | try test__fixtfsi(-0x1.0000000000000p+127, -0x80000000); | |
| 735 | try test__fixtfsi(-0x1.FFFFFFFFFFFFFp+126, -0x80000000); | |
| 736 | try test__fixtfsi(-0x1.FFFFFFFFFFFFEp+126, -0x80000000); | |
| 737 | ||
| 738 | try test__fixtfsi(-0x1.0000000000001p+63, -0x80000000); | |
| 739 | try test__fixtfsi(-0x1.0000000000000p+63, -0x80000000); | |
| 740 | try test__fixtfsi(-0x1.FFFFFFFFFFFFFp+62, -0x80000000); | |
| 741 | try test__fixtfsi(-0x1.FFFFFFFFFFFFEp+62, -0x80000000); | |
| 742 | ||
| 743 | try test__fixtfsi(-0x1.FFFFFEp+62, -0x80000000); | |
| 744 | try test__fixtfsi(-0x1.FFFFFCp+62, -0x80000000); | |
| 745 | ||
| 746 | try test__fixtfsi(-0x1.000000p+31, -0x80000000); | |
| 747 | try test__fixtfsi(-0x1.FFFFFFp+30, -0x7FFFFFC0); | |
| 748 | try test__fixtfsi(-0x1.FFFFFEp+30, -0x7FFFFF80); | |
| 749 | try test__fixtfsi(-0x1.FFFFFCp+30, -0x7FFFFF00); | |
| 750 | ||
| 751 | try test__fixtfsi(-2.01, -2); | |
| 752 | try test__fixtfsi(-2.0, -2); | |
| 753 | try test__fixtfsi(-1.99, -1); | |
| 754 | try test__fixtfsi(-1.0, -1); | |
| 755 | try test__fixtfsi(-0.99, 0); | |
| 756 | try test__fixtfsi(-0.5, 0); | |
| 757 | try test__fixtfsi(-math.floatMin(f32), 0); | |
| 758 | try test__fixtfsi(0.0, 0); | |
| 759 | try test__fixtfsi(math.floatMin(f32), 0); | |
| 760 | try test__fixtfsi(0.5, 0); | |
| 761 | try test__fixtfsi(0.99, 0); | |
| 762 | try test__fixtfsi(1.0, 1); | |
| 763 | try test__fixtfsi(1.5, 1); | |
| 764 | try test__fixtfsi(1.99, 1); | |
| 765 | try test__fixtfsi(2.0, 2); | |
| 766 | try test__fixtfsi(2.01, 2); | |
| 767 | ||
| 768 | try test__fixtfsi(0x1.FFFFFCp+30, 0x7FFFFF00); | |
| 769 | try test__fixtfsi(0x1.FFFFFEp+30, 0x7FFFFF80); | |
| 770 | try test__fixtfsi(0x1.FFFFFFp+30, 0x7FFFFFC0); | |
| 771 | try test__fixtfsi(0x1.000000p+31, 0x7FFFFFFF); | |
| 772 | ||
| 773 | try test__fixtfsi(0x1.FFFFFCp+62, 0x7FFFFFFF); | |
| 774 | try test__fixtfsi(0x1.FFFFFEp+62, 0x7FFFFFFF); | |
| 775 | ||
| 776 | try test__fixtfsi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF); | |
| 777 | try test__fixtfsi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF); | |
| 778 | try test__fixtfsi(0x1.0000000000000p+63, 0x7FFFFFFF); | |
| 779 | try test__fixtfsi(0x1.0000000000001p+63, 0x7FFFFFFF); | |
| 780 | ||
| 781 | try test__fixtfsi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF); | |
| 782 | try test__fixtfsi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF); | |
| 783 | try test__fixtfsi(0x1.0000000000000p+127, 0x7FFFFFFF); | |
| 784 | ||
| 785 | try test__fixtfsi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF); | |
| 786 | try test__fixtfsi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32)); | |
| 787 | ||
| 788 | try test__fixtfsi(math.floatMax(f128), math.maxInt(i32)); | |
| 744 | test i32_intFromFloat_f128 { | |
| 745 | try test_i32_intFromFloat_f128(-math.floatMax(f128), math.minInt(i32)); | |
| 746 | ||
| 747 | try test_i32_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i32)); | |
| 748 | try test_i32_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000); | |
| 749 | ||
| 750 | try test_i32_intFromFloat_f128(-0x1.0000000000000p+127, -0x80000000); | |
| 751 | try test_i32_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+126, -0x80000000); | |
| 752 | try test_i32_intFromFloat_f128(-0x1.FFFFFFFFFFFFEp+126, -0x80000000); | |
| 753 | ||
| 754 | try test_i32_intFromFloat_f128(-0x1.0000000000001p+63, -0x80000000); | |
| 755 | try test_i32_intFromFloat_f128(-0x1.0000000000000p+63, -0x80000000); | |
| 756 | try test_i32_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+62, -0x80000000); | |
| 757 | try test_i32_intFromFloat_f128(-0x1.FFFFFFFFFFFFEp+62, -0x80000000); | |
| 758 | ||
| 759 | try test_i32_intFromFloat_f128(-0x1.FFFFFEp+62, -0x80000000); | |
| 760 | try test_i32_intFromFloat_f128(-0x1.FFFFFCp+62, -0x80000000); | |
| 761 | ||
| 762 | try test_i32_intFromFloat_f128(-0x1.000000p+31, -0x80000000); | |
| 763 | try test_i32_intFromFloat_f128(-0x1.FFFFFFp+30, -0x7FFFFFC0); | |
| 764 | try test_i32_intFromFloat_f128(-0x1.FFFFFEp+30, -0x7FFFFF80); | |
| 765 | try test_i32_intFromFloat_f128(-0x1.FFFFFCp+30, -0x7FFFFF00); | |
| 766 | ||
| 767 | try test_i32_intFromFloat_f128(-2.01, -2); | |
| 768 | try test_i32_intFromFloat_f128(-2.0, -2); | |
| 769 | try test_i32_intFromFloat_f128(-1.99, -1); | |
| 770 | try test_i32_intFromFloat_f128(-1.0, -1); | |
| 771 | try test_i32_intFromFloat_f128(-0.99, 0); | |
| 772 | try test_i32_intFromFloat_f128(-0.5, 0); | |
| 773 | try test_i32_intFromFloat_f128(-math.floatMin(f32), 0); | |
| 774 | try test_i32_intFromFloat_f128(0.0, 0); | |
| 775 | try test_i32_intFromFloat_f128(math.floatMin(f32), 0); | |
| 776 | try test_i32_intFromFloat_f128(0.5, 0); | |
| 777 | try test_i32_intFromFloat_f128(0.99, 0); | |
| 778 | try test_i32_intFromFloat_f128(1.0, 1); | |
| 779 | try test_i32_intFromFloat_f128(1.5, 1); | |
| 780 | try test_i32_intFromFloat_f128(1.99, 1); | |
| 781 | try test_i32_intFromFloat_f128(2.0, 2); | |
| 782 | try test_i32_intFromFloat_f128(2.01, 2); | |
| 783 | ||
| 784 | try test_i32_intFromFloat_f128(0x1.FFFFFCp+30, 0x7FFFFF00); | |
| 785 | try test_i32_intFromFloat_f128(0x1.FFFFFEp+30, 0x7FFFFF80); | |
| 786 | try test_i32_intFromFloat_f128(0x1.FFFFFFp+30, 0x7FFFFFC0); | |
| 787 | try test_i32_intFromFloat_f128(0x1.000000p+31, 0x7FFFFFFF); | |
| 788 | ||
| 789 | try test_i32_intFromFloat_f128(0x1.FFFFFCp+62, 0x7FFFFFFF); | |
| 790 | try test_i32_intFromFloat_f128(0x1.FFFFFEp+62, 0x7FFFFFFF); | |
| 791 | ||
| 792 | try test_i32_intFromFloat_f128(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFF); | |
| 793 | try test_i32_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFF); | |
| 794 | try test_i32_intFromFloat_f128(0x1.0000000000000p+63, 0x7FFFFFFF); | |
| 795 | try test_i32_intFromFloat_f128(0x1.0000000000001p+63, 0x7FFFFFFF); | |
| 796 | ||
| 797 | try test_i32_intFromFloat_f128(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFF); | |
| 798 | try test_i32_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFF); | |
| 799 | try test_i32_intFromFloat_f128(0x1.0000000000000p+127, 0x7FFFFFFF); | |
| 800 | ||
| 801 | try test_i32_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFF); | |
| 802 | try test_i32_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i32)); | |
| 803 | ||
| 804 | try test_i32_intFromFloat_f128(math.floatMax(f128), math.maxInt(i32)); | |
| 789 | 805 | } |
| 790 | 806 | |
| 791 | test "fixunstfsi" { | |
| 792 | try test__fixunstfsi(math.inf(f128), 0xffffffff); | |
| 793 | try test__fixunstfsi(0, 0x0); | |
| 794 | try test__fixunstfsi(0x1.23456789abcdefp+5, 0x24); | |
| 795 | try test__fixunstfsi(0x1.23456789abcdefp-3, 0x0); | |
| 796 | try test__fixunstfsi(0x1.23456789abcdefp+20, 0x123456); | |
| 797 | try test__fixunstfsi(0x1.23456789abcdefp+40, 0xffffffff); | |
| 798 | try test__fixunstfsi(0x1.23456789abcdefp+256, 0xffffffff); | |
| 799 | try test__fixunstfsi(-0x1.23456789abcdefp+3, 0x0); | |
| 800 | ||
| 801 | try test__fixunstfsi(0x1p+32, 0xFFFFFFFF); | |
| 807 | test u32_intFromFloat_f128 { | |
| 808 | try test_u32_intFromFloat_f128(math.inf(f128), 0xffffffff); | |
| 809 | try test_u32_intFromFloat_f128(0, 0x0); | |
| 810 | try test_u32_intFromFloat_f128(0x1.23456789abcdefp+5, 0x24); | |
| 811 | try test_u32_intFromFloat_f128(0x1.23456789abcdefp-3, 0x0); | |
| 812 | try test_u32_intFromFloat_f128(0x1.23456789abcdefp+20, 0x123456); | |
| 813 | try test_u32_intFromFloat_f128(0x1.23456789abcdefp+40, 0xffffffff); | |
| 814 | try test_u32_intFromFloat_f128(0x1.23456789abcdefp+256, 0xffffffff); | |
| 815 | try test_u32_intFromFloat_f128(-0x1.23456789abcdefp+3, 0x0); | |
| 816 | ||
| 817 | try test_u32_intFromFloat_f128(0x1p+32, 0xFFFFFFFF); | |
| 802 | 818 | } |
| 803 | 819 | |
| 804 | fn test__fixtfdi(a: f128, expected: i64) !void { | |
| 805 | const x = __fixtfdi(a); | |
| 820 | fn test_i64_intFromFloat_f128(a: f128, expected: i64) !void { | |
| 821 | const x = i64_intFromFloat_f128(a); | |
| 806 | 822 | try testing.expect(x == expected); |
| 807 | 823 | } |
| 808 | 824 | |
| 809 | fn test__fixunstfdi(a: f128, expected: u64) !void { | |
| 810 | const x = __fixunstfdi(a); | |
| 825 | fn test_u64_intFromFloat_f128(a: f128, expected: u64) !void { | |
| 826 | const x = u64_intFromFloat_f128(a); | |
| 811 | 827 | try testing.expect(x == expected); |
| 812 | 828 | } |
| 813 | 829 | |
| 814 | test "fixtfdi" { | |
| 815 | try test__fixtfdi(-math.floatMax(f128), math.minInt(i64)); | |
| 816 | ||
| 817 | try test__fixtfdi(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64)); | |
| 818 | try test__fixtfdi(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000); | |
| 819 | ||
| 820 | try test__fixtfdi(-0x1.0000000000000p+127, -0x8000000000000000); | |
| 821 | try test__fixtfdi(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000); | |
| 822 | try test__fixtfdi(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000); | |
| 823 | ||
| 824 | try test__fixtfdi(-0x1.0000000000001p+63, -0x8000000000000000); | |
| 825 | try test__fixtfdi(-0x1.0000000000000p+63, -0x8000000000000000); | |
| 826 | try test__fixtfdi(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00); | |
| 827 | try test__fixtfdi(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800); | |
| 828 | ||
| 829 | try test__fixtfdi(-0x1.FFFFFEp+62, -0x7FFFFF8000000000); | |
| 830 | try test__fixtfdi(-0x1.FFFFFCp+62, -0x7FFFFF0000000000); | |
| 831 | ||
| 832 | try test__fixtfdi(-0x1.000000p+31, -0x80000000); | |
| 833 | try test__fixtfdi(-0x1.FFFFFFp+30, -0x7FFFFFC0); | |
| 834 | try test__fixtfdi(-0x1.FFFFFEp+30, -0x7FFFFF80); | |
| 835 | try test__fixtfdi(-0x1.FFFFFCp+30, -0x7FFFFF00); | |
| 836 | ||
| 837 | try test__fixtfdi(-2.01, -2); | |
| 838 | try test__fixtfdi(-2.0, -2); | |
| 839 | try test__fixtfdi(-1.99, -1); | |
| 840 | try test__fixtfdi(-1.0, -1); | |
| 841 | try test__fixtfdi(-0.99, 0); | |
| 842 | try test__fixtfdi(-0.5, 0); | |
| 843 | try test__fixtfdi(-math.floatMin(f64), 0); | |
| 844 | try test__fixtfdi(0.0, 0); | |
| 845 | try test__fixtfdi(math.floatMin(f64), 0); | |
| 846 | try test__fixtfdi(0.5, 0); | |
| 847 | try test__fixtfdi(0.99, 0); | |
| 848 | try test__fixtfdi(1.0, 1); | |
| 849 | try test__fixtfdi(1.5, 1); | |
| 850 | try test__fixtfdi(1.99, 1); | |
| 851 | try test__fixtfdi(2.0, 2); | |
| 852 | try test__fixtfdi(2.01, 2); | |
| 853 | ||
| 854 | try test__fixtfdi(0x1.FFFFFCp+30, 0x7FFFFF00); | |
| 855 | try test__fixtfdi(0x1.FFFFFEp+30, 0x7FFFFF80); | |
| 856 | try test__fixtfdi(0x1.FFFFFFp+30, 0x7FFFFFC0); | |
| 857 | try test__fixtfdi(0x1.000000p+31, 0x80000000); | |
| 858 | ||
| 859 | try test__fixtfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | |
| 860 | try test__fixtfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | |
| 861 | ||
| 862 | try test__fixtfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); | |
| 863 | try test__fixtfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); | |
| 864 | try test__fixtfdi(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF); | |
| 865 | try test__fixtfdi(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF); | |
| 866 | ||
| 867 | try test__fixtfdi(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF); | |
| 868 | try test__fixtfdi(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF); | |
| 869 | try test__fixtfdi(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF); | |
| 870 | ||
| 871 | try test__fixtfdi(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF); | |
| 872 | try test__fixtfdi(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64)); | |
| 873 | ||
| 874 | try test__fixtfdi(math.floatMax(f128), math.maxInt(i64)); | |
| 830 | test i64_intFromFloat_f128 { | |
| 831 | try test_i64_intFromFloat_f128(-math.floatMax(f128), math.minInt(i64)); | |
| 832 | ||
| 833 | try test_i64_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i64)); | |
| 834 | try test_i64_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+1023, -0x8000000000000000); | |
| 835 | ||
| 836 | try test_i64_intFromFloat_f128(-0x1.0000000000000p+127, -0x8000000000000000); | |
| 837 | try test_i64_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+126, -0x8000000000000000); | |
| 838 | try test_i64_intFromFloat_f128(-0x1.FFFFFFFFFFFFEp+126, -0x8000000000000000); | |
| 839 | ||
| 840 | try test_i64_intFromFloat_f128(-0x1.0000000000001p+63, -0x8000000000000000); | |
| 841 | try test_i64_intFromFloat_f128(-0x1.0000000000000p+63, -0x8000000000000000); | |
| 842 | try test_i64_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00); | |
| 843 | try test_i64_intFromFloat_f128(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800); | |
| 844 | ||
| 845 | try test_i64_intFromFloat_f128(-0x1.FFFFFEp+62, -0x7FFFFF8000000000); | |
| 846 | try test_i64_intFromFloat_f128(-0x1.FFFFFCp+62, -0x7FFFFF0000000000); | |
| 847 | ||
| 848 | try test_i64_intFromFloat_f128(-0x1.000000p+31, -0x80000000); | |
| 849 | try test_i64_intFromFloat_f128(-0x1.FFFFFFp+30, -0x7FFFFFC0); | |
| 850 | try test_i64_intFromFloat_f128(-0x1.FFFFFEp+30, -0x7FFFFF80); | |
| 851 | try test_i64_intFromFloat_f128(-0x1.FFFFFCp+30, -0x7FFFFF00); | |
| 852 | ||
| 853 | try test_i64_intFromFloat_f128(-2.01, -2); | |
| 854 | try test_i64_intFromFloat_f128(-2.0, -2); | |
| 855 | try test_i64_intFromFloat_f128(-1.99, -1); | |
| 856 | try test_i64_intFromFloat_f128(-1.0, -1); | |
| 857 | try test_i64_intFromFloat_f128(-0.99, 0); | |
| 858 | try test_i64_intFromFloat_f128(-0.5, 0); | |
| 859 | try test_i64_intFromFloat_f128(-math.floatMin(f64), 0); | |
| 860 | try test_i64_intFromFloat_f128(0.0, 0); | |
| 861 | try test_i64_intFromFloat_f128(math.floatMin(f64), 0); | |
| 862 | try test_i64_intFromFloat_f128(0.5, 0); | |
| 863 | try test_i64_intFromFloat_f128(0.99, 0); | |
| 864 | try test_i64_intFromFloat_f128(1.0, 1); | |
| 865 | try test_i64_intFromFloat_f128(1.5, 1); | |
| 866 | try test_i64_intFromFloat_f128(1.99, 1); | |
| 867 | try test_i64_intFromFloat_f128(2.0, 2); | |
| 868 | try test_i64_intFromFloat_f128(2.01, 2); | |
| 869 | ||
| 870 | try test_i64_intFromFloat_f128(0x1.FFFFFCp+30, 0x7FFFFF00); | |
| 871 | try test_i64_intFromFloat_f128(0x1.FFFFFEp+30, 0x7FFFFF80); | |
| 872 | try test_i64_intFromFloat_f128(0x1.FFFFFFp+30, 0x7FFFFFC0); | |
| 873 | try test_i64_intFromFloat_f128(0x1.000000p+31, 0x80000000); | |
| 874 | ||
| 875 | try test_i64_intFromFloat_f128(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | |
| 876 | try test_i64_intFromFloat_f128(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | |
| 877 | ||
| 878 | try test_i64_intFromFloat_f128(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); | |
| 879 | try test_i64_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); | |
| 880 | try test_i64_intFromFloat_f128(0x1.0000000000000p+63, 0x7FFFFFFFFFFFFFFF); | |
| 881 | try test_i64_intFromFloat_f128(0x1.0000000000001p+63, 0x7FFFFFFFFFFFFFFF); | |
| 882 | ||
| 883 | try test_i64_intFromFloat_f128(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFFFFF); | |
| 884 | try test_i64_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFFFF); | |
| 885 | try test_i64_intFromFloat_f128(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFF); | |
| 886 | ||
| 887 | try test_i64_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFF); | |
| 888 | try test_i64_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i64)); | |
| 889 | ||
| 890 | try test_i64_intFromFloat_f128(math.floatMax(f128), math.maxInt(i64)); | |
| 875 | 891 | } |
| 876 | 892 | |
| 877 | test "fixunstfdi" { | |
| 878 | try test__fixunstfdi(0.0, 0); | |
| 879 | ||
| 880 | try test__fixunstfdi(0.5, 0); | |
| 881 | try test__fixunstfdi(0.99, 0); | |
| 882 | try test__fixunstfdi(1.0, 1); | |
| 883 | try test__fixunstfdi(1.5, 1); | |
| 884 | try test__fixunstfdi(1.99, 1); | |
| 885 | try test__fixunstfdi(2.0, 2); | |
| 886 | try test__fixunstfdi(2.01, 2); | |
| 887 | try test__fixunstfdi(-0.5, 0); | |
| 888 | try test__fixunstfdi(-0.99, 0); | |
| 889 | try test__fixunstfdi(-1.0, 0); | |
| 890 | try test__fixunstfdi(-1.5, 0); | |
| 891 | try test__fixunstfdi(-1.99, 0); | |
| 892 | try test__fixunstfdi(-2.0, 0); | |
| 893 | try test__fixunstfdi(-2.01, 0); | |
| 894 | ||
| 895 | try test__fixunstfdi(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | |
| 896 | try test__fixunstfdi(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | |
| 897 | ||
| 898 | try test__fixunstfdi(-0x1.FFFFFEp+62, 0); | |
| 899 | try test__fixunstfdi(-0x1.FFFFFCp+62, 0); | |
| 900 | ||
| 901 | try test__fixunstfdi(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); | |
| 902 | try test__fixunstfdi(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); | |
| 903 | ||
| 904 | try test__fixunstfdi(-0x1.FFFFFFFFFFFFFp+62, 0); | |
| 905 | try test__fixunstfdi(-0x1.FFFFFFFFFFFFEp+62, 0); | |
| 906 | ||
| 907 | try test__fixunstfdi(0x1.FFFFFFFFFFFFFFFEp+63, 0xFFFFFFFFFFFFFFFF); | |
| 908 | try test__fixunstfdi(0x1.0000000000000002p+63, 0x8000000000000001); | |
| 909 | try test__fixunstfdi(0x1.0000000000000000p+63, 0x8000000000000000); | |
| 910 | try test__fixunstfdi(0x1.FFFFFFFFFFFFFFFCp+62, 0x7FFFFFFFFFFFFFFF); | |
| 911 | try test__fixunstfdi(0x1.FFFFFFFFFFFFFFF8p+62, 0x7FFFFFFFFFFFFFFE); | |
| 912 | try test__fixunstfdi(0x1p+64, 0xFFFFFFFFFFFFFFFF); | |
| 913 | ||
| 914 | try test__fixunstfdi(-0x1.0000000000000000p+63, 0); | |
| 915 | try test__fixunstfdi(-0x1.FFFFFFFFFFFFFFFCp+62, 0); | |
| 916 | try test__fixunstfdi(-0x1.FFFFFFFFFFFFFFF8p+62, 0); | |
| 893 | test u64_intFromFloat_f128 { | |
| 894 | try test_u64_intFromFloat_f128(0.0, 0); | |
| 895 | ||
| 896 | try test_u64_intFromFloat_f128(0.5, 0); | |
| 897 | try test_u64_intFromFloat_f128(0.99, 0); | |
| 898 | try test_u64_intFromFloat_f128(1.0, 1); | |
| 899 | try test_u64_intFromFloat_f128(1.5, 1); | |
| 900 | try test_u64_intFromFloat_f128(1.99, 1); | |
| 901 | try test_u64_intFromFloat_f128(2.0, 2); | |
| 902 | try test_u64_intFromFloat_f128(2.01, 2); | |
| 903 | try test_u64_intFromFloat_f128(-0.5, 0); | |
| 904 | try test_u64_intFromFloat_f128(-0.99, 0); | |
| 905 | try test_u64_intFromFloat_f128(-1.0, 0); | |
| 906 | try test_u64_intFromFloat_f128(-1.5, 0); | |
| 907 | try test_u64_intFromFloat_f128(-1.99, 0); | |
| 908 | try test_u64_intFromFloat_f128(-2.0, 0); | |
| 909 | try test_u64_intFromFloat_f128(-2.01, 0); | |
| 910 | ||
| 911 | try test_u64_intFromFloat_f128(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | |
| 912 | try test_u64_intFromFloat_f128(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | |
| 913 | ||
| 914 | try test_u64_intFromFloat_f128(-0x1.FFFFFEp+62, 0); | |
| 915 | try test_u64_intFromFloat_f128(-0x1.FFFFFCp+62, 0); | |
| 916 | ||
| 917 | try test_u64_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); | |
| 918 | try test_u64_intFromFloat_f128(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); | |
| 919 | ||
| 920 | try test_u64_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+62, 0); | |
| 921 | try test_u64_intFromFloat_f128(-0x1.FFFFFFFFFFFFEp+62, 0); | |
| 922 | ||
| 923 | try test_u64_intFromFloat_f128(0x1.FFFFFFFFFFFFFFFEp+63, 0xFFFFFFFFFFFFFFFF); | |
| 924 | try test_u64_intFromFloat_f128(0x1.0000000000000002p+63, 0x8000000000000001); | |
| 925 | try test_u64_intFromFloat_f128(0x1.0000000000000000p+63, 0x8000000000000000); | |
| 926 | try test_u64_intFromFloat_f128(0x1.FFFFFFFFFFFFFFFCp+62, 0x7FFFFFFFFFFFFFFF); | |
| 927 | try test_u64_intFromFloat_f128(0x1.FFFFFFFFFFFFFFF8p+62, 0x7FFFFFFFFFFFFFFE); | |
| 928 | try test_u64_intFromFloat_f128(0x1p+64, 0xFFFFFFFFFFFFFFFF); | |
| 929 | ||
| 930 | try test_u64_intFromFloat_f128(-0x1.0000000000000000p+63, 0); | |
| 931 | try test_u64_intFromFloat_f128(-0x1.FFFFFFFFFFFFFFFCp+62, 0); | |
| 932 | try test_u64_intFromFloat_f128(-0x1.FFFFFFFFFFFFFFF8p+62, 0); | |
| 917 | 933 | } |
| 918 | 934 | |
| 919 | fn test__fixtfti(a: f128, expected: i128) !void { | |
| 920 | const x = __fixtfti(a); | |
| 935 | fn test_i128_intFromFloat_f128(a: f128, expected: i128) !void { | |
| 936 | const x = i128_intFromFloat_f128(a); | |
| 921 | 937 | try testing.expect(x == expected); |
| 922 | 938 | } |
| 923 | 939 | |
| 924 | fn test__fixunstfti(a: f128, expected: u128) !void { | |
| 925 | const x = __fixunstfti(a); | |
| 940 | fn test_u128_intFromFloat_f128(a: f128, expected: u128) !void { | |
| 941 | const x = u128_intFromFloat_f128(a); | |
| 926 | 942 | try testing.expect(x == expected); |
| 927 | 943 | } |
| 928 | 944 | |
| 929 | test "fixtfti" { | |
| 930 | try test__fixtfti(-math.floatMax(f128), math.minInt(i128)); | |
| 931 | ||
| 932 | try test__fixtfti(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128)); | |
| 933 | try test__fixtfti(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000); | |
| 934 | ||
| 935 | try test__fixtfti(-0x1.0000000000000p+127, -0x80000000000000000000000000000000); | |
| 936 | try test__fixtfti(-0x1.FFFFFFFFFFFFFp+126, -0x7FFFFFFFFFFFFC000000000000000000); | |
| 937 | try test__fixtfti(-0x1.FFFFFFFFFFFFEp+126, -0x7FFFFFFFFFFFF8000000000000000000); | |
| 938 | ||
| 939 | try test__fixtfti(-0x1.0000000000001p+63, -0x8000000000000800); | |
| 940 | try test__fixtfti(-0x1.0000000000000p+63, -0x8000000000000000); | |
| 941 | try test__fixtfti(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00); | |
| 942 | try test__fixtfti(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800); | |
| 943 | ||
| 944 | try test__fixtfti(-0x1.FFFFFEp+62, -0x7fffff8000000000); | |
| 945 | try test__fixtfti(-0x1.FFFFFCp+62, -0x7fffff0000000000); | |
| 946 | ||
| 947 | try test__fixtfti(-2.01, -2); | |
| 948 | try test__fixtfti(-2.0, -2); | |
| 949 | try test__fixtfti(-1.99, -1); | |
| 950 | try test__fixtfti(-1.0, -1); | |
| 951 | try test__fixtfti(-0.99, 0); | |
| 952 | try test__fixtfti(-0.5, 0); | |
| 953 | try test__fixtfti(-math.floatMin(f128), 0); | |
| 954 | try test__fixtfti(0.0, 0); | |
| 955 | try test__fixtfti(math.floatMin(f128), 0); | |
| 956 | try test__fixtfti(0.5, 0); | |
| 957 | try test__fixtfti(0.99, 0); | |
| 958 | try test__fixtfti(1.0, 1); | |
| 959 | try test__fixtfti(1.5, 1); | |
| 960 | try test__fixtfti(1.99, 1); | |
| 961 | try test__fixtfti(2.0, 2); | |
| 962 | try test__fixtfti(2.01, 2); | |
| 963 | ||
| 964 | try test__fixtfti(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | |
| 965 | try test__fixtfti(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | |
| 966 | ||
| 967 | try test__fixtfti(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); | |
| 968 | try test__fixtfti(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); | |
| 969 | try test__fixtfti(0x1.0000000000000p+63, 0x8000000000000000); | |
| 970 | try test__fixtfti(0x1.0000000000001p+63, 0x8000000000000800); | |
| 971 | ||
| 972 | try test__fixtfti(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000); | |
| 973 | try test__fixtfti(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000); | |
| 974 | try test__fixtfti(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | |
| 975 | ||
| 976 | try test__fixtfti(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | |
| 977 | try test__fixtfti(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128)); | |
| 978 | ||
| 979 | try test__fixtfti(math.floatMax(f128), math.maxInt(i128)); | |
| 945 | test i128_intFromFloat_f128 { | |
| 946 | try test_i128_intFromFloat_f128(-math.floatMax(f128), math.minInt(i128)); | |
| 947 | ||
| 948 | try test_i128_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+1023, math.minInt(i128)); | |
| 949 | try test_i128_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+1023, -0x80000000000000000000000000000000); | |
| 950 | ||
| 951 | try test_i128_intFromFloat_f128(-0x1.0000000000000p+127, -0x80000000000000000000000000000000); | |
| 952 | try test_i128_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+126, -0x7FFFFFFFFFFFFC000000000000000000); | |
| 953 | try test_i128_intFromFloat_f128(-0x1.FFFFFFFFFFFFEp+126, -0x7FFFFFFFFFFFF8000000000000000000); | |
| 954 | ||
| 955 | try test_i128_intFromFloat_f128(-0x1.0000000000001p+63, -0x8000000000000800); | |
| 956 | try test_i128_intFromFloat_f128(-0x1.0000000000000p+63, -0x8000000000000000); | |
| 957 | try test_i128_intFromFloat_f128(-0x1.FFFFFFFFFFFFFp+62, -0x7FFFFFFFFFFFFC00); | |
| 958 | try test_i128_intFromFloat_f128(-0x1.FFFFFFFFFFFFEp+62, -0x7FFFFFFFFFFFF800); | |
| 959 | ||
| 960 | try test_i128_intFromFloat_f128(-0x1.FFFFFEp+62, -0x7fffff8000000000); | |
| 961 | try test_i128_intFromFloat_f128(-0x1.FFFFFCp+62, -0x7fffff0000000000); | |
| 962 | ||
| 963 | try test_i128_intFromFloat_f128(-2.01, -2); | |
| 964 | try test_i128_intFromFloat_f128(-2.0, -2); | |
| 965 | try test_i128_intFromFloat_f128(-1.99, -1); | |
| 966 | try test_i128_intFromFloat_f128(-1.0, -1); | |
| 967 | try test_i128_intFromFloat_f128(-0.99, 0); | |
| 968 | try test_i128_intFromFloat_f128(-0.5, 0); | |
| 969 | try test_i128_intFromFloat_f128(-math.floatMin(f128), 0); | |
| 970 | try test_i128_intFromFloat_f128(0.0, 0); | |
| 971 | try test_i128_intFromFloat_f128(math.floatMin(f128), 0); | |
| 972 | try test_i128_intFromFloat_f128(0.5, 0); | |
| 973 | try test_i128_intFromFloat_f128(0.99, 0); | |
| 974 | try test_i128_intFromFloat_f128(1.0, 1); | |
| 975 | try test_i128_intFromFloat_f128(1.5, 1); | |
| 976 | try test_i128_intFromFloat_f128(1.99, 1); | |
| 977 | try test_i128_intFromFloat_f128(2.0, 2); | |
| 978 | try test_i128_intFromFloat_f128(2.01, 2); | |
| 979 | ||
| 980 | try test_i128_intFromFloat_f128(0x1.FFFFFCp+62, 0x7FFFFF0000000000); | |
| 981 | try test_i128_intFromFloat_f128(0x1.FFFFFEp+62, 0x7FFFFF8000000000); | |
| 982 | ||
| 983 | try test_i128_intFromFloat_f128(0x1.FFFFFFFFFFFFEp+62, 0x7FFFFFFFFFFFF800); | |
| 984 | try test_i128_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+62, 0x7FFFFFFFFFFFFC00); | |
| 985 | try test_i128_intFromFloat_f128(0x1.0000000000000p+63, 0x8000000000000000); | |
| 986 | try test_i128_intFromFloat_f128(0x1.0000000000001p+63, 0x8000000000000800); | |
| 987 | ||
| 988 | try test_i128_intFromFloat_f128(0x1.FFFFFFFFFFFFEp+126, 0x7FFFFFFFFFFFF8000000000000000000); | |
| 989 | try test_i128_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+126, 0x7FFFFFFFFFFFFC000000000000000000); | |
| 990 | try test_i128_intFromFloat_f128(0x1.0000000000000p+127, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | |
| 991 | ||
| 992 | try test_i128_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+1023, 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); | |
| 993 | try test_i128_intFromFloat_f128(0x1.FFFFFFFFFFFFFp+1023, math.maxInt(i128)); | |
| 994 | ||
| 995 | try test_i128_intFromFloat_f128(math.floatMax(f128), math.maxInt(i128)); | |
| 980 | 996 | } |
| 981 | 997 | |
| 982 | test "fixunstfti" { | |
| 983 | try test__fixunstfti(math.inf(f128), 0xffffffffffffffffffffffffffffffff); | |
| 998 | test u128_intFromFloat_f128 { | |
| 999 | try test_u128_intFromFloat_f128(math.inf(f128), 0xffffffffffffffffffffffffffffffff); | |
| 984 | 1000 | |
| 985 | try test__fixunstfti(0.0, 0); | |
| 1001 | try test_u128_intFromFloat_f128(0.0, 0); | |
| 986 | 1002 | |
| 987 | try test__fixunstfti(0.5, 0); | |
| 988 | try test__fixunstfti(0.99, 0); | |
| 989 | try test__fixunstfti(1.0, 1); | |
| 990 | try test__fixunstfti(1.5, 1); | |
| 991 | try test__fixunstfti(1.99, 1); | |
| 992 | try test__fixunstfti(2.0, 2); | |
| 993 | try test__fixunstfti(2.01, 2); | |
| 994 | try test__fixunstfti(-0.01, 0); | |
| 995 | try test__fixunstfti(-0.99, 0); | |
| 1003 | try test_u128_intFromFloat_f128(0.5, 0); | |
| 1004 | try test_u128_intFromFloat_f128(0.99, 0); | |
| 1005 | try test_u128_intFromFloat_f128(1.0, 1); | |
| 1006 | try test_u128_intFromFloat_f128(1.5, 1); | |
| 1007 | try test_u128_intFromFloat_f128(1.99, 1); | |
| 1008 | try test_u128_intFromFloat_f128(2.0, 2); | |
| 1009 | try test_u128_intFromFloat_f128(2.01, 2); | |
| 1010 | try test_u128_intFromFloat_f128(-0.01, 0); | |
| 1011 | try test_u128_intFromFloat_f128(-0.99, 0); | |
| 996 | 1012 | |
| 997 | try test__fixunstfti(0x1p+128, 0xffffffffffffffffffffffffffffffff); | |
| 1013 | try test_u128_intFromFloat_f128(0x1p+128, 0xffffffffffffffffffffffffffffffff); | |
| 998 | 1014 | |
| 999 | try test__fixunstfti(0x1.FFFFFEp+126, 0x7fffff80000000000000000000000000); | |
| 1000 | try test__fixunstfti(0x1.FFFFFEp+127, 0xffffff00000000000000000000000000); | |
| 1001 | try test__fixunstfti(0x1.FFFFFEp+128, 0xffffffffffffffffffffffffffffffff); | |
| 1002 | try test__fixunstfti(0x1.FFFFFEp+129, 0xffffffffffffffffffffffffffffffff); | |
| 1015 | try test_u128_intFromFloat_f128(0x1.FFFFFEp+126, 0x7fffff80000000000000000000000000); | |
| 1016 | try test_u128_intFromFloat_f128(0x1.FFFFFEp+127, 0xffffff00000000000000000000000000); | |
| 1017 | try test_u128_intFromFloat_f128(0x1.FFFFFEp+128, 0xffffffffffffffffffffffffffffffff); | |
| 1018 | try test_u128_intFromFloat_f128(0x1.FFFFFEp+129, 0xffffffffffffffffffffffffffffffff); | |
| 1003 | 1019 | } |
| 1004 | 1020 | |
| 1005 | fn test__fixunshfti(a: f16, expected: u128) !void { | |
| 1006 | const x = __fixunshfti(a); | |
| 1021 | fn test_u128_intFromFloat_f16(a: f16, expected: u128) !void { | |
| 1022 | const x = impl.u128_intFromFloat_f16(a); | |
| 1007 | 1023 | try testing.expect(x == expected); |
| 1008 | 1024 | } |
| 1009 | 1025 | |
| 1010 | test "fixunshfti for f16" { | |
| 1011 | try test__fixunshfti(math.inf(f16), math.maxInt(u128)); | |
| 1012 | try test__fixunshfti(math.floatMax(f16), 65504); | |
| 1026 | test u128_intFromFloat_f16 { | |
| 1027 | try test_u128_intFromFloat_f16(math.inf(f16), math.maxInt(u128)); | |
| 1028 | try test_u128_intFromFloat_f16(math.floatMax(f16), 65504); | |
| 1013 | 1029 | } |
| 1014 | 1030 | |
| 1015 | fn test__fixunsxfti(a: f80, expected: u128) !void { | |
| 1016 | const x = __fixunsxfti(a); | |
| 1031 | fn test_u128_intFromFloat_f80(a: f80, expected: u128) !void { | |
| 1032 | const x = impl.u128_intFromFloat_f80(a); | |
| 1017 | 1033 | try testing.expect(x == expected); |
| 1018 | 1034 | } |
| 1019 | 1035 | |
| 1020 | test "fixunsxfti for f80" { | |
| 1021 | try test__fixunsxfti(math.inf(f80), math.maxInt(u128)); | |
| 1022 | try test__fixunsxfti(math.floatMax(f80), math.maxInt(u128)); | |
| 1023 | try test__fixunsxfti(math.maxInt(u64), math.maxInt(u64)); | |
| 1036 | test u128_intFromFloat_f80 { | |
| 1037 | try test_u128_intFromFloat_f80(math.inf(f80), math.maxInt(u128)); | |
| 1038 | try test_u128_intFromFloat_f80(math.floatMax(f80), math.maxInt(u128)); | |
| 1039 | try test_u128_intFromFloat_f80(math.maxInt(u64), math.maxInt(u64)); | |
| 1024 | 1040 | } |
lib/compiler_rt/limb64.zig+1-1| ... | ... | @@ -6,7 +6,7 @@ const minInt = std.math.minInt; |
| 6 | 6 | |
| 7 | 7 | const builtin = @import("builtin"); |
| 8 | 8 | const compiler_rt = @import("../compiler_rt.zig"); |
| 9 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 9 | const symbol = compiler_rt.symbol; | |
| 10 | 10 | |
| 11 | 11 | const endian = builtin.cpu.arch.endian(); |
| 12 | 12 |
lib/compiler_rt/log.zig+113-101| ... | ... | @@ -11,26 +11,29 @@ const expectEqual = std.testing.expectEqual; |
| 11 | 11 | const expectApproxEqRel = std.testing.expectApproxEqRel; |
| 12 | 12 | |
| 13 | 13 | const compiler_rt = @import("../compiler_rt.zig"); |
| 14 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 14 | const symbol = compiler_rt.symbol; | |
| 15 | 15 | |
| 16 | 16 | comptime { |
| 17 | 17 | symbol(&__logh, "__logh"); |
| 18 | 18 | symbol(&logf, "logf"); |
| 19 | 19 | symbol(&log, "log"); |
| 20 | 20 | symbol(&__logx, "__logx"); |
| 21 | if (compiler_rt.want_ppc_abi) { | |
| 22 | symbol(&logq, "logf128"); | |
| 23 | } | |
| 24 | symbol(&logq, "logq"); | |
| 21 | symbol(&logq, "logf128"); | |
| 25 | 22 | symbol(&logl, "logl"); |
| 26 | 23 | } |
| 27 | 24 | |
| 28 | pub fn __logh(a: f16) callconv(.c) f16 { | |
| 25 | fn __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 | } | |
| 28 | pub fn log_f16(a: f16) f16 { | |
| 29 | 29 | // TODO: more efficient implementation |
| 30 | return @floatCast(logf(a)); | |
| 30 | return @floatCast(log_f32(a)); | |
| 31 | 31 | } |
| 32 | 32 | |
| 33 | pub fn logf(x_: f32) callconv(.c) f32 { | |
| 33 | fn 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 | } | |
| 36 | pub fn log_f32(x_: f32) f32 { | |
| 34 | 37 | const ln2_hi: f32 = 6.9313812256e-01; |
| 35 | 38 | const ln2_lo: f32 = 9.0580006145e-06; |
| 36 | 39 | const Lg1: f32 = 0xaaaaaa.0p-24; |
| ... | ... | @@ -82,7 +85,10 @@ pub fn logf(x_: f32) callconv(.c) f32 { |
| 82 | 85 | return s * (hfsq + R) + dk * ln2_lo - hfsq + f + dk * ln2_hi; |
| 83 | 86 | } |
| 84 | 87 | |
| 85 | pub fn log(x: f64) callconv(.c) f64 { | |
| 88 | fn 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 | } | |
| 91 | pub fn log_f64(x: f64) f64 { | |
| 86 | 92 | const poly1 = [_]f64{ |
| 87 | 93 | -0x1p-1, |
| 88 | 94 | 0x1.5555555555577p-2, |
| ... | ... | @@ -432,11 +438,17 @@ pub fn log(x: f64) callconv(.c) f64 { |
| 432 | 438 | return @bitCast(y); |
| 433 | 439 | } |
| 434 | 440 | |
| 435 | pub fn __logx(a: f80) callconv(.c) f80 { | |
| 441 | fn __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 | } | |
| 444 | pub fn log_f80(a: f80) f80 { | |
| 436 | 445 | // TODO: more efficient implementation |
| 437 | return @floatCast(logq(a)); | |
| 446 | return @floatCast(log_f128(a)); | |
| 438 | 447 | } |
| 439 | 448 | |
| 449 | fn 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 | 452 | /// Implementation of "Table-driven implementation of the logarithm function in IEEE floating-point arithmetic" |
| 441 | 453 | /// 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 | 461 | /// |
| 450 | 462 | /// Accuracy on 10 million random numbers near x = 1 (testing the proc2 case): |
| 451 | 463 | /// <= 0.5 ulp: 99.96%, worst case <= 0.528 ulp |
| 452 | pub fn logq(x: f128) callconv(.c) f128 { | |
| 464 | pub fn log_f128(x: f128) f128 { | |
| 453 | 465 | const impl = @import("log_f128.zig"); |
| 454 | 466 | |
| 455 | 467 | if (impl.specialCases(x)) |y| |
| ... | ... | @@ -626,123 +638,123 @@ pub fn logq(x: f128) callconv(.c) f128 { |
| 626 | 638 | |
| 627 | 639 | pub fn logl(x: c_longdouble) callconv(.c) c_longdouble { |
| 628 | 640 | switch (@typeInfo(c_longdouble).float.bits) { |
| 629 | 64 => return log(x), | |
| 630 | 80 => return __logx(x), | |
| 631 | 128 => return logq(x), | |
| 632 | else => @compileError("unreachable"), | |
| 641 | 64 => return log_f64(x), | |
| 642 | 80 => return log_f80(x), | |
| 643 | 128 => return log_f128(x), | |
| 644 | else => comptime unreachable, | |
| 633 | 645 | } |
| 634 | 646 | } |
| 635 | 647 | |
| 636 | 648 | test "logf() special" { |
| 637 | try expectEqual(logf(0.0), -math.inf(f32)); | |
| 638 | try expectEqual(logf(-0.0), -math.inf(f32)); | |
| 639 | try expect(math.isPositiveZero(logf(1.0))); | |
| 640 | try expectEqual(logf(math.e), 1.0); | |
| 641 | try expectEqual(logf(math.inf(f32)), math.inf(f32)); | |
| 642 | try expect(math.isNan(logf(-1.0))); | |
| 643 | try expect(math.isNan(logf(-math.inf(f32)))); | |
| 644 | try expect(math.isNan(logf(math.nan(f32)))); | |
| 645 | try expect(math.isNan(logf(math.snan(f32)))); | |
| 649 | try expectEqual(log_f32(0.0), -math.inf(f32)); | |
| 650 | try expectEqual(log_f32(-0.0), -math.inf(f32)); | |
| 651 | try expect(math.isPositiveZero(log_f32(1.0))); | |
| 652 | try expectEqual(log_f32(math.e), 1.0); | |
| 653 | try expectEqual(log_f32(math.inf(f32)), math.inf(f32)); | |
| 654 | try expect(math.isNan(log_f32(-1.0))); | |
| 655 | try expect(math.isNan(log_f32(-math.inf(f32)))); | |
| 656 | try expect(math.isNan(log_f32(math.nan(f32)))); | |
| 657 | try expect(math.isNan(log_f32(math.snan(f32)))); | |
| 646 | 658 | } |
| 647 | 659 | |
| 648 | 660 | test "logf() sanity" { |
| 649 | try expect(math.isNan(logf(-0x1.0223a0p+3))); | |
| 650 | try expectEqual(logf(0x1.161868p+2), 0x1.7815b0p+0); | |
| 651 | try expect(math.isNan(logf(-0x1.0c34b4p+3))); | |
| 652 | try expect(math.isNan(logf(-0x1.a206f0p+2))); | |
| 653 | try expectEqual(logf(0x1.288bbcp+3), 0x1.1cfcd6p+1); | |
| 654 | try expectEqual(logf(0x1.52efd0p-1), -0x1.a6694cp-2); | |
| 655 | try expect(math.isNan(logf(-0x1.a05cc8p-2))); | |
| 656 | try expectEqual(logf(0x1.1f9efap-1), -0x1.2742bap-1); | |
| 657 | try expectEqual(logf(0x1.8c5db0p-1), -0x1.062160p-2); | |
| 658 | try expect(math.isNan(logf(-0x1.5b86eap-1))); | |
| 661 | try expect(math.isNan(log_f32(-0x1.0223a0p+3))); | |
| 662 | try expectEqual(log_f32(0x1.161868p+2), 0x1.7815b0p+0); | |
| 663 | try expect(math.isNan(log_f32(-0x1.0c34b4p+3))); | |
| 664 | try expect(math.isNan(log_f32(-0x1.a206f0p+2))); | |
| 665 | try expectEqual(log_f32(0x1.288bbcp+3), 0x1.1cfcd6p+1); | |
| 666 | try expectEqual(log_f32(0x1.52efd0p-1), -0x1.a6694cp-2); | |
| 667 | try expect(math.isNan(log_f32(-0x1.a05cc8p-2))); | |
| 668 | try expectEqual(log_f32(0x1.1f9efap-1), -0x1.2742bap-1); | |
| 669 | try expectEqual(log_f32(0x1.8c5db0p-1), -0x1.062160p-2); | |
| 670 | try expect(math.isNan(log_f32(-0x1.5b86eap-1))); | |
| 659 | 671 | } |
| 660 | 672 | |
| 661 | 673 | test "logf() boundary" { |
| 662 | try expectEqual(logf(0x1.fffffep+127), 0x1.62e430p+6); // Max input value | |
| 663 | try expectEqual(logf(0x1p-149), -0x1.9d1da0p+6); // Min positive input value | |
| 664 | try expect(math.isNan(logf(-0x1p-149))); // Min negative input value | |
| 665 | try expectEqual(logf(0x1.000002p+0), 0x1.fffffep-24); // Last value before result reaches +0 | |
| 666 | try expectEqual(logf(0x1.fffffep-1), -0x1p-24); // Last value before result reaches -0 | |
| 667 | try expectEqual(logf(0x1p-126), -0x1.5d58a0p+6); // First subnormal | |
| 668 | try expect(math.isNan(logf(-0x1p-126))); // First negative subnormal | |
| 674 | try expectEqual(log_f32(0x1.fffffep+127), 0x1.62e430p+6); // Max input value | |
| 675 | try expectEqual(log_f32(0x1p-149), -0x1.9d1da0p+6); // Min positive input value | |
| 676 | try expect(math.isNan(log_f32(-0x1p-149))); // Min negative input value | |
| 677 | try expectEqual(log_f32(0x1.000002p+0), 0x1.fffffep-24); // Last value before result reaches +0 | |
| 678 | try expectEqual(log_f32(0x1.fffffep-1), -0x1p-24); // Last value before result reaches -0 | |
| 679 | try expectEqual(log_f32(0x1p-126), -0x1.5d58a0p+6); // First subnormal | |
| 680 | try expect(math.isNan(log_f32(-0x1p-126))); // First negative subnormal | |
| 669 | 681 | } |
| 670 | 682 | |
| 671 | 683 | test "log() special" { |
| 672 | try expectEqual(log(0.0), -math.inf(f64)); | |
| 673 | try expectEqual(log(-0.0), -math.inf(f64)); | |
| 674 | try expect(math.isPositiveZero(log(1.0))); | |
| 675 | try expectEqual(log(math.e), 1.0); | |
| 676 | try expectEqual(log(math.inf(f64)), math.inf(f64)); | |
| 677 | try expect(math.isNan(log(-1.0))); | |
| 678 | try expect(math.isNan(log(-math.inf(f64)))); | |
| 679 | try expect(math.isNan(log(math.nan(f64)))); | |
| 680 | try expect(math.isNan(log(math.snan(f64)))); | |
| 684 | try expectEqual(log_f64(0.0), -math.inf(f64)); | |
| 685 | try expectEqual(log_f64(-0.0), -math.inf(f64)); | |
| 686 | try expect(math.isPositiveZero(log_f64(1.0))); | |
| 687 | try expectEqual(log_f64(math.e), 1.0); | |
| 688 | try expectEqual(log_f64(math.inf(f64)), math.inf(f64)); | |
| 689 | try expect(math.isNan(log_f64(-1.0))); | |
| 690 | try expect(math.isNan(log_f64(-math.inf(f64)))); | |
| 691 | try expect(math.isNan(log_f64(math.nan(f64)))); | |
| 692 | try expect(math.isNan(log_f64(math.snan(f64)))); | |
| 681 | 693 | } |
| 682 | 694 | |
| 683 | 695 | test "log() sanity" { |
| 684 | try expect(math.isNan(log(-0x1.02239f3c6a8f1p+3))); | |
| 685 | try expectEqual(log(0x1.161868e18bc67p+2), 0x1.7815b08f99c65p+0); | |
| 686 | try expect(math.isNan(log(-0x1.0c34b3e01e6e7p+3))); | |
| 687 | try expect(math.isNan(log(-0x1.a206f0a19dcc4p+2))); | |
| 688 | try expectEqual(log(0x1.288bbb0d6a1e6p+3), 0x1.1cfcd53d72604p+1); | |
| 689 | try expectEqual(log(0x1.52efd0cd80497p-1), -0x1.a6694a4a85621p-2); | |
| 690 | try expect(math.isNan(log(-0x1.a05cc754481d1p-2))); | |
| 691 | try expectEqual(log(0x1.1f9ef934745cbp-1), -0x1.2742bc03d02ddp-1); | |
| 692 | try expectEqual(log(0x1.8c5db097f7442p-1), -0x1.06215de4a3f92p-2); | |
| 693 | try expect(math.isNan(log(-0x1.5b86ea8118a0ep-1))); | |
| 696 | try expect(math.isNan(log_f64(-0x1.02239f3c6a8f1p+3))); | |
| 697 | try expectEqual(log_f64(0x1.161868e18bc67p+2), 0x1.7815b08f99c65p+0); | |
| 698 | try expect(math.isNan(log_f64(-0x1.0c34b3e01e6e7p+3))); | |
| 699 | try expect(math.isNan(log_f64(-0x1.a206f0a19dcc4p+2))); | |
| 700 | try expectEqual(log_f64(0x1.288bbb0d6a1e6p+3), 0x1.1cfcd53d72604p+1); | |
| 701 | try expectEqual(log_f64(0x1.52efd0cd80497p-1), -0x1.a6694a4a85621p-2); | |
| 702 | try expect(math.isNan(log_f64(-0x1.a05cc754481d1p-2))); | |
| 703 | try expectEqual(log_f64(0x1.1f9ef934745cbp-1), -0x1.2742bc03d02ddp-1); | |
| 704 | try expectEqual(log_f64(0x1.8c5db097f7442p-1), -0x1.06215de4a3f92p-2); | |
| 705 | try expect(math.isNan(log_f64(-0x1.5b86ea8118a0ep-1))); | |
| 694 | 706 | } |
| 695 | 707 | |
| 696 | 708 | test "log() boundary" { |
| 697 | try expectEqual(log(0x1.fffffffffffffp+1023), 0x1.62e42fefa39efp+9); // Max input value | |
| 698 | try expectEqual(log(0x1p-1074), -0x1.74385446d71c3p+9); // Min positive input value | |
| 699 | try expect(math.isNan(log(-0x1p-1074))); // Min negative input value | |
| 700 | try expectEqual(log(0x1.0000000000001p+0), 0x1.fffffffffffffp-53); // Last value before result reaches +0 | |
| 701 | try expectEqual(log(0x1.fffffffffffffp-1), -0x1p-53); // Last value before result reaches -0 | |
| 702 | try expectEqual(log(0x1p-1022), -0x1.6232bdd7abcd2p+9); // First subnormal | |
| 703 | try expect(math.isNan(log(-0x1p-1022))); // First negative subnormal | |
| 709 | try expectEqual(log_f64(0x1.fffffffffffffp+1023), 0x1.62e42fefa39efp+9); // Max input value | |
| 710 | try expectEqual(log_f64(0x1p-1074), -0x1.74385446d71c3p+9); // Min positive input value | |
| 711 | try expect(math.isNan(log_f64(-0x1p-1074))); // Min negative input value | |
| 712 | try expectEqual(log_f64(0x1.0000000000001p+0), 0x1.fffffffffffffp-53); // Last value before result reaches +0 | |
| 713 | try expectEqual(log_f64(0x1.fffffffffffffp-1), -0x1p-53); // Last value before result reaches -0 | |
| 714 | try expectEqual(log_f64(0x1p-1022), -0x1.6232bdd7abcd2p+9); // First subnormal | |
| 715 | try expect(math.isNan(log_f64(-0x1p-1022))); // First negative subnormal | |
| 704 | 716 | } |
| 705 | 717 | |
| 706 | 718 | test "logq() special" { |
| 707 | try expectEqual(logq(0.0), -math.inf(f128)); | |
| 708 | try expectEqual(logq(-0.0), -math.inf(f128)); | |
| 709 | try expect(math.isPositiveZero(logq(1.0))); | |
| 719 | try expectEqual(log_f128(0.0), -math.inf(f128)); | |
| 720 | try expectEqual(log_f128(-0.0), -math.inf(f128)); | |
| 721 | try expect(math.isPositiveZero(log_f128(1.0))); | |
| 710 | 722 | // Sadly, the rounding gods decided that 0.9999999999999999999999999999999999 |
| 711 | // is the correctly rounded value of logq(math.e) | |
| 712 | try expectApproxEqRel(logq(math.e), 1.0, math.floatEpsAt(f128, 1.0)); | |
| 713 | try expectEqual(logq(math.inf(f128)), math.inf(f128)); | |
| 714 | try expect(math.isNan(logq(-1.0))); | |
| 715 | try expect(math.isNan(logq(-math.inf(f128)))); | |
| 716 | try expect(math.isNan(logq(math.nan(f128)))); | |
| 717 | try expect(math.isNan(logq(math.snan(f128)))); | |
| 723 | // is the correctly rounded value of log_f128(math.e) | |
| 724 | try expectApproxEqRel(log_f128(math.e), 1.0, math.floatEpsAt(f128, 1.0)); | |
| 725 | try expectEqual(log_f128(math.inf(f128)), math.inf(f128)); | |
| 726 | try expect(math.isNan(log_f128(-1.0))); | |
| 727 | try expect(math.isNan(log_f128(-math.inf(f128)))); | |
| 728 | try expect(math.isNan(log_f128(math.nan(f128)))); | |
| 729 | try expect(math.isNan(log_f128(math.snan(f128)))); | |
| 718 | 730 | } |
| 719 | 731 | |
| 720 | 732 | test "logq() boundary" { |
| 721 | try expectEqual(logq(0x1.ffffffffffffffffffffffffffffp16383), 0x1.62e42fefa39ef35793c7673007e6p13); // Max input value | |
| 722 | try expectEqual(logq(0x1p-16494), -0x1.6546282207802c89d24d65e96274p13); // Min positive input value | |
| 723 | try expect(math.isNan(logq(-0x1p-16494))); // Min negative input value | |
| 724 | try expectEqual(logq(0x1.0000000000000000000000000001p0), 0x1.ffffffffffffffffffffffffffffp-113); // Last value before result reaches +0 | |
| 725 | try expectEqual(logq(0x1.ffffffffffffffffffffffffffffp-1), -0x1p-113); // Last value before result reaches -0 | |
| 726 | try expectEqual(logq(0x1p-16382), -0x1.62d918ce2421d65ff90ac8f4ce66p13); // First subnormal | |
| 727 | try expect(math.isNan(logq(-0x1p-16382))); // First negative subnormal | |
| 733 | try expectEqual(log_f128(0x1.ffffffffffffffffffffffffffffp16383), 0x1.62e42fefa39ef35793c7673007e6p13); // Max input value | |
| 734 | try expectEqual(log_f128(0x1p-16494), -0x1.6546282207802c89d24d65e96274p13); // Min positive input value | |
| 735 | try expect(math.isNan(log_f128(-0x1p-16494))); // Min negative input value | |
| 736 | try expectEqual(log_f128(0x1.0000000000000000000000000001p0), 0x1.ffffffffffffffffffffffffffffp-113); // Last value before result reaches +0 | |
| 737 | try expectEqual(log_f128(0x1.ffffffffffffffffffffffffffffp-1), -0x1p-113); // Last value before result reaches -0 | |
| 738 | try expectEqual(log_f128(0x1p-16382), -0x1.62d918ce2421d65ff90ac8f4ce66p13); // First subnormal | |
| 739 | try expect(math.isNan(log_f128(-0x1p-16382))); // First negative subnormal | |
| 728 | 740 | } |
| 729 | 741 | |
| 730 | 742 | test "logq() sanity" { |
| 731 | try expectEqual(logq(4.151135979023751199079583784623537e-4), -7.7869583453055243113993340258295346e0); | |
| 732 | try expectEqual(logq(9.614234245933828353176667689130293e-14), -2.9972946567656004014786271559909435e1); | |
| 733 | try expectEqual(logq(1.012889803704721484375e13), 2.9946413646144315985379677542014356e1); | |
| 734 | try expectEqual(logq(2.397741857206453154086912e24), 5.613656963346284538829358703465392e1); | |
| 735 | try expectEqual(logq(3.442377567808290806386655232e27), 6.3405959896920645453203836625419693e1); | |
| 736 | try expectEqual(logq(1.0689155158234028407981544637594257e-8), -1.835403614606774451014272772421113e1); | |
| 737 | try expectEqual(logq(1.4813913545768791536741499811327596e-10), -2.263286917934202003739900705050399e1); | |
| 738 | try expectEqual(logq(4.518948965781299591064453125e10), 2.453413036705097282892685629562292e1); | |
| 739 | try expectEqual(logq(1.200355637363589375e14), 3.2418809179272977400408325788186897e1); | |
| 740 | try expectEqual(logq(6.6145398293682003021240234375e9), 2.261253606737223221601998075023261e1); | |
| 741 | try expectEqual(logq(5.16179116383965741056e20), 4.7692985503915646405875629300054525e1); | |
| 743 | try expectEqual(log_f128(4.151135979023751199079583784623537e-4), -7.7869583453055243113993340258295346e0); | |
| 744 | try expectEqual(log_f128(9.614234245933828353176667689130293e-14), -2.9972946567656004014786271559909435e1); | |
| 745 | try expectEqual(log_f128(1.012889803704721484375e13), 2.9946413646144315985379677542014356e1); | |
| 746 | try expectEqual(log_f128(2.397741857206453154086912e24), 5.613656963346284538829358703465392e1); | |
| 747 | try expectEqual(log_f128(3.442377567808290806386655232e27), 6.3405959896920645453203836625419693e1); | |
| 748 | try expectEqual(log_f128(1.0689155158234028407981544637594257e-8), -1.835403614606774451014272772421113e1); | |
| 749 | try expectEqual(log_f128(1.4813913545768791536741499811327596e-10), -2.263286917934202003739900705050399e1); | |
| 750 | try expectEqual(log_f128(4.518948965781299591064453125e10), 2.453413036705097282892685629562292e1); | |
| 751 | try expectEqual(log_f128(1.200355637363589375e14), 3.2418809179272977400408325788186897e1); | |
| 752 | try expectEqual(log_f128(6.6145398293682003021240234375e9), 2.261253606737223221601998075023261e1); | |
| 753 | try expectEqual(log_f128(5.16179116383965741056e20), 4.7692985503915646405875629300054525e1); | |
| 742 | 754 | // testing near 1 |
| 743 | try expectEqual(logq(1.026586845186097528392910049888087e0), 2.6239557099466251374193777672800004e-2); | |
| 744 | try expectEqual(logq(9.878220373715243107115568932385941e-1), -1.2252721576456821219120474521538944e-2); | |
| 745 | try expectEqual(logq(9.417921077517196685541245315675951e-1), -5.997072116986790367958922503195352e-2); | |
| 746 | try expectEqual(logq(1.043095786320424537962914257605007e0), 4.219300911769055080390811808602425e-2); | |
| 747 | try expectEqual(logq(1.019043049323190694932517175175235e0), 1.8863999985309781522599012445793722e-2); | |
| 755 | try expectEqual(log_f128(1.026586845186097528392910049888087e0), 2.6239557099466251374193777672800004e-2); | |
| 756 | try expectEqual(log_f128(9.878220373715243107115568932385941e-1), -1.2252721576456821219120474521538944e-2); | |
| 757 | try expectEqual(log_f128(9.417921077517196685541245315675951e-1), -5.997072116986790367958922503195352e-2); | |
| 758 | try expectEqual(log_f128(1.043095786320424537962914257605007e0), 4.219300911769055080390811808602425e-2); | |
| 759 | try expectEqual(log_f128(1.019043049323190694932517175175235e0), 1.8863999985309781522599012445793722e-2); | |
| 748 | 760 | } |
lib/compiler_rt/log10.zig+114-102| ... | ... | @@ -18,19 +18,22 @@ comptime { |
| 18 | 18 | symbol(&log10f, "log10f"); |
| 19 | 19 | symbol(&log10, "log10"); |
| 20 | 20 | symbol(&__log10x, "__log10x"); |
| 21 | if (compiler_rt.want_ppc_abi) { | |
| 22 | symbol(&log10q, "log10f128"); | |
| 23 | } | |
| 24 | symbol(&log10q, "log10q"); | |
| 21 | symbol(&log10q, "log10f128"); | |
| 25 | 22 | symbol(&log10l, "log10l"); |
| 26 | 23 | } |
| 27 | 24 | |
| 28 | pub fn __log10h(a: f16) callconv(.c) f16 { | |
| 25 | fn __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 | } | |
| 28 | pub fn log10_f16(a: f16) f16 { | |
| 29 | 29 | // TODO: more efficient implementation |
| 30 | return @floatCast(log10f(a)); | |
| 30 | return @floatCast(log10_f32(a)); | |
| 31 | 31 | } |
| 32 | 32 | |
| 33 | pub fn log10f(x_: f32) callconv(.c) f32 { | |
| 33 | fn 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 | } | |
| 36 | pub fn log10_f32(x_: f32) f32 { | |
| 34 | 37 | const ivln10hi: f32 = 4.3432617188e-01; |
| 35 | 38 | const ivln10lo: f32 = -3.1689971365e-05; |
| 36 | 39 | const log10_2hi: f32 = 3.0102920532e-01; |
| ... | ... | @@ -90,7 +93,10 @@ pub fn log10f(x_: f32) callconv(.c) f32 { |
| 90 | 93 | return dk * log10_2lo + (lo + hi) * ivln10lo + lo * ivln10hi + hi * ivln10hi + dk * log10_2hi; |
| 91 | 94 | } |
| 92 | 95 | |
| 93 | pub fn log10(x_: f64) callconv(.c) f64 { | |
| 96 | fn 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 | } | |
| 99 | pub fn log10_f64(x_: f64) f64 { | |
| 94 | 100 | const ivln10hi: f64 = 4.34294481878168880939e-01; |
| 95 | 101 | const ivln10lo: f64 = 2.50829467116452752298e-11; |
| 96 | 102 | const log10_2hi: f64 = 3.01029995663611771306e-01; |
| ... | ... | @@ -165,11 +171,17 @@ pub fn log10(x_: f64) callconv(.c) f64 { |
| 165 | 171 | return val_lo + val_hi; |
| 166 | 172 | } |
| 167 | 173 | |
| 168 | pub fn __log10x(a: f80) callconv(.c) f80 { | |
| 174 | fn __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 | } | |
| 177 | pub fn log10_f80(a: f80) f80 { | |
| 169 | 178 | // TODO: more efficient implementation |
| 170 | return @floatCast(log10q(a)); | |
| 179 | return @floatCast(log10_f128(a)); | |
| 171 | 180 | } |
| 172 | 181 | |
| 182 | fn 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 | 185 | /// Implementation of "Table-driven implementation of the logarithm function in IEEE floating-point arithmetic" |
| 174 | 186 | /// 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 | 194 | /// |
| 183 | 195 | /// Accuracy on 10 million random numbers near x = 1 (testing the proc2 case): |
| 184 | 196 | /// <= 0.5 ulp: 99.96%, worst case <= 0.565 ulp |
| 185 | pub fn log10q(x: f128) callconv(.c) f128 { | |
| 197 | pub fn log10_f128(x: f128) f128 { | |
| 186 | 198 | const impl = @import("log_f128.zig"); |
| 187 | 199 | |
| 188 | 200 | if (impl.specialCases(x)) |y| |
| ... | ... | @@ -359,124 +371,124 @@ pub fn log10q(x: f128) callconv(.c) f128 { |
| 359 | 371 | |
| 360 | 372 | pub fn log10l(x: c_longdouble) callconv(.c) c_longdouble { |
| 361 | 373 | switch (@typeInfo(c_longdouble).float.bits) { |
| 362 | 64 => return log10(x), | |
| 363 | 80 => return __log10x(x), | |
| 364 | 128 => return log10q(x), | |
| 365 | else => @compileError("unreachable"), | |
| 374 | 64 => return log10_f64(x), | |
| 375 | 80 => return log10_f80(x), | |
| 376 | 128 => return log10_f128(x), | |
| 377 | else => comptime unreachable, | |
| 366 | 378 | } |
| 367 | 379 | } |
| 368 | 380 | |
| 369 | 381 | test "log10f() special" { |
| 370 | try expectEqual(log10f(0.0), -math.inf(f32)); | |
| 371 | try expectEqual(log10f(-0.0), -math.inf(f32)); | |
| 372 | try expect(math.isPositiveZero(log10f(1.0))); | |
| 373 | try expectEqual(log10f(10.0), 1.0); | |
| 374 | try expectEqual(log10f(0.1), -1.0); | |
| 375 | try expectEqual(log10f(math.inf(f32)), math.inf(f32)); | |
| 376 | try expect(math.isNan(log10f(-1.0))); | |
| 377 | try expect(math.isNan(log10f(-math.inf(f32)))); | |
| 378 | try expect(math.isNan(log10f(math.nan(f32)))); | |
| 379 | try expect(math.isNan(log10f(math.snan(f32)))); | |
| 382 | try expectEqual(log10_f32(0.0), -math.inf(f32)); | |
| 383 | try expectEqual(log10_f32(-0.0), -math.inf(f32)); | |
| 384 | try expect(math.isPositiveZero(log10_f32(1.0))); | |
| 385 | try expectEqual(log10_f32(10.0), 1.0); | |
| 386 | try expectEqual(log10_f32(0.1), -1.0); | |
| 387 | try expectEqual(log10_f32(math.inf(f32)), math.inf(f32)); | |
| 388 | try expect(math.isNan(log10_f32(-1.0))); | |
| 389 | try expect(math.isNan(log10_f32(-math.inf(f32)))); | |
| 390 | try expect(math.isNan(log10_f32(math.nan(f32)))); | |
| 391 | try expect(math.isNan(log10_f32(math.snan(f32)))); | |
| 380 | 392 | } |
| 381 | 393 | |
| 382 | 394 | test "log10f() sanity" { |
| 383 | try expect(math.isNan(log10f(-0x1.0223a0p+3))); | |
| 384 | try expectEqual(log10f(0x1.161868p+2), 0x1.46a9bcp-1); | |
| 385 | try expect(math.isNan(log10f(-0x1.0c34b4p+3))); | |
| 386 | try expect(math.isNan(log10f(-0x1.a206f0p+2))); | |
| 387 | try expectEqual(log10f(0x1.288bbcp+3), 0x1.ef1300p-1); | |
| 388 | try expectEqual(log10f(0x1.52efd0p-1), -0x1.6ee6dcp-3); // Disagrees with GCC in last bit | |
| 389 | try expect(math.isNan(log10f(-0x1.a05cc8p-2))); | |
| 390 | try expectEqual(log10f(0x1.1f9efap-1), -0x1.0075ccp-2); | |
| 391 | try expectEqual(log10f(0x1.8c5db0p-1), -0x1.c75df8p-4); | |
| 392 | try expect(math.isNan(log10f(-0x1.5b86eap-1))); | |
| 395 | try expect(math.isNan(log10_f32(-0x1.0223a0p+3))); | |
| 396 | try expectEqual(log10_f32(0x1.161868p+2), 0x1.46a9bcp-1); | |
| 397 | try expect(math.isNan(log10_f32(-0x1.0c34b4p+3))); | |
| 398 | try expect(math.isNan(log10_f32(-0x1.a206f0p+2))); | |
| 399 | try expectEqual(log10_f32(0x1.288bbcp+3), 0x1.ef1300p-1); | |
| 400 | try expectEqual(log10_f32(0x1.52efd0p-1), -0x1.6ee6dcp-3); // Disagrees with GCC in last bit | |
| 401 | try expect(math.isNan(log10_f32(-0x1.a05cc8p-2))); | |
| 402 | try expectEqual(log10_f32(0x1.1f9efap-1), -0x1.0075ccp-2); | |
| 403 | try expectEqual(log10_f32(0x1.8c5db0p-1), -0x1.c75df8p-4); | |
| 404 | try expect(math.isNan(log10_f32(-0x1.5b86eap-1))); | |
| 393 | 405 | } |
| 394 | 406 | |
| 395 | 407 | test "log10f() boundary" { |
| 396 | try expectEqual(log10f(0x1.fffffep+127), 0x1.344136p+5); // Max input value | |
| 397 | try expectEqual(log10f(0x1p-149), -0x1.66d3e8p+5); // Min positive input value | |
| 398 | try expect(math.isNan(log10f(-0x1p-149))); // Min negative input value | |
| 399 | try expectEqual(log10f(0x1.000002p+0), 0x1.bcb7b0p-25); // Last value before result reaches +0 | |
| 400 | try expectEqual(log10f(0x1.fffffep-1), -0x1.bcb7b2p-26); // Last value before result reaches -0 | |
| 401 | try expectEqual(log10f(0x1p-126), -0x1.2f7030p+5); // First subnormal | |
| 402 | try expect(math.isNan(log10f(-0x1p-126))); // First negative subnormal | |
| 408 | try expectEqual(log10_f32(0x1.fffffep+127), 0x1.344136p+5); // Max input value | |
| 409 | try expectEqual(log10_f32(0x1p-149), -0x1.66d3e8p+5); // Min positive input value | |
| 410 | try expect(math.isNan(log10_f32(-0x1p-149))); // Min negative input value | |
| 411 | try expectEqual(log10_f32(0x1.000002p+0), 0x1.bcb7b0p-25); // Last value before result reaches +0 | |
| 412 | try expectEqual(log10_f32(0x1.fffffep-1), -0x1.bcb7b2p-26); // Last value before result reaches -0 | |
| 413 | try expectEqual(log10_f32(0x1p-126), -0x1.2f7030p+5); // First subnormal | |
| 414 | try expect(math.isNan(log10_f32(-0x1p-126))); // First negative subnormal | |
| 403 | 415 | } |
| 404 | 416 | |
| 405 | 417 | test "log10() special" { |
| 406 | try expectEqual(log10(0.0), -math.inf(f64)); | |
| 407 | try expectEqual(log10(-0.0), -math.inf(f64)); | |
| 408 | try expect(math.isPositiveZero(log10(1.0))); | |
| 409 | try expectEqual(log10(10.0), 1.0); | |
| 410 | try expectEqual(log10(0.1), -1.0); | |
| 411 | try expectEqual(log10(math.inf(f64)), math.inf(f64)); | |
| 412 | try expect(math.isNan(log10(-1.0))); | |
| 413 | try expect(math.isNan(log10(-math.inf(f64)))); | |
| 414 | try expect(math.isNan(log10(math.nan(f64)))); | |
| 415 | try expect(math.isNan(log10(math.snan(f64)))); | |
| 418 | try expectEqual(log10_f64(0.0), -math.inf(f64)); | |
| 419 | try expectEqual(log10_f64(-0.0), -math.inf(f64)); | |
| 420 | try expect(math.isPositiveZero(log10_f64(1.0))); | |
| 421 | try expectEqual(log10_f64(10.0), 1.0); | |
| 422 | try expectEqual(log10_f64(0.1), -1.0); | |
| 423 | try expectEqual(log10_f64(math.inf(f64)), math.inf(f64)); | |
| 424 | try expect(math.isNan(log10_f64(-1.0))); | |
| 425 | try expect(math.isNan(log10_f64(-math.inf(f64)))); | |
| 426 | try expect(math.isNan(log10_f64(math.nan(f64)))); | |
| 427 | try expect(math.isNan(log10_f64(math.snan(f64)))); | |
| 416 | 428 | } |
| 417 | 429 | |
| 418 | 430 | test "log10() sanity" { |
| 419 | try expect(math.isNan(log10(-0x1.02239f3c6a8f1p+3))); | |
| 420 | try expectEqual(log10(0x1.161868e18bc67p+2), 0x1.46a9bd1d2eb87p-1); | |
| 421 | try expect(math.isNan(log10(-0x1.0c34b3e01e6e7p+3))); | |
| 422 | try expect(math.isNan(log10(-0x1.a206f0a19dcc4p+2))); | |
| 423 | try expectEqual(log10(0x1.288bbb0d6a1e6p+3), 0x1.ef12fff994862p-1); | |
| 424 | try expectEqual(log10(0x1.52efd0cd80497p-1), -0x1.6ee6db5a155cbp-3); | |
| 425 | try expect(math.isNan(log10(-0x1.a05cc754481d1p-2))); | |
| 426 | try expectEqual(log10(0x1.1f9ef934745cbp-1), -0x1.0075cda79d321p-2); | |
| 427 | try expectEqual(log10(0x1.8c5db097f7442p-1), -0x1.c75df6442465ap-4); | |
| 428 | try expect(math.isNan(log10(-0x1.5b86ea8118a0ep-1))); | |
| 431 | try expect(math.isNan(log10_f64(-0x1.02239f3c6a8f1p+3))); | |
| 432 | try expectEqual(log10_f64(0x1.161868e18bc67p+2), 0x1.46a9bd1d2eb87p-1); | |
| 433 | try expect(math.isNan(log10_f64(-0x1.0c34b3e01e6e7p+3))); | |
| 434 | try expect(math.isNan(log10_f64(-0x1.a206f0a19dcc4p+2))); | |
| 435 | try expectEqual(log10_f64(0x1.288bbb0d6a1e6p+3), 0x1.ef12fff994862p-1); | |
| 436 | try expectEqual(log10_f64(0x1.52efd0cd80497p-1), -0x1.6ee6db5a155cbp-3); | |
| 437 | try expect(math.isNan(log10_f64(-0x1.a05cc754481d1p-2))); | |
| 438 | try expectEqual(log10_f64(0x1.1f9ef934745cbp-1), -0x1.0075cda79d321p-2); | |
| 439 | try expectEqual(log10_f64(0x1.8c5db097f7442p-1), -0x1.c75df6442465ap-4); | |
| 440 | try expect(math.isNan(log10_f64(-0x1.5b86ea8118a0ep-1))); | |
| 429 | 441 | } |
| 430 | 442 | |
| 431 | 443 | test "log10() boundary" { |
| 432 | try expectEqual(log10(0x1.fffffffffffffp+1023), 0x1.34413509f79ffp+8); // Max input value | |
| 433 | try expectEqual(log10(0x1p-1074), -0x1.434e6420f4374p+8); // Min positive input value | |
| 434 | try expect(math.isNan(log10(-0x1p-1074))); // Min negative input value | |
| 435 | try expectEqual(log10(0x1.0000000000001p+0), 0x1.bcb7b1526e50dp-54); // Last value before result reaches +0 | |
| 436 | try expectEqual(log10(0x1.fffffffffffffp-1), -0x1.bcb7b1526e50fp-55); // Last value before result reaches -0 | |
| 437 | try expectEqual(log10(0x1p-1022), -0x1.33a7146f72a42p+8); // First subnormal | |
| 438 | try expect(math.isNan(log10(-0x1p-1022))); // First negative subnormal | |
| 444 | try expectEqual(log10_f64(0x1.fffffffffffffp+1023), 0x1.34413509f79ffp+8); // Max input value | |
| 445 | try expectEqual(log10_f64(0x1p-1074), -0x1.434e6420f4374p+8); // Min positive input value | |
| 446 | try expect(math.isNan(log10_f64(-0x1p-1074))); // Min negative input value | |
| 447 | try expectEqual(log10_f64(0x1.0000000000001p+0), 0x1.bcb7b1526e50dp-54); // Last value before result reaches +0 | |
| 448 | try expectEqual(log10_f64(0x1.fffffffffffffp-1), -0x1.bcb7b1526e50fp-55); // Last value before result reaches -0 | |
| 449 | try expectEqual(log10_f64(0x1p-1022), -0x1.33a7146f72a42p+8); // First subnormal | |
| 450 | try expect(math.isNan(log10_f64(-0x1p-1022))); // First negative subnormal | |
| 439 | 451 | } |
| 440 | 452 | |
| 441 | 453 | test "log10q() special" { |
| 442 | try expectEqual(log10q(0.0), -math.inf(f128)); | |
| 443 | try expectEqual(log10q(-0.0), -math.inf(f128)); | |
| 444 | try expect(math.isPositiveZero(log10q(1.0))); | |
| 445 | try expectEqual(log10q(10.0), 1.0); | |
| 446 | try expectEqual(log10q(0.1), -1.0); | |
| 447 | try expectEqual(log10q(math.inf(f128)), math.inf(f128)); | |
| 448 | try expect(math.isNan(log10q(-1.0))); | |
| 449 | try expect(math.isNan(log10q(-math.inf(f128)))); | |
| 450 | try expect(math.isNan(log10q(math.nan(f128)))); | |
| 451 | try expect(math.isNan(log10q(math.snan(f128)))); | |
| 454 | try expectEqual(log10_f128(0.0), -math.inf(f128)); | |
| 455 | try expectEqual(log10_f128(-0.0), -math.inf(f128)); | |
| 456 | try expect(math.isPositiveZero(log10_f128(1.0))); | |
| 457 | try expectEqual(log10_f128(10.0), 1.0); | |
| 458 | try expectEqual(log10_f128(0.1), -1.0); | |
| 459 | try expectEqual(log10_f128(math.inf(f128)), math.inf(f128)); | |
| 460 | try expect(math.isNan(log10_f128(-1.0))); | |
| 461 | try expect(math.isNan(log10_f128(-math.inf(f128)))); | |
| 462 | try expect(math.isNan(log10_f128(math.nan(f128)))); | |
| 463 | try expect(math.isNan(log10_f128(math.snan(f128)))); | |
| 452 | 464 | } |
| 453 | 465 | |
| 454 | 466 | test "log10q() sanity" { |
| 455 | try expectEqual(log10q(2.1744503117482705706605762784484114e1949), 1.949337349488073972035715318447419e3); | |
| 456 | try expectEqual(log10q(2.3695331993665660983204066767386505e2150), 2.1503746627979481420243846411400265e3); | |
| 457 | try expectEqual(log10q(1.8071775728314983136779370752110857e612), 6.122570008283284411311428111991705e2); | |
| 458 | try expectEqual(log10q(2.612170297226630737309271722008693e-2629), -2.628582998513179919647069989114319e3); | |
| 459 | try expectEqual(log10q(8.485091636263895897993044621224502e-3748), -3.7470713434630800881474518447042895e3); | |
| 460 | try expectEqual(log10q(4.3668077579803801413736022136116655e-4051), -4.0503598359268068567757367259544416e3); | |
| 461 | try expectEqual(log10q(2.9321353260885285826237030859036923e4830), 4.830467184010313310864606285356782e3); | |
| 462 | try expectEqual(log10q(6.6119754254652455408442826553161645e-1417), -1.416179668769227128601620567685071e3); | |
| 463 | try expectEqual(log10q(5.2459104673488555418645321788108695e4178), 4.178719820874155944446586083585479e3); | |
| 464 | try expectEqual(log10q(7.809812890804996586377267218360886e-418), -4.1710735937091966815220294599598215e2); | |
| 467 | try expectEqual(log10_f128(2.1744503117482705706605762784484114e1949), 1.949337349488073972035715318447419e3); | |
| 468 | try expectEqual(log10_f128(2.3695331993665660983204066767386505e2150), 2.1503746627979481420243846411400265e3); | |
| 469 | try expectEqual(log10_f128(1.8071775728314983136779370752110857e612), 6.122570008283284411311428111991705e2); | |
| 470 | try expectEqual(log10_f128(2.612170297226630737309271722008693e-2629), -2.628582998513179919647069989114319e3); | |
| 471 | try expectEqual(log10_f128(8.485091636263895897993044621224502e-3748), -3.7470713434630800881474518447042895e3); | |
| 472 | try expectEqual(log10_f128(4.3668077579803801413736022136116655e-4051), -4.0503598359268068567757367259544416e3); | |
| 473 | try expectEqual(log10_f128(2.9321353260885285826237030859036923e4830), 4.830467184010313310864606285356782e3); | |
| 474 | try expectEqual(log10_f128(6.6119754254652455408442826553161645e-1417), -1.416179668769227128601620567685071e3); | |
| 475 | try expectEqual(log10_f128(5.2459104673488555418645321788108695e4178), 4.178719820874155944446586083585479e3); | |
| 476 | try expectEqual(log10_f128(7.809812890804996586377267218360886e-418), -4.1710735937091966815220294599598215e2); | |
| 465 | 477 | // testing near 1 |
| 466 | try expectEqual(log10q(1.0291437165967803055610652052109798e0), 1.2476026819466393459130418401605807e-2); | |
| 467 | try expectEqual(log10q(1.043095786320424537962914257605007e0), 1.8324191034706598279642145362763252e-2); | |
| 468 | try expectEqual(log10q(9.900264873754467234601150948947179e-1), -4.3531860417287584780652055666513634e-3); | |
| 469 | try expectEqual(log10q(1.038295346547007736348611217636062e0), 1.6320907588397540309035279023485962e-2); | |
| 470 | try expectEqual(log10q(9.821701941230028324703038578036285e-1), -7.813249520562034832371814409278784e-3); | |
| 471 | try expectEqual(log10q(9.593555263530179895381522214847791e-1), -1.8020418356217558657107271163588764e-2); | |
| 478 | try expectEqual(log10_f128(1.0291437165967803055610652052109798e0), 1.2476026819466393459130418401605807e-2); | |
| 479 | try expectEqual(log10_f128(1.043095786320424537962914257605007e0), 1.8324191034706598279642145362763252e-2); | |
| 480 | try expectEqual(log10_f128(9.900264873754467234601150948947179e-1), -4.3531860417287584780652055666513634e-3); | |
| 481 | try expectEqual(log10_f128(1.038295346547007736348611217636062e0), 1.6320907588397540309035279023485962e-2); | |
| 482 | try expectEqual(log10_f128(9.821701941230028324703038578036285e-1), -7.813249520562034832371814409278784e-3); | |
| 483 | try expectEqual(log10_f128(9.593555263530179895381522214847791e-1), -1.8020418356217558657107271163588764e-2); | |
| 472 | 484 | } |
| 473 | 485 | |
| 474 | 486 | test "log10q() boundary" { |
| 475 | try expectEqual(log10q(0x1.ffffffffffffffffffffffffffffp16383), 0x1.34413509f79fef311f12b35816f9p12); // Max input value | |
| 476 | try expectEqual(log10q(0x1p-16494), -0x1.3653051d20c18a143b801b7c5661p12); // Min positive input value | |
| 477 | try expect(math.isNan(log10q(-0x1p-16494))); // Min negative input value | |
| 478 | try expectEqual(log10q(0x1.0000000000000000000000000001p0), 0x1.bcb7b1526e50e32a6ab7555f5a67p-114); // Last value before result reaches +0 | |
| 479 | try expectEqual(log10q(0x1.ffffffffffffffffffffffffffffp-1), -0x1.bcb7b1526e50e32a6ab7555f5a68p-115); // Last value before result reaches -0 | |
| 480 | try expectEqual(log10q(0x1p-16382), -0x1.343793004f503231a589bac27c38p12); // First subnormal | |
| 481 | try expect(math.isNan(log10q(-0x1p-16382))); // First negative subnormal | |
| 487 | try expectEqual(log10_f128(0x1.ffffffffffffffffffffffffffffp16383), 0x1.34413509f79fef311f12b35816f9p12); // Max input value | |
| 488 | try expectEqual(log10_f128(0x1p-16494), -0x1.3653051d20c18a143b801b7c5661p12); // Min positive input value | |
| 489 | try expect(math.isNan(log10_f128(-0x1p-16494))); // Min negative input value | |
| 490 | try expectEqual(log10_f128(0x1.0000000000000000000000000001p0), 0x1.bcb7b1526e50e32a6ab7555f5a67p-114); // Last value before result reaches +0 | |
| 491 | try expectEqual(log10_f128(0x1.ffffffffffffffffffffffffffffp-1), -0x1.bcb7b1526e50e32a6ab7555f5a68p-115); // Last value before result reaches -0 | |
| 492 | try expectEqual(log10_f128(0x1p-16382), -0x1.343793004f503231a589bac27c38p12); // First subnormal | |
| 493 | try expect(math.isNan(log10_f128(-0x1p-16382))); // First negative subnormal | |
| 482 | 494 | } |
lib/compiler_rt/log2.zig+106-94| ... | ... | @@ -19,19 +19,22 @@ comptime { |
| 19 | 19 | symbol(&log2f, "log2f"); |
| 20 | 20 | symbol(&log2, "log2"); |
| 21 | 21 | symbol(&__log2x, "__log2x"); |
| 22 | if (compiler_rt.want_ppc_abi) { | |
| 23 | symbol(&log2q, "log2f128"); | |
| 24 | } | |
| 25 | symbol(&log2q, "log2q"); | |
| 22 | symbol(&log2q, "log2f128"); | |
| 26 | 23 | symbol(&log2l, "log2l"); |
| 27 | 24 | } |
| 28 | 25 | |
| 29 | pub fn __log2h(a: f16) callconv(.c) f16 { | |
| 26 | fn __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 | } | |
| 29 | pub fn log2_f16(a: f16) f16 { | |
| 30 | 30 | // TODO: more efficient implementation |
| 31 | return @floatCast(log2f(a)); | |
| 31 | return @floatCast(log2_f32(a)); | |
| 32 | 32 | } |
| 33 | 33 | |
| 34 | pub fn log2f(x_: f32) callconv(.c) f32 { | |
| 34 | fn 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 | } | |
| 37 | pub fn log2_f32(x_: f32) f32 { | |
| 35 | 38 | const ivln2hi: f32 = 1.4428710938e+00; |
| 36 | 39 | const ivln2lo: f32 = -1.7605285393e-04; |
| 37 | 40 | const Lg1: f32 = 0xaaaaaa.0p-24; |
| ... | ... | @@ -87,7 +90,10 @@ pub fn log2f(x_: f32) callconv(.c) f32 { |
| 87 | 90 | return (lo + hi) * ivln2lo + lo * ivln2hi + hi * ivln2hi + @as(f32, @floatFromInt(k)); |
| 88 | 91 | } |
| 89 | 92 | |
| 90 | pub fn log2(x_: f64) callconv(.c) f64 { | |
| 93 | fn 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 | } | |
| 96 | pub fn log2_f64(x_: f64) f64 { | |
| 91 | 97 | const ivln2hi: f64 = 1.44269504072144627571e+00; |
| 92 | 98 | const ivln2lo: f64 = 1.67517131648865118353e-10; |
| 93 | 99 | const Lg1: f64 = 6.666666666666735130e-01; |
| ... | ... | @@ -158,11 +164,17 @@ pub fn log2(x_: f64) callconv(.c) f64 { |
| 158 | 164 | return val_lo + val_hi; |
| 159 | 165 | } |
| 160 | 166 | |
| 161 | pub fn __log2x(a: f80) callconv(.c) f80 { | |
| 167 | fn __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 | } | |
| 170 | pub fn log2_f80(a: f80) f80 { | |
| 162 | 171 | // TODO: more efficient implementation |
| 163 | return @floatCast(log2q(a)); | |
| 172 | return @floatCast(log2_f128(a)); | |
| 164 | 173 | } |
| 165 | 174 | |
| 175 | fn 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 | 178 | /// Implementation of "Table-driven implementation of the logarithm function in IEEE floating-point arithmetic" |
| 167 | 179 | /// 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 | 187 | /// |
| 176 | 188 | /// Accuracy on 10 million random numbers near x = 1 (testing the proc2 case): |
| 177 | 189 | /// <= 0.5 ulp: 99.86%, worst case <= 0.546 ulp |
| 178 | pub fn log2q(x: f128) callconv(.c) f128 { | |
| 190 | pub fn log2_f128(x: f128) f128 { | |
| 179 | 191 | const impl = @import("log_f128.zig"); |
| 180 | 192 | |
| 181 | 193 | if (impl.specialCases(x)) |y| |
| ... | ... | @@ -351,117 +363,117 @@ pub fn log2q(x: f128) callconv(.c) f128 { |
| 351 | 363 | |
| 352 | 364 | pub fn log2l(x: c_longdouble) callconv(.c) c_longdouble { |
| 353 | 365 | switch (@typeInfo(c_longdouble).float.bits) { |
| 354 | 64 => return log2(x), | |
| 355 | 80 => return __log2x(x), | |
| 356 | 128 => return log2q(x), | |
| 357 | else => @compileError("unreachable"), | |
| 366 | 64 => return log2_f64(x), | |
| 367 | 80 => return log2_f80(x), | |
| 368 | 128 => return log2_f128(x), | |
| 369 | else => comptime unreachable, | |
| 358 | 370 | } |
| 359 | 371 | } |
| 360 | 372 | |
| 361 | 373 | test "log2f() special" { |
| 362 | try expectEqual(log2f(0.0), -math.inf(f32)); | |
| 363 | try expectEqual(log2f(-0.0), -math.inf(f32)); | |
| 364 | try expect(math.isPositiveZero(log2f(1.0))); | |
| 365 | try expectEqual(log2f(2.0), 1.0); | |
| 366 | try expectEqual(log2f(math.inf(f32)), math.inf(f32)); | |
| 367 | try expect(math.isNan(log2f(-1.0))); | |
| 368 | try expect(math.isNan(log2f(-math.inf(f32)))); | |
| 369 | try expect(math.isNan(log2f(math.nan(f32)))); | |
| 370 | try expect(math.isNan(log2f(math.snan(f32)))); | |
| 374 | try expectEqual(log2_f32(0.0), -math.inf(f32)); | |
| 375 | try expectEqual(log2_f32(-0.0), -math.inf(f32)); | |
| 376 | try expect(math.isPositiveZero(log2_f32(1.0))); | |
| 377 | try expectEqual(log2_f32(2.0), 1.0); | |
| 378 | try expectEqual(log2_f32(math.inf(f32)), math.inf(f32)); | |
| 379 | try expect(math.isNan(log2_f32(-1.0))); | |
| 380 | try expect(math.isNan(log2_f32(-math.inf(f32)))); | |
| 381 | try expect(math.isNan(log2_f32(math.nan(f32)))); | |
| 382 | try expect(math.isNan(log2_f32(math.snan(f32)))); | |
| 371 | 383 | } |
| 372 | 384 | |
| 373 | 385 | test "log2f() sanity" { |
| 374 | try expect(math.isNan(log2f(-0x1.0223a0p+3))); | |
| 375 | try expectEqual(log2f(0x1.161868p+2), 0x1.0f49acp+1); | |
| 376 | try expect(math.isNan(log2f(-0x1.0c34b4p+3))); | |
| 377 | try expect(math.isNan(log2f(-0x1.a206f0p+2))); | |
| 378 | try expectEqual(log2f(0x1.288bbcp+3), 0x1.9b2676p+1); | |
| 379 | try expectEqual(log2f(0x1.52efd0p-1), -0x1.30b494p-1); // Disagrees with GCC in last bit | |
| 380 | try expect(math.isNan(log2f(-0x1.a05cc8p-2))); | |
| 381 | try expectEqual(log2f(0x1.1f9efap-1), -0x1.a9f89ap-1); | |
| 382 | try expectEqual(log2f(0x1.8c5db0p-1), -0x1.7a2c96p-2); | |
| 383 | try expect(math.isNan(log2f(-0x1.5b86eap-1))); | |
| 386 | try expect(math.isNan(log2_f32(-0x1.0223a0p+3))); | |
| 387 | try expectEqual(log2_f32(0x1.161868p+2), 0x1.0f49acp+1); | |
| 388 | try expect(math.isNan(log2_f32(-0x1.0c34b4p+3))); | |
| 389 | try expect(math.isNan(log2_f32(-0x1.a206f0p+2))); | |
| 390 | try expectEqual(log2_f32(0x1.288bbcp+3), 0x1.9b2676p+1); | |
| 391 | try expectEqual(log2_f32(0x1.52efd0p-1), -0x1.30b494p-1); // Disagrees with GCC in last bit | |
| 392 | try expect(math.isNan(log2_f32(-0x1.a05cc8p-2))); | |
| 393 | try expectEqual(log2_f32(0x1.1f9efap-1), -0x1.a9f89ap-1); | |
| 394 | try expectEqual(log2_f32(0x1.8c5db0p-1), -0x1.7a2c96p-2); | |
| 395 | try expect(math.isNan(log2_f32(-0x1.5b86eap-1))); | |
| 384 | 396 | } |
| 385 | 397 | |
| 386 | 398 | test "log2f() boundary" { |
| 387 | try expectEqual(log2f(0x1.fffffep+127), 0x1p+7); // Max input value | |
| 388 | try expectEqual(log2f(0x1p-149), -0x1.2ap+7); // Min positive input value | |
| 389 | try expect(math.isNan(log2f(-0x1p-149))); // Min negative input value | |
| 390 | try expectEqual(log2f(0x1.000002p+0), 0x1.715474p-23); // Last value before result reaches +0 | |
| 391 | try expectEqual(log2f(0x1.fffffep-1), -0x1.715478p-24); // Last value before result reaches -0 | |
| 392 | try expectEqual(log2f(0x1p-126), -0x1.f8p+6); // First subnormal | |
| 393 | try expect(math.isNan(log2f(-0x1p-126))); // First negative subnormal | |
| 399 | try expectEqual(log2_f32(0x1.fffffep+127), 0x1p+7); // Max input value | |
| 400 | try expectEqual(log2_f32(0x1p-149), -0x1.2ap+7); // Min positive input value | |
| 401 | try expect(math.isNan(log2_f32(-0x1p-149))); // Min negative input value | |
| 402 | try expectEqual(log2_f32(0x1.000002p+0), 0x1.715474p-23); // Last value before result reaches +0 | |
| 403 | try expectEqual(log2_f32(0x1.fffffep-1), -0x1.715478p-24); // Last value before result reaches -0 | |
| 404 | try expectEqual(log2_f32(0x1p-126), -0x1.f8p+6); // First subnormal | |
| 405 | try expect(math.isNan(log2_f32(-0x1p-126))); // First negative subnormal | |
| 394 | 406 | |
| 395 | 407 | } |
| 396 | 408 | |
| 397 | 409 | test "log2() special" { |
| 398 | try expectEqual(log2(0.0), -math.inf(f64)); | |
| 399 | try expectEqual(log2(-0.0), -math.inf(f64)); | |
| 400 | try expect(math.isPositiveZero(log2(1.0))); | |
| 401 | try expectEqual(log2(2.0), 1.0); | |
| 402 | try expectEqual(log2(math.inf(f64)), math.inf(f64)); | |
| 403 | try expect(math.isNan(log2(-1.0))); | |
| 404 | try expect(math.isNan(log2(-math.inf(f64)))); | |
| 405 | try expect(math.isNan(log2(math.nan(f64)))); | |
| 406 | try expect(math.isNan(log2(math.snan(f64)))); | |
| 410 | try expectEqual(log2_f64(0.0), -math.inf(f64)); | |
| 411 | try expectEqual(log2_f64(-0.0), -math.inf(f64)); | |
| 412 | try expect(math.isPositiveZero(log2_f64(1.0))); | |
| 413 | try expectEqual(log2_f64(2.0), 1.0); | |
| 414 | try expectEqual(log2_f64(math.inf(f64)), math.inf(f64)); | |
| 415 | try expect(math.isNan(log2_f64(-1.0))); | |
| 416 | try expect(math.isNan(log2_f64(-math.inf(f64)))); | |
| 417 | try expect(math.isNan(log2_f64(math.nan(f64)))); | |
| 418 | try expect(math.isNan(log2_f64(math.snan(f64)))); | |
| 407 | 419 | } |
| 408 | 420 | |
| 409 | 421 | test "log2() sanity" { |
| 410 | try expect(math.isNan(log2(-0x1.02239f3c6a8f1p+3))); | |
| 411 | try expectEqual(log2(0x1.161868e18bc67p+2), 0x1.0f49ac3838580p+1); | |
| 412 | try expect(math.isNan(log2(-0x1.0c34b3e01e6e7p+3))); | |
| 413 | try expect(math.isNan(log2(-0x1.a206f0a19dcc4p+2))); | |
| 414 | try expectEqual(log2(0x1.288bbb0d6a1e6p+3), 0x1.9b26760c2a57ep+1); | |
| 415 | try expectEqual(log2(0x1.52efd0cd80497p-1), -0x1.30b490ef684c7p-1); | |
| 416 | try expect(math.isNan(log2(-0x1.a05cc754481d1p-2))); | |
| 417 | try expectEqual(log2(0x1.1f9ef934745cbp-1), -0x1.a9f89b5f5acb8p-1); | |
| 418 | try expectEqual(log2(0x1.8c5db097f7442p-1), -0x1.7a2c947173f06p-2); | |
| 419 | try expect(math.isNan(log2(-0x1.5b86ea8118a0ep-1))); | |
| 422 | try expect(math.isNan(log2_f64(-0x1.02239f3c6a8f1p+3))); | |
| 423 | try expectEqual(log2_f64(0x1.161868e18bc67p+2), 0x1.0f49ac3838580p+1); | |
| 424 | try expect(math.isNan(log2_f64(-0x1.0c34b3e01e6e7p+3))); | |
| 425 | try expect(math.isNan(log2_f64(-0x1.a206f0a19dcc4p+2))); | |
| 426 | try expectEqual(log2_f64(0x1.288bbb0d6a1e6p+3), 0x1.9b26760c2a57ep+1); | |
| 427 | try expectEqual(log2_f64(0x1.52efd0cd80497p-1), -0x1.30b490ef684c7p-1); | |
| 428 | try expect(math.isNan(log2_f64(-0x1.a05cc754481d1p-2))); | |
| 429 | try expectEqual(log2_f64(0x1.1f9ef934745cbp-1), -0x1.a9f89b5f5acb8p-1); | |
| 430 | try expectEqual(log2_f64(0x1.8c5db097f7442p-1), -0x1.7a2c947173f06p-2); | |
| 431 | try expect(math.isNan(log2_f64(-0x1.5b86ea8118a0ep-1))); | |
| 420 | 432 | } |
| 421 | 433 | |
| 422 | 434 | test "log2() boundary" { |
| 423 | try expectEqual(log2(0x1.fffffffffffffp+1023), 0x1p+10); // Max input value | |
| 424 | try expectEqual(log2(0x1p-1074), -0x1.0c8p+10); // Min positive input value | |
| 425 | try expect(math.isNan(log2(-0x1p-1074))); // Min negative input value | |
| 426 | try expectEqual(log2(0x1.0000000000001p+0), 0x1.71547652b82fdp-52); // Last value before result reaches +0 | |
| 427 | try expectEqual(log2(0x1.fffffffffffffp-1), -0x1.71547652b82fep-53); // Last value before result reaches -0 | |
| 428 | try expectEqual(log2(0x1p-1022), -0x1.ffp+9); // First subnormal | |
| 429 | try expect(math.isNan(log2(-0x1p-1022))); // First negative subnormal | |
| 435 | try expectEqual(log2_f64(0x1.fffffffffffffp+1023), 0x1p+10); // Max input value | |
| 436 | try expectEqual(log2_f64(0x1p-1074), -0x1.0c8p+10); // Min positive input value | |
| 437 | try expect(math.isNan(log2_f64(-0x1p-1074))); // Min negative input value | |
| 438 | try expectEqual(log2_f64(0x1.0000000000001p+0), 0x1.71547652b82fdp-52); // Last value before result reaches +0 | |
| 439 | try expectEqual(log2_f64(0x1.fffffffffffffp-1), -0x1.71547652b82fep-53); // Last value before result reaches -0 | |
| 440 | try expectEqual(log2_f64(0x1p-1022), -0x1.ffp+9); // First subnormal | |
| 441 | try expect(math.isNan(log2_f64(-0x1p-1022))); // First negative subnormal | |
| 430 | 442 | } |
| 431 | 443 | |
| 432 | 444 | test "log2q() special" { |
| 433 | try expectEqual(log2q(0.0), -math.inf(f128)); | |
| 434 | try expectEqual(log2q(-0.0), -math.inf(f128)); | |
| 435 | try expect(math.isPositiveZero(log2q(1.0))); | |
| 436 | try expectEqual(log2q(2.0), 1.0); | |
| 437 | try expectEqual(log2q(math.inf(f128)), math.inf(f128)); | |
| 438 | try expect(math.isNan(log2q(-1.0))); | |
| 439 | try expect(math.isNan(log2q(-math.inf(f128)))); | |
| 440 | try expect(math.isNan(log2q(math.nan(f128)))); | |
| 441 | try expect(math.isNan(log2q(math.snan(f128)))); | |
| 445 | try expectEqual(log2_f128(0.0), -math.inf(f128)); | |
| 446 | try expectEqual(log2_f128(-0.0), -math.inf(f128)); | |
| 447 | try expect(math.isPositiveZero(log2_f128(1.0))); | |
| 448 | try expectEqual(log2_f128(2.0), 1.0); | |
| 449 | try expectEqual(log2_f128(math.inf(f128)), math.inf(f128)); | |
| 450 | try expect(math.isNan(log2_f128(-1.0))); | |
| 451 | try expect(math.isNan(log2_f128(-math.inf(f128)))); | |
| 452 | try expect(math.isNan(log2_f128(math.nan(f128)))); | |
| 453 | try expect(math.isNan(log2_f128(math.snan(f128)))); | |
| 442 | 454 | } |
| 443 | 455 | |
| 444 | 456 | test "log2q() boundary" { |
| 445 | try expectEqual(log2q(0x1.ffffffffffffffffffffffffffffp16383), 0x1p14); // Max input value | |
| 446 | try expectEqual(log2q(0x1p-16494), -0x1.01b8p14); // Min positive input value | |
| 447 | try expect(math.isNan(log2q(-0x1p-16494))); // Min negative input value | |
| 448 | try expectEqual(log2q(0x1.0000000000000000000000000001p0), 0x1.71547652b82fe1777d0ffda0d23ap-112); // Last value before result reaches +0 | |
| 449 | try expectEqual(log2q(0x1.ffffffffffffffffffffffffffffp-1), -0x1.71547652b82fe1777d0ffda0d23bp-113); // Last value before result reaches -0 | |
| 450 | try expectEqual(log2q(0x1p-16382), -0x1.fffp13); // First subnormal | |
| 451 | try expect(math.isNan(log2q(-0x1p-16382))); // First negative subnormal | |
| 457 | try expectEqual(log2_f128(0x1.ffffffffffffffffffffffffffffp16383), 0x1p14); // Max input value | |
| 458 | try expectEqual(log2_f128(0x1p-16494), -0x1.01b8p14); // Min positive input value | |
| 459 | try expect(math.isNan(log2_f128(-0x1p-16494))); // Min negative input value | |
| 460 | try expectEqual(log2_f128(0x1.0000000000000000000000000001p0), 0x1.71547652b82fe1777d0ffda0d23ap-112); // Last value before result reaches +0 | |
| 461 | try expectEqual(log2_f128(0x1.ffffffffffffffffffffffffffffp-1), -0x1.71547652b82fe1777d0ffda0d23bp-113); // Last value before result reaches -0 | |
| 462 | try expectEqual(log2_f128(0x1p-16382), -0x1.fffp13); // First subnormal | |
| 463 | try expect(math.isNan(log2_f128(-0x1p-16382))); // First negative subnormal | |
| 452 | 464 | } |
| 453 | 465 | |
| 454 | 466 | test "log2q() sanity" { |
| 455 | try expectEqual(log2q(8.0965013884643408203125e11), 3.955850767769801288865582596068254e1); | |
| 456 | try expectEqual(log2q(8.346531942223744e15), 5.28900982928636641107356163006646e1); | |
| 457 | try expectEqual(log2q(9.707809913413123613777865431464565e-20), -6.315941603809020445822192336703809e1); | |
| 458 | try expectEqual(log2q(1.9179565888043380306021427656243352e-24), -7.878670421065570557450089031998522e1); | |
| 459 | try expectEqual(log2q(2.5260048200126556877075044745936796e-25), -8.17113449801679676275805009400338e1); | |
| 460 | try expectEqual(log2q(3.1170134002568967640399932861328125e7), 2.489366102143423848582774267206741e1); | |
| 467 | try expectEqual(log2_f128(8.0965013884643408203125e11), 3.955850767769801288865582596068254e1); | |
| 468 | try expectEqual(log2_f128(8.346531942223744e15), 5.28900982928636641107356163006646e1); | |
| 469 | try expectEqual(log2_f128(9.707809913413123613777865431464565e-20), -6.315941603809020445822192336703809e1); | |
| 470 | try expectEqual(log2_f128(1.9179565888043380306021427656243352e-24), -7.878670421065570557450089031998522e1); | |
| 471 | try expectEqual(log2_f128(2.5260048200126556877075044745936796e-25), -8.17113449801679676275805009400338e1); | |
| 472 | try expectEqual(log2_f128(3.1170134002568967640399932861328125e7), 2.489366102143423848582774267206741e1); | |
| 461 | 473 | // test near 1 |
| 462 | try expectEqual(log2q(1.026586845186097528392910049888087e0), 3.7855678902522753591699367969189364e-2); | |
| 463 | try expectEqual(log2q(1.0005582850578053877743656130405725e0), 8.052103367568488432896147152682078e-4); | |
| 464 | try expectEqual(log2q(1.0370174103591254835765589348284266e0), 5.244011558596899945639244281954306e-2); | |
| 465 | try expectEqual(log2q(1.0429996503525671713075162472250667e0), 6.073867421942172944687194557176633e-2); | |
| 466 | try expectEqual(log2q(1.0383384027961064621892184334228659e0), 5.4276706191956281784022630732940314e-2); | |
| 474 | try expectEqual(log2_f128(1.026586845186097528392910049888087e0), 3.7855678902522753591699367969189364e-2); | |
| 475 | try expectEqual(log2_f128(1.0005582850578053877743656130405725e0), 8.052103367568488432896147152682078e-4); | |
| 476 | try expectEqual(log2_f128(1.0370174103591254835765589348284266e0), 5.244011558596899945639244281954306e-2); | |
| 477 | try expectEqual(log2_f128(1.0429996503525671713075162472250667e0), 6.073867421942172944687194557176633e-2); | |
| 478 | try expectEqual(log2_f128(1.0383384027961064621892184334228659e0), 5.4276706191956281784022630732940314e-2); | |
| 467 | 479 | } |
lib/compiler_rt/memcpy.zig+1-1| ... | ... | @@ -11,7 +11,7 @@ comptime { |
| 11 | 11 | .visibility = compiler_rt.visibility, |
| 12 | 12 | }; |
| 13 | 13 | |
| 14 | if (builtin.mode == .ReleaseSmall or builtin.zig_backend == .stage2_aarch64) | |
| 14 | if (builtin.mode == .small or builtin.zig_backend == .stage2_aarch64) | |
| 15 | 15 | @export(&memcpySmall, export_options) |
| 16 | 16 | else |
| 17 | 17 | @export(&memcpyFast, export_options); |
lib/compiler_rt/memmove.zig+1-1| ... | ... | @@ -14,7 +14,7 @@ comptime { |
| 14 | 14 | .visibility = compiler_rt.visibility, |
| 15 | 15 | }; |
| 16 | 16 | |
| 17 | if (builtin.mode == .ReleaseSmall or builtin.zig_backend == .stage2_aarch64) | |
| 17 | if (builtin.mode == .small or builtin.zig_backend == .stage2_aarch64) | |
| 18 | 18 | @export(&memmoveSmall, export_options) |
| 19 | 19 | else |
| 20 | 20 | @export(&memmoveFast, export_options); |
lib/compiler_rt/mulc3.zig+75-10| ... | ... | @@ -3,19 +3,80 @@ const isNan = std.math.isNan; |
| 3 | 3 | const isInf = std.math.isInf; |
| 4 | 4 | const copysign = std.math.copysign; |
| 5 | 5 | |
| 6 | pub fn Complex(comptime T: type) type { | |
| 7 | return extern struct { | |
| 8 | real: T, | |
| 9 | imag: T, | |
| 10 | }; | |
| 6 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 7 | const symbol = compiler_rt.symbol; | |
| 8 | const Complex = compiler_rt.Complex; | |
| 9 | ||
| 10 | comptime { | |
| 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 | ||
| 24 | fn __mulhc3(lhs_real: compiler_rt.f16.Abi, lhs_imag: compiler_rt.f16.Abi, rhs_real: compiler_rt.f16.Abi, rhs_imag: compiler_rt.f16.Abi) callconv(.c) compiler_rt.f16.complex.Abi { | |
| 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 | } | |
| 30 | pub fn mul_cf16(a: Complex(f16), b: Complex(f16)) Complex(f16) { | |
| 31 | return mulc3(f16, a, b); | |
| 32 | } | |
| 33 | ||
| 34 | fn __mulsc3(lhs_real: compiler_rt.f32.Abi, lhs_imag: compiler_rt.f32.Abi, rhs_real: compiler_rt.f32.Abi, rhs_imag: compiler_rt.f32.Abi) callconv(.c) compiler_rt.f32.complex.Abi { | |
| 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 | } | |
| 40 | pub fn mul_cf32(a: Complex(f32), b: Complex(f32)) Complex(f32) { | |
| 41 | return mulc3(f32, a, b); | |
| 42 | } | |
| 43 | ||
| 44 | fn __muldc3(lhs_real: compiler_rt.f64.Abi, lhs_imag: compiler_rt.f64.Abi, rhs_real: compiler_rt.f64.Abi, rhs_imag: compiler_rt.f64.Abi) callconv(.c) compiler_rt.f64.complex.Abi { | |
| 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 | } | |
| 50 | pub fn mul_cf64(a: Complex(f64), b: Complex(f64)) Complex(f64) { | |
| 51 | return mulc3(f64, a, b); | |
| 52 | } | |
| 53 | ||
| 54 | fn __mulxc3(lhs_real: compiler_rt.f80.Abi, lhs_imag: compiler_rt.f80.Abi, rhs_real: compiler_rt.f80.Abi, rhs_imag: compiler_rt.f80.Abi) callconv(.c) compiler_rt.f80.complex.Abi { | |
| 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 | } | |
| 60 | pub fn mul_cf80(a: Complex(f80), b: Complex(f80)) Complex(f80) { | |
| 61 | return mulc3(f80, a, b); | |
| 62 | } | |
| 63 | ||
| 64 | fn __multc3(lhs_real: compiler_rt.f128.Abi, lhs_imag: compiler_rt.f128.Abi, rhs_real: compiler_rt.f128.Abi, rhs_imag: compiler_rt.f128.Abi) callconv(.c) compiler_rt.f128.complex.Abi { | |
| 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 | } | |
| 70 | pub fn mul_cf128(a: Complex(f128), b: Complex(f128)) Complex(f128) { | |
| 71 | return mulc3(f128, a, b); | |
| 11 | 72 | } |
| 12 | 73 | |
| 13 | 74 | /// Implementation based on Annex G of C17 Standard (N2176) |
| 14 | pub inline fn mulc3(comptime T: type, a_in: T, b_in: T, c_in: T, d_in: T) Complex(T) { | |
| 15 | var a = a_in; | |
| 16 | var b = b_in; | |
| 17 | var c = c_in; | |
| 18 | var d = d_in; | |
| 75 | inline fn mulc3(comptime T: type, lhs: Complex(T), rhs: Complex(T)) Complex(T) { | |
| 76 | var a = lhs.real; | |
| 77 | var b = lhs.imag; | |
| 78 | var c = rhs.real; | |
| 79 | var d = rhs.imag; | |
| 19 | 80 | |
| 20 | 81 | const ac = a * c; |
| 21 | 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 | 138 | } |
| 78 | 139 | return z; |
| 79 | 140 | } |
| 141 | ||
| 142 | test { | |
| 143 | _ = @import("mulc3_test.zig"); | |
| 144 | } |
lib/compiler_rt/mulc3_test.zig+23-42| ... | ... | @@ -2,64 +2,45 @@ const std = @import("std"); |
| 2 | 2 | const math = std.math; |
| 3 | 3 | const expect = std.testing.expect; |
| 4 | 4 | |
| 5 | const Complex = @import("./mulc3.zig").Complex; | |
| 6 | const __mulhc3 = @import("./mulhc3.zig").__mulhc3; | |
| 7 | const __mulsc3 = @import("./mulsc3.zig").__mulsc3; | |
| 8 | const __muldc3 = @import("./muldc3.zig").__muldc3; | |
| 9 | const __mulxc3 = @import("./mulxc3.zig").__mulxc3; | |
| 10 | const __multc3 = @import("./multc3.zig").__multc3; | |
| 5 | const Complex = @import("../compiler_rt.zig").Complex; | |
| 6 | const impl = @import("mulc3.zig"); | |
| 7 | const mul_cf16 = impl.mul_cf16; | |
| 8 | const mul_cf32 = impl.mul_cf32; | |
| 9 | const mul_cf64 = impl.mul_cf64; | |
| 10 | const mul_cf80 = impl.mul_cf80; | |
| 11 | const mul_cf128 = impl.mul_cf128; | |
| 11 | 12 | |
| 12 | 13 | test "mulc3" { |
| 13 | try testMul(f16, __mulhc3); | |
| 14 | try testMul(f32, __mulsc3); | |
| 15 | try testMul(f64, __muldc3); | |
| 16 | try testMul(f80, __mulxc3); | |
| 17 | try testMul(f128, __multc3); | |
| 14 | try testMul(f16, mul_cf16); | |
| 15 | try testMul(f32, mul_cf32); | |
| 16 | try testMul(f64, mul_cf64); | |
| 17 | try testMul(f80, mul_cf80); | |
| 18 | try testMul(f128, mul_cf128); | |
| 18 | 19 | } |
| 19 | 20 | |
| 20 | fn testMul(comptime T: type, comptime f: fn (T, T, T, T) callconv(.c) Complex(T)) !void { | |
| 21 | fn testMul(comptime T: type, comptime f: fn (Complex(T), Complex(T)) Complex(T)) !void { | |
| 21 | 22 | { |
| 22 | const a: T = 1.0; | |
| 23 | const b: T = 0.0; | |
| 24 | const c: T = -1.0; | |
| 25 | const d: T = 0.0; | |
| 26 | ||
| 27 | const result = f(a, b, c, d); | |
| 23 | const result = f(.{ .real = 1.0, .imag = 0.0 }, .{ .real = -1.0, .imag = 0.0 }); | |
| 28 | 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; | |
| 33 | const b: T = 0.0; | |
| 34 | const c: T = -4.0; | |
| 35 | const d: T = 0.0; | |
| 36 | ||
| 37 | const result = f(a, b, c, d); | |
| 28 | const result = f(.{ .real = 1.0, .imag = 0.0 }, .{ .real = -4.0, .imag = 0.0 }); | |
| 38 | 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 | 33 | // if one operand is an infinity and the other operand is a nonzero finite number or an infinity, |
| 43 | 34 | // then the result of the * operator is an infinity; |
| 44 | const a: T = math.inf(T); | |
| 45 | const b: T = -math.inf(T); | |
| 46 | const c: T = 1.0; | |
| 47 | const d: T = 0.0; | |
| 48 | ||
| 49 | const result = f(a, b, c, d); | |
| 50 | try expect(result.real == math.inf(T)); | |
| 51 | try expect(result.imag == -math.inf(T)); | |
| 35 | const result = f(.{ .real = math.inf(T), .imag = -math.inf(T) }, .{ .real = 1.0, .imag = 0.0 }); | |
| 36 | try expect(math.isPositiveInf(result.real)); | |
| 37 | try expect(math.isNegativeInf(result.imag)); | |
| 52 | 38 | } |
| 53 | 39 | { |
| 54 | 40 | // if one operand is an infinity and the other operand is a nonzero finite number or an infinity, |
| 55 | 41 | // then the result of the * operator is an infinity; |
| 56 | const a: T = math.inf(T); | |
| 57 | const b: T = -1.0; | |
| 58 | const c: T = 1.0; | |
| 59 | const d: T = math.inf(T); | |
| 60 | ||
| 61 | const result = f(a, b, c, d); | |
| 62 | try expect(result.real == math.inf(T)); | |
| 63 | try expect(result.imag == math.inf(T)); | |
| 42 | const result = f(.{ .real = math.inf(T), .imag = -1.0 }, .{ .real = 1.0, .imag = math.inf(T) }); | |
| 43 | try expect(math.isPositiveInf(result.real)); | |
| 44 | try expect(math.isPositiveInf(result.imag)); | |
| 64 | 45 | } |
| 65 | 46 | } |
lib/compiler_rt/muldc3.zig deleted-12| ... | ... | @@ -1,12 +0,0 @@ |
| 1 | const mulc3 = @import("./mulc3.zig"); | |
| 2 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 3 | ||
| 4 | comptime { | |
| 5 | if (@import("builtin").zig_backend != .stage2_c) { | |
| 6 | symbol(&__muldc3, "__muldc3"); | |
| 7 | } | |
| 8 | } | |
| 9 | ||
| 10 | pub 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 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 3 | const mulf3 = @import("./mulf3.zig").mulf3; | |
| 4 | ||
| 5 | comptime { | |
| 6 | if (compiler_rt.want_aeabi) { | |
| 7 | symbol(&__aeabi_dmul, "__aeabi_dmul"); | |
| 8 | } else { | |
| 9 | symbol(&__muldf3, "__muldf3"); | |
| 10 | } | |
| 11 | } | |
| 12 | ||
| 13 | pub fn __muldf3(a: f64, b: f64) callconv(.c) f64 { | |
| 14 | return mulf3(f64, a, b); | |
| 15 | } | |
| 16 | ||
| 17 | fn __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 | 2 | const math = std.math; |
| 3 | 3 | const builtin = @import("builtin"); |
| 4 | 4 | const compiler_rt = @import("../compiler_rt.zig"); |
| 5 | const symbol = compiler_rt.symbol; | |
| 6 | ||
| 7 | comptime { | |
| 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 | ||
| 28 | fn __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 | } | |
| 31 | pub fn mul_f16(a: f16, b: f16) f16 { | |
| 32 | return mulf3(f16, a, b); | |
| 33 | } | |
| 34 | ||
| 35 | fn __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 | } | |
| 38 | fn __aeabi_fmul(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) f32 { | |
| 39 | return mul_f32(a, b); | |
| 40 | } | |
| 41 | pub fn mul_f32(a: f32, b: f32) f32 { | |
| 42 | return mulf3(f32, a, b); | |
| 43 | } | |
| 44 | ||
| 45 | fn __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 | } | |
| 48 | fn __aeabi_dmul(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) f64 { | |
| 49 | return mul_f64(a, b); | |
| 50 | } | |
| 51 | pub fn mul_f64(a: f64, b: f64) f64 { | |
| 52 | return mulf3(f64, a, b); | |
| 53 | } | |
| 54 | ||
| 55 | fn __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 | } | |
| 58 | pub fn mul_f80(a: f80, b: f80) f80 { | |
| 59 | return mulf3(f80, a, b); | |
| 60 | } | |
| 61 | ||
| 62 | fn __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 | } | |
| 65 | fn _Qp_mul(c: *f128, a: *const f128, b: *const f128) callconv(.c) void { | |
| 66 | c.* = mul_f128(a.*, b.*); | |
| 67 | } | |
| 68 | pub fn mul_f128(a: f128, b: f128) f128 { | |
| 69 | return mulf3(f128, a, b); | |
| 70 | } | |
| 5 | 71 | |
| 6 | 72 | /// Ported from: |
| 7 | 73 | /// https://github.com/llvm/llvm-project/blob/2ffb1b0413efa9a24eb3c49e710e36f92e2cb50b/compiler-rt/lib/builtins/fp_mul_impl.inc |
| 8 | pub inline fn mulf3(comptime T: type, a: T, b: T) T { | |
| 74 | inline fn mulf3(comptime T: type, a: T, b: T) T { | |
| 9 | 75 | @setRuntimeSafety(compiler_rt.test_safety); |
| 10 | 76 | const typeWidth = @typeInfo(T).float.bits; |
| 11 | 77 | const significandBits = math.floatMantissaBits(T); |
lib/compiler_rt/mulf3_test.zig+48-46| ... | ... | @@ -7,10 +7,12 @@ const math = std.math; |
| 7 | 7 | const qnan128: f128 = @bitCast(@as(u128, 0x7fff800000000000) << 64); |
| 8 | 8 | const inf128: f128 = @bitCast(@as(u128, 0x7fff000000000000) << 64); |
| 9 | 9 | |
| 10 | const __multf3 = @import("multf3.zig").__multf3; | |
| 11 | const __mulxf3 = @import("mulxf3.zig").__mulxf3; | |
| 12 | const __muldf3 = @import("muldf3.zig").__muldf3; | |
| 13 | const __mulsf3 = @import("mulsf3.zig").__mulsf3; | |
| 10 | const impl = @import("mulf3.zig"); | |
| 11 | const mul_f16 = impl.mul_f16; | |
| 12 | const mul_f32 = impl.mul_f32; | |
| 13 | const mul_f64 = impl.mul_f64; | |
| 14 | const mul_f80 = impl.mul_f80; | |
| 15 | const mul_f128 = impl.mul_f128; | |
| 14 | 16 | |
| 15 | 17 | // return true if equal |
| 16 | 18 | // 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 | 36 | return false; |
| 35 | 37 | } |
| 36 | 38 | |
| 37 | fn test__multf3(a: f128, b: f128, expected_hi: u64, expected_lo: u64) !void { | |
| 38 | const x = __multf3(a, b); | |
| 39 | fn test_mul_f128(a: f128, b: f128, expected_hi: u64, expected_lo: u64) !void { | |
| 40 | const x = mul_f128(a, b); | |
| 39 | 41 | |
| 40 | 42 | if (compareResultLD(x, expected_hi, expected_lo)) |
| 41 | 43 | return; |
| ... | ... | @@ -49,68 +51,68 @@ fn makeNaN128(rand: u64) f128 { |
| 49 | 51 | } |
| 50 | 52 | test "multf3" { |
| 51 | 53 | // qNaN * any = qNaN |
| 52 | try test__multf3(qnan128, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0); | |
| 54 | try test_mul_f128(qnan128, 0x1.23456789abcdefp+5, 0x7fff800000000000, 0x0); | |
| 53 | 55 | |
| 54 | 56 | // NaN * any = NaN |
| 55 | 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 | 59 | // inf * any = inf |
| 58 | try test__multf3(inf128, 0x1.23456789abcdefp+5, 0x7fff000000000000, 0x0); | |
| 60 | try test_mul_f128(inf128, 0x1.23456789abcdefp+5, 0x7fff000000000000, 0x0); | |
| 59 | 61 | |
| 60 | 62 | // any * any |
| 61 | try test__multf3( | |
| 63 | try test_mul_f128( | |
| 62 | 64 | @as(f128, @bitCast(@as(u128, 0x40042eab345678439abcdefea5678234))), |
| 63 | 65 | @as(f128, @bitCast(@as(u128, 0x3ffeedcb34a235253948765432134675))), |
| 64 | 66 | 0x400423e7f9e3c9fc, |
| 65 | 67 | 0xd906c2c2a85777c4, |
| 66 | 68 | ); |
| 67 | 69 | |
| 68 | try test__multf3( | |
| 70 | try test_mul_f128( | |
| 69 | 71 | @as(f128, @bitCast(@as(u128, 0x3fcd353e45674d89abacc3a2ebf3ff50))), |
| 70 | 72 | @as(f128, @bitCast(@as(u128, 0x3ff6ed8764648369535adf4be3214568))), |
| 71 | 73 | 0x3fc52a163c6223fc, |
| 72 | 74 | 0xc94c4bf0430768b4, |
| 73 | 75 | ); |
| 74 | 76 | |
| 75 | try test__multf3( | |
| 77 | try test_mul_f128( | |
| 76 | 78 | 0x1.234425696abcad34a35eeffefdcbap+456, |
| 77 | 79 | 0x451.ed98d76e5d46e5f24323dff21ffp+600, |
| 78 | 80 | 0x44293a91de5e0e94, |
| 79 | 81 | 0xe8ed17cc2cdf64ac, |
| 80 | 82 | ); |
| 81 | 83 | |
| 82 | try test__multf3( | |
| 84 | try test_mul_f128( | |
| 83 | 85 | @as(f128, @bitCast(@as(u128, 0x3f154356473c82a9fabf2d22ace345df))), |
| 84 | 86 | @as(f128, @bitCast(@as(u128, 0x3e38eda98765476743ab21da23d45679))), |
| 85 | 87 | 0x3d4f37c1a3137cae, |
| 86 | 88 | 0xfc6807048bc2836a, |
| 87 | 89 | ); |
| 88 | 90 | |
| 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); | |
| 90 | 92 | |
| 91 | 93 | // Denormal operands. |
| 92 | try test__multf3( | |
| 94 | try test_mul_f128( | |
| 93 | 95 | 0x0.0000000000000000000000000001p-16382, |
| 94 | 96 | 0x1p16383, |
| 95 | 97 | 0x3f90000000000000, |
| 96 | 98 | 0x0, |
| 97 | 99 | ); |
| 98 | try test__multf3( | |
| 100 | try test_mul_f128( | |
| 99 | 101 | 0x1p16383, |
| 100 | 102 | 0x0.0000000000000000000000000001p-16382, |
| 101 | 103 | 0x3f90000000000000, |
| 102 | 104 | 0x0, |
| 103 | 105 | ); |
| 104 | 106 | |
| 105 | try test__multf3(0x1.0000_0000_0000_0000_0000_0000_0001p+0, 0x1.8p+5, 0x4004_8000_0000_0000, 0x0000_0000_0000_0002); | |
| 106 | try test__multf3(0x1.0000_0000_0000_0000_0000_0000_0002p+0, 0x1.8p+5, 0x4004_8000_0000_0000, 0x0000_0000_0000_0003); | |
| 107 | try test__multf3(2.0, math.floatTrueMin(f128), 0x0000_0000_0000_0000, 0x0000_0000_0000_0002); | |
| 107 | try test_mul_f128(0x1.0000_0000_0000_0000_0000_0000_0001p+0, 0x1.8p+5, 0x4004_8000_0000_0000, 0x0000_0000_0000_0002); | |
| 108 | try test_mul_f128(0x1.0000_0000_0000_0000_0000_0000_0002p+0, 0x1.8p+5, 0x4004_8000_0000_0000, 0x0000_0000_0000_0003); | |
| 109 | try test_mul_f128(2.0, math.floatTrueMin(f128), 0x0000_0000_0000_0000, 0x0000_0000_0000_0002); | |
| 108 | 110 | } |
| 109 | 111 | |
| 110 | 112 | const qnan80: f80 = @bitCast(@as(u80, @bitCast(math.nan(f80))) | (1 << (math.floatFractionalBits(f80) - 1))); |
| 111 | 113 | |
| 112 | fn test__mulxf3(a: f80, b: f80, expected: u80) !void { | |
| 113 | const x = __mulxf3(a, b); | |
| 114 | fn test_mul_f80(a: f80, b: f80, expected: u80) !void { | |
| 115 | const x = mul_f80(a, b); | |
| 114 | 116 | const rep: u80 = @bitCast(x); |
| 115 | 117 | |
| 116 | 118 | if (rep == expected) |
| ... | ... | @@ -124,47 +126,47 @@ fn test__mulxf3(a: f80, b: f80, expected: u80) !void { |
| 124 | 126 | |
| 125 | 127 | test "mulxf3" { |
| 126 | 128 | // NaN * any = NaN |
| 127 | try test__mulxf3(qnan80, 0x1.23456789abcdefp+5, @as(u80, @bitCast(qnan80))); | |
| 128 | try test__mulxf3(@as(f80, @bitCast(@as(u80, 0x7fff_8000_8000_3000_0000))), 0x1.23456789abcdefp+5, @as(u80, @bitCast(qnan80))); | |
| 129 | try test_mul_f80(qnan80, 0x1.23456789abcdefp+5, @as(u80, @bitCast(qnan80))); | |
| 130 | try test_mul_f80(@as(f80, @bitCast(@as(u80, 0x7fff_8000_8000_3000_0000))), 0x1.23456789abcdefp+5, @as(u80, @bitCast(qnan80))); | |
| 129 | 131 | |
| 130 | 132 | // any * NaN = NaN |
| 131 | try test__mulxf3(0x1.23456789abcdefp+5, qnan80, @as(u80, @bitCast(qnan80))); | |
| 132 | try test__mulxf3(0x1.23456789abcdefp+5, @as(f80, @bitCast(@as(u80, 0x7fff_8000_8000_3000_0000))), @as(u80, @bitCast(qnan80))); | |
| 133 | try test_mul_f80(0x1.23456789abcdefp+5, qnan80, @as(u80, @bitCast(qnan80))); | |
| 134 | try test_mul_f80(0x1.23456789abcdefp+5, @as(f80, @bitCast(@as(u80, 0x7fff_8000_8000_3000_0000))), @as(u80, @bitCast(qnan80))); | |
| 133 | 135 | |
| 134 | 136 | // 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))); | |
| 136 | 138 | |
| 137 | 139 | // 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))); | |
| 139 | 141 | |
| 140 | 142 | // 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)))); | |
| 142 | 144 | |
| 143 | 145 | // 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)))); | |
| 145 | 147 | |
| 146 | 148 | // -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)))); | |
| 148 | 150 | |
| 149 | 151 | // 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)))); | |
| 151 | 153 | |
| 152 | 154 | // 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)))); | |
| 154 | 156 | |
| 155 | 157 | // any * any |
| 156 | try test__mulxf3(0x1.0p+0, 0x1.dcba987654321p+5, 0x4004_ee5d_4c3b_2a19_0800); | |
| 157 | try test__mulxf3(0x1.0000_0000_0000_0004p+0, 0x1.8p+5, 0x4004_C000_0000_0000_0003); // exact | |
| 158 | ||
| 159 | try test__mulxf3(0x1.0000_0000_0000_0002p+0, 0x1.0p+5, 0x4004_8000_0000_0000_0001); // exact | |
| 160 | try test__mulxf3(0x1.0000_0000_0000_0002p+0, 0x1.7ffep+5, 0x4004_BFFF_0000_0000_0001); // round down | |
| 161 | try test__mulxf3(0x1.0000_0000_0000_0002p+0, 0x1.8p+5, 0x4004_C000_0000_0000_0002); // round up to even | |
| 162 | try test__mulxf3(0x1.0000_0000_0000_0002p+0, 0x1.8002p+5, 0x4004_C001_0000_0000_0002); // round up | |
| 163 | try test__mulxf3(0x1.0000_0000_0000_0002p+0, 0x1.0p+6, 0x4005_8000_0000_0000_0001); // exact | |
| 164 | ||
| 165 | try test__mulxf3(0x1.0000_0001p+0, 0x1.0000_0001p+0, 0x3FFF_8000_0001_0000_0000); // round down to even | |
| 166 | try test__mulxf3(0x1.0000_0001p+0, 0x1.0000_0001_0002p+0, 0x3FFF_8000_0001_0001_0001); // round up | |
| 167 | try test__mulxf3(0x0.8000_0000_0000_0000p-16382, 2.0, 0x0001_8000_0000_0000_0000); // denormal -> normal | |
| 168 | try test__mulxf3(0x0.7fff_ffff_ffff_fffep-16382, 0x2.0000_0000_0000_0008p0, 0x0001_8000_0000_0000_0000); // denormal -> normal | |
| 169 | try test__mulxf3(0x0.7fff_ffff_ffff_fffep-16382, 0x1.0000_0000_0000_0000p0, 0x0000_3FFF_FFFF_FFFF_FFFF); // denormal -> denormal | |
| 158 | try test_mul_f80(0x1.0p+0, 0x1.dcba987654321p+5, 0x4004_ee5d_4c3b_2a19_0800); | |
| 159 | try test_mul_f80(0x1.0000_0000_0000_0004p+0, 0x1.8p+5, 0x4004_C000_0000_0000_0003); // exact | |
| 160 | ||
| 161 | try test_mul_f80(0x1.0000_0000_0000_0002p+0, 0x1.0p+5, 0x4004_8000_0000_0000_0001); // exact | |
| 162 | try test_mul_f80(0x1.0000_0000_0000_0002p+0, 0x1.7ffep+5, 0x4004_BFFF_0000_0000_0001); // round down | |
| 163 | try test_mul_f80(0x1.0000_0000_0000_0002p+0, 0x1.8p+5, 0x4004_C000_0000_0000_0002); // round up to even | |
| 164 | try test_mul_f80(0x1.0000_0000_0000_0002p+0, 0x1.8002p+5, 0x4004_C001_0000_0000_0002); // round up | |
| 165 | try test_mul_f80(0x1.0000_0000_0000_0002p+0, 0x1.0p+6, 0x4005_8000_0000_0000_0001); // exact | |
| 166 | ||
| 167 | try test_mul_f80(0x1.0000_0001p+0, 0x1.0000_0001p+0, 0x3FFF_8000_0001_0000_0000); // round down to even | |
| 168 | try test_mul_f80(0x1.0000_0001p+0, 0x1.0000_0001_0002p+0, 0x3FFF_8000_0001_0001_0001); // round up | |
| 169 | try test_mul_f80(0x0.8000_0000_0000_0000p-16382, 2.0, 0x0001_8000_0000_0000_0000); // denormal -> normal | |
| 170 | try test_mul_f80(0x0.7fff_ffff_ffff_fffep-16382, 0x2.0000_0000_0000_0008p0, 0x0001_8000_0000_0000_0000); // denormal -> normal | |
| 171 | try test_mul_f80(0x0.7fff_ffff_ffff_fffep-16382, 0x1.0000_0000_0000_0000p0, 0x0000_3FFF_FFFF_FFFF_FFFF); // denormal -> denormal | |
| 170 | 172 | } |
lib/compiler_rt/mulhc3.zig deleted-13| ... | ... | @@ -1,13 +0,0 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = compiler_rt.symbol; | |
| 3 | const mulc3 = @import("./mulc3.zig"); | |
| 4 | ||
| 5 | comptime { | |
| 6 | if (@import("builtin").zig_backend != .stage2_c) { | |
| 7 | symbol(&__mulhc3, "__mulhc3"); | |
| 8 | } | |
| 9 | } | |
| 10 | ||
| 11 | pub 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 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = compiler_rt.symbol; | |
| 3 | const mulf3 = @import("./mulf3.zig").mulf3; | |
| 4 | ||
| 5 | comptime { | |
| 6 | symbol(&__mulhf3, "__mulhf3"); | |
| 7 | } | |
| 8 | ||
| 9 | pub 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 @@ |
| 1 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 2 | const mulc3 = @import("./mulc3.zig"); | |
| 3 | ||
| 4 | comptime { | |
| 5 | if (@import("builtin").zig_backend != .stage2_c) { | |
| 6 | symbol(&__mulsc3, "__mulsc3"); | |
| 7 | } | |
| 8 | } | |
| 9 | ||
| 10 | pub 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 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = compiler_rt.symbol; | |
| 3 | const mulf3 = @import("./mulf3.zig").mulf3; | |
| 4 | ||
| 5 | comptime { | |
| 6 | if (compiler_rt.want_aeabi) { | |
| 7 | symbol(&__aeabi_fmul, "__aeabi_fmul"); | |
| 8 | } else { | |
| 9 | symbol(&__mulsf3, "__mulsf3"); | |
| 10 | } | |
| 11 | } | |
| 12 | ||
| 13 | pub fn __mulsf3(a: f32, b: f32) callconv(.c) f32 { | |
| 14 | return mulf3(f32, a, b); | |
| 15 | } | |
| 16 | ||
| 17 | fn __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 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 3 | const mulc3 = @import("./mulc3.zig"); | |
| 4 | ||
| 5 | comptime { | |
| 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 | ||
| 13 | pub 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 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = compiler_rt.symbol; | |
| 3 | const mulf3 = @import("./mulf3.zig").mulf3; | |
| 4 | ||
| 5 | comptime { | |
| 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 | ||
| 16 | pub fn __multf3(a: f128, b: f128) callconv(.c) f128 { | |
| 17 | return mulf3(f128, a, b); | |
| 18 | } | |
| 19 | ||
| 20 | fn _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 | 1 | const testing = @import("std").testing; |
| 2 | 2 | |
| 3 | 3 | const mulv = @import("mulo.zig"); |
| 4 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 4 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 5 | const symbol = compiler_rt.symbol; | |
| 5 | 6 | |
| 6 | 7 | comptime { |
| 7 | 8 | symbol(&__mulvsi3, "__mulvsi3"); |
| ... | ... | @@ -10,7 +11,7 @@ comptime { |
| 10 | 11 | pub fn __mulvsi3(a: i32, b: i32) callconv(.c) i32 { |
| 11 | 12 | var overflow: c_int = 0; |
| 12 | 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 | 15 | return sum; |
| 15 | 16 | } |
| 16 | 17 |
lib/compiler_rt/mulxc3.zig deleted-13| ... | ... | @@ -1,13 +0,0 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = compiler_rt.symbol; | |
| 3 | const mulc3 = @import("./mulc3.zig"); | |
| 4 | ||
| 5 | comptime { | |
| 6 | if (@import("builtin").zig_backend != .stage2_c) { | |
| 7 | symbol(&__mulxc3, "__mulxc3"); | |
| 8 | } | |
| 9 | } | |
| 10 | ||
| 11 | pub 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 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = compiler_rt.symbol; | |
| 3 | const mulf3 = @import("./mulf3.zig").mulf3; | |
| 4 | ||
| 5 | comptime { | |
| 6 | symbol(&__mulxf3, "__mulxf3"); | |
| 7 | } | |
| 8 | ||
| 9 | pub 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 | 33 | }; |
| 34 | 34 | const N: UT = @bitSizeOf(ST); |
| 35 | 35 | const min: ST = @as(ST, @bitCast((@as(UT, 1) << (N - 1)))); |
| 36 | if (a == min) | |
| 37 | @panic("compiler_rt negv: overflow"); | |
| 36 | if (a == min) @panic("integer overflow"); | |
| 38 | 37 | return -a; |
| 39 | 38 | } |
| 40 | 39 |
lib/compiler_rt/os_version_check.zig-1| ... | ... | @@ -3,7 +3,6 @@ const testing = std.testing; |
| 3 | 3 | const builtin = @import("builtin"); |
| 4 | 4 | const compiler_rt = @import("../compiler_rt.zig"); |
| 5 | 5 | const symbol = compiler_rt.symbol; |
| 6 | const panic = @import("../compiler_rt.zig").panic; | |
| 7 | 6 | |
| 8 | 7 | const have_availability_version_check = builtin.os.tag.isDarwin() and |
| 9 | 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 | 1 | //! parity - if number of bits set is even => 0, else => 1 |
| 2 | 2 | //! - pariytXi2_generic for big and little endian |
| 3 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 3 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 4 | const symbol = compiler_rt.symbol; | |
| 4 | 5 | |
| 5 | 6 | comptime { |
| 6 | 7 | symbol(&__paritysi2, "__paritysi2"); |
lib/compiler_rt/popcount.zig+2-1| ... | ... | @@ -6,7 +6,8 @@ |
| 6 | 6 | //! TAOCP: Combinational Algorithms, Bitwise Tricks And Techniques, |
| 7 | 7 | //! subsubsection "Working with the rightmost bits" and "Sideways addition". |
| 8 | 8 | |
| 9 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 9 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 10 | const symbol = compiler_rt.symbol; | |
| 10 | 11 | |
| 11 | 12 | comptime { |
| 12 | 13 | symbol(&__popcountsi2, "__popcountsi2"); |
lib/compiler_rt/powiXf2.zig+28-11| ... | ... | @@ -4,16 +4,18 @@ |
| 4 | 4 | //! error propagation and this method is optimized for performance, not accuracy. |
| 5 | 5 | |
| 6 | 6 | const compiler_rt = @import("../compiler_rt.zig"); |
| 7 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 7 | const symbol = compiler_rt.symbol; | |
| 8 | 8 | |
| 9 | 9 | comptime { |
| 10 | 10 | symbol(&__powihf2, "__powihf2"); |
| 11 | 11 | symbol(&__powisf2, "__powisf2"); |
| 12 | 12 | symbol(&__powidf2, "__powidf2"); |
| 13 | if (compiler_rt.want_ppc_abi) | |
| 14 | symbol(&__powitf2, "__powikf2"); | |
| 15 | symbol(&__powitf2, "__powitf2"); | |
| 16 | 13 | symbol(&__powixf2, "__powixf2"); |
| 14 | if (compiler_rt.want_ppc_abi) { | |
| 15 | symbol(&__powitf2, "__powikf2"); | |
| 16 | } else { | |
| 17 | symbol(&__powitf2, "__powitf2"); | |
| 18 | } | |
| 17 | 19 | } |
| 18 | 20 | |
| 19 | 21 | 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 | 34 | return if (is_recip) 1 / r else r; |
| 33 | 35 | } |
| 34 | 36 | |
| 35 | pub fn __powihf2(a: f16, b: i32) callconv(.c) f16 { | |
| 37 | fn __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 | } | |
| 40 | pub fn powi_f16(a: f16, b: i32) f16 { | |
| 36 | 41 | return powiXf2(f16, a, b); |
| 37 | 42 | } |
| 38 | 43 | |
| 39 | pub fn __powisf2(a: f32, b: i32) callconv(.c) f32 { | |
| 44 | fn __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 | } | |
| 47 | pub fn powi_f32(a: f32, b: i32) f32 { | |
| 40 | 48 | return powiXf2(f32, a, b); |
| 41 | 49 | } |
| 42 | 50 | |
| 43 | pub fn __powidf2(a: f64, b: i32) callconv(.c) f64 { | |
| 51 | fn __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 | } | |
| 54 | pub fn powi_f64(a: f64, b: i32) f64 { | |
| 44 | 55 | return powiXf2(f64, a, b); |
| 45 | 56 | } |
| 46 | 57 | |
| 47 | pub fn __powitf2(a: f128, b: i32) callconv(.c) f128 { | |
| 48 | return powiXf2(f128, a, b); | |
| 58 | fn __powixf2(a: compiler_rt.f80.Abi, b: i32) callconv(.c) compiler_rt.f80.Abi { | |
| 59 | return compiler_rt.f80.toAbi(powi_f80(compiler_rt.f80.fromAbi(a), b)); | |
| 49 | 60 | } |
| 50 | ||
| 51 | pub fn __powixf2(a: f80, b: i32) callconv(.c) f80 { | |
| 61 | pub fn powi_f80(a: f80, b: i32) f80 { | |
| 52 | 62 | return powiXf2(f80, a, b); |
| 53 | 63 | } |
| 54 | 64 | |
| 65 | fn __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 | } | |
| 68 | pub fn powi_f128(a: f128, b: i32) f128 { | |
| 69 | return powiXf2(f128, a, b); | |
| 70 | } | |
| 71 | ||
| 55 | 72 | test { |
| 56 | 73 | _ = @import("powiXf2_test.zig"); |
| 57 | 74 | } |
lib/compiler_rt/powiXf2_test.zig+531-525| ... | ... | @@ -2,562 +2,568 @@ |
| 2 | 2 | // powisf2_test.c, powidf2_test.c, powitf2_test.c, powixf2_test.c |
| 3 | 3 | // powihf2 adapted from powisf2 tests |
| 4 | 4 | |
| 5 | const powiXf2 = @import("powiXf2.zig"); | |
| 6 | 5 | const std = @import("std"); |
| 7 | const builtin = @import("builtin"); | |
| 8 | 6 | const testing = std.testing; |
| 9 | 7 | const math = std.math; |
| 10 | 8 | |
| 11 | fn test__powihf2(a: f16, b: i32, expected: f16) !void { | |
| 12 | const result = powiXf2.__powihf2(a, b); | |
| 9 | const impl = @import("powiXf2.zig"); | |
| 10 | ||
| 11 | const powi_f16 = impl.powi_f16; | |
| 12 | const powi_f32 = impl.powi_f32; | |
| 13 | const powi_f64 = impl.powi_f64; | |
| 14 | const powi_f80 = impl.powi_f80; | |
| 15 | const powi_f128 = impl.powi_f128; | |
| 16 | ||
| 17 | fn test_powi_f16(a: f16, b: i32, expected: f16) !void { | |
| 18 | const result = powi_f16(a, b); | |
| 13 | 19 | try testing.expectEqual(expected, result); |
| 14 | 20 | } |
| 15 | 21 | |
| 16 | fn test__powisf2(a: f32, b: i32, expected: f32) !void { | |
| 17 | const result = powiXf2.__powisf2(a, b); | |
| 22 | fn test_powi_f32(a: f32, b: i32, expected: f32) !void { | |
| 23 | const result = powi_f32(a, b); | |
| 18 | 24 | try testing.expectEqual(expected, result); |
| 19 | 25 | } |
| 20 | 26 | |
| 21 | fn test__powidf2(a: f64, b: i32, expected: f64) !void { | |
| 22 | const result = powiXf2.__powidf2(a, b); | |
| 27 | fn test_powi_f64(a: f64, b: i32, expected: f64) !void { | |
| 28 | const result = powi_f64(a, b); | |
| 23 | 29 | try testing.expectEqual(expected, result); |
| 24 | 30 | } |
| 25 | 31 | |
| 26 | fn test__powitf2(a: f128, b: i32, expected: f128) !void { | |
| 27 | const result = powiXf2.__powitf2(a, b); | |
| 32 | fn test_powi_f80(a: f80, b: i32, expected: f80) !void { | |
| 33 | const result = powi_f80(a, b); | |
| 28 | 34 | try testing.expectEqual(expected, result); |
| 29 | 35 | } |
| 30 | 36 | |
| 31 | fn test__powixf2(a: f80, b: i32, expected: f80) !void { | |
| 32 | const result = powiXf2.__powixf2(a, b); | |
| 37 | fn test_powi_f128(a: f128, b: i32, expected: f128) !void { | |
| 38 | const result = powi_f128(a, b); | |
| 33 | 39 | try testing.expectEqual(expected, result); |
| 34 | 40 | } |
| 35 | 41 | |
| 36 | test "powihf2" { | |
| 42 | test powi_f16 { | |
| 37 | 43 | const inf_f16 = math.inf(f16); |
| 38 | try test__powisf2(0, 0, 1); | |
| 39 | try test__powihf2(1, 0, 1); | |
| 40 | try test__powihf2(1.5, 0, 1); | |
| 41 | try test__powihf2(2, 0, 1); | |
| 42 | try test__powihf2(inf_f16, 0, 1); | |
| 43 | ||
| 44 | try test__powihf2(-0.0, 0, 1); | |
| 45 | try test__powihf2(-1, 0, 1); | |
| 46 | try test__powihf2(-1.5, 0, 1); | |
| 47 | try test__powihf2(-2, 0, 1); | |
| 48 | try test__powihf2(-inf_f16, 0, 1); | |
| 49 | ||
| 50 | try test__powihf2(0, 1, 0); | |
| 51 | try test__powihf2(0, 2, 0); | |
| 52 | try test__powihf2(0, 3, 0); | |
| 53 | try test__powihf2(0, 4, 0); | |
| 54 | try test__powihf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); | |
| 55 | try test__powihf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0); | |
| 56 | ||
| 57 | try test__powihf2(-0.0, 1, -0.0); | |
| 58 | try test__powihf2(-0.0, 2, 0); | |
| 59 | try test__powihf2(-0.0, 3, -0.0); | |
| 60 | try test__powihf2(-0.0, 4, 0); | |
| 61 | try test__powihf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); | |
| 62 | try test__powihf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0); | |
| 63 | ||
| 64 | try test__powihf2(1, 1, 1); | |
| 65 | try test__powihf2(1, 2, 1); | |
| 66 | try test__powihf2(1, 3, 1); | |
| 67 | try test__powihf2(1, 4, 1); | |
| 68 | try test__powihf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1); | |
| 69 | try test__powihf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1); | |
| 70 | ||
| 71 | try test__powihf2(inf_f16, 1, inf_f16); | |
| 72 | try test__powihf2(inf_f16, 2, inf_f16); | |
| 73 | try test__powihf2(inf_f16, 3, inf_f16); | |
| 74 | try test__powihf2(inf_f16, 4, inf_f16); | |
| 75 | try test__powihf2(inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f16); | |
| 76 | try test__powihf2(inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f16); | |
| 77 | ||
| 78 | try test__powihf2(-inf_f16, 1, -inf_f16); | |
| 79 | try test__powihf2(-inf_f16, 2, inf_f16); | |
| 80 | try test__powihf2(-inf_f16, 3, -inf_f16); | |
| 81 | try test__powihf2(-inf_f16, 4, inf_f16); | |
| 82 | try test__powihf2(-inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f16); | |
| 83 | try test__powihf2(-inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f16); | |
| 44 | try test_powi_f16(0, 0, 1); | |
| 45 | try test_powi_f16(1, 0, 1); | |
| 46 | try test_powi_f16(1.5, 0, 1); | |
| 47 | try test_powi_f16(2, 0, 1); | |
| 48 | try test_powi_f16(inf_f16, 0, 1); | |
| 49 | ||
| 50 | try test_powi_f16(-0.0, 0, 1); | |
| 51 | try test_powi_f16(-1, 0, 1); | |
| 52 | try test_powi_f16(-1.5, 0, 1); | |
| 53 | try test_powi_f16(-2, 0, 1); | |
| 54 | try test_powi_f16(-inf_f16, 0, 1); | |
| 55 | ||
| 56 | try test_powi_f16(0, 1, 0); | |
| 57 | try test_powi_f16(0, 2, 0); | |
| 58 | try test_powi_f16(0, 3, 0); | |
| 59 | try test_powi_f16(0, 4, 0); | |
| 60 | try test_powi_f16(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); | |
| 61 | try test_powi_f16(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0); | |
| 62 | ||
| 63 | try test_powi_f16(-0.0, 1, -0.0); | |
| 64 | try test_powi_f16(-0.0, 2, 0); | |
| 65 | try test_powi_f16(-0.0, 3, -0.0); | |
| 66 | try test_powi_f16(-0.0, 4, 0); | |
| 67 | try test_powi_f16(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); | |
| 68 | try test_powi_f16(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0); | |
| 69 | ||
| 70 | try test_powi_f16(1, 1, 1); | |
| 71 | try test_powi_f16(1, 2, 1); | |
| 72 | try test_powi_f16(1, 3, 1); | |
| 73 | try test_powi_f16(1, 4, 1); | |
| 74 | try test_powi_f16(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1); | |
| 75 | try test_powi_f16(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1); | |
| 76 | ||
| 77 | try test_powi_f16(inf_f16, 1, inf_f16); | |
| 78 | try test_powi_f16(inf_f16, 2, inf_f16); | |
| 79 | try test_powi_f16(inf_f16, 3, inf_f16); | |
| 80 | try test_powi_f16(inf_f16, 4, inf_f16); | |
| 81 | try test_powi_f16(inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f16); | |
| 82 | try test_powi_f16(inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f16); | |
| 83 | ||
| 84 | try test_powi_f16(-inf_f16, 1, -inf_f16); | |
| 85 | try test_powi_f16(-inf_f16, 2, inf_f16); | |
| 86 | try test_powi_f16(-inf_f16, 3, -inf_f16); | |
| 87 | try test_powi_f16(-inf_f16, 4, inf_f16); | |
| 88 | try test_powi_f16(-inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f16); | |
| 89 | try test_powi_f16(-inf_f16, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f16); | |
| 84 | 90 | // |
| 85 | try test__powihf2(0, -1, inf_f16); | |
| 86 | try test__powihf2(0, -2, inf_f16); | |
| 87 | try test__powihf2(0, -3, inf_f16); | |
| 88 | try test__powihf2(0, -4, inf_f16); | |
| 89 | try test__powihf2(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f16); // 0 ^ anything = +inf | |
| 90 | try test__powihf2(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f16); | |
| 91 | try test__powihf2(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f16); | |
| 92 | ||
| 93 | try test__powihf2(-0.0, -1, -inf_f16); | |
| 94 | try test__powihf2(-0.0, -2, inf_f16); | |
| 95 | try test__powihf2(-0.0, -3, -inf_f16); | |
| 96 | try test__powihf2(-0.0, -4, inf_f16); | |
| 97 | try test__powihf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f16); // -0 ^ anything even = +inf | |
| 98 | try test__powihf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f16); // -0 ^ anything odd = -inf | |
| 99 | try test__powihf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f16); | |
| 100 | ||
| 101 | try test__powihf2(1, -1, 1); | |
| 102 | try test__powihf2(1, -2, 1); | |
| 103 | try test__powihf2(1, -3, 1); | |
| 104 | try test__powihf2(1, -4, 1); | |
| 105 | try test__powihf2(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1); // 1.0 ^ anything = 1 | |
| 106 | try test__powihf2(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1); | |
| 107 | try test__powihf2(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1); | |
| 108 | ||
| 109 | try test__powihf2(inf_f16, -1, 0); | |
| 110 | try test__powihf2(inf_f16, -2, 0); | |
| 111 | try test__powihf2(inf_f16, -3, 0); | |
| 112 | try test__powihf2(inf_f16, -4, 0); | |
| 113 | try test__powihf2(inf_f16, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); | |
| 114 | try test__powihf2(inf_f16, @as(i32, @bitCast(@as(u32, 0x80000001))), 0); | |
| 115 | try test__powihf2(inf_f16, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); | |
| 91 | try test_powi_f16(0, -1, inf_f16); | |
| 92 | try test_powi_f16(0, -2, inf_f16); | |
| 93 | try test_powi_f16(0, -3, inf_f16); | |
| 94 | try test_powi_f16(0, -4, inf_f16); | |
| 95 | try test_powi_f16(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f16); // 0 ^ anything = +inf | |
| 96 | try test_powi_f16(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f16); | |
| 97 | try test_powi_f16(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f16); | |
| 98 | ||
| 99 | try test_powi_f16(-0.0, -1, -inf_f16); | |
| 100 | try test_powi_f16(-0.0, -2, inf_f16); | |
| 101 | try test_powi_f16(-0.0, -3, -inf_f16); | |
| 102 | try test_powi_f16(-0.0, -4, inf_f16); | |
| 103 | try test_powi_f16(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f16); // -0 ^ anything even = +inf | |
| 104 | try test_powi_f16(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f16); // -0 ^ anything odd = -inf | |
| 105 | try test_powi_f16(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f16); | |
| 106 | ||
| 107 | try test_powi_f16(1, -1, 1); | |
| 108 | try test_powi_f16(1, -2, 1); | |
| 109 | try test_powi_f16(1, -3, 1); | |
| 110 | try test_powi_f16(1, -4, 1); | |
| 111 | try test_powi_f16(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1); // 1.0 ^ anything = 1 | |
| 112 | try test_powi_f16(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1); | |
| 113 | try test_powi_f16(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1); | |
| 114 | ||
| 115 | try test_powi_f16(inf_f16, -1, 0); | |
| 116 | try test_powi_f16(inf_f16, -2, 0); | |
| 117 | try test_powi_f16(inf_f16, -3, 0); | |
| 118 | try test_powi_f16(inf_f16, -4, 0); | |
| 119 | try test_powi_f16(inf_f16, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); | |
| 120 | try test_powi_f16(inf_f16, @as(i32, @bitCast(@as(u32, 0x80000001))), 0); | |
| 121 | try test_powi_f16(inf_f16, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); | |
| 116 | 122 | // |
| 117 | try test__powihf2(-inf_f16, -1, -0.0); | |
| 118 | try test__powihf2(-inf_f16, -2, 0); | |
| 119 | try test__powihf2(-inf_f16, -3, -0.0); | |
| 120 | try test__powihf2(-inf_f16, -4, 0); | |
| 121 | try test__powihf2(-inf_f16, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); | |
| 122 | try test__powihf2(-inf_f16, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0); | |
| 123 | try test__powihf2(-inf_f16, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); | |
| 124 | ||
| 125 | try test__powihf2(2, 10, 1024.0); | |
| 126 | try test__powihf2(-2, 10, 1024.0); | |
| 127 | try test__powihf2(2, -10, 1.0 / 1024.0); | |
| 128 | try test__powihf2(-2, -10, 1.0 / 1024.0); | |
| 129 | ||
| 130 | try test__powihf2(2, 14, 16384.0); | |
| 131 | try test__powihf2(-2, 14, 16384.0); | |
| 132 | try test__powihf2(2, 15, 32768.0); | |
| 133 | try test__powihf2(-2, 15, -32768.0); | |
| 134 | try test__powihf2(2, 16, inf_f16); | |
| 135 | try test__powihf2(-2, 16, inf_f16); | |
| 136 | ||
| 137 | try test__powihf2(2, -13, 1.0 / 8192.0); | |
| 138 | try test__powihf2(-2, -13, -1.0 / 8192.0); | |
| 139 | try test__powihf2(2, -15, 1.0 / 32768.0); | |
| 140 | try test__powihf2(-2, -15, -1.0 / 32768.0); | |
| 141 | try test__powihf2(2, -16, 0.0); // expected = 0.0 = 1/(-2**16) | |
| 142 | try test__powihf2(-2, -16, 0.0); // expected = 0.0 = 1/(2**16) | |
| 123 | try test_powi_f16(-inf_f16, -1, -0.0); | |
| 124 | try test_powi_f16(-inf_f16, -2, 0); | |
| 125 | try test_powi_f16(-inf_f16, -3, -0.0); | |
| 126 | try test_powi_f16(-inf_f16, -4, 0); | |
| 127 | try test_powi_f16(-inf_f16, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); | |
| 128 | try test_powi_f16(-inf_f16, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0); | |
| 129 | try test_powi_f16(-inf_f16, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); | |
| 130 | ||
| 131 | try test_powi_f16(2, 10, 1024.0); | |
| 132 | try test_powi_f16(-2, 10, 1024.0); | |
| 133 | try test_powi_f16(2, -10, 1.0 / 1024.0); | |
| 134 | try test_powi_f16(-2, -10, 1.0 / 1024.0); | |
| 135 | ||
| 136 | try test_powi_f16(2, 14, 16384.0); | |
| 137 | try test_powi_f16(-2, 14, 16384.0); | |
| 138 | try test_powi_f16(2, 15, 32768.0); | |
| 139 | try test_powi_f16(-2, 15, -32768.0); | |
| 140 | try test_powi_f16(2, 16, inf_f16); | |
| 141 | try test_powi_f16(-2, 16, inf_f16); | |
| 142 | ||
| 143 | try test_powi_f16(2, -13, 1.0 / 8192.0); | |
| 144 | try test_powi_f16(-2, -13, -1.0 / 8192.0); | |
| 145 | try test_powi_f16(2, -15, 1.0 / 32768.0); | |
| 146 | try test_powi_f16(-2, -15, -1.0 / 32768.0); | |
| 147 | try test_powi_f16(2, -16, 0.0); // expected = 0.0 = 1/(-2**16) | |
| 148 | try test_powi_f16(-2, -16, 0.0); // expected = 0.0 = 1/(2**16) | |
| 143 | 149 | } |
| 144 | 150 | |
| 145 | test "powisf2" { | |
| 151 | test powi_f32 { | |
| 146 | 152 | const inf_f32 = math.inf(f32); |
| 147 | try test__powisf2(0, 0, 1); | |
| 148 | try test__powisf2(1, 0, 1); | |
| 149 | try test__powisf2(1.5, 0, 1); | |
| 150 | try test__powisf2(2, 0, 1); | |
| 151 | try test__powisf2(inf_f32, 0, 1); | |
| 152 | ||
| 153 | try test__powisf2(-0.0, 0, 1); | |
| 154 | try test__powisf2(-1, 0, 1); | |
| 155 | try test__powisf2(-1.5, 0, 1); | |
| 156 | try test__powisf2(-2, 0, 1); | |
| 157 | try test__powisf2(-inf_f32, 0, 1); | |
| 158 | ||
| 159 | try test__powisf2(0, 1, 0); | |
| 160 | try test__powisf2(0, 2, 0); | |
| 161 | try test__powisf2(0, 3, 0); | |
| 162 | try test__powisf2(0, 4, 0); | |
| 163 | try test__powisf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); | |
| 164 | try test__powisf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0); | |
| 165 | ||
| 166 | try test__powisf2(-0.0, 1, -0.0); | |
| 167 | try test__powisf2(-0.0, 2, 0); | |
| 168 | try test__powisf2(-0.0, 3, -0.0); | |
| 169 | try test__powisf2(-0.0, 4, 0); | |
| 170 | try test__powisf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); | |
| 171 | try test__powisf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0); | |
| 172 | ||
| 173 | try test__powisf2(1, 1, 1); | |
| 174 | try test__powisf2(1, 2, 1); | |
| 175 | try test__powisf2(1, 3, 1); | |
| 176 | try test__powisf2(1, 4, 1); | |
| 177 | try test__powisf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1); | |
| 178 | try test__powisf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1); | |
| 179 | ||
| 180 | try test__powisf2(inf_f32, 1, inf_f32); | |
| 181 | try test__powisf2(inf_f32, 2, inf_f32); | |
| 182 | try test__powisf2(inf_f32, 3, inf_f32); | |
| 183 | try test__powisf2(inf_f32, 4, inf_f32); | |
| 184 | try test__powisf2(inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f32); | |
| 185 | try test__powisf2(inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f32); | |
| 186 | ||
| 187 | try test__powisf2(-inf_f32, 1, -inf_f32); | |
| 188 | try test__powisf2(-inf_f32, 2, inf_f32); | |
| 189 | try test__powisf2(-inf_f32, 3, -inf_f32); | |
| 190 | try test__powisf2(-inf_f32, 4, inf_f32); | |
| 191 | try test__powisf2(-inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f32); | |
| 192 | try test__powisf2(-inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f32); | |
| 193 | ||
| 194 | try test__powisf2(0, -1, inf_f32); | |
| 195 | try test__powisf2(0, -2, inf_f32); | |
| 196 | try test__powisf2(0, -3, inf_f32); | |
| 197 | try test__powisf2(0, -4, inf_f32); | |
| 198 | try test__powisf2(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f32); | |
| 199 | try test__powisf2(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f32); | |
| 200 | try test__powisf2(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f32); | |
| 201 | ||
| 202 | try test__powisf2(-0.0, -1, -inf_f32); | |
| 203 | try test__powisf2(-0.0, -2, inf_f32); | |
| 204 | try test__powisf2(-0.0, -3, -inf_f32); | |
| 205 | try test__powisf2(-0.0, -4, inf_f32); | |
| 206 | try test__powisf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f32); | |
| 207 | try test__powisf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f32); | |
| 208 | try test__powisf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f32); | |
| 209 | ||
| 210 | try test__powisf2(1, -1, 1); | |
| 211 | try test__powisf2(1, -2, 1); | |
| 212 | try test__powisf2(1, -3, 1); | |
| 213 | try test__powisf2(1, -4, 1); | |
| 214 | try test__powisf2(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1); | |
| 215 | try test__powisf2(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1); | |
| 216 | try test__powisf2(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1); | |
| 217 | ||
| 218 | try test__powisf2(inf_f32, -1, 0); | |
| 219 | try test__powisf2(inf_f32, -2, 0); | |
| 220 | try test__powisf2(inf_f32, -3, 0); | |
| 221 | try test__powisf2(inf_f32, -4, 0); | |
| 222 | try test__powisf2(inf_f32, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); | |
| 223 | try test__powisf2(inf_f32, @as(i32, @bitCast(@as(u32, 0x80000001))), 0); | |
| 224 | try test__powisf2(inf_f32, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); | |
| 225 | ||
| 226 | try test__powisf2(-inf_f32, -1, -0.0); | |
| 227 | try test__powisf2(-inf_f32, -2, 0); | |
| 228 | try test__powisf2(-inf_f32, -3, -0.0); | |
| 229 | try test__powisf2(-inf_f32, -4, 0); | |
| 230 | try test__powisf2(-inf_f32, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); | |
| 231 | try test__powisf2(-inf_f32, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0); | |
| 232 | try test__powisf2(-inf_f32, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); | |
| 233 | ||
| 234 | try test__powisf2(2.0, 10, 1024.0); | |
| 235 | try test__powisf2(-2, 10, 1024.0); | |
| 236 | try test__powisf2(2, -10, 1.0 / 1024.0); | |
| 237 | try test__powisf2(-2, -10, 1.0 / 1024.0); | |
| 153 | try test_powi_f32(0, 0, 1); | |
| 154 | try test_powi_f32(1, 0, 1); | |
| 155 | try test_powi_f32(1.5, 0, 1); | |
| 156 | try test_powi_f32(2, 0, 1); | |
| 157 | try test_powi_f32(inf_f32, 0, 1); | |
| 158 | ||
| 159 | try test_powi_f32(-0.0, 0, 1); | |
| 160 | try test_powi_f32(-1, 0, 1); | |
| 161 | try test_powi_f32(-1.5, 0, 1); | |
| 162 | try test_powi_f32(-2, 0, 1); | |
| 163 | try test_powi_f32(-inf_f32, 0, 1); | |
| 164 | ||
| 165 | try test_powi_f32(0, 1, 0); | |
| 166 | try test_powi_f32(0, 2, 0); | |
| 167 | try test_powi_f32(0, 3, 0); | |
| 168 | try test_powi_f32(0, 4, 0); | |
| 169 | try test_powi_f32(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); | |
| 170 | try test_powi_f32(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0); | |
| 171 | ||
| 172 | try test_powi_f32(-0.0, 1, -0.0); | |
| 173 | try test_powi_f32(-0.0, 2, 0); | |
| 174 | try test_powi_f32(-0.0, 3, -0.0); | |
| 175 | try test_powi_f32(-0.0, 4, 0); | |
| 176 | try test_powi_f32(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); | |
| 177 | try test_powi_f32(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0); | |
| 178 | ||
| 179 | try test_powi_f32(1, 1, 1); | |
| 180 | try test_powi_f32(1, 2, 1); | |
| 181 | try test_powi_f32(1, 3, 1); | |
| 182 | try test_powi_f32(1, 4, 1); | |
| 183 | try test_powi_f32(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1); | |
| 184 | try test_powi_f32(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1); | |
| 185 | ||
| 186 | try test_powi_f32(inf_f32, 1, inf_f32); | |
| 187 | try test_powi_f32(inf_f32, 2, inf_f32); | |
| 188 | try test_powi_f32(inf_f32, 3, inf_f32); | |
| 189 | try test_powi_f32(inf_f32, 4, inf_f32); | |
| 190 | try test_powi_f32(inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f32); | |
| 191 | try test_powi_f32(inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f32); | |
| 192 | ||
| 193 | try test_powi_f32(-inf_f32, 1, -inf_f32); | |
| 194 | try test_powi_f32(-inf_f32, 2, inf_f32); | |
| 195 | try test_powi_f32(-inf_f32, 3, -inf_f32); | |
| 196 | try test_powi_f32(-inf_f32, 4, inf_f32); | |
| 197 | try test_powi_f32(-inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f32); | |
| 198 | try test_powi_f32(-inf_f32, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f32); | |
| 199 | ||
| 200 | try test_powi_f32(0, -1, inf_f32); | |
| 201 | try test_powi_f32(0, -2, inf_f32); | |
| 202 | try test_powi_f32(0, -3, inf_f32); | |
| 203 | try test_powi_f32(0, -4, inf_f32); | |
| 204 | try test_powi_f32(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f32); | |
| 205 | try test_powi_f32(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f32); | |
| 206 | try test_powi_f32(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f32); | |
| 207 | ||
| 208 | try test_powi_f32(-0.0, -1, -inf_f32); | |
| 209 | try test_powi_f32(-0.0, -2, inf_f32); | |
| 210 | try test_powi_f32(-0.0, -3, -inf_f32); | |
| 211 | try test_powi_f32(-0.0, -4, inf_f32); | |
| 212 | try test_powi_f32(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f32); | |
| 213 | try test_powi_f32(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f32); | |
| 214 | try test_powi_f32(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f32); | |
| 215 | ||
| 216 | try test_powi_f32(1, -1, 1); | |
| 217 | try test_powi_f32(1, -2, 1); | |
| 218 | try test_powi_f32(1, -3, 1); | |
| 219 | try test_powi_f32(1, -4, 1); | |
| 220 | try test_powi_f32(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1); | |
| 221 | try test_powi_f32(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1); | |
| 222 | try test_powi_f32(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1); | |
| 223 | ||
| 224 | try test_powi_f32(inf_f32, -1, 0); | |
| 225 | try test_powi_f32(inf_f32, -2, 0); | |
| 226 | try test_powi_f32(inf_f32, -3, 0); | |
| 227 | try test_powi_f32(inf_f32, -4, 0); | |
| 228 | try test_powi_f32(inf_f32, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); | |
| 229 | try test_powi_f32(inf_f32, @as(i32, @bitCast(@as(u32, 0x80000001))), 0); | |
| 230 | try test_powi_f32(inf_f32, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); | |
| 231 | ||
| 232 | try test_powi_f32(-inf_f32, -1, -0.0); | |
| 233 | try test_powi_f32(-inf_f32, -2, 0); | |
| 234 | try test_powi_f32(-inf_f32, -3, -0.0); | |
| 235 | try test_powi_f32(-inf_f32, -4, 0); | |
| 236 | try test_powi_f32(-inf_f32, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); | |
| 237 | try test_powi_f32(-inf_f32, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0); | |
| 238 | try test_powi_f32(-inf_f32, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); | |
| 239 | ||
| 240 | try test_powi_f32(2.0, 10, 1024.0); | |
| 241 | try test_powi_f32(-2, 10, 1024.0); | |
| 242 | try test_powi_f32(2, -10, 1.0 / 1024.0); | |
| 243 | try test_powi_f32(-2, -10, 1.0 / 1024.0); | |
| 238 | 244 | // |
| 239 | try test__powisf2(2, 19, 524288.0); | |
| 240 | try test__powisf2(-2, 19, -524288.0); | |
| 241 | try test__powisf2(2, -19, 1.0 / 524288.0); | |
| 242 | try test__powisf2(-2, -19, -1.0 / 524288.0); | |
| 243 | ||
| 244 | try test__powisf2(2, 31, 2147483648.0); | |
| 245 | try test__powisf2(-2, 31, -2147483648.0); | |
| 246 | try test__powisf2(2, -31, 1.0 / 2147483648.0); | |
| 247 | try test__powisf2(-2, -31, -1.0 / 2147483648.0); | |
| 245 | try test_powi_f32(2, 19, 524288.0); | |
| 246 | try test_powi_f32(-2, 19, -524288.0); | |
| 247 | try test_powi_f32(2, -19, 1.0 / 524288.0); | |
| 248 | try test_powi_f32(-2, -19, -1.0 / 524288.0); | |
| 249 | ||
| 250 | try test_powi_f32(2, 31, 2147483648.0); | |
| 251 | try test_powi_f32(-2, 31, -2147483648.0); | |
| 252 | try test_powi_f32(2, -31, 1.0 / 2147483648.0); | |
| 253 | try test_powi_f32(-2, -31, -1.0 / 2147483648.0); | |
| 248 | 254 | } |
| 249 | 255 | |
| 250 | test "powidf2" { | |
| 256 | test powi_f64 { | |
| 251 | 257 | const inf_f64 = math.inf(f64); |
| 252 | try test__powidf2(0, 0, 1); | |
| 253 | try test__powidf2(1, 0, 1); | |
| 254 | try test__powidf2(1.5, 0, 1); | |
| 255 | try test__powidf2(2, 0, 1); | |
| 256 | try test__powidf2(inf_f64, 0, 1); | |
| 257 | ||
| 258 | try test__powidf2(-0.0, 0, 1); | |
| 259 | try test__powidf2(-1, 0, 1); | |
| 260 | try test__powidf2(-1.5, 0, 1); | |
| 261 | try test__powidf2(-2, 0, 1); | |
| 262 | try test__powidf2(-inf_f64, 0, 1); | |
| 263 | ||
| 264 | try test__powidf2(0, 1, 0); | |
| 265 | try test__powidf2(0, 2, 0); | |
| 266 | try test__powidf2(0, 3, 0); | |
| 267 | try test__powidf2(0, 4, 0); | |
| 268 | try test__powidf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); | |
| 269 | try test__powidf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0); | |
| 270 | ||
| 271 | try test__powidf2(-0.0, 1, -0.0); | |
| 272 | try test__powidf2(-0.0, 2, 0); | |
| 273 | try test__powidf2(-0.0, 3, -0.0); | |
| 274 | try test__powidf2(-0.0, 4, 0); | |
| 275 | try test__powidf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); | |
| 276 | try test__powidf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0); | |
| 277 | ||
| 278 | try test__powidf2(1, 1, 1); | |
| 279 | try test__powidf2(1, 2, 1); | |
| 280 | try test__powidf2(1, 3, 1); | |
| 281 | try test__powidf2(1, 4, 1); | |
| 282 | try test__powidf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1); | |
| 283 | try test__powidf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1); | |
| 284 | ||
| 285 | try test__powidf2(inf_f64, 1, inf_f64); | |
| 286 | try test__powidf2(inf_f64, 2, inf_f64); | |
| 287 | try test__powidf2(inf_f64, 3, inf_f64); | |
| 288 | try test__powidf2(inf_f64, 4, inf_f64); | |
| 289 | try test__powidf2(inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f64); | |
| 290 | try test__powidf2(inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f64); | |
| 291 | ||
| 292 | try test__powidf2(-inf_f64, 1, -inf_f64); | |
| 293 | try test__powidf2(-inf_f64, 2, inf_f64); | |
| 294 | try test__powidf2(-inf_f64, 3, -inf_f64); | |
| 295 | try test__powidf2(-inf_f64, 4, inf_f64); | |
| 296 | try test__powidf2(-inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f64); | |
| 297 | try test__powidf2(-inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f64); | |
| 298 | ||
| 299 | try test__powidf2(0, -1, inf_f64); | |
| 300 | try test__powidf2(0, -2, inf_f64); | |
| 301 | try test__powidf2(0, -3, inf_f64); | |
| 302 | try test__powidf2(0, -4, inf_f64); | |
| 303 | try test__powidf2(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f64); | |
| 304 | try test__powidf2(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f64); | |
| 305 | try test__powidf2(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f64); | |
| 306 | ||
| 307 | try test__powidf2(-0.0, -1, -inf_f64); | |
| 308 | try test__powidf2(-0.0, -2, inf_f64); | |
| 309 | try test__powidf2(-0.0, -3, -inf_f64); | |
| 310 | try test__powidf2(-0.0, -4, inf_f64); | |
| 311 | try test__powidf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f64); | |
| 312 | try test__powidf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f64); | |
| 313 | try test__powidf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f64); | |
| 314 | ||
| 315 | try test__powidf2(1, -1, 1); | |
| 316 | try test__powidf2(1, -2, 1); | |
| 317 | try test__powidf2(1, -3, 1); | |
| 318 | try test__powidf2(1, -4, 1); | |
| 319 | try test__powidf2(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1); | |
| 320 | try test__powidf2(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1); | |
| 321 | try test__powidf2(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1); | |
| 322 | ||
| 323 | try test__powidf2(inf_f64, -1, 0); | |
| 324 | try test__powidf2(inf_f64, -2, 0); | |
| 325 | try test__powidf2(inf_f64, -3, 0); | |
| 326 | try test__powidf2(inf_f64, -4, 0); | |
| 327 | try test__powidf2(inf_f64, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); | |
| 328 | try test__powidf2(inf_f64, @as(i32, @bitCast(@as(u32, 0x80000001))), 0); | |
| 329 | try test__powidf2(inf_f64, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); | |
| 330 | ||
| 331 | try test__powidf2(-inf_f64, -1, -0.0); | |
| 332 | try test__powidf2(-inf_f64, -2, 0); | |
| 333 | try test__powidf2(-inf_f64, -3, -0.0); | |
| 334 | try test__powidf2(-inf_f64, -4, 0); | |
| 335 | try test__powidf2(-inf_f64, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); | |
| 336 | try test__powidf2(-inf_f64, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0); | |
| 337 | try test__powidf2(-inf_f64, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); | |
| 338 | ||
| 339 | try test__powidf2(2, 10, 1024.0); | |
| 340 | try test__powidf2(-2, 10, 1024.0); | |
| 341 | try test__powidf2(2, -10, 1.0 / 1024.0); | |
| 342 | try test__powidf2(-2, -10, 1.0 / 1024.0); | |
| 343 | ||
| 344 | try test__powidf2(2, 19, 524288.0); | |
| 345 | try test__powidf2(-2, 19, -524288.0); | |
| 346 | try test__powidf2(2, -19, 1.0 / 524288.0); | |
| 347 | try test__powidf2(-2, -19, -1.0 / 524288.0); | |
| 348 | ||
| 349 | try test__powidf2(2, 31, 2147483648.0); | |
| 350 | try test__powidf2(-2, 31, -2147483648.0); | |
| 351 | try test__powidf2(2, -31, 1.0 / 2147483648.0); | |
| 352 | try test__powidf2(-2, -31, -1.0 / 2147483648.0); | |
| 258 | try test_powi_f64(0, 0, 1); | |
| 259 | try test_powi_f64(1, 0, 1); | |
| 260 | try test_powi_f64(1.5, 0, 1); | |
| 261 | try test_powi_f64(2, 0, 1); | |
| 262 | try test_powi_f64(inf_f64, 0, 1); | |
| 263 | ||
| 264 | try test_powi_f64(-0.0, 0, 1); | |
| 265 | try test_powi_f64(-1, 0, 1); | |
| 266 | try test_powi_f64(-1.5, 0, 1); | |
| 267 | try test_powi_f64(-2, 0, 1); | |
| 268 | try test_powi_f64(-inf_f64, 0, 1); | |
| 269 | ||
| 270 | try test_powi_f64(0, 1, 0); | |
| 271 | try test_powi_f64(0, 2, 0); | |
| 272 | try test_powi_f64(0, 3, 0); | |
| 273 | try test_powi_f64(0, 4, 0); | |
| 274 | try test_powi_f64(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); | |
| 275 | try test_powi_f64(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0); | |
| 276 | ||
| 277 | try test_powi_f64(-0.0, 1, -0.0); | |
| 278 | try test_powi_f64(-0.0, 2, 0); | |
| 279 | try test_powi_f64(-0.0, 3, -0.0); | |
| 280 | try test_powi_f64(-0.0, 4, 0); | |
| 281 | try test_powi_f64(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); | |
| 282 | try test_powi_f64(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0); | |
| 283 | ||
| 284 | try test_powi_f64(1, 1, 1); | |
| 285 | try test_powi_f64(1, 2, 1); | |
| 286 | try test_powi_f64(1, 3, 1); | |
| 287 | try test_powi_f64(1, 4, 1); | |
| 288 | try test_powi_f64(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1); | |
| 289 | try test_powi_f64(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1); | |
| 290 | ||
| 291 | try test_powi_f64(inf_f64, 1, inf_f64); | |
| 292 | try test_powi_f64(inf_f64, 2, inf_f64); | |
| 293 | try test_powi_f64(inf_f64, 3, inf_f64); | |
| 294 | try test_powi_f64(inf_f64, 4, inf_f64); | |
| 295 | try test_powi_f64(inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f64); | |
| 296 | try test_powi_f64(inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f64); | |
| 297 | ||
| 298 | try test_powi_f64(-inf_f64, 1, -inf_f64); | |
| 299 | try test_powi_f64(-inf_f64, 2, inf_f64); | |
| 300 | try test_powi_f64(-inf_f64, 3, -inf_f64); | |
| 301 | try test_powi_f64(-inf_f64, 4, inf_f64); | |
| 302 | try test_powi_f64(-inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f64); | |
| 303 | try test_powi_f64(-inf_f64, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f64); | |
| 304 | ||
| 305 | try test_powi_f64(0, -1, inf_f64); | |
| 306 | try test_powi_f64(0, -2, inf_f64); | |
| 307 | try test_powi_f64(0, -3, inf_f64); | |
| 308 | try test_powi_f64(0, -4, inf_f64); | |
| 309 | try test_powi_f64(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f64); | |
| 310 | try test_powi_f64(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f64); | |
| 311 | try test_powi_f64(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f64); | |
| 312 | ||
| 313 | try test_powi_f64(-0.0, -1, -inf_f64); | |
| 314 | try test_powi_f64(-0.0, -2, inf_f64); | |
| 315 | try test_powi_f64(-0.0, -3, -inf_f64); | |
| 316 | try test_powi_f64(-0.0, -4, inf_f64); | |
| 317 | try test_powi_f64(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f64); | |
| 318 | try test_powi_f64(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f64); | |
| 319 | try test_powi_f64(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f64); | |
| 320 | ||
| 321 | try test_powi_f64(1, -1, 1); | |
| 322 | try test_powi_f64(1, -2, 1); | |
| 323 | try test_powi_f64(1, -3, 1); | |
| 324 | try test_powi_f64(1, -4, 1); | |
| 325 | try test_powi_f64(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1); | |
| 326 | try test_powi_f64(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1); | |
| 327 | try test_powi_f64(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1); | |
| 328 | ||
| 329 | try test_powi_f64(inf_f64, -1, 0); | |
| 330 | try test_powi_f64(inf_f64, -2, 0); | |
| 331 | try test_powi_f64(inf_f64, -3, 0); | |
| 332 | try test_powi_f64(inf_f64, -4, 0); | |
| 333 | try test_powi_f64(inf_f64, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); | |
| 334 | try test_powi_f64(inf_f64, @as(i32, @bitCast(@as(u32, 0x80000001))), 0); | |
| 335 | try test_powi_f64(inf_f64, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); | |
| 336 | ||
| 337 | try test_powi_f64(-inf_f64, -1, -0.0); | |
| 338 | try test_powi_f64(-inf_f64, -2, 0); | |
| 339 | try test_powi_f64(-inf_f64, -3, -0.0); | |
| 340 | try test_powi_f64(-inf_f64, -4, 0); | |
| 341 | try test_powi_f64(-inf_f64, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); | |
| 342 | try test_powi_f64(-inf_f64, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0); | |
| 343 | try test_powi_f64(-inf_f64, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); | |
| 344 | ||
| 345 | try test_powi_f64(2, 10, 1024.0); | |
| 346 | try test_powi_f64(-2, 10, 1024.0); | |
| 347 | try test_powi_f64(2, -10, 1.0 / 1024.0); | |
| 348 | try test_powi_f64(-2, -10, 1.0 / 1024.0); | |
| 349 | ||
| 350 | try test_powi_f64(2, 19, 524288.0); | |
| 351 | try test_powi_f64(-2, 19, -524288.0); | |
| 352 | try test_powi_f64(2, -19, 1.0 / 524288.0); | |
| 353 | try test_powi_f64(-2, -19, -1.0 / 524288.0); | |
| 354 | ||
| 355 | try test_powi_f64(2, 31, 2147483648.0); | |
| 356 | try test_powi_f64(-2, 31, -2147483648.0); | |
| 357 | try test_powi_f64(2, -31, 1.0 / 2147483648.0); | |
| 358 | try test_powi_f64(-2, -31, -1.0 / 2147483648.0); | |
| 353 | 359 | } |
| 354 | 360 | |
| 355 | test "powitf2" { | |
| 356 | const inf_f128 = math.inf(f128); | |
| 357 | try test__powitf2(0, 0, 1); | |
| 358 | try test__powitf2(1, 0, 1); | |
| 359 | try test__powitf2(1.5, 0, 1); | |
| 360 | try test__powitf2(2, 0, 1); | |
| 361 | try test__powitf2(inf_f128, 0, 1); | |
| 362 | ||
| 363 | try test__powitf2(-0.0, 0, 1); | |
| 364 | try test__powitf2(-1, 0, 1); | |
| 365 | try test__powitf2(-1.5, 0, 1); | |
| 366 | try test__powitf2(-2, 0, 1); | |
| 367 | try test__powitf2(-inf_f128, 0, 1); | |
| 368 | ||
| 369 | try test__powitf2(0, 1, 0); | |
| 370 | try test__powitf2(0, 2, 0); | |
| 371 | try test__powitf2(0, 3, 0); | |
| 372 | try test__powitf2(0, 4, 0); | |
| 373 | try test__powitf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); | |
| 374 | try test__powitf2(0, 0x7FFFFFFF, 0); | |
| 375 | ||
| 376 | try test__powitf2(-0.0, 1, -0.0); | |
| 377 | try test__powitf2(-0.0, 2, 0); | |
| 378 | try test__powitf2(-0.0, 3, -0.0); | |
| 379 | try test__powitf2(-0.0, 4, 0); | |
| 380 | try test__powitf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); | |
| 381 | try test__powitf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0); | |
| 382 | ||
| 383 | try test__powitf2(1, 1, 1); | |
| 384 | try test__powitf2(1, 2, 1); | |
| 385 | try test__powitf2(1, 3, 1); | |
| 386 | try test__powitf2(1, 4, 1); | |
| 387 | try test__powitf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1); | |
| 388 | try test__powitf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1); | |
| 389 | ||
| 390 | try test__powitf2(inf_f128, 1, inf_f128); | |
| 391 | try test__powitf2(inf_f128, 2, inf_f128); | |
| 392 | try test__powitf2(inf_f128, 3, inf_f128); | |
| 393 | try test__powitf2(inf_f128, 4, inf_f128); | |
| 394 | try test__powitf2(inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f128); | |
| 395 | try test__powitf2(inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f128); | |
| 396 | ||
| 397 | try test__powitf2(-inf_f128, 1, -inf_f128); | |
| 398 | try test__powitf2(-inf_f128, 2, inf_f128); | |
| 399 | try test__powitf2(-inf_f128, 3, -inf_f128); | |
| 400 | try test__powitf2(-inf_f128, 4, inf_f128); | |
| 401 | try test__powitf2(-inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f128); | |
| 402 | try test__powitf2(-inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f128); | |
| 403 | ||
| 404 | try test__powitf2(0, -1, inf_f128); | |
| 405 | try test__powitf2(0, -2, inf_f128); | |
| 406 | try test__powitf2(0, -3, inf_f128); | |
| 407 | try test__powitf2(0, -4, inf_f128); | |
| 408 | try test__powitf2(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f128); | |
| 409 | try test__powitf2(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f128); | |
| 410 | try test__powitf2(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f128); | |
| 411 | ||
| 412 | try test__powitf2(-0.0, -1, -inf_f128); | |
| 413 | try test__powitf2(-0.0, -2, inf_f128); | |
| 414 | try test__powitf2(-0.0, -3, -inf_f128); | |
| 415 | try test__powitf2(-0.0, -4, inf_f128); | |
| 416 | try test__powitf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f128); | |
| 417 | try test__powitf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f128); | |
| 418 | try test__powitf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f128); | |
| 419 | ||
| 420 | try test__powitf2(1, -1, 1); | |
| 421 | try test__powitf2(1, -2, 1); | |
| 422 | try test__powitf2(1, -3, 1); | |
| 423 | try test__powitf2(1, -4, 1); | |
| 424 | try test__powitf2(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1); | |
| 425 | try test__powitf2(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1); | |
| 426 | try test__powitf2(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1); | |
| 427 | ||
| 428 | try test__powitf2(inf_f128, -1, 0); | |
| 429 | try test__powitf2(inf_f128, -2, 0); | |
| 430 | try test__powitf2(inf_f128, -3, 0); | |
| 431 | try test__powitf2(inf_f128, -4, 0); | |
| 432 | try test__powitf2(inf_f128, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); | |
| 433 | try test__powitf2(inf_f128, @as(i32, @bitCast(@as(u32, 0x80000001))), 0); | |
| 434 | try test__powitf2(inf_f128, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); | |
| 435 | ||
| 436 | try test__powitf2(-inf_f128, -1, -0.0); | |
| 437 | try test__powitf2(-inf_f128, -2, 0); | |
| 438 | try test__powitf2(-inf_f128, -3, -0.0); | |
| 439 | try test__powitf2(-inf_f128, -4, 0); | |
| 440 | try test__powitf2(-inf_f128, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); | |
| 441 | try test__powitf2(-inf_f128, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0); | |
| 442 | try test__powitf2(-inf_f128, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); | |
| 443 | ||
| 444 | try test__powitf2(2, 10, 1024.0); | |
| 445 | try test__powitf2(-2, 10, 1024.0); | |
| 446 | try test__powitf2(2, -10, 1.0 / 1024.0); | |
| 447 | try test__powitf2(-2, -10, 1.0 / 1024.0); | |
| 448 | ||
| 449 | try test__powitf2(2, 19, 524288.0); | |
| 450 | try test__powitf2(-2, 19, -524288.0); | |
| 451 | try test__powitf2(2, -19, 1.0 / 524288.0); | |
| 452 | try test__powitf2(-2, -19, -1.0 / 524288.0); | |
| 453 | ||
| 454 | try test__powitf2(2, 31, 2147483648.0); | |
| 455 | try test__powitf2(-2, 31, -2147483648.0); | |
| 456 | try test__powitf2(2, -31, 1.0 / 2147483648.0); | |
| 457 | try test__powitf2(-2, -31, -1.0 / 2147483648.0); | |
| 361 | test powi_f80 { | |
| 362 | const inf_f80 = math.inf(f80); | |
| 363 | try test_powi_f80(0, 0, 1); | |
| 364 | try test_powi_f80(1, 0, 1); | |
| 365 | try test_powi_f80(1.5, 0, 1); | |
| 366 | try test_powi_f80(2, 0, 1); | |
| 367 | try test_powi_f80(inf_f80, 0, 1); | |
| 368 | ||
| 369 | try test_powi_f80(-0.0, 0, 1); | |
| 370 | try test_powi_f80(-1, 0, 1); | |
| 371 | try test_powi_f80(-1.5, 0, 1); | |
| 372 | try test_powi_f80(-2, 0, 1); | |
| 373 | try test_powi_f80(-inf_f80, 0, 1); | |
| 374 | ||
| 375 | try test_powi_f80(0, 1, 0); | |
| 376 | try test_powi_f80(0, 2, 0); | |
| 377 | try test_powi_f80(0, 3, 0); | |
| 378 | try test_powi_f80(0, 4, 0); | |
| 379 | try test_powi_f80(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); | |
| 380 | try test_powi_f80(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0); | |
| 381 | ||
| 382 | try test_powi_f80(-0.0, 1, -0.0); | |
| 383 | try test_powi_f80(-0.0, 2, 0); | |
| 384 | try test_powi_f80(-0.0, 3, -0.0); | |
| 385 | try test_powi_f80(-0.0, 4, 0); | |
| 386 | try test_powi_f80(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); | |
| 387 | try test_powi_f80(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0); | |
| 388 | ||
| 389 | try test_powi_f80(1, 1, 1); | |
| 390 | try test_powi_f80(1, 2, 1); | |
| 391 | try test_powi_f80(1, 3, 1); | |
| 392 | try test_powi_f80(1, 4, 1); | |
| 393 | try test_powi_f80(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1); | |
| 394 | try test_powi_f80(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1); | |
| 395 | ||
| 396 | try test_powi_f80(inf_f80, 1, inf_f80); | |
| 397 | try test_powi_f80(inf_f80, 2, inf_f80); | |
| 398 | try test_powi_f80(inf_f80, 3, inf_f80); | |
| 399 | try test_powi_f80(inf_f80, 4, inf_f80); | |
| 400 | try test_powi_f80(inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f80); | |
| 401 | try test_powi_f80(inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f80); | |
| 402 | ||
| 403 | try test_powi_f80(-inf_f80, 1, -inf_f80); | |
| 404 | try test_powi_f80(-inf_f80, 2, inf_f80); | |
| 405 | try test_powi_f80(-inf_f80, 3, -inf_f80); | |
| 406 | try test_powi_f80(-inf_f80, 4, inf_f80); | |
| 407 | try test_powi_f80(-inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f80); | |
| 408 | try test_powi_f80(-inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f80); | |
| 409 | ||
| 410 | try test_powi_f80(0, -1, inf_f80); | |
| 411 | try test_powi_f80(0, -2, inf_f80); | |
| 412 | try test_powi_f80(0, -3, inf_f80); | |
| 413 | try test_powi_f80(0, -4, inf_f80); | |
| 414 | try test_powi_f80(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f80); | |
| 415 | try test_powi_f80(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f80); | |
| 416 | try test_powi_f80(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f80); | |
| 417 | ||
| 418 | try test_powi_f80(-0.0, -1, -inf_f80); | |
| 419 | try test_powi_f80(-0.0, -2, inf_f80); | |
| 420 | try test_powi_f80(-0.0, -3, -inf_f80); | |
| 421 | try test_powi_f80(-0.0, -4, inf_f80); | |
| 422 | try test_powi_f80(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f80); | |
| 423 | try test_powi_f80(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f80); | |
| 424 | try test_powi_f80(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f80); | |
| 425 | ||
| 426 | try test_powi_f80(1, -1, 1); | |
| 427 | try test_powi_f80(1, -2, 1); | |
| 428 | try test_powi_f80(1, -3, 1); | |
| 429 | try test_powi_f80(1, -4, 1); | |
| 430 | try test_powi_f80(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1); | |
| 431 | try test_powi_f80(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1); | |
| 432 | try test_powi_f80(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1); | |
| 433 | ||
| 434 | try test_powi_f80(inf_f80, -1, 0); | |
| 435 | try test_powi_f80(inf_f80, -2, 0); | |
| 436 | try test_powi_f80(inf_f80, -3, 0); | |
| 437 | try test_powi_f80(inf_f80, -4, 0); | |
| 438 | try test_powi_f80(inf_f80, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); | |
| 439 | try test_powi_f80(inf_f80, @as(i32, @bitCast(@as(u32, 0x80000001))), 0); | |
| 440 | try test_powi_f80(inf_f80, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); | |
| 441 | ||
| 442 | try test_powi_f80(-inf_f80, -1, -0.0); | |
| 443 | try test_powi_f80(-inf_f80, -2, 0); | |
| 444 | try test_powi_f80(-inf_f80, -3, -0.0); | |
| 445 | try test_powi_f80(-inf_f80, -4, 0); | |
| 446 | try test_powi_f80(-inf_f80, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); | |
| 447 | try test_powi_f80(-inf_f80, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0); | |
| 448 | try test_powi_f80(-inf_f80, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); | |
| 449 | ||
| 450 | try test_powi_f80(2, 10, 1024.0); | |
| 451 | try test_powi_f80(-2, 10, 1024.0); | |
| 452 | try test_powi_f80(2, -10, 1.0 / 1024.0); | |
| 453 | try test_powi_f80(-2, -10, 1.0 / 1024.0); | |
| 454 | ||
| 455 | try test_powi_f80(2, 19, 524288.0); | |
| 456 | try test_powi_f80(-2, 19, -524288.0); | |
| 457 | try test_powi_f80(2, -19, 1.0 / 524288.0); | |
| 458 | try test_powi_f80(-2, -19, -1.0 / 524288.0); | |
| 459 | ||
| 460 | try test_powi_f80(2, 31, 2147483648.0); | |
| 461 | try test_powi_f80(-2, 31, -2147483648.0); | |
| 462 | try test_powi_f80(2, -31, 1.0 / 2147483648.0); | |
| 463 | try test_powi_f80(-2, -31, -1.0 / 2147483648.0); | |
| 458 | 464 | } |
| 459 | 465 | |
| 460 | test "powixf2" { | |
| 461 | const inf_f80 = math.inf(f80); | |
| 462 | try test__powixf2(0, 0, 1); | |
| 463 | try test__powixf2(1, 0, 1); | |
| 464 | try test__powixf2(1.5, 0, 1); | |
| 465 | try test__powixf2(2, 0, 1); | |
| 466 | try test__powixf2(inf_f80, 0, 1); | |
| 467 | ||
| 468 | try test__powixf2(-0.0, 0, 1); | |
| 469 | try test__powixf2(-1, 0, 1); | |
| 470 | try test__powixf2(-1.5, 0, 1); | |
| 471 | try test__powixf2(-2, 0, 1); | |
| 472 | try test__powixf2(-inf_f80, 0, 1); | |
| 473 | ||
| 474 | try test__powixf2(0, 1, 0); | |
| 475 | try test__powixf2(0, 2, 0); | |
| 476 | try test__powixf2(0, 3, 0); | |
| 477 | try test__powixf2(0, 4, 0); | |
| 478 | try test__powixf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); | |
| 479 | try test__powixf2(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 0); | |
| 480 | ||
| 481 | try test__powixf2(-0.0, 1, -0.0); | |
| 482 | try test__powixf2(-0.0, 2, 0); | |
| 483 | try test__powixf2(-0.0, 3, -0.0); | |
| 484 | try test__powixf2(-0.0, 4, 0); | |
| 485 | try test__powixf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); | |
| 486 | try test__powixf2(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0); | |
| 487 | ||
| 488 | try test__powixf2(1, 1, 1); | |
| 489 | try test__powixf2(1, 2, 1); | |
| 490 | try test__powixf2(1, 3, 1); | |
| 491 | try test__powixf2(1, 4, 1); | |
| 492 | try test__powixf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1); | |
| 493 | try test__powixf2(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1); | |
| 494 | ||
| 495 | try test__powixf2(inf_f80, 1, inf_f80); | |
| 496 | try test__powixf2(inf_f80, 2, inf_f80); | |
| 497 | try test__powixf2(inf_f80, 3, inf_f80); | |
| 498 | try test__powixf2(inf_f80, 4, inf_f80); | |
| 499 | try test__powixf2(inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f80); | |
| 500 | try test__powixf2(inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f80); | |
| 501 | ||
| 502 | try test__powixf2(-inf_f80, 1, -inf_f80); | |
| 503 | try test__powixf2(-inf_f80, 2, inf_f80); | |
| 504 | try test__powixf2(-inf_f80, 3, -inf_f80); | |
| 505 | try test__powixf2(-inf_f80, 4, inf_f80); | |
| 506 | try test__powixf2(-inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f80); | |
| 507 | try test__powixf2(-inf_f80, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f80); | |
| 508 | ||
| 509 | try test__powixf2(0, -1, inf_f80); | |
| 510 | try test__powixf2(0, -2, inf_f80); | |
| 511 | try test__powixf2(0, -3, inf_f80); | |
| 512 | try test__powixf2(0, -4, inf_f80); | |
| 513 | try test__powixf2(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f80); | |
| 514 | try test__powixf2(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f80); | |
| 515 | try test__powixf2(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f80); | |
| 516 | ||
| 517 | try test__powixf2(-0.0, -1, -inf_f80); | |
| 518 | try test__powixf2(-0.0, -2, inf_f80); | |
| 519 | try test__powixf2(-0.0, -3, -inf_f80); | |
| 520 | try test__powixf2(-0.0, -4, inf_f80); | |
| 521 | try test__powixf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f80); | |
| 522 | try test__powixf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f80); | |
| 523 | try test__powixf2(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f80); | |
| 524 | ||
| 525 | try test__powixf2(1, -1, 1); | |
| 526 | try test__powixf2(1, -2, 1); | |
| 527 | try test__powixf2(1, -3, 1); | |
| 528 | try test__powixf2(1, -4, 1); | |
| 529 | try test__powixf2(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1); | |
| 530 | try test__powixf2(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1); | |
| 531 | try test__powixf2(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1); | |
| 532 | ||
| 533 | try test__powixf2(inf_f80, -1, 0); | |
| 534 | try test__powixf2(inf_f80, -2, 0); | |
| 535 | try test__powixf2(inf_f80, -3, 0); | |
| 536 | try test__powixf2(inf_f80, -4, 0); | |
| 537 | try test__powixf2(inf_f80, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); | |
| 538 | try test__powixf2(inf_f80, @as(i32, @bitCast(@as(u32, 0x80000001))), 0); | |
| 539 | try test__powixf2(inf_f80, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); | |
| 540 | ||
| 541 | try test__powixf2(-inf_f80, -1, -0.0); | |
| 542 | try test__powixf2(-inf_f80, -2, 0); | |
| 543 | try test__powixf2(-inf_f80, -3, -0.0); | |
| 544 | try test__powixf2(-inf_f80, -4, 0); | |
| 545 | try test__powixf2(-inf_f80, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); | |
| 546 | try test__powixf2(-inf_f80, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0); | |
| 547 | try test__powixf2(-inf_f80, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); | |
| 548 | ||
| 549 | try test__powixf2(2, 10, 1024.0); | |
| 550 | try test__powixf2(-2, 10, 1024.0); | |
| 551 | try test__powixf2(2, -10, 1.0 / 1024.0); | |
| 552 | try test__powixf2(-2, -10, 1.0 / 1024.0); | |
| 553 | ||
| 554 | try test__powixf2(2, 19, 524288.0); | |
| 555 | try test__powixf2(-2, 19, -524288.0); | |
| 556 | try test__powixf2(2, -19, 1.0 / 524288.0); | |
| 557 | try test__powixf2(-2, -19, -1.0 / 524288.0); | |
| 558 | ||
| 559 | try test__powixf2(2, 31, 2147483648.0); | |
| 560 | try test__powixf2(-2, 31, -2147483648.0); | |
| 561 | try test__powixf2(2, -31, 1.0 / 2147483648.0); | |
| 562 | try test__powixf2(-2, -31, -1.0 / 2147483648.0); | |
| 466 | test powi_f128 { | |
| 467 | const inf_f128 = math.inf(f128); | |
| 468 | try test_powi_f128(0, 0, 1); | |
| 469 | try test_powi_f128(1, 0, 1); | |
| 470 | try test_powi_f128(1.5, 0, 1); | |
| 471 | try test_powi_f128(2, 0, 1); | |
| 472 | try test_powi_f128(inf_f128, 0, 1); | |
| 473 | ||
| 474 | try test_powi_f128(-0.0, 0, 1); | |
| 475 | try test_powi_f128(-1, 0, 1); | |
| 476 | try test_powi_f128(-1.5, 0, 1); | |
| 477 | try test_powi_f128(-2, 0, 1); | |
| 478 | try test_powi_f128(-inf_f128, 0, 1); | |
| 479 | ||
| 480 | try test_powi_f128(0, 1, 0); | |
| 481 | try test_powi_f128(0, 2, 0); | |
| 482 | try test_powi_f128(0, 3, 0); | |
| 483 | try test_powi_f128(0, 4, 0); | |
| 484 | try test_powi_f128(0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); | |
| 485 | try test_powi_f128(0, 0x7FFFFFFF, 0); | |
| 486 | ||
| 487 | try test_powi_f128(-0.0, 1, -0.0); | |
| 488 | try test_powi_f128(-0.0, 2, 0); | |
| 489 | try test_powi_f128(-0.0, 3, -0.0); | |
| 490 | try test_powi_f128(-0.0, 4, 0); | |
| 491 | try test_powi_f128(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 0); | |
| 492 | try test_powi_f128(-0.0, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -0.0); | |
| 493 | ||
| 494 | try test_powi_f128(1, 1, 1); | |
| 495 | try test_powi_f128(1, 2, 1); | |
| 496 | try test_powi_f128(1, 3, 1); | |
| 497 | try test_powi_f128(1, 4, 1); | |
| 498 | try test_powi_f128(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), 1); | |
| 499 | try test_powi_f128(1, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), 1); | |
| 500 | ||
| 501 | try test_powi_f128(inf_f128, 1, inf_f128); | |
| 502 | try test_powi_f128(inf_f128, 2, inf_f128); | |
| 503 | try test_powi_f128(inf_f128, 3, inf_f128); | |
| 504 | try test_powi_f128(inf_f128, 4, inf_f128); | |
| 505 | try test_powi_f128(inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f128); | |
| 506 | try test_powi_f128(inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), inf_f128); | |
| 507 | ||
| 508 | try test_powi_f128(-inf_f128, 1, -inf_f128); | |
| 509 | try test_powi_f128(-inf_f128, 2, inf_f128); | |
| 510 | try test_powi_f128(-inf_f128, 3, -inf_f128); | |
| 511 | try test_powi_f128(-inf_f128, 4, inf_f128); | |
| 512 | try test_powi_f128(-inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFE))), inf_f128); | |
| 513 | try test_powi_f128(-inf_f128, @as(i32, @bitCast(@as(u32, 0x7FFFFFFF))), -inf_f128); | |
| 514 | ||
| 515 | try test_powi_f128(0, -1, inf_f128); | |
| 516 | try test_powi_f128(0, -2, inf_f128); | |
| 517 | try test_powi_f128(0, -3, inf_f128); | |
| 518 | try test_powi_f128(0, -4, inf_f128); | |
| 519 | try test_powi_f128(0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f128); | |
| 520 | try test_powi_f128(0, @as(i32, @bitCast(@as(u32, 0x80000001))), inf_f128); | |
| 521 | try test_powi_f128(0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f128); | |
| 522 | ||
| 523 | try test_powi_f128(-0.0, -1, -inf_f128); | |
| 524 | try test_powi_f128(-0.0, -2, inf_f128); | |
| 525 | try test_powi_f128(-0.0, -3, -inf_f128); | |
| 526 | try test_powi_f128(-0.0, -4, inf_f128); | |
| 527 | try test_powi_f128(-0.0, @as(i32, @bitCast(@as(u32, 0x80000002))), inf_f128); | |
| 528 | try test_powi_f128(-0.0, @as(i32, @bitCast(@as(u32, 0x80000001))), -inf_f128); | |
| 529 | try test_powi_f128(-0.0, @as(i32, @bitCast(@as(u32, 0x80000000))), inf_f128); | |
| 530 | ||
| 531 | try test_powi_f128(1, -1, 1); | |
| 532 | try test_powi_f128(1, -2, 1); | |
| 533 | try test_powi_f128(1, -3, 1); | |
| 534 | try test_powi_f128(1, -4, 1); | |
| 535 | try test_powi_f128(1, @as(i32, @bitCast(@as(u32, 0x80000002))), 1); | |
| 536 | try test_powi_f128(1, @as(i32, @bitCast(@as(u32, 0x80000001))), 1); | |
| 537 | try test_powi_f128(1, @as(i32, @bitCast(@as(u32, 0x80000000))), 1); | |
| 538 | ||
| 539 | try test_powi_f128(inf_f128, -1, 0); | |
| 540 | try test_powi_f128(inf_f128, -2, 0); | |
| 541 | try test_powi_f128(inf_f128, -3, 0); | |
| 542 | try test_powi_f128(inf_f128, -4, 0); | |
| 543 | try test_powi_f128(inf_f128, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); | |
| 544 | try test_powi_f128(inf_f128, @as(i32, @bitCast(@as(u32, 0x80000001))), 0); | |
| 545 | try test_powi_f128(inf_f128, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); | |
| 546 | ||
| 547 | try test_powi_f128(-inf_f128, -1, -0.0); | |
| 548 | try test_powi_f128(-inf_f128, -2, 0); | |
| 549 | try test_powi_f128(-inf_f128, -3, -0.0); | |
| 550 | try test_powi_f128(-inf_f128, -4, 0); | |
| 551 | try test_powi_f128(-inf_f128, @as(i32, @bitCast(@as(u32, 0x80000002))), 0); | |
| 552 | try test_powi_f128(-inf_f128, @as(i32, @bitCast(@as(u32, 0x80000001))), -0.0); | |
| 553 | try test_powi_f128(-inf_f128, @as(i32, @bitCast(@as(u32, 0x80000000))), 0); | |
| 554 | ||
| 555 | try test_powi_f128(2, 10, 1024.0); | |
| 556 | try test_powi_f128(-2, 10, 1024.0); | |
| 557 | try test_powi_f128(2, -10, 1.0 / 1024.0); | |
| 558 | try test_powi_f128(-2, -10, 1.0 / 1024.0); | |
| 559 | ||
| 560 | try test_powi_f128(2, 19, 524288.0); | |
| 561 | try test_powi_f128(-2, 19, -524288.0); | |
| 562 | try test_powi_f128(2, -19, 1.0 / 524288.0); | |
| 563 | try test_powi_f128(-2, -19, -1.0 / 524288.0); | |
| 564 | ||
| 565 | try test_powi_f128(2, 31, 2147483648.0); | |
| 566 | try test_powi_f128(-2, 31, -2147483648.0); | |
| 567 | try test_powi_f128(2, -31, 1.0 / 2147483648.0); | |
| 568 | try test_powi_f128(-2, -31, -1.0 / 2147483648.0); | |
| 563 | 569 | } |
lib/compiler_rt/round.zig+87-50| ... | ... | @@ -18,19 +18,22 @@ comptime { |
| 18 | 18 | symbol(&roundf, "roundf"); |
| 19 | 19 | symbol(&round, "round"); |
| 20 | 20 | symbol(&__roundx, "__roundx"); |
| 21 | if (compiler_rt.want_ppc_abi) { | |
| 22 | symbol(&roundq, "roundf128"); | |
| 23 | } | |
| 24 | symbol(&roundq, "roundq"); | |
| 21 | symbol(&roundq, "roundf128"); | |
| 25 | 22 | symbol(&roundl, "roundl"); |
| 26 | 23 | } |
| 27 | 24 | |
| 28 | pub fn __roundh(x: f16) callconv(.c) f16 { | |
| 25 | fn __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 | } | |
| 28 | pub fn round_f16(x: f16) f16 { | |
| 29 | 29 | // TODO: more efficient implementation |
| 30 | return @floatCast(roundf(x)); | |
| 30 | return @floatCast(round_f32(x)); | |
| 31 | 31 | } |
| 32 | 32 | |
| 33 | pub fn roundf(x_: f32) callconv(.c) f32 { | |
| 33 | fn 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 | } | |
| 36 | pub fn round_f32(x_: f32) f32 { | |
| 34 | 37 | const f32_toint = 1.0 / math.floatEps(f32); |
| 35 | 38 | |
| 36 | 39 | var x = x_; |
| ... | ... | @@ -65,7 +68,10 @@ pub fn roundf(x_: f32) callconv(.c) f32 { |
| 65 | 68 | } |
| 66 | 69 | } |
| 67 | 70 | |
| 68 | pub fn round(x_: f64) callconv(.c) f64 { | |
| 71 | fn 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 | } | |
| 74 | pub fn round_f64(x_: f64) f64 { | |
| 69 | 75 | const f64_toint = 1.0 / math.floatEps(f64); |
| 70 | 76 | |
| 71 | 77 | var x = x_; |
| ... | ... | @@ -100,12 +106,18 @@ pub fn round(x_: f64) callconv(.c) f64 { |
| 100 | 106 | } |
| 101 | 107 | } |
| 102 | 108 | |
| 103 | pub fn __roundx(x: f80) callconv(.c) f80 { | |
| 109 | fn __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 | } | |
| 112 | pub fn round_f80(x: f80) f80 { | |
| 104 | 113 | // TODO: more efficient implementation |
| 105 | return @floatCast(roundq(x)); | |
| 114 | return @floatCast(round_f128(x)); | |
| 106 | 115 | } |
| 107 | 116 | |
| 108 | pub fn roundq(x_: f128) callconv(.c) f128 { | |
| 117 | fn 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 | } | |
| 120 | pub fn round_f128(x_: f128) f128 { | |
| 109 | 121 | const f128_toint = 1.0 / math.floatEps(f128); |
| 110 | 122 | |
| 111 | 123 | var x = x_; |
| ... | ... | @@ -142,54 +154,79 @@ pub fn roundq(x_: f128) callconv(.c) f128 { |
| 142 | 154 | |
| 143 | 155 | pub fn roundl(x: c_longdouble) callconv(.c) c_longdouble { |
| 144 | 156 | switch (@typeInfo(c_longdouble).float.bits) { |
| 145 | 64 => return round(x), | |
| 146 | 80 => return __roundx(x), | |
| 147 | 128 => return roundq(x), | |
| 148 | else => @compileError("unreachable"), | |
| 157 | 64 => return round_f64(x), | |
| 158 | 80 => return round_f80(x), | |
| 159 | 128 => return round_f128(x), | |
| 160 | else => comptime unreachable, | |
| 149 | 161 | } |
| 150 | 162 | } |
| 151 | 163 | |
| 152 | test "round32" { | |
| 153 | try expect(roundf(1.3) == 1.0); | |
| 154 | try expect(roundf(-1.3) == -1.0); | |
| 155 | try expect(roundf(0.2) == 0.0); | |
| 156 | try expect(roundf(1.8) == 2.0); | |
| 157 | } | |
| 158 | ||
| 159 | test "round64" { | |
| 160 | try expect(round(1.3) == 1.0); | |
| 161 | try expect(round(-1.3) == -1.0); | |
| 162 | try expect(round(0.2) == 0.0); | |
| 163 | try expect(round(1.8) == 2.0); | |
| 164 | test round_f16 { | |
| 165 | try expect(round_f16(1.3) == 1.0); | |
| 166 | try expect(round_f16(-1.3) == -1.0); | |
| 167 | try expect(round_f16(1.8) == 2.0); | |
| 168 | try expect(round_f16(-1.8) == -2.0); | |
| 169 | try expect(math.isPositiveZero(round_f16(0.2))); | |
| 170 | try expect(math.isNegativeZero(round_f16(-0.2))); | |
| 171 | try expect(math.isPositiveZero(round_f16(0.0))); | |
| 172 | try expect(math.isNegativeZero(round_f16(-0.0))); | |
| 173 | try expect(math.isPositiveInf(round_f16(math.inf(f32)))); | |
| 174 | try expect(math.isNegativeInf(round_f16(-math.inf(f32)))); | |
| 175 | try expect(math.isNan(round_f16(math.nan(f32)))); | |
| 164 | 176 | } |
| 165 | 177 | |
| 166 | test "round128" { | |
| 167 | try expect(roundq(1.3) == 1.0); | |
| 168 | try expect(roundq(-1.3) == -1.0); | |
| 169 | try expect(roundq(0.2) == 0.0); | |
| 170 | try expect(roundq(1.8) == 2.0); | |
| 178 | test round_f32 { | |
| 179 | try expect(round_f32(1.3) == 1.0); | |
| 180 | try expect(round_f32(-1.3) == -1.0); | |
| 181 | try expect(round_f32(1.8) == 2.0); | |
| 182 | try expect(round_f32(-1.8) == -2.0); | |
| 183 | try expect(math.isPositiveZero(round_f32(0.2))); | |
| 184 | try expect(math.isNegativeZero(round_f32(-0.2))); | |
| 185 | try expect(math.isPositiveZero(round_f32(0.0))); | |
| 186 | try expect(math.isNegativeZero(round_f32(-0.0))); | |
| 187 | try expect(math.isPositiveInf(round_f32(math.inf(f32)))); | |
| 188 | try expect(math.isNegativeInf(round_f32(-math.inf(f32)))); | |
| 189 | try expect(math.isNan(round_f32(math.nan(f32)))); | |
| 171 | 190 | } |
| 172 | 191 | |
| 173 | test "round32.special" { | |
| 174 | try expect(roundf(0.0) == 0.0); | |
| 175 | try expect(roundf(-0.0) == -0.0); | |
| 176 | try expect(math.isPositiveInf(roundf(math.inf(f32)))); | |
| 177 | try expect(math.isNegativeInf(roundf(-math.inf(f32)))); | |
| 178 | try expect(math.isNan(roundf(math.nan(f32)))); | |
| 192 | test round_f64 { | |
| 193 | try expect(round_f64(1.3) == 1.0); | |
| 194 | try expect(round_f64(-1.3) == -1.0); | |
| 195 | try expect(round_f64(1.8) == 2.0); | |
| 196 | try expect(round_f64(-1.8) == -2.0); | |
| 197 | try expect(math.isPositiveZero(round_f64(0.2))); | |
| 198 | try expect(math.isNegativeZero(round_f64(-0.2))); | |
| 199 | try expect(math.isPositiveZero(round_f64(0.0))); | |
| 200 | try expect(math.isNegativeZero(round_f64(-0.0))); | |
| 201 | try expect(math.isPositiveInf(round_f64(math.inf(f64)))); | |
| 202 | try expect(math.isNegativeInf(round_f64(-math.inf(f64)))); | |
| 203 | try expect(math.isNan(round_f64(math.nan(f64)))); | |
| 179 | 204 | } |
| 180 | 205 | |
| 181 | test "round64.special" { | |
| 182 | try expect(round(0.0) == 0.0); | |
| 183 | try expect(round(-0.0) == -0.0); | |
| 184 | try expect(math.isPositiveInf(round(math.inf(f64)))); | |
| 185 | try expect(math.isNegativeInf(round(-math.inf(f64)))); | |
| 186 | try expect(math.isNan(round(math.nan(f64)))); | |
| 206 | test round_f80 { | |
| 207 | try expect(round_f80(1.3) == 1.0); | |
| 208 | try expect(round_f80(-1.3) == -1.0); | |
| 209 | try expect(round_f80(1.8) == 2.0); | |
| 210 | try expect(round_f80(-1.8) == -2.0); | |
| 211 | try expect(math.isPositiveZero(round_f80(0.2))); | |
| 212 | try expect(math.isNegativeZero(round_f80(-0.2))); | |
| 213 | try expect(math.isPositiveZero(round_f80(0.0))); | |
| 214 | try expect(math.isNegativeZero(round_f80(-0.0))); | |
| 215 | try expect(math.isPositiveInf(round_f80(math.inf(f64)))); | |
| 216 | try expect(math.isNegativeInf(round_f80(-math.inf(f64)))); | |
| 217 | try expect(math.isNan(round_f80(math.nan(f64)))); | |
| 187 | 218 | } |
| 188 | 219 | |
| 189 | test "round128.special" { | |
| 190 | try expect(roundq(0.0) == 0.0); | |
| 191 | try expect(roundq(-0.0) == -0.0); | |
| 192 | try expect(math.isPositiveInf(roundq(math.inf(f128)))); | |
| 193 | try expect(math.isNegativeInf(roundq(-math.inf(f128)))); | |
| 194 | try expect(math.isNan(roundq(math.nan(f128)))); | |
| 220 | test round_f128 { | |
| 221 | try expect(round_f128(1.3) == 1.0); | |
| 222 | try expect(round_f128(-1.3) == -1.0); | |
| 223 | try expect(round_f128(1.8) == 2.0); | |
| 224 | try expect(round_f128(-1.8) == -2.0); | |
| 225 | try expect(math.isPositiveZero(round_f128(0.2))); | |
| 226 | try expect(math.isNegativeZero(round_f128(-0.2))); | |
| 227 | try expect(math.isPositiveZero(round_f128(0.0))); | |
| 228 | try expect(math.isNegativeZero(round_f128(-0.0))); | |
| 229 | try expect(math.isPositiveInf(round_f128(math.inf(f128)))); | |
| 230 | try expect(math.isNegativeInf(round_f128(-math.inf(f128)))); | |
| 231 | try expect(math.isNan(round_f128(math.nan(f128)))); | |
| 195 | 232 | } |
lib/compiler_rt/sin.zig+66-53| ... | ... | @@ -13,31 +13,34 @@ const expect = std.testing.expect; |
| 13 | 13 | const expectApproxEqAbs = std.testing.expectApproxEqAbs; |
| 14 | 14 | |
| 15 | 15 | const compiler_rt = @import("../compiler_rt.zig"); |
| 16 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 16 | const symbol = compiler_rt.symbol; | |
| 17 | 17 | const trig = @import("trig.zig"); |
| 18 | 18 | const rem_pio2 = @import("rem_pio2.zig").rem_pio2; |
| 19 | 19 | const rem_pio2f = @import("rem_pio2f.zig").rem_pio2f; |
| 20 | 20 | const rem_pio2l = @import("rem_pio2l.zig").rem_pio2l; |
| 21 | 21 | |
| 22 | 22 | comptime { |
| 23 | symbol(&sinh, "__sinh"); | |
| 24 | symbol(&sinl, "__sinl"); | |
| 23 | symbol(&__sinh, "__sinh"); | |
| 25 | 24 | symbol(&sinf, "sinf"); |
| 26 | 25 | symbol(&sin, "sin"); |
| 27 | symbol(&sinx, "__sinx"); | |
| 28 | if (compiler_rt.want_ppc_abi) { | |
| 29 | symbol(&sinq, "sinf128"); | |
| 30 | } | |
| 31 | symbol(&sinq, "sinq"); | |
| 26 | symbol(&__sinx, "__sinx"); | |
| 27 | symbol(&sinq, "sinf128"); | |
| 32 | 28 | symbol(&sinl, "sinl"); |
| 29 | symbol(&sinl, "__sinl"); // required by musl | |
| 33 | 30 | } |
| 34 | 31 | |
| 35 | pub fn sinh(x: f16) callconv(.c) f16 { | |
| 32 | fn __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 | } | |
| 35 | pub fn sin_f16(x: f16) f16 { | |
| 36 | 36 | // TODO: more efficient implementation |
| 37 | return @floatCast(sinf(x)); | |
| 37 | return @floatCast(sin_f32(x)); | |
| 38 | 38 | } |
| 39 | 39 | |
| 40 | pub fn sinf(x: f32) callconv(.c) f32 { | |
| 40 | fn 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 | } | |
| 43 | pub fn sin_f32(x: f32) f32 { | |
| 41 | 44 | // Small multiples of pi/2 rounded to double precision. |
| 42 | 45 | const s1pio2: f64 = 1.0 * math.pi / 2.0; // 0x3FF921FB, 0x54442D18 |
| 43 | 46 | const s2pio2: f64 = 2.0 * math.pi / 2.0; // 0x400921FB, 0x54442D18 |
| ... | ... | @@ -98,7 +101,10 @@ pub fn sinf(x: f32) callconv(.c) f32 { |
| 98 | 101 | }; |
| 99 | 102 | } |
| 100 | 103 | |
| 101 | pub fn sin(x: f64) callconv(.c) f64 { | |
| 104 | fn 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 | } | |
| 107 | pub fn sin_f64(x: f64) f64 { | |
| 102 | 108 | var ix = @as(u64, @bitCast(x)) >> 32; |
| 103 | 109 | ix &= 0x7fffffff; |
| 104 | 110 | |
| ... | ... | @@ -133,7 +139,10 @@ pub fn sin(x: f64) callconv(.c) f64 { |
| 133 | 139 | }; |
| 134 | 140 | } |
| 135 | 141 | |
| 136 | fn sinx(x: f80) callconv(.c) f80 { | |
| 142 | fn __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 | } | |
| 145 | pub fn sin_f80(x: f80) f80 { | |
| 137 | 146 | const se = ld.signExponent(x) & 0x7fff; |
| 138 | 147 | if (se == 0x7fff) { |
| 139 | 148 | return x - x; |
| ... | ... | @@ -160,7 +169,10 @@ fn sinx(x: f80) callconv(.c) f80 { |
| 160 | 169 | }; |
| 161 | 170 | } |
| 162 | 171 | |
| 163 | pub fn sinq(x: f128) callconv(.c) f128 { | |
| 172 | fn 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 | } | |
| 175 | pub fn sin_f128(x: f128) f128 { | |
| 164 | 176 | const se = ld.signExponent(x) & 0x7fff; |
| 165 | 177 | if (se == 0x7fff) { |
| 166 | 178 | return x - x; |
| ... | ... | @@ -189,20 +201,21 @@ pub fn sinq(x: f128) callconv(.c) f128 { |
| 189 | 201 | |
| 190 | 202 | pub fn sinl(x: c_longdouble) callconv(.c) c_longdouble { |
| 191 | 203 | switch (@typeInfo(c_longdouble).float.bits) { |
| 192 | 64 => return sin(x), | |
| 193 | 80 => return sinx(x), | |
| 194 | 128 => return sinq(x), | |
| 195 | else => @compileError("unreachable"), | |
| 204 | 64 => return sin_f64(x), | |
| 205 | 80 => return sin_f80(x), | |
| 206 | 128 => return sin_f128(x), | |
| 207 | else => comptime unreachable, | |
| 196 | 208 | } |
| 197 | 209 | } |
| 198 | 210 | |
| 199 | 211 | fn testSinSpecial(comptime T: type) !void { |
| 200 | 212 | const f = switch (T) { |
| 201 | f32 => sinf, | |
| 202 | f64 => sin, | |
| 203 | f80 => sinx, | |
| 204 | f128 => sinq, | |
| 205 | else => @compileError("unimplemented"), | |
| 213 | f16 => sin_f16, | |
| 214 | f32 => sin_f32, | |
| 215 | f64 => sin_f64, | |
| 216 | f80 => sin_f80, | |
| 217 | f128 => sin_f128, | |
| 218 | else => comptime unreachable, | |
| 206 | 219 | }; |
| 207 | 220 | |
| 208 | 221 | try expect(math.isPositiveZero(f(0.0))); |
| ... | ... | @@ -214,13 +227,13 @@ fn testSinSpecial(comptime T: type) !void { |
| 214 | 227 | |
| 215 | 228 | test "sin32.normal" { |
| 216 | 229 | const epsilon = math.floatEps(f32); |
| 217 | try expectApproxEqAbs(@as(f32, 0.0), sinf(0.0), epsilon); | |
| 218 | try expectApproxEqAbs(@as(f32, 0.19866933), sinf(0.2), epsilon); | |
| 219 | try expectApproxEqAbs(@as(f32, 0.77851737), sinf(0.8923), epsilon); | |
| 220 | try expectApproxEqAbs(@as(f32, 0.997495), sinf(1.5), epsilon); | |
| 221 | try expectApproxEqAbs(@as(f32, -0.997495), sinf(-1.5), epsilon); | |
| 222 | try expectApproxEqAbs(@as(f32, -0.24654257), sinf(37.45), epsilon); | |
| 223 | try expectApproxEqAbs(@as(f32, 0.9161657), sinf(89.123), epsilon); | |
| 230 | try expectApproxEqAbs(@as(f32, 0.0), sin_f32(0.0), epsilon); | |
| 231 | try expectApproxEqAbs(@as(f32, 0.19866933), sin_f32(0.2), epsilon); | |
| 232 | try expectApproxEqAbs(@as(f32, 0.77851737), sin_f32(0.8923), epsilon); | |
| 233 | try expectApproxEqAbs(@as(f32, 0.997495), sin_f32(1.5), epsilon); | |
| 234 | try expectApproxEqAbs(@as(f32, -0.997495), sin_f32(-1.5), epsilon); | |
| 235 | try expectApproxEqAbs(@as(f32, -0.24654257), sin_f32(37.45), epsilon); | |
| 236 | try expectApproxEqAbs(@as(f32, 0.9161657), sin_f32(89.123), epsilon); | |
| 224 | 237 | } |
| 225 | 238 | |
| 226 | 239 | test "sin32.special" { |
| ... | ... | @@ -229,13 +242,13 @@ test "sin32.special" { |
| 229 | 242 | |
| 230 | 243 | test "sin64.normal" { |
| 231 | 244 | const epsilon = math.floatEps(f64); |
| 232 | try expectApproxEqAbs(@as(f64, 0.0), sin(0.0), epsilon); | |
| 233 | try expectApproxEqAbs(@as(f64, 0.19866933079506122), sin(0.2), epsilon); | |
| 234 | try expectApproxEqAbs(@as(f64, 0.7785173385577349), sin(0.8923), epsilon); | |
| 235 | try expectApproxEqAbs(@as(f64, 0.9974949866040544), sin(1.5), epsilon); | |
| 236 | try expectApproxEqAbs(@as(f64, -0.9974949866040544), sin(-1.5), epsilon); | |
| 237 | try expectApproxEqAbs(@as(f64, -0.24654331551411082), sin(37.45), epsilon); | |
| 238 | try expectApproxEqAbs(@as(f64, 0.9161652766622714), sin(89.123), epsilon); | |
| 245 | try expectApproxEqAbs(@as(f64, 0.0), sin_f64(0.0), epsilon); | |
| 246 | try expectApproxEqAbs(@as(f64, 0.19866933079506122), sin_f64(0.2), epsilon); | |
| 247 | try expectApproxEqAbs(@as(f64, 0.7785173385577349), sin_f64(0.8923), epsilon); | |
| 248 | try expectApproxEqAbs(@as(f64, 0.9974949866040544), sin_f64(1.5), epsilon); | |
| 249 | try expectApproxEqAbs(@as(f64, -0.9974949866040544), sin_f64(-1.5), epsilon); | |
| 250 | try expectApproxEqAbs(@as(f64, -0.24654331551411082), sin_f64(37.45), epsilon); | |
| 251 | try expectApproxEqAbs(@as(f64, 0.9161652766622714), sin_f64(89.123), epsilon); | |
| 239 | 252 | } |
| 240 | 253 | |
| 241 | 254 | test "sin64.special" { |
| ... | ... | @@ -244,13 +257,13 @@ test "sin64.special" { |
| 244 | 257 | |
| 245 | 258 | test "sin80.normal" { |
| 246 | 259 | const epsilon = math.floatEps(f80); |
| 247 | try expectApproxEqAbs(@as(f80, 0.0), sinx(0.0), epsilon); | |
| 248 | try expectApproxEqAbs(@as(f80, 0.19866933079506121545941262711838975), sinx(0.2), epsilon); | |
| 249 | try expectApproxEqAbs(@as(f80, 0.77851733855773487830689285621486050), sinx(0.8923), epsilon); | |
| 250 | try expectApproxEqAbs(@as(f80, 0.99749498660405443094172337114148732), sinx(1.5), epsilon); | |
| 251 | try expectApproxEqAbs(@as(f80, -0.99749498660405443094172337114148732), sinx(-1.5), epsilon); | |
| 252 | try expectApproxEqAbs(@as(f80, -0.24654331551411356504), sinx(37.45), epsilon); | |
| 253 | try expectApproxEqAbs(@as(f80, 0.91616527666226951006), sinx(89.123), epsilon); | |
| 260 | try expectApproxEqAbs(@as(f80, 0.0), sin_f80(0.0), epsilon); | |
| 261 | try expectApproxEqAbs(@as(f80, 0.19866933079506121545941262711838975), sin_f80(0.2), epsilon); | |
| 262 | try expectApproxEqAbs(@as(f80, 0.77851733855773487830689285621486050), sin_f80(0.8923), epsilon); | |
| 263 | try expectApproxEqAbs(@as(f80, 0.99749498660405443094172337114148732), sin_f80(1.5), epsilon); | |
| 264 | try expectApproxEqAbs(@as(f80, -0.99749498660405443094172337114148732), sin_f80(-1.5), epsilon); | |
| 265 | try expectApproxEqAbs(@as(f80, -0.24654331551411356504), sin_f80(37.45), epsilon); | |
| 266 | try expectApproxEqAbs(@as(f80, 0.91616527666226951006), sin_f80(89.123), epsilon); | |
| 254 | 267 | } |
| 255 | 268 | |
| 256 | 269 | test "sin80.special" { |
| ... | ... | @@ -259,13 +272,13 @@ test "sin80.special" { |
| 259 | 272 | |
| 260 | 273 | test "sin128.normal" { |
| 261 | 274 | const epsilon = math.floatEps(f128); |
| 262 | try expectApproxEqAbs(@as(f128, 0.0), sinq(0.0), epsilon); | |
| 263 | try expectApproxEqAbs(@as(f128, 0.19866933079506121545941262711838975), sinq(0.2), epsilon); | |
| 264 | try expectApproxEqAbs(@as(f128, 0.77851733855773487830689285621486050), sinq(0.8923), epsilon); | |
| 265 | try expectApproxEqAbs(@as(f128, 0.99749498660405443094172337114148732), sinq(1.5), epsilon); | |
| 266 | try expectApproxEqAbs(@as(f128, -0.99749498660405443094172337114148732), sinq(-1.5), epsilon); | |
| 267 | try expectApproxEqAbs(@as(f128, -0.24654331551411356571238581321661085), sinq(37.45), epsilon); | |
| 268 | try expectApproxEqAbs(@as(f128, 0.91616527666226951075019849560482170), sinq(89.123), epsilon); | |
| 275 | try expectApproxEqAbs(@as(f128, 0.0), sin_f128(0.0), epsilon); | |
| 276 | try expectApproxEqAbs(@as(f128, 0.19866933079506121545941262711838975), sin_f128(0.2), epsilon); | |
| 277 | try expectApproxEqAbs(@as(f128, 0.77851733855773487830689285621486050), sin_f128(0.8923), epsilon); | |
| 278 | try expectApproxEqAbs(@as(f128, 0.99749498660405443094172337114148732), sin_f128(1.5), epsilon); | |
| 279 | try expectApproxEqAbs(@as(f128, -0.99749498660405443094172337114148732), sin_f128(-1.5), epsilon); | |
| 280 | try expectApproxEqAbs(@as(f128, -0.24654331551411356571238581321661085), sin_f128(37.45), epsilon); | |
| 281 | try expectApproxEqAbs(@as(f128, 0.91616527666226951075019849560482170), sin_f128(89.123), epsilon); | |
| 269 | 282 | } |
| 270 | 283 | |
| 271 | 284 | test "sin128.special" { |
| ... | ... | @@ -274,10 +287,10 @@ test "sin128.special" { |
| 274 | 287 | |
| 275 | 288 | test "sin32 #9901" { |
| 276 | 289 | const float: f32 = @bitCast(@as(u32, 0b11100011111111110000000000000000)); |
| 277 | _ = sinf(float); | |
| 290 | _ = sin_f32(float); | |
| 278 | 291 | } |
| 279 | 292 | |
| 280 | 293 | test "sin64 #9901" { |
| 281 | 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 | 18 | symbol(&sincosf, "sincosf"); |
| 19 | 19 | symbol(&sincos, "sincos"); |
| 20 | 20 | symbol(&sincosx, "__sincosx"); |
| 21 | if (compiler_rt.want_ppc_abi) { | |
| 22 | symbol(&sincosq, "sincosf128"); | |
| 23 | } | |
| 24 | symbol(&sincosq, "sincosq"); | |
| 21 | symbol(&sincosq, "sincosf128"); | |
| 25 | 22 | symbol(&sincosl, "sincosl"); |
| 26 | 23 | } |
| 27 | 24 | |
| 28 | pub fn sincosh(x: f16, r_sin: *f16, r_cos: *f16) callconv(.c) void { | |
| 25 | fn 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 | } | |
| 30 | pub fn sincos_f16(x: f16) struct { f16, f16 } { | |
| 29 | 31 | // TODO: more efficient implementation |
| 30 | var big_sin: f32 = undefined; | |
| 31 | var big_cos: f32 = undefined; | |
| 32 | sincosf(x, &big_sin, &big_cos); | |
| 33 | r_sin.* = @as(f16, @floatCast(big_sin)); | |
| 34 | r_cos.* = @as(f16, @floatCast(big_cos)); | |
| 32 | const s, const c = sincos_f32(x); | |
| 33 | return .{ @floatCast(s), @floatCast(c) }; | |
| 35 | 34 | } |
| 36 | 35 | |
| 37 | pub fn sincosf(x: f32, r_sin: *f32, r_cos: *f32) callconv(.c) void { | |
| 36 | fn 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 | } | |
| 41 | pub fn sincos_f32(x: f32) struct { f32, f32 } { | |
| 38 | 42 | const sc1pio2: f64 = 1.0 * math.pi / 2.0; // 0x3FF921FB, 0x54442D18 |
| 39 | 43 | const sc2pio2: f64 = 2.0 * math.pi / 2.0; // 0x400921FB, 0x54442D18 |
| 40 | 44 | 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 | 60 | mem.doNotOptimizeAway(x + 0x1p120); |
| 57 | 61 | } |
| 58 | 62 | } |
| 59 | r_sin.* = x; | |
| 60 | r_cos.* = 1.0; | |
| 61 | return; | |
| 63 | return .{ x, 1.0 }; | |
| 62 | 64 | } |
| 63 | r_sin.* = trig.sindf(x); | |
| 64 | r_cos.* = trig.cosdf(x); | |
| 65 | return; | |
| 65 | return .{ trig.sindf(x), trig.cosdf(x) }; | |
| 66 | 66 | } |
| 67 | 67 | |
| 68 | 68 | // |x| ~<= 5*pi/4 |
| ... | ... | @@ -70,18 +70,16 @@ pub fn sincosf(x: f32, r_sin: *f32, r_cos: *f32) callconv(.c) void { |
| 70 | 70 | // |x| ~<= 3pi/4 |
| 71 | 71 | if (ix <= 0x4016cbe3) { |
| 72 | 72 | if (sign) { |
| 73 | r_sin.* = -trig.cosdf(x + sc1pio2); | |
| 74 | r_cos.* = trig.sindf(x + sc1pio2); | |
| 73 | return .{ -trig.cosdf(x + sc1pio2), trig.sindf(x + sc1pio2) }; | |
| 75 | 74 | } else { |
| 76 | r_sin.* = trig.cosdf(sc1pio2 - x); | |
| 77 | r_cos.* = trig.sindf(sc1pio2 - x); | |
| 75 | return .{ trig.cosdf(sc1pio2 - x), trig.sindf(sc1pio2 - x) }; | |
| 78 | 76 | } |
| 79 | return; | |
| 80 | 77 | } |
| 81 | 78 | // -sin(x+c) is not correct if x+c could be 0: -0 vs +0 |
| 82 | r_sin.* = -trig.sindf(if (sign) x + sc2pio2 else x - sc2pio2); | |
| 83 | r_cos.* = -trig.cosdf(if (sign) x + sc2pio2 else x - sc2pio2); | |
| 84 | return; | |
| 79 | return .{ | |
| 80 | -trig.sindf(if (sign) x + sc2pio2 else x - sc2pio2), | |
| 81 | -trig.cosdf(if (sign) x + sc2pio2 else x - sc2pio2), | |
| 82 | }; | |
| 85 | 83 | } |
| 86 | 84 | |
| 87 | 85 | // |x| ~<= 9*pi/4 |
| ... | ... | @@ -89,25 +87,21 @@ pub fn sincosf(x: f32, r_sin: *f32, r_cos: *f32) callconv(.c) void { |
| 89 | 87 | // |x| ~<= 7*pi/4 |
| 90 | 88 | if (ix <= 0x40afeddf) { |
| 91 | 89 | if (sign) { |
| 92 | r_sin.* = trig.cosdf(x + sc3pio2); | |
| 93 | r_cos.* = -trig.sindf(x + sc3pio2); | |
| 90 | return .{ trig.cosdf(x + sc3pio2), -trig.sindf(x + sc3pio2) }; | |
| 94 | 91 | } else { |
| 95 | r_sin.* = -trig.cosdf(x - sc3pio2); | |
| 96 | r_cos.* = trig.sindf(x - sc3pio2); | |
| 92 | return .{ -trig.cosdf(x - sc3pio2), trig.sindf(x - sc3pio2) }; | |
| 97 | 93 | } |
| 98 | return; | |
| 99 | 94 | } |
| 100 | r_sin.* = trig.sindf(if (sign) x + sc4pio2 else x - sc4pio2); | |
| 101 | r_cos.* = trig.cosdf(if (sign) x + sc4pio2 else x - sc4pio2); | |
| 102 | return; | |
| 95 | return .{ | |
| 96 | trig.sindf(if (sign) x + sc4pio2 else x - sc4pio2), | |
| 97 | trig.cosdf(if (sign) x + sc4pio2 else x - sc4pio2), | |
| 98 | }; | |
| 103 | 99 | } |
| 104 | 100 | |
| 105 | 101 | // sin(Inf or NaN) is NaN |
| 106 | 102 | if (ix >= 0x7f800000) { |
| 107 | 103 | const result = x - x; |
| 108 | r_sin.* = result; | |
| 109 | r_cos.* = result; | |
| 110 | return; | |
| 104 | return .{ result, result }; | |
| 111 | 105 | } |
| 112 | 106 | |
| 113 | 107 | // general argument reduction needed |
| ... | ... | @@ -115,27 +109,20 @@ pub fn sincosf(x: f32, r_sin: *f32, r_cos: *f32) callconv(.c) void { |
| 115 | 109 | const n = rem_pio2f(x, &y); |
| 116 | 110 | const s = trig.sindf(y); |
| 117 | 111 | const c = trig.cosdf(y); |
| 118 | switch (n & 3) { | |
| 119 | 0 => { | |
| 120 | r_sin.* = s; | |
| 121 | r_cos.* = c; | |
| 122 | }, | |
| 123 | 1 => { | |
| 124 | r_sin.* = c; | |
| 125 | r_cos.* = -s; | |
| 126 | }, | |
| 127 | 2 => { | |
| 128 | r_sin.* = -s; | |
| 129 | r_cos.* = -c; | |
| 130 | }, | |
| 131 | else => { | |
| 132 | r_sin.* = -c; | |
| 133 | r_cos.* = s; | |
| 134 | }, | |
| 135 | } | |
| 112 | return switch (@as(u2, @truncate(@as(u32, @bitCast(n))))) { | |
| 113 | 0 => .{ s, c }, | |
| 114 | 1 => .{ c, -s }, | |
| 115 | 2 => .{ -s, -c }, | |
| 116 | 3 => .{ -c, s }, | |
| 117 | }; | |
| 136 | 118 | } |
| 137 | 119 | |
| 138 | pub fn sincos(x: f64, r_sin: *f64, r_cos: *f64) callconv(.c) void { | |
| 120 | fn 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 | } | |
| 125 | pub fn sincos_f64(x: f64) struct { f64, f64 } { | |
| 139 | 126 | const ix = @as(u32, @truncate(@as(u64, @bitCast(x)) >> 32)) & 0x7fffffff; |
| 140 | 127 | |
| 141 | 128 | // |x| ~< pi/4 |
| ... | ... | @@ -150,21 +137,15 @@ pub fn sincos(x: f64, r_sin: *f64, r_cos: *f64) callconv(.c) void { |
| 150 | 137 | mem.doNotOptimizeAway(x + 0x1p120); |
| 151 | 138 | } |
| 152 | 139 | } |
| 153 | r_sin.* = x; | |
| 154 | r_cos.* = 1.0; | |
| 155 | return; | |
| 140 | return .{ x, 1.0 }; | |
| 156 | 141 | } |
| 157 | r_sin.* = trig.sin(x, 0.0, 0); | |
| 158 | r_cos.* = trig.cos(x, 0.0); | |
| 159 | return; | |
| 142 | return .{ trig.sin(x, 0.0, 0), trig.cos(x, 0.0) }; | |
| 160 | 143 | } |
| 161 | 144 | |
| 162 | 145 | // sincos(Inf or NaN) is NaN |
| 163 | 146 | if (ix >= 0x7ff00000) { |
| 164 | 147 | const result = x - x; |
| 165 | r_sin.* = result; | |
| 166 | r_cos.* = result; | |
| 167 | return; | |
| 148 | return .{ result, result }; | |
| 168 | 149 | } |
| 169 | 150 | |
| 170 | 151 | // argument reduction needed |
| ... | ... | @@ -172,33 +153,24 @@ pub fn sincos(x: f64, r_sin: *f64, r_cos: *f64) callconv(.c) void { |
| 172 | 153 | const n = rem_pio2(x, &y); |
| 173 | 154 | const s = trig.sin(y[0], y[1], 1); |
| 174 | 155 | const c = trig.cos(y[0], y[1]); |
| 175 | switch (n & 3) { | |
| 176 | 0 => { | |
| 177 | r_sin.* = s; | |
| 178 | r_cos.* = c; | |
| 179 | }, | |
| 180 | 1 => { | |
| 181 | r_sin.* = c; | |
| 182 | r_cos.* = -s; | |
| 183 | }, | |
| 184 | 2 => { | |
| 185 | r_sin.* = -s; | |
| 186 | r_cos.* = -c; | |
| 187 | }, | |
| 188 | else => { | |
| 189 | r_sin.* = -c; | |
| 190 | r_cos.* = s; | |
| 191 | }, | |
| 192 | } | |
| 156 | return switch (@as(u2, @truncate(@as(u32, @bitCast(n))))) { | |
| 157 | 0 => .{ s, c }, | |
| 158 | 1 => .{ c, -s }, | |
| 159 | 2 => .{ -s, -c }, | |
| 160 | 3 => .{ -c, s }, | |
| 161 | }; | |
| 193 | 162 | } |
| 194 | 163 | |
| 195 | pub fn sincosx(x: f80, r_sin: *f80, r_cos: *f80) callconv(.c) void { | |
| 164 | fn 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 | } | |
| 169 | pub fn sincos_f80(x: f80) struct { f80, f80 } { | |
| 196 | 170 | const se = ld.signExponent(x) & 0x7fff; |
| 197 | 171 | if (se == 0x7fff) { |
| 198 | 172 | const result = x - x; |
| 199 | r_sin.* = result; | |
| 200 | r_cos.* = result; | |
| 201 | return; | |
| 173 | return .{ result, result }; | |
| 202 | 174 | } |
| 203 | 175 | |
| 204 | 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 | 179 | if (compiler_rt.want_float_exceptions and se == 0) { |
| 208 | 180 | mem.doNotOptimizeAway(x * 0x1p-120); |
| 209 | 181 | } |
| 210 | r_sin.* = x; | |
| 211 | 182 | // raise inexact if x!=0 |
| 212 | r_cos.* = 1.0 + x; | |
| 213 | return; | |
| 183 | return .{ x, 1.0 + x }; | |
| 214 | 184 | } |
| 215 | r_sin.* = trig.sinx(x, 0.0, 0); | |
| 216 | r_cos.* = trig.cosx(x, 0.0); | |
| 217 | return; | |
| 185 | return .{ trig.sinx(x, 0.0, 0), trig.cosx(x, 0.0) }; | |
| 218 | 186 | } |
| 219 | 187 | |
| 220 | 188 | var y: [2]f80 = undefined; |
| 221 | 189 | const n = rem_pio2l(f80, x, &y); |
| 222 | 190 | const s = trig.sinx(y[0], y[1], 1); |
| 223 | 191 | const c = trig.cosx(y[0], y[1]); |
| 224 | switch (n & 3) { | |
| 225 | 0 => { | |
| 226 | r_sin.* = s; | |
| 227 | r_cos.* = c; | |
| 228 | }, | |
| 229 | 1 => { | |
| 230 | r_sin.* = c; | |
| 231 | r_cos.* = -s; | |
| 232 | }, | |
| 233 | 2 => { | |
| 234 | r_sin.* = -s; | |
| 235 | r_cos.* = -c; | |
| 236 | }, | |
| 237 | else => { | |
| 238 | r_sin.* = -c; | |
| 239 | r_cos.* = s; | |
| 240 | }, | |
| 241 | } | |
| 192 | return switch (@as(u2, @truncate(@as(u32, @bitCast(n))))) { | |
| 193 | 0 => .{ s, c }, | |
| 194 | 1 => .{ c, -s }, | |
| 195 | 2 => .{ -s, -c }, | |
| 196 | 3 => .{ -c, s }, | |
| 197 | }; | |
| 242 | 198 | } |
| 243 | 199 | |
| 244 | pub fn sincosq(x: f128, r_sin: *f128, r_cos: *f128) callconv(.c) void { | |
| 200 | fn 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 | } | |
| 205 | pub fn sincos_f128(x: f128) struct { f128, f128 } { | |
| 245 | 206 | const se = ld.signExponent(x) & 0x7fff; |
| 246 | 207 | if (se == 0x7fff) { |
| 247 | 208 | const result = x - x; |
| 248 | r_sin.* = result; | |
| 249 | r_cos.* = result; | |
| 250 | return; | |
| 209 | return .{ result, result }; | |
| 251 | 210 | } |
| 252 | 211 | |
| 253 | 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 | 215 | if (compiler_rt.want_float_exceptions and se == 0) { |
| 257 | 216 | mem.doNotOptimizeAway(x * 0x1p-120); |
| 258 | 217 | } |
| 259 | r_sin.* = x; | |
| 260 | 218 | // raise inexact if x!=0 |
| 261 | r_cos.* = 1.0 + x; | |
| 262 | return; | |
| 219 | return .{ x, 1.0 + x }; | |
| 263 | 220 | } |
| 264 | r_sin.* = trig.sinq(x, 0.0, 0); | |
| 265 | r_cos.* = trig.cosq(x, 0.0); | |
| 266 | return; | |
| 221 | return .{ trig.sinq(x, 0.0, 0), trig.cosq(x, 0.0) }; | |
| 267 | 222 | } |
| 268 | 223 | |
| 269 | 224 | var y: [2]f128 = undefined; |
| 270 | 225 | const n = rem_pio2l(f128, x, &y); |
| 271 | 226 | const s = trig.sinq(y[0], y[1], 1); |
| 272 | 227 | const c = trig.cosq(y[0], y[1]); |
| 273 | switch (n & 3) { | |
| 274 | 0 => { | |
| 275 | r_sin.* = s; | |
| 276 | r_cos.* = c; | |
| 277 | }, | |
| 278 | 1 => { | |
| 279 | r_sin.* = c; | |
| 280 | r_cos.* = -s; | |
| 281 | }, | |
| 282 | 2 => { | |
| 283 | r_sin.* = -s; | |
| 284 | r_cos.* = -c; | |
| 285 | }, | |
| 286 | else => { | |
| 287 | r_sin.* = -c; | |
| 288 | r_cos.* = s; | |
| 289 | }, | |
| 290 | } | |
| 228 | return switch (@as(u2, @truncate(@as(u32, @bitCast(n))))) { | |
| 229 | 0 => .{ s, c }, | |
| 230 | 1 => .{ c, -s }, | |
| 231 | 2 => .{ -s, -c }, | |
| 232 | 3 => .{ -c, s }, | |
| 233 | }; | |
| 291 | 234 | } |
| 292 | 235 | |
| 293 | 236 | pub fn sincosl(x: c_longdouble, r_sin: *c_longdouble, r_cos: *c_longdouble) callconv(.c) void { |
| 294 | switch (@typeInfo(c_longdouble).float.bits) { | |
| 295 | 64 => return sincos(x, r_sin, r_cos), | |
| 296 | 80 => return sincosx(x, r_sin, r_cos), | |
| 297 | 128 => return sincosq(x, r_sin, r_cos), | |
| 298 | else => @compileError("unreachable"), | |
| 299 | } | |
| 237 | r_sin.*, r_cos.* = switch (@typeInfo(c_longdouble).float.bits) { | |
| 238 | 64 => sincos_f64(x), | |
| 239 | 80 => sincos_f80(x), | |
| 240 | 128 => sincos_f128(x), | |
| 241 | else => comptime unreachable, | |
| 242 | }; | |
| 300 | 243 | } |
| 301 | 244 | |
| 302 | 245 | fn testSincosSpecial(comptime T: type) !void { |
| 303 | 246 | const f = switch (T) { |
| 304 | f32 => sincosf, | |
| 305 | f64 => sincos, | |
| 306 | f80 => sincosx, | |
| 307 | f128 => sincosq, | |
| 247 | f16 => sincos_f16, | |
| 248 | f32 => sincos_f32, | |
| 249 | f64 => sincos_f64, | |
| 250 | f80 => sincos_f80, | |
| 251 | f128 => sincos_f128, | |
| 308 | 252 | else => @compileError("unimplemented"), |
| 309 | 253 | }; |
| 310 | 254 | |
| 311 | 255 | var s: T = undefined; |
| 312 | 256 | var c: T = undefined; |
| 313 | 257 | |
| 314 | f(0.0, &s, &c); | |
| 258 | s, c = f(0.0); | |
| 315 | 259 | try expect(math.isPositiveZero(s)); |
| 316 | 260 | try expect(c == 1.0); |
| 317 | 261 | |
| 318 | f(-0.0, &s, &c); | |
| 262 | s, c = f(-0.0); | |
| 319 | 263 | try expect(math.isNegativeZero(s)); |
| 320 | 264 | try expect(c == 1.0); |
| 321 | 265 | |
| 322 | f(math.inf(T), &s, &c); | |
| 266 | s, c = f(math.inf(T)); | |
| 323 | 267 | try expect(math.isNan(s)); |
| 324 | 268 | try expect(math.isNan(c)); |
| 325 | 269 | |
| 326 | f(-math.inf(T), &s, &c); | |
| 270 | s, c = f(-math.inf(T)); | |
| 327 | 271 | try expect(math.isNan(s)); |
| 328 | 272 | try expect(math.isNan(c)); |
| 329 | 273 | |
| 330 | f(math.nan(T), &s, &c); | |
| 274 | s, c = f(math.nan(T)); | |
| 331 | 275 | try expect(math.isNan(s)); |
| 332 | 276 | try expect(math.isNan(c)); |
| 333 | 277 | } |
| ... | ... | @@ -337,31 +281,31 @@ test "sincos32.normal" { |
| 337 | 281 | var s: f32 = undefined; |
| 338 | 282 | var c: f32 = undefined; |
| 339 | 283 | |
| 340 | sincosf(0.0, &s, &c); | |
| 284 | s, c = sincos_f32(0.0); | |
| 341 | 285 | try expectApproxEqAbs(@as(f32, 0.0), s, epsilon); |
| 342 | 286 | try expectApproxEqAbs(@as(f32, 1.0), c, epsilon); |
| 343 | 287 | |
| 344 | sincosf(0.2, &s, &c); | |
| 288 | s, c = sincos_f32(0.2); | |
| 345 | 289 | try expectApproxEqAbs(@as(f32, 0.19866933), s, epsilon); |
| 346 | 290 | try expectApproxEqAbs(@as(f32, 0.9800666), c, epsilon); |
| 347 | 291 | |
| 348 | sincosf(0.8923, &s, &c); | |
| 292 | s, c = sincos_f32(0.8923); | |
| 349 | 293 | try expectApproxEqAbs(@as(f32, 0.77851737), s, epsilon); |
| 350 | 294 | try expectApproxEqAbs(@as(f32, 0.6276231), c, epsilon); |
| 351 | 295 | |
| 352 | sincosf(1.5, &s, &c); | |
| 296 | s, c = sincos_f32(1.5); | |
| 353 | 297 | try expectApproxEqAbs(@as(f32, 0.997495), s, epsilon); |
| 354 | 298 | try expectApproxEqAbs(@as(f32, 0.0707372), c, epsilon); |
| 355 | 299 | |
| 356 | sincosf(-1.5, &s, &c); | |
| 300 | s, c = sincos_f32(-1.5); | |
| 357 | 301 | try expectApproxEqAbs(@as(f32, -0.997495), s, epsilon); |
| 358 | 302 | try expectApproxEqAbs(@as(f32, 0.0707372), c, epsilon); |
| 359 | 303 | |
| 360 | sincosf(37.45, &s, &c); | |
| 304 | s, c = sincos_f32(37.45); | |
| 361 | 305 | try expectApproxEqAbs(@as(f32, -0.24654257), s, epsilon); |
| 362 | 306 | try expectApproxEqAbs(@as(f32, 0.96913195), c, epsilon); |
| 363 | 307 | |
| 364 | sincosf(89.123, &s, &c); | |
| 308 | s, c = sincos_f32(89.123); | |
| 365 | 309 | try expectApproxEqAbs(@as(f32, 0.9161657), s, epsilon); |
| 366 | 310 | try expectApproxEqAbs(@as(f32, 0.40079966), c, epsilon); |
| 367 | 311 | } |
| ... | ... | @@ -375,31 +319,31 @@ test "sincos64.normal" { |
| 375 | 319 | var s: f64 = undefined; |
| 376 | 320 | var c: f64 = undefined; |
| 377 | 321 | |
| 378 | sincos(0.0, &s, &c); | |
| 322 | s, c = sincos_f64(0.0); | |
| 379 | 323 | try expectApproxEqAbs(@as(f64, 0.0), s, epsilon); |
| 380 | 324 | try expectApproxEqAbs(@as(f64, 1.0), c, epsilon); |
| 381 | 325 | |
| 382 | sincos(0.2, &s, &c); | |
| 326 | s, c = sincos_f64(0.2); | |
| 383 | 327 | try expectApproxEqAbs(@as(f64, 0.19866933079506122), s, epsilon); |
| 384 | 328 | try expectApproxEqAbs(@as(f64, 0.9800665778412416), c, epsilon); |
| 385 | 329 | |
| 386 | sincos(0.8923, &s, &c); | |
| 330 | s, c = sincos_f64(0.8923); | |
| 387 | 331 | try expectApproxEqAbs(@as(f64, 0.7785173385577349), s, epsilon); |
| 388 | 332 | try expectApproxEqAbs(@as(f64, 0.6276230983360804), c, epsilon); |
| 389 | 333 | |
| 390 | sincos(1.5, &s, &c); | |
| 334 | s, c = sincos_f64(1.5); | |
| 391 | 335 | try expectApproxEqAbs(@as(f64, 0.9974949866040544), s, epsilon); |
| 392 | 336 | try expectApproxEqAbs(@as(f64, 0.0707372016677029), c, epsilon); |
| 393 | 337 | |
| 394 | sincos(-1.5, &s, &c); | |
| 338 | s, c = sincos_f64(-1.5); | |
| 395 | 339 | try expectApproxEqAbs(@as(f64, -0.9974949866040544), s, epsilon); |
| 396 | 340 | try expectApproxEqAbs(@as(f64, 0.0707372016677029), c, epsilon); |
| 397 | 341 | |
| 398 | sincos(37.45, &s, &c); | |
| 342 | s, c = sincos_f64(37.45); | |
| 399 | 343 | try expectApproxEqAbs(@as(f64, -0.24654331551411082), s, epsilon); |
| 400 | 344 | try expectApproxEqAbs(@as(f64, 0.9691317730707778), c, epsilon); |
| 401 | 345 | |
| 402 | sincos(89.123, &s, &c); | |
| 346 | s, c = sincos_f64(89.123); | |
| 403 | 347 | try expectApproxEqAbs(@as(f64, 0.9161652766622714), s, epsilon); |
| 404 | 348 | try expectApproxEqAbs(@as(f64, 0.4008006809354791), c, epsilon); |
| 405 | 349 | } |
| ... | ... | @@ -413,31 +357,31 @@ test "sincos80.normal" { |
| 413 | 357 | var s: f80 = undefined; |
| 414 | 358 | var c: f80 = undefined; |
| 415 | 359 | |
| 416 | sincosx(0.0, &s, &c); | |
| 360 | s, c = sincos_f80(0.0); | |
| 417 | 361 | try expectApproxEqAbs(@as(f80, 0.0), s, epsilon); |
| 418 | 362 | try expectApproxEqAbs(@as(f80, 1.0), c, epsilon); |
| 419 | 363 | |
| 420 | sincosx(0.2, &s, &c); | |
| 364 | s, c = sincos_f80(0.2); | |
| 421 | 365 | try expectApproxEqAbs(@as(f80, 0.19866933079506121545941262711838975), s, epsilon); |
| 422 | 366 | try expectApproxEqAbs(@as(f80, 0.98006657784124163112419651674816888), c, epsilon); |
| 423 | 367 | |
| 424 | sincosx(0.8923, &s, &c); | |
| 368 | s, c = sincos_f80(0.8923); | |
| 425 | 369 | try expectApproxEqAbs(@as(f80, 0.77851733855773487830689285621486050), s, epsilon); |
| 426 | 370 | try expectApproxEqAbs(@as(f80, 0.62762309833608037003563995939286067), c, epsilon); |
| 427 | 371 | |
| 428 | sincosx(1.5, &s, &c); | |
| 372 | s, c = sincos_f80(1.5); | |
| 429 | 373 | try expectApproxEqAbs(@as(f80, 0.99749498660405443094172337114148732), s, epsilon); |
| 430 | 374 | try expectApproxEqAbs(@as(f80, 0.070737201667702910088189851434268747), c, epsilon); |
| 431 | 375 | |
| 432 | sincosx(-1.5, &s, &c); | |
| 376 | s, c = sincos_f80(-1.5); | |
| 433 | 377 | try expectApproxEqAbs(@as(f80, -0.99749498660405443094172337114148732), s, epsilon); |
| 434 | 378 | try expectApproxEqAbs(@as(f80, 0.070737201667702910088189851434268747), c, epsilon); |
| 435 | 379 | |
| 436 | sincosx(37.45, &s, &c); | |
| 380 | s, c = sincos_f80(37.45); | |
| 437 | 381 | try expectApproxEqAbs(@as(f80, -0.24654331551411356504), s, epsilon); |
| 438 | 382 | try expectApproxEqAbs(@as(f80, 0.9691317730707771246), c, epsilon); |
| 439 | 383 | |
| 440 | sincosx(89.123, &s, &c); | |
| 384 | s, c = sincos_f80(89.123); | |
| 441 | 385 | try expectApproxEqAbs(@as(f80, 0.91616527666226951006), s, epsilon); |
| 442 | 386 | try expectApproxEqAbs(@as(f80, 0.4008006809354834001), c, epsilon); |
| 443 | 387 | } |
| ... | ... | @@ -451,31 +395,31 @@ test "sincos128.normal" { |
| 451 | 395 | var s: f128 = undefined; |
| 452 | 396 | var c: f128 = undefined; |
| 453 | 397 | |
| 454 | sincosq(0.0, &s, &c); | |
| 398 | s, c = sincos_f128(0.0); | |
| 455 | 399 | try expectApproxEqAbs(@as(f128, 0.0), s, epsilon); |
| 456 | 400 | try expectApproxEqAbs(@as(f128, 1.0), c, epsilon); |
| 457 | 401 | |
| 458 | sincosq(0.2, &s, &c); | |
| 402 | s, c = sincos_f128(0.2); | |
| 459 | 403 | try expectApproxEqAbs(@as(f128, 0.19866933079506121545941262711838975), s, epsilon); |
| 460 | 404 | try expectApproxEqAbs(@as(f128, 0.98006657784124163112419651674816888), c, epsilon); |
| 461 | 405 | |
| 462 | sincosq(0.8923, &s, &c); | |
| 406 | s, c = sincos_f128(0.8923); | |
| 463 | 407 | try expectApproxEqAbs(@as(f128, 0.77851733855773487830689285621486050), s, epsilon); |
| 464 | 408 | try expectApproxEqAbs(@as(f128, 0.62762309833608037003563995939286067), c, epsilon); |
| 465 | 409 | |
| 466 | sincosq(1.5, &s, &c); | |
| 410 | s, c = sincos_f128(1.5); | |
| 467 | 411 | try expectApproxEqAbs(@as(f128, 0.99749498660405443094172337114148732), s, epsilon); |
| 468 | 412 | try expectApproxEqAbs(@as(f128, 0.070737201667702910088189851434268747), c, epsilon); |
| 469 | 413 | |
| 470 | sincosq(-1.5, &s, &c); | |
| 414 | s, c = sincos_f128(-1.5); | |
| 471 | 415 | try expectApproxEqAbs(@as(f128, -0.99749498660405443094172337114148732), s, epsilon); |
| 472 | 416 | try expectApproxEqAbs(@as(f128, 0.070737201667702910088189851434268747), c, epsilon); |
| 473 | 417 | |
| 474 | sincosq(37.45, &s, &c); | |
| 418 | s, c = sincos_f128(37.45); | |
| 475 | 419 | try expectApproxEqAbs(@as(f128, -0.24654331551411356571238581321661085), s, epsilon); |
| 476 | 420 | try expectApproxEqAbs(@as(f128, 0.96913177307077712443149563847233230), c, epsilon); |
| 477 | 421 | |
| 478 | sincosq(89.123, &s, &c); | |
| 422 | s, c = sincos_f128(89.123); | |
| 479 | 423 | try expectApproxEqAbs(@as(f128, 0.91616527666226951075019849560482170), s, epsilon); |
| 480 | 424 | try expectApproxEqAbs(@as(f128, 0.40080068093548339848199454493704702), c, epsilon); |
| 481 | 425 | } |
lib/compiler_rt/sqrt.zig+150-137| ... | ... | @@ -17,18 +17,19 @@ comptime { |
| 17 | 17 | symbol(&sqrtf, "sqrtf"); |
| 18 | 18 | symbol(&sqrt, "sqrt"); |
| 19 | 19 | symbol(&__sqrtx, "__sqrtx"); |
| 20 | if (compiler_rt.want_ppc_abi) { | |
| 21 | symbol(&sqrtq, "sqrtf128"); | |
| 22 | } else if (compiler_rt.want_sparc64_abi) { | |
| 20 | symbol(&sqrtq, "sqrtf128"); | |
| 21 | if (compiler_rt.want_sparc64_abi) { | |
| 23 | 22 | symbol(&_Qp_sqrt, "_Qp_sqrt"); |
| 24 | 23 | } else if (compiler_rt.want_sparc32_abi) { |
| 25 | 24 | symbol(&sqrtq, "_Q_sqrt"); |
| 26 | 25 | } |
| 27 | symbol(&sqrtq, "sqrtq"); | |
| 28 | 26 | symbol(&sqrtl, "sqrtl"); |
| 29 | 27 | } |
| 30 | 28 | |
| 31 | pub fn __sqrth(x: f16) callconv(.c) f16 { | |
| 29 | fn __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 | } | |
| 32 | pub fn sqrt_f16(x: f16) f16 { | |
| 32 | 33 | var ix: u16 = @bitCast(x); |
| 33 | 34 | var top = ix >> 10; |
| 34 | 35 | |
| ... | ... | @@ -93,7 +94,10 @@ pub fn __sqrth(x: f16) callconv(.c) f16 { |
| 93 | 94 | return y; |
| 94 | 95 | } |
| 95 | 96 | |
| 96 | pub fn sqrtf(x: f32) callconv(.c) f32 { | |
| 97 | fn 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 | } | |
| 100 | pub fn sqrt_f32(x: f32) f32 { | |
| 97 | 101 | var ix: u32 = @bitCast(x); |
| 98 | 102 | |
| 99 | 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 | 151 | return y + t; |
| 148 | 152 | } |
| 149 | 153 | |
| 150 | pub fn sqrt(x: f64) callconv(.c) f64 { | |
| 154 | fn 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 | } | |
| 157 | pub fn sqrt_f64(x: f64) f64 { | |
| 151 | 158 | var ix: u64 = @bitCast(x); |
| 152 | 159 | var top = ix >> 52; |
| 153 | 160 | |
| ... | ... | @@ -284,7 +291,10 @@ pub fn sqrt(x: f64) callconv(.c) f64 { |
| 284 | 291 | return y; |
| 285 | 292 | } |
| 286 | 293 | |
| 287 | pub fn __sqrtx(x: f80) callconv(.c) f80 { | |
| 294 | fn __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 | } | |
| 297 | pub fn sqrt_f80(x: f80) f80 { | |
| 288 | 298 | var ix: u80 = @bitCast(x); |
| 289 | 299 | var top = ix >> 64; |
| 290 | 300 | |
| ... | ... | @@ -381,7 +391,10 @@ pub fn __sqrtx(x: f80) callconv(.c) f80 { |
| 381 | 391 | return y; |
| 382 | 392 | } |
| 383 | 393 | |
| 384 | pub fn sqrtq(x: f128) callconv(.c) f128 { | |
| 394 | fn 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 | } | |
| 397 | pub fn sqrt_f128(x: f128) f128 { | |
| 385 | 398 | var ix: u128 = @bitCast(x); |
| 386 | 399 | var top = ix >> 112; |
| 387 | 400 | |
| ... | ... | @@ -483,10 +496,10 @@ fn _Qp_sqrt(c: *f128, a: *f128) callconv(.c) void { |
| 483 | 496 | |
| 484 | 497 | pub fn sqrtl(x: c_longdouble) callconv(.c) c_longdouble { |
| 485 | 498 | switch (@typeInfo(c_longdouble).float.bits) { |
| 486 | 64 => return sqrt(x), | |
| 487 | 80 => return __sqrtx(x), | |
| 488 | 128 => return sqrtq(x), | |
| 489 | else => @compileError("unreachable"), | |
| 499 | 64 => return sqrt_f64(x), | |
| 500 | 80 => return sqrt_f80(x), | |
| 501 | 128 => return sqrt_f128(x), | |
| 502 | else => comptime unreachable, | |
| 490 | 503 | } |
| 491 | 504 | } |
| 492 | 505 | |
| ... | ... | @@ -545,187 +558,187 @@ inline fn mul80_tail(a: u80, b: u80) u80 { |
| 545 | 558 | return alo * blo +% ((ahi * blo) << 40) +% ((alo * bhi) << 40); |
| 546 | 559 | } |
| 547 | 560 | |
| 548 | test "__sqrth" { | |
| 561 | test "sqrt_f16" { | |
| 549 | 562 | // sqrt(±0) is ±0 |
| 550 | try std.testing.expectEqual(__sqrth(0x0.0p0), 0x0.0p0); | |
| 551 | try std.testing.expectEqual(__sqrth(-0x0.0p0), -0x0.0p0); | |
| 563 | try std.testing.expectEqual(sqrt_f16(0x0.0p0), 0x0.0p0); | |
| 564 | try std.testing.expectEqual(sqrt_f16(-0x0.0p0), -0x0.0p0); | |
| 552 | 565 | // 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 | 567 | // sqrt(4)=2 |
| 555 | try std.testing.expectEqual(__sqrth(0x1p2), 0x1p1); | |
| 568 | try std.testing.expectEqual(sqrt_f16(0x1p2), 0x1p1); | |
| 556 | 569 | // sqrt(x) for x=1, 1±ulp |
| 557 | try std.testing.expectEqual(__sqrth(0x1p0), 0x1p0); | |
| 558 | try std.testing.expectEqual(__sqrth(0x1.004p0), 0x1p0); | |
| 559 | try std.testing.expectEqual(__sqrth(0x1.FF8p-1), 0x1.FFCp-1); | |
| 570 | try std.testing.expectEqual(sqrt_f16(0x1p0), 0x1p0); | |
| 571 | try std.testing.expectEqual(sqrt_f16(0x1.004p0), 0x1p0); | |
| 572 | try std.testing.expectEqual(sqrt_f16(0x1.FF8p-1), 0x1.FFCp-1); | |
| 560 | 573 | // 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 | 575 | // 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 | 577 | // 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 | 579 | // 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 | 581 | // sqrt(-ve) is nan |
| 569 | try std.testing.expect(math.isNan(__sqrth(-0x1p-14))); | |
| 570 | try std.testing.expect(math.isNan(__sqrth(-0x1p+0))); | |
| 571 | try std.testing.expect(math.isNan(__sqrth(-math.inf(f16)))); | |
| 582 | try std.testing.expect(math.isNan(sqrt_f16(-0x1p-14))); | |
| 583 | try std.testing.expect(math.isNan(sqrt_f16(-0x1p+0))); | |
| 584 | try std.testing.expect(math.isNan(sqrt_f16(-math.inf(f16)))); | |
| 572 | 585 | // random arguments |
| 573 | try std.testing.expectEqual(__sqrth(0x1.1p14), 0x1.08p7); | |
| 574 | try std.testing.expectEqual(__sqrth(0x1.C9p-12), 0x1.56p-6); | |
| 575 | try std.testing.expectEqual(__sqrth(0x1.CE8p-7), 0x1.E68p-4); | |
| 576 | try std.testing.expectEqual(__sqrth(0x1.134p-7), 0x1.778p-4); | |
| 577 | try std.testing.expectEqual(__sqrth(0x1.E9Cp-10), 0x1.62p-5); | |
| 578 | try std.testing.expectEqual(__sqrth(0x1.3Dp9), 0x1.92Cp4); | |
| 579 | try std.testing.expectEqual(__sqrth(0x1.AA4p8), 0x1.4A4p4); | |
| 580 | try std.testing.expectEqual(__sqrth(0x1.8A8p4), 0x1.3DCp2); | |
| 581 | try std.testing.expectEqual(__sqrth(0x1.8Fp-7), 0x1.C4p-4); | |
| 582 | try std.testing.expectEqual(__sqrth(0x1.584p-11), 0x1.A3Cp-6); | |
| 586 | try std.testing.expectEqual(sqrt_f16(0x1.1p14), 0x1.08p7); | |
| 587 | try std.testing.expectEqual(sqrt_f16(0x1.C9p-12), 0x1.56p-6); | |
| 588 | try std.testing.expectEqual(sqrt_f16(0x1.CE8p-7), 0x1.E68p-4); | |
| 589 | try std.testing.expectEqual(sqrt_f16(0x1.134p-7), 0x1.778p-4); | |
| 590 | try std.testing.expectEqual(sqrt_f16(0x1.E9Cp-10), 0x1.62p-5); | |
| 591 | try std.testing.expectEqual(sqrt_f16(0x1.3Dp9), 0x1.92Cp4); | |
| 592 | try std.testing.expectEqual(sqrt_f16(0x1.AA4p8), 0x1.4A4p4); | |
| 593 | try std.testing.expectEqual(sqrt_f16(0x1.8A8p4), 0x1.3DCp2); | |
| 594 | try std.testing.expectEqual(sqrt_f16(0x1.8Fp-7), 0x1.C4p-4); | |
| 595 | try std.testing.expectEqual(sqrt_f16(0x1.584p-11), 0x1.A3Cp-6); | |
| 583 | 596 | } |
| 584 | 597 | |
| 585 | test "sqrtf" { | |
| 598 | test "sqrt_f32" { | |
| 586 | 599 | // sqrt(±0) is ±0 |
| 587 | try std.testing.expectEqual(sqrtf(0x0.0p0), 0x0.0p0); | |
| 588 | try std.testing.expectEqual(sqrtf(-0x0.0p0), -0x0.0p0); | |
| 600 | try std.testing.expectEqual(sqrt_f32(0x0.0p0), 0x0.0p0); | |
| 601 | try std.testing.expectEqual(sqrt_f32(-0x0.0p0), -0x0.0p0); | |
| 589 | 602 | // 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 | 604 | // sqrt(4)=2 |
| 592 | try std.testing.expectEqual(sqrtf(0x1p2), 0x1p1); | |
| 605 | try std.testing.expectEqual(sqrt_f32(0x1p2), 0x1p1); | |
| 593 | 606 | // sqrt(x) for x=1, 1±ulp |
| 594 | try std.testing.expectEqual(sqrtf(0x1p0), 0x1p0); | |
| 595 | try std.testing.expectEqual(sqrtf(0x1.000002p0), 0x1p0); | |
| 596 | try std.testing.expectEqual(sqrtf(0x1.FFFFFEp-1), 0x1.FFFFFEp-1); | |
| 607 | try std.testing.expectEqual(sqrt_f32(0x1p0), 0x1p0); | |
| 608 | try std.testing.expectEqual(sqrt_f32(0x1.000002p0), 0x1p0); | |
| 609 | try std.testing.expectEqual(sqrt_f32(0x1.FFFFFEp-1), 0x1.FFFFFEp-1); | |
| 597 | 610 | // 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 | 612 | // 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 | 614 | // 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 | 616 | // 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 | 618 | // sqrt(-ve) is nan |
| 606 | try std.testing.expect(math.isNan(sqrtf(-0x1p-149))); | |
| 607 | try std.testing.expect(math.isNan(sqrtf(-0x1p0))); | |
| 608 | try std.testing.expect(math.isNan(sqrtf(-math.inf(f32)))); | |
| 619 | try std.testing.expect(math.isNan(sqrt_f32(-0x1p-149))); | |
| 620 | try std.testing.expect(math.isNan(sqrt_f32(-0x1p0))); | |
| 621 | try std.testing.expect(math.isNan(sqrt_f32(-math.inf(f32)))); | |
| 609 | 622 | // random arguments |
| 610 | try std.testing.expectEqual(sqrtf(0x1.4DD57Ep77), 0x1.9D6DA8p38); | |
| 611 | try std.testing.expectEqual(sqrtf(0x1.871848p102), 0x1.3C6AFAp51); | |
| 612 | try std.testing.expectEqual(sqrtf(0x1.A1D748p-112), 0x1.470EFCp-56); | |
| 613 | try std.testing.expectEqual(sqrtf(0x1.E626C2p18), 0x1.60C80Ep9); | |
| 614 | try std.testing.expectEqual(sqrtf(0x1.E80E66p-29), 0x1.F3E282p-15); | |
| 615 | try std.testing.expectEqual(sqrtf(0x1.B47204p89), 0x1.D8B732p44); | |
| 616 | try std.testing.expectEqual(sqrtf(0x1.77F45p15), 0x1.B6BC3Ap7); | |
| 617 | try std.testing.expectEqual(sqrtf(0x1.AD5F5p-48), 0x1.4B8A72p-24); | |
| 618 | try std.testing.expectEqual(sqrtf(0x1.91A39p-76), 0x1.40A7A8p-38); | |
| 619 | try std.testing.expectEqual(sqrtf(0x1.DAE088p79), 0x1.ED16DCp39); | |
| 623 | try std.testing.expectEqual(sqrt_f32(0x1.4DD57Ep77), 0x1.9D6DA8p38); | |
| 624 | try std.testing.expectEqual(sqrt_f32(0x1.871848p102), 0x1.3C6AFAp51); | |
| 625 | try std.testing.expectEqual(sqrt_f32(0x1.A1D748p-112), 0x1.470EFCp-56); | |
| 626 | try std.testing.expectEqual(sqrt_f32(0x1.E626C2p18), 0x1.60C80Ep9); | |
| 627 | try std.testing.expectEqual(sqrt_f32(0x1.E80E66p-29), 0x1.F3E282p-15); | |
| 628 | try std.testing.expectEqual(sqrt_f32(0x1.B47204p89), 0x1.D8B732p44); | |
| 629 | try std.testing.expectEqual(sqrt_f32(0x1.77F45p15), 0x1.B6BC3Ap7); | |
| 630 | try std.testing.expectEqual(sqrt_f32(0x1.AD5F5p-48), 0x1.4B8A72p-24); | |
| 631 | try std.testing.expectEqual(sqrt_f32(0x1.91A39p-76), 0x1.40A7A8p-38); | |
| 632 | try std.testing.expectEqual(sqrt_f32(0x1.DAE088p79), 0x1.ED16DCp39); | |
| 620 | 633 | } |
| 621 | 634 | |
| 622 | test "sqrt" { | |
| 635 | test "sqrt_f64" { | |
| 623 | 636 | // sqrt(±0) is ±0 |
| 624 | try std.testing.expectEqual(sqrt(0x0.0p0), 0x0.0p0); | |
| 625 | try std.testing.expectEqual(sqrt(-0x0.0p0), -0x0.0p0); | |
| 637 | try std.testing.expectEqual(sqrt_f64(0x0.0p0), 0x0.0p0); | |
| 638 | try std.testing.expectEqual(sqrt_f64(-0x0.0p0), -0x0.0p0); | |
| 626 | 639 | // 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 | 641 | // sqrt(4)=2 |
| 629 | try std.testing.expectEqual(sqrt(0x1p2), 0x1p1); | |
| 642 | try std.testing.expectEqual(sqrt_f64(0x1p2), 0x1p1); | |
| 630 | 643 | // sqrt(x) for x=1, 1±ulp |
| 631 | try std.testing.expectEqual(sqrt(0x1p0), 0x1p0); | |
| 632 | try std.testing.expectEqual(sqrt(0x1p0 + math.floatEps(f64)), 0x1p0); | |
| 633 | try std.testing.expectEqual(sqrt(0x1p0 - math.floatEps(f64)), 0x1.FFFFFFFFFFFFFp-1); | |
| 644 | try std.testing.expectEqual(sqrt_f64(0x1p0), 0x1p0); | |
| 645 | try std.testing.expectEqual(sqrt_f64(0x1p0 + math.floatEps(f64)), 0x1p0); | |
| 646 | try std.testing.expectEqual(sqrt_f64(0x1p0 - math.floatEps(f64)), 0x1.FFFFFFFFFFFFFp-1); | |
| 634 | 647 | // 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 | 649 | // 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 | 651 | // 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 | 653 | // 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 | 655 | // sqrt(-ve) is nan |
| 643 | try std.testing.expect(math.isNan(sqrt(-0x1p-1074))); | |
| 644 | try std.testing.expect(math.isNan(sqrt(-0x1p0))); | |
| 645 | try std.testing.expect(math.isNan(sqrt(-math.inf(f64)))); | |
| 656 | try std.testing.expect(math.isNan(sqrt_f64(-0x1p-1074))); | |
| 657 | try std.testing.expect(math.isNan(sqrt_f64(-0x1p0))); | |
| 658 | try std.testing.expect(math.isNan(sqrt_f64(-math.inf(f64)))); | |
| 646 | 659 | // random arguments |
| 647 | try std.testing.expectEqual(sqrt(0x1.27D3510D4789Bp471), 0x1.852E97E58CFB7p235); | |
| 648 | try std.testing.expectEqual(sqrt(0x1.8C4FCD5A07846p791), 0x1.C27504E56D938p395); | |
| 649 | try std.testing.expectEqual(sqrt(0x1.B1B69324F96E7p-137), 0x1.D73BD0414D8BFp-69); | |
| 650 | try std.testing.expectEqual(sqrt(0x1.1CBD179A811FEp278), 0x1.0DFCB9A114A61p139); | |
| 651 | try std.testing.expectEqual(sqrt(0x1.1D0C7EFB04A56p917), 0x1.7E0708A25DDCDp458); | |
| 652 | try std.testing.expectEqual(sqrt(0x1.21B355DA8C94Bp-249), 0x1.8121CBE2608E3p-125); | |
| 653 | try std.testing.expectEqual(sqrt(0x1.63024D4C5E987p487), 0x1.AA56AEA589DCDp243); | |
| 654 | try std.testing.expectEqual(sqrt(0x1.45AC3BE941F6Ep339), 0x1.9857F3F453E2Dp169); | |
| 655 | try std.testing.expectEqual(sqrt(0x1.3B719C733AA24p267), 0x1.91E12E3AC8F71p133); | |
| 656 | try std.testing.expectEqual(sqrt(0x1.0B150433A2275p357), 0x1.71CAB87F8277Cp178); | |
| 660 | try std.testing.expectEqual(sqrt_f64(0x1.27D3510D4789Bp471), 0x1.852E97E58CFB7p235); | |
| 661 | try std.testing.expectEqual(sqrt_f64(0x1.8C4FCD5A07846p791), 0x1.C27504E56D938p395); | |
| 662 | try std.testing.expectEqual(sqrt_f64(0x1.B1B69324F96E7p-137), 0x1.D73BD0414D8BFp-69); | |
| 663 | try std.testing.expectEqual(sqrt_f64(0x1.1CBD179A811FEp278), 0x1.0DFCB9A114A61p139); | |
| 664 | try std.testing.expectEqual(sqrt_f64(0x1.1D0C7EFB04A56p917), 0x1.7E0708A25DDCDp458); | |
| 665 | try std.testing.expectEqual(sqrt_f64(0x1.21B355DA8C94Bp-249), 0x1.8121CBE2608E3p-125); | |
| 666 | try std.testing.expectEqual(sqrt_f64(0x1.63024D4C5E987p487), 0x1.AA56AEA589DCDp243); | |
| 667 | try std.testing.expectEqual(sqrt_f64(0x1.45AC3BE941F6Ep339), 0x1.9857F3F453E2Dp169); | |
| 668 | try std.testing.expectEqual(sqrt_f64(0x1.3B719C733AA24p267), 0x1.91E12E3AC8F71p133); | |
| 669 | try std.testing.expectEqual(sqrt_f64(0x1.0B150433A2275p357), 0x1.71CAB87F8277Cp178); | |
| 657 | 670 | } |
| 658 | 671 | |
| 659 | 672 | test "__sqrtx" { |
| 660 | 673 | // sqrt(±0) is ±0 |
| 661 | try std.testing.expectEqual(__sqrtx(0x0.0p0), 0x0.0p0); | |
| 662 | try std.testing.expectEqual(__sqrtx(-0x0.0p0), -0x0.0p0); | |
| 674 | try std.testing.expectEqual(sqrt_f80(0x0.0p0), 0x0.0p0); | |
| 675 | try std.testing.expectEqual(sqrt_f80(-0x0.0p0), -0x0.0p0); | |
| 663 | 676 | // 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 | 678 | // sqrt(4)=2 |
| 666 | try std.testing.expectEqual(__sqrtx(0x1p2), 0x1p1); | |
| 679 | try std.testing.expectEqual(sqrt_f80(0x1p2), 0x1p1); | |
| 667 | 680 | // sqrt(x) for x=1, 1±ulp |
| 668 | try std.testing.expectEqual(__sqrtx(0x1p0), 0x1p0); | |
| 669 | try std.testing.expectEqual(__sqrtx(0x1p0 + math.floatEps(f80)), 0x1p0); | |
| 670 | try std.testing.expectEqual(__sqrtx(0x1p0 - math.floatEps(f80)), 0x1.FFFFFFFFFFFFFFFEp-1); | |
| 681 | try std.testing.expectEqual(sqrt_f80(0x1p0), 0x1p0); | |
| 682 | try std.testing.expectEqual(sqrt_f80(0x1p0 + math.floatEps(f80)), 0x1p0); | |
| 683 | try std.testing.expectEqual(sqrt_f80(0x1p0 - math.floatEps(f80)), 0x1.FFFFFFFFFFFFFFFEp-1); | |
| 671 | 684 | // 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 | 686 | // 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 | 688 | // 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 | 690 | // 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 | 692 | // sqrt(-ve) is nan |
| 680 | try std.testing.expect(math.isNan(__sqrtx(-0x1p-16442))); | |
| 681 | try std.testing.expect(math.isNan(__sqrtx(-0x1p0))); | |
| 682 | try std.testing.expect(math.isNan(__sqrtx(-math.inf(f80)))); | |
| 693 | try std.testing.expect(math.isNan(sqrt_f80(-0x1p-16442))); | |
| 694 | try std.testing.expect(math.isNan(sqrt_f80(-0x1p0))); | |
| 695 | try std.testing.expect(math.isNan(sqrt_f80(-math.inf(f80)))); | |
| 683 | 696 | // random arguments |
| 684 | try std.testing.expectEqual(__sqrtx(0x1.087F3953486918A4p15482), 0x1.0436BBE03D02F32p7741); | |
| 685 | try std.testing.expectEqual(__sqrtx(0x1.530CF9E2AE84D8Fp-6330), 0x1.269CFEF51933BE58p-3165); | |
| 686 | try std.testing.expectEqual(__sqrtx(0x1.3F971515EADD574Ap5713), 0x1.9483232AB780B006p2856); | |
| 687 | try std.testing.expectEqual(__sqrtx(0x1.4CC0DC7379222954p864), 0x1.23DD4D0A4758C2Cp432); | |
| 688 | try std.testing.expectEqual(__sqrtx(0x1.920E5649559A839Ep-3181), 0x1.C5B5BC0F98DD83D2p-1591); | |
| 689 | try std.testing.expectEqual(__sqrtx(0x1.2E59726F87CD1746p-629), 0x1.8973327E95CB350Cp-315); | |
| 690 | try std.testing.expectEqual(__sqrtx(0x1.D3A16391F57B4D64p-9034), 0x1.59FF08B7DEEF5DB2p-4517); | |
| 691 | try std.testing.expectEqual(__sqrtx(0x1.E7053D8DAA49BCEEp-11411), 0x1.F35AA3EA5E18E344p-5706); | |
| 692 | try std.testing.expectEqual(__sqrtx(0x1.797ED0B05DD4A984p7521), 0x1.B7A22E40C6A7867Ap3760); | |
| 693 | try std.testing.expectEqual(__sqrtx(0x1.FC50806445C7226Ap15371), 0x1.FE2766142653F5BEp7685); | |
| 697 | try std.testing.expectEqual(sqrt_f80(0x1.087F3953486918A4p15482), 0x1.0436BBE03D02F32p7741); | |
| 698 | try std.testing.expectEqual(sqrt_f80(0x1.530CF9E2AE84D8Fp-6330), 0x1.269CFEF51933BE58p-3165); | |
| 699 | try std.testing.expectEqual(sqrt_f80(0x1.3F971515EADD574Ap5713), 0x1.9483232AB780B006p2856); | |
| 700 | try std.testing.expectEqual(sqrt_f80(0x1.4CC0DC7379222954p864), 0x1.23DD4D0A4758C2Cp432); | |
| 701 | try std.testing.expectEqual(sqrt_f80(0x1.920E5649559A839Ep-3181), 0x1.C5B5BC0F98DD83D2p-1591); | |
| 702 | try std.testing.expectEqual(sqrt_f80(0x1.2E59726F87CD1746p-629), 0x1.8973327E95CB350Cp-315); | |
| 703 | try std.testing.expectEqual(sqrt_f80(0x1.D3A16391F57B4D64p-9034), 0x1.59FF08B7DEEF5DB2p-4517); | |
| 704 | try std.testing.expectEqual(sqrt_f80(0x1.E7053D8DAA49BCEEp-11411), 0x1.F35AA3EA5E18E344p-5706); | |
| 705 | try std.testing.expectEqual(sqrt_f80(0x1.797ED0B05DD4A984p7521), 0x1.B7A22E40C6A7867Ap3760); | |
| 706 | try std.testing.expectEqual(sqrt_f80(0x1.FC50806445C7226Ap15371), 0x1.FE2766142653F5BEp7685); | |
| 694 | 707 | } |
| 695 | 708 | |
| 696 | test "sqrtq" { | |
| 709 | test "sqrt_f128" { | |
| 697 | 710 | // sqrt(±0) is ±0 |
| 698 | try std.testing.expectEqual(sqrtq(0x0.0p0), 0x0.0p0); | |
| 699 | try std.testing.expectEqual(sqrtq(-0x0.0p0), -0x0.0p0); | |
| 711 | try std.testing.expectEqual(sqrt_f128(0x0.0p0), 0x0.0p0); | |
| 712 | try std.testing.expectEqual(sqrt_f128(-0x0.0p0), -0x0.0p0); | |
| 700 | 713 | // 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 | 715 | // sqrt(4)=2 |
| 703 | try std.testing.expectEqual(sqrtq(0x1p2), 0x1p1); | |
| 716 | try std.testing.expectEqual(sqrt_f128(0x1p2), 0x1p1); | |
| 704 | 717 | // sqrt(x) for x=1, 1±ulp |
| 705 | try std.testing.expectEqual(sqrtq(0x1p0), 0x1p0); | |
| 706 | try std.testing.expectEqual(sqrtq(0x1p0 + math.floatEps(f128)), 0x1p0); | |
| 707 | try std.testing.expectEqual(sqrtq(0x1p0 - math.floatEps(f128)), 0x1.FFFFFFFFFFFFFFFFFFFFFFFFFFFFp-1); | |
| 718 | try std.testing.expectEqual(sqrt_f128(0x1p0), 0x1p0); | |
| 719 | try std.testing.expectEqual(sqrt_f128(0x1p0 + math.floatEps(f128)), 0x1p0); | |
| 720 | try std.testing.expectEqual(sqrt_f128(0x1p0 - math.floatEps(f128)), 0x1.FFFFFFFFFFFFFFFFFFFFFFFFFFFFp-1); | |
| 708 | 721 | // 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 | 723 | // 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 | 725 | // 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 | 727 | // 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 | 729 | // sqrt(-ve) is nan |
| 717 | try std.testing.expect(math.isNan(sqrtq(-0x1p-16442))); | |
| 718 | try std.testing.expect(math.isNan(sqrtq(-0x1p0))); | |
| 719 | try std.testing.expect(math.isNan(sqrtq(-math.inf(f128)))); | |
| 730 | try std.testing.expect(math.isNan(sqrt_f128(-0x1p-16442))); | |
| 731 | try std.testing.expect(math.isNan(sqrt_f128(-0x1p0))); | |
| 732 | try std.testing.expect(math.isNan(sqrt_f128(-math.inf(f128)))); | |
| 720 | 733 | // random arguments |
| 721 | try std.testing.expectEqual(sqrtq(0x1.B6942D29A331751600C9F3AF7E5Fp3363), 0x1.D9DE9AFEF0F2D25586A50CA39D4Dp1681); | |
| 722 | try std.testing.expectEqual(sqrtq(0x1.5E65C405F84D471A8070ADD7A42Dp11765), 0x1.A78F7F9452B4D9EC2403C81D9D42p5882); | |
| 723 | try std.testing.expectEqual(sqrtq(0x1.B42334D68F8016D8AE6F5E22B044p-5624), 0x1.4E247A7F2FF2A325E9377BB09C8p-2812); | |
| 724 | try std.testing.expectEqual(sqrtq(0x1.E61715047F80F2E0B9382B38E06Bp10062), 0x1.60C25D9DFDC0116B78EF5AFDE0E9p5031); | |
| 725 | try std.testing.expectEqual(sqrtq(0x1.2ED0B53B494CB55A7B04E653D40Ep-1026), 0x1.166CE78D658D2453D700B04C5748p-513); | |
| 726 | try std.testing.expectEqual(sqrtq(0x1.1BA756B9790E78A4E6F0B083AA89p1835), 0x1.7D1767EA3303DB7A46940033988p917); | |
| 727 | try std.testing.expectEqual(sqrtq(0x1.5B6C574319C1120335C8E1609704p4512), 0x1.2A3A8A415BB1648C548FBA2A4182p2256); | |
| 728 | try std.testing.expectEqual(sqrtq(0x1.FF91E8CDEE1552A2B74E77B602Ep14953), 0x1.FFC8F171267D4FE75CBE7AB4D851p7476); | |
| 729 | try std.testing.expectEqual(sqrtq(0x1.9B1837CFC629A1B6B1BB97099E7Dp2892), 0x1.4468511B909EAF8641BD59105A6Bp1446); | |
| 730 | try std.testing.expectEqual(sqrtq(0x1.0E2115475E64A92340914E7F7B37p-13951), 0x1.73E536F82F414134012F55BA5368p-6976); | |
| 734 | try std.testing.expectEqual(sqrt_f128(0x1.B6942D29A331751600C9F3AF7E5Fp3363), 0x1.D9DE9AFEF0F2D25586A50CA39D4Dp1681); | |
| 735 | try std.testing.expectEqual(sqrt_f128(0x1.5E65C405F84D471A8070ADD7A42Dp11765), 0x1.A78F7F9452B4D9EC2403C81D9D42p5882); | |
| 736 | try std.testing.expectEqual(sqrt_f128(0x1.B42334D68F8016D8AE6F5E22B044p-5624), 0x1.4E247A7F2FF2A325E9377BB09C8p-2812); | |
| 737 | try std.testing.expectEqual(sqrt_f128(0x1.E61715047F80F2E0B9382B38E06Bp10062), 0x1.60C25D9DFDC0116B78EF5AFDE0E9p5031); | |
| 738 | try std.testing.expectEqual(sqrt_f128(0x1.2ED0B53B494CB55A7B04E653D40Ep-1026), 0x1.166CE78D658D2453D700B04C5748p-513); | |
| 739 | try std.testing.expectEqual(sqrt_f128(0x1.1BA756B9790E78A4E6F0B083AA89p1835), 0x1.7D1767EA3303DB7A46940033988p917); | |
| 740 | try std.testing.expectEqual(sqrt_f128(0x1.5B6C574319C1120335C8E1609704p4512), 0x1.2A3A8A415BB1648C548FBA2A4182p2256); | |
| 741 | try std.testing.expectEqual(sqrt_f128(0x1.FF91E8CDEE1552A2B74E77B602Ep14953), 0x1.FFC8F171267D4FE75CBE7AB4D851p7476); | |
| 742 | try std.testing.expectEqual(sqrt_f128(0x1.9B1837CFC629A1B6B1BB97099E7Dp2892), 0x1.4468511B909EAF8641BD59105A6Bp1446); | |
| 743 | try std.testing.expectEqual(sqrt_f128(0x1.0E2115475E64A92340914E7F7B37p-13951), 0x1.73E536F82F414134012F55BA5368p-6976); | |
| 731 | 744 | } |
lib/compiler_rt/ssp.zig+2-2| ... | ... | @@ -17,7 +17,7 @@ const compiler_rt = @import("../compiler_rt.zig"); |
| 17 | 17 | const symbol = compiler_rt.symbol; |
| 18 | 18 | const builtin = @import("builtin"); |
| 19 | 19 | |
| 20 | extern fn memset(dest: ?[*]u8, c: u8, n: usize) callconv(.c) ?[*]u8; | |
| 20 | extern fn memset(dest: ?[*]u8, c: c_int, n: usize) callconv(.c) ?[*]u8; | |
| 21 | 21 | extern fn memcpy(noalias dest: ?[*]u8, noalias src: ?[*]const u8, n: usize) callconv(.c) ?[*]u8; |
| 22 | 22 | extern fn memmove(dest: ?[*]u8, src: ?[*]const u8, n: usize) callconv(.c) ?[*]u8; |
| 23 | 23 | |
| ... | ... | @@ -138,7 +138,7 @@ fn __memmove_chk(dest: ?[*]u8, src: ?[*]const u8, n: usize, dest_n: usize) callc |
| 138 | 138 | return memmove(dest, src, n); |
| 139 | 139 | } |
| 140 | 140 | |
| 141 | fn __memset_chk(dest: ?[*]u8, c: u8, n: usize, dest_n: usize) callconv(.c) ?[*]u8 { | |
| 141 | fn __memset_chk(dest: ?[*]u8, c: c_int, n: usize, dest_n: usize) callconv(.c) ?[*]u8 { | |
| 142 | 142 | if (dest_n < n) __chk_fail(); |
| 143 | 143 | return memset(dest, c, n); |
| 144 | 144 | } |
lib/compiler_rt/subdf3.zig deleted-24| ... | ... | @@ -1,24 +0,0 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const addf3 = @import("./addf3.zig").addf3; | |
| 3 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 4 | ||
| 5 | comptime { | |
| 6 | if (compiler_rt.want_aeabi) { | |
| 7 | symbol(&__aeabi_dsub, "__aeabi_dsub"); | |
| 8 | } else { | |
| 9 | symbol(&__subdf3, "__subdf3"); | |
| 10 | } | |
| 11 | } | |
| 12 | ||
| 13 | fn __subdf3(a: f64, b: f64) callconv(.c) f64 { | |
| 14 | return sub(a, b); | |
| 15 | } | |
| 16 | ||
| 17 | fn __aeabi_dsub(a: f64, b: f64) callconv(.{ .arm_aapcs = .{} }) f64 { | |
| 18 | return sub(a, b); | |
| 19 | } | |
| 20 | ||
| 21 | inline 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 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = compiler_rt.symbol; | |
| 3 | const addf3 = @import("./addf3.zig").addf3; | |
| 4 | ||
| 5 | comptime { | |
| 6 | symbol(&__subhf3, "__subhf3"); | |
| 7 | } | |
| 8 | ||
| 9 | fn __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 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = compiler_rt.symbol; | |
| 3 | const addf3 = @import("./addf3.zig").addf3; | |
| 4 | ||
| 5 | comptime { | |
| 6 | if (compiler_rt.want_aeabi) { | |
| 7 | symbol(&__aeabi_fsub, "__aeabi_fsub"); | |
| 8 | } else { | |
| 9 | symbol(&__subsf3, "__subsf3"); | |
| 10 | } | |
| 11 | } | |
| 12 | ||
| 13 | fn __subsf3(a: f32, b: f32) callconv(.c) f32 { | |
| 14 | return sub(a, b); | |
| 15 | } | |
| 16 | ||
| 17 | fn __aeabi_fsub(a: f32, b: f32) callconv(.{ .arm_aapcs = .{} }) f32 { | |
| 18 | return sub(a, b); | |
| 19 | } | |
| 20 | ||
| 21 | inline 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 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = compiler_rt.symbol; | |
| 3 | const addf3 = @import("./addf3.zig").addf3; | |
| 4 | ||
| 5 | comptime { | |
| 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 | ||
| 16 | pub fn __subtf3(a: f128, b: f128) callconv(.c) f128 { | |
| 17 | return sub(a, b); | |
| 18 | } | |
| 19 | ||
| 20 | fn _Qp_sub(c: *f128, a: *const f128, b: *const f128) callconv(.c) void { | |
| 21 | c.* = sub(a.*, b.*); | |
| 22 | } | |
| 23 | ||
| 24 | inline 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 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 2 | 1 | const testing = @import("std").testing; |
| 2 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 3 | const symbol = compiler_rt.symbol; | |
| 3 | 4 | |
| 4 | 5 | comptime { |
| 5 | 6 | symbol(&__subvdi3, "__subvdi3"); |
| ... | ... | @@ -9,7 +10,7 @@ pub fn __subvdi3(a: i64, b: i64) callconv(.c) i64 { |
| 9 | 10 | const sum = a -% b; |
| 10 | 11 | // Overflow occurred iff the operands have opposite signs, and the sign of the |
| 11 | 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 | 14 | return sum; |
| 14 | 15 | } |
| 15 | 16 |
lib/compiler_rt/subvsi3.zig+1-1| ... | ... | @@ -10,7 +10,7 @@ pub fn __subvsi3(a: i32, b: i32) callconv(.c) i32 { |
| 10 | 10 | const sum = a -% b; |
| 11 | 11 | // Overflow occurred iff the operands have opposite signs, and the sign of the |
| 12 | 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 | 14 | return sum; |
| 15 | 15 | } |
| 16 | 16 |
lib/compiler_rt/subxf3.zig deleted-13| ... | ... | @@ -1,13 +0,0 @@ |
| 1 | const std = @import("std"); | |
| 2 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 3 | ||
| 4 | comptime { | |
| 5 | symbol(&__subxf3, "__subxf3"); | |
| 6 | } | |
| 7 | ||
| 8 | fn __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 | 21 | |
| 22 | 22 | const arch = builtin.cpu.arch; |
| 23 | 23 | const compiler_rt = @import("../compiler_rt.zig"); |
| 24 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 24 | const symbol = compiler_rt.symbol; | |
| 25 | 25 | |
| 26 | 26 | comptime { |
| 27 | symbol(&tanh, "__tanh"); | |
| 27 | symbol(&__tanh, "__tanh"); | |
| 28 | 28 | symbol(&tanf, "tanf"); |
| 29 | 29 | symbol(&tan, "tan"); |
| 30 | symbol(&tanx, "__tanx"); | |
| 31 | if (compiler_rt.want_ppc_abi) { | |
| 32 | symbol(&tanq, "tanf128"); | |
| 33 | } | |
| 34 | symbol(&tanq, "tanq"); | |
| 30 | symbol(&__tanx, "__tanx"); | |
| 31 | symbol(&tanq, "tanf128"); | |
| 35 | 32 | symbol(&tanl, "tanl"); |
| 36 | 33 | } |
| 37 | 34 | |
| 38 | pub fn tanh(x: f16) callconv(.c) f16 { | |
| 35 | fn __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 | } | |
| 38 | pub fn tan_f16(x: f16) f16 { | |
| 39 | 39 | // TODO: more efficient implementation |
| 40 | return @floatCast(tanf(x)); | |
| 40 | return @floatCast(tan_f32(x)); | |
| 41 | 41 | } |
| 42 | 42 | |
| 43 | pub fn tanf(x: f32) callconv(.c) f32 { | |
| 43 | fn 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 | } | |
| 46 | pub fn tan_f32(x: f32) f32 { | |
| 44 | 47 | // Small multiples of pi/2 rounded to double precision. |
| 45 | 48 | const t1pio2: f64 = 1.0 * math.pi / 2.0; // 0x3FF921FB, 0x54442D18 |
| 46 | 49 | const t2pio2: f64 = 2.0 * math.pi / 2.0; // 0x400921FB, 0x54442D18 |
| ... | ... | @@ -90,7 +93,10 @@ pub fn tanf(x: f32) callconv(.c) f32 { |
| 90 | 93 | return kernel.tandf(y, n & 1 != 0); |
| 91 | 94 | } |
| 92 | 95 | |
| 93 | pub fn tan(x: f64) callconv(.c) f64 { | |
| 96 | fn 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 | } | |
| 99 | pub fn tan_f64(x: f64) f64 { | |
| 94 | 100 | var ix = @as(u64, @bitCast(x)) >> 32; |
| 95 | 101 | ix &= 0x7fffffff; |
| 96 | 102 | |
| ... | ... | @@ -120,7 +126,10 @@ pub fn tan(x: f64) callconv(.c) f64 { |
| 120 | 126 | return kernel.tan(y[0], y[1], n & 1 != 0); |
| 121 | 127 | } |
| 122 | 128 | |
| 123 | pub fn tanx(x: f80) callconv(.c) f80 { | |
| 129 | fn __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 | } | |
| 132 | pub fn tan_f80(x: f80) f80 { | |
| 124 | 133 | const se = ld.signExponent(x) & 0x7fff; |
| 125 | 134 | if (se == 0x7fff) { |
| 126 | 135 | return x - x; |
| ... | ... | @@ -141,7 +150,10 @@ pub fn tanx(x: f80) callconv(.c) f80 { |
| 141 | 150 | return kernel.tanx(y[0], y[1], n & 1); |
| 142 | 151 | } |
| 143 | 152 | |
| 144 | pub fn tanq(x: f128) callconv(.c) f128 { | |
| 153 | fn 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 | } | |
| 156 | pub fn tan_f128(x: f128) f128 { | |
| 145 | 157 | const se = ld.signExponent(x) & 0x7fff; |
| 146 | 158 | if (se == 0x7fff) { |
| 147 | 159 | return x - x; |
| ... | ... | @@ -164,18 +176,21 @@ pub fn tanq(x: f128) callconv(.c) f128 { |
| 164 | 176 | |
| 165 | 177 | pub fn tanl(x: c_longdouble) callconv(.c) c_longdouble { |
| 166 | 178 | switch (@typeInfo(c_longdouble).float.bits) { |
| 167 | 64 => return tan(x), | |
| 168 | 80 => return tanx(x), | |
| 169 | 128 => return tanq(x), | |
| 170 | else => @compileError("unreachable"), | |
| 179 | 64 => return tan_f64(x), | |
| 180 | 80 => return tan_f80(x), | |
| 181 | 128 => return tan_f128(x), | |
| 182 | else => comptime unreachable, | |
| 171 | 183 | } |
| 172 | 184 | } |
| 173 | 185 | |
| 174 | 186 | fn testTanNormal(comptime T: type) !void { |
| 175 | 187 | const f = switch (T) { |
| 176 | f32 => tanf, | |
| 177 | f64 => tan, | |
| 178 | else => @compileError("unimplemented"), | |
| 188 | f16 => tan_f16, | |
| 189 | f32 => tan_f32, | |
| 190 | f64 => tan_f64, | |
| 191 | f80 => tan_f80, | |
| 192 | f128 => tan_f128, | |
| 193 | else => comptime unreachable, | |
| 179 | 194 | }; |
| 180 | 195 | const epsilon = 0.00001; |
| 181 | 196 | |
| ... | ... | @@ -189,11 +204,12 @@ fn testTanNormal(comptime T: type) !void { |
| 189 | 204 | |
| 190 | 205 | fn testTanSpecial(comptime T: type) !void { |
| 191 | 206 | const f = switch (T) { |
| 192 | f32 => tanf, | |
| 193 | f64 => tan, | |
| 194 | f80 => tanx, | |
| 195 | f128 => tanq, | |
| 196 | else => @compileError("unimplemented"), | |
| 207 | f16 => tan_f16, | |
| 208 | f32 => tan_f32, | |
| 209 | f64 => tan_f64, | |
| 210 | f80 => tan_f80, | |
| 211 | f128 => tan_f128, | |
| 212 | else => comptime unreachable, | |
| 197 | 213 | }; |
| 198 | 214 | |
| 199 | 215 | try expect(math.isPositiveZero(f(0.0))); |
| ... | ... | @@ -214,23 +230,23 @@ test "tan64.normal" { |
| 214 | 230 | test "tan80.normal" { |
| 215 | 231 | const epsilon = math.floatEps(f80); |
| 216 | 232 | |
| 217 | try expectApproxEqAbs(@as(f80, 0.0), tanx(0.0), epsilon); | |
| 218 | try expectApproxEqAbs(@as(f80, 0.2027100355086724833213582716475345), tanx(0.2), epsilon); | |
| 219 | try expectApproxEqAbs(@as(f80, 1.2404217445497097995561220131857544), tanx(0.8923), epsilon); | |
| 220 | try expectApproxEqAbs(@as(f80, 14.10141994717171938764), tanx(1.5), epsilon); | |
| 221 | try expectApproxEqAbs(@as(f80, -0.25439607116885656232), tanx(37.45), epsilon); | |
| 222 | try expectApproxEqAbs(@as(f80, 2.2858376251355320963), tanx(89.123), epsilon); | |
| 233 | try expectApproxEqAbs(@as(f80, 0.0), tan_f80(0.0), epsilon); | |
| 234 | try expectApproxEqAbs(@as(f80, 0.2027100355086724833213582716475345), tan_f80(0.2), epsilon); | |
| 235 | try expectApproxEqAbs(@as(f80, 1.2404217445497097995561220131857544), tan_f80(0.8923), epsilon); | |
| 236 | try expectApproxEqAbs(@as(f80, 14.10141994717171938764), tan_f80(1.5), epsilon); | |
| 237 | try expectApproxEqAbs(@as(f80, -0.25439607116885656232), tan_f80(37.45), epsilon); | |
| 238 | try expectApproxEqAbs(@as(f80, 2.2858376251355320963), tan_f80(89.123), epsilon); | |
| 223 | 239 | } |
| 224 | 240 | |
| 225 | 241 | test "tan128.normal" { |
| 226 | 242 | const epsilon = math.floatEps(f128); |
| 227 | 243 | |
| 228 | try expectApproxEqAbs(@as(f128, 0.0), tanq(0.0), epsilon); | |
| 229 | try expectApproxEqAbs(@as(f128, 0.2027100355086724833213582716475345), tanq(0.2), epsilon); | |
| 230 | try expectApproxEqAbs(@as(f128, 1.2404217445497097995561220131857544), tanq(0.8923), epsilon); | |
| 231 | try expectApproxEqAbs(@as(f128, 14.101419947171719387646083651987755), tanq(1.5), epsilon); | |
| 232 | try expectApproxEqAbs(@as(f128, -0.2543960711688565630469573224504774), tanq(37.45), epsilon); | |
| 233 | try expectApproxEqAbs(@as(f128, 2.2858376251355321074066028114094292), tanq(89.123), epsilon); | |
| 244 | try expectApproxEqAbs(@as(f128, 0.0), tan_f128(0.0), epsilon); | |
| 245 | try expectApproxEqAbs(@as(f128, 0.2027100355086724833213582716475345), tan_f128(0.2), epsilon); | |
| 246 | try expectApproxEqAbs(@as(f128, 1.2404217445497097995561220131857544), tan_f128(0.8923), epsilon); | |
| 247 | try expectApproxEqAbs(@as(f128, 14.101419947171719387646083651987755), tan_f128(1.5), epsilon); | |
| 248 | try expectApproxEqAbs(@as(f128, -0.2543960711688565630469573224504774), tan_f128(37.45), epsilon); | |
| 249 | try expectApproxEqAbs(@as(f128, 2.2858376251355321074066028114094292), tan_f128(89.123), epsilon); | |
| 234 | 250 | } |
| 235 | 251 | |
| 236 | 252 | test "tan32.special" { |
lib/compiler_rt/trunc.zig+77-47| ... | ... | @@ -17,19 +17,22 @@ comptime { |
| 17 | 17 | symbol(&truncf, "truncf"); |
| 18 | 18 | symbol(&trunc, "trunc"); |
| 19 | 19 | symbol(&__truncx, "__truncx"); |
| 20 | if (compiler_rt.want_ppc_abi) { | |
| 21 | symbol(&truncq, "truncf128"); | |
| 22 | } | |
| 23 | symbol(&truncq, "truncq"); | |
| 20 | symbol(&truncq, "truncf128"); | |
| 24 | 21 | symbol(&truncl, "truncl"); |
| 25 | 22 | } |
| 26 | 23 | |
| 27 | pub fn __trunch(x: f16) callconv(.c) f16 { | |
| 24 | fn __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 | } | |
| 27 | pub fn trunc_f16(x: f16) f16 { | |
| 28 | 28 | // TODO: more efficient implementation |
| 29 | return @floatCast(truncf(x)); | |
| 29 | return @floatCast(trunc_f32(x)); | |
| 30 | 30 | } |
| 31 | 31 | |
| 32 | pub fn truncf(x: f32) callconv(.c) f32 { | |
| 32 | fn 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 | } | |
| 35 | pub fn trunc_f32(x: f32) f32 { | |
| 33 | 36 | const u: u32 = @bitCast(x); |
| 34 | 37 | var e = @as(i32, @intCast(((u >> 23) & 0xFF))) - 0x7F + 9; |
| 35 | 38 | var m: u32 = undefined; |
| ... | ... | @@ -50,7 +53,10 @@ pub fn truncf(x: f32) callconv(.c) f32 { |
| 50 | 53 | } |
| 51 | 54 | } |
| 52 | 55 | |
| 53 | pub fn trunc(x: f64) callconv(.c) f64 { | |
| 56 | fn 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 | } | |
| 59 | pub fn trunc_f64(x: f64) f64 { | |
| 54 | 60 | const u: u64 = @bitCast(x); |
| 55 | 61 | var e = @as(i32, @intCast(((u >> 52) & 0x7FF))) - 0x3FF + 12; |
| 56 | 62 | var m: u64 = undefined; |
| ... | ... | @@ -71,12 +77,18 @@ pub fn trunc(x: f64) callconv(.c) f64 { |
| 71 | 77 | } |
| 72 | 78 | } |
| 73 | 79 | |
| 74 | pub fn __truncx(x: f80) callconv(.c) f80 { | |
| 80 | fn __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 | } | |
| 83 | pub fn trunc_f80(x: f80) f80 { | |
| 75 | 84 | // TODO: more efficient implementation |
| 76 | return @floatCast(truncq(x)); | |
| 85 | return @floatCast(trunc_f128(x)); | |
| 77 | 86 | } |
| 78 | 87 | |
| 79 | pub fn truncq(x: f128) callconv(.c) f128 { | |
| 88 | fn 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 | } | |
| 91 | pub fn trunc_f128(x: f128) f128 { | |
| 80 | 92 | const u: u128 = @bitCast(x); |
| 81 | 93 | var e = @as(i32, @intCast(((u >> 112) & 0x7FFF))) - 0x3FFF + 16; |
| 82 | 94 | var m: u128 = undefined; |
| ... | ... | @@ -99,51 +111,69 @@ pub fn truncq(x: f128) callconv(.c) f128 { |
| 99 | 111 | |
| 100 | 112 | pub fn truncl(x: c_longdouble) callconv(.c) c_longdouble { |
| 101 | 113 | switch (@typeInfo(c_longdouble).float.bits) { |
| 102 | 64 => return trunc(x), | |
| 103 | 80 => return __truncx(x), | |
| 104 | 128 => return truncq(x), | |
| 105 | else => @compileError("unreachable"), | |
| 114 | 64 => return trunc_f64(x), | |
| 115 | 80 => return trunc_f80(x), | |
| 116 | 128 => return trunc_f128(x), | |
| 117 | else => comptime unreachable, | |
| 106 | 118 | } |
| 107 | 119 | } |
| 108 | 120 | |
| 109 | test "trunc32" { | |
| 110 | try expect(truncf(1.3) == 1.0); | |
| 111 | try expect(truncf(-1.3) == -1.0); | |
| 112 | try expect(truncf(0.2) == 0.0); | |
| 113 | } | |
| 114 | ||
| 115 | test "trunc64" { | |
| 116 | try expect(trunc(1.3) == 1.0); | |
| 117 | try expect(trunc(-1.3) == -1.0); | |
| 118 | try expect(trunc(0.2) == 0.0); | |
| 121 | test trunc_f16 { | |
| 122 | try expect(trunc_f16(1.3) == 1.0); | |
| 123 | try expect(trunc_f16(-1.3) == -1.0); | |
| 124 | try expect(math.isPositiveZero(trunc_f16(0.2))); | |
| 125 | try expect(math.isNegativeZero(trunc_f16(-0.2))); | |
| 126 | try expect(math.isPositiveZero(trunc_f16(0.0))); | |
| 127 | try expect(math.isNegativeZero(trunc_f16(-0.0))); | |
| 128 | try expect(math.isPositiveInf(trunc_f16(math.inf(f32)))); | |
| 129 | try expect(math.isNegativeInf(trunc_f16(-math.inf(f32)))); | |
| 130 | try expect(math.isNan(trunc_f16(math.nan(f32)))); | |
| 119 | 131 | } |
| 120 | 132 | |
| 121 | test "trunc128" { | |
| 122 | try expect(truncq(1.3) == 1.0); | |
| 123 | try expect(truncq(-1.3) == -1.0); | |
| 124 | try expect(truncq(0.2) == 0.0); | |
| 133 | test trunc_f32 { | |
| 134 | try expect(trunc_f32(1.3) == 1.0); | |
| 135 | try expect(trunc_f32(-1.3) == -1.0); | |
| 136 | try expect(math.isPositiveZero(trunc_f32(0.2))); | |
| 137 | try expect(math.isNegativeZero(trunc_f32(-0.2))); | |
| 138 | try expect(math.isPositiveZero(trunc_f32(0.0))); | |
| 139 | try expect(math.isNegativeZero(trunc_f32(-0.0))); | |
| 140 | try expect(math.isPositiveInf(trunc_f32(math.inf(f32)))); | |
| 141 | try expect(math.isNegativeInf(trunc_f32(-math.inf(f32)))); | |
| 142 | try expect(math.isNan(trunc_f32(math.nan(f32)))); | |
| 125 | 143 | } |
| 126 | 144 | |
| 127 | test "trunc32.special" { | |
| 128 | try expect(truncf(0.0) == 0.0); // 0x3F800000 | |
| 129 | try expect(truncf(-0.0) == -0.0); | |
| 130 | try expect(math.isPositiveInf(truncf(math.inf(f32)))); | |
| 131 | try expect(math.isNegativeInf(truncf(-math.inf(f32)))); | |
| 132 | try expect(math.isNan(truncf(math.nan(f32)))); | |
| 145 | test trunc_f64 { | |
| 146 | try expect(trunc_f64(1.3) == 1.0); | |
| 147 | try expect(trunc_f64(-1.3) == -1.0); | |
| 148 | try expect(math.isPositiveZero(trunc_f64(0.2))); | |
| 149 | try expect(math.isNegativeZero(trunc_f64(-0.2))); | |
| 150 | try expect(math.isPositiveZero(trunc_f64(0.0))); | |
| 151 | try expect(math.isNegativeZero(trunc_f64(-0.0))); | |
| 152 | try expect(math.isPositiveInf(trunc_f64(math.inf(f64)))); | |
| 153 | try expect(math.isNegativeInf(trunc_f64(-math.inf(f64)))); | |
| 154 | try expect(math.isNan(trunc_f64(math.nan(f64)))); | |
| 133 | 155 | } |
| 134 | 156 | |
| 135 | test "trunc64.special" { | |
| 136 | try expect(trunc(0.0) == 0.0); | |
| 137 | try expect(trunc(-0.0) == -0.0); | |
| 138 | try expect(math.isPositiveInf(trunc(math.inf(f64)))); | |
| 139 | try expect(math.isNegativeInf(trunc(-math.inf(f64)))); | |
| 140 | try expect(math.isNan(trunc(math.nan(f64)))); | |
| 157 | test trunc_f80 { | |
| 158 | try expect(trunc_f80(1.3) == 1.0); | |
| 159 | try expect(trunc_f80(-1.3) == -1.0); | |
| 160 | try expect(math.isPositiveZero(trunc_f80(0.2))); | |
| 161 | try expect(math.isNegativeZero(trunc_f80(-0.2))); | |
| 162 | try expect(math.isPositiveZero(trunc_f80(0.0))); | |
| 163 | try expect(math.isNegativeZero(trunc_f80(-0.0))); | |
| 164 | try expect(math.isPositiveInf(trunc_f80(math.inf(f64)))); | |
| 165 | try expect(math.isNegativeInf(trunc_f80(-math.inf(f64)))); | |
| 166 | try expect(math.isNan(trunc_f80(math.nan(f64)))); | |
| 141 | 167 | } |
| 142 | 168 | |
| 143 | test "trunc128.special" { | |
| 144 | try expect(truncq(0.0) == 0.0); | |
| 145 | try expect(truncq(-0.0) == -0.0); | |
| 146 | try expect(math.isPositiveInf(truncq(math.inf(f128)))); | |
| 147 | try expect(math.isNegativeInf(truncq(-math.inf(f128)))); | |
| 148 | try expect(math.isNan(truncq(math.nan(f128)))); | |
| 169 | test trunc_f128 { | |
| 170 | try expect(trunc_f128(1.3) == 1.0); | |
| 171 | try expect(trunc_f128(-1.3) == -1.0); | |
| 172 | try expect(math.isPositiveZero(trunc_f128(0.2))); | |
| 173 | try expect(math.isNegativeZero(trunc_f128(-0.2))); | |
| 174 | try expect(math.isPositiveZero(trunc_f128(0.0))); | |
| 175 | try expect(math.isNegativeZero(trunc_f128(-0.0))); | |
| 176 | try expect(math.isPositiveInf(trunc_f128(math.inf(f128)))); | |
| 177 | try expect(math.isNegativeInf(trunc_f128(-math.inf(f128)))); | |
| 178 | try expect(math.isNan(trunc_f128(math.nan(f128)))); | |
| 149 | 179 | } |
lib/compiler_rt/truncdfhf2.zig deleted-18| ... | ... | @@ -1,18 +0,0 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const truncf = @import("./truncf.zig").truncf; | |
| 3 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 4 | ||
| 5 | comptime { | |
| 6 | if (compiler_rt.want_aeabi) { | |
| 7 | symbol(&__aeabi_d2h, "__aeabi_d2h"); | |
| 8 | } | |
| 9 | symbol(&__truncdfhf2, "__truncdfhf2"); | |
| 10 | } | |
| 11 | ||
| 12 | pub fn __truncdfhf2(a: f64) callconv(.c) compiler_rt.F16T(f64) { | |
| 13 | return @bitCast(truncf(f16, f64, a)); | |
| 14 | } | |
| 15 | ||
| 16 | fn __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 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = compiler_rt.symbol; | |
| 3 | const truncf = @import("./truncf.zig").truncf; | |
| 4 | ||
| 5 | comptime { | |
| 6 | if (compiler_rt.want_aeabi) { | |
| 7 | symbol(&__aeabi_d2f, "__aeabi_d2f"); | |
| 8 | } else { | |
| 9 | symbol(&__truncdfsf2, "__truncdfsf2"); | |
| 10 | } | |
| 11 | } | |
| 12 | ||
| 13 | pub fn __truncdfsf2(a: f64) callconv(.c) f32 { | |
| 14 | return truncf(f32, f64, a); | |
| 15 | } | |
| 16 | ||
| 17 | fn __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 | 1 | const std = @import("std"); |
| 2 | 2 | |
| 3 | pub inline fn truncf(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t { | |
| 3 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 4 | const symbol = compiler_rt.symbol; | |
| 5 | ||
| 6 | comptime { | |
| 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 | ||
| 61 | fn __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 | } | |
| 64 | fn __aeabi_f2h(a: u32) callconv(.{ .arm_aapcs = .{} }) u16 { | |
| 65 | return @bitCast(f16_floatCast_f32(@bitCast(a))); | |
| 66 | } | |
| 67 | pub fn f16_floatCast_f32(a: f32) f16 { | |
| 68 | return truncf(f16, f32, a); | |
| 69 | } | |
| 70 | ||
| 71 | fn __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 | } | |
| 74 | fn __aeabi_d2h(a: u64) callconv(.{ .arm_aapcs = .{} }) u16 { | |
| 75 | return @bitCast(f16_floatCast_f64(@bitCast(a))); | |
| 76 | } | |
| 77 | pub fn f16_floatCast_f64(a: f64) f16 { | |
| 78 | return truncf(f16, f64, a); | |
| 79 | } | |
| 80 | ||
| 81 | fn __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 | } | |
| 84 | pub fn f16_floatCast_f80(a: f80) f16 { | |
| 85 | return trunc_f80(f16, a); | |
| 86 | } | |
| 87 | ||
| 88 | fn __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 | } | |
| 91 | pub fn f16_floatCast_f128(a: f128) f16 { | |
| 92 | return truncf(f16, f128, a); | |
| 93 | } | |
| 94 | ||
| 95 | fn __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 | } | |
| 98 | fn __aeabi_d2f(a: f64) callconv(.{ .arm_aapcs = .{} }) f32 { | |
| 99 | return f32_floatCast_f64(a); | |
| 100 | } | |
| 101 | pub fn f32_floatCast_f64(a: f64) f32 { | |
| 102 | return truncf(f32, f64, a); | |
| 103 | } | |
| 104 | ||
| 105 | fn __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 | } | |
| 108 | pub fn f32_floatCast_f80(a: f80) f32 { | |
| 109 | return trunc_f80(f32, a); | |
| 110 | } | |
| 111 | ||
| 112 | fn __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 | } | |
| 115 | fn _Qp_qtos(a: *const f128) callconv(.c) f32 { | |
| 116 | return f32_floatCast_f128(a.*); | |
| 117 | } | |
| 118 | pub fn f32_floatCast_f128(a: f128) f32 { | |
| 119 | return truncf(f32, f128, a); | |
| 120 | } | |
| 121 | ||
| 122 | fn __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 | } | |
| 125 | pub fn f64_floatCast_f80(a: f80) f64 { | |
| 126 | return trunc_f80(f64, a); | |
| 127 | } | |
| 128 | ||
| 129 | fn __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 | } | |
| 132 | fn _Qp_qtod(a: *const f128) callconv(.c) f64 { | |
| 133 | return f64_floatCast_f128(a.*); | |
| 134 | } | |
| 135 | pub fn f64_floatCast_f128(a: f128) f64 { | |
| 136 | return truncf(f64, f128, a); | |
| 137 | } | |
| 138 | ||
| 139 | fn __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 | } | |
| 142 | pub 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 | ||
| 201 | inline fn truncf(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t { | |
| 4 | 202 | const src_rep_t = @Int(.unsigned, @typeInfo(src_t).float.bits); |
| 5 | 203 | const dst_rep_t = @Int(.unsigned, @typeInfo(dst_t).float.bits); |
| 6 | 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 | 297 | return @bitCast(result); |
| 100 | 298 | } |
| 101 | 299 | |
| 102 | pub inline fn trunc_f80(comptime dst_t: type, a: f80) dst_t { | |
| 300 | inline fn trunc_f80(comptime dst_t: type, a: f80) dst_t { | |
| 103 | 301 | const dst_rep_t = @Int(.unsigned, @typeInfo(dst_t).float.bits); |
| 104 | 302 | const src_sig_bits = std.math.floatMantissaBits(f80) - 1; // -1 for the integer bit |
| 105 | 303 | const dst_sig_bits = std.math.floatMantissaBits(dst_t); |
lib/compiler_rt/truncf_test.zig+160-174| ... | ... | @@ -1,79 +1,82 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | 2 | const testing = std.testing; |
| 3 | 3 | |
| 4 | const __truncsfhf2 = @import("truncsfhf2.zig").__truncsfhf2; | |
| 5 | const __truncdfhf2 = @import("truncdfhf2.zig").__truncdfhf2; | |
| 6 | const __truncdfsf2 = @import("truncdfsf2.zig").__truncdfsf2; | |
| 7 | const __trunctfhf2 = @import("trunctfhf2.zig").__trunctfhf2; | |
| 8 | const __trunctfsf2 = @import("trunctfsf2.zig").__trunctfsf2; | |
| 9 | const __trunctfdf2 = @import("trunctfdf2.zig").__trunctfdf2; | |
| 10 | const __trunctfxf2 = @import("trunctfxf2.zig").__trunctfxf2; | |
| 11 | ||
| 12 | fn test__truncsfhf2(a: u32, expected: u16) !void { | |
| 13 | const actual: u16 = @bitCast(__truncsfhf2(@bitCast(a))); | |
| 14 | ||
| 15 | if (actual == expected) { | |
| 16 | return; | |
| 17 | } | |
| 4 | const impl = @import("truncf.zig"); | |
| 18 | 5 | |
| 19 | return error.TestFailure; | |
| 6 | const f16_floatCast_f32 = impl.f16_floatCast_f32; | |
| 7 | const f16_floatCast_f64 = impl.f16_floatCast_f64; | |
| 8 | const f16_floatCast_f80 = impl.f16_floatCast_f80; | |
| 9 | const f16_floatCast_f128 = impl.f16_floatCast_f128; | |
| 10 | ||
| 11 | const f32_floatCast_f64 = impl.f32_floatCast_f64; | |
| 12 | const f32_floatCast_f80 = impl.f32_floatCast_f80; | |
| 13 | const f32_floatCast_f128 = impl.f32_floatCast_f128; | |
| 14 | ||
| 15 | const f64_floatCast_f80 = impl.f64_floatCast_f80; | |
| 16 | const f64_floatCast_f128 = impl.f64_floatCast_f128; | |
| 17 | ||
| 18 | const f80_floatCast_f128 = impl.f80_floatCast_f128; | |
| 19 | ||
| 20 | fn 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 | } |
| 21 | 24 | |
| 22 | test "truncsfhf2" { | |
| 23 | try test__truncsfhf2(0x7fc00000, 0x7e00); // qNaN | |
| 24 | try test__truncsfhf2(0x7fe00000, 0x7f00); // sNaN | |
| 25 | test f16_floatCast_f32 { | |
| 26 | try test_f16_floatCast_f32(0x7fc00000, 0x7e00); // qNaN | |
| 27 | try test_f16_floatCast_f32(0x7fe00000, 0x7f00); // sNaN | |
| 25 | 28 | |
| 26 | try test__truncsfhf2(0, 0); // 0 | |
| 27 | try test__truncsfhf2(0x80000000, 0x8000); // -0 | |
| 29 | try test_f16_floatCast_f32(0, 0); // 0 | |
| 30 | try test_f16_floatCast_f32(0x80000000, 0x8000); // -0 | |
| 28 | 31 | |
| 29 | try test__truncsfhf2(0x7f800000, 0x7c00); // inf | |
| 30 | try test__truncsfhf2(0xff800000, 0xfc00); // -inf | |
| 32 | try test_f16_floatCast_f32(0x7f800000, 0x7c00); // inf | |
| 33 | try test_f16_floatCast_f32(0xff800000, 0xfc00); // -inf | |
| 31 | 34 | |
| 32 | try test__truncsfhf2(0x477ff000, 0x7c00); // 65520 -> inf | |
| 33 | try test__truncsfhf2(0xc77ff000, 0xfc00); // -65520 -> -inf | |
| 35 | try test_f16_floatCast_f32(0x477ff000, 0x7c00); // 65520 -> inf | |
| 36 | try test_f16_floatCast_f32(0xc77ff000, 0xfc00); // -65520 -> -inf | |
| 34 | 37 | |
| 35 | try test__truncsfhf2(0x71cc3892, 0x7c00); // 0x1.987124876876324p+100 -> inf | |
| 36 | try test__truncsfhf2(0xf1cc3892, 0xfc00); // -0x1.987124876876324p+100 -> -inf | |
| 38 | try test_f16_floatCast_f32(0x71cc3892, 0x7c00); // 0x1.987124876876324p+100 -> inf | |
| 39 | try test_f16_floatCast_f32(0xf1cc3892, 0xfc00); // -0x1.987124876876324p+100 -> -inf | |
| 37 | 40 | |
| 38 | try test__truncsfhf2(0x38800000, 0x0400); // normal (min), 2**-14 | |
| 39 | try test__truncsfhf2(0xb8800000, 0x8400); // normal (min), -2**-14 | |
| 41 | try test_f16_floatCast_f32(0x38800000, 0x0400); // normal (min), 2**-14 | |
| 42 | try test_f16_floatCast_f32(0xb8800000, 0x8400); // normal (min), -2**-14 | |
| 40 | 43 | |
| 41 | try test__truncsfhf2(0x477fe000, 0x7bff); // normal (max), 65504 | |
| 42 | try test__truncsfhf2(0xc77fe000, 0xfbff); // normal (max), -65504 | |
| 44 | try test_f16_floatCast_f32(0x477fe000, 0x7bff); // normal (max), 65504 | |
| 45 | try test_f16_floatCast_f32(0xc77fe000, 0xfbff); // normal (max), -65504 | |
| 43 | 46 | |
| 44 | try test__truncsfhf2(0x477fe100, 0x7bff); // normal, 65505 -> 65504 | |
| 45 | try test__truncsfhf2(0xc77fe100, 0xfbff); // normal, -65505 -> -65504 | |
| 47 | try test_f16_floatCast_f32(0x477fe100, 0x7bff); // normal, 65505 -> 65504 | |
| 48 | try test_f16_floatCast_f32(0xc77fe100, 0xfbff); // normal, -65505 -> -65504 | |
| 46 | 49 | |
| 47 | try test__truncsfhf2(0x477fef00, 0x7bff); // normal, 65519 -> 65504 | |
| 48 | try test__truncsfhf2(0xc77fef00, 0xfbff); // normal, -65519 -> -65504 | |
| 50 | try test_f16_floatCast_f32(0x477fef00, 0x7bff); // normal, 65519 -> 65504 | |
| 51 | try test_f16_floatCast_f32(0xc77fef00, 0xfbff); // normal, -65519 -> -65504 | |
| 49 | 52 | |
| 50 | try test__truncsfhf2(0x3f802000, 0x3c01); // normal, 1 + 2**-10 | |
| 51 | try test__truncsfhf2(0xbf802000, 0xbc01); // normal, -1 - 2**-10 | |
| 53 | try test_f16_floatCast_f32(0x3f802000, 0x3c01); // normal, 1 + 2**-10 | |
| 54 | try test_f16_floatCast_f32(0xbf802000, 0xbc01); // normal, -1 - 2**-10 | |
| 52 | 55 | |
| 53 | try test__truncsfhf2(0x3eaaa000, 0x3555); // normal, approx. 1/3 | |
| 54 | try test__truncsfhf2(0xbeaaa000, 0xb555); // normal, approx. -1/3 | |
| 56 | try test_f16_floatCast_f32(0x3eaaa000, 0x3555); // normal, approx. 1/3 | |
| 57 | try test_f16_floatCast_f32(0xbeaaa000, 0xb555); // normal, approx. -1/3 | |
| 55 | 58 | |
| 56 | try test__truncsfhf2(0x40490fdb, 0x4248); // normal, 3.1415926535 | |
| 57 | try test__truncsfhf2(0xc0490fdb, 0xc248); // normal, -3.1415926535 | |
| 59 | try test_f16_floatCast_f32(0x40490fdb, 0x4248); // normal, 3.1415926535 | |
| 60 | try test_f16_floatCast_f32(0xc0490fdb, 0xc248); // normal, -3.1415926535 | |
| 58 | 61 | |
| 59 | try test__truncsfhf2(0x45cc3892, 0x6e62); // normal, 0x1.987124876876324p+12 | |
| 62 | try test_f16_floatCast_f32(0x45cc3892, 0x6e62); // normal, 0x1.987124876876324p+12 | |
| 60 | 63 | |
| 61 | try test__truncsfhf2(0x3f800000, 0x3c00); // normal, 1 | |
| 62 | try test__truncsfhf2(0x38800000, 0x0400); // normal, 0x1.0p-14 | |
| 64 | try test_f16_floatCast_f32(0x3f800000, 0x3c00); // normal, 1 | |
| 65 | try test_f16_floatCast_f32(0x38800000, 0x0400); // normal, 0x1.0p-14 | |
| 63 | 66 | |
| 64 | try test__truncsfhf2(0x33800000, 0x0001); // denormal (min), 2**-24 | |
| 65 | try test__truncsfhf2(0xb3800000, 0x8001); // denormal (min), -2**-24 | |
| 67 | try test_f16_floatCast_f32(0x33800000, 0x0001); // denormal (min), 2**-24 | |
| 68 | try test_f16_floatCast_f32(0xb3800000, 0x8001); // denormal (min), -2**-24 | |
| 66 | 69 | |
| 67 | try test__truncsfhf2(0x387fc000, 0x03ff); // denormal (max), 2**-14 - 2**-24 | |
| 68 | try test__truncsfhf2(0xb87fc000, 0x83ff); // denormal (max), -2**-14 + 2**-24 | |
| 70 | try test_f16_floatCast_f32(0x387fc000, 0x03ff); // denormal (max), 2**-14 - 2**-24 | |
| 71 | try test_f16_floatCast_f32(0xb87fc000, 0x83ff); // denormal (max), -2**-14 + 2**-24 | |
| 69 | 72 | |
| 70 | try test__truncsfhf2(0x35800000, 0x0010); // denormal, 0x1.0p-20 | |
| 71 | try test__truncsfhf2(0x33280000, 0x0001); // denormal, 0x1.5p-25 -> 0x1.0p-24 | |
| 72 | try test__truncsfhf2(0x33000000, 0x0000); // 0x1.0p-25 -> zero | |
| 73 | try test_f16_floatCast_f32(0x35800000, 0x0010); // denormal, 0x1.0p-20 | |
| 74 | try test_f16_floatCast_f32(0x33280000, 0x0001); // denormal, 0x1.5p-25 -> 0x1.0p-24 | |
| 75 | try test_f16_floatCast_f32(0x33000000, 0x0000); // 0x1.0p-25 -> zero | |
| 73 | 76 | } |
| 74 | 77 | |
| 75 | fn test__truncdfhf2(a: f64, expected: u16) void { | |
| 76 | const rep: u16 = @bitCast(__truncdfhf2(a)); | |
| 78 | fn test_f16_floatCast_f64(a: f64, expected: u16) !void { | |
| 79 | const rep: u16 = @bitCast(f16_floatCast_f64(a)); | |
| 77 | 80 | |
| 78 | 81 | if (rep == expected) { |
| 79 | 82 | return; |
| ... | ... | @@ -84,62 +87,56 @@ fn test__truncdfhf2(a: f64, expected: u16) void { |
| 84 | 87 | return; |
| 85 | 88 | } |
| 86 | 89 | } |
| 87 | ||
| 88 | @panic("__truncdfhf2 test failure"); | |
| 90 | return error.TestFailure; | |
| 89 | 91 | } |
| 90 | 92 | |
| 91 | fn test__truncdfhf2_raw(a: u64, expected: u16) void { | |
| 92 | const actual: u16 = @bitCast(__truncdfhf2(@bitCast(a))); | |
| 93 | ||
| 94 | if (actual == expected) { | |
| 95 | return; | |
| 96 | } | |
| 97 | ||
| 98 | @panic("__truncdfhf2 test failure"); | |
| 93 | fn test_f16_floatCast_f64_raw(a: u64, expected: u16) !void { | |
| 94 | const actual: u16 = @bitCast(f16_floatCast_f64(@bitCast(a))); | |
| 95 | try testing.expect(actual == expected); | |
| 99 | 96 | } |
| 100 | 97 | |
| 101 | test "truncdfhf2" { | |
| 102 | test__truncdfhf2_raw(0x7ff8000000000000, 0x7e00); // qNaN | |
| 103 | test__truncdfhf2_raw(0x7ff0000000008000, 0x7e00); // NaN | |
| 98 | test f16_floatCast_f64 { | |
| 99 | try test_f16_floatCast_f64_raw(0x7ff8000000000000, 0x7e00); // qNaN | |
| 100 | try test_f16_floatCast_f64_raw(0x7ff0000000008000, 0x7e00); // NaN | |
| 104 | 101 | |
| 105 | test__truncdfhf2_raw(0x7ff0000000000000, 0x7c00); //inf | |
| 106 | test__truncdfhf2_raw(0xfff0000000000000, 0xfc00); // -inf | |
| 102 | try test_f16_floatCast_f64_raw(0x7ff0000000000000, 0x7c00); //inf | |
| 103 | try test_f16_floatCast_f64_raw(0xfff0000000000000, 0xfc00); // -inf | |
| 107 | 104 | |
| 108 | test__truncdfhf2(0.0, 0x0); // zero | |
| 109 | test__truncdfhf2_raw(0x80000000 << 32, 0x8000); // -zero | |
| 105 | try test_f16_floatCast_f64(0.0, 0x0); // zero | |
| 106 | try test_f16_floatCast_f64_raw(0x80000000 << 32, 0x8000); // -zero | |
| 110 | 107 | |
| 111 | test__truncdfhf2(3.1415926535, 0x4248); | |
| 112 | test__truncdfhf2(-3.1415926535, 0xc248); | |
| 108 | try test_f16_floatCast_f64(3.1415926535, 0x4248); | |
| 109 | try test_f16_floatCast_f64(-3.1415926535, 0xc248); | |
| 113 | 110 | |
| 114 | test__truncdfhf2(0x1.987124876876324p+1000, 0x7c00); | |
| 115 | test__truncdfhf2(0x1.987124876876324p+12, 0x6e62); | |
| 116 | test__truncdfhf2(0x1.0p+0, 0x3c00); | |
| 117 | test__truncdfhf2(0x1.0p-14, 0x0400); | |
| 111 | try test_f16_floatCast_f64(0x1.987124876876324p+1000, 0x7c00); | |
| 112 | try test_f16_floatCast_f64(0x1.987124876876324p+12, 0x6e62); | |
| 113 | try test_f16_floatCast_f64(0x1.0p+0, 0x3c00); | |
| 114 | try test_f16_floatCast_f64(0x1.0p-14, 0x0400); | |
| 118 | 115 | |
| 119 | 116 | // denormal |
| 120 | test__truncdfhf2(0x1.0p-20, 0x0010); | |
| 121 | test__truncdfhf2(0x1.0p-24, 0x0001); | |
| 122 | test__truncdfhf2(-0x1.0p-24, 0x8001); | |
| 123 | test__truncdfhf2(0x1.5p-25, 0x0001); | |
| 117 | try test_f16_floatCast_f64(0x1.0p-20, 0x0010); | |
| 118 | try test_f16_floatCast_f64(0x1.0p-24, 0x0001); | |
| 119 | try test_f16_floatCast_f64(-0x1.0p-24, 0x8001); | |
| 120 | try test_f16_floatCast_f64(0x1.5p-25, 0x0001); | |
| 124 | 121 | |
| 125 | 122 | // and back to zero |
| 126 | test__truncdfhf2(0x1.0p-25, 0x0000); | |
| 127 | test__truncdfhf2(-0x1.0p-25, 0x8000); | |
| 123 | try test_f16_floatCast_f64(0x1.0p-25, 0x0000); | |
| 124 | try test_f16_floatCast_f64(-0x1.0p-25, 0x8000); | |
| 128 | 125 | |
| 129 | 126 | // max (precise) |
| 130 | test__truncdfhf2(65504.0, 0x7bff); | |
| 127 | try test_f16_floatCast_f64(65504.0, 0x7bff); | |
| 131 | 128 | |
| 132 | 129 | // max (rounded) |
| 133 | test__truncdfhf2(65519.0, 0x7bff); | |
| 130 | try test_f16_floatCast_f64(65519.0, 0x7bff); | |
| 134 | 131 | |
| 135 | 132 | // max (to +inf) |
| 136 | test__truncdfhf2(65520.0, 0x7c00); | |
| 137 | test__truncdfhf2(-65520.0, 0xfc00); | |
| 138 | test__truncdfhf2(65536.0, 0x7c00); | |
| 133 | try test_f16_floatCast_f64(65520.0, 0x7c00); | |
| 134 | try test_f16_floatCast_f64(-65520.0, 0xfc00); | |
| 135 | try test_f16_floatCast_f64(65536.0, 0x7c00); | |
| 139 | 136 | } |
| 140 | 137 | |
| 141 | fn test__trunctfsf2(a: f128, expected: u32) void { | |
| 142 | const x = __trunctfsf2(a); | |
| 138 | fn test_f32_floatCast_f128(a: f128, expected: u32) !void { | |
| 139 | const x = f32_floatCast_f128(a); | |
| 143 | 140 | |
| 144 | 141 | const rep: u32 = @bitCast(x); |
| 145 | 142 | if (rep == expected) { |
| ... | ... | @@ -151,28 +148,27 @@ fn test__trunctfsf2(a: f128, expected: u32) void { |
| 151 | 148 | return; |
| 152 | 149 | } |
| 153 | 150 | } |
| 154 | ||
| 155 | @panic("__trunctfsf2 test failure"); | |
| 151 | return error.TestFailure; | |
| 156 | 152 | } |
| 157 | 153 | |
| 158 | test "trunctfsf2" { | |
| 154 | test f32_floatCast_f128 { | |
| 159 | 155 | // qnan |
| 160 | test__trunctfsf2(@bitCast(@as(u128, 0x7fff800000000000 << 64)), 0x7fc00000); | |
| 156 | try test_f32_floatCast_f128(@bitCast(@as(u128, 0x7fff800000000000 << 64)), 0x7fc00000); | |
| 161 | 157 | // 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 | 159 | // inf |
| 164 | test__trunctfsf2(@bitCast(@as(u128, 0x7fff000000000000 << 64)), 0x7f800000); | |
| 160 | try test_f32_floatCast_f128(@bitCast(@as(u128, 0x7fff000000000000 << 64)), 0x7f800000); | |
| 165 | 161 | // zero |
| 166 | test__trunctfsf2(0.0, 0x0); | |
| 162 | try test_f32_floatCast_f128(0.0, 0x0); | |
| 167 | 163 | |
| 168 | test__trunctfsf2(0x1.23a2abb4a2ddee355f36789abcdep+5, 0x4211d156); | |
| 169 | test__trunctfsf2(0x1.e3d3c45bd3abfd98b76a54cc321fp-9, 0x3b71e9e2); | |
| 170 | test__trunctfsf2(0x1.234eebb5faa678f4488693abcdefp+4534, 0x7f800000); | |
| 171 | test__trunctfsf2(0x1.edcba9bb8c76a5a43dd21f334634p-435, 0x0); | |
| 164 | try test_f32_floatCast_f128(0x1.23a2abb4a2ddee355f36789abcdep+5, 0x4211d156); | |
| 165 | try test_f32_floatCast_f128(0x1.e3d3c45bd3abfd98b76a54cc321fp-9, 0x3b71e9e2); | |
| 166 | try test_f32_floatCast_f128(0x1.234eebb5faa678f4488693abcdefp+4534, 0x7f800000); | |
| 167 | try test_f32_floatCast_f128(0x1.edcba9bb8c76a5a43dd21f334634p-435, 0x0); | |
| 172 | 168 | } |
| 173 | 169 | |
| 174 | fn test__trunctfdf2(a: f128, expected: u64) void { | |
| 175 | const x = __trunctfdf2(a); | |
| 170 | fn test_f64_floatCast_f128(a: f128, expected: u64) !void { | |
| 171 | const x = f64_floatCast_f128(a); | |
| 176 | 172 | |
| 177 | 173 | const rep: u64 = @bitCast(x); |
| 178 | 174 | if (rep == expected) { |
| ... | ... | @@ -184,28 +180,27 @@ fn test__trunctfdf2(a: f128, expected: u64) void { |
| 184 | 180 | return; |
| 185 | 181 | } |
| 186 | 182 | } |
| 187 | ||
| 188 | @panic("__trunctfsf2 test failure"); | |
| 183 | return error.TestFailure; | |
| 189 | 184 | } |
| 190 | 185 | |
| 191 | test "trunctfdf2" { | |
| 186 | test f64_floatCast_f128 { | |
| 192 | 187 | // qnan |
| 193 | test__trunctfdf2(@bitCast(@as(u128, 0x7fff800000000000 << 64)), 0x7ff8000000000000); | |
| 188 | try test_f64_floatCast_f128(@bitCast(@as(u128, 0x7fff800000000000 << 64)), 0x7ff8000000000000); | |
| 194 | 189 | // 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 | 191 | // inf |
| 197 | test__trunctfdf2(@bitCast(@as(u128, 0x7fff000000000000 << 64)), 0x7ff0000000000000); | |
| 192 | try test_f64_floatCast_f128(@bitCast(@as(u128, 0x7fff000000000000 << 64)), 0x7ff0000000000000); | |
| 198 | 193 | // zero |
| 199 | test__trunctfdf2(0.0, 0x0); | |
| 194 | try test_f64_floatCast_f128(0.0, 0x0); | |
| 200 | 195 | |
| 201 | test__trunctfdf2(0x1.af23456789bbaaab347645365cdep+5, 0x404af23456789bbb); | |
| 202 | test__trunctfdf2(0x1.dedafcff354b6ae9758763545432p-9, 0x3f6dedafcff354b7); | |
| 203 | test__trunctfdf2(0x1.2f34dd5f437e849b4baab754cdefp+4534, 0x7ff0000000000000); | |
| 204 | test__trunctfdf2(0x1.edcbff8ad76ab5bf46463233214fp-435, 0x24cedcbff8ad76ab); | |
| 196 | try test_f64_floatCast_f128(0x1.af23456789bbaaab347645365cdep+5, 0x404af23456789bbb); | |
| 197 | try test_f64_floatCast_f128(0x1.dedafcff354b6ae9758763545432p-9, 0x3f6dedafcff354b7); | |
| 198 | try test_f64_floatCast_f128(0x1.2f34dd5f437e849b4baab754cdefp+4534, 0x7ff0000000000000); | |
| 199 | try test_f64_floatCast_f128(0x1.edcbff8ad76ab5bf46463233214fp-435, 0x24cedcbff8ad76ab); | |
| 205 | 200 | } |
| 206 | 201 | |
| 207 | fn test__truncdfsf2(a: f64, expected: u32) void { | |
| 208 | const x = __truncdfsf2(a); | |
| 202 | fn test_f32_floatCast_f64(a: f64, expected: u32) !void { | |
| 203 | const x = f32_floatCast_f64(a); | |
| 209 | 204 | |
| 210 | 205 | const rep: u32 = @bitCast(x); |
| 211 | 206 | if (rep == expected) { |
| ... | ... | @@ -217,90 +212,81 @@ fn test__truncdfsf2(a: f64, expected: u32) void { |
| 217 | 212 | return; |
| 218 | 213 | } |
| 219 | 214 | } |
| 220 | ||
| 221 | std.debug.print("got 0x{x} wanted 0x{x}\n", .{ rep, expected }); | |
| 222 | ||
| 223 | @panic("__trunctfsf2 test failure"); | |
| 215 | return error.TestFailure; | |
| 224 | 216 | } |
| 225 | 217 | |
| 226 | test "truncdfsf2" { | |
| 218 | test f32_floatCast_f64 { | |
| 227 | 219 | // nan & qnan |
| 228 | test__truncdfsf2(@bitCast(@as(u64, 0x7ff8000000000000)), 0x7fc00000); | |
| 229 | test__truncdfsf2(@bitCast(@as(u64, 0x7ff0000000000001)), 0x7fc00000); | |
| 220 | try test_f32_floatCast_f64(@bitCast(@as(u64, 0x7ff8000000000000)), 0x7fc00000); | |
| 221 | try test_f32_floatCast_f64(@bitCast(@as(u64, 0x7ff0000000000001)), 0x7fc00000); | |
| 230 | 222 | // inf |
| 231 | test__truncdfsf2(@bitCast(@as(u64, 0x7ff0000000000000)), 0x7f800000); | |
| 232 | test__truncdfsf2(@bitCast(@as(u64, 0xfff0000000000000)), 0xff800000); | |
| 223 | try test_f32_floatCast_f64(@bitCast(@as(u64, 0x7ff0000000000000)), 0x7f800000); | |
| 224 | try test_f32_floatCast_f64(@bitCast(@as(u64, 0xfff0000000000000)), 0xff800000); | |
| 233 | 225 | |
| 234 | test__truncdfsf2(0.0, 0x0); | |
| 235 | test__truncdfsf2(1.0, 0x3f800000); | |
| 236 | test__truncdfsf2(-1.0, 0xbf800000); | |
| 226 | try test_f32_floatCast_f64(0.0, 0x0); | |
| 227 | try test_f32_floatCast_f64(1.0, 0x3f800000); | |
| 228 | try test_f32_floatCast_f64(-1.0, 0xbf800000); | |
| 237 | 229 | |
| 238 | 230 | // huge number becomes inf |
| 239 | test__truncdfsf2(340282366920938463463374607431768211456.0, 0x7f800000); | |
| 231 | try test_f32_floatCast_f64(340282366920938463463374607431768211456.0, 0x7f800000); | |
| 240 | 232 | } |
| 241 | 233 | |
| 242 | fn test__trunctfhf2(a: f128, expected: u16) void { | |
| 243 | const x = __trunctfhf2(a); | |
| 234 | fn test_f16_floatCast_f128(a: f128, expected: u16) !void { | |
| 235 | const x = f16_floatCast_f128(a); | |
| 244 | 236 | |
| 245 | 237 | const rep: u16 = @bitCast(x); |
| 246 | if (rep == expected) { | |
| 247 | return; | |
| 248 | } | |
| 249 | ||
| 250 | std.debug.print("got 0x{x} wanted 0x{x}\n", .{ rep, expected }); | |
| 251 | ||
| 252 | @panic("__trunctfhf2 test failure"); | |
| 238 | try testing.expect(rep == expected); | |
| 253 | 239 | } |
| 254 | 240 | |
| 255 | test "trunctfhf2" { | |
| 241 | test f16_floatCast_f128 { | |
| 256 | 242 | // qNaN |
| 257 | test__trunctfhf2(@bitCast(@as(u128, 0x7fff8000000000000000000000000000)), 0x7e00); | |
| 243 | try test_f16_floatCast_f128(@bitCast(@as(u128, 0x7fff8000000000000000000000000000)), 0x7e00); | |
| 258 | 244 | // NaN |
| 259 | test__trunctfhf2(@bitCast(@as(u128, 0x7fff0000000000000000000000000001)), 0x7e00); | |
| 245 | try test_f16_floatCast_f128(@bitCast(@as(u128, 0x7fff0000000000000000000000000001)), 0x7e00); | |
| 260 | 246 | // inf |
| 261 | test__trunctfhf2(@bitCast(@as(u128, 0x7fff0000000000000000000000000000)), 0x7c00); | |
| 262 | test__trunctfhf2(-@as(f128, @bitCast(@as(u128, 0x7fff0000000000000000000000000000))), 0xfc00); | |
| 247 | try test_f16_floatCast_f128(@bitCast(@as(u128, 0x7fff0000000000000000000000000000)), 0x7c00); | |
| 248 | try test_f16_floatCast_f128(-@as(f128, @bitCast(@as(u128, 0x7fff0000000000000000000000000000))), 0xfc00); | |
| 263 | 249 | // zero |
| 264 | test__trunctfhf2(0.0, 0x0); | |
| 265 | test__trunctfhf2(-0.0, 0x8000); | |
| 266 | ||
| 267 | test__trunctfhf2(3.1415926535, 0x4248); | |
| 268 | test__trunctfhf2(-3.1415926535, 0xc248); | |
| 269 | test__trunctfhf2(0x1.987124876876324p+100, 0x7c00); | |
| 270 | test__trunctfhf2(0x1.987124876876324p+12, 0x6e62); | |
| 271 | test__trunctfhf2(0x1.0p+0, 0x3c00); | |
| 272 | test__trunctfhf2(0x1.0p-14, 0x0400); | |
| 250 | try test_f16_floatCast_f128(0.0, 0x0); | |
| 251 | try test_f16_floatCast_f128(-0.0, 0x8000); | |
| 252 | ||
| 253 | try test_f16_floatCast_f128(3.1415926535, 0x4248); | |
| 254 | try test_f16_floatCast_f128(-3.1415926535, 0xc248); | |
| 255 | try test_f16_floatCast_f128(0x1.987124876876324p+100, 0x7c00); | |
| 256 | try test_f16_floatCast_f128(0x1.987124876876324p+12, 0x6e62); | |
| 257 | try test_f16_floatCast_f128(0x1.0p+0, 0x3c00); | |
| 258 | try test_f16_floatCast_f128(0x1.0p-14, 0x0400); | |
| 273 | 259 | // denormal |
| 274 | test__trunctfhf2(0x1.0p-20, 0x0010); | |
| 275 | test__trunctfhf2(0x1.0p-24, 0x0001); | |
| 276 | test__trunctfhf2(-0x1.0p-24, 0x8001); | |
| 277 | test__trunctfhf2(0x1.5p-25, 0x0001); | |
| 260 | try test_f16_floatCast_f128(0x1.0p-20, 0x0010); | |
| 261 | try test_f16_floatCast_f128(0x1.0p-24, 0x0001); | |
| 262 | try test_f16_floatCast_f128(-0x1.0p-24, 0x8001); | |
| 263 | try test_f16_floatCast_f128(0x1.5p-25, 0x0001); | |
| 278 | 264 | // and back to zero |
| 279 | test__trunctfhf2(0x1.0p-25, 0x0000); | |
| 280 | test__trunctfhf2(-0x1.0p-25, 0x8000); | |
| 265 | try test_f16_floatCast_f128(0x1.0p-25, 0x0000); | |
| 266 | try test_f16_floatCast_f128(-0x1.0p-25, 0x8000); | |
| 281 | 267 | // max (precise) |
| 282 | test__trunctfhf2(65504.0, 0x7bff); | |
| 268 | try test_f16_floatCast_f128(65504.0, 0x7bff); | |
| 283 | 269 | // max (rounded) |
| 284 | test__trunctfhf2(65519.0, 0x7bff); | |
| 270 | try test_f16_floatCast_f128(65519.0, 0x7bff); | |
| 285 | 271 | // max (to +inf) |
| 286 | test__trunctfhf2(65520.0, 0x7c00); | |
| 287 | test__trunctfhf2(65536.0, 0x7c00); | |
| 288 | test__trunctfhf2(-65520.0, 0xfc00); | |
| 289 | ||
| 290 | test__trunctfhf2(0x1.23a2abb4a2ddee355f36789abcdep+5, 0x508f); | |
| 291 | test__trunctfhf2(0x1.e3d3c45bd3abfd98b76a54cc321fp-9, 0x1b8f); | |
| 292 | test__trunctfhf2(0x1.234eebb5faa678f4488693abcdefp+453, 0x7c00); | |
| 293 | test__trunctfhf2(0x1.edcba9bb8c76a5a43dd21f334634p-43, 0x0); | |
| 272 | try test_f16_floatCast_f128(65520.0, 0x7c00); | |
| 273 | try test_f16_floatCast_f128(65536.0, 0x7c00); | |
| 274 | try test_f16_floatCast_f128(-65520.0, 0xfc00); | |
| 275 | ||
| 276 | try test_f16_floatCast_f128(0x1.23a2abb4a2ddee355f36789abcdep+5, 0x508f); | |
| 277 | try test_f16_floatCast_f128(0x1.e3d3c45bd3abfd98b76a54cc321fp-9, 0x1b8f); | |
| 278 | try test_f16_floatCast_f128(0x1.234eebb5faa678f4488693abcdefp+453, 0x7c00); | |
| 279 | try test_f16_floatCast_f128(0x1.edcba9bb8c76a5a43dd21f334634p-43, 0x0); | |
| 294 | 280 | } |
| 295 | 281 | |
| 296 | test "trunctfxf2" { | |
| 297 | try test__trunctfxf2(1.5, 1.5); | |
| 298 | try test__trunctfxf2(2.5, 2.5); | |
| 299 | try test__trunctfxf2(-2.5, -2.5); | |
| 300 | try test__trunctfxf2(0.0, 0.0); | |
| 282 | fn test_f80_floatCast_f128(a: f128, expected: f80) !void { | |
| 283 | const x = f80_floatCast_f128(a); | |
| 284 | try testing.expect(x == expected); | |
| 301 | 285 | } |
| 302 | 286 | |
| 303 | fn test__trunctfxf2(a: f128, expected: f80) !void { | |
| 304 | const x = __trunctfxf2(a); | |
| 305 | try testing.expect(x == expected); | |
| 287 | test f80_floatCast_f128 { | |
| 288 | try test_f80_floatCast_f128(1.5, 1.5); | |
| 289 | try test_f80_floatCast_f128(2.5, 2.5); | |
| 290 | try test_f80_floatCast_f128(-2.5, -2.5); | |
| 291 | try test_f80_floatCast_f128(0.0, 0.0); | |
| 306 | 292 | } |
lib/compiler_rt/truncsfhf2.zig deleted-24| ... | ... | @@ -1,24 +0,0 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = compiler_rt.symbol; | |
| 3 | const truncf = @import("./truncf.zig").truncf; | |
| 4 | ||
| 5 | comptime { | |
| 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 | ||
| 14 | pub fn __truncsfhf2(a: f32) callconv(.c) compiler_rt.F16T(f32) { | |
| 15 | return @bitCast(truncf(f16, f32, a)); | |
| 16 | } | |
| 17 | ||
| 18 | fn __gnu_f2h_ieee(a: f32) callconv(.c) compiler_rt.F16T(f32) { | |
| 19 | return @bitCast(truncf(f16, f32, a)); | |
| 20 | } | |
| 21 | ||
| 22 | fn __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 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = compiler_rt.symbol; | |
| 3 | const truncf = @import("./truncf.zig").truncf; | |
| 4 | ||
| 5 | comptime { | |
| 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 | ||
| 16 | pub fn __trunctfdf2(a: f128) callconv(.c) f64 { | |
| 17 | return truncf(f64, f128, a); | |
| 18 | } | |
| 19 | ||
| 20 | fn _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 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 3 | const truncf = @import("./truncf.zig").truncf; | |
| 4 | ||
| 5 | comptime { | |
| 6 | symbol(&__trunctfhf2, "__trunctfhf2"); | |
| 7 | if (compiler_rt.want_ppc_abi) { | |
| 8 | symbol(&__trunctfhf2, "__trunckfhf2"); | |
| 9 | } | |
| 10 | } | |
| 11 | ||
| 12 | pub 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 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const truncf = @import("./truncf.zig").truncf; | |
| 3 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 4 | ||
| 5 | comptime { | |
| 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 | ||
| 16 | pub fn __trunctfsf2(a: f128) callconv(.c) f32 { | |
| 17 | return truncf(f32, f128, a); | |
| 18 | } | |
| 19 | ||
| 20 | fn _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 @@ |
| 1 | const math = @import("std").math; | |
| 2 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 3 | const symbol = compiler_rt.symbol; | |
| 4 | const trunc_f80 = @import("./truncf.zig").trunc_f80; | |
| 5 | ||
| 6 | comptime { | |
| 7 | symbol(&__trunctfxf2, "__trunctfxf2"); | |
| 8 | } | |
| 9 | ||
| 10 | pub 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 @@ |
| 1 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 2 | const trunc_f80 = @import("./truncf.zig").trunc_f80; | |
| 3 | ||
| 4 | comptime { | |
| 5 | symbol(&__truncxfdf2, "__truncxfdf2"); | |
| 6 | } | |
| 7 | ||
| 8 | fn __truncxfdf2(a: f80) callconv(.c) f64 { | |
| 9 | return trunc_f80(f64, a); | |
| 10 | } |
lib/compiler_rt/truncxfhf2.zig deleted-11| ... | ... | @@ -1,11 +0,0 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 3 | const trunc_f80 = @import("./truncf.zig").trunc_f80; | |
| 4 | ||
| 5 | comptime { | |
| 6 | symbol(&__truncxfhf2, "__truncxfhf2"); | |
| 7 | } | |
| 8 | ||
| 9 | fn __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 @@ |
| 1 | const trunc_f80 = @import("./truncf.zig").trunc_f80; | |
| 2 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 3 | ||
| 4 | comptime { | |
| 5 | symbol(&__truncxfsf2, "__truncxfsf2"); | |
| 6 | } | |
| 7 | ||
| 8 | fn __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 | 6 | const shl = std.math.shl; |
| 7 | 7 | |
| 8 | 8 | const compiler_rt = @import("../compiler_rt.zig"); |
| 9 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 9 | const symbol = compiler_rt.symbol; | |
| 10 | 10 | |
| 11 | 11 | const max_limbs = @divCeil(65535, 32); // max supported type is u65535 |
| 12 | 12 |
lib/compiler_rt/unorddf2.zig deleted-19| ... | ... | @@ -1,19 +0,0 @@ |
| 1 | const compiler_rt = @import("../compiler_rt.zig"); | |
| 2 | const comparef = @import("./comparef.zig"); | |
| 3 | const symbol = @import("../compiler_rt.zig").symbol; | |
| 4 | ||
| 5 | comptime { | |
| 6 | if (compiler_rt.want_aeabi) { | |
| 7 | symbol(&__aeabi_dcmpun, "__aeabi_dcmpun"); | |
| 8 | } else { | |
| 9 | symbol(&__unorddf2, "__unorddf2"); | |
| 10 | } | |
| 11 | } | |
| 12 | ||
| 13 | pub fn __unorddf2(a: f64, b: f64) callconv(.c) i32 { | |
| 14 | return comparef.unordcmp(f64, a, b); | |
| 15 | } | |
| 16 | ||
| 17 | fn __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 | 62 | var cursor: usize = ast.tokenStart(start_token); |
| 63 | 63 | |
| 64 | 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 | 66 | for (ast.source[newline_index + 1 .. cursor]) |c| { |
| 67 | 67 | if (c == ' ') { |
| 68 | 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 | 153 | continue; |
| 154 | 154 | } |
| 155 | 155 | // 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 | 157 | points += 2; |
| 158 | 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 | 161 | points += 1; |
| 162 | 162 | continue; |
| 163 | 163 | } |
| ... | ... | @@ -803,7 +803,7 @@ fn unpackInner(tar_bytes: []u8) !void { |
| 803 | 803 | if (std.mem.endsWith(u8, tar_file.name, ".zig")) { |
| 804 | 804 | log.debug("found file: '{s}'", .{tar_file.name}); |
| 805 | 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 | 807 | const pkg_name = file_name[0..pkg_name_end]; |
| 808 | 808 | const gop = try Walk.modules.getOrPut(gpa, pkg_name); |
| 809 | 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 | 108 | // In Debug and ReleaseSafe builds, there may be hidden extra fields |
| 109 | 109 | // included for safety checks. Without such safety checks enabled, |
| 110 | 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 | 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 | 159 | .heading => null, |
| 160 | 160 | .code_block => code_block: { |
| 161 | 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 | 163 | const effective_indent = @min(indent, b.data.code_block.indent); |
| 164 | 164 | break :code_block line[effective_indent..]; |
| 165 | 165 | } else { |
| ... | ... | @@ -209,7 +209,7 @@ pub fn feedLine(p: *Parser, line: []const u8) Allocator.Error!void { |
| 209 | 209 | } else p.pending_blocks.items.len; |
| 210 | 210 | |
| 211 | 211 | 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 | 213 | const code_block_end = in_code_block and |
| 214 | 214 | first_unmatched + 1 == p.pending_blocks.items.len; |
| 215 | 215 | // 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 | 225 | if (maybe_block_start == null and |
| 226 | 226 | !isBlank(rest_line) and |
| 227 | 227 | p.pending_blocks.items.len > 0 and |
| 228 | p.pending_blocks.getLast().?.tag == .paragraph) | |
| 228 | p.pending_blocks.last().?.tag == .paragraph) | |
| 229 | 229 | { |
| 230 | 230 | try p.addScratchStringLine(mem.trimStart(u8, rest_line, " \t")); |
| 231 | 231 | return; |
| ... | ... | @@ -236,7 +236,7 @@ pub fn feedLine(p: *Parser, line: []const u8) Allocator.Error!void { |
| 236 | 236 | // paragraphs. |
| 237 | 237 | if (maybe_block_start != null and |
| 238 | 238 | p.pending_blocks.items.len > 0 and |
| 239 | p.pending_blocks.getLast().?.tag == .paragraph) | |
| 239 | p.pending_blocks.last().?.tag == .paragraph) | |
| 240 | 240 | { |
| 241 | 241 | try p.closeLastBlock(); |
| 242 | 242 | } |
| ... | ... | @@ -259,7 +259,7 @@ pub fn feedLine(p: *Parser, line: []const u8) Allocator.Error!void { |
| 259 | 259 | // Do not append the end of a code block (```) as textual content. |
| 260 | 260 | if (code_block_end) return; |
| 261 | 261 | |
| 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 | 263 | last_pending_block.canAccept() |
| 264 | 264 | else |
| 265 | 265 | .blocks; |
| ... | ... | @@ -273,7 +273,7 @@ pub fn feedLine(p: *Parser, line: []const u8) Allocator.Error!void { |
| 273 | 273 | // loose, since we might just be looking at a blank line after the |
| 274 | 274 | // end of the last item in the list. The final determination will be |
| 275 | 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 | 277 | p.pending_blocks.items.len - 2 |
| 278 | 278 | else |
| 279 | 279 | null; |
| ... | ... | @@ -368,7 +368,7 @@ const BlockStart = struct { |
| 368 | 368 | }; |
| 369 | 369 | |
| 370 | 370 | fn 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 | 372 | // Close the last block if it is a list and the new block is not a list item |
| 373 | 373 | // or not of the same marker type. |
| 374 | 374 | const should_close_list = last_pending_block.tag == .list and |
| ... | ... | @@ -383,7 +383,7 @@ fn appendBlockStart(p: *Parser, block_start: BlockStart) !void { |
| 383 | 383 | } |
| 384 | 384 | } |
| 385 | 385 | |
| 386 | if (p.pending_blocks.getLast()) |last_pending_block| { | |
| 386 | if (p.pending_blocks.last()) |last_pending_block| { | |
| 387 | 387 | // If the last block is a list or list item, check for tightness based |
| 388 | 388 | // on the last line. |
| 389 | 389 | const maybe_containing_list = switch (last_pending_block.tag) { |
| ... | ... | @@ -401,7 +401,7 @@ fn appendBlockStart(p: *Parser, block_start: BlockStart) !void { |
| 401 | 401 | // Start a new list if the new block is a list item and there is no |
| 402 | 402 | // containing list yet. |
| 403 | 403 | 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 | 406 | try p.pending_blocks.append(p.allocator, .{ |
| 407 | 407 | .tag = .list, |
| ... | ... | @@ -417,7 +417,7 @@ fn appendBlockStart(p: *Parser, block_start: BlockStart) !void { |
| 417 | 417 | |
| 418 | 418 | if (block_start.tag == .table_row) { |
| 419 | 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 | 421 | try p.pending_blocks.append(p.allocator, .{ |
| 422 | 422 | .tag = .table, |
| 423 | 423 | .data = .{ .table = .{ |
| ... | ... | @@ -429,7 +429,7 @@ fn appendBlockStart(p: *Parser, block_start: BlockStart) !void { |
| 429 | 429 | }); |
| 430 | 430 | } |
| 431 | 431 | |
| 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 | 433 | if (current_row <= 1) { |
| 434 | 434 | var buffer: [max_table_columns]Node.TableCellAlignment = undefined; |
| 435 | 435 | const table_row = &block_start.data.table_row; |
| ... | ... | @@ -441,7 +441,7 @@ fn appendBlockStart(p: *Parser, block_start: BlockStart) !void { |
| 441 | 441 | // We need to go back and mark the header row and its column |
| 442 | 442 | // alignments. |
| 443 | 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 | 445 | for (p.extraChildren(header_data.container.children), 0..) |header_cell, i| { |
| 446 | 446 | const alignment = if (i < alignments.len) alignments[i] else .unset; |
| 447 | 447 | const cell_data = &datas[@backingInt(header_cell)].table_cell; |
| ... | ... | @@ -594,7 +594,7 @@ fn startListItem(unindented_line: []const u8) ?ListItemStart { |
| 594 | 594 | }; |
| 595 | 595 | } |
| 596 | 596 | |
| 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 | 598 | const after_number = unindented_line[number_end..]; |
| 599 | 599 | const marker: Block.Data.ListMarker = if (mem.startsWith(u8, after_number, ". ")) |
| 600 | 600 | .number_dot |
| ... | ... | @@ -639,10 +639,10 @@ fn startTableRow(unindented_line: []const u8) ?TableRowStart { |
| 639 | 639 | // Ignoring pipes in code spans allows table cells to contain |
| 640 | 640 | // code using ||, for example. |
| 641 | 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 | 643 | const open_len = i - open_start; |
| 644 | while (mem.indexOfScalarPos(u8, table_row_content, i, '`')) |close_start| { | |
| 645 | i = mem.indexOfNonePos(u8, table_row_content, close_start, "`") orelse return null; | |
| 644 | while (mem.findScalarPos(u8, table_row_content, i, '`')) |close_start| { | |
| 645 | i = mem.findNonePos(u8, table_row_content, close_start, "`") orelse return null; | |
| 646 | 646 | const close_len = i - close_start; |
| 647 | 647 | if (close_len == open_len) break; |
| 648 | 648 | } else return null; |
| ... | ... | @@ -794,7 +794,7 @@ fn startCodeBlock(p: *Parser, unindented_line: []const u8) !?CodeBlockStart { |
| 794 | 794 | } else ""; |
| 795 | 795 | // Code block tags may not contain backticks, since that would create |
| 796 | 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 | 798 | return .{ |
| 799 | 799 | .tag = try p.addString(mem.trim(u8, tag_bytes, " ")), |
| 800 | 800 | .fence_len = fence_len, |
| ... | ... | @@ -1382,12 +1382,12 @@ const InlineParser = struct { |
| 1382 | 1382 | /// parsing. |
| 1383 | 1383 | fn parseCodeSpan(ip: *InlineParser) !void { |
| 1384 | 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 | 1386 | const opener_len = ip.pos - opener_start; |
| 1387 | 1387 | |
| 1388 | 1388 | const start = ip.pos; |
| 1389 | const end = while (mem.indexOfScalarPos(u8, ip.content, ip.pos, '`')) |closer_start| { | |
| 1390 | ip.pos = mem.indexOfNonePos(u8, ip.content, closer_start, "`") orelse ip.content.len; | |
| 1389 | const end = while (mem.findScalarPos(u8, ip.content, ip.pos, '`')) |closer_start| { | |
| 1390 | ip.pos = mem.findNonePos(u8, ip.content, closer_start, "`") orelse ip.content.len; | |
| 1391 | 1391 | const closer_len = ip.pos - closer_start; |
| 1392 | 1392 | |
| 1393 | 1393 | if (closer_len == opener_len) break closer_start; |
| ... | ... | @@ -1627,7 +1627,7 @@ fn addScratchStringLine(p: *Parser, line: []const u8) !void { |
| 1627 | 1627 | } |
| 1628 | 1628 | |
| 1629 | 1629 | fn isBlank(line: []const u8) bool { |
| 1630 | return mem.indexOfNone(u8, line, " \t") == null; | |
| 1630 | return mem.findNone(u8, line, " \t") == null; | |
| 1631 | 1631 | } |
| 1632 | 1632 | |
| 1633 | 1633 | fn isPunctuation(c: u8) bool { |
lib/fuzzer.zig+4-4| ... | ... | @@ -41,8 +41,8 @@ fn logOverride( |
| 41 | 41 | |
| 42 | 42 | var safe_allocator: std.heap.SafeAllocator = .init(std.heap.page_allocator, .{}); |
| 43 | 43 | const gpa = switch (builtin.mode) { |
| 44 | .Debug, .ReleaseSafe => safe_allocator.allocator(), | |
| 45 | .ReleaseFast, .ReleaseSmall => std.heap.smp_allocator, | |
| 44 | .debug, .safe => safe_allocator.allocator(), | |
| 45 | .fast, .small => std.heap.smp_allocator, | |
| 46 | 46 | }; |
| 47 | 47 | |
| 48 | 48 | // Seperate from `exec` to allow initialization before `exec` is. |
| ... | ... | @@ -1085,7 +1085,7 @@ const Fuzzer = struct { |
| 1085 | 1085 | fn removeBest(f: *Fuzzer, i: Input.Index, best_i: u32) void { |
| 1086 | 1086 | const t = &f.tests[f.test_i]; |
| 1087 | 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 | 1089 | ref.best_i_len -= 1; |
| 1090 | 1090 | ref.best_i_buf[list_i] = ref.best_i_buf[ref.best_i_len]; |
| 1091 | 1091 | |
| ... | ... | @@ -1209,7 +1209,7 @@ const Fuzzer = struct { |
| 1209 | 1209 | f.req_bytes = @intCast(f.input_builder.bytes_table.items.len); |
| 1210 | 1210 | const quality: Input.Best.Quality = .{ |
| 1211 | 1211 | .n_pcs = n_pcs: { |
| 1212 | @setRuntimeSafety(builtin.mode == .Debug); // Necessary for vectorization | |
| 1212 | @setRuntimeSafety(builtin.mode == .debug); // Necessary for vectorization | |
| 1213 | 1213 | var n: u32 = 0; |
| 1214 | 1214 | for (exec.pc_counters) |c| { |
| 1215 | 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 | 798 | #define NT_X86_XSTATE	0x202		/* x86 extended state using xsave */ |
| 799 | 799 | #define NT_X86_SHSTK	0x204		/* x86 SHSTK state */ |
| 800 | 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 | 803 | #define NT_S390_TIMER	0x301		/* s390 timer register */ |
| 803 | 804 | #define NT_S390_TODCMP	0x302		/* s390 TOD clock comparator register */ |
| 804 | 805 | #define NT_S390_TODPREG	0x303		/* s390 TOD programmable register */ |
| ... | ... | @@ -846,6 +847,7 @@ typedef struct |
| 846 | 847 | #define NT_RISCV_VECTOR	0x901		/* RISC-V vector registers */ |
| 847 | 848 | #define NT_RISCV_TAGGED_ADDR_CTRL	0x902	/* RISC-V tagged |
| 848 | 849 | 						 address control */ |
| 850 | #define NT_RISCV_USER_CFI	0x903		/* RISC-V shadow stack state */ | |
| 849 | 851 | #define NT_LOONGARCH_CPUCFG	0xa00	/* LoongArch CPU config registers. */ |
| 850 | 852 | #define NT_LOONGARCH_CSR	0xa01	/* LoongArch control and |
| 851 | 853 | 					 status registers. */ |
| ... | ... | @@ -3470,7 +3472,9 @@ enum |
| 3470 | 3472 | |
| 3471 | 3473 | /* Valid values for the e_flags field. */ |
| 3472 | 3474 | |
| 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. */ | |
| 3474 | 3478 | |
| 3475 | 3479 | /* Additional s390 relocs */ |
| 3476 | 3480 |
lib/libc/glibc/include/libc-symbols.h+2-1| ... | ... | @@ -113,6 +113,7 @@ |
| 113 | 113 | #define HAVE_LIBINTL_H	1 |
| 114 | 114 | #define HAVE_WCTYPE_H	1 |
| 115 | 115 | #define HAVE_ISWCTYPE	1 |
| 116 | #define HAVE_MEMPCPY	1 | |
| 116 | 117 | #define ENABLE_NLS	1 |
| 117 | 118 | |
| 118 | 119 | /* The symbols in all the user (non-_) macros are C symbols. */ |
| ... | ... | @@ -682,7 +683,7 @@ for linking") |
| 682 | 683 | |
| 683 | 684 | /* Helper / base macros for indirect function symbols. */ |
| 684 | 685 | #define __ifunc_resolver(type_name, name, expr, init, classifier, ...)	\ |
| 685 | classifier inhibit_stack_protector					\ | |
| 686 | classifier								\ | |
| 686 | 687 | __typeof (type_name) *name##_ifunc (__VA_ARGS__)			\ |
| 687 | 688 | {									\ |
| 688 | 689 | init ();								\ |
lib/libc/glibc/sysdeps/aarch64/sysdep.h+28-4| ... | ... | @@ -43,7 +43,6 @@ |
| 43 | 43 | #define FEATURE_1_PAC 2 |
| 44 | 44 | #define FEATURE_1_GCS 4 |
| 45 | 45 | |
| 46 | /* Add a NT_GNU_PROPERTY_TYPE_0 note. */ | |
| 47 | 46 | #define GNU_PROPERTY(type, value)	\ |
| 48 | 47 | .section .note.gnu.property, "a";	\ |
| 49 | 48 | .p2align 3;				\ |
| ... | ... | @@ -57,9 +56,34 @@ |
| 57 | 56 | .word 0;				\ |
| 58 | 57 | .text |
| 59 | 58 | |
| 60 | /* Add GNU property note with the supported features to all asm code | |
| 61 | where sysdep.h is included. */ | |
| 62 | GNU_PROPERTY (FEATURE_1_AND, FEATURE_1_BTI|FEATURE_1_PAC|FEATURE_1_GCS) | |
| 59 | #ifdef __ARM_BUILDATTR64_FV | |
| 60 | /* Add AArch64 feature bits build attributes. */ | |
| 61 | # define FEATURE_1_AND_MARK(value)					\ | |
| 62 | .aeabi_subsection aeabi_feature_and_bits, optional, ULEB128;	\ | |
| 63 | .if ((value) & FEATURE_1_BTI);					\ | |
| 64 | .aeabi_attribute Tag_Feature_BTI, 1;				\ | |
| 65 | .else;								\ | |
| 66 | .aeabi_attribute Tag_Feature_BTI, 0;				\ | |
| 67 | .endif;								\ | |
| 68 | .if ((value) & FEATURE_1_GCS);					\ | |
| 69 | .aeabi_attribute Tag_Feature_GCS, 1;				\ | |
| 70 | .else;								\ | |
| 71 | .aeabi_attribute Tag_Feature_GCS, 0;				\ | |
| 72 | .endif;								\ | |
| 73 | .if ((value) & FEATURE_1_PAC);					\ | |
| 74 | .aeabi_attribute Tag_Feature_PAC, 1;				\ | |
| 75 | .else;								\ | |
| 76 | .aeabi_attribute Tag_Feature_PAC, 0;				\ | |
| 77 | .endif;								\ | |
| 78 | .text | |
| 79 | #else | |
| 80 | /* Add a NT_GNU_PROPERTY_TYPE_0 note. */ | |
| 81 | # define FEATURE_1_AND_MARK(value) GNU_PROPERTY (FEATURE_1_AND, value) | |
| 82 | #endif /* __ARM_BUILDATTR64_FV */ | |
| 83 | ||
| 84 | /* Add marking with the supported features to all asm code where sysdep.h | |
| 85 | is included. */ | |
| 86 | FEATURE_1_AND_MARK (FEATURE_1_BTI | FEATURE_1_PAC | FEATURE_1_GCS) | |
| 63 | 87 | |
| 64 | 88 | /* Define an entry point visible from C. */ |
| 65 | 89 | #define ENTRY(name)						\ |
lib/libc/glibc/sysdeps/arm/start.S+27| ... | ... | @@ -90,6 +90,7 @@ _start: |
| 90 | 90 | 	push { a1 } |
| 91 | 91 | |
| 92 | 92 | #ifdef PIC |
| 93 | # ifdef SHARED | |
| 93 | 94 | 	ldr sl, .L_GOT |
| 94 | 95 | 	adr a4, .L_GOT |
| 95 | 96 | 	add sl, sl, a4 |
| ... | ... | @@ -103,6 +104,16 @@ _start: |
| 103 | 104 | 	/* __libc_start_main (main, argc, argv, init, fini, rtld_fini, stack_end) */ |
| 104 | 105 | 	/* Let the libc call main and exit with its return code. */ |
| 105 | 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 | 117 | #else |
| 107 | 118 | |
| 108 | 119 | 	mov a4, #0		/* Used to init. */ |
| ... | ... | @@ -119,14 +130,30 @@ _start: |
| 119 | 130 | |
| 120 | 131 | #ifdef PIC |
| 121 | 132 | 	.align 2 |
| 133 | # ifdef SHARED | |
| 122 | 134 | .L_GOT: |
| 123 | 135 | 	.word _GLOBAL_OFFSET_TABLE_ - .L_GOT |
| 124 | 136 | 	.word main(GOT) |
| 137 | # else | |
| 138 | .L_main_rel: | |
| 139 | 	.word __wrap_main - .L_main_rel | |
| 140 | # endif | |
| 125 | 141 | #endif |
| 126 | 142 | |
| 127 | 143 | .cantunwind |
| 128 | 144 | .fnend |
| 129 | 145 | |
| 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 | 157 | /* Define a symbol for the first piece of initialized data. */ |
| 131 | 158 | 	.data |
| 132 | 159 | 	.globl __data_start |
lib/libc/glibc/sysdeps/htl/libc-lockP.h+14| ... | ... | @@ -21,6 +21,20 @@ |
| 21 | 21 | |
| 22 | 22 | #include <pthread.h> |
| 23 | 23 | |
| 24 | typedef 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 | 38 | /* If we check for a weakly referenced symbol and then perform a |
| 25 | 39 | normal jump to it te code generated for some platforms in case of |
| 26 | 40 | 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 | 36 | #define __ASSEMBLY__ 1 |
| 37 | 37 | #include <entry.h> |
| 38 | 38 | #include <sys/asm.h> |
| 39 | #include <sysdep.h> | |
| 39 | 40 | |
| 40 | 41 | /* The entry point's job is to call __libc_start_main. Per the ABI, |
| 41 | 42 | a0 contains the address of a function to be passed to atexit. |
| ... | ... | @@ -57,23 +58,32 @@ ENTRY (ENTRY_POINT) |
| 57 | 58 | /* Terminate call stack by noting ra is undefined. Use a dummy |
| 58 | 59 | .cfi_label to force starting the FDE. */ |
| 59 | 60 | 	.cfi_label .Ldummy |
| 60 | 	cfi_undefined (1) | |
| 61 | 	cfi_undefined	(1) | |
| 61 | 62 | 	or		a5, a0, zero /* rtld_fini */ |
| 62 | 63 | |
| 63 | 	la.pcrel	a0, t0, main | |
| 64 | #if defined PIC && !defined SHARED | |
| 65 | 	/* Avoid relocation in static PIE since _start is called before it | |
| 66 | 	 is relocated. */ | |
| 67 | 	la.pcrel	a0, __wrap_main | |
| 68 | #else | |
| 69 | 	LA_GOT		(a0, main) | |
| 70 | #endif | |
| 71 | ||
| 64 | 72 | 	REG_L		a1, sp, 0 |
| 65 | 73 | 	ADDI		a2, sp, SZREG |
| 66 | 74 | |
| 67 | 	/* Adjust $sp for 16-aligned */ | |
| 68 | 	BSTRINS		sp, zero, 3, 0 | |
| 75 | 	/* Adjust $sp for 16-bytes aligned */ | |
| 76 | 	REG_ALIGN_ASM	(sp, 4) | |
| 69 | 77 | |
| 70 | 78 | 	move		a3, zero /* used to be init */ |
| 71 | 79 | 	move		a4, zero /* used to be fini */ |
| 72 | 80 | 	or		a6, sp, zero /* stack_end */ |
| 73 | 81 | |
| 74 | 	la.pcrel	ra, t0, __libc_start_main | |
| 75 | 	jirl		ra, ra, 0 | |
| 82 | 	CALL		(__libc_start_main) | |
| 83 | 	CALL		(abort) | |
| 76 | 84 | |
| 77 | 	la.pcrel	ra, t0, abort | |
| 78 | 	jirl		ra, ra, 0 | |
| 85 | #if defined PIC && !defined SHARED | |
| 86 | __wrap_main: | |
| 87 | 	TAIL		(main) | |
| 88 | #endif | |
| 79 | 89 | END (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;	\ | |
| 78 | symbol: \ | |
| 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;	\ | |
| 89 | symbol: \ | |
| 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 | 145 | #define __rtld_lock_unlock_recursive(NAME) \ |
| 146 | 146 | __libc_lock_unlock_recursive (NAME) |
| 147 | 147 | |
| 148 | /* XXX for now */ | |
| 149 | #define __libc_rwlock_define		__libc_lock_define | |
| 150 | #define __libc_rwlock_define_initialized __libc_lock_define_initialized | |
| 151 | #define __libc_rwlock_init		__libc_lock_init | |
| 152 | #define __libc_rwlock_fini		__libc_lock_fini | |
| 153 | #define __libc_rwlock_rdlock		__libc_lock_lock | |
| 154 | #define __libc_rwlock_wrlock		__libc_lock_lock | |
| 155 | #define __libc_rwlock_tryrdlock		__libc_lock_trylock | |
| 156 | #define __libc_rwlock_trywrlock		__libc_lock_trylock | |
| 157 | #define __libc_rwlock_unlock		__libc_lock_unlock | |
| 148 | /* XXX for now, waiting for a futex-based pthread_rwlock implementation */ | |
| 149 | #define __mach_rwlock_define		__libc_lock_define | |
| 150 | #define __mach_rwlock_define_initialized __libc_lock_define_initialized | |
| 151 | #define __mach_rwlock_init		__libc_lock_init | |
| 152 | #define __mach_rwlock_fini		__libc_lock_fini | |
| 153 | #define __mach_rwlock_rdlock		__libc_lock_lock | |
| 154 | #define __mach_rwlock_wrlock		__libc_lock_lock | |
| 155 | #define __mach_rwlock_tryrdlock		__libc_lock_trylock | |
| 156 | #define __mach_rwlock_trywrlock		__libc_lock_trylock | |
| 157 | #define __mach_rwlock_unlock		__libc_lock_unlock | |
| 158 | 158 | |
| 159 | 159 | struct __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) \ | |
| 67 | lose: 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) \ | |
| 67 | lose: 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 | 155 | similar to kernel: |
| 156 | 156 | |
| 157 | 157 | - __ASSUME_CLONE_BACKWARDS: for variant 1. |
| 158 | - __ASSUME_CLONE_BACKWARDS2: for variant 2 (s390). | |
| 158 | - __ASSUME_CLONE_BACKWARDS2: for variant 2 (s390x). | |
| 159 | 159 | - __ASSUME_CLONE_BACKWARDS3: for variant 3 (microblaze). |
| 160 | 160 | - __ASSUME_CLONE_DEFAULT: for variant 4. |
| 161 | 161 | */ |
| ... | ... | @@ -266,4 +266,9 @@ |
| 266 | 266 | /* zig patch: don't assume kernel version */ |
| 267 | 267 | #define __ASSUME_MSEAL 0 |
| 268 | 268 | |
| 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 | 274 | #endif /* kernel-features.h */ |
lib/libc/glibc/sysdeps/unix/sysv/linux/loongarch/sysdep.h+25-6| ... | ... | @@ -19,6 +19,7 @@ |
| 19 | 19 | #ifndef _LINUX_LOONGARCH_SYSDEP_H |
| 20 | 20 | #define _LINUX_LOONGARCH_SYSDEP_H 1 |
| 21 | 21 | |
| 22 | #include <sysdeps/loongarch/sysdep.h> | |
| 22 | 23 | #include <sysdeps/unix/sysv/linux/sysdep.h> |
| 23 | 24 | #include <sysdeps/unix/sysdep.h> |
| 24 | 25 | #include <tls.h> |
| ... | ... | @@ -34,9 +35,9 @@ |
| 34 | 35 | #undef PSEUDO |
| 35 | 36 | #define PSEUDO(name, syscall_name, args) \ |
| 36 | 37 | ENTRY (name); \ |
| 37 | li.d a7, SYS_ify (syscall_name); \ | |
| 38 | LI a7, SYS_ify (syscall_name); \ | |
| 38 | 39 | syscall 0; \ |
| 39 | li.d a7, -4096; \ | |
| 40 | LI a7, -4096; \ | |
| 40 | 41 | bltu a7, a0, .Lsyscall_error##name; |
| 41 | 42 | |
| 42 | 43 | #undef PSEUDO_END |
| ... | ... | @@ -52,16 +53,16 @@ |
| 52 | 53 | .Lsyscall_error##name : la t0, rtld_errno; \ |
| 53 | 54 | sub.w a0, zero, a0; \ |
| 54 | 55 | st.w a0, t0, 0; \ |
| 55 | li.d a0, -1; | |
| 56 | LI a0, -1; | |
| 56 | 57 | |
| 57 | 58 | #else |
| 58 | 59 | |
| 59 | 60 | #define SYSCALL_ERROR_HANDLER(name) \ |
| 60 | 61 | .Lsyscall_error##name : la.tls.ie t0, errno; \ |
| 61 | add.d t0, tp, t0; \ | |
| 62 | ADD t0, tp, t0; \ | |
| 62 | 63 | sub.w a0, zero, a0; \ |
| 63 | 64 | st.w a0, t0, 0; \ |
| 64 | li.d a0, -1; | |
| 65 | LI a0, -1; | |
| 65 | 66 | |
| 66 | 67 | #endif |
| 67 | 68 | #else |
| ... | ... | @@ -74,7 +75,7 @@ |
| 74 | 75 | #undef PSEUDO_NEORRNO |
| 75 | 76 | #define PSEUDO_NOERRNO(name, syscall_name, args) \ |
| 76 | 77 | ENTRY (name); \ |
| 77 | li.d a7, SYS_ify (syscall_name); \ | |
| 78 | LI a7, SYS_ify (syscall_name); \ | |
| 78 | 79 | syscall 0; |
| 79 | 80 | |
| 80 | 81 | #undef PSEUDO_END_NOERRNO |
| ... | ... | @@ -85,11 +86,17 @@ |
| 85 | 86 | |
| 86 | 87 | /* Performs a system call, returning the error code. */ |
| 87 | 88 | #undef PSEUDO_ERRVAL |
| 89 | #if __loongarch_grlen == 64 | |
| 88 | 90 | #define PSEUDO_ERRVAL(name, syscall_name, args) \ |
| 89 | 91 | PSEUDO_NOERRNO (name, syscall_name, args); \ |
| 90 | 92 | slli.d a0, a0, 32; \ |
| 91 | 93 | srai.d a0, a0, 32; /* sign_ext */ \ |
| 92 | 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 | |
| 93 | 100 | |
| 94 | 101 | #undef PSEUDO_END_ERRVAL |
| 95 | 102 | #define PSEUDO_END_ERRVAL(name) END (name); |
| ... | ... | @@ -109,6 +116,18 @@ |
| 109 | 116 | #undef SYS_ify |
| 110 | 117 | #define SYS_ify(syscall_name) __NR_##syscall_name |
| 111 | 118 | |
| 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 | 131 | #ifndef __ASSEMBLER__ |
| 113 | 132 | |
| 114 | 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 | 57 | #define __TIMER_T_TYPE		void * |
| 58 | 58 | #define __BLKSIZE_T_TYPE	__SLONGWORD_TYPE |
| 59 | 59 | #define __FSID_T_TYPE		struct { int __val[2]; } |
| 60 | #if defined __GNUC__ && __GNUC__ <= 2 | |
| 61 | /* Compatibility with g++ 2.95.x. */ | |
| 62 | #define __SSIZE_T_TYPE		__SWORD_TYPE | |
| 63 | #else | |
| 64 | /* size_t is unsigned long int on s390 -m31. */ | |
| 65 | #define __SSIZE_T_TYPE		__SLONGWORD_TYPE | |
| 66 | #endif | |
| 60 | ||
| 61 | /* With s390-32, __SSIZE_T_TYPE was __SWORD_TYPE for compatibility with | |
| 62 | g++ 2.95.x. Afterwards __SLONGWORD_TYPE was needed as size_t was | |
| 63 | unsigned long int on s390-32. | |
| 64 | Now as only s390-64 exists, __SWORD_TYPE can be used as also used in the | |
| 65 | generic version as both types result in long int. */ | |
| 66 | #define __SSIZE_T_TYPE __SWORD_TYPE | |
| 67 | ||
| 67 | 68 | #define __SYSCALL_SLONG_TYPE	__SLONGWORD_TYPE |
| 68 | 69 | #define __SYSCALL_ULONG_TYPE	__ULONGWORD_TYPE |
| 69 | #define __CPU_MASK_TYPE 	__ULONGWORD_TYPE | |
| 70 | #define __CPU_MASK_TYPE		__ULONGWORD_TYPE | |
| 70 | 71 | |
| 71 | #ifdef __s390x__ | |
| 72 | 72 | /* Tell the libc code that off_t and off64_t are actually the same type |
| 73 | 73 | for all ABI purposes, even if possibly expressed as different base types |
| 74 | 74 | for C type-checking purposes. */ |
| 75 | # define __OFF_T_MATCHES_OFF64_T	1 | |
| 75 | #define __OFF_T_MATCHES_OFF64_T	1 | |
| 76 | 76 | |
| 77 | 77 | /* Same for ino_t and ino64_t. */ |
| 78 | # define __INO_T_MATCHES_INO64_T	1 | |
| 78 | #define __INO_T_MATCHES_INO64_T	1 | |
| 79 | 79 | |
| 80 | 80 | /* And for __rlim_t and __rlim64_t. */ |
| 81 | # define __RLIM_T_MATCHES_RLIM64_T	1 | |
| 81 | #define __RLIM_T_MATCHES_RLIM64_T	1 | |
| 82 | 82 | |
| 83 | 83 | /* And for fsblkcnt_t, fsblkcnt64_t, fsfilcnt_t and fsfilcnt64_t. */ |
| 84 | # define __STATFS_MATCHES_STATFS64 1 | |
| 84 | #define __STATFS_MATCHES_STATFS64 1 | |
| 85 | 85 | |
| 86 | 86 | /* And for getitimer, setitimer and rusage */ |
| 87 | # define __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64 1 | |
| 88 | #else | |
| 89 | # define __RLIM_T_MATCHES_RLIM64_T	0 | |
| 90 | ||
| 91 | # define __STATFS_MATCHES_STATFS64 0 | |
| 92 | ||
| 93 | /* And for getitimer, setitimer and rusage */ | |
| 94 | # define __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64 0 | |
| 95 | #endif | |
| 87 | #define __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64 1 | |
| 96 | 88 | |
| 97 | 89 | /* Number of descriptors that can fit in an `fd_set'. */ |
| 98 | 90 | #define	__FD_SETSIZE		1024 |
lib/libc/glibc/sysdeps/unix/sysv/linux/s390/kernel-features.h-3| ... | ... | @@ -47,9 +47,6 @@ |
| 47 | 47 | # undef __ASSUME_DIRECT_SYSVIPC_SYSCALLS |
| 48 | 48 | # undef __ASSUME_SYSVIPC_DEFAULT_IPC_64 |
| 49 | 49 | #endif |
| 50 | #ifndef __s390x__ | |
| 51 | # define __ASSUME_SYSVIPC_BROKEN_MODE_T | |
| 52 | #endif | |
| 53 | 50 | |
| 54 | 51 | #undef __ASSUME_CLONE_DEFAULT |
| 55 | 52 | #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 \ | |
| 98 | 0: 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 \ | |
| 112 | 0: 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 \ | |
| 125 | 0: larl %r1,_GLOBAL_OFFSET_TABLE_;					 \ | |
| 126 | lg %r1,errno@GOT(%r1);						 \ | |
| 127 | lcr %r2,%r2;							 \ | |
| 128 | st %r2,0(%r1);							 \ | |
| 129 | lghi %r2,-1;							 \ | |
| 130 | br %r14 | |
| 131 | # endif /* _LIBC_REENTRANT */ | |
| 132 | #endif /* PIC */ | |
| 133 | ||
| 134 | /* Linux takes system call arguments in registers: | |
| 135 | ||
| 136 | 	syscall number	1	 call-clobbered | |
| 137 | 	arg 1		2	 call-clobbered | |
| 138 | 	arg 2		3	 call-clobbered | |
| 139 | 	arg 3		4	 call-clobbered | |
| 140 | 	arg 4		5	 call-clobbered | |
| 141 | 	arg 5		6	 call-saved | |
| 142 | 	arg 6		7	 call-saved | |
| 143 | ||
| 144 | (Of course a function with say 3 arguments does not have entries for | |
| 145 | arguments 4 and 5.) | |
| 146 | For system calls with 6 parameters a stack operation is required | |
| 147 | to load the 6th parameter to register 7. Call saved register 7 is | |
| 148 | moved to register 0 and back to avoid an additional stack frame. | |
| 149 | */ | |
| 150 | ||
| 151 | #define DO_CALL(syscall, args)						 \ | |
| 152 | .if args > 5;								 \ | |
| 153 | lgr %r0,%r7;							 \ | |
| 154 | lg %r7,160(%r15);							 \ | |
| 155 | .endif;								 \ | |
| 156 | lghi %r1,SYS_ify (syscall);						 \ | |
| 157 | svc 0;								 \ | |
| 158 | .if args > 5;								 \ | |
| 159 | lgr %r7,%r0;							 \ | |
| 160 | .endif | |
| 161 | ||
| 162 | #define ret								 \ | |
| 163 | br	 14 | |
| 164 | ||
| 165 | #define ret_NOERRNO							 \ | |
| 166 | br	 14 | |
| 167 | ||
| 168 | #define ret_ERRVAL							 \ | |
| 169 | br	 14 | |
| 170 | ||
| 171 | #else | |
| 172 | ||
| 173 | # undef HAVE_INTERNAL_BRK_ADDR_SYMBOL | |
| 174 | # define HAVE_INTERNAL_BRK_ADDR_SYMBOL 1 | |
| 175 | ||
| 176 | #endif /* __ASSEMBLER__ */ | |
| 177 | ||
| 178 | #endif /* _LINUX_S390_SYSDEP_H */ |
lib/libc/glibc/sysdeps/unix/sysv/linux/s390/sysdep.h+186-37| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | /* Syscall definitions, Linux s390 version. | |
| 2 | Copyright (C) 2019-2026 Free Software Foundation, Inc. | |
| 1 | /* Assembler macros for 64 bit S/390. | |
| 2 | Copyright (C) 2001-2026 Free Software Foundation, Inc. | |
| 3 | 3 | This file is part of the GNU C Library. |
| 4 | 4 | |
| 5 | 5 | The GNU C Library is free software; you can redistribute it and/or |
| ... | ... | @@ -14,15 +14,163 @@ |
| 14 | 14 | |
| 15 | 15 | You should have received a copy of the GNU Lesser General Public |
| 16 | 16 | License along with the GNU C Library; if not, see |
| 17 | <http://www.gnu.org/licenses/>. */ | |
| 17 | <https://www.gnu.org/licenses/>. */ | |
| 18 | 18 | |
| 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 | |
| 20 | 34 | |
| 21 | 35 | #undef SYS_ify |
| 22 | 36 | #define SYS_ify(syscall_name)	__NR_##syscall_name |
| 23 | 37 | |
| 24 | #undef INTERNAL_SYSCALL_NCS | |
| 25 | #define INTERNAL_SYSCALL_NCS(no, nr, args...)				 \ | |
| 38 | #ifdef __ASSEMBLER__ | |
| 39 | ||
| 40 | /* Linux uses a negative return value to indicate syscall errors, unlike | |
| 41 | most Unices, which use the condition codes' carry flag. | |
| 42 | ||
| 43 | Since version 2.1 the return value of a system call might be negative | |
| 44 | even if the call succeeded.	E.g., the `lseek' system call might return | |
| 45 | a large offset. Therefore we must not anymore test for < 0, but test | |
| 46 | for a real error by making sure the value in gpr2 is a real error | |
| 47 | number. Linus said he will make sure that no syscall returns a value | |
| 48 | in -1 .. -4095 as a valid result so we can safely test with -4095. */ | |
| 49 | ||
| 50 | # undef PSEUDO | |
| 51 | # define PSEUDO(name, syscall_name, args)				 \ | |
| 52 | .text;								 \ | |
| 53 | ENTRY (name)								 \ | |
| 54 | DO_CALL (syscall_name, args);					 \ | |
| 55 | lghi %r4,-4095 ;							 \ | |
| 56 | clgr %r2,%r4 ;							 \ | |
| 57 | jgnl SYSCALL_ERROR_LABEL | |
| 58 | ||
| 59 | # undef PSEUDO_END | |
| 60 | # define PSEUDO_END(name)						 \ | |
| 61 | SYSCALL_ERROR_HANDLER;						 \ | |
| 62 | END (name) | |
| 63 | ||
| 64 | # undef PSEUDO_NOERRNO | |
| 65 | # define PSEUDO_NOERRNO(name, syscall_name, args)			 \ | |
| 66 | .text;								 \ | |
| 67 | ENTRY (name)								 \ | |
| 68 | DO_CALL (syscall_name, args) | |
| 69 | ||
| 70 | # undef PSEUDO_END_NOERRNO | |
| 71 | # define PSEUDO_END_NOERRNO(name)					 \ | |
| 72 | SYSCALL_ERROR_HANDLER;						 \ | |
| 73 | END (name) | |
| 74 | ||
| 75 | # undef PSEUDO_ERRVAL | |
| 76 | # define PSEUDO_ERRVAL(name, syscall_name, args)				 \ | |
| 77 | .text;								 \ | |
| 78 | ENTRY (name)								 \ | |
| 79 | DO_CALL (syscall_name, args);					 \ | |
| 80 | lcgr %r2,%r2 | |
| 81 | ||
| 82 | # undef PSEUDO_END_ERRVAL | |
| 83 | # define PSEUDO_END_ERRVAL(name)						 \ | |
| 84 | SYSCALL_ERROR_HANDLER;						 \ | |
| 85 | END (name) | |
| 86 | ||
| 87 | # undef SYSCALL_ERROR_LABEL | |
| 88 | # ifndef PIC | |
| 89 | # undef SYSCALL_ERROR_LABEL | |
| 90 | # define SYSCALL_ERROR_LABEL syscall_error | |
| 91 | # define SYSCALL_ERROR_HANDLER | |
| 92 | # else | |
| 93 | # if RTLD_PRIVATE_ERRNO | |
| 94 | # undef SYSCALL_ERROR_LABEL | |
| 95 | # define SYSCALL_ERROR_LABEL 0f | |
| 96 | # define SYSCALL_ERROR_HANDLER \ | |
| 97 | 0: 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 \ | |
| 111 | 0: 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 \ | |
| 124 | 0: 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 | 175 | DECLARGS_##nr(args)							 \ |
| 28 | 176 | register unsigned long int _nr __asm__("1") = (unsigned long int)(no); \ |
| ... | ... | @@ -34,51 +182,52 @@ |
| 34 | 182 | 			 : "memory" );					 \ |
| 35 | 183 | _ret; }) |
| 36 | 184 | |
| 37 | #undef INTERNAL_SYSCALL | |
| 38 | #define INTERNAL_SYSCALL(name, nr, args...)				\ | |
| 185 | # undef INTERNAL_SYSCALL | |
| 186 | # define INTERNAL_SYSCALL(name, nr, args...)				\ | |
| 39 | 187 | INTERNAL_SYSCALL_NCS(__NR_##name, nr, args) |
| 40 | 188 | |
| 41 | #define DECLARGS_0() | |
| 42 | #define DECLARGS_1(arg1) \ | |
| 189 | # define DECLARGS_0() | |
| 190 | # define DECLARGS_1(arg1) \ | |
| 43 | 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 | 193 | DECLARGS_1(arg1) \ |
| 46 | 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 | 196 | DECLARGS_2(arg1, arg2) \ |
| 49 | 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 | 199 | DECLARGS_3(arg1, arg2, arg3) \ |
| 52 | 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 | 202 | DECLARGS_4(arg1, arg2, arg3, arg4) \ |
| 55 | 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 | 205 | DECLARGS_5(arg1, arg2, arg3, arg4, arg5) \ |
| 58 | 206 | register unsigned long int gpr7 __asm__ ("7") = (unsigned long int)(arg6); |
| 59 | 207 | |
| 60 | #define ASMFMT_0 | |
| 61 | #define ASMFMT_1 , "0" (gpr2) | |
| 62 | #define ASMFMT_2 , "0" (gpr2), "d" (gpr3) | |
| 63 | #define ASMFMT_3 , "0" (gpr2), "d" (gpr3), "d" (gpr4) | |
| 64 | #define ASMFMT_4 , "0" (gpr2), "d" (gpr3), "d" (gpr4), "d" (gpr5) | |
| 65 | #define ASMFMT_5 , "0" (gpr2), "d" (gpr3), "d" (gpr4), "d" (gpr5), "d" (gpr6) | |
| 66 | #define ASMFMT_6 , "0" (gpr2), "d" (gpr3), "d" (gpr4), "d" (gpr5), "d" (gpr6), "d" (gpr7) | |
| 208 | # define ASMFMT_0 | |
| 209 | # define ASMFMT_1 , "0" (gpr2) | |
| 210 | # define ASMFMT_2 , "0" (gpr2), "d" (gpr3) | |
| 211 | # define ASMFMT_3 , "0" (gpr2), "d" (gpr3), "d" (gpr4) | |
| 212 | # define ASMFMT_4 , "0" (gpr2), "d" (gpr3), "d" (gpr4), "d" (gpr5) | |
| 213 | # define ASMFMT_5 , "0" (gpr2), "d" (gpr3), "d" (gpr4), "d" (gpr5), "d" (gpr6) | |
| 214 | # define ASMFMT_6 , "0" (gpr2), "d" (gpr3), "d" (gpr4), "d" (gpr5), "d" (gpr6), "d" (gpr7) | |
| 67 | 215 | |
| 68 | #define VDSO_NAME "LINUX_2.6.29" | |
| 69 | #define VDSO_HASH 123718585 | |
| 216 | # define VDSO_NAME "LINUX_2.6.29" | |
| 217 | # define VDSO_HASH 123718585 | |
| 70 | 218 | |
| 71 | 219 | /* List of system calls which are supported as vsyscalls. */ |
| 72 | #ifdef __s390x__ | |
| 73 | #define HAVE_CLOCK_GETRES64_VSYSCALL	"__kernel_clock_getres" | |
| 74 | #define HAVE_CLOCK_GETTIME64_VSYSCALL	"__kernel_clock_gettime" | |
| 75 | #define HAVE_GETRANDOM_VSYSCALL		"__kernel_getrandom" | |
| 76 | #else | |
| 77 | #define HAVE_CLOCK_GETRES_VSYSCALL	"__kernel_clock_getres" | |
| 78 | #define HAVE_CLOCK_GETTIME_VSYSCALL	"__kernel_clock_gettime" | |
| 79 | #endif | |
| 80 | #define HAVE_GETTIMEOFDAY_VSYSCALL	"__kernel_gettimeofday" | |
| 81 | #define HAVE_GETCPU_VSYSCALL		"__kernel_getcpu" | |
| 82 | ||
| 83 | #define HAVE_CLONE3_WRAPPER		1 | |
| 84 | #endif | |
| 220 | # define HAVE_CLOCK_GETRES64_VSYSCALL	"__kernel_clock_getres" | |
| 221 | # define HAVE_CLOCK_GETTIME64_VSYSCALL	"__kernel_clock_gettime" | |
| 222 | # define HAVE_GETRANDOM_VSYSCALL		"__kernel_getrandom" | |
| 223 | # define HAVE_GETTIMEOFDAY_VSYSCALL	"__kernel_gettimeofday" | |
| 224 | # define HAVE_GETCPU_VSYSCALL		"__kernel_getcpu" | |
| 225 | ||
| 226 | # define HAVE_CLONE3_WRAPPER		1 | |
| 227 | ||
| 228 | # undef HAVE_INTERNAL_BRK_ADDR_SYMBOL | |
| 229 | # define HAVE_INTERNAL_BRK_ADDR_SYMBOL 1 | |
| 230 | ||
| 231 | #endif /* __ASSEMBLER__ */ | |
| 232 | ||
| 233 | #endif /* _LINUX_S390_SYSDEP_H */ |
lib/libc/glibc/sysdeps/unix/sysv/linux/s390/xstatver.h+6-15| ... | ... | @@ -1,19 +1,10 @@ |
| 1 | 1 | /* Versions of the 'struct stat' data structure used in compatibility xstat |
| 2 | 2 | functions. */ |
| 3 | ||
| 4 | #include <bits/wordsize.h> | |
| 5 | ||
| 6 | #if __WORDSIZE == 64 | |
| 7 | # define _STAT_VER_KERNEL	0 | |
| 8 | # define _STAT_VER_LINUX	1 | |
| 9 | # define _MKNOD_VER_LINUX	0 | |
| 10 | #else | |
| 11 | # define _STAT_VER_LINUX_OLD	1 | |
| 12 | # define _STAT_VER_KERNEL	1 | |
| 13 | # define _STAT_VER_SVR4		2 | |
| 14 | # define _STAT_VER_LINUX	3 | |
| 15 | # define _MKNOD_VER_LINUX	1 | |
| 16 | # define _MKNOD_VER_SVR4	2 | |
| 17 | #endif | |
| 3 | #define _STAT_VER_KERNEL	0 | |
| 4 | #define _STAT_VER_LINUX		1 | |
| 18 | 5 | #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 | 10 | #define _MKNOD_VER		_MKNOD_VER_LINUX |
lib/libc/include/aarch64-linux-gnu/bits/hwcap.h+18-1| ... | ... | @@ -55,6 +55,21 @@ |
| 55 | 55 | #define HWCAP_PACA		(1 << 30) |
| 56 | 56 | #define HWCAP_PACG		(1UL << 31) |
| 57 | 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) | |
| 58 | 73 | |
| 59 | 74 | #define HWCAP2_DCPODP		(1 << 0) |
| 60 | 75 | #define HWCAP2_SVE2		(1 << 1) |
| ... | ... | @@ -122,4 +137,6 @@ |
| 122 | 137 | #define HWCAP2_POE		(1UL << 63) |
| 123 | 138 | |
| 124 | 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 | 157 | # define __DECL_SIMD_pow __DECL_SIMD_aarch64 |
| 158 | 158 | # undef __DECL_SIMD_powf |
| 159 | 159 | # 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 | 164 | # undef __DECL_SIMD_rsqrt |
| 161 | 165 | # define __DECL_SIMD_rsqrt __DECL_SIMD_aarch64 |
| 162 | 166 | # undef __DECL_SIMD_rsqrtf |
| ... | ... | @@ -243,6 +247,7 @@ __vpcs __f32x4_t _ZGVnN4v_log2f (__f32x4_t); |
| 243 | 247 | __vpcs __f32x4_t _ZGVnN4v_log2p1f (__f32x4_t); |
| 244 | 248 | __vpcs __f32x4_t _ZGVnN4v_logp1f (__f32x4_t); |
| 245 | 249 | __vpcs __f32x4_t _ZGVnN4vv_powf (__f32x4_t, __f32x4_t); |
| 250 | __vpcs __f32x4_t _ZGVnN4vv_powrf (__f32x4_t, __f32x4_t); | |
| 246 | 251 | __vpcs __f32x4_t _ZGVnN4v_rsqrtf (__f32x4_t); |
| 247 | 252 | __vpcs __f32x4_t _ZGVnN4v_sinf (__f32x4_t); |
| 248 | 253 | __vpcs __f32x4_t _ZGVnN4v_sinhf (__f32x4_t); |
| ... | ... | @@ -283,6 +288,7 @@ __vpcs __f64x2_t _ZGVnN2v_log2 (__f64x2_t); |
| 283 | 288 | __vpcs __f64x2_t _ZGVnN2v_log2p1 (__f64x2_t); |
| 284 | 289 | __vpcs __f64x2_t _ZGVnN2v_logp1 (__f64x2_t); |
| 285 | 290 | __vpcs __f64x2_t _ZGVnN2vv_pow (__f64x2_t, __f64x2_t); |
| 291 | __vpcs __f64x2_t _ZGVnN2vv_powr (__f64x2_t, __f64x2_t); | |
| 286 | 292 | __vpcs __f64x2_t _ZGVnN2v_rsqrt (__f64x2_t); |
| 287 | 293 | __vpcs __f64x2_t _ZGVnN2v_sin (__f64x2_t); |
| 288 | 294 | __vpcs __f64x2_t _ZGVnN2v_sinh (__f64x2_t); |
| ... | ... | @@ -328,6 +334,7 @@ __sv_f32_t _ZGVsMxv_log2f (__sv_f32_t, __sv_bool_t); |
| 328 | 334 | __sv_f32_t _ZGVsMxv_log2p1f (__sv_f32_t, __sv_bool_t); |
| 329 | 335 | __sv_f32_t _ZGVsMxv_logp1f (__sv_f32_t, __sv_bool_t); |
| 330 | 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 | 338 | __sv_f32_t _ZGVsMxv_rsqrtf (__sv_f32_t, __sv_bool_t); |
| 332 | 339 | __sv_f32_t _ZGVsMxv_sinf (__sv_f32_t, __sv_bool_t); |
| 333 | 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 | 375 | __sv_f64_t _ZGVsMxv_log2p1 (__sv_f64_t, __sv_bool_t); |
| 369 | 376 | __sv_f64_t _ZGVsMxv_logp1 (__sv_f64_t, __sv_bool_t); |
| 370 | 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 | 379 | __sv_f64_t _ZGVsMxv_rsqrt (__sv_f64_t, __sv_bool_t); |
| 372 | 380 | __sv_f64_t _ZGVsMxv_sin (__sv_f64_t, __sv_bool_t); |
| 373 | 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 | ||
| 44 | struct 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 | |
| 85 | struct 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 | 16 | ! License along with the GNU C Library; if not, see |
| 17 | 17 | ! <https://www.gnu.org/licenses/>. |
| 18 | 18 | |
| 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 | 24 | #define LIBRESOLV_SO "libresolv.so.2" |
| 25 | 25 | #define LIBRT_SO "librt.so.1" |
| 26 | 26 | #define LIBTHREAD_DB_SO "libthread_db.so.1" |
| 27 | #define LIBUNWIND_SO "libunwind.so.1" | |
| 27 | 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 | 24 | #define LIBRESOLV_SO "libresolv.so.2" |
| 25 | 25 | #define LIBRT_SO "librt.so.1" |
| 26 | 26 | #define LIBTHREAD_DB_SO "libthread_db.so.1" |
| 27 | #define LIBUNWIND_SO "libunwind.so.1" | |
| 27 | 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 | ||
| 44 | struct 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 | |
| 85 | struct 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 | 25 | #define LIBRESOLV_SO "libresolv.so.2" |
| 26 | 26 | #define LIBRT_SO "librt.so.1" |
| 27 | 27 | #define LIBTHREAD_DB_SO "libthread_db.so.1" |
| 28 | #define LIBUNWIND_SO "libunwind.so.1" | |
| 28 | 29 | #define LIBUTIL_SO "libutil.so.1" |
| 29 | 30 | |
| 30 | 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 | 31 | #define LIBRESOLV_SO "libresolv.so.2" |
| 32 | 32 | #define LIBRT_SO "librt.so.1" |
| 33 | 33 | #define LIBTHREAD_DB_SO "libthread_db.so.1" |
| 34 | #define LIBUNWIND_SO "libunwind.so.1" | |
| 34 | 35 | #define LIBUTIL_SO "libutil.so.1" |
| 35 | 36 | |
| 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 | 52 | comma in the initializer list, can be passed to assert. This |
| 53 | 53 | depends on support for variadic macros (added in C99 and GCC 2.95), |
| 54 | 54 | and on support for _Bool (added in C99 and GCC 3.0) in order to |
| 55 | validate that only a single expression is passed as an argument, | |
| 56 | and is currently implemented only for C. */ | |
| 57 | #if (__GLIBC_USE (ISOC23)						\ | |
| 58 | && (defined __GNUC__						\ | |
| 59 | 	 ? __GNUC_PREREQ (3, 0)						\ | |
| 60 | 	 : defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L)	\ | |
| 61 | && !defined __cplusplus) | |
| 55 | validate that only a single expression is passed as an argument. */ | |
| 56 | #if ((__GLIBC_USE (ISOC23)						\ | |
| 57 | && (defined __GNUC__						\ | |
| 58 | 	 ? __GNUC_PREREQ (3, 0)					\ | |
| 59 | 	 : defined __STDC_VERSION__ && __STDC_VERSION__ >= 199901L))	\ | |
| 60 | || (defined __cplusplus && __cplusplus > 202302L)) | |
| 62 | 61 | # define __ASSERT_VARIADIC 1 |
| 63 | 62 | #else |
| 64 | 63 | # define __ASSERT_VARIADIC 0 |
| ... | ... | @@ -108,7 +107,7 @@ extern void __assert (const char *__assertion, const char *__file, int __line) |
| 108 | 107 | __THROW __attribute__ ((__noreturn__)) __COLD; |
| 109 | 108 | |
| 110 | 109 | |
| 111 | # if __ASSERT_VARIADIC | |
| 110 | # if __ASSERT_VARIADIC && !defined __cplusplus | |
| 112 | 111 | /* This function is not defined and is not called outside of an |
| 113 | 112 | unevaluated sizeof, but serves to verify that the argument to |
| 114 | 113 | assert is a single expression. */ |
| ... | ... | @@ -131,11 +130,22 @@ __END_DECLS |
| 131 | 130 | # define __ASSERT_FILE __FILE__ |
| 132 | 131 | # define __ASSERT_LINE __LINE__ |
| 133 | 132 | # 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 | 144 | (static_cast <bool> (expr)						\ |
| 136 | 145 | ? void (0)							\ |
| 137 | 146 | : __assert_fail (#expr, __ASSERT_FILE, __ASSERT_LINE, \ |
| 138 | 147 | __ASSERT_FUNCTION)) |
| 148 | # endif | |
| 139 | 149 | # elif !defined __GNUC__ || defined __STRICT_ANSI__ |
| 140 | 150 | # if __ASSERT_VARIADIC |
| 141 | 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 | 81 | #ifndef __O_NOFOLLOW |
| 82 | 82 | # define __O_NOFOLLOW	0400000 |
| 83 | 83 | #endif |
| 84 | #ifndef __O_CLOEXEC | |
| 85 | # define __O_CLOEXEC 02000000 | |
| 86 | #endif | |
| 84 | #include <bits/cloexec.h> | |
| 87 | 85 | #ifndef __O_DIRECT |
| 88 | 86 | # define __O_DIRECT	 040000 |
| 89 | 87 | #endif |
| ... | ... | @@ -176,8 +174,8 @@ |
| 176 | 174 | #endif |
| 177 | 175 | |
| 178 | 176 | #if defined __USE_UNIX98 || defined __USE_XOPEN2K8 |
| 179 | # define F_SETOWN	__F_SETOWN /* Get owner (process receiving SIGIO). */ | |
| 180 | # define F_GETOWN	__F_GETOWN /* Set owner (process receiving SIGIO). */ | |
| 177 | # define F_SETOWN	__F_SETOWN /* Set owner (process receiving SIGIO). */ | |
| 178 | # define F_GETOWN	__F_GETOWN /* Get owner (process receiving SIGIO). */ | |
| 181 | 179 | #endif |
| 182 | 180 | |
| 183 | 181 | #ifndef __F_SETSIG |
| ... | ... | @@ -185,15 +183,15 @@ |
| 185 | 183 | # define __F_GETSIG	11	/* Get number of signal to be sent. */ |
| 186 | 184 | #endif |
| 187 | 185 | #ifndef __F_SETOWN_EX |
| 188 | # define __F_SETOWN_EX	15	/* Get owner (thread receiving SIGIO). */ | |
| 189 | # define __F_GETOWN_EX	16	/* Set owner (thread receiving SIGIO). */ | |
| 186 | # define __F_SETOWN_EX	15	/* Set owner (thread receiving SIGIO). */ | |
| 187 | # define __F_GETOWN_EX	16	/* Get owner (thread receiving SIGIO). */ | |
| 190 | 188 | #endif |
| 191 | 189 | |
| 192 | 190 | #ifdef __USE_GNU |
| 193 | 191 | # define F_SETSIG	__F_SETSIG	/* Set number of signal to be sent. */ |
| 194 | 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). */ | |
| 196 | # define F_GETOWN_EX	__F_GETOWN_EX	/* Set owner (thread receiving SIGIO). */ | |
| 193 | # define F_SETOWN_EX	__F_SETOWN_EX	/* Set owner (thread receiving SIGIO). */ | |
| 194 | # define F_GETOWN_EX	__F_GETOWN_EX	/* Get owner (thread receiving SIGIO). */ | |
| 197 | 195 | #endif |
| 198 | 196 | |
| 199 | 197 | #ifdef __USE_GNU |
| ... | ... | @@ -203,7 +201,7 @@ |
| 203 | 201 | # define F_DUPFD_QUERY 1027 /* Compare two file descriptors for sameness. */ |
| 204 | 202 | # define F_CREATED_QUERY 1028 /* Was the file just created? */ |
| 205 | 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 | 205 | # define F_ADD_SEALS	1033	/* Add seals to file. */ |
| 208 | 206 | # define F_GET_SEALS	1034	/* Get seals for file. */ |
| 209 | 207 | /* Set / get write life time hints. */ |
| ... | ... | @@ -211,6 +209,8 @@ |
| 211 | 209 | # define F_SET_RW_HINT	1036 |
| 212 | 210 | # define F_GET_FILE_RW_HINT	1037 |
| 213 | 211 | # define F_SET_FILE_RW_HINT	1038 |
| 212 | # define F_GETDELEG	1039	/* Get delegation. */ | |
| 213 | # define F_SETDELEG	1040	/* Set delegation. */ | |
| 214 | 214 | #endif |
| 215 | 215 | #ifdef __USE_XOPEN2K8 |
| 216 | 216 | # define F_DUPFD_CLOEXEC 1030	/* Duplicate file descriptor with |
| ... | ... | @@ -221,6 +221,7 @@ |
| 221 | 221 | #define FD_CLOEXEC	1	/* Actually anything with low bit set goes */ |
| 222 | 222 | #ifdef __USE_GNU |
| 223 | 223 | # define FD_PIDFS_ROOT	-10002	/* Root of the pidfs filesystem */ |
| 224 | # define FD_NSFS_ROOT	-10003	/* Root of the nsfs filesystem */ | |
| 224 | 225 | #endif |
| 225 | 226 | |
| 226 | 227 | #ifndef F_RDLCK |
lib/libc/include/generic-glibc/bits/libm-simd-decl-stubs.h+11| ... | ... | @@ -99,6 +99,17 @@ |
| 99 | 99 | #define __DECL_SIMD_powf64x |
| 100 | 100 | #define __DECL_SIMD_powf128x |
| 101 | 101 | |
| 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 | 113 | #define __DECL_SIMD_acos |
| 103 | 114 | #define __DECL_SIMD_acosf |
| 104 | 115 | #define __DECL_SIMD_acosl |
lib/libc/include/generic-glibc/bits/long-double.h+3-6| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | /* Properties of long double type. MIPS version. | |
| 1 | /* Properties of long double type. ldbl-128 version. | |
| 2 | 2 | Copyright (C) 2016-2026 Free Software Foundation, Inc. |
| 3 | 3 | This file is part of the GNU C Library. |
| 4 | 4 | |
| ... | ... | @@ -16,9 +16,6 @@ |
| 16 | 16 | License along with the GNU C Library; if not, see |
| 17 | 17 | <https://www.gnu.org/licenses/>. */ |
| 18 | 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 | |
| 19 | /* long double is distinct from double, so there is nothing to | |
| 20 | define here. */ | |
| 24 | 21 | #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 | 197 | __MATHCALL (pown,, (_Mdouble_ __x, long long int __y)); |
| 198 | 198 | |
| 199 | 199 | /* Return X to the Y power. */ |
| 200 | __MATHCALL_VEC (powr,, (_Mdouble_ __x, _Mdouble_ __y)); | |
| 200 | 201 | __MATHCALL (powr,, (_Mdouble_ __x, _Mdouble_ __y)); |
| 201 | 202 | |
| 202 | 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. */ | |
| 29 | extern 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 | 54 | #define SCHED_FLAG_UTIL_CLAMP \ |
| 55 | 55 | (SCHED_FLAG_UTIL_CLAMP_MIN | SCHED_FLAG_UTIL_CLAMP_MAX) |
| 56 | 56 | |
| 57 | /* Flags for the flags argument of sched_getattr. */ | |
| 58 | #define SCHED_GETATTR_FLAG_DL_DYNAMIC	0x01 | |
| 59 | ||
| 57 | 60 | /* Use "" to work around incorrect macro expansion of the |
| 58 | 61 | __has_include argument (GCC PR 80005). */ |
| 59 | 62 | # ifdef __has_include |
lib/libc/include/generic-glibc/bits/struct_stat.h+54-164| ... | ... | @@ -23,215 +23,105 @@ |
| 23 | 23 | #ifndef _BITS_STRUCT_STAT_H |
| 24 | 24 | #define _BITS_STRUCT_STAT_H	1 |
| 25 | 25 | |
| 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 | |
| 27 | 43 | |
| 28 | #if _MIPS_SIM == _ABIO32 | |
| 29 | /* Structure describing file characteristics. */ | |
| 30 | 44 | struct stat |
| 31 | 45 | { |
| 32 | # ifdef __USE_TIME64_REDIRECTS | |
| 33 | # include <bits/struct_stat_time64_helper.h> | |
| 34 | # else | |
| 35 | unsigned long int st_dev; | |
| 36 | long int st_pad1[3]; | |
| 37 | # ifndef __USE_FILE_OFFSET64 | |
| 38 | __ino_t st_ino;		/* File serial number.		*/ | |
| 39 | # else | |
| 40 | __ino64_t st_ino;		/* File serial number.		*/ | |
| 41 | # endif | |
| 46 | __dev_t st_dev;		/* Device. */ | |
| 47 | __field64(__ino_t, __ino64_t, st_ino); /* File serial number. */ | |
| 42 | 48 | __mode_t st_mode;		/* File mode. */ |
| 43 | 49 | __nlink_t st_nlink;		/* Link count. */ |
| 44 | 50 | __uid_t st_uid;		/* User ID of the file's owner.	*/ |
| 45 | 51 | __gid_t st_gid;		/* Group ID of the file's group.*/ |
| 46 | unsigned long int st_rdev;	/* Device number, if device. */ | |
| 47 | # ifndef __USE_FILE_OFFSET64 | |
| 48 | long int st_pad2[2]; | |
| 49 | __off_t st_size;		/* Size of file, in bytes. */ | |
| 50 | /* SVR4 added this extra long to allow for expansion of off_t. */ | |
| 51 | long int st_pad3; | |
| 52 | # else | |
| 53 | long int st_pad2[3]; | |
| 54 | __off64_t st_size;		/* Size of file, in bytes. */ | |
| 55 | # endif | |
| 56 | # ifdef __USE_XOPEN2K8 | |
| 52 | __dev_t st_rdev;		/* Device number, if device. */ | |
| 53 | __dev_t __pad1; | |
| 54 | __field64(__off_t, __off64_t, st_size); /* Size of file, in bytes. */ | |
| 55 | __blksize_t st_blksize;	/* Optimal block size for I/O. */ | |
| 56 | int __pad2; | |
| 57 | __field64(__blkcnt_t, __blkcnt64_t, st_blocks); /* 512-byte blocks */ | |
| 58 | #ifdef __USE_XOPEN2K8 | |
| 57 | 59 | /* Nanosecond resolution timestamps are stored in a format |
| 58 | 60 | equivalent to 'struct timespec'. This is the type used |
| 59 | 61 | whenever possible but the Unix namespace rules do not allow the |
| 60 | 62 | identifier 'timespec' to appear in the <sys/stat.h> header. |
| 61 | 63 | Therefore we have to handle the use of this header in strictly |
| 62 | 64 | standard-compliant sources special. */ |
| 63 | struct timespec st_atim; /* Time of last access. */ | |
| 64 | struct timespec st_mtim; /* Time of last modification. */ | |
| 65 | struct timespec st_ctim; /* Time of last status change. */ | |
| 66 | # define st_atime st_atim.tv_sec /* Backward compatibility. */ | |
| 67 | # define st_mtime st_mtim.tv_sec | |
| 68 | # define st_ctime st_ctim.tv_sec | |
| 69 | # else | |
| 65 | struct timespec st_atim;		/* Time of last access. */ | |
| 66 | struct timespec st_mtim;		/* Time of last modification. */ | |
| 67 | struct timespec st_ctim;		/* Time of last status change. */ | |
| 68 | # define st_atime st_atim.tv_sec	/* Backward compatibility. */ | |
| 69 | # define st_mtime st_mtim.tv_sec | |
| 70 | # define st_ctime st_ctim.tv_sec | |
| 71 | #else | |
| 70 | 72 | __time_t st_atime;			/* Time of last access. */ |
| 71 | 73 | unsigned long int st_atimensec;	/* Nscecs of last access. */ |
| 72 | 74 | __time_t st_mtime;			/* Time of last modification. */ |
| 73 | 75 | unsigned long int st_mtimensec;	/* Nsecs of last modification. */ |
| 74 | 76 | __time_t st_ctime;			/* Time of last status change. */ |
| 75 | 77 | unsigned long int st_ctimensec;	/* Nsecs of last status change. */ |
| 76 | # endif | |
| 77 | __blksize_t st_blksize;	/* Optimal block size for I/O. */ | |
| 78 | # ifndef __USE_FILE_OFFSET64 | |
| 79 | __blkcnt_t st_blocks;	/* Number of 512-byte blocks allocated. */ | |
| 80 | # else | |
| 81 | long int st_pad4; | |
| 82 | __blkcnt64_t st_blocks;	/* Number of 512-byte blocks allocated. */ | |
| 83 | # endif | |
| 84 | long int st_pad5[14]; | |
| 85 | # endif /* __USE_TIME64_REDIRECTS */ | |
| 78 | #endif | |
| 79 | int __glibc_reserved[2]; | |
| 86 | 80 | }; |
| 87 | 81 | |
| 88 | # ifdef __USE_LARGEFILE64 | |
| 82 | #undef __field64 | |
| 83 | ||
| 84 | #ifdef __USE_LARGEFILE64 | |
| 89 | 85 | struct stat64 |
| 90 | 86 | { |
| 91 | # ifdef __USE_TIME64_REDIRECTS | |
| 92 | # include <bits/struct_stat_time64_helper.h> | |
| 93 | # else | |
| 94 | unsigned long int st_dev; | |
| 95 | long int st_pad1[3]; | |
| 96 | __ino64_t st_ino;		/* File serial number.		*/ | |
| 87 | __dev_t st_dev;		/* Device. */ | |
| 88 | __ino64_t st_ino;		/* File serial number.	*/ | |
| 97 | 89 | __mode_t st_mode;		/* File mode. */ |
| 98 | 90 | __nlink_t st_nlink;		/* Link count. */ |
| 99 | 91 | __uid_t st_uid;		/* User ID of the file's owner.	*/ |
| 100 | 92 | __gid_t st_gid;		/* Group ID of the file's group.*/ |
| 101 | unsigned long int st_rdev;	/* Device number, if device. */ | |
| 102 | long int st_pad2[3]; | |
| 93 | __dev_t st_rdev;		/* Device number, if device. */ | |
| 94 | __dev_t __pad1; | |
| 103 | 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 | 96 | __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 | ||
| 132 | struct stat | |
| 133 | { | |
| 134 | # ifdef __USE_TIME64_REDIRECTS | |
| 135 | # include <bits/struct_stat_time64_helper.h> | |
| 136 | # else | |
| 137 | __dev_t st_dev; | |
| 138 | int	st_pad1[3];		/* Reserved for st_dev expansion */ | |
| 139 | # ifndef __USE_FILE_OFFSET64 | |
| 140 | __ino_t st_ino; | |
| 141 | # else | |
| 142 | __ino64_t st_ino; | |
| 143 | # endif | |
| 144 | __mode_t st_mode; | |
| 145 | __nlink_t st_nlink; | |
| 146 | __uid_t st_uid; | |
| 147 | __gid_t st_gid; | |
| 148 | __dev_t st_rdev; | |
| 149 | # if !defined __USE_FILE_OFFSET64 | |
| 150 | unsigned int st_pad2[2];	/* Reserved for st_rdev expansion */ | |
| 151 | __off_t st_size; | |
| 152 | int st_pad3; | |
| 153 | # else | |
| 154 | unsigned int st_pad2[3];	/* Reserved for st_rdev expansion */ | |
| 155 | __off64_t st_size; | |
| 156 | # endif | |
| 157 | # ifdef __USE_XOPEN2K8 | |
| 97 | int __pad2; | |
| 98 | __blkcnt64_t st_blocks;	/* Nr. 512-byte blocks allocated. */ | |
| 99 | #ifdef __USE_XOPEN2K8 | |
| 158 | 100 | /* Nanosecond resolution timestamps are stored in a format |
| 159 | 101 | equivalent to 'struct timespec'. This is the type used |
| 160 | 102 | whenever possible but the Unix namespace rules do not allow the |
| 161 | 103 | identifier 'timespec' to appear in the <sys/stat.h> header. |
| 162 | 104 | Therefore we have to handle the use of this header in strictly |
| 163 | 105 | standard-compliant sources special. */ |
| 164 | struct timespec st_atim; /* Time of last access. */ | |
| 165 | struct timespec st_mtim; /* Time of last modification. */ | |
| 166 | struct timespec st_ctim; /* Time of last status change. */ | |
| 167 | # define st_atime st_atim.tv_sec /* Backward compatibility. */ | |
| 168 | # define st_mtime st_mtim.tv_sec | |
| 169 | # define st_ctime st_ctim.tv_sec | |
| 170 | # else | |
| 106 | struct timespec st_atim;		/* Time of last access. */ | |
| 107 | struct timespec st_mtim;		/* Time of last modification. */ | |
| 108 | struct timespec st_ctim;		/* Time of last status change. */ | |
| 109 | #else | |
| 171 | 110 | __time_t st_atime;			/* Time of last access. */ |
| 172 | 111 | unsigned long int st_atimensec;	/* Nscecs of last access. */ |
| 173 | 112 | __time_t st_mtime;			/* Time of last modification. */ |
| 174 | 113 | unsigned long int st_mtimensec;	/* Nsecs of last modification. */ |
| 175 | 114 | __time_t st_ctime;			/* Time of last status change. */ |
| 176 | 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 | |
| 190 | struct 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 | 116 | #endif |
| 230 | ||
| 117 | int __glibc_reserved[2]; | |
| 118 | }; | |
| 231 | 119 | #endif |
| 232 | 120 | |
| 233 | 121 | /* Tell code we have these members. */ |
| 234 | 122 | #define	_STATBUF_ST_BLKSIZE |
| 235 | #define	_STATBUF_ST_RDEV | |
| 123 | #define _STATBUF_ST_RDEV | |
| 124 | /* Nanosecond resolution time values are supported. */ | |
| 125 | #define _STATBUF_ST_NSEC | |
| 236 | 126 | |
| 237 | 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 | 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. */ | |
| 3 | 3 | |
| 4 | 4 | #ifndef _SYSCALL_H |
| 5 | 5 | # error "Never use <bits/syscall.h> directly; include <sys/syscall.h> instead." |
| 6 | 6 | #endif |
| 7 | 7 | |
| 8 | #define __GLIBC_LINUX_VERSION_CODE 397568 | |
| 8 | #define __GLIBC_LINUX_VERSION_CODE 459008 | |
| 9 | 9 | |
| 10 | 10 | #ifdef __NR_FAST_atomic_update |
| 11 | 11 | # define SYS_FAST_atomic_update __NR_FAST_atomic_update |
| ... | ... | @@ -883,6 +883,10 @@ |
| 883 | 883 | # define SYS_listmount __NR_listmount |
| 884 | 884 | #endif |
| 885 | 885 | |
| 886 | #ifdef __NR_listns | |
| 887 | # define SYS_listns __NR_listns | |
| 888 | #endif | |
| 889 | ||
| 886 | 890 | #ifdef __NR_listxattr |
| 887 | 891 | # define SYS_listxattr __NR_listxattr |
| 888 | 892 | #endif |
| ... | ... | @@ -1899,6 +1903,10 @@ |
| 1899 | 1903 | # define SYS_rseq __NR_rseq |
| 1900 | 1904 | #endif |
| 1901 | 1905 | |
| 1906 | #ifdef __NR_rseq_slice_yield | |
| 1907 | # define SYS_rseq_slice_yield __NR_rseq_slice_yield | |
| 1908 | #endif | |
| 1909 | ||
| 1902 | 1910 | #ifdef __NR_rt_sigaction |
| 1903 | 1911 | # define SYS_rt_sigaction __NR_rt_sigaction |
| 1904 | 1912 | #endif |
| ... | ... | @@ -2551,6 +2559,10 @@ |
| 2551 | 2559 | # define SYS_unshare __NR_unshare |
| 2552 | 2560 | #endif |
| 2553 | 2561 | |
| 2562 | #ifdef __NR_uprobe | |
| 2563 | # define SYS_uprobe __NR_uprobe | |
| 2564 | #endif | |
| 2565 | ||
| 2554 | 2566 | #ifdef __NR_uretprobe |
| 2555 | 2567 | # define SYS_uretprobe __NR_uretprobe |
| 2556 | 2568 | #endif |
lib/libc/include/generic-glibc/bits/timesize.h+3-5| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | /* Bit size of the time_t type at glibc build time, Linux/MIPS. | |
| 2 | Copyright (C) 2021-2026 Free Software Foundation, Inc. | |
| 1 | /* Bit size of the time_t type at glibc build time, general case. | |
| 2 | Copyright (C) 2018-2026 Free Software Foundation, Inc. | |
| 3 | 3 | This file is part of the GNU C Library. |
| 4 | 4 | |
| 5 | 5 | The GNU C Library is free software; you can redistribute it and/or |
| ... | ... | @@ -16,7 +16,5 @@ |
| 16 | 16 | License along with the GNU C Library; if not, see |
| 17 | 17 | <https://www.gnu.org/licenses/>. */ |
| 18 | 18 | |
| 19 | #include <bits/wordsize.h> | |
| 20 | ||
| 21 | 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 | 51 | #define RWF_ATOMIC	0x00000040 /* Write is to be issued with torn-write |
| 52 | 52 | 				 prevention. */ |
| 53 | 53 | #define RWF_DONTCACHE	0x00000080 /* Uncached buffered IO. */ |
| 54 | #define RWF_NOSIGNAL	0x00000100 /* Do not generate SIGPIPE on error. */ | |
| 54 | 55 | |
| 55 | 56 | __END_DECLS |
| 56 | 57 |
lib/libc/include/generic-glibc/dlfcn.h+6-1| ... | ... | @@ -167,7 +167,12 @@ enum |
| 167 | 167 | the number of program headers in the array. */ |
| 168 | 168 | RTLD_DI_PHDR = 11, |
| 169 | 169 | |
| 170 | RTLD_DI_MAX = 11 | |
| 170 | /* Treat ARG as `const char **' and at that location, store the address | |
| 171 | of the directory name used to expand $ORIGIN in this shared object's | |
| 172 | dependency file names. */ | |
| 173 | RTLD_DI_ORIGIN_PATH = 12, | |
| 174 | ||
| 175 | RTLD_DI_MAX = 12 | |
| 171 | 176 | }; |
| 172 | 177 | |
| 173 | 178 |
lib/libc/include/generic-glibc/elf.h+6-2| ... | ... | @@ -798,7 +798,8 @@ typedef struct |
| 798 | 798 | #define NT_X86_XSTATE	0x202		/* x86 extended state using xsave */ |
| 799 | 799 | #define NT_X86_SHSTK	0x204		/* x86 SHSTK state */ |
| 800 | 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 | 803 | #define NT_S390_TIMER	0x301		/* s390 timer register */ |
| 803 | 804 | #define NT_S390_TODCMP	0x302		/* s390 TOD clock comparator register */ |
| 804 | 805 | #define NT_S390_TODPREG	0x303		/* s390 TOD programmable register */ |
| ... | ... | @@ -846,6 +847,7 @@ typedef struct |
| 846 | 847 | #define NT_RISCV_VECTOR	0x901		/* RISC-V vector registers */ |
| 847 | 848 | #define NT_RISCV_TAGGED_ADDR_CTRL	0x902	/* RISC-V tagged |
| 848 | 849 | 						 address control */ |
| 850 | #define NT_RISCV_USER_CFI	0x903		/* RISC-V shadow stack state */ | |
| 849 | 851 | #define NT_LOONGARCH_CPUCFG	0xa00	/* LoongArch CPU config registers. */ |
| 850 | 852 | #define NT_LOONGARCH_CSR	0xa01	/* LoongArch control and |
| 851 | 853 | 					 status registers. */ |
| ... | ... | @@ -3470,7 +3472,9 @@ enum |
| 3470 | 3472 | |
| 3471 | 3473 | /* Valid values for the e_flags field. */ |
| 3472 | 3474 | |
| 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. */ | |
| 3474 | 3478 | |
| 3475 | 3479 | /* Additional s390 relocs */ |
| 3476 | 3480 |
lib/libc/include/generic-glibc/features.h+2-2| ... | ... | @@ -162,7 +162,7 @@ |
| 162 | 162 | #undef	__GLIBC_USE_DEPRECATED_SCANF |
| 163 | 163 | #undef	__GLIBC_USE_C23_STRTOL |
| 164 | 164 | |
| 165 | /* Suppress kernel-name space pollution unless user expressedly asks | |
| 165 | /* Suppress kernel-name space pollution unless user explicitly asks | |
| 166 | 166 | for it. */ |
| 167 | 167 | #ifndef _LOOSE_KERNEL_NAMES |
| 168 | 168 | # define __KERNEL_STRICT_NAMES |
| ... | ... | @@ -580,4 +580,4 @@ |
| 580 | 580 | #include <gnu/stubs.h> |
| 581 | 581 | |
| 582 | 582 | |
| 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 | 52 | |
| 53 | 53 | #include <features.h> |
| 54 | 54 | #include <sys/types.h> |
| 55 | ||
| 55 | #include <sys/stat.h> | |
| 56 | #include <dirent.h> | |
| 57 | #include <stdbool.h> | |
| 58 | ||
| 59 | enum { __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. */ | |
| 69 | struct __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 | }; | |
| 77 | typedef struct __I_ring __I_ring; | |
| 56 | 78 | |
| 57 | 79 | typedef struct { |
| 58 | 80 | 	struct _ftsent *fts_cur;	/* current node */ |
| ... | ... | @@ -73,11 +95,106 @@ typedef struct { |
| 73 | 95 | #define	FTS_SEEDOT	0x0020		/* return dot and dot-dot */ |
| 74 | 96 | #define	FTS_XDEV	0x0040		/* don't cross devices */ |
| 75 | 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 */ | |
| 77 | 154 | |
| 78 | 155 | #define	FTS_NAMEONLY	0x0100		/* (private) child names only */ |
| 79 | 156 | #define	FTS_STOP	0x0200		/* (private) unrecoverable error */ |
| 157 | ||
| 80 | 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 | 198 | } FTS; |
| 82 | 199 | |
| 83 | 200 | #ifdef __USE_LARGEFILE64 |
| ... | ... | @@ -92,6 +209,13 @@ typedef struct { |
| 92 | 209 | 	int fts_nitems;			/* elements in the sort array */ |
| 93 | 210 | 	int (*fts_compar) (const void *, const void *); /* compare fn */ |
| 94 | 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 | 219 | } FTS64; |
| 96 | 220 | #endif |
| 97 | 221 |
lib/libc/include/generic-glibc/gnu/lib-names-32.h+1| ... | ... | @@ -24,4 +24,5 @@ |
| 24 | 24 | #define LIBRESOLV_SO "libresolv.so.2" |
| 25 | 25 | #define LIBRT_SO "librt.so.1" |
| 26 | 26 | #define LIBTHREAD_DB_SO "libthread_db.so.1" |
| 27 | #define LIBUNWIND_SO "libunwind.so.1" | |
| 27 | 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 | 24 | #define LIBRESOLV_SO "libresolv.so.2" |
| 25 | 25 | #define LIBRT_SO "librt.so.1" |
| 26 | 26 | #define LIBTHREAD_DB_SO "libthread_db.so.1" |
| 27 | #define LIBUNWIND_SO "libunwind.so.1" | |
| 27 | 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 | 23 | #define LIBRESOLV_SO "libresolv.so.2" |
| 24 | 24 | #define LIBRT_SO "librt.so.1" |
| 25 | 25 | #define LIBTHREAD_DB_SO "libthread_db.so.1" |
| 26 | #define LIBUNWIND_SO "libunwind.so.1" | |
| 26 | 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 | 23 | #define LIBRESOLV_SO "libresolv.so.2" |
| 24 | 24 | #define LIBRT_SO "librt.so.1" |
| 25 | 25 | #define LIBTHREAD_DB_SO "libthread_db.so.1" |
| 26 | #define LIBUNWIND_SO "libunwind.so.1" | |
| 26 | 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 | 23 | #define LIBRESOLV_SO "libresolv.so.2" |
| 24 | 24 | #define LIBRT_SO "librt.so.1" |
| 25 | 25 | #define LIBTHREAD_DB_SO "libthread_db.so.1" |
| 26 | #define LIBUNWIND_SO "libunwind.so.1" | |
| 26 | 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 | 23 | #define LIBRESOLV_SO "libresolv.so.2" |
| 24 | 24 | #define LIBRT_SO "librt.so.1" |
| 25 | 25 | #define LIBTHREAD_DB_SO "libthread_db.so.1" |
| 26 | #define LIBUNWIND_SO "libunwind.so.1" | |
| 26 | 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 | 24 | #define LIBRESOLV_SO "libresolv.so.2" |
| 25 | 25 | #define LIBRT_SO "librt.so.1" |
| 26 | 26 | #define LIBTHREAD_DB_SO "libthread_db.so.1" |
| 27 | #define LIBUNWIND_SO "libunwind.so.1" | |
| 27 | 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 | 91 | #define IPPROTO_MPLS		IPPROTO_MPLS |
| 92 | 92 | IPPROTO_ETHERNET = 143, /* Ethernet-within-IPv6 Encapsulation. */ |
| 93 | 93 | #define IPPROTO_ETHERNET	IPPROTO_ETHERNET |
| 94 | IPPROTO_AGGFRAG = 144, /* AGGFRAG in ESP (RFC 9347). */ | |
| 95 | #define IPPROTO_AGGFRAG		IPPROTO_AGGFRAG | |
| 94 | 96 | IPPROTO_RAW = 255,	 /* Raw IP packets. */ |
| 95 | 97 | #define IPPROTO_RAW		IPPROTO_RAW |
| 96 | 98 | IPPROTO_SMC = 256,	 /* Shared Memory Communications. */ |
lib/libc/include/generic-glibc/netinet/tcp.h+25-2| ... | ... | @@ -80,6 +80,9 @@ |
| 80 | 80 | 				 as a cmsg on read. */ |
| 81 | 81 | #define TCP_CM_INQ		 TCP_INQ |
| 82 | 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). */ | |
| 83 | 86 | |
| 84 | 87 | #define TCP_REPAIR_ON		 1 |
| 85 | 88 | #define TCP_REPAIR_OFF		 0 |
| ... | ... | @@ -226,6 +229,24 @@ enum tcp_ca_state |
| 226 | 229 | TCP_CA_Loss = 4 |
| 227 | 230 | }; |
| 228 | 231 | |
| 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 | ||
| 229 | 250 | struct tcp_info |
| 230 | 251 | { |
| 231 | 252 | uint8_t	tcpi_state; |
| ... | ... | @@ -319,8 +340,10 @@ struct tcp_info |
| 319 | 340 | uint32_t	tcpi_received_e1_bytes; |
| 320 | 341 | uint32_t	tcpi_received_e0_bytes; |
| 321 | 342 | uint32_t	tcpi_received_ce_bytes; |
| 322 | uint16_t	tcpi_accecn_fail_mode; | |
| 323 | uint16_t	tcpi_accecn_opt_seen; | |
| 343 | uint32_t	tcpi_ecn_mode:2, | |
| 344 | 		tcpi_accecn_opt_seen:2, | |
| 345 | 		tcpi_accecn_fail_mode:4, | |
| 346 | 		tcpi_options2:24; | |
| 324 | 347 | }; |
| 325 | 348 | |
| 326 | 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 | 74 | #ifdef __USE_GNU |
| 75 | 75 | /* If this bit is not set, then \ inside a bracket expression is literal. |
| 76 | 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 | |
| 78 | 78 | |
| 79 | 79 | /* If this bit is not set, then + and ? are operators, and \+ and \? are |
| 80 | 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 | 200 | 					 int __fd, int __newfd) |
| 201 | 201 | __THROW __nonnull ((1)); |
| 202 | 202 | |
| 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. */ | |
| 208 | extern 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. */ | |
| 217 | extern 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 | 223 | #ifdef __USE_MISC |
| 204 | 224 | /* Add an action changing the directory to PATH during spawn. This |
| 205 | 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 | 1225 | |
| 1226 | 1226 | __END_DECLS |
| 1227 | 1227 | |
| 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 | 21 | #ifndef _SYS_MOUNT_H |
| 22 | 22 | #define _SYS_MOUNT_H	1 |
| 23 | 23 | |
| 24 | #include <fcntl.h> | |
| 25 | 24 | #include <features.h> |
| 26 | 25 | #include <stdint.h> |
| 27 | 26 | #include <stddef.h> |
| ... | ... | @@ -190,6 +189,11 @@ enum |
| 190 | 189 | |
| 191 | 190 | /* fsmount flags. */ |
| 192 | 191 | #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 */ | |
| 193 | 197 | |
| 194 | 198 | /* mount attributes used on fsmount. */ |
| 195 | 199 | #define MOUNT_ATTR_RDONLY 0x00000001 /* Mount read-only. */ |
| ... | ... | @@ -267,10 +271,20 @@ enum fsconfig_command |
| 267 | 271 | #define FSOPEN_CLOEXEC 0x00000001 |
| 268 | 272 | |
| 269 | 273 | /* open_tree flags. */ |
| 270 | #define OPEN_TREE_CLONE 1 /* Clone the target tree and attach the clone */ | |
| 271 | #define OPEN_TREE_CLOEXEC O_CLOEXEC /* Close the file on execve() */ | |
| 272 | ||
| 274 | #ifndef OPEN_TREE_CLONE | |
| 275 | # define OPEN_TREE_CLONE 1 /* Clone the target tree and attach the clone */ | |
| 276 | #endif | |
| 277 | #define OPEN_TREE_NAMESPACE (1 << 1) /* Clone the target tree into a new mount | |
| 278 | 					namespace */ | |
| 279 | #ifndef O_CLOEXEC | |
| 280 | # include <bits/cloexec.h> | |
| 281 | # define O_CLOEXEC __O_CLOEXEC | |
| 273 | 282 | #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 */ | |
| 274 | 288 | |
| 275 | 289 | __BEGIN_DECLS |
| 276 | 290 |
lib/libc/include/generic-glibc/sys/pidfd.h+26| ... | ... | @@ -64,6 +64,15 @@ |
| 64 | 64 | #define PIDFD_INFO_EXIT (1UL << 3) |
| 65 | 65 | /* Only returned if requested. */ |
| 66 | 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 */ | |
| 67 | 76 | |
| 68 | 77 | |
| 69 | 78 | /* Value for coredump_mask in pidfd_info. Only valid if PIDFD_INFO_COREDUMP |
| ... | ... | @@ -95,11 +104,28 @@ struct pidfd_info |
| 95 | 104 | __uint32_t fsgid; |
| 96 | 105 | __int32_t exit_code; |
| 97 | 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 | 114 | __uint32_t __spare1; |
| 115 | #endif /* (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 44) || __GLIBC__ > 2 */ | |
| 99 | 116 | }; |
| 100 | 117 | |
| 101 | 118 | /* sizeof first published struct */ |
| 102 | 119 | #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 */ | |
| 103 | 129 | |
| 104 | 130 | #define PIDFD_GET_INFO _IOWR(PIDFS_IOCTL_MAGIC, 11, struct pidfd_info) |
| 105 | 131 |
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. */ | |
| 27 | static __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. */ | |
| 59 | static __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. */ | |
| 69 | static __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. */ | |
| 79 | static __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 | ||
| 97 | static __inline__ void | |
| 98 | __ppc_set_ppr_med (void) | |
| 99 | { | |
| 100 | __asm__ volatile ("or 2,2,2"); | |
| 101 | } | |
| 102 | ||
| 103 | static __inline__ void | |
| 104 | __ppc_set_ppr_med_low (void) | |
| 105 | { | |
| 106 | __asm__ volatile ("or 6,6,6"); | |
| 107 | } | |
| 108 | ||
| 109 | static __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 | ||
| 132 | static __inline__ void | |
| 133 | __ppc_set_ppr_very_low (void) | |
| 134 | { | |
| 135 | __asm__ volatile ("or 31,31,31"); | |
| 136 | } | |
| 137 | ||
| 138 | static __inline__ void | |
| 139 | __ppc_set_ppr_med_high (void) | |
| 140 | { | |
| 141 | __asm__ volatile ("or 5,5,5"); | |
| 142 | } | |
| 143 | ||
| 144 | #endif | |
| 145 | ||
| 146 | #endif /* sys/platform/ppc.h */ | |
| \ No newline at end of file |
lib/libc/include/generic-netbsd/fcntl.h+4-1| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | /*	$NetBSD: fcntl.h,v 1.57 2025/07/25 23:24:46 kre Exp $	*/ | |
| 1 | /*	$NetBSD: fcntl.h,v 1.57.2.1 2026/06/16 09:06:50 martin Exp $	*/ | |
| 2 | 2 | |
| 3 | 3 | /*- |
| 4 | 4 | * Copyright (c) 1983, 1990, 1993 |
| ... | ... | @@ -121,6 +121,9 @@ |
| 121 | 121 | #if defined(_NETBSD_SOURCE) |
| 122 | 122 | #define	O_NOSIGPIPE	0x01000000	/* don't deliver sigpipe */ |
| 123 | 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 | 127 | #define	O_EXEC		0x04000000	/* open for executing only */ |
| 125 | 128 | #endif |
| 126 | 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 | /*	$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 $	*/ | |
| 2 | 2 | |
| 3 | 3 | /*- |
| 4 | 4 | * Copyright (c) 1999 The NetBSD Foundation, Inc. |
| ... | ... | @@ -40,6 +40,7 @@ |
| 40 | 40 | #define	_UC_CLRSTACK	_UC_MD_BIT17 |
| 41 | 41 | #define	_UC_VM		_UC_MD_BIT18 |
| 42 | 42 | #define	_UC_TLSBASE	_UC_MD_BIT19 |
| 43 | #define	_UC_XSAVE	_UC_MD_BIT20 | |
| 43 | 44 | |
| 44 | 45 | /* |
| 45 | 46 | * Layout of mcontext_t according to the System V Application Binary Interface, |
| ... | ... | @@ -85,6 +86,27 @@ typedef struct { |
| 85 | 86 | 			char	__fp_xmm[512]; |
| 86 | 87 | 		} __fp_xmm_state;	/* x87 and xmm regs in fxsave format */ |
| 87 | 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 | 110 | 	} __fp_reg_set; |
| 89 | 111 | 	int 	__fp_pad[33];			/* Historic padding */ |
| 90 | 112 | } __fpregset_t; |
lib/libc/include/generic-netbsd/i386/wchar_limits.h+1-1| ... | ... | @@ -44,4 +44,4 @@ |
| 44 | 44 | #define	WINT_MIN	(-0x7fffffff-1)			/* wint_t	 */ |
| 45 | 45 | #define	WINT_MAX	0x7fffffff			/* wint_t	 */ |
| 46 | 46 | |
| 47 | #endif /* !_I386_WCHAR_LIMITS_H_ */ | |
| 47 | #endif /* !_I386_WCHAR_LIMITS_H_ */ | |
| \ No newline at end of file |
lib/libc/include/generic-netbsd/machine/pte.h+32-19| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | /* $NetBSD: pte.h,v 1.14.2.2 2025/10/26 12:28:36 martin Exp $ */ | |
| 1 | /* $NetBSD: pte.h,v 1.14.2.3 2026/06/03 18:17:02 martin Exp $ */ | |
| 2 | 2 | |
| 3 | 3 | /* |
| 4 | 4 | * Copyright (c) 2014, 2019, 2021 The NetBSD Foundation, Inc. |
| ... | ... | @@ -139,6 +139,12 @@ pte_modified_p(pt_entry_t pte) |
| 139 | 139 | 	return (pte & PTE_D) != 0; |
| 140 | 140 | } |
| 141 | 141 | |
| 142 | static inline bool | |
| 143 | pte_referenced_p(pt_entry_t pte) | |
| 144 | { | |
| 145 | 	return (pte & PTE_A) != 0; | |
| 146 | } | |
| 147 | ||
| 142 | 148 | static inline bool |
| 143 | 149 | pte_cached_p(pt_entry_t pte) |
| 144 | 150 | { |
| ... | ... | @@ -177,9 +183,15 @@ pte_nv_entry(bool kernel_p) |
| 177 | 183 | } |
| 178 | 184 | |
| 179 | 185 | static inline pt_entry_t |
| 180 | pte_prot_nowrite(pt_entry_t pte) | |
| 186 | pte_clear_modify(pt_entry_t pte) | |
| 187 | { | |
| 188 | 	return pte & ~PTE_D; | |
| 189 | } | |
| 190 | ||
| 191 | static inline pt_entry_t | |
| 192 | pte_clear_reference(pt_entry_t pte) | |
| 181 | 193 | { |
| 182 | 	return pte & ~PTE_W; | |
| 194 | 	return pte & ~PTE_A; | |
| 183 | 195 | } |
| 184 | 196 | |
| 185 | 197 | static inline pt_entry_t |
| ... | ... | @@ -237,28 +249,29 @@ pte_make_enter(paddr_t pa, struct vm_page_md *mdpg, vm_prot_t prot, |
| 237 | 249 | 	pte |= pte_prot_bits(mdpg, prot, kernel_p); |
| 238 | 250 | 	pte |= pte_enter_flags_to_pbmt(flags); |
| 239 | 251 | |
| 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)); | |
| 241 | 259 | |
| 242 | 		if ((prot & VM_PROT_WRITE) != 0 && | |
| 243 | 		 ((flags & VM_PROT_WRITE) != 0 || VM_PAGEMD_MODIFIED_P(mdpg))) { | |
| 260 | 	if (mdpg != NULL) { | |
| 261 | 		if ((prot & VM_PROT_WRITE) != 0 && VM_PAGEMD_MODIFIED_P(mdpg)) { | |
| 244 | 262 | 			/* |
| 245 | 			* This is a writable mapping, and the page's mod state | |
| 246 | 			* indicates it has already been modified. No need for | |
| 247 | 			* modified emulation. | |
| 248 | 			*/ | |
| 263 | 			 * This is a writable mapping, and the page's mod state | |
| 264 | 			 * indicates it has already been modified. No need for | |
| 265 | 			 * reference or modified emulation. | |
| 266 | 			 */ | |
| 249 | 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 do | |
| 253 | 			* referenced emulation. | |
| 254 | 			* OR | |
| 255 | 			* - The physical page has already been referenced so no need | |
| 256 | 			* to re-do referenced emulation here. | |
| 257 | 			*/ | |
| 270 | 			 * The physical page has already been referenced so no need | |
| 271 | 			 * to re-do referenced emulation here. | |
| 272 | 			 */ | |
| 258 | 273 | 			pte |= PTE_A; |
| 259 | 274 | 		} |
| 260 | 	} else { | |
| 261 | 		pte |= PTE_A | PTE_D; | |
| 262 | 275 | 	} |
| 263 | 276 | |
| 264 | 277 | 	return pte; |
lib/libc/include/generic-netbsd/machine/vmparam.h+21-9| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | /*	$NetBSD: vmparam.h,v 1.14 2023/05/07 12:41:48 skrll Exp $	*/ | |
| 1 | /*	$NetBSD: vmparam.h,v 1.14.8.2 2026/06/03 18:17:02 martin Exp $	*/ | |
| 2 | 2 | |
| 3 | 3 | /*- |
| 4 | 4 | * Copyright (c) 2014, 2020 The NetBSD Foundation, Inc. |
| ... | ... | @@ -50,6 +50,25 @@ |
| 50 | 50 | #define	PAGE_SIZE	(1 << PAGE_SHIFT) |
| 51 | 51 | #define	PAGE_MASK	(PAGE_SIZE - 1) |
| 52 | 52 | |
| 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 | 73 | * USRSTACK is the top (end) of the user stack. |
| 55 | 74 | * |
| ... | ... | @@ -125,12 +144,6 @@ |
| 125 | 144 | #define VM_MAX_KERNEL_ADDRESS	((vaddr_t)0xffffffd000000000) |
| 126 | 145 | |
| 127 | 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 | */ | |
| 134 | 147 | |
| 135 | 148 | /* |
| 136 | 149 | * kernel virtual space layout without direct map (common case) |
| ... | ... | @@ -154,13 +167,12 @@ |
| 154 | 167 | * |
| 155 | 168 | */ |
| 156 | 169 | |
| 157 | ||
| 158 | ||
| 159 | 170 | #define VM_MAXUSER_ADDRESS	((vaddr_t)-0x7fffffff-1)/* 0xffff_ffff_8000_0000 */ |
| 160 | 171 | #define VM_MIN_KERNEL_ADDRESS	((vaddr_t)-0x7fffffff-1)/* 0xffff_ffff_8000_0000 */ |
| 161 | 172 | #define VM_MAX_KERNEL_ADDRESS	((vaddr_t)-0x10000000)	/* 0xffff_ffff_f000_0000 */ |
| 162 | 173 | |
| 163 | 174 | #endif |
| 175 | ||
| 164 | 176 | #define VM_KERNEL_BASE		VM_MIN_KERNEL_ADDRESS |
| 165 | 177 | #define VM_KERNEL_SIZE		0x2000000	/* 32 MiB (8 / 16 megapages) */ |
| 166 | 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 | /*	$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 $	*/ | |
| 2 | 2 | |
| 3 | 3 | /*- |
| 4 | 4 | * Copyright (c) 1997 The NetBSD Foundation, Inc. |
| ... | ... | @@ -269,6 +269,12 @@ pte_modified_p(pt_entry_t pte) |
| 269 | 269 | 	return (pte & MIPS_MMU(PG_D)) != 0; |
| 270 | 270 | } |
| 271 | 271 | |
| 272 | static inline bool | |
| 273 | pte_referenced_p(pt_entry_t pte) | |
| 274 | { | |
| 275 | 	return false; | |
| 276 | } | |
| 277 | ||
| 272 | 278 | static inline bool |
| 273 | 279 | pte_global_p(pt_entry_t pte) |
| 274 | 280 | { |
| ... | ... | @@ -340,11 +346,17 @@ pte_prot_downgrade(pt_entry_t pte, vm_prot_t prot) |
| 340 | 346 | } |
| 341 | 347 | |
| 342 | 348 | static inline pt_entry_t |
| 343 | pte_prot_nowrite(pt_entry_t pte) | |
| 349 | pte_clear_modify(pt_entry_t pte) | |
| 344 | 350 | { |
| 345 | 351 | 	return pte & ~MIPS_MMU(PG_D); |
| 346 | 352 | } |
| 347 | 353 | |
| 354 | static inline pt_entry_t | |
| 355 | pte_clear_reference(pt_entry_t pte) | |
| 356 | { | |
| 357 | 	return pte; | |
| 358 | } | |
| 359 | ||
| 348 | 360 | static inline pt_entry_t |
| 349 | 361 | pte_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 | /*	$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 $	*/ | |
| 2 | 2 | |
| 3 | 3 | /*- |
| 4 | 4 | * Copyright (c) 2001, 2005 The NetBSD Foundation, Inc. |
| ... | ... | @@ -119,7 +119,7 @@ |
| 119 | 119 | #define	TCPTV_MSL	( 30*PR_SLOWHZ)		/* max seg lifetime (hah!) */ |
| 120 | 120 | #define	TCPTV_SRTTBASE	0			/* base roundtrip time; |
| 121 | 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) */ | |
| 123 | 123 | |
| 124 | 124 | #define	TCPTV_PERSMIN	( 5*PR_SLOWHZ)		/* retransmit persistance */ |
| 125 | 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 | /*	$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 | 3 | * Copyright (c) 1989, 1993, 1995 |
| 4 | 4 | *	The Regents of the University of California. All rights reserved. |
| ... | ... | @@ -451,6 +451,8 @@ struct nfssvc_sock { |
| 451 | 451 | 	int		ns_sflags;		/* b: */ |
| 452 | 452 | 	int		ns_cc;			/* b: */ |
| 453 | 453 | 	int		ns_reclen;		/* b: */ |
| 454 | 	int		ns_frag_count;		/* b: */ | |
| 455 | 	int		ns_streamlen;		/* b: */ | |
| 454 | 456 | 	int		ns_numuids; |
| 455 | 457 | 	u_int32_t	ns_sref;		/* g: */ |
| 456 | 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 | /*	$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 $	*/ | |
| 2 | 2 | |
| 3 | 3 | /* |
| 4 | 4 | * Copyright (c) 1989, 1993 |
| ... | ... | @@ -92,13 +92,15 @@ struct nfs_args { |
| 92 | 92 | #define	NFSMNT_READDIRSIZE	0x00020000 /* Set readdir size */ |
| 93 | 93 | #define NFSMNT_XLATECOOKIE	0x00040000 /* 32<->64 dir cookie xlation */ |
| 94 | 94 | #define	NFSMNT_NOAC		0x00080000 /* Turn off attribute cache */ |
| 95 | #define	NFSMNT_NOWCCMSG		0x00100000 /* Turn off attribute wcc messages */ | |
| 95 | 96 | |
| 96 | 97 | #define NFSMNT_BITS	"\177\20" \ |
| 97 | 98 | "b\00soft\0b\01wsize\0b\02rsize\0b\03timeo\0" \ |
| 98 | 99 | "b\04retrans\0b\05maxgrps\0b\06intr\0b\07noconn\0" \ |
| 99 | 100 | "b\10nqnfs\0b\11nfsv3\0b\12kerb\0b\13dumbtimr\0" \ |
| 100 | 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" | |
| 102 | 104 | |
| 103 | 105 | /* |
| 104 | 106 | * NFS internal flags (nm_iflag) */ |
lib/libc/include/generic-netbsd/pthread.h+1-1| ... | ... | @@ -461,4 +461,4 @@ __END_DECLS |
| 461 | 461 | |
| 462 | 462 | #endif /* __LIBPTHREAD_SOURCE__ */ |
| 463 | 463 | |
| 464 | #endif /* _LIB_PTHREAD_H */ | |
| 464 | #endif /* _LIB_PTHREAD_H */ | |
| \ No newline at end of file |
lib/libc/include/generic-netbsd/riscv/pte.h+32-19| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | /* $NetBSD: pte.h,v 1.14.2.2 2025/10/26 12:28:36 martin Exp $ */ | |
| 1 | /* $NetBSD: pte.h,v 1.14.2.3 2026/06/03 18:17:02 martin Exp $ */ | |
| 2 | 2 | |
| 3 | 3 | /* |
| 4 | 4 | * Copyright (c) 2014, 2019, 2021 The NetBSD Foundation, Inc. |
| ... | ... | @@ -139,6 +139,12 @@ pte_modified_p(pt_entry_t pte) |
| 139 | 139 | 	return (pte & PTE_D) != 0; |
| 140 | 140 | } |
| 141 | 141 | |
| 142 | static inline bool | |
| 143 | pte_referenced_p(pt_entry_t pte) | |
| 144 | { | |
| 145 | 	return (pte & PTE_A) != 0; | |
| 146 | } | |
| 147 | ||
| 142 | 148 | static inline bool |
| 143 | 149 | pte_cached_p(pt_entry_t pte) |
| 144 | 150 | { |
| ... | ... | @@ -177,9 +183,15 @@ pte_nv_entry(bool kernel_p) |
| 177 | 183 | } |
| 178 | 184 | |
| 179 | 185 | static inline pt_entry_t |
| 180 | pte_prot_nowrite(pt_entry_t pte) | |
| 186 | pte_clear_modify(pt_entry_t pte) | |
| 187 | { | |
| 188 | 	return pte & ~PTE_D; | |
| 189 | } | |
| 190 | ||
| 191 | static inline pt_entry_t | |
| 192 | pte_clear_reference(pt_entry_t pte) | |
| 181 | 193 | { |
| 182 | 	return pte & ~PTE_W; | |
| 194 | 	return pte & ~PTE_A; | |
| 183 | 195 | } |
| 184 | 196 | |
| 185 | 197 | static inline pt_entry_t |
| ... | ... | @@ -237,28 +249,29 @@ pte_make_enter(paddr_t pa, struct vm_page_md *mdpg, vm_prot_t prot, |
| 237 | 249 | 	pte |= pte_prot_bits(mdpg, prot, kernel_p); |
| 238 | 250 | 	pte |= pte_enter_flags_to_pbmt(flags); |
| 239 | 251 | |
| 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)); | |
| 241 | 259 | |
| 242 | 		if ((prot & VM_PROT_WRITE) != 0 && | |
| 243 | 		 ((flags & VM_PROT_WRITE) != 0 || VM_PAGEMD_MODIFIED_P(mdpg))) { | |
| 260 | 	if (mdpg != NULL) { | |
| 261 | 		if ((prot & VM_PROT_WRITE) != 0 && VM_PAGEMD_MODIFIED_P(mdpg)) { | |
| 244 | 262 | 			/* |
| 245 | 			* This is a writable mapping, and the page's mod state | |
| 246 | 			* indicates it has already been modified. No need for | |
| 247 | 			* modified emulation. | |
| 248 | 			*/ | |
| 263 | 			 * This is a writable mapping, and the page's mod state | |
| 264 | 			 * indicates it has already been modified. No need for | |
| 265 | 			 * reference or modified emulation. | |
| 266 | 			 */ | |
| 249 | 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 do | |
| 253 | 			* referenced emulation. | |
| 254 | 			* OR | |
| 255 | 			* - The physical page has already been referenced so no need | |
| 256 | 			* to re-do referenced emulation here. | |
| 257 | 			*/ | |
| 270 | 			 * The physical page has already been referenced so no need | |
| 271 | 			 * to re-do referenced emulation here. | |
| 272 | 			 */ | |
| 258 | 273 | 			pte |= PTE_A; |
| 259 | 274 | 		} |
| 260 | 	} else { | |
| 261 | 		pte |= PTE_A | PTE_D; | |
| 262 | 275 | 	} |
| 263 | 276 | |
| 264 | 277 | 	return pte; |
lib/libc/include/generic-netbsd/riscv/vmparam.h+21-9| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | /*	$NetBSD: vmparam.h,v 1.14 2023/05/07 12:41:48 skrll Exp $	*/ | |
| 1 | /*	$NetBSD: vmparam.h,v 1.14.8.2 2026/06/03 18:17:02 martin Exp $	*/ | |
| 2 | 2 | |
| 3 | 3 | /*- |
| 4 | 4 | * Copyright (c) 2014, 2020 The NetBSD Foundation, Inc. |
| ... | ... | @@ -50,6 +50,25 @@ |
| 50 | 50 | #define	PAGE_SIZE	(1 << PAGE_SHIFT) |
| 51 | 51 | #define	PAGE_MASK	(PAGE_SIZE - 1) |
| 52 | 52 | |
| 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 | 73 | * USRSTACK is the top (end) of the user stack. |
| 55 | 74 | * |
| ... | ... | @@ -125,12 +144,6 @@ |
| 125 | 144 | #define VM_MAX_KERNEL_ADDRESS	((vaddr_t)0xffffffd000000000) |
| 126 | 145 | |
| 127 | 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 | */ | |
| 134 | 147 | |
| 135 | 148 | /* |
| 136 | 149 | * kernel virtual space layout without direct map (common case) |
| ... | ... | @@ -154,13 +167,12 @@ |
| 154 | 167 | * |
| 155 | 168 | */ |
| 156 | 169 | |
| 157 | ||
| 158 | ||
| 159 | 170 | #define VM_MAXUSER_ADDRESS	((vaddr_t)-0x7fffffff-1)/* 0xffff_ffff_8000_0000 */ |
| 160 | 171 | #define VM_MIN_KERNEL_ADDRESS	((vaddr_t)-0x7fffffff-1)/* 0xffff_ffff_8000_0000 */ |
| 161 | 172 | #define VM_MAX_KERNEL_ADDRESS	((vaddr_t)-0x10000000)	/* 0xffff_ffff_f000_0000 */ |
| 162 | 173 | |
| 163 | 174 | #endif |
| 175 | ||
| 164 | 176 | #define VM_KERNEL_BASE		VM_MIN_KERNEL_ADDRESS |
| 165 | 177 | #define VM_KERNEL_SIZE		0x2000000	/* 32 MiB (8 / 16 megapages) */ |
| 166 | 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 | /*	$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 $	*/ | |
| 2 | 2 | |
| 3 | 3 | /*- |
| 4 | 4 | * Copyright (c) 1983, 1990, 1993 |
| ... | ... | @@ -121,6 +121,9 @@ |
| 121 | 121 | #if defined(_NETBSD_SOURCE) |
| 122 | 122 | #define	O_NOSIGPIPE	0x01000000	/* don't deliver sigpipe */ |
| 123 | 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 | 127 | #define	O_EXEC		0x04000000	/* open for executing only */ |
| 125 | 128 | #endif |
| 126 | 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 | /*	$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 $ */ | |
| 2 | 2 | |
| 3 | 3 | /* |
| 4 | 4 | * Copyright (c) 2014 by Lourival Vieira Neto <lneto@NetBSD.org>. |
| ... | ... | @@ -33,7 +33,9 @@ |
| 33 | 33 | #define _SYS_LUA_H_ |
| 34 | 34 | |
| 35 | 35 | #include <sys/param.h> |
| 36 | ||
| 36 | 37 | #include <sys/ioccom.h> |
| 38 | #include <sys/stdbool.h> | |
| 37 | 39 | |
| 38 | 40 | #include <lua.h>		/* for lua_State */ |
| 39 | 41 |
lib/libc/include/generic-netbsd/sys/param.h+2-2| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | /*	$NetBSD: param.h,v 1.738.2.5 2026/05/12 04:23:51 martin Exp $	*/ | |
| 1 | /*	$NetBSD: param.h,v 1.738.2.9 2026/07/30 15:23:12 martin Exp $	*/ | |
| 2 | 2 | |
| 3 | 3 | /*- |
| 4 | 4 | * Copyright (c) 1982, 1986, 1989, 1993 |
| ... | ... | @@ -566,4 +566,4 @@ extern size_t coherency_unit; |
| 566 | 566 | #endif |
| 567 | 567 | #endif /* !__ASSEMBLER__ */ |
| 568 | 568 | |
| 569 | #endif /* !_SYS_PARAM_H_ */ | |
| 569 | #endif /* !_SYS_PARAM_H_ */ | |
| \ No newline at end of file |
lib/libc/include/generic-netbsd/x86/cpu_extended_state.h+3-1| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | /*	$NetBSD: cpu_extended_state.h,v 1.19 2025/04/24 01:50:39 riastradh Exp $	*/ | |
| 1 | /*	$NetBSD: cpu_extended_state.h,v 1.19.2.1 2026/07/19 15:57:27 martin Exp $	*/ | |
| 2 | 2 | |
| 3 | 3 | #ifndef _X86_CPU_EXTENDED_STATE_H_ |
| 4 | 4 | #define _X86_CPU_EXTENDED_STATE_H_ |
| ... | ... | @@ -142,6 +142,8 @@ struct xsave_header { |
| 142 | 142 | }; |
| 143 | 143 | __CTASSERT(sizeof(struct xsave_header) == 512 + 64); |
| 144 | 144 | |
| 145 | #define	XSAVE_ALIGN	64 | |
| 146 | ||
| 145 | 147 | /* |
| 146 | 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 | /*	$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 $	*/ | |
| 2 | 2 | |
| 3 | 3 | #ifndef	_X86_FPU_H_ |
| 4 | 4 | #define	_X86_FPU_H_ |
| ... | ... | @@ -46,6 +46,12 @@ int process_read_xstate(struct lwp *, struct xstate *); |
| 46 | 46 | int process_verify_xstate(const struct xstate *); |
| 47 | 47 | int process_write_xstate(struct lwp *, const struct xstate *); |
| 48 | 48 | |
| 49 | bool process_xsave_needed_p(struct lwp *); | |
| 50 | void process_read_xsave(struct lwp *, const struct xsave_header **, size_t *); | |
| 51 | int process_verify_xsavelen(struct lwp *, size_t); | |
| 52 | int process_verify_xsave(struct lwp *, const struct xsave_header *, size_t); | |
| 53 | void process_write_xsave(struct lwp *, const struct xsave_header *, size_t); | |
| 54 | ||
| 49 | 55 | #endif |
| 50 | 56 | |
| 51 | 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 | /*	$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 $	*/ | |
| 2 | 2 | |
| 3 | 3 | /* |
| 4 | 4 | * Copyright (c) 2014-2020 The NetBSD Foundation, Inc. |
| ... | ... | @@ -183,16 +183,82 @@ |
| 183 | 183 | 	"\0" |
| 184 | 184 | |
| 185 | 185 | /* |
| 186 | * Known FPU bits, only these get enabled. The save area is sized for all the | |
| 187 | * fields below. | |
| 186 | * XCR0_FPU: Known FPU bits, only these get enabled. The save area is | |
| 187 | * sized for all the fields below. | |
| 188 | * | |
| 189 | * Any bits added to this will expand the extended CPU state that we | |
| 190 | * may have to save and restore with XSAVE for userland processes, | |
| 191 | * either in the kernel when preempting threads, or on the user's stack | |
| 192 | * when delivering a signal. | |
| 193 | * | |
| 194 | * The kernel can dyanmically allocate larger sizes (on amd64, anyway, | |
| 195 | * though not currently on i386 or Xen PV). But if the XSAVE area is | |
| 196 | * expanded so much that it and mcontext_t exceed MINSIGSTKSZ | |
| 197 | * (currently 8192), a userland ABI change and compatibility layer is | |
| 198 | * required to accommodate that, because existing programs may use | |
| 199 | * sigaltstack(2) with stacks sized for the old MINSIGSTKSZ. | |
| 200 | * | |
| 201 | * The current stack requirement is 3160 bytes of space plus up to | |
| 202 | * 63+15+8=86 bytes of padding for alignment (could be reduced by | |
| 203 | * around 512 bytes by having mcontext_t overlap with the XSAVE area a | |
| 204 | * little in machdep.c cpu_getmcontext_xsave, but we don't do that | |
| 205 | * right now): | |
| 206 | * | |
| 207 | * - mcontext_t (728 bytes: general registers and 512-byte FXSAVE area) | |
| 208 | * - XSAVE header (576 bytes: 512 bytes of FXSAVE, 64 bytes of metadata) | |
| 209 | * - AVX state: ymm0..ymm15 high 128-bit halves (256 bytes) | |
| 210 | * - AVX-512 state: | |
| 211 | * . k0..k7 opmask registers (64 bytes) | |
| 212 | * . zmm0..zmm15 high 256-bit halves (512 bytes) | |
| 213 | * . zmm16..zmm31 registers (1024 bytes) | |
| 214 | * | |
| 215 | * Likely future extensions that would expand the state beyond | |
| 216 | * MINSIGSTKSZ: | |
| 217 | * | |
| 218 | * - AMX (Advanced Matrix Extensions) and ACE (AI Compute Extensions) | |
| 219 | * state: | |
| 220 | * . [AMX/ACE] TILECFG (64 bytes) | |
| 221 | * . [AMX/ACE] TILEDATA (8192 bytes) | |
| 222 | * . [ACE] SCALEDATA (128 bytes) | |
| 223 | * | |
| 224 | * As a precaution against ABI breakage, x86/identcpu.c will panic at | |
| 225 | * boot if the XSAVE state size enabled in XCR0 exceeds MINSIGSTKSZ. | |
| 226 | * | |
| 227 | * References: | |
| 228 | * | |
| 229 | * - Intel 64 and IA-32 Architectures Software Developer's Manual, | |
| 230 | * Volume 1: Basic Architecture, Intel, Order Number: 253665-092US, | |
| 231 | * June 2026, Sec. 13.1 `XSAVE-Supported Features and State-Component | |
| 232 | * Bitmaps', pp. 13-1 -- 13-2. | |
| 233 | * https://web.archive.org/web/20260709150417/https://cdrdv2-public.intel.com/922477/253665-092-sdm-vol-1.pdf | |
| 234 | * | |
| 235 | * - AI Compute Extensions (ACE) Specification, x86 Ecosystem Advisory | |
| 236 | * Group, Version 1.15, 2026-05-15, Sec 15.4.1 `XSAVE State | |
| 237 | * Components', p. 86. | |
| 238 | * https://web.archive.org/web/20260619062626/https://x86ecosystem.org/wp-content/uploads/2026/06/ACE_v1_Specification_public_1_15.pdf | |
| 188 | 239 | */ |
| 189 | 240 | #if defined __i386__ || defined XENPV /* XXX XENPV PR kern/59371 */ |
| 190 | 241 | #define XCR0_FPU	(XCR0_X87 | XCR0_SSE | XCR0_YMM_Hi128 | \ |
| 191 | 242 | 			 XCR0_Opmask | XCR0_ZMM_Hi256 | XCR0_Hi16_ZMM) |
| 192 | 243 | #else |
| 193 | 244 | #define XCR0_FPU	(XCR0_X87 | XCR0_SSE | XCR0_YMM_Hi128 | \ |
| 194 | 			 XCR0_Opmask | XCR0_ZMM_Hi256 | XCR0_Hi16_ZMM | \ | |
| 195 | 			 XCR0_TILECFG | XCR0_TILEDATA) | |
| 245 | 			 XCR0_Opmask | XCR0_ZMM_Hi256 | XCR0_Hi16_ZMM) | |
| 246 | #endif | |
| 247 | ||
| 248 | /* | |
| 249 | * Maximum size of XSAVE state that we can handle without ABI changes | |
| 250 | * to userland. Must match usage in cpu_getmcontext. Extra 8 is neeed | |
| 251 | * on amd64 to have space for return address in 16-byte-aligned stack | |
| 252 | * frame. | |
| 253 | */ | |
| 254 | #ifdef __x86_64__ | |
| 255 | #define	XSAVE_MAX_BYTES							 \ | |
| 256 | 	(MINSIGSTKSZ - (8 + STACK_ALIGNBYTES +				 \ | |
| 257 | 	 sizeof(struct sigframe_siginfo) + (XSAVE_ALIGN - 1))) | |
| 258 | #else | |
| 259 | #define	XSAVE_MAX_BYTES							 \ | |
| 260 | 	(MINSIGSTKSZ - (STACK_ALIGNBYTES +				 \ | |
| 261 | 	 sizeof(struct sigframe_siginfo) + (XSAVE_ALIGN - 1))) | |
| 196 | 262 | #endif |
| 197 | 263 | |
| 198 | 264 | /* |
lib/libc/include/loongarch-linux-gnu/bits/hwcap.h+3-1| ... | ... | @@ -36,4 +36,6 @@ |
| 36 | 36 | #define HWCAP_LOONGARCH_LBT_ARM (1 << 11) |
| 37 | 37 | #define HWCAP_LOONGARCH_LBT_MIPS (1 << 12) |
| 38 | 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 | ||
| 44 | struct 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 | |
| 85 | struct 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 | 15 | License along with the GNU C Library; if not, see |
| 16 | 16 | <https://www.gnu.org/licenses/>. */ |
| 17 | 17 | |
| 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 | 94 | #define _FPU_GETCW(cw) __asm__ volatile ("movfcsr2gr %0,$fcsr0" : "=r"(cw)) |
| 95 | 95 | #define _FPU_SETCW(cw) __asm__ volatile ("movgr2fcsr $fcsr0,%0" : : "r"(cw)) |
| 96 | 96 | |
| 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 | 106 | /* Default control word set at startup. */ |
| 98 | 107 | extern fpu_control_t __fpu_control; |
| 99 | 108 |
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 | 24 | #define LIBRESOLV_SO "libresolv.so.2" |
| 25 | 25 | #define LIBRT_SO "librt.so.1" |
| 26 | 26 | #define LIBTHREAD_DB_SO "libthread_db.so.1" |
| 27 | #define LIBUNWIND_SO "libunwind.so.1" | |
| 27 | 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 | 24 | #define LIBRESOLV_SO "libresolv.so.2" |
| 25 | 25 | #define LIBRT_SO "librt.so.1" |
| 26 | 26 | #define LIBTHREAD_DB_SO "libthread_db.so.1" |
| 27 | #define LIBUNWIND_SO "libunwind.so.1" | |
| 27 | 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 | |
| 7 | 7 | #include <bits/wordsize.h> |
| 8 | 8 | |
| 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 | 15 | #if __WORDSIZE == 64 && defined __loongarch_soft_float |
| 10 | 16 | # include <gnu/lib-names-lp64s.h> |
| 11 | 17 | #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 | 4 | |
| 5 | 5 | #include <bits/wordsize.h> |
| 6 | 6 | |
| 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 | 13 | #if __WORDSIZE == 64 && defined __loongarch_soft_float |
| 8 | 14 | # include <gnu/stubs-lp64s.h> |
| 9 | 15 | #endif |
lib/libc/include/loongarch-linux-gnu/sys/asm.h+32-6| ... | ... | @@ -23,10 +23,8 @@ |
| 23 | 23 | #include <sysdeps/generic/sysdep.h> |
| 24 | 24 | |
| 25 | 25 | /* Macros to handle different pointer/register sizes for 32/64-bit code. */ |
| 26 | #if __loongarch_grlen == 64 | |
| 26 | 27 | #define SZREG 8 |
| 27 | #define SZFREG 8 | |
| 28 | #define SZVREG 16 | |
| 29 | #define SZXREG 32 | |
| 30 | 28 | #define REG_L ld.d |
| 31 | 29 | #define REG_S st.d |
| 32 | 30 | #define SRLI srli.d |
| ... | ... | @@ -34,10 +32,38 @@ |
| 34 | 32 | #define ADDI addi.d |
| 35 | 33 | #define ADD add.d |
| 36 | 34 | #define SUB sub.d |
| 37 | #define BSTRINS bstrins.d | |
| 38 | 35 | #define LI li.d |
| 39 | #define FREG_L fld.d | |
| 40 | #define FREG_S fst.d | |
| 36 | #define BSTRINS bstrins.d | |
| 37 | ||
| 38 | #elif __loongarch_grlen == 32 | |
| 39 | ||
| 40 | #define SZREG 4 | |
| 41 | #define REG_L ld.w | |
| 42 | #define REG_S st.w | |
| 43 | #define SRLI srli.w | |
| 44 | #define SLLI slli.w | |
| 45 | #define ADDI addi.w | |
| 46 | #define ADD add.w | |
| 47 | #define SUB sub.w | |
| 48 | #define LI li.w | |
| 49 | #define BSTRINS bstrins.w | |
| 50 | ||
| 51 | #else | |
| 52 | #error __loongarch_grlen must equal 32 or 64 | |
| 53 | #endif | |
| 54 | ||
| 55 | #if __loongarch_frlen == 64 | |
| 56 | #define SZFREG 8 | |
| 57 | #define FREG_L fld.d | |
| 58 | #define FREG_S fst.d | |
| 59 | #elif __loongarch_frlen == 32 | |
| 60 | #define SZFREG 4 | |
| 61 | #define FREG_L fld.s | |
| 62 | #define FREG_S fst.s | |
| 63 | #endif | |
| 64 | ||
| 65 | #define SZVREG 16 | |
| 66 | #define SZXREG 32 | |
| 41 | 67 | |
| 42 | 68 | /* Declare leaf routine. |
| 43 | 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 | 24 | #define LIBRESOLV_SO "libresolv.so.2" |
| 25 | 25 | #define LIBRT_SO "librt.so.1" |
| 26 | 26 | #define LIBTHREAD_DB_SO "libthread_db.so.1" |
| 27 | #define LIBUNWIND_SO "libunwind.so.1" | |
| 27 | 28 | #define LIBUTIL_SO "libutil.so.1" |
| 28 | 29 | |
| 29 | 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. */ | |
| 30 | struct 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 | |
| 89 | struct 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 | ||
| 132 | struct 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 | |
| 190 | struct 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. */ | |
| 42 | static __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. */ | |
| 49 | static __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 | 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 | 3 | This file is part of the GNU C Library. |
| 4 | 4 | |
| 5 | 5 | 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. */ | |
| 29 | extern 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 | 59 | 0, 0, 0, __kind, 0, { { 0, 0 } } |
| 60 | 60 | #endif |
| 61 | 61 | |
| 62 | #endif | |
| 62 | #endif | |
| \ No newline at end of file |
lib/libc/include/powerpc-linux-gnu/gnu/lib-names-32.h deleted-26| ... | ... | @@ -1,26 +0,0 @@ |
| 1 | /* This file is automatically generated. */ | |
| 2 | #ifndef __GNU_LIB_NAMES_H | |
| 3 | # error "Never use <gnu/lib-names-32.h> directly; include <gnu/lib-names.h> instead." | |
| 4 | #endif | |
| 5 | ||
| 6 | #define LD_SO "ld.so.1" | |
| 7 | #define LIBANL_SO "libanl.so.1" | |
| 8 | #define LIBBROKENLOCALE_SO "libBrokenLocale.so.1" | |
| 9 | #define LIBC_MALLOC_DEBUG_SO "libc_malloc_debug.so.0" | |
| 10 | #define LIBC_SO "libc.so.6" | |
| 11 | #define LIBDL_SO "libdl.so.2" | |
| 12 | #define LIBGCC_S_SO "libgcc_s.so.1" | |
| 13 | #define LIBMVEC_SO "libmvec.so.1" | |
| 14 | #define LIBM_SO "libm.so.6" | |
| 15 | #define LIBNSL_SO "libnsl.so.1" | |
| 16 | #define LIBNSS_COMPAT_SO "libnss_compat.so.2" | |
| 17 | #define LIBNSS_DB_SO "libnss_db.so.2" | |
| 18 | #define LIBNSS_DNS_SO "libnss_dns.so.2" | |
| 19 | #define LIBNSS_FILES_SO "libnss_files.so.2" | |
| 20 | #define LIBNSS_HESIOD_SO "libnss_hesiod.so.2" | |
| 21 | #define LIBNSS_LDAP_SO "libnss_ldap.so.2" | |
| 22 | #define LIBPTHREAD_SO "libpthread.so.0" | |
| 23 | #define LIBRESOLV_SO "libresolv.so.2" | |
| 24 | #define LIBRT_SO "librt.so.1" | |
| 25 | #define LIBTHREAD_DB_SO "libthread_db.so.1" | |
| 26 | #define LIBUTIL_SO "libutil.so.1" | |
| \ No newline at end of file |
lib/libc/include/powerpc-linux-gnu/gnu/lib-names-64-v1.h deleted-27| ... | ... | @@ -1,27 +0,0 @@ |
| 1 | /* This file is automatically generated. */ | |
| 2 | #ifndef __GNU_LIB_NAMES_H | |
| 3 | # error "Never use <gnu/lib-names-64-v1.h> directly; include <gnu/lib-names.h> instead." | |
| 4 | #endif | |
| 5 | ||
| 6 | #define LD64_SO "ld64.so.1" | |
| 7 | #define LD_SO "ld64.so.1" | |
| 8 | #define LIBANL_SO "libanl.so.1" | |
| 9 | #define LIBBROKENLOCALE_SO "libBrokenLocale.so.1" | |
| 10 | #define LIBC_MALLOC_DEBUG_SO "libc_malloc_debug.so.0" | |
| 11 | #define LIBC_SO "libc.so.6" | |
| 12 | #define LIBDL_SO "libdl.so.2" | |
| 13 | #define LIBGCC_S_SO "libgcc_s.so.1" | |
| 14 | #define LIBMVEC_SO "libmvec.so.1" | |
| 15 | #define LIBM_SO "libm.so.6" | |
| 16 | #define LIBNSL_SO "libnsl.so.1" | |
| 17 | #define LIBNSS_COMPAT_SO "libnss_compat.so.2" | |
| 18 | #define LIBNSS_DB_SO "libnss_db.so.2" | |
| 19 | #define LIBNSS_DNS_SO "libnss_dns.so.2" | |
| 20 | #define LIBNSS_FILES_SO "libnss_files.so.2" | |
| 21 | #define LIBNSS_HESIOD_SO "libnss_hesiod.so.2" | |
| 22 | #define LIBNSS_LDAP_SO "libnss_ldap.so.2" | |
| 23 | #define LIBPTHREAD_SO "libpthread.so.0" | |
| 24 | #define LIBRESOLV_SO "libresolv.so.2" | |
| 25 | #define LIBRT_SO "librt.so.1" | |
| 26 | #define LIBTHREAD_DB_SO "libthread_db.so.1" | |
| 27 | #define LIBUTIL_SO "libutil.so.1" | |
| \ No newline at end of file |
lib/libc/include/powerpc-linux-gnu/gnu/lib-names-64-v2.h+1| ... | ... | @@ -24,4 +24,5 @@ |
| 24 | 24 | #define LIBRESOLV_SO "libresolv.so.2" |
| 25 | 25 | #define LIBRT_SO "librt.so.1" |
| 26 | 26 | #define LIBTHREAD_DB_SO "libthread_db.so.1" |
| 27 | #define LIBUNWIND_SO "libunwind.so.1" | |
| 27 | 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. */ | |
| 27 | static __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. */ | |
| 59 | static __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. */ | |
| 69 | static __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. */ | |
| 79 | static __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 | ||
| 97 | static __inline__ void | |
| 98 | __ppc_set_ppr_med (void) | |
| 99 | { | |
| 100 | __asm__ volatile ("or 2,2,2"); | |
| 101 | } | |
| 102 | ||
| 103 | static __inline__ void | |
| 104 | __ppc_set_ppr_med_low (void) | |
| 105 | { | |
| 106 | __asm__ volatile ("or 6,6,6"); | |
| 107 | } | |
| 108 | ||
| 109 | static __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 | ||
| 132 | static __inline__ void | |
| 133 | __ppc_set_ppr_very_low (void) | |
| 134 | { | |
| 135 | __asm__ volatile ("or 31,31,31"); | |
| 136 | } | |
| 137 | ||
| 138 | static __inline__ void | |
| 139 | __ppc_set_ppr_med_high (void) | |
| 140 | { | |
| 141 | __asm__ volatile ("or 5,5,5"); | |
| 142 | } | |
| 143 | ||
| 144 | #endif | |
| 145 | ||
| 146 | #endif /* sys/platform/ppc.h */ | |
| \ No newline at end of file |
lib/libc/include/powerpc-netbsd-eabi/powerpc/oea/pmap.h+6-4| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | /*	$NetBSD: pmap.h,v 1.39 2023/12/15 09:42:33 rin Exp $	*/ | |
| 1 | /*	$NetBSD: pmap.h,v 1.39.4.1 2026/07/03 17:51:59 martin Exp $	*/ | |
| 2 | 2 | |
| 3 | 3 | /*- |
| 4 | 4 | * Copyright (C) 1995, 1996 Wolfgang Solfrank. |
| ... | ... | @@ -122,11 +122,13 @@ __BEGIN_DECLS |
| 122 | 122 | #include <sys/systm.h> |
| 123 | 123 | |
| 124 | 124 | /* |
| 125 | * For OEA and OEA64_BRIDGE, we guarantee that pa below USER_ADDR | |
| 126 | * (== 3GB < VM_MIN_KERNEL_ADDRESS) is direct-mapped. | |
| 125 | * Physical memory below PMAP_DIRECT_MAPPED_LEN is direct-mapped | |
| 126 | * (pa == va). Direct region covers the segments below BOTH | |
| 127 | * the user copyin window (USER_SR) and the kernel HTAB window | |
| 128 | * (KERNEL_SR), so it can never overlap. | |
| 127 | 129 | */ |
| 128 | 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 | 132 | #define	PMAP_DIRECT_MAPPED_LEN \ |
| 131 | 133 | ((vaddr_t)SEGMENT_LENGTH * (PMAP_DIRECT_MAPPED_SR + 1)) |
| 132 | 134 | #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 | ||
| 44 | struct 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 | |
| 85 | struct 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 | 24 | #define LIBRESOLV_SO "libresolv.so.2" |
| 25 | 25 | #define LIBRT_SO "librt.so.1" |
| 26 | 26 | #define LIBTHREAD_DB_SO "libthread_db.so.1" |
| 27 | #define LIBUNWIND_SO "libunwind.so.1" | |
| 27 | 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 | 24 | #define LIBRESOLV_SO "libresolv.so.2" |
| 25 | 25 | #define LIBRT_SO "librt.so.1" |
| 26 | 26 | #define LIBTHREAD_DB_SO "libthread_db.so.1" |
| 27 | #define LIBUNWIND_SO "libunwind.so.1" | |
| 27 | 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 | 27 | |
| 28 | 28 | #define __ELF_NATIVE_CLASS __WORDSIZE |
| 29 | 29 | |
| 30 | #if __WORDSIZE == 64 | |
| 31 | 30 | /* 64 bit Linux for S/390 is exceptional as it has .hash section with |
| 32 | 31 | 64 bit entries. */ |
| 33 | typedef uint64_t Elf_Symndx; | |
| 34 | #else | |
| 35 | /* 32 bit Linux for S/390 has normal .hash section entries with 32 bits. */ | |
| 36 | typedef uint32_t Elf_Symndx; | |
| 37 | #endif | |
| \ No newline at end of file | ||
| 32 | typedef 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 | 22 | |
| 23 | 23 | #include <bits/wordsize.h> |
| 24 | 24 | |
| 25 | #if __WORDSIZE == 64 | |
| 26 | 25 | /* Not necessary, files are always with 64bit off_t. */ |
| 27 | # define __O_LARGEFILE	0 | |
| 28 | #endif | |
| 26 | #define __O_LARGEFILE	0 | |
| 29 | 27 | |
| 30 | #if __WORDSIZE == 64 | |
| 31 | 28 | /* Not necessary, we always have 64-bit offsets. */ |
| 32 | # define F_GETLK64	5	/* Get record locking info. */ | |
| 33 | # define F_SETLK64	6	/* Set record locking info (non-blocking). */ | |
| 34 | # define F_SETLKW64	7	/* Set record locking info (blocking).	*/ | |
| 35 | #endif | |
| 29 | #define F_GETLK64	5	/* Get record locking info. */ | |
| 30 | #define F_SETLK64	6	/* Set record locking info (non-blocking). */ | |
| 31 | #define F_SETLKW64	7	/* Set record locking info (blocking).	*/ | |
| 36 | 32 | |
| 37 | 33 | struct flock |
| 38 | 34 | { |
| 39 | 35 | short int l_type;	/* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK.	*/ |
| 40 | 36 | short int l_whence;	/* Where `l_start' is relative to (like `lseek'). */ |
| 41 | #if __WORDSIZE == 64 || !defined __USE_FILE_OFFSET64 | |
| 42 | 37 | __off_t l_start;	/* Offset where the lock begins. */ |
| 43 | 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 | 39 | __pid_t l_pid;	/* Process holding the lock. */ |
| 49 | 40 | }; |
| 50 | 41 | |
| ... | ... | @@ -59,13 +50,8 @@ struct flock64 |
| 59 | 50 | }; |
| 60 | 51 | #endif |
| 61 | 52 | |
| 62 | #if __WORDSIZE == 64 | |
| 63 | # define __POSIX_FADV_DONTNEED	6 /* Don't need these pages. */ | |
| 64 | # define __POSIX_FADV_NOREUSE	7 /* Data will be accessed once. */ | |
| 65 | #else | |
| 66 | # define __POSIX_FADV_DONTNEED	4 /* Don't need these pages. */ | |
| 67 | # define __POSIX_FADV_NOREUSE	5 /* Data will be accessed once. */ | |
| 68 | #endif | |
| 53 | #define __POSIX_FADV_DONTNEED	6 /* Don't need these pages. */ | |
| 54 | #define __POSIX_FADV_NOREUSE	7 /* Data will be accessed once. */ | |
| 69 | 55 | |
| 70 | 56 | /* Include generic Linux declarations. */ |
| 71 | 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 | 77 | { |
| 78 | 78 | fexcept_t __fpc; |
| 79 | 79 | void *__glibc_reserved; |
| 80 | /* The field __unused (formerly __ieee_instruction_pointer) is a relict from | |
| 81 | commit "Remove PTRACE_PEEKUSER" (87b9b50f0d4b92248905e95a06a13c513dc45e59) | |
| 82 | and isn't used anymore. */ | |
| 80 | /* The field __glibc_reserved (formerly __ieee_instruction_pointer) is a | |
| 81 | relict from commit "Remove PTRACE_PEEKUSER" | |
| 82 | (87b9b50f0d4b92248905e95a06a13c513dc45e59) and isn't used anymore. */ | |
| 83 | 83 | } fenv_t; |
| 84 | 84 | |
| 85 | 85 | /* If the default argument is used we use this value. */ |
| ... | ... | @@ -96,4 +96,4 @@ typedef unsigned int femode_t; |
| 96 | 96 | |
| 97 | 97 | /* Default floating-point control modes. */ |
| 98 | 98 | # define FE_DFL_MODE	((const femode_t *) -1L) |
| 99 | #endif | |
| 99 | #endif | |
| \ No newline at end of file |
lib/libc/include/s390x-linux-gnu/bits/link.h+1-61| ... | ... | @@ -23,64 +23,6 @@ |
| 23 | 23 | typedef char La_s390_vr[16]; |
| 24 | 24 | #endif |
| 25 | 25 | |
| 26 | #if __ELF_NATIVE_CLASS == 32 | |
| 27 | ||
| 28 | /* Registers for entry into PLT on s390-32. */ | |
| 29 | typedef 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. */ | |
| 51 | typedef 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 | ||
| 64 | extern 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); | |
| 72 | extern 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 | 26 | /* Registers for entry into PLT on s390-64. */ |
| 85 | 27 | typedef struct La_s390_64_regs |
| 86 | 28 | { |
| ... | ... | @@ -134,6 +76,4 @@ extern unsigned int la_s390_64_gnu_pltexit (Elf64_Sym *__sym, |
| 134 | 76 | 					 La_s390_64_retval *__outregs, |
| 135 | 77 | 					 const char *__symname); |
| 136 | 78 | |
| 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 | |
| 28 | typedef unsigned int elf_greg_t32; | |
| 29 | typedef elf_greg_t32 | |
| 30 | elf_gregset_t32[ELF_NGREG32] __attribute__ ((__aligned__ (8))); | |
| 31 | typedef elf_fpregset_t elf_fpregset_t32; | |
| 32 | ||
| 33 | struct 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 | ||
| 54 | struct 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 | ||
| 69 | typedef elf_gregset_t32 prgregset32_t; | |
| 70 | typedef elf_fpregset_t32 prfpregset32_t; | |
| 71 | ||
| 72 | typedef struct elf_prstatus32 prstatus32_t; | |
| 73 | typedef 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 | |
| 25 | typedef unsigned int __pr_uid_t; | |
| 26 | typedef unsigned int __pr_gid_t; | |
| 27 | #else | |
| 28 | typedef unsigned short int __pr_uid_t; | |
| 29 | typedef 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 | 33 | /* We save registers 6-15. */ |
| 34 | 34 | long int __gregs[10]; |
| 35 | 35 | |
| 36 | # if __WORDSIZE == 64 | |
| 37 | /* We save fpu registers f8 - f15. */ | |
| 38 | 36 | long __fpregs[8]; |
| 39 | # else | |
| 40 | /* We save fpu registers 4 and 6. */ | |
| 41 | long __fpregs[4]; | |
| 42 | # endif | |
| 43 | 37 | } __jmp_buf[1]; |
| 44 | 38 | |
| 45 | 39 | #endif |
lib/libc/include/s390x-linux-gnu/bits/sigaction.h+1-34| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | /* Definitions for 31 & 64 bit S/390 sigaction. | |
| 1 | /* Definitions for 64 bit S/390 sigaction. | |
| 2 | 2 | Copyright (C) 2001-2026 Free Software Foundation, Inc. |
| 3 | 3 | This file is part of the GNU C Library. |
| 4 | 4 | |
| ... | ... | @@ -23,9 +23,6 @@ |
| 23 | 23 | # error "Never include <bits/sigaction.h> directly; use <signal.h> instead." |
| 24 | 24 | #endif |
| 25 | 25 | |
| 26 | #include <bits/wordsize.h> | |
| 27 | ||
| 28 | #if __WORDSIZE == 64 | |
| 29 | 26 | /* Structure describing the action to be taken when a signal arrives. */ |
| 30 | 27 | struct sigaction |
| 31 | 28 | { |
| ... | ... | @@ -55,36 +52,6 @@ struct sigaction |
| 55 | 52 | /* Additional set of signals to be blocked.	 */ |
| 56 | 53 | __sigset_t sa_mask; |
| 57 | 54 | }; |
| 58 | #else | |
| 59 | /* Structure describing the action to be taken when a signal arrives. */ | |
| 60 | struct 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 | |
| 88 | 55 | |
| 89 | 56 | /* Bits in `sa_flags'. */ |
| 90 | 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 | 24 | int __lock; |
| 25 | 25 | unsigned int __count; |
| 26 | 26 | int __owner; |
| 27 | #if __WORDSIZE == 64 | |
| 28 | 27 | unsigned int __nusers; |
| 29 | #endif | |
| 30 | 28 | /* KIND must stay at this position in the structure to maintain |
| 31 | 29 | binary compatibility with static initializers. */ |
| 32 | 30 | int __kind; |
| 33 | #if __WORDSIZE == 64 | |
| 34 | 31 | short __spins; |
| 35 | 32 | short __glibc_reserved; |
| 36 | 33 | __pthread_list_t __list; |
| 37 | 34 | # 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 | }; |
| 53 | 36 | |
| 54 | #if __WORDSIZE == 64 | |
| 55 | # define __PTHREAD_MUTEX_INITIALIZER(__kind) \ | |
| 37 | #define __PTHREAD_MUTEX_INITIALIZER(__kind) \ | |
| 56 | 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 | |
| 61 | 39 | |
| 62 | #endif | |
| 40 | #endif | |
| \ No newline at end of file |
lib/libc/include/s390x-linux-gnu/bits/struct_rwlock.h+1-16| ... | ... | @@ -28,7 +28,6 @@ struct __pthread_rwlock_arch_t |
| 28 | 28 | unsigned int __writers_futex; |
| 29 | 29 | unsigned int __pad3; |
| 30 | 30 | unsigned int __pad4; |
| 31 | #if __WORDSIZE == 64 | |
| 32 | 31 | int __cur_writer; |
| 33 | 32 | int __shared; |
| 34 | 33 | unsigned long int __pad1; |
| ... | ... | @@ -36,23 +35,9 @@ struct __pthread_rwlock_arch_t |
| 36 | 35 | /* FLAGS must stay at this position in the structure to maintain |
| 37 | 36 | binary compatibility. */ |
| 38 | 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 | }; |
| 49 | 39 | |
| 50 | #if __WORDSIZE == 64 | |
| 51 | # define __PTHREAD_RWLOCK_INITIALIZER(__flags) \ | |
| 40 | #define __PTHREAD_RWLOCK_INITIALIZER(__flags) \ | |
| 52 | 41 | 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 | |
| 57 | 42 | |
| 58 | 43 | #endif |
| \ No newline at end of file |
lib/libc/include/s390x-linux-gnu/bits/struct_stat.h+6-114| ... | ... | @@ -25,7 +25,6 @@ |
| 25 | 25 | |
| 26 | 26 | #include <bits/wordsize.h> |
| 27 | 27 | |
| 28 | #if __WORDSIZE == 64 | |
| 29 | 28 | struct stat |
| 30 | 29 | { |
| 31 | 30 | __dev_t st_dev;		/* Device. */ |
| ... | ... | @@ -62,70 +61,8 @@ struct stat |
| 62 | 61 | __blkcnt_t st_blocks;	/* Nr. 512-byte blocks allocated. */ |
| 63 | 62 | long int __glibc_reserved[3]; |
| 64 | 63 | }; |
| 65 | #else | |
| 66 | struct 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 | |
| 126 | 64 | |
| 127 | 65 | #ifdef __USE_LARGEFILE64 |
| 128 | # if __WORDSIZE == 64 | |
| 129 | 66 | /* Note stat64 is the same shape as stat. */ |
| 130 | 67 | struct stat64 |
| 131 | 68 | { |
| ... | ... | @@ -138,7 +75,7 @@ struct stat64 |
| 138 | 75 | int __glibc_reserved0; |
| 139 | 76 | __dev_t st_rdev;		/* Device number, if device. */ |
| 140 | 77 | __off_t st_size;		/* Size of file, in bytes. */ |
| 141 | # ifdef __USE_XOPEN2K8 | |
| 78 | # ifdef __USE_XOPEN2K8 | |
| 142 | 79 | /* Nanosecond resolution timestamps are stored in a format |
| 143 | 80 | equivalent to 'struct timespec'. This is the type used |
| 144 | 81 | whenever possible but the Unix namespace rules do not allow the |
| ... | ... | @@ -148,66 +85,21 @@ struct stat64 |
| 148 | 85 | struct timespec st_atim;		/* Time of last access. */ |
| 149 | 86 | struct timespec st_mtim;		/* Time of last modification. */ |
| 150 | 87 | struct timespec st_ctim;		/* Time of last status change. */ |
| 151 | # define st_atime st_atim.tv_sec	/* Backward compatibility. */ | |
| 152 | # define st_mtime st_mtim.tv_sec | |
| 153 | # define st_ctime st_ctim.tv_sec | |
| 154 | # else | |
| 88 | # define st_atime st_atim.tv_sec	/* Backward compatibility. */ | |
| 89 | # define st_mtime st_mtim.tv_sec | |
| 90 | # define st_ctime st_ctim.tv_sec | |
| 91 | # else | |
| 155 | 92 | __time_t st_atime;			/* Time of last access. */ |
| 156 | 93 | unsigned long int st_atimensec;	/* Nscecs of last access. */ |
| 157 | 94 | __time_t st_mtime;			/* Time of last modification. */ |
| 158 | 95 | unsigned long int st_mtimensec;	/* Nsecs of last modification. */ |
| 159 | 96 | __time_t st_ctime;			/* Time of last status change. */ |
| 160 | 97 | unsigned long int st_ctimensec;	/* Nsecs of last status change. */ |
| 161 | # endif | |
| 98 | # endif | |
| 162 | 99 | __blksize_t st_blksize;	/* Optimal block size for I/O.	*/ |
| 163 | 100 | __blkcnt64_t st_blocks;	/* Nr. 512-byte blocks allocated. */ |
| 164 | 101 | long int __glibc_reserved[3]; |
| 165 | 102 | }; |
| 166 | # else | |
| 167 | struct 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 | 103 | #endif |
| 212 | 104 | |
| 213 | 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 | 57 | #define __TIMER_T_TYPE		void * |
| 58 | 58 | #define __BLKSIZE_T_TYPE	__SLONGWORD_TYPE |
| 59 | 59 | #define __FSID_T_TYPE		struct { int __val[2]; } |
| 60 | #if defined __GNUC__ && __GNUC__ <= 2 | |
| 61 | /* Compatibility with g++ 2.95.x. */ | |
| 62 | #define __SSIZE_T_TYPE		__SWORD_TYPE | |
| 63 | #else | |
| 64 | /* size_t is unsigned long int on s390 -m31. */ | |
| 65 | #define __SSIZE_T_TYPE		__SLONGWORD_TYPE | |
| 66 | #endif | |
| 60 | ||
| 61 | /* With s390-32, __SSIZE_T_TYPE was __SWORD_TYPE for compatibility with | |
| 62 | g++ 2.95.x. Afterwards __SLONGWORD_TYPE was needed as size_t was | |
| 63 | unsigned long int on s390-32. | |
| 64 | Now as only s390-64 exists, __SWORD_TYPE can be used as also used in the | |
| 65 | generic version as both types result in long int. */ | |
| 66 | #define __SSIZE_T_TYPE __SWORD_TYPE | |
| 67 | ||
| 67 | 68 | #define __SYSCALL_SLONG_TYPE	__SLONGWORD_TYPE |
| 68 | 69 | #define __SYSCALL_ULONG_TYPE	__ULONGWORD_TYPE |
| 69 | #define __CPU_MASK_TYPE 	__ULONGWORD_TYPE | |
| 70 | #define __CPU_MASK_TYPE		__ULONGWORD_TYPE | |
| 70 | 71 | |
| 71 | #ifdef __s390x__ | |
| 72 | 72 | /* Tell the libc code that off_t and off64_t are actually the same type |
| 73 | 73 | for all ABI purposes, even if possibly expressed as different base types |
| 74 | 74 | for C type-checking purposes. */ |
| 75 | # define __OFF_T_MATCHES_OFF64_T	1 | |
| 75 | #define __OFF_T_MATCHES_OFF64_T	1 | |
| 76 | 76 | |
| 77 | 77 | /* Same for ino_t and ino64_t. */ |
| 78 | # define __INO_T_MATCHES_INO64_T	1 | |
| 78 | #define __INO_T_MATCHES_INO64_T	1 | |
| 79 | 79 | |
| 80 | 80 | /* And for __rlim_t and __rlim64_t. */ |
| 81 | # define __RLIM_T_MATCHES_RLIM64_T	1 | |
| 81 | #define __RLIM_T_MATCHES_RLIM64_T	1 | |
| 82 | 82 | |
| 83 | 83 | /* And for fsblkcnt_t, fsblkcnt64_t, fsfilcnt_t and fsfilcnt64_t. */ |
| 84 | # define __STATFS_MATCHES_STATFS64 1 | |
| 84 | #define __STATFS_MATCHES_STATFS64 1 | |
| 85 | 85 | |
| 86 | 86 | /* And for getitimer, setitimer and rusage */ |
| 87 | # define __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64 1 | |
| 88 | #else | |
| 89 | # define __RLIM_T_MATCHES_RLIM64_T	0 | |
| 90 | ||
| 91 | # define __STATFS_MATCHES_STATFS64 0 | |
| 92 | ||
| 93 | /* And for getitimer, setitimer and rusage */ | |
| 94 | # define __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64 0 | |
| 95 | #endif | |
| 87 | #define __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64 1 | |
| 96 | 88 | |
| 97 | 89 | /* Number of descriptors that can fit in an `fd_set'. */ |
| 98 | 90 | #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. */ | |
| 36 | struct 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. */ | |
| 50 | struct 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. */ | |
| 58 | struct 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. */ | |
| 42 | struct __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. */ | |
| 55 | struct utmpx | |
| 56 | { | |
| 57 | short int ut_type;		/* Type of login. */ | |
| 58 | __pid_t ut_pid;		/* Process ID of login process. */ | |
| 59 | char ut_line[__UT_LINESIZE] | |
| 60 | __attribute_nonstring__;	/* Devicename. */ | |
| 61 | char ut_id[4] | |
| 62 | __attribute_nonstring__;	/* Inittab ID. */ | |
| 63 | char ut_user[__UT_NAMESIZE] | |
| 64 | __attribute_nonstring__;	/* Username. */ | |
| 65 | char ut_host[__UT_HOSTSIZE] | |
| 66 | __attribute_nonstring__;	/* Hostname for remote login. */ | |
| 67 | struct __exit_status ut_exit;	/* Exit status of a process marked | |
| 68 | 				 as DEAD_PROCESS. */ | |
| 69 | ||
| 70 | /* The fields ut_session and ut_tv must be the same size when compiled | |
| 71 | 32- and 64-bit. This allows files and shared memory to be shared | |
| 72 | between 32- and 64-bit applications. */ | |
| 73 | #if __WORDSIZE == 32 | |
| 74 | __int64_t ut_session;		/* Session ID, used for windowing. */ | |
| 75 | struct | |
| 76 | { | |
| 77 | __int64_t tv_sec;		/* Seconds. */ | |
| 78 | __int64_t tv_usec;		/* Microseconds. */ | |
| 79 | } ut_tv;			/* Time entry was made. */ | |
| 80 | #else | |
| 81 | long int ut_session;		/* Session ID, used for windowing. */ | |
| 82 | struct timeval ut_tv;		/* Time entry was made. */ | |
| 83 | #endif | |
| 84 | __int32_t ut_addr_v6[4];	/* Internet address of remote host. */ | |
| 85 | char __glibc_reserved[20];		/* Reserved for future use. */ | |
| 86 | }; | |
| 87 | ||
| 88 | ||
| 89 | /* Values for the `ut_type' field of a `struct utmpx'. */ | |
| 90 | #define EMPTY		0	/* No valid user accounting information. */ | |
| 91 | ||
| 92 | #ifdef __USE_GNU | |
| 93 | # define RUN_LVL	1	/* The system's runlevel. */ | |
| 94 | #endif | |
| 95 | #define BOOT_TIME	2	/* Time of system boot. */ | |
| 96 | #define NEW_TIME	3	/* Time after system clock changed. */ | |
| 97 | #define OLD_TIME	4	/* Time when system clock changed. */ | |
| 98 | ||
| 99 | #define INIT_PROCESS	5	/* Process spawned by the init process. */ | |
| 100 | #define LOGIN_PROCESS	6	/* Session leader of a logged in user. */ | |
| 101 | #define USER_PROCESS	7	/* Normal process. */ | |
| 102 | #define DEAD_PROCESS	8	/* Terminated process. */ | |
| 103 | ||
| 104 | #ifdef __USE_GNU | |
| 105 | # define ACCOUNTING	9	/* System accounting. */ | |
| 106 | #endif | |
| \ No newline at end of file |
lib/libc/include/s390x-linux-gnu/bits/wordsize.h+17-9| ... | ... | @@ -1,11 +1,19 @@ |
| 1 | /* Determine the wordsize from the preprocessor defines. */ | |
| 1 | /* Copyright (C) 1999-2026 Free Software Foundation, Inc. | |
| 2 | This file is part of the GNU C Library. | |
| 2 | 3 | |
| 3 | #if defined __s390x__ | |
| 4 | # define __WORDSIZE	64 | |
| 5 | #else | |
| 6 | # define __WORDSIZE	32 | |
| 7 | # define __WORDSIZE32_SIZE_ULONG 1 | |
| 8 | # define __WORDSIZE32_PTRDIFF_LONG 0 | |
| 9 | #endif | |
| 4 | The GNU C Library is free software; you can redistribute it and/or | |
| 5 | modify it under the terms of the GNU Lesser General Public | |
| 6 | License as published by the Free Software Foundation; either | |
| 7 | version 2.1 of the License, or (at your option) any later version. | |
| 10 | 8 | |
| 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 | 4 | #ifndef __GNU_LIB_NAMES_H |
| 5 | 5 | #define __GNU_LIB_NAMES_H	1 |
| 6 | 6 | |
| 7 | #include <bits/wordsize.h> | |
| 8 | ||
| 9 | #if __WORDSIZE == 32 | |
| 10 | # include <gnu/lib-names-32.h> | |
| 11 | #endif | |
| 12 | #if __WORDSIZE == 64 | |
| 13 | # include <gnu/lib-names-64.h> | |
| 14 | #endif | |
| 7 | #define LD64_SO "ld64.so.1" | |
| 8 | #define LD_SO "ld64.so.1" | |
| 9 | #define LIBANL_SO "libanl.so.1" | |
| 10 | #define LIBBROKENLOCALE_SO "libBrokenLocale.so.1" | |
| 11 | #define LIBC_MALLOC_DEBUG_SO "libc_malloc_debug.so.0" | |
| 12 | #define LIBC_SO "libc.so.6" | |
| 13 | #define LIBDL_SO "libdl.so.2" | |
| 14 | #define LIBGCC_S_SO "libgcc_s.so.1" | |
| 15 | #define LIBMVEC_SO "libmvec.so.1" | |
| 16 | #define LIBM_SO "libm.so.6" | |
| 17 | #define LIBNSL_SO "libnsl.so.1" | |
| 18 | #define LIBNSS_COMPAT_SO "libnss_compat.so.2" | |
| 19 | #define LIBNSS_DB_SO "libnss_db.so.2" | |
| 20 | #define LIBNSS_DNS_SO "libnss_dns.so.2" | |
| 21 | #define LIBNSS_FILES_SO "libnss_files.so.2" | |
| 22 | #define LIBNSS_HESIOD_SO "libnss_hesiod.so.2" | |
| 23 | #define LIBNSS_LDAP_SO "libnss_ldap.so.2" | |
| 24 | #define LIBPTHREAD_SO "libpthread.so.0" | |
| 25 | #define LIBRESOLV_SO "libresolv.so.2" | |
| 26 | #define LIBRT_SO "librt.so.1" | |
| 27 | #define LIBTHREAD_DB_SO "libthread_db.so.1" | |
| 28 | #define LIBUNWIND_SO "libunwind.so.1" | |
| 29 | #define LIBUTIL_SO "libutil.so.1" | |
| 15 | 30 | |
| 16 | 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 | 1 | /* This file is automatically generated. |
| 2 | This file selects the right generated file of `__stub_FUNCTION' macros | |
| 3 | based on the architecture being compiled for. */ | |
| 2 | It defines a symbol `__stub_FUNCTION' for each function | |
| 3 | in the C library which is a stub, meaning it will fail | |
| 4 | every time called, usually setting errno to ENOSYS. */ | |
| 4 | 5 | |
| 5 | #include <bits/wordsize.h> | |
| 6 | ||
| 7 | #if __WORDSIZE == 32 | |
| 8 | # include <gnu/stubs-32.h> | |
| 6 | #ifdef _LIBC | |
| 7 | #error Applications may not define the macro _LIBC | |
| 9 | 8 | #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 | 45 | the register set is an array, we make gregset_t a simple array |
| 46 | 46 | that has the same size as s390_regs. This is needed for the |
| 47 | 47 | elf_prstatus structure. */ |
| 48 | #if __WORDSIZE == 64 | |
| 49 | # define __NGREG 27 | |
| 50 | #else | |
| 51 | # define __NGREG 36 | |
| 52 | #endif | |
| 48 | #define __NGREG 27 | |
| 53 | 49 | #ifdef __USE_MISC |
| 54 | 50 | # define NGREG __NGREG |
| 55 | 51 | #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 | 24 | #define LIBRESOLV_SO "libresolv.so.2" |
| 25 | 25 | #define LIBRT_SO "librt.so.1" |
| 26 | 26 | #define LIBTHREAD_DB_SO "libthread_db.so.1" |
| 27 | #define LIBUNWIND_SO "libunwind.so.1" | |
| 27 | 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 | 59 | 0, 0, 0, __kind, 0, { { 0, 0 } } |
| 60 | 60 | #endif |
| 61 | 61 | |
| 62 | #endif | |
| 62 | #endif | |
| \ No newline at end of file |
lib/libc/include/x86-linux-gnu/gnu/lib-names-64.h+1| ... | ... | @@ -24,4 +24,5 @@ |
| 24 | 24 | #define LIBRESOLV_SO "libresolv.so.2" |
| 25 | 25 | #define LIBRT_SO "librt.so.1" |
| 26 | 26 | #define LIBTHREAD_DB_SO "libthread_db.so.1" |
| 27 | #define LIBUNWIND_SO "libunwind.so.1" | |
| 27 | 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 | 24 | #define LIBRESOLV_SO "libresolv.so.2" |
| 25 | 25 | #define LIBRT_SO "librt.so.1" |
| 26 | 26 | #define LIBTHREAD_DB_SO "libthread_db.so.1" |
| 27 | #define LIBUNWIND_SO "libunwind.so.1" | |
| 27 | 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 | /*	$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 $	*/ | |
| 2 | 2 | |
| 3 | 3 | /*- |
| 4 | 4 | * Copyright (c) 1999 The NetBSD Foundation, Inc. |
| ... | ... | @@ -40,6 +40,7 @@ |
| 40 | 40 | #define	_UC_CLRSTACK	_UC_MD_BIT17 |
| 41 | 41 | #define	_UC_VM		_UC_MD_BIT18 |
| 42 | 42 | #define	_UC_TLSBASE	_UC_MD_BIT19 |
| 43 | #define	_UC_XSAVE	_UC_MD_BIT20 | |
| 43 | 44 | |
| 44 | 45 | /* |
| 45 | 46 | * Layout of mcontext_t according to the System V Application Binary Interface, |
| ... | ... | @@ -85,6 +86,27 @@ typedef struct { |
| 85 | 86 | 			char	__fp_xmm[512]; |
| 86 | 87 | 		} __fp_xmm_state;	/* x87 and xmm regs in fxsave format */ |
| 87 | 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 | 110 | 	} __fp_reg_set; |
| 89 | 111 | 	int 	__fp_pad[33];			/* Historic padding */ |
| 90 | 112 | } __fpregset_t; |
lib/libc/include/x86_64-netbsd-none/amd64/mcontext.h+31-2| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | /*	$NetBSD: mcontext.h,v 1.24 2024/11/30 01:04:06 christos Exp $	*/ | |
| 1 | /*	$NetBSD: mcontext.h,v 1.24.2.1 2026/07/19 15:57:26 martin Exp $	*/ | |
| 2 | 2 | |
| 3 | 3 | /*- |
| 4 | 4 | * Copyright (c) 1999 The NetBSD Foundation, Inc. |
| ... | ... | @@ -56,7 +56,28 @@ typedef	__greg_t	__gregset_t[_NGREG]; |
| 56 | 56 | * which requires 16 byte alignment. However the mcontext version |
| 57 | 57 | * is never directly accessed. |
| 58 | 58 | */ |
| 59 | typedef char __fpregset_t[512] __aligned(8); | |
| 59 | typedef 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; | |
| 60 | 81 | |
| 61 | 82 | typedef struct { |
| 62 | 83 | 	__gregset_t	__gregs; |
| ... | ... | @@ -75,6 +96,7 @@ typedef struct { |
| 75 | 96 | #define	_UC_MACHINE_SET_PC(uc, pc)	_UC_MACHINE_PC(uc) = (pc) |
| 76 | 97 | |
| 77 | 98 | #define	_UC_TLSBASE	_UC_MD_BIT19 |
| 99 | #define	_UC_XSAVE	_UC_MD_BIT20 | |
| 78 | 100 | |
| 79 | 101 | /* |
| 80 | 102 | * mcontext extensions to handle signal delivery. |
| ... | ... | @@ -127,6 +149,13 @@ typedef struct { |
| 127 | 149 | 		struct { |
| 128 | 150 | 			char	__fp_xmm[512]; |
| 129 | 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 | 159 | 	} __fp_reg_set; |
| 131 | 160 | 	int	__fp_pad[33];			/* Historic padding */ |
| 132 | 161 | } __fpregset32_t; |
lib/libc/include/x86_64-netbsd-none/machine/mcontext.h+31-2| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | /*	$NetBSD: mcontext.h,v 1.24 2024/11/30 01:04:06 christos Exp $	*/ | |
| 1 | /*	$NetBSD: mcontext.h,v 1.24.2.1 2026/07/19 15:57:26 martin Exp $	*/ | |
| 2 | 2 | |
| 3 | 3 | /*- |
| 4 | 4 | * Copyright (c) 1999 The NetBSD Foundation, Inc. |
| ... | ... | @@ -56,7 +56,28 @@ typedef	__greg_t	__gregset_t[_NGREG]; |
| 56 | 56 | * which requires 16 byte alignment. However the mcontext version |
| 57 | 57 | * is never directly accessed. |
| 58 | 58 | */ |
| 59 | typedef char __fpregset_t[512] __aligned(8); | |
| 59 | typedef 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; | |
| 60 | 81 | |
| 61 | 82 | typedef struct { |
| 62 | 83 | 	__gregset_t	__gregs; |
| ... | ... | @@ -75,6 +96,7 @@ typedef struct { |
| 75 | 96 | #define	_UC_MACHINE_SET_PC(uc, pc)	_UC_MACHINE_PC(uc) = (pc) |
| 76 | 97 | |
| 77 | 98 | #define	_UC_TLSBASE	_UC_MD_BIT19 |
| 99 | #define	_UC_XSAVE	_UC_MD_BIT20 | |
| 78 | 100 | |
| 79 | 101 | /* |
| 80 | 102 | * mcontext extensions to handle signal delivery. |
| ... | ... | @@ -127,6 +149,13 @@ typedef struct { |
| 127 | 149 | 		struct { |
| 128 | 150 | 			char	__fp_xmm[512]; |
| 129 | 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 | 159 | 	} __fp_reg_set; |
| 131 | 160 | 	int	__fp_pad[33];			/* Historic padding */ |
| 132 | 161 | } __fpregset32_t; |
lib/std/Build.zig+48-44| ... | ... | @@ -45,17 +45,6 @@ debug_log_scopes: []const []const u8 = &.{}, |
| 45 | 45 | /// Set to 0 to disable stack collection. |
| 46 | 46 | debug_stack_frames_count: u8 = 8, |
| 47 | 47 | |
| 48 | /// Experimental. Use system Darling installation to run cross compiled macOS build artifacts. | |
| 49 | enable_darling: bool = false, | |
| 50 | /// Use system QEMU installation to run cross compiled foreign architecture build artifacts. | |
| 51 | enable_qemu: bool = false, | |
| 52 | /// Darwin. Use Rosetta to run x86_64 macOS build artifacts on arm64 macOS. | |
| 53 | enable_rosetta: bool = false, | |
| 54 | /// Use system Wasmtime installation to run cross compiled wasm/wasi build artifacts. | |
| 55 | enable_wasmtime: bool = false, | |
| 56 | /// Use system Wine installation to run cross compiled Windows build artifacts. | |
| 57 | enable_wine: bool = false, | |
| 58 | ||
| 59 | 48 | dep_prefix: []const u8 = "", |
| 60 | 49 | |
| 61 | 50 | modules: std.array_hash_map.String(*Module), |
| ... | ... | @@ -388,11 +377,6 @@ fn createChild( |
| 388 | 377 | .default_step = undefined, |
| 389 | 378 | .top_level_steps = .{}, |
| 390 | 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 | 380 | .dep_prefix = parent.fmt("{s}{s}.", .{ parent.dep_prefix, dep_name }), |
| 397 | 381 | .modules = .empty, |
| 398 | 382 | .named_writefiles = .empty, |
| ... | ... | @@ -830,7 +814,7 @@ pub fn addTest(b: *Build, options: TestOptions) *Step.Compile { |
| 830 | 814 | .kind = if (options.emit_object) .test_obj else .@"test", |
| 831 | 815 | .root_module = options.root_module, |
| 832 | 816 | .max_rss = options.max_rss, |
| 833 | .filters = b.dupeStrings(options.filters), | |
| 817 | .filters = b.graph.dupeStrings(options.filters), | |
| 834 | 818 | .test_runner = options.test_runner, |
| 835 | 819 | .use_llvm = options.use_llvm, |
| 836 | 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 | 1109 | const type_id = comptime typeToEnum(T); |
| 1126 | 1110 | const enum_options = if (type_id == .@"enum" or type_id == .enum_list) blk: { |
| 1127 | 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 | 1113 | var options = std.array_list.Managed([]const u8).initCapacity(b.allocator, field_names.len) catch @panic("OOM"); |
| 1130 | 1114 | |
| 1131 | 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 | 1194 | return null; |
| 1211 | 1195 | }, |
| 1212 | 1196 | .scalar => |s| { |
| 1213 | if (std.meta.stringToEnum(T, s)) |enum_lit| { | |
| 1214 | return enum_lit; | |
| 1215 | } else { | |
| 1216 | log.err("expected -D{s} to be of type {s}", .{ name, @typeName(T) }); | |
| 1217 | b.markInvalidUserInput(); | |
| 1218 | return null; | |
| 1197 | if (T == std.lang.Optimize) { | |
| 1198 | if (std.lang.Optimize.fromString(s)) |tag| { | |
| 1199 | return tag; | |
| 1200 | } | |
| 1201 | } else if (std.meta.stringToEnum(T, s)) |tag| { | |
| 1202 | return tag; | |
| 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 | 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 | 1249 | }, |
| 1263 | 1250 | .scalar => |s| { |
| 1264 | 1251 | const Child = @typeInfo(T).pointer.child; |
| 1265 | const value = std.meta.stringToEnum(Child, s) orelse { | |
| 1266 | log.err("expected -D{s} to be of type {s}", .{ name, @typeName(Child) }); | |
| 1267 | b.markInvalidUserInput(); | |
| 1268 | return null; | |
| 1269 | }; | |
| 1270 | return arena.dupe(Child, &[_]Child{value}) catch @panic("OOM"); | |
| 1252 | if (Child == std.lang.Optimize) { | |
| 1253 | if (std.lang.Optimize.fromString(s)) |tag| { | |
| 1254 | return arena.dupe(Child, &.{tag}) catch @panic("OOM"); | |
| 1255 | } | |
| 1256 | } else { | |
| 1257 | if (std.meta.stringToEnum(Child, s)) |tag| { | |
| 1258 | return arena.dupe(Child, &.{tag}) catch @panic("OOM"); | |
| 1259 | } | |
| 1260 | } | |
| 1261 | log.err("expected -D{s} to be of type {q}", .{ name, @typeName(Child) }); | |
| 1262 | b.markInvalidUserInput(); | |
| 1263 | return null; | |
| 1271 | 1264 | }, |
| 1272 | 1265 | .list => |lst| { |
| 1273 | 1266 | const Child = @typeInfo(T).pointer.child; |
| 1274 | 1267 | const new_list = graph.alloc(Child, lst.items.len); |
| 1275 | 1268 | for (new_list, lst.items) |*new_item, str| { |
| 1276 | new_item.* = std.meta.stringToEnum(Child, str) orelse { | |
| 1277 | log.err("expected -D{s} to be of type {s}", .{ name, @typeName(Child) }); | |
| 1278 | b.markInvalidUserInput(); | |
| 1279 | arena.free(new_list); | |
| 1280 | return null; | |
| 1281 | }; | |
| 1269 | if (Child == std.lang.Optimize) { | |
| 1270 | if (std.lang.Optimize.fromString(str)) |tag| { | |
| 1271 | new_item.* = tag; | |
| 1272 | continue; | |
| 1273 | } | |
| 1274 | } | |
| 1275 | if (std.meta.stringToEnum(Child, str)) |tag| { | |
| 1276 | new_item.* = tag; | |
| 1277 | continue; | |
| 1278 | } | |
| 1279 | log.err("expected -D{s} to be of type {q}", .{ name, @typeName(Child) }); | |
| 1280 | b.markInvalidUserInput(); | |
| 1281 | return null; | |
| 1282 | 1282 | } |
| 1283 | 1283 | return new_list; |
| 1284 | 1284 | }, |
| ... | ... | @@ -1359,14 +1359,14 @@ pub fn standardOptimizeOption(b: *Build, options: StandardOptimizeOptionOptions) |
| 1359 | 1359 | } |
| 1360 | 1360 | |
| 1361 | 1361 | return switch (graph.release_mode) { |
| 1362 | .off => .Debug, | |
| 1362 | .off => .debug, | |
| 1363 | 1363 | .any => { |
| 1364 | 1364 | std.debug.print("the project does not declare a preferred optimization mode. choose: --release=fast, --release=safe, or --release=small\n", .{}); |
| 1365 | 1365 | process.exit(1); |
| 1366 | 1366 | }, |
| 1367 | .fast => .ReleaseFast, | |
| 1368 | .safe => .ReleaseSafe, | |
| 1369 | .small => .ReleaseSmall, | |
| 1367 | .fast => .fast, | |
| 1368 | .safe => .safe, | |
| 1369 | .small => .small, | |
| 1370 | 1370 | }; |
| 1371 | 1371 | } |
| 1372 | 1372 | |
| ... | ... | @@ -1420,7 +1420,7 @@ pub fn parseTargetQuery(options: std.Target.Query.ParseOptions) error{ParseFaile |
| 1420 | 1420 | \\available operating systems: |
| 1421 | 1421 | \\ |
| 1422 | 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 | 1424 | std.debug.print(" {s}\n", .{field_name}); |
| 1425 | 1425 | } |
| 1426 | 1426 | return error.ParseFailed; |
| ... | ... | @@ -2144,7 +2144,7 @@ pub fn dependencyLazy(b: *Build, name: []const u8, args: anytype) error{LazyDepe |
| 2144 | 2144 | return dependencyResolved(b, name, entry, userInputOptionsFromArgs(b.graph.arena, args)); |
| 2145 | 2145 | } |
| 2146 | 2146 | |
| 2147 | const PackageEntry = struct { | |
| 2147 | pub const PackageEntry = struct { | |
| 2148 | 2148 | hash: []const u8, |
| 2149 | 2149 | available: bool, |
| 2150 | 2150 | build_root: []const u8, |
| ... | ... | @@ -2152,7 +2152,8 @@ const PackageEntry = struct { |
| 2152 | 2152 | run_build: ?*const fn (*Build) void, |
| 2153 | 2153 | }; |
| 2154 | 2154 | |
| 2155 | const package_map: std.StaticStringMap(PackageEntry) = blk: { | |
| 2155 | /// Build system implementation detail. | |
| 2156 | pub const package_map: std.StaticStringMap(PackageEntry) = blk: { | |
| 2156 | 2157 | const deps = @import("root").dependencies; |
| 2157 | 2158 | const decl_names = @typeInfo(deps.packages).@"struct".decl_names; |
| 2158 | 2159 | var kvs: [decl_names.len]struct { []const u8, PackageEntry } = undefined; |
| ... | ... | @@ -2632,7 +2633,10 @@ pub const LazyPath = union(enum) { |
| 2632 | 2633 | |
| 2633 | 2634 | fn dupeInner(lazy_path: LazyPath, arena: Allocator) LazyPath { |
| 2634 | 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 | 2640 | .cwd_relative => |p| .{ .cwd_relative = Graph.dupePathInner(arena, p) }, |
| 2637 | 2641 | .relative => |r| .{ .relative = r }, |
| 2638 | 2642 | .generated => |gen| .{ .generated = .{ |
lib/std/Build/Configuration.zig+77-334| ... | ... | @@ -15,6 +15,8 @@ unlazy_deps: []String, |
| 15 | 15 | system_integrations: []SystemIntegration, |
| 16 | 16 | available_options: []AvailableOption, |
| 17 | 17 | search_prefixes: []String, |
| 18 | /// Index 0 always exists and is the root package. | |
| 19 | packages: []Package, | |
| 18 | 20 | extra: []u32, |
| 19 | 21 | default_step: Step.Index, |
| 20 | 22 | generated_files_len: u32, |
| ... | ... | @@ -30,6 +32,7 @@ pub const Header = extern struct { |
| 30 | 32 | system_integrations_len: u32, |
| 31 | 33 | available_options_len: u32, |
| 32 | 34 | search_prefixes_len: u32, |
| 35 | packages_len: u32, | |
| 33 | 36 | extra_len: u32, |
| 34 | 37 | |
| 35 | 38 | default_step: Step.Index, |
| ... | ... | @@ -58,6 +61,7 @@ pub const Wip = struct { |
| 58 | 61 | steps: std.ArrayList(Step) = .empty, |
| 59 | 62 | path_deps: std.ArrayList(PathDep) = .empty, |
| 60 | 63 | search_prefixes: std.ArrayList(String) = .empty, |
| 64 | packages: std.ArrayList(Package) = .empty, | |
| 61 | 65 | extra: std.ArrayList(u32) = .empty, |
| 62 | 66 | next_generated_file_index: u32 = 0, |
| 63 | 67 | cache_poison: bool = false, |
| ... | ... | @@ -121,7 +125,7 @@ pub const Wip = struct { |
| 121 | 125 | } |
| 122 | 126 | |
| 123 | 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 | 129 | return std.hash_map.hashString(adapted_key); |
| 126 | 130 | } |
| 127 | 131 | }; |
| ... | ... | @@ -139,6 +143,7 @@ pub const Wip = struct { |
| 139 | 143 | wip.steps.deinit(gpa); |
| 140 | 144 | wip.path_deps.deinit(gpa); |
| 141 | 145 | wip.search_prefixes.deinit(gpa); |
| 146 | wip.packages.deinit(gpa); | |
| 142 | 147 | wip.extra.deinit(gpa); |
| 143 | 148 | wip.* = undefined; |
| 144 | 149 | } |
| ... | ... | @@ -158,6 +163,7 @@ pub const Wip = struct { |
| 158 | 163 | .system_integrations_len = @intCast(wip.system_integrations.items.len), |
| 159 | 164 | .available_options_len = @intCast(wip.available_options.items.len), |
| 160 | 165 | .search_prefixes_len = @intCast(wip.search_prefixes.items.len), |
| 166 | .packages_len = @intCast(wip.packages.items.len), | |
| 161 | 167 | .extra_len = @intCast(wip.extra.items.len), |
| 162 | 168 | |
| 163 | 169 | .default_step = static.default_step, |
| ... | ... | @@ -175,6 +181,7 @@ pub const Wip = struct { |
| 175 | 181 | @ptrCast(wip.system_integrations.items), |
| 176 | 182 | @ptrCast(wip.available_options.items), |
| 177 | 183 | @ptrCast(wip.search_prefixes.items), |
| 184 | @ptrCast(wip.packages.items), | |
| 178 | 185 | @ptrCast(wip.extra.items), |
| 179 | 186 | }; |
| 180 | 187 | try w.writeVecAll(&buffers); |
| ... | ... | @@ -182,7 +189,7 @@ pub const Wip = struct { |
| 182 | 189 | |
| 183 | 190 | pub fn addString(wip: *Wip, bytes: []const u8) Allocator.Error!String { |
| 184 | 191 | const gpa = wip.gpa; |
| 185 | assert(std.mem.indexOfScalar(u8, bytes, 0) == null); | |
| 192 | assert(std.mem.findScalar(u8, bytes, 0) == null); | |
| 186 | 193 | const gop = try wip.string_table.getOrPutContextAdapted( |
| 187 | 194 | gpa, |
| 188 | 195 | @as([]const u8, bytes), |
| ... | ... | @@ -439,7 +446,7 @@ pub const Wip = struct { |
| 439 | 446 | /// Returned slice expires upon next append to the configuration. |
| 440 | 447 | pub fn stringSlice(wip: *const Wip, s: String) [:0]const u8 { |
| 441 | 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 | }; |
| 445 | 452 | |
| ... | ... | @@ -569,8 +576,7 @@ pub const Step = extern struct { |
| 569 | 576 | flags2: Flags2, |
| 570 | 577 | args: Storage.LengthPrefixedList(Arg.Index), |
| 571 | 578 | cwd: Storage.FlagOptional(.flags, .cwd, LazyPath.Index), |
| 572 | preopen_names: Storage.LengthPrefixedList(String), | |
| 573 | preopen_paths: Storage.LengthPrefixedList(LazyPath.Index), | |
| 579 | preopens: Storage.FlagLengthPrefixedList(.flags, .preopens, Preopen), | |
| 574 | 580 | captured_stdout: Storage.FlagOptional(.flags, .captured_stdout, CapturedStream), |
| 575 | 581 | captured_stderr: Storage.FlagOptional(.flags, .captured_stderr, CapturedStream), |
| 576 | 582 | file_inputs: Storage.LengthPrefixedList(LazyPath.Index), |
| ... | ... | @@ -627,6 +633,13 @@ pub const Step = extern struct { |
| 627 | 633 | output_file, |
| 628 | 634 | output_directory, |
| 629 | 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 | }; |
| 631 | 644 | |
| 632 | 645 | pub const Index = IndexType(@This()); |
| ... | ... | @@ -646,6 +659,11 @@ pub const Step = extern struct { |
| 646 | 659 | manual, |
| 647 | 660 | }; |
| 648 | 661 | |
| 662 | pub const Preopen = extern struct { | |
| 663 | name: String, | |
| 664 | path: LazyPath.Index, | |
| 665 | }; | |
| 666 | ||
| 649 | 667 | pub const StdIn = union(@This().Tag) { |
| 650 | 668 | none: void, |
| 651 | 669 | bytes: Bytes, |
| ... | ... | @@ -676,7 +694,8 @@ pub const Step = extern struct { |
| 676 | 694 | captured_stdout: bool, |
| 677 | 695 | captured_stderr: bool, |
| 678 | 696 | environ_map: bool, |
| 679 | _: u4 = 0, | |
| 697 | preopens: bool, | |
| 698 | _: u3 = 0, | |
| 680 | 699 | }; |
| 681 | 700 | |
| 682 | 701 | pub const Flags2 = packed struct(u32) { |
| ... | ... | @@ -979,8 +998,6 @@ pub const Step = extern struct { |
| 979 | 998 | }; |
| 980 | 999 | |
| 981 | 1000 | pub const Flags3 = packed struct(u32) { |
| 982 | is_linking_libc: bool, | |
| 983 | is_linking_libcpp: bool, | |
| 984 | 1001 | version: bool, |
| 985 | 1002 | initial_memory: bool, |
| 986 | 1003 | max_memory: bool, |
| ... | ... | @@ -998,6 +1015,7 @@ pub const Step = extern struct { |
| 998 | 1015 | entry: Entry, |
| 999 | 1016 | lto: Lto, |
| 1000 | 1017 | subsystem: Subsystem, |
| 1018 | _: u2 = 0, | |
| 1001 | 1019 | }; |
| 1002 | 1020 | |
| 1003 | 1021 | pub const Flags4 = packed struct(u32) { |
| ... | ... | @@ -1076,6 +1094,7 @@ pub const Step = extern struct { |
| 1076 | 1094 | autoconf_undef, |
| 1077 | 1095 | autoconf_at, |
| 1078 | 1096 | cmake, |
| 1097 | meson, | |
| 1079 | 1098 | blank, |
| 1080 | 1099 | nasm, |
| 1081 | 1100 | |
| ... | ... | @@ -1084,6 +1103,7 @@ pub const Step = extern struct { |
| 1084 | 1103 | .autoconf_undef => .autoconf_undef, |
| 1085 | 1104 | .autoconf_at => .autoconf_at, |
| 1086 | 1105 | .cmake => .cmake, |
| 1106 | .meson => .meson, | |
| 1087 | 1107 | .blank => .blank, |
| 1088 | 1108 | .nasm => .nasm, |
| 1089 | 1109 | }; |
| ... | ... | @@ -1589,30 +1609,28 @@ pub const OptionalGeneratedFileIndex = enum(u32) { |
| 1589 | 1609 | } |
| 1590 | 1610 | }; |
| 1591 | 1611 | |
| 1592 | pub const Package = struct { | |
| 1612 | pub const Package = extern struct { | |
| 1593 | 1613 | dep_prefix: String, |
| 1594 | 1614 | hash: String, |
| 1595 | 1615 | root_path: String, |
| 1616 | deps: Dep.List.Index, | |
| 1596 | 1617 | |
| 1597 | 1618 | pub const Index = enum(u32) { |
| 1598 | root = max_u32, | |
| 1619 | root, | |
| 1599 | 1620 | _, |
| 1600 | 1621 | |
| 1601 | /// Returns `null` for root package. | |
| 1602 | pub fn get(i: @This(), c: *const Configuration) ?Package { | |
| 1603 | if (i == .root) return null; | |
| 1604 | return extraData(c, Package, @backingInt(i)); | |
| 1622 | pub fn ptr(i: @This(), c: *const Configuration) *const Package { | |
| 1623 | return &c.packages[@backingInt(i)]; | |
| 1605 | 1624 | } |
| 1606 | 1625 | |
| 1607 | 1626 | pub fn depPrefixSlice(i: @This(), c: *const Configuration) [:0]const u8 { |
| 1608 | const package = get(i, c) orelse return ""; | |
| 1609 | return package.dep_prefix.slice(c); | |
| 1627 | return ptr(i, c).dep_prefix.slice(c); | |
| 1610 | 1628 | } |
| 1611 | 1629 | }; |
| 1612 | 1630 | |
| 1613 | 1631 | pub const OptionalIndex = enum(u32) { |
| 1614 | none = max_u32 - 1, | |
| 1615 | root = max_u32, | |
| 1632 | root, | |
| 1633 | none = max_u32, | |
| 1616 | 1634 | _, |
| 1617 | 1635 | |
| 1618 | 1636 | pub fn init(i: Index) OptionalIndex { |
| ... | ... | @@ -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 | }; |
| 1633 | 1673 | |
| 1634 | 1674 | pub const Module = struct { |
| ... | ... | @@ -1655,10 +1695,10 @@ pub const Module = struct { |
| 1655 | 1695 | |
| 1656 | 1696 | pub fn init(o: ?std.builtin.OptimizeMode) Optimize { |
| 1657 | 1697 | return switch (o orelse return .default) { |
| 1658 | .Debug => .debug, | |
| 1659 | .ReleaseSafe => .safe, | |
| 1660 | .ReleaseFast => .fast, | |
| 1661 | .ReleaseSmall => .small, | |
| 1698 | .debug => .debug, | |
| 1699 | .safe => .safe, | |
| 1700 | .fast => .fast, | |
| 1701 | .small => .small, | |
| 1662 | 1702 | }; |
| 1663 | 1703 | } |
| 1664 | 1704 | }; |
| ... | ... | @@ -1946,7 +1986,7 @@ pub const String = enum(u32) { |
| 1946 | 1986 | |
| 1947 | 1987 | pub fn slice(index: String, c: *const Configuration) [:0]const u8 { |
| 1948 | 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 | }; |
| 1952 | 1992 | |
| ... | ... | @@ -2113,27 +2153,18 @@ pub const OptionalCSourceLanguage = enum(u3) { |
| 2113 | 2153 | objective_cpp, |
| 2114 | 2154 | assembly, |
| 2115 | 2155 | assembly_with_preprocessor, |
| 2156 | ||
| 2116 | 2157 | default, |
| 2117 | 2158 | |
| 2118 | 2159 | pub fn init(x: ?std.Build.Module.CSourceLanguage) @This() { |
| 2119 | 2160 | return switch (x orelse return .default) { |
| 2120 | .c => .c, | |
| 2121 | .cpp => .cpp, | |
| 2122 | .objective_c => .objective_c, | |
| 2123 | .objective_cpp => .objective_cpp, | |
| 2124 | .assembly => .assembly, | |
| 2125 | .assembly_with_preprocessor => .assembly_with_preprocessor, | |
| 2161 | inline else => |tag| @field(@This(), @tagName(tag)), | |
| 2126 | 2162 | }; |
| 2127 | 2163 | } |
| 2128 | 2164 | |
| 2129 | 2165 | pub fn get(this: @This()) ?std.Build.Module.CSourceLanguage { |
| 2130 | 2166 | return switch (this) { |
| 2131 | .c => .c, | |
| 2132 | .cpp => .cpp, | |
| 2133 | .objective_c => .objective_c, | |
| 2134 | .objective_cpp => .objective_cpp, | |
| 2135 | .assembly => .assembly, | |
| 2136 | .assembly_with_preprocessor => .assembly_with_preprocessor, | |
| 2167 | inline else => |tag| @field(std.Build.Module.CSourceLanguage, @tagName(tag)), | |
| 2137 | 2168 | .default => null, |
| 2138 | 2169 | }; |
| 2139 | 2170 | } |
| ... | ... | @@ -2261,10 +2292,7 @@ pub const TargetQuery = struct { |
| 2261 | 2292 | |
| 2262 | 2293 | pub fn init(x: std.Target.Query.CpuModel) @This() { |
| 2263 | 2294 | return switch (x) { |
| 2264 | .native => .native, | |
| 2265 | .baseline => .baseline, | |
| 2266 | .determined_by_arch_os => .determined_by_arch_os, | |
| 2267 | .explicit => .explicit, | |
| 2295 | inline else => |_, tag| @field(@This(), @tagName(tag)), | |
| 2268 | 2296 | }; |
| 2269 | 2297 | } |
| 2270 | 2298 | }; |
| ... | ... | @@ -2322,71 +2350,13 @@ pub const TargetQuery = struct { |
| 2322 | 2350 | |
| 2323 | 2351 | pub fn init(x: ?std.Target.Abi) @This() { |
| 2324 | 2352 | return switch (x orelse return .default) { |
| 2325 | .none => .none, | |
| 2326 | .gnu => .gnu, | |
| 2327 | .gnuabin32 => .gnuabin32, | |
| 2328 | .gnuabi64 => .gnuabi64, | |
| 2329 | .gnueabi => .gnueabi, | |
| 2330 | .gnueabihf => .gnueabihf, | |
| 2331 | .gnuf32 => .gnuf32, | |
| 2332 | .gnusf => .gnusf, | |
| 2333 | .gnux32 => .gnux32, | |
| 2334 | .eabi => .eabi, | |
| 2335 | .eabihf => .eabihf, | |
| 2336 | .abin32 => .abin32, | |
| 2337 | .x32 => .x32, | |
| 2338 | .ilp32 => .ilp32, | |
| 2339 | .android => .android, | |
| 2340 | .androideabi => .androideabi, | |
| 2341 | .musl => .musl, | |
| 2342 | .muslabin32 => .muslabin32, | |
| 2343 | .muslabi64 => .muslabi64, | |
| 2344 | .musleabi => .musleabi, | |
| 2345 | .musleabihf => .musleabihf, | |
| 2346 | .muslf32 => .muslf32, | |
| 2347 | .muslsf => .muslsf, | |
| 2348 | .muslx32 => .muslx32, | |
| 2349 | .msvc => .msvc, | |
| 2350 | .itanium => .itanium, | |
| 2351 | .simulator => .simulator, | |
| 2352 | .ohos => .ohos, | |
| 2353 | .ohoseabi => .ohoseabi, | |
| 2354 | .call0 => .call0, | |
| 2353 | inline else => |tag| @field(@This(), @tagName(tag)), | |
| 2355 | 2354 | }; |
| 2356 | 2355 | } |
| 2357 | 2356 | |
| 2358 | 2357 | pub fn unwrap(this: @This()) ?std.Target.Abi { |
| 2359 | 2358 | return switch (this) { |
| 2360 | .none => .none, | |
| 2361 | .gnu => .gnu, | |
| 2362 | .gnuabin32 => .gnuabin32, | |
| 2363 | .gnuabi64 => .gnuabi64, | |
| 2364 | .gnueabi => .gnueabi, | |
| 2365 | .gnueabihf => .gnueabihf, | |
| 2366 | .gnuf32 => .gnuf32, | |
| 2367 | .gnusf => .gnusf, | |
| 2368 | .gnux32 => .gnux32, | |
| 2369 | .eabi => .eabi, | |
| 2370 | .eabihf => .eabihf, | |
| 2371 | .abin32 => .abin32, | |
| 2372 | .x32 => .x32, | |
| 2373 | .ilp32 => .ilp32, | |
| 2374 | .android => .android, | |
| 2375 | .androideabi => .androideabi, | |
| 2376 | .musl => .musl, | |
| 2377 | .muslabin32 => .muslabin32, | |
| 2378 | .muslabi64 => .muslabi64, | |
| 2379 | .musleabi => .musleabi, | |
| 2380 | .musleabihf => .musleabihf, | |
| 2381 | .muslf32 => .muslf32, | |
| 2382 | .muslsf => .muslsf, | |
| 2383 | .muslx32 => .muslx32, | |
| 2384 | .msvc => .msvc, | |
| 2385 | .itanium => .itanium, | |
| 2386 | .simulator => .simulator, | |
| 2387 | .ohos => .ohos, | |
| 2388 | .ohoseabi => .ohoseabi, | |
| 2389 | .call0 => .call0, | |
| 2359 | inline else => |tag| @field(std.Target.Abi, @tagName(tag)), | |
| 2390 | 2360 | .default => null, |
| 2391 | 2361 | }; |
| 2392 | 2362 | } |
| ... | ... | @@ -2458,132 +2428,13 @@ pub const TargetQuery = struct { |
| 2458 | 2428 | |
| 2459 | 2429 | pub fn init(x: ?std.Target.Cpu.Arch) @This() { |
| 2460 | 2430 | return switch (x orelse return .default) { |
| 2461 | .aarch64 => .aarch64, | |
| 2462 | .aarch64_be => .aarch64_be, | |
| 2463 | .alpha => .alpha, | |
| 2464 | .amdgcn => .amdgcn, | |
| 2465 | .arc => .arc, | |
| 2466 | .arceb => .arceb, | |
| 2467 | .arm => .arm, | |
| 2468 | .armeb => .armeb, | |
| 2469 | .avr => .avr, | |
| 2470 | .bpfeb => .bpfeb, | |
| 2471 | .bpfel => .bpfel, | |
| 2472 | .csky => .csky, | |
| 2473 | .ez80 => .ez80, | |
| 2474 | .hexagon => .hexagon, | |
| 2475 | .hppa => .hppa, | |
| 2476 | .hppa64 => .hppa64, | |
| 2477 | .kalimba => .kalimba, | |
| 2478 | .kvx => .kvx, | |
| 2479 | .lanai => .lanai, | |
| 2480 | .loongarch32 => .loongarch32, | |
| 2481 | .loongarch64 => .loongarch64, | |
| 2482 | .m68k => .m68k, | |
| 2483 | .m88k => .m88k, | |
| 2484 | .microblaze => .microblaze, | |
| 2485 | .microblazeel => .microblazeel, | |
| 2486 | .mips => .mips, | |
| 2487 | .mipsel => .mipsel, | |
| 2488 | .mips64 => .mips64, | |
| 2489 | .mips64el => .mips64el, | |
| 2490 | .msp430 => .msp430, | |
| 2491 | .nvptx => .nvptx, | |
| 2492 | .nvptx64 => .nvptx64, | |
| 2493 | .or1k => .or1k, | |
| 2494 | .powerpc => .powerpc, | |
| 2495 | .powerpcle => .powerpcle, | |
| 2496 | .powerpc64 => .powerpc64, | |
| 2497 | .powerpc64le => .powerpc64le, | |
| 2498 | .propeller => .propeller, | |
| 2499 | .riscv32 => .riscv32, | |
| 2500 | .riscv32be => .riscv32be, | |
| 2501 | .riscv64 => .riscv64, | |
| 2502 | .riscv64be => .riscv64be, | |
| 2503 | .s390x => .s390x, | |
| 2504 | .sh => .sh, | |
| 2505 | .sheb => .sheb, | |
| 2506 | .sparc => .sparc, | |
| 2507 | .sparc64 => .sparc64, | |
| 2508 | .spirv32 => .spirv32, | |
| 2509 | .spirv64 => .spirv64, | |
| 2510 | .thumb => .thumb, | |
| 2511 | .thumbeb => .thumbeb, | |
| 2512 | .ve => .ve, | |
| 2513 | .wasm32 => .wasm32, | |
| 2514 | .wasm64 => .wasm64, | |
| 2515 | .x86_16 => .x86_16, | |
| 2516 | .x86 => .x86, | |
| 2517 | .x86_64 => .x86_64, | |
| 2518 | .xcore => .xcore, | |
| 2519 | .xtensa => .xtensa, | |
| 2520 | .xtensaeb => .xtensaeb, | |
| 2431 | inline else => |tag| @field(@This(), @tagName(tag)), | |
| 2521 | 2432 | }; |
| 2522 | 2433 | } |
| 2523 | 2434 | |
| 2524 | 2435 | pub fn unwrap(this: @This()) ?std.Target.Cpu.Arch { |
| 2525 | 2436 | return switch (this) { |
| 2526 | .aarch64 => .aarch64, | |
| 2527 | .aarch64_be => .aarch64_be, | |
| 2528 | .alpha => .alpha, | |
| 2529 | .amdgcn => .amdgcn, | |
| 2530 | .arc => .arc, | |
| 2531 | .arceb => .arceb, | |
| 2532 | .arm => .arm, | |
| 2533 | .armeb => .armeb, | |
| 2534 | .avr => .avr, | |
| 2535 | .bpfeb => .bpfeb, | |
| 2536 | .bpfel => .bpfel, | |
| 2537 | .csky => .csky, | |
| 2538 | .ez80 => .ez80, | |
| 2539 | .hexagon => .hexagon, | |
| 2540 | .hppa => .hppa, | |
| 2541 | .hppa64 => .hppa64, | |
| 2542 | .kalimba => .kalimba, | |
| 2543 | .kvx => .kvx, | |
| 2544 | .lanai => .lanai, | |
| 2545 | .loongarch32 => .loongarch32, | |
| 2546 | .loongarch64 => .loongarch64, | |
| 2547 | .m68k => .m68k, | |
| 2548 | .m88k => .m88k, | |
| 2549 | .microblaze => .microblaze, | |
| 2550 | .microblazeel => .microblazeel, | |
| 2551 | .mips => .mips, | |
| 2552 | .mipsel => .mipsel, | |
| 2553 | .mips64 => .mips64, | |
| 2554 | .mips64el => .mips64el, | |
| 2555 | .msp430 => .msp430, | |
| 2556 | .nvptx => .nvptx, | |
| 2557 | .nvptx64 => .nvptx64, | |
| 2558 | .or1k => .or1k, | |
| 2559 | .powerpc => .powerpc, | |
| 2560 | .powerpcle => .powerpcle, | |
| 2561 | .powerpc64 => .powerpc64, | |
| 2562 | .powerpc64le => .powerpc64le, | |
| 2563 | .propeller => .propeller, | |
| 2564 | .riscv32 => .riscv32, | |
| 2565 | .riscv32be => .riscv32be, | |
| 2566 | .riscv64 => .riscv64, | |
| 2567 | .riscv64be => .riscv64be, | |
| 2568 | .s390x => .s390x, | |
| 2569 | .sh => .sh, | |
| 2570 | .sheb => .sheb, | |
| 2571 | .sparc => .sparc, | |
| 2572 | .sparc64 => .sparc64, | |
| 2573 | .spirv32 => .spirv32, | |
| 2574 | .spirv64 => .spirv64, | |
| 2575 | .thumb => .thumb, | |
| 2576 | .thumbeb => .thumbeb, | |
| 2577 | .ve => .ve, | |
| 2578 | .wasm32 => .wasm32, | |
| 2579 | .wasm64 => .wasm64, | |
| 2580 | .x86_16 => .x86_16, | |
| 2581 | .x86 => .x86, | |
| 2582 | .x86_64 => .x86_64, | |
| 2583 | .xcore => .xcore, | |
| 2584 | .xtensa => .xtensa, | |
| 2585 | .xtensaeb => .xtensaeb, | |
| 2586 | ||
| 2437 | inline else => |tag| @field(std.Target.Cpu.Arch, @tagName(tag)), | |
| 2587 | 2438 | .default => null, |
| 2588 | 2439 | }; |
| 2589 | 2440 | } |
| ... | ... | @@ -2642,106 +2493,13 @@ pub const TargetQuery = struct { |
| 2642 | 2493 | |
| 2643 | 2494 | pub fn init(x: ?std.Target.Os.Tag) @This() { |
| 2644 | 2495 | return switch (x orelse return .default) { |
| 2645 | .freestanding => .freestanding, | |
| 2646 | .other => .other, | |
| 2647 | .contiki => .contiki, | |
| 2648 | .fuchsia => .fuchsia, | |
| 2649 | .hermit => .hermit, | |
| 2650 | .managarm => .managarm, | |
| 2651 | .haiku => .haiku, | |
| 2652 | .hurd => .hurd, | |
| 2653 | .illumos => .illumos, | |
| 2654 | .linux => .linux, | |
| 2655 | .plan9 => .plan9, | |
| 2656 | .rtems => .rtems, | |
| 2657 | .serenity => .serenity, | |
| 2658 | .dragonfly => .dragonfly, | |
| 2659 | .freebsd => .freebsd, | |
| 2660 | .netbsd => .netbsd, | |
| 2661 | .openbsd => .openbsd, | |
| 2662 | .driverkit => .driverkit, | |
| 2663 | .ios => .ios, | |
| 2664 | .maccatalyst => .maccatalyst, | |
| 2665 | .macos => .macos, | |
| 2666 | .tvos => .tvos, | |
| 2667 | .visionos => .visionos, | |
| 2668 | .watchos => .watchos, | |
| 2669 | .windows => .windows, | |
| 2670 | .uefi => .uefi, | |
| 2671 | .@"3ds" => .@"3ds", | |
| 2672 | .wiiu => .wiiu, | |
| 2673 | .@"switch" => .@"switch", | |
| 2674 | .psx => .psx, | |
| 2675 | .ps3 => .ps3, | |
| 2676 | .ps4 => .ps4, | |
| 2677 | .ps5 => .ps5, | |
| 2678 | .psp => .psp, | |
| 2679 | .vita => .vita, | |
| 2680 | .emscripten => .emscripten, | |
| 2681 | .wasi => .wasi, | |
| 2682 | .amdhsa => .amdhsa, | |
| 2683 | .amdpal => .amdpal, | |
| 2684 | .cuda => .cuda, | |
| 2685 | .mesa3d => .mesa3d, | |
| 2686 | .nvcl => .nvcl, | |
| 2687 | .opencl => .opencl, | |
| 2688 | .opengl => .opengl, | |
| 2689 | .vulkan => .vulkan, | |
| 2690 | .tios => .tios, | |
| 2691 | .ashetos => .ashetos, | |
| 2496 | inline else => |tag| @field(@This(), @tagName(tag)), | |
| 2692 | 2497 | }; |
| 2693 | 2498 | } |
| 2694 | 2499 | |
| 2695 | 2500 | pub fn unwrap(this: @This()) ?std.Target.Os.Tag { |
| 2696 | 2501 | return switch (this) { |
| 2697 | .freestanding => .freestanding, | |
| 2698 | .other => .other, | |
| 2699 | .contiki => .contiki, | |
| 2700 | .fuchsia => .fuchsia, | |
| 2701 | .hermit => .hermit, | |
| 2702 | .managarm => .managarm, | |
| 2703 | .haiku => .haiku, | |
| 2704 | .hurd => .hurd, | |
| 2705 | .illumos => .illumos, | |
| 2706 | .linux => .linux, | |
| 2707 | .plan9 => .plan9, | |
| 2708 | .rtems => .rtems, | |
| 2709 | .serenity => .serenity, | |
| 2710 | .dragonfly => .dragonfly, | |
| 2711 | .freebsd => .freebsd, | |
| 2712 | .netbsd => .netbsd, | |
| 2713 | .openbsd => .openbsd, | |
| 2714 | .driverkit => .driverkit, | |
| 2715 | .ios => .ios, | |
| 2716 | .maccatalyst => .maccatalyst, | |
| 2717 | .macos => .macos, | |
| 2718 | .tvos => .tvos, | |
| 2719 | .visionos => .visionos, | |
| 2720 | .watchos => .watchos, | |
| 2721 | .windows => .windows, | |
| 2722 | .uefi => .uefi, | |
| 2723 | .@"3ds" => .@"3ds", | |
| 2724 | .wiiu => .wiiu, | |
| 2725 | .@"switch" => .@"switch", | |
| 2726 | .psx => .psx, | |
| 2727 | .ps3 => .ps3, | |
| 2728 | .ps4 => .ps4, | |
| 2729 | .ps5 => .ps5, | |
| 2730 | .psp => .psp, | |
| 2731 | .vita => .vita, | |
| 2732 | .emscripten => .emscripten, | |
| 2733 | .wasi => .wasi, | |
| 2734 | .amdhsa => .amdhsa, | |
| 2735 | .amdpal => .amdpal, | |
| 2736 | .cuda => .cuda, | |
| 2737 | .mesa3d => .mesa3d, | |
| 2738 | .nvcl => .nvcl, | |
| 2739 | .opencl => .opencl, | |
| 2740 | .opengl => .opengl, | |
| 2741 | .vulkan => .vulkan, | |
| 2742 | .tios => .tios, | |
| 2743 | .ashetos => .ashetos, | |
| 2744 | ||
| 2502 | inline else => |tag| @field(std.Target.Os.Tag, @tagName(tag)), | |
| 2745 | 2503 | .default => null, |
| 2746 | 2504 | }; |
| 2747 | 2505 | } |
| ... | ... | @@ -2762,30 +2520,13 @@ pub const TargetQuery = struct { |
| 2762 | 2520 | |
| 2763 | 2521 | pub fn init(x: ?std.Target.ObjectFormat) @This() { |
| 2764 | 2522 | return switch (x orelse return .default) { |
| 2765 | .c => .c, | |
| 2766 | .coff => .coff, | |
| 2767 | .elf => .elf, | |
| 2768 | .hex => .hex, | |
| 2769 | .macho => .macho, | |
| 2770 | .plan9 => .plan9, | |
| 2771 | .raw => .raw, | |
| 2772 | .spirv => .spirv, | |
| 2773 | .wasm => .wasm, | |
| 2523 | inline else => |tag| @field(@This(), @tagName(tag)), | |
| 2774 | 2524 | }; |
| 2775 | 2525 | } |
| 2776 | 2526 | |
| 2777 | 2527 | pub fn unwrap(this: @This()) ?std.Target.ObjectFormat { |
| 2778 | 2528 | return switch (this) { |
| 2779 | .c => .c, | |
| 2780 | .coff => .coff, | |
| 2781 | .elf => .elf, | |
| 2782 | .hex => .hex, | |
| 2783 | .macho => .macho, | |
| 2784 | .plan9 => .plan9, | |
| 2785 | .raw => .raw, | |
| 2786 | .spirv => .spirv, | |
| 2787 | .wasm => .wasm, | |
| 2788 | ||
| 2529 | inline else => |tag| @field(std.Target.ObjectFormat, @tagName(tag)), | |
| 2789 | 2530 | .default => null, |
| 2790 | 2531 | }; |
| 2791 | 2532 | } |
| ... | ... | @@ -3462,6 +3203,7 @@ pub fn load(arena: Allocator, reader: *Io.Reader) LoadError!Configuration { |
| 3462 | 3203 | .system_integrations = try arena.alloc(SystemIntegration, header.system_integrations_len), |
| 3463 | 3204 | .available_options = try arena.alloc(AvailableOption, header.available_options_len), |
| 3464 | 3205 | .search_prefixes = try arena.alloc(String, header.search_prefixes_len), |
| 3206 | .packages = try arena.alloc(Package, header.packages_len), | |
| 3465 | 3207 | .extra = try arena.alloc(u32, header.extra_len), |
| 3466 | 3208 | .default_step = header.default_step, |
| 3467 | 3209 | .generated_files_len = header.generated_files_len, |
| ... | ... | @@ -3475,6 +3217,7 @@ pub fn load(arena: Allocator, reader: *Io.Reader) LoadError!Configuration { |
| 3475 | 3217 | @ptrCast(result.system_integrations), |
| 3476 | 3218 | @ptrCast(result.available_options), |
| 3477 | 3219 | @ptrCast(result.search_prefixes), |
| 3220 | @ptrCast(result.packages), | |
| 3478 | 3221 | @ptrCast(result.extra), |
| 3479 | 3222 | }; |
| 3480 | 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 | 402 | const c_source_files = arena.create(CSourceFiles) catch @panic("OOM"); |
| 403 | 403 | c_source_files.* = .{ |
| 404 | 404 | .root = options.root orelse b.path(""), |
| 405 | .files = b.dupeStrings(options.files), | |
| 406 | .flags = b.dupeStrings(options.flags), | |
| 405 | .files = b.graph.dupeStrings(options.files), | |
| 406 | .flags = b.graph.dupeStrings(options.flags), | |
| 407 | 407 | .language = options.language, |
| 408 | 408 | }; |
| 409 | 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 | 10 | arena: Allocator, |
| 11 | 11 | wc: *Configuration.Wip, |
| 12 | 12 | module_map: std.array_hash_map.Auto(*std.Build.Module, Configuration.Module.Index) = .empty, |
| 13 | package_map: std.array_hash_map.Auto(*std.Build, Configuration.Package.Index) = .empty, | |
| 13 | /// Keyed by package hash. | |
| 14 | package_map: std.array_hash_map.String(Configuration.Package.Index) = .empty, | |
| 14 | 15 | /// Index corresponds to `Configuration.steps` index. |
| 15 | 16 | step_map: std.array_hash_map.Auto(*Step, void) = .empty, |
| 16 | 17 | |
| ... | ... | @@ -21,6 +22,10 @@ pub fn write(b: *std.Build, wc: *Configuration.Wip, writer: *std.Io.Writer) !voi |
| 21 | 22 | |
| 22 | 23 | var s: Serialize = .{ .wc = wc, .arena = arena }; |
| 23 | 24 | |
| 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 | 29 | try wc.path_deps.ensureTotalCapacityPrecise(gpa, graph.configure_dependencies.items.len); |
| 25 | 30 | for ( |
| 26 | 31 | graph.configure_dependencies.items, |
| ... | ... | @@ -44,10 +49,10 @@ pub fn write(b: *std.Build, wc: *Configuration.Wip, writer: *std.Io.Writer) !voi |
| 44 | 49 | .relative => |r| try wc.addString(r.sub_path), |
| 45 | 50 | }, |
| 46 | 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 | 53 | .generated => unreachable, |
| 49 | 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 | 89 | try wc.steps.ensureTotalCapacity(gpa, s.step_map.entries.capacity); |
| 85 | 90 | wc.steps.appendAssumeCapacity(.{ |
| 86 | 91 | .name = try wc.addString(step.name), |
| 87 | .owner = try s.builderToPackage(step.owner), | |
| 92 | .owner = s.packageFromHash(step.owner.pkg_hash), | |
| 88 | 93 | .deps = deps, |
| 89 | 94 | .max_rss = .fromBytes(step.max_rss), |
| 90 | 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 | 173 | .linkage = .init(c.linkage), |
| 169 | 174 | }, |
| 170 | 175 | .flags3 = .{ |
| 171 | .is_linking_libc = c.is_linking_libc, | |
| 172 | .is_linking_libcpp = c.is_linking_libcpp, | |
| 173 | 176 | .version = c.version != null, |
| 174 | 177 | .compress_debug_sections = c.compress_debug_sections, |
| 175 | 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 | 457 | }, |
| 455 | 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 | } | |
| 457 | 467 | |
| 458 | 468 | break :e try wc.addExtraErased(Configuration.Step.Run, .{ |
| 459 | 469 | .flags = .{ |
| ... | ... | @@ -482,6 +492,7 @@ pub fn write(b: *std.Build, wc: *Configuration.Wip, writer: *std.Io.Writer) !voi |
| 482 | 492 | .captured_stdout = run.captured_stdout != null, |
| 483 | 493 | .captured_stderr = run.captured_stderr != null, |
| 484 | 494 | .environ_map = run.environ_map != null, |
| 495 | .preopens = run.preopens.count() > 0, | |
| 485 | 496 | }, |
| 486 | 497 | .flags2 = .{ |
| 487 | 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 | 507 | .file_inputs = .{ .slice = try s.initLazyPathList(run.file_inputs.items) }, |
| 497 | 508 | .args = .{ .slice = try s.initArgsList(run.argv.items) }, |
| 498 | 509 | .cwd = .{ .value = try s.addOptionalLazyPath(run.cwd) }, |
| 499 | .preopen_names = .{ .slice = try s.initStringList(run.preopens.keys()) }, | |
| 500 | .preopen_paths = .{ .slice = try s.initLazyPathList(run.preopens.values()) }, | |
| 510 | .preopens = .{ .slice = preopens }, | |
| 501 | 511 | .captured_stdout = .{ .value = if (run.captured_stdout) |cs| .{ |
| 502 | 512 | .basename = try wc.addString(cs.basename), |
| 503 | 513 | .generated_file = cs.generated_file, |
| ... | ... | @@ -717,19 +727,64 @@ pub fn packageOptions(b: *std.Build, wc: *Configuration.Wip) Allocator.Error!voi |
| 717 | 727 | } |
| 718 | 728 | } |
| 719 | 729 | |
| 720 | fn builderToPackage(s: *Serialize, b: *std.Build) !Configuration.Package.Index { | |
| 721 | if (b.pkg_hash.len == 0) return .root; | |
| 730 | fn addRootPackage(s: *Serialize, b: *std.Build) Allocator.Error!void { | |
| 722 | 731 | const arena = s.arena; |
| 723 | 732 | const wc = s.wc; |
| 724 | const gop = try s.package_map.getOrPut(arena, b); | |
| 725 | if (!gop.found_existing) { | |
| 726 | gop.value_ptr.* = try wc.addExtra(Configuration.Package, .{ | |
| 727 | .hash = try wc.addString(b.pkg_hash), | |
| 728 | .dep_prefix = try wc.addString(b.dep_prefix), | |
| 729 | .root_path = try wc.addString(try b.root.toString(arena)), | |
| 730 | }); | |
| 731 | } | |
| 732 | return gop.value_ptr.*; | |
| 733 | ||
| 734 | try wc.packages.append(wc.gpa, .{ | |
| 735 | .dep_prefix = .empty, | |
| 736 | .hash = .empty, | |
| 737 | .root_path = try wc.addString(try b.root.toString(arena)), | |
| 738 | .deps = undefined, | |
| 739 | }); | |
| 740 | ||
| 741 | const deps = try arena.alloc(Configuration.Package.Dep, b.available_deps.len); | |
| 742 | for (deps, b.available_deps) |*dest, src| dest.* = try s.makePackageDep("", src[0], src[1]); | |
| 743 | ||
| 744 | wc.packages.items[0].deps = try wc.addExtra(Configuration.Package.Dep.List, .{ | |
| 745 | .deps = .{ .slice = deps }, | |
| 746 | }); | |
| 747 | } | |
| 748 | ||
| 749 | fn 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 | ||
| 785 | fn 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 | } |
| 734 | 789 | |
| 735 | 790 | fn addOptionalLazyPathEnum(s: *Serialize, lp: ?std.Build.LazyPath) !Configuration.LazyPath.OptionalIndex { |
| ... | ... | @@ -738,7 +793,7 @@ fn addOptionalLazyPathEnum(s: *Serialize, lp: ?std.Build.LazyPath) !Configuratio |
| 738 | 793 | .src_path => |src_path| i: { |
| 739 | 794 | const sub_path = try wc.addString(src_path.sub_path); |
| 740 | 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 | 797 | .sub_path = sub_path, |
| 743 | 798 | }); |
| 744 | 799 | }, |
| ... | ... | @@ -766,7 +821,7 @@ fn addOptionalLazyPathEnum(s: *Serialize, lp: ?std.Build.LazyPath) !Configuratio |
| 766 | 821 | .dependency => |dependency| i: { |
| 767 | 822 | const sub_path = try wc.addString(dependency.sub_path); |
| 768 | 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 | 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 | 1067 | .producer = .{ .value = null }, |
| 1013 | 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 | 1167 | return result; |
| ... | ... | @@ -1131,7 +1281,7 @@ fn addModule(s: *Serialize, m: *std.Build.Module) !Configuration.Module.Index { |
| 1131 | 1281 | .link_libcpp = .init(m.link_libcpp), |
| 1132 | 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 | 1285 | .root_source_file = try s.addOptionalLazyPathEnum(m.root_source_file), |
| 1136 | 1286 | .import_table = .invalid, |
| 1137 | 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 | 101 | /// This option overrides the CLI argument passed to `zig build`. |
| 102 | 102 | build_id: ?std.zig.BuildId = null, |
| 103 | 103 | |
| 104 | /// Create a .eh_frame_hdr section and a PT_GNU_EH_FRAME segment in the ELF | |
| 104 | /// Create a .eh_frame_hdr section and a PT.GNU_EH_FRAME segment in the ELF | |
| 105 | 105 | /// file. |
| 106 | 106 | link_eh_frame_hdr: bool = false, |
| 107 | 107 | link_emit_relocs: bool = false, |
| ... | ... | @@ -220,11 +220,6 @@ expect_errors: ?ExpectedCompileErrors = null, |
| 220 | 220 | /// `std.math.maxInt(u16)`. Overrides the argument passed to `zig build`. |
| 221 | 221 | error_limit: ?u32 = null, |
| 222 | 222 | |
| 223 | /// Computed during make(). | |
| 224 | is_linking_libc: bool = false, | |
| 225 | /// Computed during make(). | |
| 226 | is_linking_libcpp: bool = false, | |
| 227 | ||
| 228 | 223 | /// Enables coverage instrumentation that is only useful if you are using third |
| 229 | 224 | /// party fuzzers that depend on it. Otherwise, slows down the instrumented |
| 230 | 225 | /// binary with unnecessary function calls. |
| ... | ... | @@ -375,7 +370,7 @@ pub fn create(owner: *std.Build, options: Options) *Compile { |
| 375 | 370 | const graph = owner.graph; |
| 376 | 371 | const arena = graph.arena; |
| 377 | 372 | |
| 378 | const name = owner.dupe(options.name); | |
| 373 | const name = owner.graph.dupeString(options.name); | |
| 379 | 374 | if (mem.find(u8, name, "/") != null or mem.find(u8, name, "\\") != null) { |
| 380 | 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 | 385 | @tagName(options.kind) |
| 391 | 386 | else |
| 392 | 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 | 389 | resolved_target.query.zigTriple(arena) catch @panic("OOM"), |
| 395 | 390 | }); |
| 396 | 391 | |
| ... | ... | @@ -645,7 +640,7 @@ pub fn producesPdbFile(compile: *Compile) bool { |
| 645 | 640 | if (target.ofmt == .c) return false; |
| 646 | 641 | if (compile.use_llvm == false) return false; |
| 647 | 642 | 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 | 645 | return false; |
| 651 | 646 | } |
lib/std/Build/Step/ConfigHeader.zig+4-1| ... | ... | @@ -27,6 +27,9 @@ pub const Style = union(enum) { |
| 27 | 27 | /// The configure format supported by CMake. It uses `@FOO@`, `${}` and |
| 28 | 28 | /// `#cmakedefine` for template substitution. |
| 29 | 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 | 33 | /// Instead of starting with an input file, start with nothing. |
| 31 | 34 | blank, |
| 32 | 35 | /// Start with nothing, like blank, and output a nasm .asm file. |
| ... | ... | @@ -34,7 +37,7 @@ pub const Style = union(enum) { |
| 34 | 37 | |
| 35 | 38 | pub fn getPath(style: Style) ?std.Build.LazyPath { |
| 36 | 39 | switch (style) { |
| 37 | .autoconf_undef, .autoconf_at, .cmake => |s| return s, | |
| 40 | .autoconf_undef, .autoconf_at, .cmake, .meson => |s| return s, | |
| 38 | 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 | 28 | |
| 29 | 29 | /// Named files that will be provided to the parent process. |
| 30 | 30 | /// See `std.process.Preopens`. |
| 31 | preopens: std.array_hash_map.String(Build.LazyPath), | |
| 31 | preopens: std.array_hash_map.Auto(Configuration.String, Build.LazyPath), | |
| 32 | 32 | |
| 33 | 33 | /// Controls the `NO_COLOR` and `CLICOLOR_FORCE` environment variables. |
| 34 | 34 | color: Color = .auto, |
| ... | ... | @@ -68,9 +68,11 @@ rename_step_with_output_arg: bool, |
| 68 | 68 | /// executed binary will not fail the build if the binary cannot be executed |
| 69 | 69 | /// due to being for a foreign binary to the host system which is running the |
| 70 | 70 | /// build graph. |
| 71 | /// | |
| 71 | 72 | /// Command-line arguments such as -fqemu and -fwasmtime may affect whether a |
| 72 | 73 | /// binary is detected as foreign, as well as system configuration such as |
| 73 | 74 | /// Rosetta (macOS) and binfmt_misc (Linux). |
| 75 | /// | |
| 74 | 76 | /// If this Run step is considered to have side-effects, then this flag does |
| 75 | 77 | /// nothing. |
| 76 | 78 | skip_foreign_checks: bool, |
| ... | ... | @@ -149,6 +151,19 @@ pub const Arg = union(enum) { |
| 149 | 151 | output_directory: *Output, |
| 150 | 152 | /// The arguments passed after "--" on the "zig build" CLI. |
| 151 | 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 | ||
| 162 | pub 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 | }; |
| 153 | 168 | |
| 154 | 169 | pub const DecoratedArtifact = struct { |
| ... | ... | @@ -576,6 +591,46 @@ pub fn addPassthruArgs(run: *Run) void { |
| 576 | 591 | run.argv.append(arena, .passthru) catch @panic("OOM"); |
| 577 | 592 | } |
| 578 | 593 | |
| 594 | /// Appends a custom string to the command line depending on the `-fdarling` | |
| 595 | /// value passed to `zig build`. | |
| 596 | pub 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`. | |
| 604 | pub 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`. | |
| 612 | pub 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`. | |
| 620 | pub 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`. | |
| 628 | pub 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 | ||
| 579 | 634 | pub fn setStdIn(run: *Run, stdin: StdIn) void { |
| 580 | 635 | switch (stdin) { |
| 581 | 636 | .lazy_path => |lazy_path| lazy_path.addStepDependencies(&run.step), |
| ... | ... | @@ -624,11 +679,12 @@ pub fn removeEnvironmentVariable(run: *Run, key: []const u8) void { |
| 624 | 679 | |
| 625 | 680 | pub fn setPreopen(run: *Run, name: []const u8, resource: Build.LazyPath) void { |
| 626 | 681 | const graph = run.step.owner.graph; |
| 682 | const wc = &graph.wip_configuration; | |
| 627 | 683 | const arena = graph.arena; |
| 628 | 684 | resource.addStepDependencies(&run.step); |
| 629 | 685 | run.preopens.put( |
| 630 | 686 | arena, |
| 631 | graph.dupeString(name), | |
| 687 | wc.addString(name) catch @panic("OOM"), | |
| 632 | 688 | resource.dupe(graph), |
| 633 | 689 | ) catch @panic("OOM"); |
| 634 | 690 | } |
lib/std/Io.zig+12-6| ... | ... | @@ -238,7 +238,7 @@ pub const VTable = struct { |
| 238 | 238 | netSend: *const fn (?*anyopaque, net.Socket.Handle, []net.OutgoingMessage, net.SendFlags) struct { ?net.Socket.SendError, usize }, |
| 239 | 239 | netWrite: *const fn (?*anyopaque, dest: net.Socket.Handle, header: []const u8, data: []const []const u8, splat: usize) net.Stream.Writer.Error!usize, |
| 240 | 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 | 242 | netShutdown: *const fn (?*anyopaque, handle: net.Socket.Handle, how: net.ShutdownHow) net.ShutdownError!void, |
| 243 | 243 | netInterfaceNameResolve: *const fn (?*anyopaque, *const net.Interface.Name) net.Interface.Name.ResolveError!net.Interface, |
| 244 | 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 | 467 | |
| 468 | 468 | /// Performs one `Operation` with provided `timeout`. |
| 469 | 469 | pub fn operateTimeout(io: Io, operation: Operation, timeout: Timeout) OperateTimeoutError!Operation.Result { |
| 470 | if (timeout == .none) return io.vtable.operate(io.userdata, operation); | |
| 470 | 471 | var storage: [1]Operation.Storage = undefined; |
| 471 | 472 | var batch: Batch = .init(&storage); |
| 472 | 473 | batch.addAt(0, operation); |
| ... | ... | @@ -778,10 +779,10 @@ pub const Clock = enum { |
| 778 | 779 | /// * On Linux, corresponds `CLOCK_BOOTTIME`. |
| 779 | 780 | /// * On macOS, corresponds to `CLOCK_MONOTONIC_RAW`. |
| 780 | 781 | boot, |
| 781 | /// Tracks the amount of CPU in user or kernel mode used by the calling | |
| 782 | /// Tracks the amount of CPU time in user or kernel mode used by the calling | |
| 782 | 783 | /// process. |
| 783 | 784 | cpu_process, |
| 784 | /// Tracks the amount of CPU in user or kernel mode used by the calling | |
| 785 | /// Tracks the amount of CPU time in user or kernel mode used by the calling | |
| 785 | 786 | /// thread. |
| 786 | 787 | cpu_thread, |
| 787 | 788 | |
| ... | ... | @@ -980,6 +981,10 @@ pub const Timestamp = struct { |
| 980 | 981 | const now_ts = clock.now(io); |
| 981 | 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 | }; |
| 984 | 989 | |
| 985 | 990 | pub const Duration = struct { |
| ... | ... | @@ -1147,6 +1152,7 @@ pub const Duration = struct { |
| 1147 | 1152 | |
| 1148 | 1153 | /// Declares under what conditions an operation should return `error.Timeout`. |
| 1149 | 1154 | pub const Timeout = union(enum) { |
| 1155 | /// `.none` will wait forever | |
| 1150 | 1156 | none, |
| 1151 | 1157 | duration: Clock.Duration, |
| 1152 | 1158 | deadline: Clock.Timestamp, |
| ... | ... | @@ -2525,7 +2531,7 @@ pub fn lockStderr(io: Io, buffer: []u8, terminal_mode: ?Terminal.Mode) Cancelabl |
| 2525 | 2531 | |
| 2526 | 2532 | /// Same as `lockStderr` but non-blocking. |
| 2527 | 2533 | pub 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 | 2535 | try ls.clear(buffer); |
| 2530 | 2536 | return ls; |
| 2531 | 2537 | } |
| ... | ... | @@ -3476,9 +3482,9 @@ pub fn failingNetWriteFile(userdata: ?*anyopaque, handle: net.Socket.Handle, hea |
| 3476 | 3482 | return error.NetworkDown; |
| 3477 | 3483 | } |
| 3478 | 3484 | |
| 3479 | pub fn unreachableNetClose(userdata: ?*anyopaque, handle: []const net.Socket.Handle) void { | |
| 3485 | pub fn unreachableNetClose(userdata: ?*anyopaque, sockets: []const net.Socket) void { | |
| 3480 | 3486 | _ = userdata; |
| 3481 | _ = handle; | |
| 3487 | _ = sockets; | |
| 3482 | 3488 | unreachable; |
| 3483 | 3489 | } |
| 3484 | 3490 |
lib/std/Io/Dispatch.zig+9-8| ... | ... | @@ -580,6 +580,7 @@ pub fn deinit(ev: *Evented) void { |
| 580 | 580 | ev.stderr_mutex.deinit(); |
| 581 | 581 | for (&ev.futexes) |*futex| futex.deinit(); |
| 582 | 582 | ev.exit_semaphore.as_object().release(); |
| 583 | ev.backing_allocator_mutex.deinit(); | |
| 583 | 584 | ev.backing_allocator.free(ev.main_loop_stack[0..main_loop_stack_size]); |
| 584 | 585 | ev.queue.as_object().release(); |
| 585 | 586 | } |
| ... | ... | @@ -825,7 +826,7 @@ const Mutex = struct { |
| 825 | 826 | sleeper: Sleeper = undefined, |
| 826 | 827 | cancelable: Cancelable, |
| 827 | 828 | mutex: *Mutex, |
| 828 | node: std.DoublyLinkedList.Node = undefined, | |
| 829 | node: std.DoublyLinkedList.Node = .{}, | |
| 829 | 830 | |
| 830 | 831 | fn add(context: ?*anyopaque) callconv(.c) void { |
| 831 | 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 | 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 | 2786 | if (n > out_buffer.len) return error.NameTooLong; |
| 2786 | 2787 | @memcpy(out_buffer[0..n], buffer[0..n]); |
| 2787 | 2788 | return n; |
| ... | ... | @@ -2803,7 +2804,7 @@ fn dirRealPathFile( |
| 2803 | 2804 | while (true) { |
| 2804 | 2805 | if (c.realpath(sub_path_posix, out_buffer.ptr)) |redundant_pointer| { |
| 2805 | 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 | 2809 | const err: c.E = @fromBackingInt(@intCast(c._errno().*)); |
| 2809 | 2810 | switch (err) { |
| ... | ... | @@ -3791,7 +3792,7 @@ fn fileRealPath(userdata: ?*anyopaque, file: File, out_buffer: []u8) File.RealPa |
| 3791 | 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 | 3796 | if (n > out_buffer.len) return error.NameTooLong; |
| 3796 | 3797 | @memcpy(out_buffer[0..n], buffer[0..n]); |
| 3797 | 3798 | return n; |
| ... | ... | @@ -3897,7 +3898,7 @@ fn fileMemoryMapDestroy(userdata: ?*anyopaque, mm: *File.MemoryMap) void { |
| 3897 | 3898 | if (memory.len == 0) return; |
| 3898 | 3899 | switch (c.errno(c.munmap(memory.ptr, memory.len))) { |
| 3899 | 3900 | .SUCCESS => {}, |
| 3900 | else => |err| if (builtin.mode == .Debug) | |
| 3901 | else => |err| if (builtin.mode == .debug) | |
| 3901 | 3902 | std.log.err("failed to unmap {d} bytes at {*}: {t}", .{ memory.len, memory.ptr, err }), |
| 3902 | 3903 | } |
| 3903 | 3904 | mm.* = undefined; |
| ... | ... | @@ -4714,7 +4715,7 @@ fn sleep(userdata: ?*anyopaque, timeout: Io.Timeout) Io.Cancelable!void { |
| 4714 | 4715 | return ev.yield(.{ .after = ev.timeFromTimeout(timeout) }); |
| 4715 | 4716 | }; |
| 4716 | 4717 | var waiter: SleepWaiter = .{ |
| 4717 | .cancelable = .{ .queue = queue, .cancel = &Futex.Waiter.canceled }, | |
| 4718 | .cancelable = .{ .queue = queue, .cancel = &SleepWaiter.canceled }, | |
| 4718 | 4719 | .timer = timer, |
| 4719 | 4720 | }; |
| 4720 | 4721 | timer.as_object().set_context(&waiter); |
| ... | ... | @@ -4911,10 +4912,10 @@ fn netWriteFileUnavailable( |
| 4911 | 4912 | return error.Unimplemented; |
| 4912 | 4913 | } |
| 4913 | 4914 | |
| 4914 | fn netClose(userdata: ?*anyopaque, handles: []const net.Socket.Handle) void { | |
| 4915 | fn netClose(userdata: ?*anyopaque, sockets: []const net.Socket) void { | |
| 4915 | 4916 | const ev: *Evented = @ptrCast(@alignCast(userdata)); |
| 4916 | 4917 | _ = ev; |
| 4917 | for (handles) |handle| closeFd(handle); | |
| 4918 | for (sockets) |socket| closeFd(socket.handle); | |
| 4918 | 4919 | } |
| 4919 | 4920 | |
| 4920 | 4921 | fn netShutdownUnavailable( |
lib/std/Io/Kqueue.zig+3-2| ... | ... | @@ -1280,10 +1280,10 @@ fn netWrite(userdata: ?*anyopaque, dest: net.Socket.Handle, header: []const u8, |
| 1280 | 1280 | @panic("TODO"); |
| 1281 | 1281 | } |
| 1282 | 1282 | |
| 1283 | fn netClose(userdata: ?*anyopaque, handles: []const net.Socket.Handle) void { | |
| 1283 | fn netClose(userdata: ?*anyopaque, sockets: []const net.Socket) void { | |
| 1284 | 1284 | const k: *Kqueue = @ptrCast(@alignCast(userdata)); |
| 1285 | 1285 | _ = k; |
| 1286 | _ = handles; | |
| 1286 | _ = sockets; | |
| 1287 | 1287 | @panic("TODO"); |
| 1288 | 1288 | } |
| 1289 | 1289 | |
| ... | ... | @@ -1422,6 +1422,7 @@ fn posixBind( |
| 1422 | 1422 | .INTR => continue, |
| 1423 | 1423 | .CANCELED => return error.Canceled, |
| 1424 | 1424 | |
| 1425 | .ACCES => return error.AccessDenied, | |
| 1425 | 1426 | .ADDRINUSE => return error.AddressInUse, |
| 1426 | 1427 | .BADF => |err| return errnoBug(err), // File descriptor used after closed. |
| 1427 | 1428 | .INVAL => |err| return errnoBug(err), // invalid parameters |
lib/std/Io/Reader.zig+3-5| ... | ... | @@ -718,7 +718,7 @@ pub inline fn readSliceEndian( |
| 718 | 718 | endian: std.builtin.Endian, |
| 719 | 719 | ) Error!void { |
| 720 | 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 | } |
| 723 | 723 | |
| 724 | 724 | pub const ReadAllocError = Error || Allocator.Error; |
| ... | ... | @@ -734,8 +734,7 @@ pub inline fn readSliceEndianAlloc( |
| 734 | 734 | ) ReadAllocError![]Elem { |
| 735 | 735 | const dest = try allocator.alloc(Elem, len); |
| 736 | 736 | errdefer allocator.free(dest); |
| 737 | try readSliceAll(r, @ptrCast(dest)); | |
| 738 | if (native_endian != endian) for (dest) |*elem| std.mem.byteSwapAllFields(Elem, elem); | |
| 737 | try r.readSliceEndian(Elem, dest, endian); | |
| 739 | 738 | return dest; |
| 740 | 739 | } |
| 741 | 740 | |
| ... | ... | @@ -1227,8 +1226,7 @@ pub inline fn takeStruct(r: *Reader, comptime T: type, endian: std.builtin.Endia |
| 1227 | 1226 | .auto => @compileError("ill-defined memory layout"), |
| 1228 | 1227 | .@"extern" => { |
| 1229 | 1228 | var res: T = undefined; |
| 1230 | try r.readSliceAll(std.mem.asBytes(&res)); | |
| 1231 | if (native_endian != endian) std.mem.byteSwapAllFields(T, &res); | |
| 1229 | try r.readSliceEndian(T, (&res)[0..1], endian); | |
| 1232 | 1230 | return res; |
| 1233 | 1231 | }, |
| 1234 | 1232 | .@"packed" => { |
lib/std/Io/RwLock.zig-2| ... | ... | @@ -284,8 +284,6 @@ test "concurrent access" { |
| 284 | 284 | } |
| 285 | 285 | |
| 286 | 286 | test "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 | 287 | const io = testing.io; |
| 290 | 288 | |
| 291 | 289 | var rl: Io.RwLock = .init; |
lib/std/Io/Semaphore.zig-2| ... | ... | @@ -4,8 +4,6 @@ |
| 4 | 4 | //! This API supports static initialization and does not require deinitialization. |
| 5 | 5 | const Semaphore = @This(); |
| 6 | 6 | |
| 7 | const builtin = @import("builtin"); | |
| 8 | ||
| 9 | 7 | const std = @import("../std.zig"); |
| 10 | 8 | const Io = std.Io; |
| 11 | 9 | const testing = std.testing; |
lib/std/Io/Threaded.zig+156-38| ... | ... | @@ -4,7 +4,7 @@ const builtin = @import("builtin"); |
| 4 | 4 | const native_os = builtin.os.tag; |
| 5 | 5 | const is_windows = native_os == .windows; |
| 6 | 6 | const is_darwin = native_os.isDarwin(); |
| 7 | const is_debug = builtin.mode == .Debug; | |
| 7 | const is_debug = builtin.mode == .debug; | |
| 8 | 8 | |
| 9 | 9 | const std = @import("../std.zig"); |
| 10 | 10 | const Io = std.Io; |
| ... | ... | @@ -440,12 +440,12 @@ pub const UseFchmodat2 = if (have_fchmodat2 and !have_fchmodat_flags) enum { |
| 440 | 440 | pub const apc_align = @max(default_fn_align, 2); |
| 441 | 441 | |
| 442 | 442 | const default_fn_align = switch (builtin.mode) { |
| 443 | .Debug, .ReleaseSafe, .ReleaseFast => switch (builtin.cpu.arch) { | |
| 443 | .debug, .safe, .fast => switch (builtin.cpu.arch) { | |
| 444 | 444 | else => |arch| @compileError("Unsupported architecture: " ++ @tagName(arch)), |
| 445 | 445 | .arm, .thumb => 4, |
| 446 | 446 | .aarch64, .x86, .x86_64 => 16, |
| 447 | 447 | }, |
| 448 | .ReleaseSmall => 1, | |
| 448 | .small => 1, | |
| 449 | 449 | }; |
| 450 | 450 | |
| 451 | 451 | const Runnable = struct { |
| ... | ... | @@ -829,6 +829,7 @@ const Thread = struct { |
| 829 | 829 | /// Always released when `Status.cancelation` is set to `.parked`. |
| 830 | 830 | futex_waiter: if (use_parking_futex) ?*parking_futex.Waiter else ?noreturn, |
| 831 | 831 | unpark_flag: UnparkFlag, |
| 832 | park_tid: if (ParkTid == std.Thread.Id) void else ParkTid, | |
| 832 | 833 | |
| 833 | 834 | csprng: Csprng, |
| 834 | 835 | |
| ... | ... | @@ -1220,7 +1221,7 @@ const Thread = struct { |
| 1220 | 1221 | parking_futex.removeCanceledWaiter(futex_waiter); |
| 1221 | 1222 | } |
| 1222 | 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 | 1225 | return false; |
| 1225 | 1226 | }, |
| 1226 | 1227 | |
| ... | ... | @@ -1749,6 +1750,7 @@ fn worker(t: *Threaded) void { |
| 1749 | 1750 | .cancel_protection = .unblocked, |
| 1750 | 1751 | .futex_waiter = undefined, |
| 1751 | 1752 | .unpark_flag = unpark_flag_init, |
| 1753 | .park_tid = if (ParkTid == std.Thread.Id) {} else getParkTid(), | |
| 1752 | 1754 | .csprng = .uninitialized, |
| 1753 | 1755 | }; |
| 1754 | 1756 | Thread.current = &thread; |
| ... | ... | @@ -3858,7 +3860,26 @@ fn fileLength(userdata: ?*anyopaque, file: File) File.LengthError!u64 { |
| 3858 | 3860 | } |
| 3859 | 3861 | } |
| 3860 | 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 | } |
| 3863 | 3884 | |
| 3864 | 3885 | const stat = try fileStat(t, file); |
| ... | ... | @@ -4382,7 +4403,7 @@ fn dirCreateFilePosix( |
| 4382 | 4403 | } |
| 4383 | 4404 | }; |
| 4384 | 4405 | |
| 4385 | fl_flags |= @as(usize, 1 << @bitOffsetOf(posix.O, "NONBLOCK")); | |
| 4406 | fl_flags &= ~@as(usize, 1 << @bitOffsetOf(posix.O, "NONBLOCK")); | |
| 4386 | 4407 | |
| 4387 | 4408 | const syscall: Syscall = try .start(); |
| 4388 | 4409 | while (true) { |
| ... | ... | @@ -4978,7 +4999,7 @@ fn dirOpenFilePosix( |
| 4978 | 4999 | } |
| 4979 | 5000 | }; |
| 4980 | 5001 | |
| 4981 | fl_flags |= @as(usize, 1 << @bitOffsetOf(posix.O, "NONBLOCK")); | |
| 5002 | fl_flags &= ~@as(usize, 1 << @bitOffsetOf(posix.O, "NONBLOCK")); | |
| 4982 | 5003 | |
| 4983 | 5004 | const syscall: Syscall = try .start(); |
| 4984 | 5005 | while (true) { |
| ... | ... | @@ -5053,7 +5074,7 @@ pub fn dirOpenFileWtf16( |
| 5053 | 5074 | .VALID_FLAGS, |
| 5054 | 5075 | .OPEN, |
| 5055 | 5076 | .{ |
| 5056 | .IO = if (flags.follow_symlinks) .SYNCHRONOUS_NONALERT else .ASYNCHRONOUS, | |
| 5077 | .IO = .SYNCHRONOUS_NONALERT, | |
| 5057 | 5078 | .NON_DIRECTORY_FILE = !allow_directory, |
| 5058 | 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 | 6838 | if (std.c.realpath(sub_path_posix, out_buffer.ptr)) |redundant_pointer| { |
| 6818 | 6839 | syscall.finish(); |
| 6819 | 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 | 6843 | const err: posix.E = @fromBackingInt(@intCast(std.c._errno().*)); |
| 6823 | 6844 | if (err == .INTR) { |
| ... | ... | @@ -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 | 6986 | if (n > out_buffer.len) return error.NameTooLong; |
| 6966 | 6987 | @memcpy(out_buffer[0..n], sufficient_buffer[0..n]); |
| 6967 | 6988 | return n; |
| ... | ... | @@ -7119,9 +7140,10 @@ fn dirDeleteFileWasi(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8) Dir. |
| 7119 | 7140 | if (builtin.link_libc) return dirDeleteFilePosix(userdata, dir, sub_path); |
| 7120 | 7141 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 7121 | 7142 | _ = t; |
| 7143 | const wasi = std.os.wasi; | |
| 7122 | 7144 | const syscall: Syscall = try .start(); |
| 7123 | 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 | 7147 | switch (res) { |
| 7126 | 7148 | .SUCCESS => { |
| 7127 | 7149 | syscall.finish(); |
| ... | ... | @@ -7131,11 +7153,35 @@ fn dirDeleteFileWasi(userdata: ?*anyopaque, dir: Dir, sub_path: []const u8) Dir. |
| 7131 | 7153 | try syscall.checkCancel(); |
| 7132 | 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 | 7182 | else => |e| { |
| 7135 | 7183 | syscall.finish(); |
| 7136 | 7184 | switch (e) { |
| 7137 | .ACCES => return error.AccessDenied, | |
| 7138 | .PERM => return error.PermissionDenied, | |
| 7139 | 7185 | .BUSY => return error.FileBusy, |
| 7140 | 7186 | .FAULT => |err| return errnoBug(err), |
| 7141 | 7187 | .IO => return error.FileSystem, |
| ... | ... | @@ -8111,7 +8157,7 @@ fn dirReadLinkWindows(dir: Dir, sub_path: []const u8, buffer: []u8) Dir.ReadLink |
| 8111 | 8157 | .{ |
| 8112 | 8158 | .DIRECTORY_FILE = false, |
| 8113 | 8159 | .NON_DIRECTORY_FILE = false, |
| 8114 | .IO = .ASYNCHRONOUS, | |
| 8160 | .IO = .SYNCHRONOUS_NONALERT, | |
| 8115 | 8161 | .OPEN_REPARSE_POINT = true, |
| 8116 | 8162 | }, |
| 8117 | 8163 | null, |
| ... | ... | @@ -8177,7 +8223,7 @@ fn dirReadLinkWindows(dir: Dir, sub_path: []const u8, buffer: []u8) Dir.ReadLink |
| 8177 | 8223 | |
| 8178 | 8224 | var reparse_buf: [windows.MAXIMUM_REPARSE_DATA_BUFFER_SIZE]u8 align(@alignOf(windows.REPARSE_DATA_BUFFER)) = undefined; |
| 8179 | 8225 | switch ((try deviceIoControl(&.{ |
| 8180 | .file = .{ .handle = result_handle, .flags = .{ .nonblocking = true } }, | |
| 8226 | .file = .{ .handle = result_handle, .flags = .{ .nonblocking = false } }, | |
| 8181 | 8227 | .code = .GET_REPARSE_POINT, |
| 8182 | 8228 | .out = &reparse_buf, |
| 8183 | 8229 | })).u.Status) { |
| ... | ... | @@ -8955,7 +9001,7 @@ fn isCygwinPty(file: File) Io.Cancelable!bool { |
| 8955 | 9001 | // The name we get from NtQueryInformationFile will be prefixed with a '\', e.g. \msys-1888ae32e00d56aa-pty0-to-master |
| 8956 | 9002 | return (std.mem.startsWith(u16, name_wide, &[_]u16{ '\\', 'm', 's', 'y', 's', '-' }) or |
| 8957 | 9003 | 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 | } |
| 8960 | 9006 | |
| 8961 | 9007 | fn fileSetLength(userdata: ?*anyopaque, file: File, length: u64) File.SetLengthError!void { |
| ... | ... | @@ -11184,7 +11230,10 @@ fn fileWriteFileStreaming( |
| 11184 | 11230 | var off: std.os.linux.off_t = undefined; |
| 11185 | 11231 | const off_ptr: ?*std.os.linux.off_t, const count: usize = switch (file_reader.mode) { |
| 11186 | 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 | 11237 | off = std.math.cast(std.os.linux.off_t, file_reader.pos) orelse return error.ReadFailed; |
| 11189 | 11238 | break :o .{ &off, @min(@backingInt(limit), size - file_reader.pos, max_count) }; |
| 11190 | 11239 | }, |
| ... | ... | @@ -11533,7 +11582,10 @@ fn fileWriteFilePositional( |
| 11533 | 11582 | if (file_reader.pos != 0) break :fcf; |
| 11534 | 11583 | if (offset != 0) break :fcf; |
| 11535 | 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 | 11589 | if (header.len != 0 or reader_buffered.len != 0) { |
| 11538 | 11590 | const n = try fileWritePositional(t, file, header, &.{limit.slice(reader_buffered)}, 1, offset); |
| 11539 | 11591 | file_reader.interface.toss(n -| header.len); |
| ... | ... | @@ -11725,7 +11777,6 @@ fn nowWasi(clock: Io.Clock) Io.Timestamp { |
| 11725 | 11777 | |
| 11726 | 11778 | fn sleep(userdata: ?*anyopaque, timeout: Io.Timeout) Io.Cancelable!void { |
| 11727 | 11779 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 11728 | if (timeout == .none) return; | |
| 11729 | 11780 | if (use_parking_sleep) return parking_sleep.sleep(timeout); |
| 11730 | 11781 | if (native_os == .wasi) return sleepWasi(t, timeout); |
| 11731 | 11782 | if (@TypeOf(posix.system.clock_nanosleep) != void) return sleepPosix(timeout); |
| ... | ... | @@ -12042,6 +12093,7 @@ fn posixBind( |
| 12042 | 12093 | else => |e| { |
| 12043 | 12094 | syscall.finish(); |
| 12044 | 12095 | switch (e) { |
| 12096 | .ACCES => return error.AccessDenied, | |
| 12045 | 12097 | .ADDRINUSE => return error.AddressInUse, |
| 12046 | 12098 | .BADF => |err| return errnoBug(err), // File descriptor used after closed. |
| 12047 | 12099 | .INVAL => |err| return errnoBug(err), // invalid parameters |
| ... | ... | @@ -12124,6 +12176,7 @@ fn posixConnectUnix( |
| 12124 | 12176 | .NOTDIR => return error.NotDir, |
| 12125 | 12177 | .ROFS => return error.ReadOnlyFileSystem, |
| 12126 | 12178 | .PERM => return error.PermissionDenied, |
| 12179 | .CONNREFUSED => return error.ConnectionRefused, | |
| 12127 | 12180 | |
| 12128 | 12181 | .BADF => |err| return errnoBug(err), // File descriptor used after closed. |
| 12129 | 12182 | .CONNABORTED => |err| return errnoBug(err), |
| ... | ... | @@ -13362,13 +13415,13 @@ fn addBuf(v: []posix.iovec_const, i: *iovlen_t, bytes: []const u8) void { |
| 13362 | 13415 | i.* += 1; |
| 13363 | 13416 | } |
| 13364 | 13417 | |
| 13365 | fn netClose(userdata: ?*anyopaque, handles: []const net.Socket.Handle) void { | |
| 13418 | fn netClose(userdata: ?*anyopaque, sockets: []const net.Socket) void { | |
| 13366 | 13419 | if (!have_networking) unreachable; |
| 13367 | 13420 | const t: *Threaded = @ptrCast(@alignCast(userdata)); |
| 13368 | 13421 | _ = t; |
| 13369 | for (handles) |handle| switch (native_os) { | |
| 13370 | .windows => windows.CloseHandle(handle), | |
| 13371 | else => closeFd(handle), | |
| 13422 | for (sockets) |socket| switch (native_os) { | |
| 13423 | .windows => windows.CloseHandle(socket.handle), | |
| 13424 | else => closeFd(socket.handle), | |
| 13372 | 13425 | }; |
| 13373 | 13426 | } |
| 13374 | 13427 | |
| ... | ... | @@ -13870,9 +13923,14 @@ fn netLookupFallible( |
| 13870 | 13923 | var port_buffer: [8]u8 = undefined; |
| 13871 | 13924 | const port_c = std.fmt.bufPrintSentinel(&port_buffer, "{d}", .{options.port}, 0) catch unreachable; |
| 13872 | 13925 | |
| 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 | 13931 | const hints: posix.addrinfo = .{ |
| 13874 | 13932 | .flags = .{ .CANONNAME = options.canonical_name_buffer != null, .NUMERICSERV = true }, |
| 13875 | .family = posix.AF.UNSPEC, | |
| 13933 | .family = family, | |
| 13876 | 13934 | .socktype = posix.SOCK.STREAM, |
| 13877 | 13935 | .protocol = posix.IPPROTO.TCP, |
| 13878 | 13936 | .canonname = null, |
| ... | ... | @@ -15302,8 +15360,7 @@ fn childKillWindows(t: *Threaded, child: *process.Child, exit_code: windows.UINT |
| 15302 | 15360 | _ = windows.ntdll.RtlReportSilentProcessExit(handle, @fromBackingInt(@intCast(exit_code))); |
| 15303 | 15361 | switch (windows.ntdll.NtTerminateProcess(handle, @fromBackingInt(@intCast(exit_code)))) { |
| 15304 | 15362 | .SUCCESS, .PROCESS_IS_TERMINATING => { |
| 15305 | const infinite_timeout: windows.LARGE_INTEGER = std.math.minInt(windows.LARGE_INTEGER); | |
| 15306 | _ = windows.ntdll.NtWaitForSingleObject(handle, .FALSE, &infinite_timeout); | |
| 15363 | _ = windows.ntdll.NtWaitForSingleObject(handle, .FALSE, null); | |
| 15307 | 15364 | childCleanupWindows(child); |
| 15308 | 15365 | }, |
| 15309 | 15366 | .ACCESS_DENIED => { |
| ... | ... | @@ -15326,8 +15383,7 @@ fn childWaitWindows(child: *process.Child) process.Child.WaitError!process.Child |
| 15326 | 15383 | const handle = child.id.?; |
| 15327 | 15384 | |
| 15328 | 15385 | const alertable_syscall: AlertableSyscall = try .start(); |
| 15329 | const infinite_timeout: windows.LARGE_INTEGER = std.math.minInt(windows.LARGE_INTEGER); | |
| 15330 | while (true) switch (windows.ntdll.NtWaitForSingleObject(handle, .TRUE, &infinite_timeout)) { | |
| 15386 | while (true) switch (windows.ntdll.NtWaitForSingleObject(handle, .TRUE, null)) { | |
| 15331 | 15387 | windows.NTSTATUS.WAIT_0 => break alertable_syscall.finish(), |
| 15332 | 15388 | .USER_APC, .ALERTED, .TIMEOUT => { |
| 15333 | 15389 | try alertable_syscall.checkCancel(); |
| ... | ... | @@ -16272,7 +16328,7 @@ fn windowsCreateProcessPathExt( |
| 16272 | 16328 | |
| 16273 | 16329 | const is_bat_or_cmd = bat_or_cmd: { |
| 16274 | 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 | 16332 | const ext = app_name[ext_start..]; |
| 16277 | 16333 | const ext_enum = windowsCreateProcessSupportsExtension(ext) orelse break :bat_or_cmd false; |
| 16278 | 16334 | switch (ext_enum) { |
| ... | ... | @@ -16308,7 +16364,7 @@ fn windowsCreateProcessPathExt( |
| 16308 | 16364 | // it's treated as an unrecoverable error. Otherwise, it'll be |
| 16309 | 16365 | // skipped as normal. |
| 16310 | 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 | 16368 | const ext = app_name[ext_start..]; |
| 16313 | 16369 | if (windows.eqlIgnoreCaseWtf16(ext, std.unicode.utf8ToUtf16LeStringLiteral(".EXE"))) { |
| 16314 | 16370 | return error.UnrecoverableInvalidExe; |
| ... | ... | @@ -17387,6 +17443,7 @@ const use_parking_futex = switch (native_os) { |
| 17387 | 17443 | .windows => true, // RtlWaitOnAddress is a userland implementation anyway |
| 17388 | 17444 | .netbsd => true, // NetBSD has `futex(2)`, but it's historically been quite buggy. TODO: evaluate whether it's okay to use now. |
| 17389 | 17445 | .illumos => true, // Illumos has no futex mechanism |
| 17446 | .haiku => true, // Haiku has no futex mechanism | |
| 17390 | 17447 | else => false, |
| 17391 | 17448 | }; |
| 17392 | 17449 | const use_parking_sleep = switch (native_os) { |
| ... | ... | @@ -17432,7 +17489,7 @@ const parking_futex = struct { |
| 17432 | 17489 | const Waiter = struct { |
| 17433 | 17490 | node: std.DoublyLinkedList.Node, |
| 17434 | 17491 | address: usize, |
| 17435 | tid: std.Thread.Id, | |
| 17492 | tid: ParkTid, | |
| 17436 | 17493 | /// `thread_status.cancelation` is `.parked` while the thread is waiting. The single thread |
| 17437 | 17494 | /// which atomically updates it (to `.none` or `.canceling`) is responsible for: |
| 17438 | 17495 | /// |
| ... | ... | @@ -17473,7 +17530,7 @@ const parking_futex = struct { |
| 17473 | 17530 | |
| 17474 | 17531 | // Put the threadlocal access outside of the critical section. |
| 17475 | 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(); | |
| 17477 | 17534 | |
| 17478 | 17535 | var waiter: Waiter = .{ |
| 17479 | 17536 | .node = undefined, // populated by list append |
| ... | ... | @@ -17721,7 +17778,12 @@ const parking_sleep = struct { |
| 17721 | 17778 | }, |
| 17722 | 17779 | } |
| 17723 | 17780 | } |
| 17781 | ||
| 17724 | 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 | 17787 | var dummy_flag: UnparkFlag = unpark_flag_init; |
| 17726 | 17788 | if (park(timeout, null, if (need_unpark_flag) &dummy_flag)) { |
| 17727 | 17789 | unreachable; // unexpected unpark |
| ... | ... | @@ -17760,7 +17822,7 @@ const ParkingMutex = struct { |
| 17760 | 17822 | /// Never modified once the `Waiter` is in the linked list. |
| 17761 | 17823 | next: ?*Waiter, |
| 17762 | 17824 | /// Never modified once the `Waiter` is in the linked list. |
| 17763 | tid: std.Thread.Id, | |
| 17825 | tid: ParkTid, | |
| 17764 | 17826 | }; |
| 17765 | 17827 | fn lock(m: *ParkingMutex) void { |
| 17766 | 17828 | state: switch (State.unlocked) { // assume 'unlocked' to optimize for uncontended case |
| ... | ... | @@ -17776,7 +17838,7 @@ const ParkingMutex = struct { |
| 17776 | 17838 | |
| 17777 | 17839 | .locked_once, _ => |last_state| { |
| 17778 | 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 | 17842 | var waiter: Waiter = .{ |
| 17781 | 17843 | .next = old_waiter, |
| 17782 | 17844 | .unpark_flag = unpark_flag_init, |
| ... | ... | @@ -17904,9 +17966,36 @@ fn setUnparkFlag(f: *UnparkFlag) void { |
| 17904 | 17966 | /// but it seems that someone at Microsoft forgot how big their TIDs are supposed to be. |
| 17905 | 17967 | const UnparkTid = switch (native_os) { |
| 17906 | 17968 | .windows => usize, |
| 17969 | else => ParkTid, | |
| 17970 | }; | |
| 17971 | ||
| 17972 | const ParkTid = switch (native_os) { | |
| 17973 | .haiku => std.c.sem_id, | |
| 17907 | 17974 | else => std.Thread.Id, |
| 17908 | 17975 | }; |
| 17909 | 17976 | |
| 17977 | threadlocal var park_sem: std.c.sem_id = -1; | |
| 17978 | ||
| 17979 | fn 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 | ||
| 17995 | fn destroyParkSem(_: ?*anyopaque) callconv(.c) void { | |
| 17996 | _ = std.c._kern_delete_sem(park_sem); | |
| 17997 | } | |
| 17998 | ||
| 17910 | 17999 | fn park( |
| 17911 | 18000 | timeout: Io.Timeout, |
| 17912 | 18001 | /// This value has no semantic effect, but may allow the OS to optimize the operation. |
| ... | ... | @@ -17972,6 +18061,27 @@ fn park( |
| 17972 | 18061 | } |
| 17973 | 18062 | }, |
| 17974 | 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 | 18085 | else => comptime unreachable, |
| 17976 | 18086 | } |
| 17977 | 18087 | } |
| ... | ... | @@ -18014,6 +18124,14 @@ fn unpark(tids: []const UnparkTid, addr_hint: ?*const anyopaque) void { |
| 18014 | 18124 | } |
| 18015 | 18125 | }, |
| 18016 | 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 | 18135 | else => comptime unreachable, |
| 18018 | 18136 | } |
| 18019 | 18137 | } |
| ... | ... | @@ -18171,7 +18289,7 @@ fn fileMemoryMapCreate( |
| 18171 | 18289 | error.Unseekable, error.Canceled, error.AccessDenied => |e| return e, |
| 18172 | 18290 | error.OperationUnsupported => {}, |
| 18173 | 18291 | else => { |
| 18174 | if (builtin.mode == .Debug) | |
| 18292 | if (builtin.mode == .debug) | |
| 18175 | 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 | 18396 | .INVALID_VIEW_SIZE => |status| return windows.statusBug(status), |
| 18279 | 18397 | else => |status| return windows.unexpectedStatus(status), |
| 18280 | 18398 | } |
| 18281 | if (builtin.mode == .Debug) { | |
| 18399 | if (builtin.mode == .debug) { | |
| 18282 | 18400 | const page_size = std.heap.pageSize(); |
| 18283 | 18401 | const alignment: Alignment = .fromByteUnits(page_size); |
| 18284 | 18402 | assert(contents_len == alignment.forward(len)); |
| ... | ... | @@ -18369,7 +18487,7 @@ fn fileMemoryMapDestroy(userdata: ?*anyopaque, mm: *File.MemoryMap) void { |
| 18369 | 18487 | switch (posix.errno(posix.system.munmap(memory.ptr, memory.len))) { |
| 18370 | 18488 | .SUCCESS => {}, |
| 18371 | 18489 | else => |e| { |
| 18372 | if (builtin.mode == .Debug) | |
| 18490 | if (builtin.mode == .debug) | |
| 18373 | 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 | 19087 | .{ |
| 18970 | 19088 | .DIRECTORY_FILE = options.filter == .dir_only, |
| 18971 | 19089 | .NON_DIRECTORY_FILE = options.filter == .non_directory_only, |
| 18972 | .IO = if (options.follow_symlinks) .SYNCHRONOUS_NONALERT else .ASYNCHRONOUS, | |
| 19090 | .IO = .SYNCHRONOUS_NONALERT, | |
| 18973 | 19091 | .OPEN_REPARSE_POINT = !options.follow_symlinks, |
| 18974 | 19092 | }, |
| 18975 | 19093 | null, |
lib/std/Io/Threaded/test.zig-2| ... | ... | @@ -149,8 +149,6 @@ test "async with array return type" { |
| 149 | 149 | } |
| 150 | 150 | |
| 151 | 151 | test "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 | 152 | const global = struct { |
| 155 | 153 | fn readFromPipe(io: Io, pipe: Io.File) !void { |
| 156 | 154 | var buf: [1]u8 = undefined; |
lib/std/Io/Uring.zig+14-8| ... | ... | @@ -1135,8 +1135,9 @@ fn mainIdleEntry() callconv(.naked) void { |
| 1135 | 1135 | |
| 1136 | 1136 | fn mainIdle( |
| 1137 | 1137 | ev: *Evented, |
| 1138 | message: *const SwitchMessage, | |
| 1138 | contexts: *const Io.fiber.Switch, | |
| 1139 | 1139 | ) callconv(.withStackAlign(.c, @max(@alignOf(Thread), @alignOf(Io.fiber.Context)))) noreturn { |
| 1140 | const message: *const SwitchMessage = @fieldParentPtr("contexts", contexts); | |
| 1140 | 1141 | message.handle(ev); |
| 1141 | 1142 | ev.idle(&ev.threads.allocated[0]); |
| 1142 | 1143 | ev.yield(@ptrCast(&ev.main_fiber_buffer), .nothing); |
| ... | ... | @@ -1414,8 +1415,9 @@ const AsyncClosure = struct { |
| 1414 | 1415 | |
| 1415 | 1416 | fn call( |
| 1416 | 1417 | closure: *AsyncClosure, |
| 1417 | message: *const SwitchMessage, | |
| 1418 | contexts: *const Io.fiber.Switch, | |
| 1418 | 1419 | ) callconv(.withStackAlign(.c, @alignOf(AsyncClosure))) noreturn { |
| 1420 | const message: *const SwitchMessage = @fieldParentPtr("contexts", contexts); | |
| 1419 | 1421 | const ev = closure.evented; |
| 1420 | 1422 | const fiber = closure.fiber; |
| 1421 | 1423 | message.handle(ev); |
| ... | ... | @@ -1779,8 +1781,9 @@ const Group = struct { |
| 1779 | 1781 | |
| 1780 | 1782 | fn call( |
| 1781 | 1783 | closure: *Group.AsyncClosure, |
| 1782 | message: *const SwitchMessage, | |
| 1784 | contexts: *const Io.fiber.Switch, | |
| 1783 | 1785 | ) callconv(.withStackAlign(.c, @alignOf(Group.AsyncClosure))) noreturn { |
| 1786 | const message: *const SwitchMessage = @fieldParentPtr("contexts", contexts); | |
| 1784 | 1787 | const ev = closure.evented; |
| 1785 | 1788 | const fiber = closure.fiber; |
| 1786 | 1789 | message.handle(ev); |
| ... | ... | @@ -3558,7 +3561,7 @@ fn dirHardLink( |
| 3558 | 3561 | old_sub_path_posix, |
| 3559 | 3562 | new_dir.handle, |
| 3560 | 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 | } |
| 3564 | 3567 | |
| ... | ... | @@ -3990,7 +3993,7 @@ fn fileHardLink( |
| 3990 | 3993 | "", |
| 3991 | 3994 | new_dir.handle, |
| 3992 | 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 | } |
| 3996 | 3999 | |
| ... | ... | @@ -4050,7 +4053,7 @@ fn fileMemoryMapDestroy(userdata: ?*anyopaque, mm: *File.MemoryMap) void { |
| 4050 | 4053 | if (memory.len == 0) return; |
| 4051 | 4054 | switch (linux.errno(linux.munmap(memory.ptr, memory.len))) { |
| 4052 | 4055 | .SUCCESS => {}, |
| 4053 | else => |err| if (builtin.mode == .Debug) | |
| 4056 | else => |err| if (builtin.mode == .debug) | |
| 4054 | 4057 | std.log.err("failed to unmap {d} bytes at {*}: {t}", .{ memory.len, memory.ptr, err }), |
| 4055 | 4058 | } |
| 4056 | 4059 | mm.* = undefined; |
| ... | ... | @@ -5186,9 +5189,9 @@ fn netWriteFileUnavailable( |
| 5186 | 5189 | return error.Unimplemented; |
| 5187 | 5190 | } |
| 5188 | 5191 | |
| 5189 | fn netClose(userdata: ?*anyopaque, handles: []const net.Socket.Handle) void { | |
| 5192 | fn netClose(userdata: ?*anyopaque, sockets: []const net.Socket) void { | |
| 5190 | 5193 | const ev: *Evented = @ptrCast(@alignCast(userdata)); |
| 5191 | for (handles) |handle| ev.close(handle); | |
| 5194 | for (sockets) |sock| ev.close(sock.handle); | |
| 5192 | 5195 | } |
| 5193 | 5196 | |
| 5194 | 5197 | fn netShutdown( |
| ... | ... | @@ -5295,6 +5298,7 @@ fn bind( |
| 5295 | 5298 | switch (cancel_region.errno()) { |
| 5296 | 5299 | .SUCCESS => return, |
| 5297 | 5300 | .INTR, .CANCELED => {}, |
| 5301 | .ACCES => return error.AccessDenied, | |
| 5298 | 5302 | .ADDRINUSE => return error.AddressInUse, |
| 5299 | 5303 | .BADF => |err| return errnoBug(err), // File descriptor used after closed. |
| 5300 | 5304 | .INVAL => |err| return errnoBug(err), // invalid parameters |
| ... | ... | @@ -5542,6 +5546,8 @@ fn linkat( |
| 5542 | 5546 | new_path: [*:0]const u8, |
| 5543 | 5547 | flags: u32, |
| 5544 | 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 | 5551 | while (true) { |
| 5546 | 5552 | const thread = try cancel_region.awaitIoUring(); |
| 5547 | 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 | 874 | } |
| 875 | 875 | |
| 876 | 876 | /// Asserts the `buffer` was initialized with a capacity of at least `@sizeOf(T)` bytes. |
| 877 | pub inline fn writeInt(w: *Writer, comptime T: type, value: T, endian: std.builtin.Endian) Error!void { | |
| 877 | pub inline fn writeInt(w: *Writer, comptime T: type, value: T, endian: std.lang.Endian) Error!void { | |
| 878 | 878 | var bytes: [@divExact(@typeInfo(T).int.bits, 8)]u8 = undefined; |
| 879 | 879 | std.mem.writeInt(std.math.ByteAlignedInt(@TypeOf(value)), &bytes, value, endian); |
| 880 | 880 | return w.writeAll(&bytes); |
| ... | ... | @@ -882,7 +882,7 @@ pub inline fn writeInt(w: *Writer, comptime T: type, value: T, endian: std.built |
| 882 | 882 | |
| 883 | 883 | /// The function is inline to avoid the dead code in case `endian` is |
| 884 | 884 | /// comptime-known and matches host endianness. |
| 885 | pub inline fn writeStruct(w: *Writer, value: anytype, endian: std.builtin.Endian) Error!void { | |
| 885 | pub inline fn writeStruct(w: *Writer, value: anytype, endian: std.lang.Endian) Error!void { | |
| 886 | 886 | switch (@typeInfo(@TypeOf(value))) { |
| 887 | 887 | .@"struct" => |info| switch (info.layout) { |
| 888 | 888 | .auto => @compileError("ill-defined memory layout"), |
| ... | ... | @@ -907,7 +907,7 @@ pub inline fn writeSliceEndian( |
| 907 | 907 | w: *Writer, |
| 908 | 908 | Elem: type, |
| 909 | 909 | slice: []const Elem, |
| 910 | endian: std.builtin.Endian, | |
| 910 | endian: std.lang.Endian, | |
| 911 | 911 | ) Error!void { |
| 912 | 912 | switch (@typeInfo(Elem)) { |
| 913 | 913 | .@"struct" => |info| comptime assert(info.layout != .auto), |
| ... | ... | @@ -2387,6 +2387,7 @@ pub fn unreachableRebase(w: *Writer, preserve: usize, capacity: usize) Error!voi |
| 2387 | 2387 | |
| 2388 | 2388 | pub fn fromArrayList(array_list: *ArrayList(u8)) Writer { |
| 2389 | 2389 | defer array_list.* = .empty; |
| 2390 | array_list.pointer_stability.assertUnlocked(); | |
| 2390 | 2391 | return .{ |
| 2391 | 2392 | .vtable = &.{ |
| 2392 | 2393 | .drain = fixedDrain, |
| ... | ... | @@ -2402,6 +2403,7 @@ pub fn toArrayList(w: *Writer) ArrayList(u8) { |
| 2402 | 2403 | const result: ArrayList(u8) = .{ |
| 2403 | 2404 | .items = w.buffer[0..w.end], |
| 2404 | 2405 | .capacity = w.buffer.len, |
| 2406 | .pointer_stability = .{}, | |
| 2405 | 2407 | }; |
| 2406 | 2408 | w.buffer = &.{}; |
| 2407 | 2409 | w.end = 0; |
| ... | ... | @@ -2651,6 +2653,7 @@ pub const Allocating = struct { |
| 2651 | 2653 | const result: std.array_list.Aligned(u8, alignment) = .{ |
| 2652 | 2654 | .items = @alignCast(w.buffer[0..w.end]), |
| 2653 | 2655 | .capacity = w.buffer.len, |
| 2656 | .pointer_stability = .{}, | |
| 2654 | 2657 | }; |
| 2655 | 2658 | w.buffer = &.{}; |
| 2656 | 2659 | w.end = 0; |
| ... | ... | @@ -2742,29 +2745,26 @@ pub const Allocating = struct { |
| 2742 | 2745 | |
| 2743 | 2746 | fn drain(w: *Writer, data: []const []const u8, splat: usize) Error!usize { |
| 2744 | 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 | 2748 | assert(data.len != 0); |
| 2749 | for (data) |bytes| { | |
| 2750 | a.ensureUnusedCapacity(bytes.len + splat_len + 1) catch return error.WriteFailed; | |
| 2749 | const count = countSplat(data, splat); | |
| 2750 | a.ensureUnusedCapacity(count + 1) catch return error.WriteFailed; | |
| 2751 | for (data[0 .. data.len - 1]) |bytes| { | |
| 2751 | 2752 | @memcpy(a.writer.buffer[a.writer.end..][0..bytes.len], bytes); |
| 2752 | 2753 | a.writer.end += bytes.len; |
| 2753 | 2754 | } |
| 2754 | if (splat == 0) { | |
| 2755 | a.writer.end -= pattern.len; | |
| 2756 | } else switch (pattern.len) { | |
| 2755 | const pattern = data[data.len - 1]; | |
| 2756 | switch (pattern.len) { | |
| 2757 | 2757 | 0 => {}, |
| 2758 | 2758 | 1 => { |
| 2759 | @memset(a.writer.buffer[a.writer.end..][0 .. splat - 1], pattern[0]); | |
| 2760 | a.writer.end += splat - 1; | |
| 2759 | @memset(a.writer.buffer[a.writer.end..][0..splat], pattern[0]); | |
| 2760 | a.writer.end += splat; | |
| 2761 | 2761 | }, |
| 2762 | else => for (0..splat - 1) |_| { | |
| 2762 | else => for (0..splat) |_| { | |
| 2763 | 2763 | @memcpy(a.writer.buffer[a.writer.end..][0..pattern.len], pattern); |
| 2764 | 2764 | a.writer.end += pattern.len; |
| 2765 | 2765 | }, |
| 2766 | 2766 | } |
| 2767 | return a.writer.end - start_len; | |
| 2767 | return count; | |
| 2768 | 2768 | } |
| 2769 | 2769 | |
| 2770 | 2770 | fn sendFile(w: *Writer, file_reader: *File.Reader, limit: Limit) FileError!usize { |
| ... | ... | @@ -2817,12 +2817,12 @@ pub const Allocating = struct { |
| 2817 | 2817 | } |
| 2818 | 2818 | |
| 2819 | 2819 | test Allocating { |
| 2820 | try testAllocating(.fromByteUnits(1)); | |
| 2821 | try testAllocating(.fromByteUnits(4)); | |
| 2822 | try testAllocating(.fromByteUnits(8)); | |
| 2823 | try testAllocating(.fromByteUnits(16)); | |
| 2824 | try testAllocating(.fromByteUnits(32)); | |
| 2825 | try testAllocating(.fromByteUnits(64)); | |
| 2820 | try testAllocating(.@"1"); | |
| 2821 | try testAllocating(.@"4"); | |
| 2822 | try testAllocating(.@"8"); | |
| 2823 | try testAllocating(.@"16"); | |
| 2824 | try testAllocating(.@"32"); | |
| 2825 | try testAllocating(.@"64"); | |
| 2826 | 2826 | } |
| 2827 | 2827 | }; |
| 2828 | 2828 |
lib/std/Io/net.zig+7-2| ... | ... | @@ -198,6 +198,8 @@ pub const IpAddress = union(enum) { |
| 198 | 198 | } |
| 199 | 199 | |
| 200 | 200 | pub const ListenError = error{ |
| 201 | /// The address is protected and the current user does not have permission to bind it. | |
| 202 | AccessDenied, | |
| 201 | 203 | /// The address is already taken. Can occur when bound port is 0 but |
| 202 | 204 | /// all ephemeral ports are already in use. |
| 203 | 205 | AddressInUse, |
| ... | ... | @@ -254,6 +256,8 @@ pub const IpAddress = union(enum) { |
| 254 | 256 | } |
| 255 | 257 | |
| 256 | 258 | pub const BindError = error{ |
| 259 | /// The address is protected and the current user does not have permission to bind it. | |
| 260 | AccessDenied, | |
| 257 | 261 | /// The address is already taken. Can occur when bound port is 0 but |
| 258 | 262 | /// all ephemeral ports are already in use. |
| 259 | 263 | AddressInUse, |
| ... | ... | @@ -901,6 +905,7 @@ pub const UnixAddress = struct { |
| 901 | 905 | ReadOnlyFileSystem, |
| 902 | 906 | WouldBlock, |
| 903 | 907 | NetworkDown, |
| 908 | ConnectionRefused, | |
| 904 | 909 | } || Io.Cancelable || Io.UnexpectedError; |
| 905 | 910 | |
| 906 | 911 | pub fn connect(ua: *const UnixAddress, io: Io) ConnectError!Stream { |
| ... | ... | @@ -1076,7 +1081,7 @@ pub const Socket = struct { |
| 1076 | 1081 | |
| 1077 | 1082 | /// Leaves `address` in a valid state. |
| 1078 | 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 | } |
| 1081 | 1086 | |
| 1082 | 1087 | pub fn closeMany(io: Io, sockets: []const Socket) void { |
| ... | ... | @@ -1253,7 +1258,7 @@ pub const Stream = struct { |
| 1253 | 1258 | } |
| 1254 | 1259 | |
| 1255 | 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 | } |
| 1258 | 1263 | |
| 1259 | 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 | 356 | } |
| 357 | 357 | |
| 358 | 358 | test "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 | 359 | const io = testing.io; |
| 362 | 360 | const localhost: net.IpAddress = .{ .ip4 = .loopback(0) }; |
| 363 | 361 |
lib/std/Io/test.zig-4| ... | ... | @@ -232,8 +232,6 @@ fn count(a: usize, b: usize, result: *usize) void { |
| 232 | 232 | } |
| 233 | 233 | |
| 234 | 234 | test "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 | 235 | const global = struct { |
| 238 | 236 | fn sleep(io: Io, result: *usize) Io.Cancelable!void { |
| 239 | 237 | defer result.* = 1; |
| ... | ... | @@ -326,8 +324,6 @@ test "Group materializes error.Cancel" { |
| 326 | 324 | } |
| 327 | 325 | |
| 328 | 326 | test "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 | 327 | const S = struct { |
| 332 | 328 | io: Io, |
| 333 | 329 | err: ?Io.Cancelable!void, |
lib/std/Progress.zig+14-2| ... | ... | @@ -442,7 +442,15 @@ pub const Node = struct { |
| 442 | 442 | global_progress.ipc_files[slot] = file; |
| 443 | 443 | storageByIndex(index).setIpcIndex(.{ .slot = slot, .generation = generation }); |
| 444 | 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 | } |
| 447 | 455 | |
| 448 | 456 | pub fn setIpcIndex(node: Node, ipc_index: Ipc.Index) void { |
| ... | ... | @@ -452,7 +460,11 @@ pub const Node = struct { |
| 452 | 460 | /// Not thread-safe. |
| 453 | 461 | pub fn takeIpcIndex(node: Node) ?Ipc.Index { |
| 454 | 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 | 468 | @atomicStore(u32, &storage.estimated_total_count, 0, .monotonic); |
| 457 | 469 | return @bitCast(storage.completed_count); |
| 458 | 470 | } |
lib/std/Random/RomuTrio.zig-1| ... | ... | @@ -122,7 +122,6 @@ test fill { |
| 122 | 122 | } |
| 123 | 123 | |
| 124 | 124 | test "buf seeding test" { |
| 125 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 126 | 125 | const buf0: [24]u8 = @bitCast([3]u64{ 16294208416658607535, 13964609475759908645, 4703697494102998476 }); |
| 127 | 126 | const resulting_state = .{ .x = 16294208416658607535, .y = 13964609475759908645, .z = 4703697494102998476 }; |
| 128 | 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 | 89 | } |
| 90 | 90 | |
| 91 | 91 | test "sequence" { |
| 92 | if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; | |
| 93 | ||
| 94 | 92 | var r = Xoshiro256.init(0); |
| 95 | 93 | |
| 96 | 94 | const seq1 = [_]u64{ |
lib/std/Random/benchmark.zig+1-1| ... | ... | @@ -122,7 +122,7 @@ fn usage() void { |
| 122 | 122 | } |
| 123 | 123 | |
| 124 | 124 | fn 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 | } |
| 127 | 127 | |
| 128 | 128 | pub 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 | 1194 | }; |
| 1195 | 1195 | } |
| 1196 | 1196 | |
| 1197 | /// Deprecated; use 'std.zig.Subsystem' instead. To be removed after 0.16.0 is tagged. | |
| 1198 | pub const SubSystem = std.zig.Subsystem; | |
| 1199 | ||
| 1200 | 1197 | pub const Cpu = struct { |
| 1201 | 1198 | /// Architecture |
| 1202 | 1199 | arch: Arch, |
| ... | ... | @@ -1796,10 +1793,12 @@ pub const Cpu = struct { |
| 1796 | 1793 | .x86_64_regcall_v4_win, |
| 1797 | 1794 | .x86_64_vectorcall, |
| 1798 | 1795 | .x86_64_interrupt, |
| 1796 | .x86_64_preserve_none, | |
| 1799 | 1797 | => &.{.x86_64}, |
| 1800 | 1798 | |
| 1801 | 1799 | .x86_sysv, |
| 1802 | 1800 | .x86_win, |
| 1801 | .x86_mingw, | |
| 1803 | 1802 | .x86_stdcall, |
| 1804 | 1803 | .x86_fastcall, |
| 1805 | 1804 | .x86_thiscall, |
| ... | ... | @@ -1821,6 +1820,7 @@ pub const Cpu = struct { |
| 1821 | 1820 | .aarch64_aapcs_win, |
| 1822 | 1821 | .aarch64_vfabi, |
| 1823 | 1822 | .aarch64_vfabi_sve, |
| 1823 | .aarch64_preserve_none, | |
| 1824 | 1824 | => &.{ .aarch64, .aarch64_be }, |
| 1825 | 1825 | |
| 1826 | 1826 | .alpha_osf, |
| ... | ... | @@ -2081,6 +2081,7 @@ pub const Cpu = struct { |
| 2081 | 2081 | else => generic(arch), |
| 2082 | 2082 | }, |
| 2083 | 2083 | .powerpc64 => switch (os.tag) { |
| 2084 | .linux, .freebsd => &powerpc.cpu.pwr8, | |
| 2084 | 2085 | .openbsd => &powerpc.cpu.pwr9, |
| 2085 | 2086 | else => generic(arch), |
| 2086 | 2087 | }, |
| ... | ... | @@ -2660,12 +2661,26 @@ pub const DynamicLinker = struct { |
| 2660 | 2661 | else => return none, |
| 2661 | 2662 | }}), |
| 2662 | 2663 | |
| 2663 | .loongarch64 => initFmt("/lib64/ld-linux-loongarch-{s}.so.1", .{switch (abi) { | |
| 2664 | .gnu => "lp64d", | |
| 2665 | .gnuf32 => "lp64f", | |
| 2666 | .gnusf => "lp64s", | |
| 2667 | else => return none, | |
| 2668 | }}), | |
| 2664 | .loongarch32, | |
| 2665 | .loongarch64, | |
| 2666 | => |arch| initFmt("/lib{s}/ld-linux-{s}{s}.so.1", .{ | |
| 2667 | switch (arch) { | |
| 2668 | .loongarch32 => "32", | |
| 2669 | .loongarch64 => "64", | |
| 2670 | else => unreachable, | |
| 2671 | }, | |
| 2672 | switch (arch) { | |
| 2673 | .loongarch32 => "loongarch-ilp32", | |
| 2674 | .loongarch64 => "loongarch-lp64", | |
| 2675 | else => unreachable, | |
| 2676 | }, | |
| 2677 | switch (abi) { | |
| 2678 | .gnu => "d", | |
| 2679 | .gnuf32 => "f", | |
| 2680 | .gnusf => "s", | |
| 2681 | else => return none, | |
| 2682 | }, | |
| 2683 | }), | |
| 2669 | 2684 | |
| 2670 | 2685 | .hppa, |
| 2671 | 2686 | .m68k, |
| ... | ... | @@ -3069,9 +3084,13 @@ pub fn stackGrowth(target: *const Target) StackGrowth { |
| 3069 | 3084 | /// Default signedness of `char` for the native C compiler for this target |
| 3070 | 3085 | /// Note that char signedness is implementation-defined and many compilers provide |
| 3071 | 3086 | /// an option to override the default signedness e.g. GCC's -funsigned-char / -fsigned-char |
| 3072 | pub fn cCharSignedness(target: *const Target) std.builtin.Signedness { | |
| 3087 | /// Returns `null` if no C ABI is defined for this target. | |
| 3088 | pub fn cCharSignedness(target: *const Target) ?std.builtin.Signedness { | |
| 3089 | switch (target.os.tag) { | |
| 3090 | .opengl => return null, | |
| 3091 | else => {}, | |
| 3092 | } | |
| 3073 | 3093 | if (target.os.tag.isDarwin() or target.os.tag == .windows or target.os.tag == .uefi) return .signed; |
| 3074 | ||
| 3075 | 3094 | return switch (target.cpu.arch) { |
| 3076 | 3095 | .aarch64, |
| 3077 | 3096 | .aarch64_be, |
| ... | ... | @@ -3117,7 +3136,8 @@ pub const CType = enum { |
| 3117 | 3136 | longdouble, |
| 3118 | 3137 | }; |
| 3119 | 3138 | |
| 3120 | pub fn cTypeByteSize(t: *const Target, c_type: CType) u16 { | |
| 3139 | /// Returns `null` if no C ABI is defined for this target. | |
| 3140 | pub fn cTypeByteSize(t: *const Target, c_type: CType) ?u16 { | |
| 3121 | 3141 | return switch (c_type) { |
| 3122 | 3142 | .char, |
| 3123 | 3143 | .short, |
| ... | ... | @@ -3130,18 +3150,19 @@ pub fn cTypeByteSize(t: *const Target, c_type: CType) u16 { |
| 3130 | 3150 | .ulonglong, |
| 3131 | 3151 | .float, |
| 3132 | 3152 | .double, |
| 3133 | => @divExact(cTypeBitSize(t, c_type), 8), | |
| 3153 | => @divExact(cTypeBitSize(t, c_type) orelse return null, 8), | |
| 3134 | 3154 | |
| 3135 | .longdouble => switch (cTypeBitSize(t, c_type)) { | |
| 3155 | .longdouble => switch (cTypeBitSize(t, c_type) orelse return null) { | |
| 3136 | 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 | 3158 | 128 => 16, |
| 3139 | 3159 | else => unreachable, |
| 3140 | 3160 | }, |
| 3141 | 3161 | }; |
| 3142 | 3162 | } |
| 3143 | 3163 | |
| 3144 | pub fn cTypeBitSize(target: *const Target, c_type: CType) u16 { | |
| 3164 | /// Returns `null` if no C ABI is defined for this target. | |
| 3165 | pub fn cTypeBitSize(target: *const Target, c_type: CType) ?u16 { | |
| 3145 | 3166 | switch (target.os.tag) { |
| 3146 | 3167 | .freestanding, |
| 3147 | 3168 | .other, |
| ... | ... | @@ -3462,15 +3483,17 @@ pub fn cTypeBitSize(target: *const Target, c_type: CType) u16 { |
| 3462 | 3483 | .longlong, .ulonglong, .longdouble => return 64, |
| 3463 | 3484 | }, |
| 3464 | 3485 | |
| 3486 | .opengl => return null, | |
| 3487 | ||
| 3465 | 3488 | .ps3, |
| 3466 | 3489 | .contiki, |
| 3467 | 3490 | .managarm, |
| 3468 | .opengl, | |
| 3469 | 3491 | => @panic("specify the C integer and float type sizes for this OS"), |
| 3470 | 3492 | } |
| 3471 | 3493 | } |
| 3472 | 3494 | |
| 3473 | pub fn cTypeAlignment(target: *const Target, c_type: CType) u16 { | |
| 3495 | /// Returns `null` if no C ABI is defined for this target. | |
| 3496 | pub fn cTypeAlignment(target: *const Target, c_type: CType) ?u16 { | |
| 3474 | 3497 | // Overrides for unusual alignments |
| 3475 | 3498 | switch (target.cpu.arch) { |
| 3476 | 3499 | .avr, |
| ... | ... | @@ -3503,7 +3526,7 @@ pub fn cTypeAlignment(target: *const Target, c_type: CType) u16 { |
| 3503 | 3526 | |
| 3504 | 3527 | // Next-power-of-two-aligned, up to a maximum. |
| 3505 | 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 | 3530 | @as(u16, switch (target.cpu.arch) { |
| 3508 | 3531 | .msp430, |
| 3509 | 3532 | .x86_16, |
| ... | ... | @@ -3578,120 +3601,6 @@ pub fn cTypeAlignment(target: *const Target, c_type: CType) u16 { |
| 3578 | 3601 | ); |
| 3579 | 3602 | } |
| 3580 | 3603 | |
| 3581 | pub 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 | ||
| 3695 | 3604 | pub fn cMaxIntAlignment(target: *const Target) u16 { |
| 3696 | 3605 | return switch (target.cpu.arch) { |
| 3697 | 3606 | .avr, |
| ... | ... | @@ -3715,6 +3624,11 @@ pub fn cMaxIntAlignment(target: *const Target) u16 { |
| 3715 | 3624 | .xcore, |
| 3716 | 3625 | => 4, |
| 3717 | 3626 | |
| 3627 | .x86 => switch (target.os.tag) { | |
| 3628 | else => 4, | |
| 3629 | .uefi, .windows => 8, | |
| 3630 | }, | |
| 3631 | ||
| 3718 | 3632 | .arm, |
| 3719 | 3633 | .armeb, |
| 3720 | 3634 | .hexagon, |
| ... | ... | @@ -3733,7 +3647,6 @@ pub fn cMaxIntAlignment(target: *const Target) u16 { |
| 3733 | 3647 | .sparc, |
| 3734 | 3648 | .thumb, |
| 3735 | 3649 | .thumbeb, |
| 3736 | .x86, | |
| 3737 | 3650 | .xtensa, |
| 3738 | 3651 | .xtensaeb, |
| 3739 | 3652 | => 8, |
| ... | ... | @@ -3769,18 +3682,14 @@ pub fn cMaxIntAlignment(target: *const Target) u16 { |
| 3769 | 3682 | pub fn cCallingConvention(target: *const Target) ?std.builtin.CallingConvention { |
| 3770 | 3683 | return switch (target.cpu.arch) { |
| 3771 | 3684 | .x86_64 => switch (target.os.tag) { |
| 3772 | .windows, | |
| 3773 | .uefi, | |
| 3774 | => .{ .x86_64_win = .{} }, | |
| 3685 | .windows, .uefi => .{ .x86_64_win = .{} }, | |
| 3775 | 3686 | else => switch (target.abi) { |
| 3776 | 3687 | .gnux32, .muslx32, .x32 => .{ .x86_64_x32 = .{} }, |
| 3777 | 3688 | else => .{ .x86_64_sysv = .{} }, |
| 3778 | 3689 | }, |
| 3779 | 3690 | }, |
| 3780 | 3691 | .x86 => switch (target.os.tag) { |
| 3781 | .windows, | |
| 3782 | .uefi, | |
| 3783 | => .{ .x86_win = .{} }, | |
| 3692 | .windows, .uefi => if (target.isMinGW()) .{ .x86_mingw = .{} } else .{ .x86_win = .{} }, | |
| 3784 | 3693 | else => .{ .x86_sysv = .{} }, |
| 3785 | 3694 | }, |
| 3786 | 3695 | .x86_16 => .{ .x86_16_cdecl = .{} }, |
lib/std/Thread.zig+36-43| ... | ... | @@ -639,8 +639,7 @@ const WindowsThreadImpl = struct { |
| 639 | 639 | } |
| 640 | 640 | |
| 641 | 641 | fn join(self: Impl) void { |
| 642 | const infinite_timeout: windows.LARGE_INTEGER = std.math.minInt(windows.LARGE_INTEGER); | |
| 643 | switch (windows.ntdll.NtWaitForSingleObject(self.thread.thread_handle, .FALSE, &infinite_timeout)) { | |
| 642 | switch (windows.ntdll.NtWaitForSingleObject(self.thread.thread_handle, .FALSE, null)) { | |
| 644 | 643 | windows.NTSTATUS.WAIT_0 => {}, |
| 645 | 644 | else => |status| windows.unexpectedStatus(status) catch unreachable, |
| 646 | 645 | } |
| ... | ... | @@ -720,10 +719,9 @@ const PosixThreadImpl = struct { |
| 720 | 719 | }, |
| 721 | 720 | .haiku => { |
| 722 | 721 | var system_info: std.c.system_info = undefined; |
| 723 | const rc = std.c.get_system_info(&system_info); // always returns B_OK | |
| 724 | return switch (posix.errno(rc)) { | |
| 725 | .SUCCESS => @as(usize, @intCast(system_info.cpu_count)), | |
| 726 | else => |err| posix.unexpectedErrno(err), | |
| 722 | return switch (std.c.get_system_info(&system_info)) { | |
| 723 | 0 => @as(usize, @intCast(system_info.cpu_count)), | |
| 724 | else => error.Unexpected, | |
| 727 | 725 | }; |
| 728 | 726 | }, |
| 729 | 727 | else => { |
| ... | ... | @@ -1146,6 +1144,13 @@ const LinuxThreadImpl = struct { |
| 1146 | 1144 | parent_tid: i32 = undefined, |
| 1147 | 1145 | mapped: []align(std.heap.page_size_min) u8, |
| 1148 | 1146 | |
| 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 | 1154 | /// Calls `munmap(mapped.ptr, mapped.len)` then `exit(1)` without touching the stack (which lives in `mapped.ptr`). |
| 1150 | 1155 | /// Ported over from musl libc's pthread detached implementation: |
| 1151 | 1156 | /// https://github.com/ifduyue/musl/search?q=__unmapself |
| ... | ... | @@ -1365,51 +1370,39 @@ const LinuxThreadImpl = struct { |
| 1365 | 1370 | [len] "{r5}" (self.mapped.len), |
| 1366 | 1371 | ), |
| 1367 | 1372 | .sparc => asm volatile ( |
| 1368 | \\ # See sparc64 comments below. | |
| 1369 | \\ 1: | |
| 1370 | \\ cmp %%fp, 0 | |
| 1371 | \\ beq 2f | |
| 1372 | \\ nop | |
| 1373 | \\ ba 1b | |
| 1374 | \\ restore | |
| 1375 | \\ 2: | |
| 1376 | \\ mov %%g1, %%o0 // ptr | |
| 1377 | \\ mov %%g2, %%o1 // len | |
| 1378 | \\ mov 73, %%g1 // SYS_munmap | |
| 1379 | \\ t 0x3 // ST_FLUSH_WINDOWS | |
| 1380 | \\ t 0x10 | |
| 1381 | \\ mov 1, %%g1 // SYS_exit | |
| 1382 | \\ mov 0, %%o0 | |
| 1383 | \\ t 0x10 | |
| 1373 | \\ // See sparc64 comments below. | |
| 1374 | \\ t 0x3 // ST_FLUSH_WINDOWS | |
| 1375 | \\ mov %%g3, %%sp | |
| 1376 | \\ mov %%g1, %%o0 | |
| 1377 | \\ mov %%g2, %%o1 | |
| 1378 | \\ mov 73, %%g1 // SYS_munmap | |
| 1379 | \\ t 0x10 | |
| 1380 | \\ mov 1, %%g1 // SYS_exit | |
| 1381 | \\ mov 0, %%o0 | |
| 1382 | \\ t 0x10 | |
| 1384 | 1383 | : |
| 1385 | 1384 | : [ptr] "{g1}" (@intFromPtr(self.mapped.ptr)), |
| 1386 | 1385 | [len] "{g2}" (self.mapped.len), |
| 1386 | [stack] "{g3}" (&sparc_exit_stack), | |
| 1387 | 1387 | : .{ .memory = true }), |
| 1388 | 1388 | .sparc64 => asm volatile ( |
| 1389 | \\ # SPARCs really don't like it when active stack frames | |
| 1390 | \\ # is unmapped (it will result in a segfault), so we | |
| 1391 | \\ # force-deactivate it by running `restore` until | |
| 1392 | \\ # all frames are cleared. | |
| 1393 | \\ 1: | |
| 1394 | \\ cmp %%fp, 0 | |
| 1395 | \\ beq 2f | |
| 1396 | \\ nop | |
| 1397 | \\ ba 1b | |
| 1398 | \\ restore | |
| 1399 | \\ 2: | |
| 1400 | \\ mov %%g1, %%o0 // ptr | |
| 1401 | \\ mov %%g2, %%o1 // len | |
| 1402 | \\ mov 73, %%g1 // SYS_munmap | |
| 1403 | \\ # Flush register window contents to prevent background | |
| 1404 | \\ # memory access before unmapping the stack. | |
| 1405 | \\ flushw | |
| 1406 | \\ t 0x6d | |
| 1407 | \\ mov 1, %%g1 // SYS_exit | |
| 1408 | \\ mov 0, %%o0 | |
| 1409 | \\ t 0x6d | |
| 1389 | \\ // Ensure that the kernel only has to flush the current register window. | |
| 1390 | \\ flushw | |
| 1391 | \\ // Set up a fake stack for the syscall to restore l/i registers from. Local | |
| 1392 | \\ // and incoming registers must be treated as effectively garbage past this | |
| 1393 | \\ // instruction! | |
| 1394 | \\ sub %%g3, 2047, %%sp | |
| 1395 | \\ mov %%g1, %%o0 | |
| 1396 | \\ mov %%g2, %%o1 | |
| 1397 | \\ mov 73, %%g1 // SYS_munmap | |
| 1398 | \\ t 0x6d | |
| 1399 | \\ mov 1, %%g1 // SYS_exit | |
| 1400 | \\ mov 0, %%o0 | |
| 1401 | \\ t 0x6d | |
| 1410 | 1402 | : |
| 1411 | 1403 | : [ptr] "{g1}" (@intFromPtr(self.mapped.ptr)), |
| 1412 | 1404 | [len] "{g2}" (self.mapped.len), |
| 1405 | [stack] "{g3}" (&sparc_exit_stack), | |
| 1413 | 1406 | : .{ .memory = true }), |
| 1414 | 1407 | .loongarch32, .loongarch64 => asm volatile ( |
| 1415 | 1408 | \\ 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 | 221 | } |
| 222 | 222 | |
| 223 | 223 | 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 | 225 | end_of_host += 1; |
| 226 | 226 | |
| 227 | if (std.mem.lastIndexOf(u8, authority, ":")) |index| { | |
| 227 | if (std.mem.findLast(u8, authority, ":")) |index| { | |
| 228 | 228 | if (index >= end_of_host) { // if not part of the V6 address field |
| 229 | 229 | end_of_host = @min(end_of_host, index); |
| 230 | 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 | 234 | if (index >= start_of_host) { // if not part of the userinfo field |
| 235 | 235 | end_of_host = @min(end_of_host, index); |
| 236 | 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 | 475 | var aux: Writer = .fixed(aux_buf.*); |
| 476 | 476 | if (!base.isEmpty()) { |
| 477 | 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 | 480 | aux.print("/{s}", .{new}) catch return error.NoSpaceLeft; |
| 481 | 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 | 13 | /// |
| 14 | 14 | /// See `AutoContext` for a description of the hash and equal implementations. |
| 15 | 15 | pub 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 | } |
| 18 | 18 | |
| 19 | 19 | /// An `ArrayHashMap` with strings as keys. |
| 20 | 20 | pub fn String(comptime V: type) type { |
| 21 | return ArrayHashMap([]const u8, V, StringContext, true); | |
| 21 | return Custom([]const u8, V, StringContext, true); | |
| 22 | 22 | } |
| 23 | 23 | |
| 24 | 24 | pub const StringContext = struct { |
| ... | ... | @@ -2130,7 +2130,7 @@ test "0 sized key and 0 sized value" { |
| 2130 | 2130 | test "setKey storehash true" { |
| 2131 | 2131 | const gpa = std.testing.allocator; |
| 2132 | 2132 | |
| 2133 | var map: ArrayHashMap(i32, i32, AutoContext(i32), true) = .empty; | |
| 2133 | var map: Custom(i32, i32, AutoContext(i32), true) = .empty; | |
| 2134 | 2134 | defer map.deinit(gpa); |
| 2135 | 2135 | |
| 2136 | 2136 | try map.put(gpa, 12, 34); |
| ... | ... | @@ -2146,7 +2146,7 @@ test "setKey storehash true" { |
| 2146 | 2146 | test "setKey storehash false" { |
| 2147 | 2147 | const gpa = std.testing.allocator; |
| 2148 | 2148 | |
| 2149 | var map: ArrayHashMap(i32, i32, AutoContext(i32), false) = .empty; | |
| 2149 | var map: Custom(i32, i32, AutoContext(i32), false) = .empty; | |
| 2150 | 2150 | defer map.deinit(gpa); |
| 2151 | 2151 | |
| 2152 | 2152 | try map.put(gpa, 12, 34); |
| ... | ... | @@ -2162,7 +2162,7 @@ test "setKey storehash false" { |
| 2162 | 2162 | test "setKey storehash false with index" { |
| 2163 | 2163 | const gpa = std.testing.allocator; |
| 2164 | 2164 | |
| 2165 | const T = ArrayHashMap(usize, usize, AutoContext(usize), false); | |
| 2165 | const T = Custom(usize, usize, AutoContext(usize), false); | |
| 2166 | 2166 | |
| 2167 | 2167 | var map: T = .empty; |
| 2168 | 2168 | defer map.deinit(gpa); |
| ... | ... | @@ -2180,9 +2180,9 @@ test "setKey storehash false with index" { |
| 2180 | 2180 | test "setKey storehash true with index" { |
| 2181 | 2181 | const gpa = std.testing.allocator; |
| 2182 | 2182 | |
| 2183 | const T = ArrayHashMap(usize, usize, AutoContext(usize), false); | |
| 2183 | const T = Custom(usize, usize, AutoContext(usize), false); | |
| 2184 | 2184 | |
| 2185 | var map: ArrayHashMap(usize, usize, AutoContext(usize), true) = .empty; | |
| 2185 | var map: Custom(usize, usize, AutoContext(usize), true) = .empty; | |
| 2186 | 2186 | defer map.deinit(gpa); |
| 2187 | 2187 | |
| 2188 | 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 | 26 | /// |
| 27 | 27 | /// Pointers to elements in this slice are invalidated by various |
| 28 | 28 | /// functions of this ArrayList in accordance with the respective |
| 29 | /// documentation. In all cases, "invalidated" means that the memory | |
| 30 | /// has been passed to this allocator's resize or free function. | |
| 29 | /// documentation. | |
| 30 | /// An invalidated pointer may point either to valid or freed memory. | |
| 31 | 31 | items: Slice, |
| 32 | 32 | /// How many T values this list can hold without allocating |
| 33 | 33 | /// additional memory. |
| ... | ... | @@ -35,7 +35,7 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type |
| 35 | 35 | allocator: Allocator, |
| 36 | 36 | |
| 37 | 37 | /// Used to detect memory safety violations. |
| 38 | pointer_stability: debug.SafetyLock = .{}, | |
| 38 | pointer_stability: debug.SafetyLock, | |
| 39 | 39 | |
| 40 | 40 | pub const Slice = if (alignment) |a| ([]align(a.toByteUnits()) T) else []T; |
| 41 | 41 | |
| ... | ... | @@ -49,6 +49,7 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type |
| 49 | 49 | .items = &[_]T{}, |
| 50 | 50 | .capacity = 0, |
| 51 | 51 | .allocator = gpa, |
| 52 | .pointer_stability = .{}, | |
| 52 | 53 | }; |
| 53 | 54 | } |
| 54 | 55 | |
| ... | ... | @@ -94,6 +95,7 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type |
| 94 | 95 | .items = slice, |
| 95 | 96 | .capacity = slice.len, |
| 96 | 97 | .allocator = gpa, |
| 98 | .pointer_stability = .{}, | |
| 97 | 99 | }; |
| 98 | 100 | } |
| 99 | 101 | |
| ... | ... | @@ -105,22 +107,28 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type |
| 105 | 107 | .items = slice, |
| 106 | 108 | .capacity = slice.len + 1, |
| 107 | 109 | .allocator = gpa, |
| 110 | .pointer_stability = .{}, | |
| 108 | 111 | }; |
| 109 | 112 | } |
| 110 | 113 | |
| 111 | 114 | /// Initializes an ArrayList with the `items` and `capacity` fields |
| 112 | 115 | /// of this ArrayList. Empties this ArrayList. |
| 113 | 116 | pub fn moveToUnmanaged(self: *Self) Aligned(T, alignment) { |
| 114 | self.pointer_stability.assertUnlocked(); | |
| 115 | 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 | 123 | self.* = init(allocator); |
| 118 | 124 | return result; |
| 119 | 125 | } |
| 120 | 126 | |
| 121 | 127 | /// The caller owns the returned memory. Empties this ArrayList. |
| 122 | 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 | 130 | pub fn toOwnedSlice(self: *Self) Allocator.Error!Slice { |
| 131 | self.pointer_stability.assertUnlocked(); | |
| 124 | 132 | const allocator = self.allocator; |
| 125 | 133 | |
| 126 | 134 | const old_memory = self.allocatedSlice(); |
| ... | ... | @@ -136,6 +144,7 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type |
| 136 | 144 | } |
| 137 | 145 | |
| 138 | 146 | /// The caller owns the returned memory. Empties this ArrayList. |
| 147 | /// May invalidate element pointers if remapping memory cannot be done in place. | |
| 139 | 148 | pub fn toOwnedSliceSentinel(self: *Self, comptime sentinel: T) Allocator.Error!SentinelSlice(sentinel) { |
| 140 | 149 | // This addition can never overflow because `self.items` can never occupy the whole address space |
| 141 | 150 | try self.ensureTotalCapacityPrecise(self.items.len + 1); |
| ... | ... | @@ -151,31 +160,31 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type |
| 151 | 160 | return cloned; |
| 152 | 161 | } |
| 153 | 162 | |
| 154 | /// Insert `item` at index `i`. Moves `list[i .. list.len]` to higher indices to make room. | |
| 155 | /// If `i` is equal to the length of the list this operation is equivalent to append. | |
| 163 | /// Insert `item` at index `index`. Moves `list[index .. list.len]` to higher indices to make room. | |
| 164 | /// If `index` is equal to the length of the list this operation is equivalent to append. | |
| 156 | 165 | /// This operation is O(N). |
| 157 | 166 | /// Invalidates element pointers if additional memory is needed. |
| 167 | /// Invalidates pre-existing pointers to elements at and after `index`. | |
| 158 | 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 { | |
| 160 | const dst = try self.addManyAt(i, 1); | |
| 169 | pub fn insert(self: *Self, index: usize, item: T) Allocator.Error!void { | |
| 170 | self.pointer_stability.assertUnlocked(); | |
| 171 | const dst = try self.addManyAt(index, 1); | |
| 161 | 172 | dst[0] = item; |
| 162 | 173 | } |
| 163 | 174 | |
| 164 | /// Insert `item` at index `i`. Moves `list[i .. list.len]` to higher indices to make room. | |
| 165 | /// If `i` is equal to the length of the list this operation is | |
| 175 | /// Insert `item` at index `index`. Moves `list[index .. list.len]` to higher indices to make room. | |
| 176 | /// If `index` is equal to the length of the list this operation is | |
| 166 | 177 | /// equivalent to appendAssumeCapacity. |
| 167 | 178 | /// This operation is O(N). |
| 179 | /// Invalidates pre-existing pointers to elements at and after `index`. | |
| 168 | 180 | /// Asserts that there is enough capacity for the new item. |
| 169 | 181 | /// Asserts that the index is in bounds or equal to the length. |
| 170 | pub fn insertAssumeCapacity(self: *Self, i: usize, item: T) void { | |
| 171 | self.pointer_stability.lock(); | |
| 172 | defer self.pointer_stability.unlock(); | |
| 173 | ||
| 182 | pub fn insertAssumeCapacity(self: *Self, index: usize, item: T) void { | |
| 183 | self.pointer_stability.assertUnlocked(); | |
| 174 | 184 | assert(self.items.len < self.capacity); |
| 175 | 185 | self.items.len += 1; |
| 176 | ||
| 177 | @memmove(self.items[i + 1 .. self.items.len], self.items[i .. self.items.len - 1]); | |
| 178 | self.items[i] = item; | |
| 186 | @memmove(self.items[index + 1 .. self.items.len], self.items[index .. self.items.len - 1]); | |
| 187 | self.items[index] = item; | |
| 179 | 188 | } |
| 180 | 189 | |
| 181 | 190 | /// 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 | 197 | /// Asserts that the index is in bounds or equal to the length. |
| 189 | 198 | pub fn addManyAt(self: *Self, index: usize, count: usize) Allocator.Error![]T { |
| 190 | 199 | const new_len = try addOrOom(self.items.len, count); |
| 200 | self.pointer_stability.assertUnlocked(); | |
| 191 | 201 | |
| 192 | 202 | if (self.capacity >= new_len) |
| 193 | 203 | return addManyAtAssumeCapacity(self, index, count); |
| 194 | 204 | |
| 195 | self.pointer_stability.lock(); | |
| 196 | defer self.pointer_stability.unlock(); | |
| 197 | 205 | // Here we avoid copying allocated but unused bytes by |
| 198 | 206 | // attempting a resize in place, and falling back to allocating |
| 199 | 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 | 233 | /// `undefined` values. Returns a slice pointing to the newly allocated |
| 226 | 234 | /// elements, which becomes invalid after various `ArrayList` |
| 227 | 235 | /// operations. |
| 236 | /// Invalidates pre-existing pointers to elements at and after `index`. | |
| 228 | 237 | /// Asserts that there is enough capacity for the new elements. |
| 229 | 238 | /// Asserts that the index is in bounds or equal to the length. |
| 230 | 239 | pub fn addManyAtAssumeCapacity(self: *Self, index: usize, count: usize) []T { |
| 240 | self.pointer_stability.assertUnlocked(); | |
| 231 | 241 | const new_len = self.items.len + count; |
| 232 | 242 | assert(self.capacity >= new_len); |
| 233 | 243 | const to_move = self.items[index..]; |
| ... | ... | @@ -238,7 +248,7 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type |
| 238 | 248 | return result; |
| 239 | 249 | } |
| 240 | 250 | |
| 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 | 252 | /// This operation is O(N). |
| 243 | 253 | /// Invalidates pre-existing pointers to elements at and after `index`. |
| 244 | 254 | /// 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 | 264 | } |
| 255 | 265 | |
| 256 | 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 | 270 | /// Asserts that the range is in bounds. |
| 259 | 271 | pub fn replaceRange(self: *Self, start: usize, len: usize, new_items: []const T) Allocator.Error!void { |
| 260 | 272 | var unmanaged = self.moveToUnmanaged(); |
| ... | ... | @@ -263,7 +275,8 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type |
| 263 | 275 | } |
| 264 | 276 | |
| 265 | 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 | 280 | /// Asserts the capacity is enough for additional items. |
| 268 | 281 | pub fn replaceRangeAssumeCapacity(self: *Self, start: usize, len: usize, new_items: []const T) void { |
| 269 | 282 | var unmanaged = self.moveToUnmanaged(); |
| ... | ... | @@ -300,10 +313,12 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type |
| 300 | 313 | |
| 301 | 314 | /// Removes the element at the specified index and returns it. |
| 302 | 315 | /// The empty slot is filled from the end of the list. |
| 316 | /// Invalidates pointers to the end of the list. | |
| 303 | 317 | /// This operation is O(1). |
| 304 | 318 | /// This may not preserve item order. Use `orderedRemove` if you need to preserve order. |
| 305 | 319 | /// Asserts that the index is in bounds. |
| 306 | 320 | pub fn swapRemove(self: *Self, i: usize) T { |
| 321 | self.pointer_stability.assertUnlocked(); | |
| 307 | 322 | const val = self.items[i]; |
| 308 | 323 | self.items[i] = self.items[self.items.len - 1]; |
| 309 | 324 | self.items[self.items.len - 1] = undefined; |
| ... | ... | @@ -353,6 +368,8 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type |
| 353 | 368 | @memcpy(self.items[old_len..][0..items.len], items); |
| 354 | 369 | } |
| 355 | 370 | |
| 371 | /// Prints a formatted string into this list. | |
| 372 | /// Invalidates element pointers if additional memory is needed. | |
| 356 | 373 | pub fn print(self: *Self, comptime fmt: []const u8, args: anytype) error{OutOfMemory}!void { |
| 357 | 374 | const gpa = self.allocator; |
| 358 | 375 | var unmanaged = self.moveToUnmanaged(); |
| ... | ... | @@ -404,9 +421,7 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type |
| 404 | 421 | /// Invalidates element pointers for the elements `items[new_len..]`. |
| 405 | 422 | /// Asserts that the new length is less than or equal to the previous length. |
| 406 | 423 | pub fn shrinkRetainingCapacity(self: *Self, new_len: usize) void { |
| 407 | self.pointer_stability.lock(); | |
| 408 | defer self.pointer_stability.unlock(); | |
| 409 | ||
| 424 | self.pointer_stability.assertUnlocked(); | |
| 410 | 425 | assert(new_len <= self.items.len); |
| 411 | 426 | @memset(self.items[new_len..], undefined); |
| 412 | 427 | self.items.len = new_len; |
| ... | ... | @@ -415,8 +430,7 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type |
| 415 | 430 | /// Reduce length to 0. |
| 416 | 431 | /// Invalidates all element pointers. |
| 417 | 432 | pub fn clearRetainingCapacity(self: *Self) void { |
| 418 | self.pointer_stability.lock(); | |
| 419 | defer self.pointer_stability.unlock(); | |
| 433 | self.pointer_stability.assertUnlocked(); | |
| 420 | 434 | @memset(self.items, undefined); |
| 421 | 435 | self.items.len = 0; |
| 422 | 436 | } |
| ... | ... | @@ -449,18 +463,15 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type |
| 449 | 463 | /// modify the array so that it can hold exactly `new_capacity` items. |
| 450 | 464 | /// Invalidates element pointers if additional memory is needed. |
| 451 | 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 | 466 | if (@sizeOf(T) == 0) { |
| 456 | 467 | self.capacity = math.maxInt(usize); |
| 457 | 468 | return; |
| 458 | 469 | } |
| 459 | 470 | |
| 460 | 471 | if (self.capacity >= new_capacity) return; |
| 461 | ||
| 472 | self.pointer_stability.assertUnlocked(); | |
| 462 | 473 | // Here we avoid copying allocated but unused bytes by |
| 463 | // attempting a resize in place, and falling back to allocating | |
| 474 | // attempting a remap, and falling back to allocating | |
| 464 | 475 | // a new buffer and doing our own copy. With a realloc() call, |
| 465 | 476 | // the allocator implementation would pointlessly copy our |
| 466 | 477 | // extra capacity. |
| ... | ... | @@ -491,7 +502,8 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type |
| 491 | 502 | } |
| 492 | 503 | |
| 493 | 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 | 507 | pub fn addOne(self: *Self) Allocator.Error!*T { |
| 496 | 508 | // This can never overflow because `self.items` can never occupy the whole address space |
| 497 | 509 | const newlen = self.items.len + 1; |
| ... | ... | @@ -500,7 +512,7 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type |
| 500 | 512 | } |
| 501 | 513 | |
| 502 | 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 | 516 | /// Never invalidates element pointers. |
| 505 | 517 | /// Asserts that the list can hold one additional item. |
| 506 | 518 | pub fn addOneAssumeCapacity(self: *Self) *T { |
| ... | ... | @@ -511,8 +523,9 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type |
| 511 | 523 | |
| 512 | 524 | /// Resize the array, adding `n` new elements, which have `undefined` values. |
| 513 | 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 | 527 | /// Resizes list if `self.capacity` is not large enough. |
| 528 | /// Invalidates element pointers if additional memory is needed. | |
| 516 | 529 | pub fn addManyAsArray(self: *Self, comptime n: usize) Allocator.Error!*[n]T { |
| 517 | 530 | const prev_len = self.items.len; |
| 518 | 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 | 535 | /// Resize the array, adding `n` new elements, which have `undefined` values. |
| 523 | 536 | /// The return value is an array pointing to the newly allocated elements. |
| 524 | 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 | 539 | /// Asserts that the list can hold the additional items. |
| 527 | 540 | pub fn addManyAsArrayAssumeCapacity(self: *Self, comptime n: usize) *[n]T { |
| 528 | 541 | assert(self.items.len + n <= self.capacity); |
| ... | ... | @@ -533,8 +546,9 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type |
| 533 | 546 | |
| 534 | 547 | /// Resize the array, adding `n` new elements, which have `undefined` values. |
| 535 | 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 | 550 | /// Resizes list if `self.capacity` is not large enough. |
| 551 | /// Invalidates element pointers if additional memory is needed. | |
| 538 | 552 | pub fn addManyAsSlice(self: *Self, n: usize) Allocator.Error![]T { |
| 539 | 553 | const prev_len = self.items.len; |
| 540 | 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 | 558 | /// Resize the array, adding `n` new elements, which have `undefined` values. |
| 545 | 559 | /// The return value is a slice pointing to the newly allocated elements. |
| 546 | 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 | 562 | /// Asserts that the list can hold the additional items. |
| 549 | 563 | pub fn addManyAsSliceAssumeCapacity(self: *Self, n: usize) []T { |
| 550 | 564 | assert(self.items.len + n <= self.capacity); |
| ... | ... | @@ -554,11 +568,10 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type |
| 554 | 568 | } |
| 555 | 569 | |
| 556 | 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 | 572 | pub fn pop(self: *Self) ?T { |
| 559 | 573 | if (self.items.len == 0) return null; |
| 560 | self.pointer_stability.lock(); | |
| 561 | defer self.pointer_stability.unlock(); | |
| 574 | self.pointer_stability.assertUnlocked(); | |
| 562 | 575 | const val = self.items[self.items.len - 1]; |
| 563 | 576 | self.items[self.items.len - 1] = undefined; |
| 564 | 577 | self.items.len -= 1; |
| ... | ... | @@ -567,6 +580,7 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type |
| 567 | 580 | |
| 568 | 581 | /// Returns a slice of all the items plus the extra capacity, whose memory |
| 569 | 582 | /// contents are `undefined`. |
| 583 | /// The returned pointer may be invalidated by further operations to this list. | |
| 570 | 584 | pub fn allocatedSlice(self: Self) Slice { |
| 571 | 585 | // `items.len` is the length, not the capacity. |
| 572 | 586 | return self.items.ptr[0..self.capacity]; |
| ... | ... | @@ -576,18 +590,29 @@ pub fn AlignedManaged(comptime T: type, comptime alignment: ?mem.Alignment) type |
| 576 | 590 | /// This can be useful for writing directly into an ArrayList. |
| 577 | 591 | /// Note that such an operation must be followed up with a direct |
| 578 | 592 | /// modification of `self.items.len`. |
| 593 | /// The returned pointer may be invalidated by further operations to this list. | |
| 579 | 594 | pub fn unusedCapacitySlice(self: Self) []T { |
| 580 | 595 | return self.allocatedSlice()[self.items.len..]; |
| 581 | 596 | } |
| 582 | 597 | |
| 583 | /// Deprecated in favor of `getLast` | |
| 584 | pub const getLastOrNull = getLast; | |
| 598 | /// Deprecated in favor of `last` | |
| 599 | pub const getLastOrNull = last; | |
| 585 | 600 | |
| 586 | /// Returns the last element from the list, or `null` if the list is empty. | |
| 587 | pub fn getLast(self: Self) ?T { | |
| 601 | /// Returns the last element from the list, or `null` if the list is | |
| 602 | /// empty. | |
| 603 | /// Never invalidates element pointers. | |
| 604 | pub fn last(self: Self) ?T { | |
| 588 | 605 | if (self.items.len == 0) return null; |
| 589 | 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 | } |
| 593 | 618 | |
| ... | ... | @@ -613,20 +638,21 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { |
| 613 | 638 | /// |
| 614 | 639 | /// Pointers to elements in this slice are invalidated by various |
| 615 | 640 | /// functions of this ArrayList in accordance with the respective |
| 616 | /// documentation. In all cases, "invalidated" means that the memory | |
| 617 | /// has been passed to an allocator's resize or free function. | |
| 641 | /// documentation. | |
| 642 | /// An invalidated pointer may point either to valid or freed memory. | |
| 618 | 643 | items: Slice, |
| 619 | 644 | /// How many T values this list can hold without allocating |
| 620 | 645 | /// additional memory. |
| 621 | 646 | capacity: usize, |
| 622 | 647 | |
| 623 | 648 | /// Used to detect memory safety violations. |
| 624 | pointer_stability: debug.SafetyLock = .{}, | |
| 649 | pointer_stability: debug.SafetyLock, | |
| 625 | 650 | |
| 626 | 651 | /// An ArrayList containing no elements. |
| 627 | 652 | pub const empty: Self = .{ |
| 628 | 653 | .items = &.{}, |
| 629 | 654 | .capacity = 0, |
| 655 | .pointer_stability = .{}, | |
| 630 | 656 | }; |
| 631 | 657 | |
| 632 | 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 | 678 | return .{ |
| 653 | 679 | .items = buffer[0..0], |
| 654 | 680 | .capacity = buffer.len, |
| 681 | .pointer_stability = .{}, | |
| 655 | 682 | }; |
| 656 | 683 | } |
| 657 | 684 | |
| ... | ... | @@ -682,7 +709,12 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { |
| 682 | 709 | /// Convert this list into an analogous memory-managed one. |
| 683 | 710 | /// The returned list has ownership of the underlying memory. |
| 684 | 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 | } |
| 687 | 719 | |
| 688 | 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 | 723 | return Self{ |
| 692 | 724 | .items = slice, |
| 693 | 725 | .capacity = slice.len, |
| 726 | .pointer_stability = .{}, | |
| 694 | 727 | }; |
| 695 | 728 | } |
| 696 | 729 | |
| ... | ... | @@ -700,13 +733,16 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { |
| 700 | 733 | return Self{ |
| 701 | 734 | .items = slice, |
| 702 | 735 | .capacity = slice.len + 1, |
| 736 | .pointer_stability = .{}, | |
| 703 | 737 | }; |
| 704 | 738 | } |
| 705 | 739 | |
| 706 | 740 | /// The caller owns the returned memory. Empties this ArrayList. |
| 707 | 741 | /// Its capacity is cleared, making deinit() safe but unnecessary to call. |
| 742 | /// May invalidate element pointers. | |
| 708 | 743 | pub fn toOwnedSlice(self: *Self, gpa: Allocator) Allocator.Error!Slice { |
| 709 | 744 | const old_memory = self.allocatedSlice(); |
| 745 | self.pointer_stability.assertUnlocked(); | |
| 710 | 746 | if (gpa.remap(old_memory, self.items.len)) |new_items| { |
| 711 | 747 | self.* = .empty; |
| 712 | 748 | return new_items; |
| ... | ... | @@ -719,7 +755,9 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { |
| 719 | 755 | } |
| 720 | 756 | |
| 721 | 757 | /// The caller owns the returned memory. ArrayList becomes empty. |
| 758 | /// May invalidate element pointers. | |
| 722 | 759 | pub fn toOwnedSliceSentinel(self: *Self, gpa: Allocator, comptime sentinel: T) Allocator.Error!SentinelSlice(sentinel) { |
| 760 | self.pointer_stability.assertUnlocked(); | |
| 723 | 761 | // This addition can never overflow because `self.items` can never occupy the whole address space. |
| 724 | 762 | try self.ensureTotalCapacityPrecise(gpa, self.items.len + 1); |
| 725 | 763 | self.appendAssumeCapacity(sentinel); |
| ... | ... | @@ -732,6 +770,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { |
| 732 | 770 | /// Its capacity is cleared, making deinit() safe but unnecessary to call. |
| 733 | 771 | /// |
| 734 | 772 | /// Asserts what the capacity is equal to the length. |
| 773 | /// Never invalidates element pointers. | |
| 735 | 774 | pub fn toOwnedSliceAssert(self: *Self) Slice { |
| 736 | 775 | assert(self.items.len == self.capacity); |
| 737 | 776 | const items = self.items; |
| ... | ... | @@ -741,6 +780,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { |
| 741 | 780 | |
| 742 | 781 | /// The caller owns the returned memory. ArrayList becomes empty. |
| 743 | 782 | /// Asserts what the capacity is equal to the length + 1. |
| 783 | /// Never invalidates element pointers. | |
| 744 | 784 | pub fn toOwnedSliceSentinelAssert(self: *Self, comptime sentinel: T) SentinelSlice(sentinel) { |
| 745 | 785 | std.debug.assert(self.items.len + 1 == self.capacity); |
| 746 | 786 | self.appendAssumeCapacity(sentinel); |
| ... | ... | @@ -755,46 +795,41 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { |
| 755 | 795 | return cloned; |
| 756 | 796 | } |
| 757 | 797 | |
| 758 | /// Insert `item` at index `i`. Moves `list[i .. list.len]` to higher indices to make room. | |
| 759 | /// If `i` is equal to the length of the list this operation is equivalent to append. | |
| 798 | /// Insert `item` at index `index`. Moves `list[index .. list.len]` to higher indices to make room. | |
| 799 | /// If `index` is equal to the length of the list this operation is equivalent to append. | |
| 760 | 800 | /// This operation is O(N). |
| 761 | 801 | /// Invalidates element pointers if additional memory is needed. |
| 802 | /// Invalidates pre-existing pointers to elements at and after `index`. | |
| 762 | 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 { | |
| 764 | const dst = try self.addManyAt(gpa, i, 1); | |
| 804 | pub fn insert(self: *Self, gpa: Allocator, index: usize, item: T) Allocator.Error!void { | |
| 805 | self.pointer_stability.assertUnlocked(); | |
| 806 | const dst = try self.addManyAt(gpa, index, 1); | |
| 765 | 807 | dst[0] = item; |
| 766 | 808 | } |
| 767 | 809 | |
| 768 | /// Insert `item` at index `i`. Moves `list[i .. list.len]` to higher indices to make room. | |
| 769 | /// | |
| 770 | /// If `i` is equal to the length of the list this operation is equivalent to append. | |
| 771 | /// | |
| 810 | /// Insert `item` at index `index`. Moves `list[index .. list.len]` to higher indices to make room. | |
| 811 | /// If `index` is equal to the length of the list this operation is | |
| 812 | /// equivalent to appendAssumeCapacity. | |
| 772 | 813 | /// This operation is O(N). |
| 773 | /// | |
| 814 | /// Invalidates pre-existing pointers to elements at and after `index`. | |
| 774 | 815 | /// Asserts that the list has capacity for one additional item. |
| 775 | /// | |
| 776 | 816 | /// Asserts that the index is in bounds or equal to the length. |
| 777 | pub fn insertAssumeCapacity(self: *Self, i: usize, item: T) void { | |
| 778 | self.pointer_stability.lock(); | |
| 779 | defer self.pointer_stability.unlock(); | |
| 780 | ||
| 817 | pub fn insertAssumeCapacity(self: *Self, index: usize, item: T) void { | |
| 818 | self.pointer_stability.assertUnlocked(); | |
| 781 | 819 | assert(self.items.len < self.capacity); |
| 782 | 820 | self.items.len += 1; |
| 783 | ||
| 784 | @memmove(self.items[i + 1 .. self.items.len], self.items[i .. self.items.len - 1]); | |
| 785 | self.items[i] = item; | |
| 821 | @memmove(self.items[index + 1 .. self.items.len], self.items[index .. self.items.len - 1]); | |
| 822 | self.items[index] = item; | |
| 786 | 823 | } |
| 787 | 824 | |
| 788 | /// Insert `item` at index `i`, moving `list[i .. list.len]` to higher indices to make room. | |
| 789 | /// | |
| 790 | /// If `i` is equal to the length of the list this operation is equivalent to append. | |
| 791 | /// | |
| 825 | /// Insert `item` at index `index`. Moves `list[index .. list.len]` to higher indices to make room. | |
| 826 | /// If `index` is equal to the length of the list this operation is | |
| 827 | /// equivalent to appendAssumeCapacity. | |
| 792 | 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 | 831 | /// If the list lacks unused capacity for the additional item, returns |
| 795 | 832 | /// `error.OutOfMemory`. |
| 796 | /// | |
| 797 | /// Asserts that the index is in bounds or equal to the length. | |
| 798 | 833 | pub fn insertBounded(self: *Self, i: usize, item: T) error{OutOfMemory}!void { |
| 799 | 834 | if (self.capacity - self.items.len == 0) return error.OutOfMemory; |
| 800 | 835 | return insertAssumeCapacity(self, i, item); |
| ... | ... | @@ -814,21 +849,48 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { |
| 814 | 849 | index: usize, |
| 815 | 850 | count: usize, |
| 816 | 851 | ) Allocator.Error![]T { |
| 817 | var managed = self.toManaged(gpa); | |
| 818 | defer self.* = managed.moveToUnmanaged(); | |
| 819 | return managed.addManyAt(index, count); | |
| 852 | const new_len = try addOrOom(self.items.len, count); | |
| 853 | self.pointer_stability.assertUnlocked(); | |
| 854 | ||
| 855 | if (self.capacity >= new_len) | |
| 856 | return addManyAtAssumeCapacity(self, index, count); | |
| 857 | ||
| 858 | // Here we avoid copying allocated but unused bytes by | |
| 859 | // attempting a resize in place, and falling back to allocating | |
| 860 | // a new buffer and doing our own copy. With a realloc() call, | |
| 861 | // the allocator implementation would pointlessly copy our | |
| 862 | // extra capacity. | |
| 863 | const new_capacity = Aligned(T, alignment).growCapacity(new_len); | |
| 864 | const old_memory = self.allocatedSlice(); | |
| 865 | if (gpa.remap(old_memory, new_capacity)) |new_memory| { | |
| 866 | self.items.ptr = new_memory.ptr; | |
| 867 | self.capacity = new_memory.len; | |
| 868 | return addManyAtAssumeCapacity(self, index, count); | |
| 869 | } | |
| 870 | ||
| 871 | // Make a new allocation, avoiding `ensureTotalCapacity` in order | |
| 872 | // to avoid extra memory copies. | |
| 873 | const new_memory = try gpa.alignedAlloc(T, alignment, new_capacity); | |
| 874 | const to_move = self.items[index..]; | |
| 875 | @memcpy(new_memory[0..index], self.items[0..index]); | |
| 876 | @memcpy(new_memory[index + count ..][0..to_move.len], to_move); | |
| 877 | gpa.free(old_memory); | |
| 878 | self.items = new_memory[0..new_len]; | |
| 879 | self.capacity = new_memory.len; | |
| 880 | // The inserted elements at `new_memory[index..][0..count]` have | |
| 881 | // already been set to `undefined` by memory allocation. | |
| 882 | return new_memory[index..][0..count]; | |
| 820 | 883 | } |
| 821 | 884 | |
| 822 | 885 | /// Add `count` new elements at position `index`, which have |
| 823 | 886 | /// `undefined` values. Returns a slice pointing to the newly allocated |
| 824 | 887 | /// elements, which becomes invalid after various `ArrayList` |
| 825 | 888 | /// operations. |
| 889 | /// Invalidates pre-existing pointers to elements at and after `index`. | |
| 826 | 890 | /// Asserts that the list has capacity for the additional items. |
| 827 | 891 | /// Asserts that the index is in bounds or equal to the length. |
| 828 | 892 | pub fn addManyAtAssumeCapacity(self: *Self, index: usize, count: usize) []T { |
| 829 | self.pointer_stability.lock(); | |
| 830 | defer self.pointer_stability.unlock(); | |
| 831 | ||
| 893 | self.pointer_stability.assertUnlocked(); | |
| 832 | 894 | const new_len = self.items.len + count; |
| 833 | 895 | assert(self.capacity >= new_len); |
| 834 | 896 | const to_move = self.items[index..]; |
| ... | ... | @@ -843,17 +905,16 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { |
| 843 | 905 | /// `undefined` values, returning a slice pointing to the newly |
| 844 | 906 | /// allocated elements, which becomes invalid after various `ArrayList` |
| 845 | 907 | /// operations. |
| 846 | /// | |
| 908 | /// Invalidates pre-existing pointers to elements at and after `index`. | |
| 847 | 909 | /// If the list lacks unused capacity for the additional items, returns |
| 848 | 910 | /// `error.OutOfMemory`. |
| 849 | /// | |
| 850 | 911 | /// Asserts that the index is in bounds or equal to the length. |
| 851 | 912 | pub fn addManyAtBounded(self: *Self, index: usize, count: usize) error{OutOfMemory}![]T { |
| 852 | 913 | if (self.capacity - self.items.len < count) return error.OutOfMemory; |
| 853 | 914 | return addManyAtAssumeCapacity(self, index, count); |
| 854 | 915 | } |
| 855 | 916 | |
| 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 | 918 | /// This operation is O(N). |
| 858 | 919 | /// Invalidates pre-existing pointers to elements at and after `index`. |
| 859 | 920 | /// 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 | 934 | @memcpy(dst, items); |
| 874 | 935 | } |
| 875 | 936 | |
| 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 | 938 | /// This operation is O(N). |
| 878 | 939 | /// Invalidates pre-existing pointers to elements at and after `index`. |
| 879 | 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 | 948 | @memcpy(dst, items); |
| 888 | 949 | } |
| 889 | 950 | |
| 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 | 952 | /// This operation is O(N). |
| 892 | 953 | /// Invalidates pre-existing pointers to elements at and after `index`. |
| 893 | 954 | /// 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 | 964 | } |
| 904 | 965 | |
| 905 | 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 | 970 | /// Asserts that the range is in bounds. |
| 908 | 971 | pub fn replaceRange( |
| 909 | 972 | self: *Self, |
| ... | ... | @@ -917,9 +980,8 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { |
| 917 | 980 | } |
| 918 | 981 | |
| 919 | 982 | /// Grows or shrinks the list as necessary. |
| 920 | /// | |
| 921 | /// Never invalidates element pointers. | |
| 922 | /// | |
| 983 | /// Invalidates pointers to elements at and above index `start + len` | |
| 984 | /// when `len` and `new_items.len` are unequal. | |
| 923 | 985 | /// Asserts the capacity is enough for additional items. |
| 924 | 986 | pub fn replaceRangeAssumeCapacity( |
| 925 | 987 | self: *Self, |
| ... | ... | @@ -928,7 +990,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { |
| 928 | 990 | new_items: []const T, |
| 929 | 991 | ) void { |
| 930 | 992 | std.debug.assert(self.capacity - self.items.len >= new_items.len -| len); |
| 931 | ||
| 993 | self.pointer_stability.assertUnlocked(); | |
| 932 | 994 | const tail = self.items[start + len ..]; |
| 933 | 995 | const vacated = self.items[self.items.len - (len -| new_items.len) ..]; |
| 934 | 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 | 999 | @memset(vacated, undefined); |
| 938 | 1000 | } |
| 939 | 1001 | |
| 940 | /// Grows or shrinks the list as necessary. | |
| 941 | /// | |
| 942 | /// Never invalidates element pointers. | |
| 943 | /// | |
| 1002 | /// Invalidates pointers to elements at and above index `start + len` | |
| 1003 | /// when `len` and `new_items.len` are unequal. | |
| 944 | 1004 | /// If the unused capacity is insufficient for additional items, |
| 945 | 1005 | /// returns `error.OutOfMemory`. |
| 946 | 1006 | pub fn replaceRangeBounded( |
| ... | ... | @@ -1003,6 +1063,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { |
| 1003 | 1063 | /// |
| 1004 | 1064 | /// Invalidates element pointers beyond the first deleted index. |
| 1005 | 1065 | pub fn orderedRemoveMany(self: *Self, sorted_indexes: []const usize) void { |
| 1066 | self.pointer_stability.assertUnlocked(); | |
| 1006 | 1067 | if (sorted_indexes.len == 0) return; |
| 1007 | 1068 | var shift: usize = 1; |
| 1008 | 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 | 1086 | /// This operation is O(1). |
| 1026 | 1087 | /// Asserts that the index is in bounds. |
| 1027 | 1088 | pub fn swapRemove(self: *Self, i: usize) T { |
| 1028 | self.pointer_stability.lock(); | |
| 1029 | defer self.pointer_stability.unlock(); | |
| 1089 | self.pointer_stability.assertUnlocked(); | |
| 1030 | 1090 | const val = self.items[i]; |
| 1031 | 1091 | self.items[i] = self.items[self.items.len - 1]; |
| 1032 | 1092 | self.items[self.items.len - 1] = undefined; |
| ... | ... | @@ -1043,7 +1103,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { |
| 1043 | 1103 | } |
| 1044 | 1104 | |
| 1045 | 1105 | /// Append the slice of items to the list. |
| 1046 | /// | |
| 1106 | /// Never invalidates element pointers. | |
| 1047 | 1107 | /// Asserts that the list can hold the additional items. |
| 1048 | 1108 | pub fn appendSliceAssumeCapacity(self: *Self, items: []const T) void { |
| 1049 | 1109 | const old_len = self.items.len; |
| ... | ... | @@ -1054,7 +1114,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { |
| 1054 | 1114 | } |
| 1055 | 1115 | |
| 1056 | 1116 | /// Append the slice of items to the list. |
| 1057 | /// | |
| 1117 | /// Never invalidates element pointers. | |
| 1058 | 1118 | /// If the list lacks unused capacity for the additional items, returns `error.OutOfMemory`. |
| 1059 | 1119 | pub fn appendSliceBounded(self: *Self, items: []const T) error{OutOfMemory}!void { |
| 1060 | 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 | 1134 | /// |
| 1075 | 1135 | /// Intended to be used only when `appendSliceAssumeCapacity` would be |
| 1076 | 1136 | /// a compile error. |
| 1077 | /// | |
| 1137 | /// Never invalidates element pointers. | |
| 1078 | 1138 | /// Asserts that the list can hold the additional items. |
| 1079 | 1139 | pub fn appendUnalignedSliceAssumeCapacity(self: *Self, items: []align(1) const T) void { |
| 1080 | 1140 | const old_len = self.items.len; |
| ... | ... | @@ -1088,7 +1148,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { |
| 1088 | 1148 | /// |
| 1089 | 1149 | /// Intended to be used only when `appendSliceAssumeCapacity` would be |
| 1090 | 1150 | /// a compile error. |
| 1091 | /// | |
| 1151 | /// Never invalidates element pointers. | |
| 1092 | 1152 | /// If the list lacks unused capacity for the additional items, returns |
| 1093 | 1153 | /// `error.OutOfMemory`. |
| 1094 | 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 | 1156 | return appendUnalignedSliceAssumeCapacity(self, items); |
| 1097 | 1157 | } |
| 1098 | 1158 | |
| 1159 | /// Prints a formatted string into this list. | |
| 1160 | /// Invalidates element pointers if additional memory is needed. | |
| 1099 | 1161 | pub fn print(self: *Self, gpa: Allocator, comptime fmt: []const u8, args: anytype) error{OutOfMemory}!void { |
| 1100 | 1162 | comptime assert(T == u8); |
| 1101 | 1163 | try self.ensureUnusedCapacity(gpa, fmt.len); |
| ... | ... | @@ -1106,6 +1168,9 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { |
| 1106 | 1168 | }; |
| 1107 | 1169 | } |
| 1108 | 1170 | |
| 1171 | /// Prints a formatted string into this list. | |
| 1172 | /// Asserts that there is enough capacity for the write. | |
| 1173 | /// Never invalidates element pointers. | |
| 1109 | 1174 | pub fn printAssumeCapacity(self: *Self, comptime fmt: []const u8, args: anytype) void { |
| 1110 | 1175 | comptime assert(T == u8); |
| 1111 | 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 | 1178 | self.items.len += w.end; |
| 1114 | 1179 | } |
| 1115 | 1180 | |
| 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 | 1184 | pub fn printBounded(self: *Self, comptime fmt: []const u8, args: anytype) error{OutOfMemory}!void { |
| 1117 | 1185 | comptime assert(T == u8); |
| 1118 | 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 | 1256 | /// Asserts that the new length is less than or equal to the previous length. |
| 1189 | 1257 | /// If succeds capacity is guaranteed to be equal to the length. |
| 1190 | 1258 | pub fn shrinkAndFreePrecise(self: *Self, gpa: Allocator, new_len: usize) Allocator.Error!void { |
| 1191 | self.pointer_stability.lock(); | |
| 1192 | defer self.pointer_stability.unlock(); | |
| 1259 | self.pointer_stability.assertUnlocked(); | |
| 1193 | 1260 | assert(new_len <= self.items.len); |
| 1194 | 1261 | |
| 1195 | 1262 | if (@sizeOf(T) == 0) { |
| ... | ... | @@ -1243,8 +1310,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { |
| 1243 | 1310 | /// Keeps capacity the same. |
| 1244 | 1311 | /// Asserts that the new length is less than or equal to the previous length. |
| 1245 | 1312 | pub fn shrinkRetainingCapacity(self: *Self, new_len: usize) void { |
| 1246 | self.pointer_stability.lock(); | |
| 1247 | defer self.pointer_stability.unlock(); | |
| 1313 | self.pointer_stability.assertUnlocked(); | |
| 1248 | 1314 | |
| 1249 | 1315 | assert(new_len <= self.items.len); |
| 1250 | 1316 | @memset(self.items[new_len..], undefined); |
| ... | ... | @@ -1254,16 +1320,14 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { |
| 1254 | 1320 | /// Reduce length to 0. |
| 1255 | 1321 | /// Invalidates all element pointers. |
| 1256 | 1322 | pub fn clearRetainingCapacity(self: *Self) void { |
| 1257 | self.pointer_stability.lock(); | |
| 1258 | defer self.pointer_stability.unlock(); | |
| 1323 | self.pointer_stability.assertUnlocked(); | |
| 1259 | 1324 | @memset(self.items, undefined); |
| 1260 | 1325 | self.items.len = 0; |
| 1261 | 1326 | } |
| 1262 | 1327 | |
| 1263 | 1328 | /// Invalidates all element pointers. |
| 1264 | 1329 | pub fn clearAndFree(self: *Self, gpa: Allocator) void { |
| 1265 | self.pointer_stability.lock(); | |
| 1266 | defer self.pointer_stability.unlock(); | |
| 1330 | self.pointer_stability.assertUnlocked(); | |
| 1267 | 1331 | gpa.free(self.allocatedSlice()); |
| 1268 | 1332 | self.items.len = 0; |
| 1269 | 1333 | self.capacity = 0; |
| ... | ... | @@ -1281,8 +1345,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { |
| 1281 | 1345 | /// modify the array so that it can hold exactly `new_capacity` items. |
| 1282 | 1346 | /// Invalidates element pointers if additional memory is needed. |
| 1283 | 1347 | pub fn ensureTotalCapacityPrecise(self: *Self, gpa: Allocator, new_capacity: usize) Allocator.Error!void { |
| 1284 | self.pointer_stability.lock(); | |
| 1285 | defer self.pointer_stability.unlock(); | |
| 1348 | self.pointer_stability.assertUnlocked(); | |
| 1286 | 1349 | |
| 1287 | 1350 | if (@sizeOf(T) == 0) { |
| 1288 | 1351 | self.capacity = math.maxInt(usize); |
| ... | ... | @@ -1327,7 +1390,8 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { |
| 1327 | 1390 | } |
| 1328 | 1391 | |
| 1329 | 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 | 1395 | pub fn addOne(self: *Self, gpa: Allocator) Allocator.Error!*T { |
| 1332 | 1396 | // This can never overflow because `self.items` can never occupy the whole address space |
| 1333 | 1397 | const newlen = self.items.len + 1; |
| ... | ... | @@ -1336,11 +1400,8 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { |
| 1336 | 1400 | } |
| 1337 | 1401 | |
| 1338 | 1402 | /// Increase length by 1, returning pointer to the new item. |
| 1339 | /// | |
| 1340 | 1403 | /// Never invalidates element pointers. |
| 1341 | /// | |
| 1342 | /// The returned element pointer becomes invalid when the list is resized. | |
| 1343 | /// | |
| 1404 | /// The returned pointer may be invalidated by further operations to this list. | |
| 1344 | 1405 | /// Asserts that the list can hold one additional item. |
| 1345 | 1406 | pub fn addOneAssumeCapacity(self: *Self) *T { |
| 1346 | 1407 | assert(self.items.len < self.capacity); |
| ... | ... | @@ -1350,11 +1411,8 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { |
| 1350 | 1411 | } |
| 1351 | 1412 | |
| 1352 | 1413 | /// Increase length by 1, returning pointer to the new item. |
| 1353 | /// | |
| 1354 | 1414 | /// Never invalidates element pointers. |
| 1355 | /// | |
| 1356 | /// The returned element pointer becomes invalid when the list is resized. | |
| 1357 | /// | |
| 1415 | /// The returned pointer may be invalidated by further operations to this list. | |
| 1358 | 1416 | /// If the list lacks unused capacity for the additional item, returns `error.OutOfMemory`. |
| 1359 | 1417 | pub fn addOneBounded(self: *Self) error{OutOfMemory}!*T { |
| 1360 | 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 | 1420 | } |
| 1363 | 1421 | |
| 1364 | 1422 | /// Resize the array, adding `n` new elements, which have `undefined` values. |
| 1423 | /// Invalidates element pointers if additional memory is required. | |
| 1365 | 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 | 1426 | pub fn addManyAsArray(self: *Self, gpa: Allocator, comptime n: usize) Allocator.Error!*[n]T { |
| 1368 | 1427 | const prev_len = self.items.len; |
| 1369 | 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 | 1430 | } |
| 1372 | 1431 | |
| 1373 | 1432 | /// Resize the array, adding `n` new elements, which have `undefined` values. |
| 1374 | /// | |
| 1375 | 1433 | /// The return value is an array pointing to the newly allocated elements. |
| 1376 | /// | |
| 1377 | 1434 | /// Never invalidates element pointers. |
| 1378 | /// | |
| 1379 | /// The returned pointer becomes invalid when the list is resized. | |
| 1380 | /// | |
| 1435 | /// The returned pointer may be invalidated by further operations to this list. | |
| 1381 | 1436 | /// Asserts that the list can hold the additional items. |
| 1382 | 1437 | pub fn addManyAsArrayAssumeCapacity(self: *Self, comptime n: usize) *[n]T { |
| 1383 | 1438 | assert(self.items.len + n <= self.capacity); |
| ... | ... | @@ -1387,13 +1442,9 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { |
| 1387 | 1442 | } |
| 1388 | 1443 | |
| 1389 | 1444 | /// Resize the array, adding `n` new elements, which have `undefined` values. |
| 1390 | /// | |
| 1391 | 1445 | /// The return value is an array pointing to the newly allocated elements. |
| 1392 | /// | |
| 1393 | 1446 | /// Never invalidates element pointers. |
| 1394 | /// | |
| 1395 | /// The returned pointer becomes invalid when the list is resized. | |
| 1396 | /// | |
| 1447 | /// The returned pointer may be invalidated by further operations to this list. | |
| 1397 | 1448 | /// If the list lacks unused capacity for the additional items, returns |
| 1398 | 1449 | /// `error.OutOfMemory`. |
| 1399 | 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 | 1454 | |
| 1404 | 1455 | /// Resize the array, adding `n` new elements, which have `undefined` values. |
| 1405 | 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 | 1458 | /// Resizes list if `self.capacity` is not large enough. |
| 1408 | 1459 | pub fn addManyAsSlice(self: *Self, gpa: Allocator, n: usize) Allocator.Error![]T { |
| 1409 | 1460 | const prev_len = self.items.len; |
| ... | ... | @@ -1413,10 +1464,8 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { |
| 1413 | 1464 | |
| 1414 | 1465 | /// Resizes the array, adding `n` new elements, which have `undefined` |
| 1415 | 1466 | /// values, returning a slice pointing to the newly allocated elements. |
| 1416 | /// | |
| 1417 | /// Never invalidates element pointers. The returned pointer becomes | |
| 1418 | /// invalid when the list is resized. | |
| 1419 | /// | |
| 1467 | /// Never invalidates element pointers. | |
| 1468 | /// The returned pointer may be invalidated by further operations to this list. | |
| 1420 | 1469 | /// Asserts that the list can hold the additional items. |
| 1421 | 1470 | pub fn addManyAsSliceAssumeCapacity(self: *Self, n: usize) []T { |
| 1422 | 1471 | assert(self.items.len + n <= self.capacity); |
| ... | ... | @@ -1427,10 +1476,8 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { |
| 1427 | 1476 | |
| 1428 | 1477 | /// Resizes the array, adding `n` new elements, which have `undefined` |
| 1429 | 1478 | /// values, returning a slice pointing to the newly allocated elements. |
| 1430 | /// | |
| 1431 | /// Never invalidates element pointers. The returned pointer becomes | |
| 1432 | /// invalid when the list is resized. | |
| 1433 | /// | |
| 1479 | /// Never invalidates element pointers. | |
| 1480 | /// The returned pointer may be invalidated by further operations to this list. | |
| 1434 | 1481 | /// If the list lacks unused capacity for the additional items, returns |
| 1435 | 1482 | /// `error.OutOfMemory`. |
| 1436 | 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 | 1490 | /// Invalidates pointers to last element. |
| 1444 | 1491 | pub fn pop(self: *Self) ?T { |
| 1445 | 1492 | if (self.items.len == 0) return null; |
| 1446 | self.pointer_stability.lock(); | |
| 1447 | defer self.pointer_stability.unlock(); | |
| 1493 | self.pointer_stability.assertUnlocked(); | |
| 1448 | 1494 | |
| 1449 | 1495 | const val = self.items[self.items.len - 1]; |
| 1450 | 1496 | self.items[self.items.len - 1] = undefined; |
| ... | ... | @@ -1454,6 +1500,7 @@ pub fn Aligned(comptime T: type, comptime alignment: ?mem.Alignment) type { |
| 1454 | 1500 | |
| 1455 | 1501 | /// Returns a slice of all the items plus the extra capacity, whose memory |
| 1456 | 1502 | /// contents are `undefined`. |
| 1503 | /// The returned pointer may be invalidated by further operations to this list. | |
| 1457 | 1504 | pub fn allocatedSlice(self: Self) Slice { |
| 1458 | 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 | 1509 | /// This can be useful for writing directly into an ArrayList. |
| 1463 | 1510 | /// Note that such an operation must be followed up with a direct |
| 1464 | 1511 | /// modification of `self.items.len`. |
| 1512 | /// The returned pointer may be invalidated by further operations to this list. | |
| 1465 | 1513 | pub fn unusedCapacitySlice(self: Self) []T { |
| 1466 | 1514 | return self.allocatedSlice()[self.items.len..]; |
| 1467 | 1515 | } |
| 1468 | 1516 | |
| 1469 | /// Deprecated in favor of `last`. | |
| 1470 | pub fn getLast(self: Self) ?T { | |
| 1517 | /// Returns the last element from the list, or `null` if the list is | |
| 1518 | /// empty. | |
| 1519 | pub fn last(self: Self) ?T { | |
| 1471 | 1520 | if (self.items.len == 0) return null; |
| 1472 | 1521 | return self.items[self.items.len - 1]; |
| 1473 | 1522 | } |
| 1474 | 1523 | |
| 1475 | 1524 | /// Returns a pointer to the last element from the list, or `null` if |
| 1476 | 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 | 1528 | if (self.items.len == 0) return null; |
| 1479 | 1529 | return &self.items[self.items.len - 1]; |
| 1480 | 1530 | } |
| ... | ... | @@ -2441,6 +2491,10 @@ test "Managed(u0)" { |
| 2441 | 2491 | count += 1; |
| 2442 | 2492 | } |
| 2443 | 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 | } |
| 2445 | 2499 | |
| 2446 | 2500 | test "Managed(?u32).pop()" { |
| ... | ... | @@ -2469,7 +2523,7 @@ test "last" { |
| 2469 | 2523 | try testing.expectEqual(list.last(), null); |
| 2470 | 2524 | |
| 2471 | 2525 | try list.append(a, 2); |
| 2472 | try testing.expectEqual(list.last().?.*, 2); | |
| 2526 | try testing.expectEqual(list.last().?, 2); | |
| 2473 | 2527 | } |
| 2474 | 2528 | |
| 2475 | 2529 | 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 | 2535 | var list: ArrayList(u32) = .{ |
| 2482 | 2536 | .items = undefined, |
| 2483 | 2537 | .capacity = math.maxInt(usize) - 1, |
| 2538 | .pointer_stability = .{}, | |
| 2484 | 2539 | }; |
| 2485 | 2540 | list.items.len = math.maxInt(usize) - 1; |
| 2486 | 2541 | |
| ... | ... | @@ -2499,6 +2554,7 @@ test "return OutOfMemory when capacity would exceed maximum usize integer value" |
| 2499 | 2554 | .items = undefined, |
| 2500 | 2555 | .capacity = math.maxInt(usize) - 1, |
| 2501 | 2556 | .allocator = a, |
| 2557 | .pointer_stability = .{}, | |
| 2502 | 2558 | }; |
| 2503 | 2559 | list.items.len = math.maxInt(usize) - 1; |
| 2504 | 2560 |
lib/std/ascii.zig+3-3| ... | ... | @@ -511,11 +511,11 @@ pub const HexEscape = struct { |
| 511 | 511 | }; |
| 512 | 512 | |
| 513 | 513 | /// Replaces non-ASCII bytes with hex escapes. |
| 514 | pub fn hexEscape(bytes: []const u8, case: std.fmt.Case) std.fmt.Alt(HexEscape, HexEscape.format) { | |
| 515 | return .{ .data = .{ .bytes = bytes, .charset = switch (case) { | |
| 514 | pub fn hexEscape(bytes: []const u8, case: std.fmt.Case) HexEscape { | |
| 515 | return .{ .bytes = bytes, .charset = switch (case) { | |
| 516 | 516 | .lower => HexEscape.lower_charset, |
| 517 | 517 | .upper => HexEscape.upper_charset, |
| 518 | } } }; | |
| 518 | } }; | |
| 519 | 519 | } |
| 520 | 520 | |
| 521 | 521 | test hexEscape { |
lib/std/bit_set.zig-2| ... | ... | @@ -1707,8 +1707,6 @@ fn testStaticBitSet(comptime Set: type) !void { |
| 1707 | 1707 | } |
| 1708 | 1708 | |
| 1709 | 1709 | test Integer { |
| 1710 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 1711 | ||
| 1712 | 1710 | try testStaticBitSet(Integer(0)); |
| 1713 | 1711 | try testStaticBitSet(Integer(1)); |
| 1714 | 1712 | try testStaticBitSet(Integer(2)); |
lib/std/c.zig+52-22| ... | ... | @@ -2821,13 +2821,14 @@ pub const SIG = switch (native_os) { |
| 2821 | 2821 | } |
| 2822 | 2822 | |
| 2823 | 2823 | pub const POLL: SIG = .IO; |
| 2824 | pub const IOT: SIG = .ABRT; | |
| 2825 | pub const CLD: SIG = .CHLD; | |
| 2824 | 2826 | |
| 2825 | 2827 | HUP = 1, |
| 2826 | 2828 | INT = 2, |
| 2827 | 2829 | QUIT = 3, |
| 2828 | 2830 | ILL = 4, |
| 2829 | 2831 | TRAP = 5, |
| 2830 | IOT = 6, | |
| 2831 | 2832 | ABRT = 6, |
| 2832 | 2833 | EMT = 7, |
| 2833 | 2834 | FPE = 8, |
| ... | ... | @@ -2840,7 +2841,6 @@ pub const SIG = switch (native_os) { |
| 2840 | 2841 | TERM = 15, |
| 2841 | 2842 | USR1 = 16, |
| 2842 | 2843 | USR2 = 17, |
| 2843 | CLD = 18, | |
| 2844 | 2844 | CHLD = 18, |
| 2845 | 2845 | PWR = 19, |
| 2846 | 2846 | WINCH = 20, |
| ... | ... | @@ -2991,6 +2991,7 @@ pub const SIG = switch (native_os) { |
| 2991 | 2991 | pub const UNBLOCK = 2; |
| 2992 | 2992 | pub const SETMASK = 3; |
| 2993 | 2993 | |
| 2994 | pub const IO: SIG = .POLL; | |
| 2994 | 2995 | pub const IOT: SIG = .ABRT; |
| 2995 | 2996 | |
| 2996 | 2997 | HUP = 1, |
| ... | ... | @@ -9736,6 +9737,7 @@ pub const SS = switch (native_os) { |
| 9736 | 9737 | |
| 9737 | 9738 | pub const EV = switch (native_os) { |
| 9738 | 9739 | .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => struct { |
| 9740 | // https://github.com/apple-oss-distributions/xnu/blob/main/bsd/sys/event.h | |
| 9739 | 9741 | /// add event to kq (implies enable) |
| 9740 | 9742 | pub const ADD = 0x0001; |
| 9741 | 9743 | /// delete event from kq |
| ... | ... | @@ -9771,11 +9773,14 @@ pub const EV = switch (native_os) { |
| 9771 | 9773 | pub const FLAG0 = 0x1000; |
| 9772 | 9774 | /// filter-specific flag |
| 9773 | 9775 | pub const FLAG1 = 0x2000; |
| 9774 | /// EOF detected | |
| 9776 | /// EOF detected (return value) | |
| 9775 | 9777 | pub const EOF = 0x8000; |
| 9776 | /// error, data contains errno | |
| 9778 | /// error, data contains errno (return value) | |
| 9777 | 9779 | pub const ERROR = 0x4000; |
| 9780 | /// use poll(2) semantics for EVFILT.READ | |
| 9778 | 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 | 9784 | pub const OOBAND = FLAG1; |
| 9780 | 9785 | }, |
| 9781 | 9786 | .dragonfly => struct { |
| ... | ... | @@ -9818,6 +9823,7 @@ pub const EV = switch (native_os) { |
| 9818 | 9823 | pub const EOF = 0x8000; |
| 9819 | 9824 | }, |
| 9820 | 9825 | .freebsd => struct { |
| 9826 | // https://cgit.freebsd.org/src/tree/sys/sys/event.h | |
| 9821 | 9827 | /// add event to kq (implies enable) |
| 9822 | 9828 | pub const ADD = 0x0001; |
| 9823 | 9829 | /// delete event from kq |
| ... | ... | @@ -9826,12 +9832,14 @@ pub const EV = switch (native_os) { |
| 9826 | 9832 | pub const ENABLE = 0x0004; |
| 9827 | 9833 | /// disable event (not reported) |
| 9828 | 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 | 9839 | /// only report one occurrence |
| 9830 | 9840 | pub const ONESHOT = 0x0010; |
| 9831 | 9841 | /// clear event state after reporting |
| 9832 | 9842 | pub const CLEAR = 0x0020; |
| 9833 | /// error, event data contains errno | |
| 9834 | pub const ERROR = 0x4000; | |
| 9835 | 9843 | /// force immediate event output |
| 9836 | 9844 | /// ... with or without ERROR |
| 9837 | 9845 | /// ... use KEVENT_FLAG_ERROR_EVENTS |
| ... | ... | @@ -9839,6 +9847,18 @@ pub const EV = switch (native_os) { |
| 9839 | 9847 | pub const RECEIPT = 0x0040; |
| 9840 | 9848 | /// disable event after reporting |
| 9841 | 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 | 9863 | .openbsd => struct { |
| 9844 | 9864 | pub const ADD = 0x0001; |
| ... | ... | @@ -9962,6 +9982,7 @@ pub const EVFILT = switch (native_os) { |
| 9962 | 9982 | pub const EMPTY = 9; |
| 9963 | 9983 | }, |
| 9964 | 9984 | .freebsd => struct { |
| 9985 | // https://cgit.freebsd.org/src/tree/sys/sys/event.h | |
| 9965 | 9986 | pub const READ = -1; |
| 9966 | 9987 | pub const WRITE = -2; |
| 9967 | 9988 | /// attached to aio requests |
| ... | ... | @@ -9978,12 +9999,18 @@ pub const EVFILT = switch (native_os) { |
| 9978 | 9999 | pub const PROCDESC = -8; |
| 9979 | 10000 | /// Filesystem events |
| 9980 | 10001 | pub const FS = -9; |
| 10002 | /// attached to lio requests | |
| 9981 | 10003 | pub const LIO = -10; |
| 9982 | 10004 | /// User events |
| 9983 | 10005 | pub const USER = -11; |
| 9984 | 10006 | /// Sendfile events |
| 9985 | 10007 | pub const SENDFILE = -12; |
| 10008 | /// empty send socket buf | |
| 9986 | 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 | 10015 | .openbsd => struct { |
| 9989 | 10016 | pub const READ = -1; |
| ... | ... | @@ -10002,6 +10029,7 @@ pub const EVFILT = switch (native_os) { |
| 10002 | 10029 | |
| 10003 | 10030 | pub const NOTE = switch (native_os) { |
| 10004 | 10031 | .driverkit, .ios, .maccatalyst, .macos, .tvos, .visionos, .watchos => struct { |
| 10032 | // https://github.com/apple-oss-distributions/xnu/blob/main/bsd/sys/event.h | |
| 10005 | 10033 | /// On input, TRIGGER causes the event to be triggered for output. |
| 10006 | 10034 | pub const TRIGGER = 0x01000000; |
| 10007 | 10035 | /// ignore input fflags |
| ... | ... | @@ -10033,7 +10061,7 @@ pub const NOTE = switch (native_os) { |
| 10033 | 10061 | pub const RENAME = 0x00000020; |
| 10034 | 10062 | /// vnode access was revoked |
| 10035 | 10063 | pub const REVOKE = 0x00000040; |
| 10036 | /// No specific vnode event: to test for EVFILT_READ activation | |
| 10064 | /// No specific vnode event: to test for EVFILT_READ activation | |
| 10037 | 10065 | pub const NONE = 0x00000080; |
| 10038 | 10066 | /// vnode was unlocked by flock(2) |
| 10039 | 10067 | pub const FUNLOCK = 0x00000100; |
| ... | ... | @@ -10045,7 +10073,7 @@ pub const NOTE = switch (native_os) { |
| 10045 | 10073 | pub const EXEC = 0x20000000; |
| 10046 | 10074 | /// shared with EVFILT_SIGNAL |
| 10047 | 10075 | pub const SIGNAL = 0x08000000; |
| 10048 | /// exit status to be returned, valid for child process only | |
| 10076 | /// exit status to be returned, valid for child process only | |
| 10049 | 10077 | pub const EXITSTATUS = 0x04000000; |
| 10050 | 10078 | /// provide details on reasons for exit |
| 10051 | 10079 | pub const EXIT_DETAIL = 0x02000000; |
| ... | ... | @@ -10056,11 +10084,11 @@ pub const NOTE = switch (native_os) { |
| 10056 | 10084 | pub const EXIT_DECRYPTFAIL = 0x00010000; |
| 10057 | 10085 | pub const EXIT_MEMORY = 0x00020000; |
| 10058 | 10086 | pub const EXIT_CSERROR = 0x00040000; |
| 10059 | /// will react on memory pressure | |
| 10087 | /// will react on memory pressure | |
| 10060 | 10088 | pub const VM_PRESSURE = 0x80000000; |
| 10061 | /// will quit on memory pressure, possibly after cleaning up dirty state | |
| 10089 | /// will quit on memory pressure, possibly after cleaning up dirty state | |
| 10062 | 10090 | pub const VM_PRESSURE_TERMINATE = 0x40000000; |
| 10063 | /// will quit immediately on memory pressure | |
| 10091 | /// will quit immediately on memory pressure | |
| 10064 | 10092 | pub const VM_PRESSURE_SUDDEN_TERMINATE = 0x20000000; |
| 10065 | 10093 | /// there was an error |
| 10066 | 10094 | pub const VM_ERROR = 0x10000000; |
| ... | ... | @@ -10078,6 +10106,9 @@ pub const NOTE = switch (native_os) { |
| 10078 | 10106 | pub const CRITICAL = 0x00000020; |
| 10079 | 10107 | /// system does maximum timer coalescing |
| 10080 | 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 | 10112 | pub const MACH_CONTINUOUS_TIME = 0x00000080; |
| 10082 | 10113 | /// data is mach absolute time units |
| 10083 | 10114 | pub const MACHTIME = 0x00000100; |
| ... | ... | @@ -11237,31 +11268,30 @@ pub const signalfd_siginfo = illumos.signalfd_siginfo; |
| 11237 | 11268 | pub const taskid_t = illumos.taskid_t; |
| 11238 | 11269 | pub const zoneid_t = illumos.zoneid_t; |
| 11239 | 11270 | |
| 11271 | pub const B_ABSOLUTE_TIMEOUT = haiku.B_ABSOLUTE_TIMEOUT; | |
| 11272 | pub const B_OS_NAME_LENGTH = haiku.B_OS_NAME_LENGTH; | |
| 11273 | pub const B_TIMEOUT_REAL_TIME_BASE = haiku.B_TIMEOUT_REAL_TIME_BASE; | |
| 11240 | 11274 | pub const DirEnt = haiku.DirEnt; |
| 11241 | pub const _get_next_area_info = haiku._get_next_area_info; | |
| 11242 | pub const _get_next_image_info = haiku._get_next_image_info; | |
| 11243 | pub const _get_team_info = haiku._get_team_info; | |
| 11244 | pub const _kern_get_current_team = haiku._kern_get_current_team; | |
| 11275 | pub const _kern_acquire_sem_etc = haiku._kern_acquire_sem_etc; | |
| 11276 | pub const _kern_create_sem = haiku._kern_create_sem; | |
| 11277 | pub const _kern_delete_sem = haiku._kern_delete_sem; | |
| 11245 | 11278 | pub const _kern_open_dir = haiku._kern_open_dir; |
| 11246 | 11279 | pub const _kern_read_dir = haiku._kern_read_dir; |
| 11247 | 11280 | pub const _kern_read_stat = haiku._kern_read_stat; |
| 11281 | pub const _kern_release_sem_etc = haiku._kern_release_sem_etc; | |
| 11248 | 11282 | pub const _kern_rewind_dir = haiku._kern_rewind_dir; |
| 11249 | pub const readv_pos = haiku.readv_pos; | |
| 11250 | pub const writev_pos = haiku.writev_pos; | |
| 11251 | 11283 | pub const area_id = haiku.area_id; |
| 11252 | pub const area_info = haiku.area_info; | |
| 11253 | pub const directory_which = haiku.directory_which; | |
| 11254 | pub const find_directory = haiku.find_directory; | |
| 11255 | 11284 | pub const find_thread = haiku.find_thread; |
| 11256 | 11285 | pub const get_system_info = haiku.get_system_info; |
| 11257 | pub const image_info = haiku.image_info; | |
| 11286 | pub const on_exit_thread = haiku.on_exit_thread; | |
| 11258 | 11287 | pub const port_id = haiku.port_id; |
| 11288 | pub const readv_pos = haiku.readv_pos; | |
| 11259 | 11289 | pub const sem_id = haiku.sem_id; |
| 11260 | 11290 | pub const status_t = haiku.status_t; |
| 11261 | 11291 | pub const system_info = haiku.system_info; |
| 11262 | 11292 | pub const team_id = haiku.team_id; |
| 11263 | pub const team_info = haiku.team_info; | |
| 11264 | 11293 | pub const thread_id = haiku.thread_id; |
| 11294 | pub const writev_pos = haiku.writev_pos; | |
| 11265 | 11295 | |
| 11266 | 11296 | pub const AUTH = openbsd.AUTH; |
| 11267 | 11297 | pub const BI = openbsd.BI; |
lib/std/c/darwin/dispatch.zig+2-2| ... | ... | @@ -44,8 +44,8 @@ pub const once_t = enum(isize) { |
| 44 | 44 | once_f(predicate, context, function); |
| 45 | 45 | } else asm volatile ("" ::: .{ .memory = true }); |
| 46 | 46 | switch (builtin.mode) { |
| 47 | .Debug, .ReleaseSafe => {}, | |
| 48 | .ReleaseFast, .ReleaseSmall => if (predicate.* != .done) unreachable, | |
| 47 | .debug, .safe => {}, | |
| 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 | 1 | const std = @import("../std.zig"); |
| 2 | const assert = std.debug.assert; | |
| 3 | 2 | const builtin = @import("builtin"); |
| 4 | const maxInt = std.math.maxInt; | |
| 5 | const iovec = std.posix.iovec; | |
| 6 | const iovec_const = std.posix.iovec_const; | |
| 7 | const socklen_t = std.c.socklen_t; | |
| 3 | const assert = std.debug.assert; | |
| 8 | 4 | const fd_t = std.c.fd_t; |
| 9 | 5 | const off_t = std.c.off_t; |
| 10 | const PATH_MAX = std.c.PATH_MAX; | |
| 11 | const uid_t = std.c.uid_t; | |
| 12 | const gid_t = std.c.gid_t; | |
| 13 | 6 | const dev_t = std.c.dev_t; |
| 14 | 7 | const ino_t = std.c.ino_t; |
| 15 | 8 | |
| ... | ... | @@ -17,52 +10,27 @@ comptime { |
| 17 | 10 | assert(builtin.os.tag == .haiku); // Prevent access of std.c symbols on wrong OS. |
| 18 | 11 | } |
| 19 | 12 | |
| 20 | pub extern "root" fn _errnop() *i32; | |
| 21 | pub extern "root" fn find_directory(which: directory_which, volume: i32, createIt: bool, path_ptr: [*]u8, length: i32) u64; | |
| 22 | pub extern "root" fn find_thread(thread_name: ?*anyopaque) i32; | |
| 23 | pub extern "root" fn get_system_info(system_info: *system_info) usize; | |
| 24 | pub extern "root" fn _get_team_info(team: i32, team_info: *team_info, size: usize) i32; | |
| 25 | pub extern "root" fn _get_next_area_info(team: i32, cookie: *i64, area_info: *area_info, size: usize) i32; | |
| 26 | pub extern "root" fn _get_next_image_info(team: i32, cookie: *i32, image_info: *image_info, size: usize) i32; | |
| 27 | pub extern "root" fn _kern_get_current_team() team_id; | |
| 13 | pub const B_OS_NAME_LENGTH = 32; | |
| 14 | pub const B_ABSOLUTE_TIMEOUT = 0x10; | |
| 15 | pub const B_TIMEOUT_REAL_TIME_BASE = 0x40; | |
| 16 | ||
| 17 | pub extern "root" fn _kern_create_sem(count: c_int, name: ?[*:0]const u8) sem_id; | |
| 18 | pub extern "root" fn _kern_delete_sem(id: sem_id) status_t; | |
| 19 | pub extern "root" fn _kern_acquire_sem_etc(id: sem_id, count: u32, flags: u32, timeout: i64) status_t; | |
| 20 | pub extern "root" fn _kern_release_sem_etc(id: sem_id, count: u32, flags: u32) status_t; | |
| 28 | 21 | pub extern "root" fn _kern_open_dir(fd: fd_t, path: [*:0]const u8) fd_t; |
| 29 | 22 | pub extern "root" fn _kern_read_dir(fd: fd_t, buffer: [*]u8, bufferSize: usize, maxCount: u32) isize; |
| 30 | 23 | pub extern "root" fn _kern_rewind_dir(fd: fd_t) status_t; |
| 31 | 24 | pub extern "root" fn _kern_read_stat(fd: fd_t, path: [*:0]const u8, traverseLink: bool, stat: *std.c.Stat, statSize: usize) status_t; |
| 32 | pub extern "root" fn readv_pos(fd: fd_t, pos: off_t, vec: [*]const std.c.iovec, count: i32) isize; | |
| 33 | pub extern "root" fn writev_pos(fd: fd_t, pos: off_t, vec: [*]const std.c.iovec_const, count: i32) isize; | |
| 34 | 25 | |
| 35 | pub const area_info = extern struct { | |
| 36 | area: u32, | |
| 37 | name: [32]u8, | |
| 38 | size: usize, | |
| 39 | lock: u32, | |
| 40 | protection: u32, | |
| 41 | team_id: i32, | |
| 42 | ram_size: u32, | |
| 43 | copy_count: u32, | |
| 44 | in_count: u32, | |
| 45 | out_count: u32, | |
| 46 | address: *anyopaque, | |
| 47 | }; | |
| 26 | pub extern "root" fn on_exit_thread(callback: *const fn (?*anyopaque) callconv(.c) void, data: ?*anyopaque) status_t; | |
| 27 | pub extern "root" fn find_thread(name: ?[*:0]const u8) thread_id; | |
| 28 | pub extern "root" fn get_system_info(info: *system_info) status_t; | |
| 48 | 29 | |
| 49 | pub const image_info = extern struct { | |
| 50 | id: u32, | |
| 51 | image_type: u32, | |
| 52 | sequence: i32, | |
| 53 | init_order: i32, | |
| 54 | init_routine: *anyopaque, | |
| 55 | term_routine: *anyopaque, | |
| 56 | device: i32, | |
| 57 | node: i64, | |
| 58 | name: [PATH_MAX]u8, | |
| 59 | text: *anyopaque, | |
| 60 | data: *anyopaque, | |
| 61 | text_size: i32, | |
| 62 | data_size: i32, | |
| 63 | api_version: i32, | |
| 64 | abi: i32, | |
| 65 | }; | |
| 30 | pub extern "root" fn _errnop() *i32; | |
| 31 | ||
| 32 | pub extern "root" fn readv_pos(fd: fd_t, pos: off_t, vec: [*]const std.c.iovec, count: i32) isize; | |
| 33 | pub extern "root" fn writev_pos(fd: fd_t, pos: off_t, vec: [*]const std.c.iovec_const, count: i32) isize; | |
| 66 | 34 | |
| 67 | 35 | pub const system_info = extern struct { |
| 68 | 36 | boot_time: i64, |
| ... | ... | @@ -86,31 +54,12 @@ pub const system_info = extern struct { |
| 86 | 54 | max_teams: u32, |
| 87 | 55 | used_teams: u32, |
| 88 | 56 | kernel_name: [256]u8, |
| 89 | kernel_build_date: [32]u8, | |
| 90 | kernel_build_time: [32]u8, | |
| 57 | kernel_build_date: [B_OS_NAME_LENGTH]u8, | |
| 58 | kernel_build_time: [B_OS_NAME_LENGTH]u8, | |
| 91 | 59 | kernel_version: i64, |
| 92 | 60 | abi: u32, |
| 93 | 61 | }; |
| 94 | 62 | |
| 95 | pub 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 | ||
| 108 | pub const directory_which = enum(i32) { | |
| 109 | B_USER_SETTINGS_DIRECTORY = 0xbbe, | |
| 110 | ||
| 111 | _, | |
| 112 | }; | |
| 113 | ||
| 114 | 63 | pub const area_id = i32; |
| 115 | 64 | pub const port_id = i32; |
| 116 | 65 | pub 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 | 738 | |
| 739 | 739 | fn clenHlen(freqs: [19]u16) u4 { |
| 740 | 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 | 742 | const V = @Vector(16, u16); |
| 743 | 743 | const hlen_mul: V = comptime m: { |
| 744 | 744 | var hlen_mul: [16]u16 = undefined; |
lib/std/compress/flate/token.zig+3-3| ... | ... | @@ -57,9 +57,9 @@ const fixed_dist = blk: { |
| 57 | 57 | }; |
| 58 | 58 | |
| 59 | 59 | // 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. | |
| 61 | pub const LenCode = if (builtin.mode != .ReleaseSmall) LookupLenCode else ShortLenCode; | |
| 62 | pub const DistCode = if (builtin.mode != .ReleaseSmall) LookupDistCode else ShortDistCode; | |
| 60 | // do via lookup table. For -Osmall, we do all mathematically to save space. | |
| 61 | pub const LenCode = if (builtin.mode != .small) LookupLenCode else ShortLenCode; | |
| 62 | pub const DistCode = if (builtin.mode != .small) LookupDistCode else ShortDistCode; | |
| 63 | 63 | const ShortLenCode = ShortCode(u8, u2, u3, true); |
| 64 | 64 | const ShortDistCode = ShortCode(u15, u1, u4, false); |
| 65 | 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 | 7 | |
| 8 | 8 | // Inline conditionally, when it can result in large code generation. |
| 9 | 9 | const bloaty_inline: std.builtin.CallingConvention = switch (builtin.mode) { |
| 10 | .ReleaseSafe, .ReleaseFast => .@"inline", | |
| 11 | .Debug, .ReleaseSmall => .auto, | |
| 10 | .safe, .fast => .@"inline", | |
| 11 | .debug, .small => .auto, | |
| 12 | 12 | }; |
| 13 | 13 | |
| 14 | 14 | pub const Fe = struct { |
lib/std/crypto/Certificate.zig+81-10| ... | ... | @@ -175,6 +175,8 @@ pub const GeneralNameTag = enum(u5) { |
| 175 | 175 | _, |
| 176 | 176 | }; |
| 177 | 177 | |
| 178 | const net = @import("../Io/net.zig"); | |
| 179 | ||
| 178 | 180 | pub const Parsed = struct { |
| 179 | 181 | certificate: Certificate, |
| 180 | 182 | issuer_slice: Slice, |
| ... | ... | @@ -315,6 +317,7 @@ pub const Parsed = struct { |
| 315 | 317 | // what to check. Otherwise, only the common name is checked. |
| 316 | 318 | const subject_alt_name = parsed_subject.subjectAltName(); |
| 317 | 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 | 321 | if (checkHostName(host_name, parsed_subject.commonName())) { |
| 319 | 322 | return; |
| 320 | 323 | } else { |
| ... | ... | @@ -332,6 +335,10 @@ pub const Parsed = struct { |
| 332 | 335 | const dns_name = subject_alt_name[general_name.slice.start..general_name.slice.end]; |
| 333 | 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 | 342 | else => {}, |
| 336 | 343 | } |
| 337 | 344 | } |
| ... | ... | @@ -376,6 +383,22 @@ pub const Parsed = struct { |
| 376 | 383 | |
| 377 | 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 | }; |
| 380 | 403 | |
| 381 | 404 | test "Parsed.checkHostName RFC 6125 compliance" { |
| ... | ... | @@ -417,6 +440,39 @@ test "Parsed.checkHostName RFC 6125 compliance" { |
| 417 | 440 | try expectEqual(false, Parsed.checkHostName("example.com", "*.")); |
| 418 | 441 | } |
| 419 | 442 | |
| 443 | test "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 | ||
| 420 | 476 | pub const ParseError = der.Element.ParseError || ParseVersionError || ParseTimeError || ParseEnumError || ParseBitStringError; |
| 421 | 477 | |
| 422 | 478 | pub fn parse(cert: Certificate) ParseError!Parsed { |
| ... | ... | @@ -793,7 +849,7 @@ fn verifyRsa( |
| 793 | 849 | inline 128, 256, 384, 512 => |modulus_len| { |
| 794 | 850 | const public_key = rsa.PublicKey.fromBytes(exponent, modulus) catch |
| 795 | 851 | return error.CertificateSignatureInvalid; |
| 796 | rsa.PKCS1v1_5Signature.verify(modulus_len, sig[0..modulus_len].*, msg, public_key, Hash) catch | |
| 852 | rsa.PKCS1v1_5Signature.verify(modulus_len, sig[0..modulus_len], msg, public_key, Hash) catch | |
| 797 | 853 | return error.CertificateSignatureInvalid; |
| 798 | 854 | }, |
| 799 | 855 | else => return error.CertificateSignatureUnsupportedBitCount, |
| ... | ... | @@ -983,7 +1039,7 @@ pub const rsa = struct { |
| 983 | 1039 | |
| 984 | 1040 | pub fn concatVerify( |
| 985 | 1041 | comptime modulus_len: usize, |
| 986 | sig: [modulus_len]u8, | |
| 1042 | sig: *const [modulus_len]u8, | |
| 987 | 1043 | msg: []const []const u8, |
| 988 | 1044 | public_key: PublicKey, |
| 989 | 1045 | comptime Hash: type, |
| ... | ... | @@ -1092,9 +1148,9 @@ pub const rsa = struct { |
| 1092 | 1148 | } |
| 1093 | 1149 | var m_p_buf: [8 + Hash.digest_length + Hash.digest_length]u8 = undefined; |
| 1094 | 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))); | |
| 1096 | std.mem.copyForwards(u8, m_p[8..], &mHash); | |
| 1097 | std.mem.copyForwards(u8, m_p[(8 + Hash.digest_length)..], salt); | |
| 1151 | @memmove(m_p[0..8], @as(*const [8]u8, &@splat(0))); | |
| 1152 | @memmove(m_p[8..][0..Hash.digest_length], &mHash); | |
| 1153 | @memmove(m_p[(8 + Hash.digest_length)..], salt); | |
| 1098 | 1154 | |
| 1099 | 1155 | // 13. Let H' = Hash(M'), an octet string of length hLen. |
| 1100 | 1156 | var h_p: [Hash.digest_length]u8 = undefined; |
| ... | ... | @@ -1136,7 +1192,7 @@ pub const rsa = struct { |
| 1136 | 1192 | |
| 1137 | 1193 | pub fn verify( |
| 1138 | 1194 | comptime modulus_len: usize, |
| 1139 | sig: [modulus_len]u8, | |
| 1195 | sig: *const [modulus_len]u8, | |
| 1140 | 1196 | msg: []const u8, |
| 1141 | 1197 | public_key: PublicKey, |
| 1142 | 1198 | comptime Hash: type, |
| ... | ... | @@ -1146,7 +1202,7 @@ pub const rsa = struct { |
| 1146 | 1202 | |
| 1147 | 1203 | pub fn concatVerify( |
| 1148 | 1204 | comptime modulus_len: usize, |
| 1149 | sig: [modulus_len]u8, | |
| 1205 | sig: *const [modulus_len]u8, | |
| 1150 | 1206 | msg: []const []const u8, |
| 1151 | 1207 | public_key: PublicKey, |
| 1152 | 1208 | comptime Hash: type, |
| ... | ... | @@ -1187,6 +1243,11 @@ pub const rsa = struct { |
| 1187 | 1243 | // DigestInfo value (see the notes below) and let tLen be the length |
| 1188 | 1244 | // in octets of T. |
| 1189 | 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 | 1251 | crypto.hash.Sha1 => .{ |
| 1191 | 1252 | 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, |
| 1192 | 1253 | 0x03, 0x02, 0x1a, 0x05, 0x00, 0x04, 0x14, |
| ... | ... | @@ -1211,7 +1272,17 @@ pub const rsa = struct { |
| 1211 | 1272 | 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, |
| 1212 | 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 | 1287 | em_index -= hash_der.len; |
| 1217 | 1288 | @memcpy(em[em_index..][0..hash_der.len], hash_der); |
| ... | ... | @@ -1292,8 +1363,8 @@ pub const rsa = struct { |
| 1292 | 1363 | |
| 1293 | 1364 | const EncryptError = error{MessageTooLong}; |
| 1294 | 1365 | |
| 1295 | fn encrypt(comptime modulus_len: usize, msg: [modulus_len]u8, public_key: PublicKey) EncryptError![modulus_len]u8 { | |
| 1296 | const m = Fe.fromBytes(public_key.n, &msg, .big) catch return error.MessageTooLong; | |
| 1366 | fn encrypt(comptime modulus_len: usize, msg: *const [modulus_len]u8, public_key: PublicKey) EncryptError![modulus_len]u8 { | |
| 1367 | const m = Fe.fromBytes(public_key.n, msg, .big) catch return error.MessageTooLong; | |
| 1297 | 1368 | const e = public_key.n.powPublic(m, public_key.e) catch unreachable; |
| 1298 | 1369 | var res: [modulus_len]u8 = undefined; |
| 1299 | 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 | 6 | const has_avx = builtin.cpu.has(.x86, .avx); |
| 7 | 7 | const has_armaes = builtin.cpu.has(.aarch64, .aes); |
| 8 | 8 | // C backend doesn't currently support passing vectors to inline asm. |
| 9 | const impl = if (builtin.cpu.arch == .x86_64 and builtin.zig_backend != .stage2_c and has_aesni and has_avx) impl: { | |
| 9 | const impl = if (builtin.cpu.arch == .x86_64 and has_aesni and has_avx) impl: { | |
| 10 | 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 | 12 | break :impl @import("aes/armcrypto.zig"); |
| 13 | 13 | } else impl: { |
| 14 | 14 | break :impl @import("aes/soft.zig"); |
lib/std/crypto/aes_ocb.zig-10| ... | ... | @@ -262,8 +262,6 @@ const hexToBytes = std.fmt.hexToBytes; |
| 262 | 262 | const testing = std.testing; |
| 263 | 263 | |
| 264 | 264 | test "AesOcb test vector 1" { |
| 265 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 266 | ||
| 267 | 265 | var k: [Aes128Ocb.key_length]u8 = undefined; |
| 268 | 266 | var nonce: [Aes128Ocb.nonce_length]u8 = undefined; |
| 269 | 267 | var tag: [Aes128Ocb.tag_length]u8 = undefined; |
| ... | ... | @@ -281,8 +279,6 @@ test "AesOcb test vector 1" { |
| 281 | 279 | } |
| 282 | 280 | |
| 283 | 281 | test "AesOcb test vector 2" { |
| 284 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 285 | ||
| 286 | 282 | var k: [Aes128Ocb.key_length]u8 = undefined; |
| 287 | 283 | var nonce: [Aes128Ocb.nonce_length]u8 = undefined; |
| 288 | 284 | var tag: [Aes128Ocb.tag_length]u8 = undefined; |
| ... | ... | @@ -303,8 +299,6 @@ test "AesOcb test vector 2" { |
| 303 | 299 | } |
| 304 | 300 | |
| 305 | 301 | test "AesOcb test vector 3" { |
| 306 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 307 | ||
| 308 | 302 | var k: [Aes128Ocb.key_length]u8 = undefined; |
| 309 | 303 | var nonce: [Aes128Ocb.nonce_length]u8 = undefined; |
| 310 | 304 | var tag: [Aes128Ocb.tag_length]u8 = undefined; |
| ... | ... | @@ -329,8 +323,6 @@ test "AesOcb test vector 3" { |
| 329 | 323 | } |
| 330 | 324 | |
| 331 | 325 | test "AesOcb test vector 4" { |
| 332 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 333 | ||
| 334 | 326 | var k: [Aes128Ocb.key_length]u8 = undefined; |
| 335 | 327 | var nonce: [Aes128Ocb.nonce_length]u8 = undefined; |
| 336 | 328 | var tag: [Aes128Ocb.tag_length]u8 = undefined; |
| ... | ... | @@ -356,8 +348,6 @@ test "AesOcb test vector 4" { |
| 356 | 348 | } |
| 357 | 349 | |
| 358 | 350 | test "AesOcb in-place encryption-decryption" { |
| 359 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 360 | ||
| 361 | 351 | var k: [Aes128Ocb.key_length]u8 = undefined; |
| 362 | 352 | var nonce: [Aes128Ocb.nonce_length]u8 = undefined; |
| 363 | 353 | var tag: [Aes128Ocb.tag_length]u8 = undefined; |
lib/std/crypto/benchmark.zig+3-3| ... | ... | @@ -454,8 +454,8 @@ fn benchmarkPwhash( |
| 454 | 454 | |
| 455 | 455 | const strHash = ty.strHash; |
| 456 | 456 | const strHashFnInfo = @typeInfo(@TypeOf(strHash)).@"fn"; |
| 457 | const needs_io = strHashFnInfo.params.len == 4 and strHashFnInfo.params[3].type == std.Io; | |
| 458 | const needs_salt = strHashFnInfo.params.len == 4 and strHashFnInfo.params[3].type != std.Io; | |
| 457 | const needs_io = strHashFnInfo.param_types.len == 4 and strHashFnInfo.param_types[3].? == std.Io; | |
| 458 | const needs_salt = strHashFnInfo.param_types.len == 4 and strHashFnInfo.param_types[3].? != std.Io; | |
| 459 | 459 | const salt: [16]u8 = @splat(0); |
| 460 | 460 | |
| 461 | 461 | const start = benchTime(io); |
| ... | ... | @@ -493,7 +493,7 @@ fn usage() void { |
| 493 | 493 | } |
| 494 | 494 | |
| 495 | 495 | fn 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 | } |
| 498 | 498 | |
| 499 | 499 | pub fn main(init: std.process.Init) !void { |
lib/std/crypto/ecdsa.zig+6-24| ... | ... | @@ -1,4 +1,3 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | 1 | const std = @import("std"); |
| 3 | 2 | const crypto = std.crypto; |
| 4 | 3 | const fmt = std.fmt; |
| ... | ... | @@ -25,14 +24,17 @@ pub const EcdsaSecp256k1Sha256 = Ecdsa(crypto.ecc.Secp256k1, crypto.hash.sha2.Sh |
| 25 | 24 | pub const EcdsaSecp256k1Sha256oSha256 = Ecdsa(crypto.ecc.Secp256k1, crypto.hash.composition.Sha256oSha256); |
| 26 | 25 | |
| 27 | 26 | /// Elliptic Curve Digital Signature Algorithm (ECDSA). |
| 28 | pub fn Ecdsa(comptime Curve: type, comptime Hash: type) type { | |
| 29 | const Prf = switch (Hash) { | |
| 27 | pub fn Ecdsa(comptime C: type, comptime H: type) type { | |
| 28 | const Prf = switch (H) { | |
| 30 | 29 | sha3.Shake128 => sha3.KMac128, |
| 31 | 30 | sha3.Shake256 => sha3.KMac256, |
| 32 | else => crypto.auth.hmac.Hmac(Hash), | |
| 31 | else => crypto.auth.hmac.Hmac(H), | |
| 33 | 32 | }; |
| 34 | 33 | |
| 35 | 34 | return struct { |
| 35 | pub const Curve = C; | |
| 36 | pub const Hash = H; | |
| 37 | ||
| 36 | 38 | /// Length (in bytes) of optional random bytes, for non-deterministic signatures. |
| 37 | 39 | pub const noise_length = Curve.scalar.encoded_length; |
| 38 | 40 | |
| ... | ... | @@ -415,8 +417,6 @@ pub fn Ecdsa(comptime Curve: type, comptime Hash: type) type { |
| 415 | 417 | } |
| 416 | 418 | |
| 417 | 419 | test "Basic operations over EcdsaP384Sha384" { |
| 418 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 419 | ||
| 420 | 420 | const io = testing.io; |
| 421 | 421 | const Scheme = EcdsaP384Sha384; |
| 422 | 422 | const kp = Scheme.KeyPair.generate(io); |
| ... | ... | @@ -432,8 +432,6 @@ test "Basic operations over EcdsaP384Sha384" { |
| 432 | 432 | } |
| 433 | 433 | |
| 434 | 434 | test "Basic operations over Secp256k1" { |
| 435 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 436 | ||
| 437 | 435 | const io = testing.io; |
| 438 | 436 | const Scheme = EcdsaSecp256k1Sha256oSha256; |
| 439 | 437 | const kp = Scheme.KeyPair.generate(io); |
| ... | ... | @@ -449,8 +447,6 @@ test "Basic operations over Secp256k1" { |
| 449 | 447 | } |
| 450 | 448 | |
| 451 | 449 | test "Basic operations over EcdsaP384Sha256" { |
| 452 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 453 | ||
| 454 | 450 | const io = testing.io; |
| 455 | 451 | const Scheme = Ecdsa(crypto.ecc.P384, crypto.hash.sha2.Sha256); |
| 456 | 452 | const kp = Scheme.KeyPair.generate(io); |
| ... | ... | @@ -466,8 +462,6 @@ test "Basic operations over EcdsaP384Sha256" { |
| 466 | 462 | } |
| 467 | 463 | |
| 468 | 464 | test "Verifying a existing signature with EcdsaP384Sha256" { |
| 469 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 470 | ||
| 471 | 465 | const Scheme = Ecdsa(crypto.ecc.P384, crypto.hash.sha2.Sha256); |
| 472 | 466 | // zig fmt: off |
| 473 | 467 | const sk_bytes = [_]u8{ |
| ... | ... | @@ -503,8 +497,6 @@ test "Verifying a existing signature with EcdsaP384Sha256" { |
| 503 | 497 | } |
| 504 | 498 | |
| 505 | 499 | test "Prehashed message operations" { |
| 506 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 507 | ||
| 508 | 500 | const io = testing.io; |
| 509 | 501 | |
| 510 | 502 | const Scheme = EcdsaP256Sha256; |
| ... | ... | @@ -539,8 +531,6 @@ const TestVector = struct { |
| 539 | 531 | }; |
| 540 | 532 | |
| 541 | 533 | test "Test vectors from Project Wycheproof - EcdsaP256Sha256 valid" { |
| 542 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 543 | ||
| 544 | 534 | const vectors: []const TestVector = &.{ |
| 545 | 535 | // well-formed DER encoding -> expected valid |
| 546 | 536 | .{ .key = "042927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", .msg = "313233343030", .sig = "304402202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e1802204cd60b855d442f5b3c7b11eb6c4e0ae7525fe710fab9aa7c77a67f79e6fadd76" }, |
| ... | ... | @@ -711,8 +701,6 @@ test "Test vectors from Project Wycheproof - EcdsaP256Sha256 valid" { |
| 711 | 701 | } |
| 712 | 702 | |
| 713 | 703 | test "Test vectors from Project Wycheproof - EcdsaP256Sha256 invalid" { |
| 714 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 715 | ||
| 716 | 704 | const vectors: []const TestVector = &.{ |
| 717 | 705 | // S encoded with negative sign -> expected invalid |
| 718 | 706 | .{ .key = "042927b10512bae3eddcfe467828128bad2903269919f7086069c8c4df6c732838c7787964eaac00e5921fb1498a60f4606766b3d9685001558d1a974e7341513e", .msg = "313233343030", .sig = "304402202ba3a8be6b94d5ec80a6d9d1190a436effe50d85a1eee859b8cc6af9bd5c2e180220b329f479a2bbd0a5c384ee1493b1f5186a87139cac5df4087c134b49156847db" }, |
| ... | ... | @@ -1026,8 +1014,6 @@ test "Test vectors from Project Wycheproof - EcdsaP256Sha256 invalid" { |
| 1026 | 1014 | } |
| 1027 | 1015 | |
| 1028 | 1016 | test "Test vectors from Project Wycheproof - EcdsaP384Sha384 valid" { |
| 1029 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 1030 | ||
| 1031 | 1017 | const vectors: []const TestVector = &.{ |
| 1032 | 1018 | // canonical sign-bit padding on R; canonical sign-bit padding on S -> expected valid |
| 1033 | 1019 | .{ .key = "0429bdb76d5fa741bfd70233cb3a66cc7d44beb3b0663d92a8136650478bcefb61ef182e155a54345a5e8e5e88f064e5bc9a525ab7f764dad3dae1468c2b419f3b62b9ba917d5e8c4fb1ec47404a3fc76474b2713081be9db4c00e043ada9fc4a3", .msg = "4d7367", .sig = "3066023100d7143a836608b25599a7f28dec6635494c2992ad1e2bbeecb7ef601a9c01746e710ce0d9c48accb38a79ede5b9638f3402310080f9e165e8c61035bf8aa7b5533960e46dd0e211c904a064edb6de41f797c0eae4e327612ee3f816f4157272bb4fabc9" }, |
| ... | ... | @@ -1243,8 +1229,6 @@ test "Test vectors from Project Wycheproof - EcdsaP384Sha384 valid" { |
| 1243 | 1229 | } |
| 1244 | 1230 | |
| 1245 | 1231 | test "Test vectors from Project Wycheproof - EcdsaP384Sha384 invalid" { |
| 1246 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 1247 | ||
| 1248 | 1232 | const vectors: []const TestVector = &.{ |
| 1249 | 1233 | // S encoded with negative sign -> expected invalid |
| 1250 | 1234 | .{ .key = "042da57dda1089276a543f9ffdac0bff0d976cad71eb7280e7d9bfd9fee4bdb2f20f47ff888274389772d98cc5752138aa4b6d054d69dcf3e25ec49df870715e34883b1836197d76f8ad962e78f6571bbc7407b0d6091f9e4d88f014274406174f", .msg = "313233343030", .sig = "3064023012b30abef6b5476fe6b612ae557c0425661e26b44b1bfe19daf2ca28e3113083ba8e4ae4cc45a0320abd3394f1c548d70230e7bf25603e2d07076ff30b7a2abec473da8b11c572b35fc631991d5de62ddca7525aaba89325dfd04fecc47bff426f82" }, |
| ... | ... | @@ -1631,8 +1615,6 @@ fn tvTry(comptime Scheme: type, vector: TestVector) !void { |
| 1631 | 1615 | } |
| 1632 | 1616 | |
| 1633 | 1617 | test "Sec1 encoding/decoding" { |
| 1634 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 1635 | ||
| 1636 | 1618 | const io = testing.io; |
| 1637 | 1619 | const Scheme = EcdsaP384Sha384; |
| 1638 | 1620 | const kp = Scheme.KeyPair.generate(io); |
lib/std/crypto/ff.zig-4| ... | ... | @@ -966,8 +966,6 @@ const ct_unprotected = struct { |
| 966 | 966 | }; |
| 967 | 967 | |
| 968 | 968 | test "finite field arithmetic" { |
| 969 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 970 | ||
| 971 | 969 | const M = Modulus(256); |
| 972 | 970 | const m = try M.fromPrimitive(u256, 3429938563481314093726330772853735541133072814650493833233); |
| 973 | 971 | var x = try M.Fe.fromPrimitive(u256, m, 80169837251094269539116136208111827396136208141182357733); |
| ... | ... | @@ -1066,8 +1064,6 @@ test "finite field arithmetic" { |
| 1066 | 1064 | } |
| 1067 | 1065 | |
| 1068 | 1066 | fn testCt(ct_: anytype) !void { |
| 1069 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 1070 | ||
| 1071 | 1067 | const l0: Limb = 0; |
| 1072 | 1068 | const l1: Limb = 1; |
| 1073 | 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 | 30 | pub const mac_length = 16; |
| 31 | 31 | pub const key_length = 16; |
| 32 | 32 | |
| 33 | const pc_count = if (builtin.mode != .ReleaseSmall) 16 else 2; | |
| 33 | const pc_count = if (builtin.mode != .small) 16 else 2; | |
| 34 | 34 | const agg_4_threshold = 22; |
| 35 | 35 | const agg_8_threshold = 84; |
| 36 | 36 | const agg_16_threshold = 328; |
| ... | ... | @@ -61,7 +61,7 @@ fn Hash(comptime endian: std.builtin.Endian, comptime shift_key: bool) type { |
| 61 | 61 | hx[0] = h; |
| 62 | 62 | hx[1] = reduce(clsq128(hx[0])); // h^2 |
| 63 | 63 | |
| 64 | if (builtin.mode != .ReleaseSmall) { | |
| 64 | if (builtin.mode != .small) { | |
| 65 | 65 | hx[2] = reduce(clmul128(hx[1], h)); // h^3 |
| 66 | 66 | hx[3] = reduce(clsq128(hx[1])); // h^4 = h^2^2 |
| 67 | 67 | if (block_count >= agg_8_threshold) { |
| ... | ... | @@ -303,7 +303,7 @@ fn Hash(comptime endian: std.builtin.Endian, comptime shift_key: bool) type { |
| 303 | 303 | |
| 304 | 304 | var i: usize = 0; |
| 305 | 305 | |
| 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 | 307 | // 16-blocks aggregated reduction |
| 308 | 308 | while (i + 256 <= msg.len) : (i += 256) { |
| 309 | 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 | 313 | } |
| 314 | 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 | 317 | // 8-blocks aggregated reduction |
| 318 | 318 | while (i + 128 <= msg.len) : (i += 128) { |
| 319 | 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 | 323 | } |
| 324 | 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 | 327 | // 4-blocks aggregated reduction |
| 328 | 328 | while (i + 64 <= msg.len) : (i += 64) { |
| 329 | 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 | 885 | |
| 886 | 886 | var select_outstanding: usize = 0; |
| 887 | 887 | var select: Select = .init(io, select_buf); |
| 888 | defer select.cancel(); | |
| 888 | defer select.cancelDiscard(); | |
| 889 | 889 | var batches_spawned: usize = 0; |
| 890 | 890 | var next_to_process: usize = 0; |
| 891 | 891 | |
| ... | ... | @@ -1398,7 +1398,7 @@ test "KT128 sequential and parallel produce same output for many random lengths" |
| 1398 | 1398 | var prng = std.Random.DefaultPrng.init(std.testing.random_seed); |
| 1399 | 1399 | const random = prng.random(); |
| 1400 | 1400 | |
| 1401 | const num_tests = if (builtin.mode == .Debug) 10 else 1000; | |
| 1401 | const num_tests = if (builtin.mode == .debug) 10 else 1000; | |
| 1402 | 1402 | const max_length = 250000; |
| 1403 | 1403 | |
| 1404 | 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 | 202 | |
| 203 | 203 | // In debug mode, track transitions to prevent insecure ones. |
| 204 | 204 | const Op = enum { uninitialized, initialized, updated, absorb, squeeze }; |
| 205 | const TransitionTracker = if (mode == .Debug) struct { | |
| 205 | const TransitionTracker = if (mode == .debug) struct { | |
| 206 | 206 | op: Op = .uninitialized, |
| 207 | 207 | |
| 208 | 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 | 294 | |
| 295 | 295 | /// Permute the state |
| 296 | 296 | pub fn permute(self: *Self) void { |
| 297 | if (mode == .Debug) { | |
| 297 | if (mode == .debug) { | |
| 298 | 298 | if (self.transition.op == .absorb and self.offset > 0) { |
| 299 | 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 | 110 | /// out1: [0x0 ~> 0xffffffffffffffff] |
| 111 | 111 | /// out2: [0x0 ~> 0xffffffffffffffff] |
| 112 | 112 | fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void { |
| 113 | @setRuntimeSafety(mode == .Debug); | |
| 113 | @setRuntimeSafety(mode == .debug); | |
| 114 | 114 | |
| 115 | 115 | const x = @as(u128, arg1) * @as(u128, arg2); |
| 116 | 116 | out1.* = @as(u64, @truncate(x)); |
| ... | ... | @@ -129,7 +129,7 @@ fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void { |
| 129 | 129 | /// Output Bounds: |
| 130 | 130 | /// out1: [0x0 ~> 0xffffffffffffffff] |
| 131 | 131 | fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void { |
| 132 | @setRuntimeSafety(mode == .Debug); | |
| 132 | @setRuntimeSafety(mode == .debug); | |
| 133 | 133 | |
| 134 | 134 | const mask = 0 -% @as(u64, arg1); |
| 135 | 135 | out1.* = (mask & arg3) | ((~mask) & arg2); |
| ... | ... | @@ -145,7 +145,7 @@ fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void { |
| 145 | 145 | /// 0 ≤ eval out1 < m |
| 146 | 146 | /// |
| 147 | 147 | pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void { |
| 148 | @setRuntimeSafety(mode == .Debug); | |
| 148 | @setRuntimeSafety(mode == .debug); | |
| 149 | 149 | |
| 150 | 150 | const x1 = (arg1[1]); |
| 151 | 151 | const x2 = (arg1[2]); |
| ... | ... | @@ -437,7 +437,7 @@ pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme |
| 437 | 437 | /// 0 ≤ eval out1 < m |
| 438 | 438 | /// |
| 439 | 439 | pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void { |
| 440 | @setRuntimeSafety(mode == .Debug); | |
| 440 | @setRuntimeSafety(mode == .debug); | |
| 441 | 441 | |
| 442 | 442 | const x1 = (arg1[1]); |
| 443 | 443 | const x2 = (arg1[2]); |
| ... | ... | @@ -730,7 +730,7 @@ pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEl |
| 730 | 730 | /// 0 ≤ eval out1 < m |
| 731 | 731 | /// |
| 732 | 732 | pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void { |
| 733 | @setRuntimeSafety(mode == .Debug); | |
| 733 | @setRuntimeSafety(mode == .debug); | |
| 734 | 734 | |
| 735 | 735 | var x1: u64 = undefined; |
| 736 | 736 | var x2: u1 = undefined; |
| ... | ... | @@ -783,7 +783,7 @@ pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme |
| 783 | 783 | /// 0 ≤ eval out1 < m |
| 784 | 784 | /// |
| 785 | 785 | pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void { |
| 786 | @setRuntimeSafety(mode == .Debug); | |
| 786 | @setRuntimeSafety(mode == .debug); | |
| 787 | 787 | |
| 788 | 788 | var x1: u64 = undefined; |
| 789 | 789 | var x2: u1 = undefined; |
| ... | ... | @@ -826,7 +826,7 @@ pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme |
| 826 | 826 | /// 0 ≤ eval out1 < m |
| 827 | 827 | /// |
| 828 | 828 | pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void { |
| 829 | @setRuntimeSafety(mode == .Debug); | |
| 829 | @setRuntimeSafety(mode == .debug); | |
| 830 | 830 | |
| 831 | 831 | var x1: u64 = undefined; |
| 832 | 832 | var x2: u1 = undefined; |
| ... | ... | @@ -869,7 +869,7 @@ pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme |
| 869 | 869 | /// 0 ≤ eval out1 < m |
| 870 | 870 | /// |
| 871 | 871 | pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void { |
| 872 | @setRuntimeSafety(mode == .Debug); | |
| 872 | @setRuntimeSafety(mode == .debug); | |
| 873 | 873 | |
| 874 | 874 | const x1 = (arg1[0]); |
| 875 | 875 | var x2: u64 = undefined; |
| ... | ... | @@ -1022,7 +1022,7 @@ pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDo |
| 1022 | 1022 | /// 0 ≤ eval out1 < m |
| 1023 | 1023 | /// |
| 1024 | 1024 | pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDomainFieldElement) void { |
| 1025 | @setRuntimeSafety(mode == .Debug); | |
| 1025 | @setRuntimeSafety(mode == .debug); | |
| 1026 | 1026 | |
| 1027 | 1027 | const x1 = (arg1[1]); |
| 1028 | 1028 | const x2 = (arg1[2]); |
| ... | ... | @@ -1297,7 +1297,7 @@ pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDoma |
| 1297 | 1297 | /// Output Bounds: |
| 1298 | 1298 | /// out1: [0x0 ~> 0xffffffffffffffff] |
| 1299 | 1299 | pub fn nonzero(out1: *u64, arg1: [4]u64) void { |
| 1300 | @setRuntimeSafety(mode == .Debug); | |
| 1300 | @setRuntimeSafety(mode == .debug); | |
| 1301 | 1301 | |
| 1302 | 1302 | const x1 = ((arg1[0]) | ((arg1[1]) | ((arg1[2]) | (arg1[3])))); |
| 1303 | 1303 | out1.* = x1; |
| ... | ... | @@ -1315,7 +1315,7 @@ pub fn nonzero(out1: *u64, arg1: [4]u64) void { |
| 1315 | 1315 | /// Output Bounds: |
| 1316 | 1316 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] |
| 1317 | 1317 | pub fn selectznz(out1: *[4]u64, arg1: u1, arg2: [4]u64, arg3: [4]u64) void { |
| 1318 | @setRuntimeSafety(mode == .Debug); | |
| 1318 | @setRuntimeSafety(mode == .debug); | |
| 1319 | 1319 | |
| 1320 | 1320 | var x1: u64 = undefined; |
| 1321 | 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 | 1343 | /// Output Bounds: |
| 1344 | 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]] |
| 1345 | 1345 | pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void { |
| 1346 | @setRuntimeSafety(mode == .Debug); | |
| 1346 | @setRuntimeSafety(mode == .debug); | |
| 1347 | 1347 | |
| 1348 | 1348 | const x1 = (arg1[3]); |
| 1349 | 1349 | const x2 = (arg1[2]); |
| ... | ... | @@ -1452,7 +1452,7 @@ pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void { |
| 1452 | 1452 | /// Output Bounds: |
| 1453 | 1453 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] |
| 1454 | 1454 | pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void { |
| 1455 | @setRuntimeSafety(mode == .Debug); | |
| 1455 | @setRuntimeSafety(mode == .debug); | |
| 1456 | 1456 | |
| 1457 | 1457 | const x1 = (@as(u64, (arg1[31])) << 56); |
| 1458 | 1458 | const x2 = (@as(u64, (arg1[30])) << 48); |
| ... | ... | @@ -1527,7 +1527,7 @@ pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void { |
| 1527 | 1527 | /// 0 ≤ eval out1 < m |
| 1528 | 1528 | /// |
| 1529 | 1529 | pub fn setOne(out1: *MontgomeryDomainFieldElement) void { |
| 1530 | @setRuntimeSafety(mode == .Debug); | |
| 1530 | @setRuntimeSafety(mode == .debug); | |
| 1531 | 1531 | |
| 1532 | 1532 | out1[0] = @as(u64, 0x1); |
| 1533 | 1533 | out1[1] = 0xffffffff00000000; |
| ... | ... | @@ -1544,7 +1544,7 @@ pub fn setOne(out1: *MontgomeryDomainFieldElement) void { |
| 1544 | 1544 | /// Output Bounds: |
| 1545 | 1545 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] |
| 1546 | 1546 | pub fn msat(out1: *[5]u64) void { |
| 1547 | @setRuntimeSafety(mode == .Debug); | |
| 1547 | @setRuntimeSafety(mode == .debug); | |
| 1548 | 1548 | |
| 1549 | 1549 | out1[0] = 0xffffffffffffffff; |
| 1550 | 1550 | out1[1] = 0xffffffff; |
| ... | ... | @@ -1582,7 +1582,7 @@ pub fn msat(out1: *[5]u64) void { |
| 1582 | 1582 | /// out4: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] |
| 1583 | 1583 | /// out5: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] |
| 1584 | 1584 | pub fn divstep(out1: *u64, out2: *[5]u64, out3: *[5]u64, out4: *[4]u64, out5: *[4]u64, arg1: u64, arg2: [5]u64, arg3: [5]u64, arg4: [4]u64, arg5: [4]u64) void { |
| 1585 | @setRuntimeSafety(mode == .Debug); | |
| 1585 | @setRuntimeSafety(mode == .debug); | |
| 1586 | 1586 | |
| 1587 | 1587 | var x1: u64 = undefined; |
| 1588 | 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 | 1816 | /// Output Bounds: |
| 1817 | 1817 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] |
| 1818 | 1818 | pub fn divstepPrecomp(out1: *[4]u64) void { |
| 1819 | @setRuntimeSafety(mode == .Debug); | |
| 1819 | @setRuntimeSafety(mode == .debug); | |
| 1820 | 1820 | |
| 1821 | 1821 | out1[0] = 0x67ffffffb8000000; |
| 1822 | 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 | 110 | /// out1: [0x0 ~> 0xffffffffffffffff] |
| 111 | 111 | /// out2: [0x0 ~> 0xffffffffffffffff] |
| 112 | 112 | fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void { |
| 113 | @setRuntimeSafety(mode == .Debug); | |
| 113 | @setRuntimeSafety(mode == .debug); | |
| 114 | 114 | |
| 115 | 115 | const x = @as(u128, arg1) * @as(u128, arg2); |
| 116 | 116 | out1.* = @as(u64, @truncate(x)); |
| ... | ... | @@ -129,7 +129,7 @@ fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void { |
| 129 | 129 | /// Output Bounds: |
| 130 | 130 | /// out1: [0x0 ~> 0xffffffffffffffff] |
| 131 | 131 | fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void { |
| 132 | @setRuntimeSafety(mode == .Debug); | |
| 132 | @setRuntimeSafety(mode == .debug); | |
| 133 | 133 | |
| 134 | 134 | const mask = 0 -% @as(u64, arg1); |
| 135 | 135 | out1.* = (mask & arg3) | ((~mask) & arg2); |
| ... | ... | @@ -145,7 +145,7 @@ fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void { |
| 145 | 145 | /// 0 ≤ eval out1 < m |
| 146 | 146 | /// |
| 147 | 147 | pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void { |
| 148 | @setRuntimeSafety(mode == .Debug); | |
| 148 | @setRuntimeSafety(mode == .debug); | |
| 149 | 149 | |
| 150 | 150 | const x1 = (arg1[1]); |
| 151 | 151 | const x2 = (arg1[2]); |
| ... | ... | @@ -485,7 +485,7 @@ pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme |
| 485 | 485 | /// 0 ≤ eval out1 < m |
| 486 | 486 | /// |
| 487 | 487 | pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void { |
| 488 | @setRuntimeSafety(mode == .Debug); | |
| 488 | @setRuntimeSafety(mode == .debug); | |
| 489 | 489 | |
| 490 | 490 | const x1 = (arg1[1]); |
| 491 | 491 | const x2 = (arg1[2]); |
| ... | ... | @@ -826,7 +826,7 @@ pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEl |
| 826 | 826 | /// 0 ≤ eval out1 < m |
| 827 | 827 | /// |
| 828 | 828 | pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void { |
| 829 | @setRuntimeSafety(mode == .Debug); | |
| 829 | @setRuntimeSafety(mode == .debug); | |
| 830 | 830 | |
| 831 | 831 | var x1: u64 = undefined; |
| 832 | 832 | var x2: u1 = undefined; |
| ... | ... | @@ -879,7 +879,7 @@ pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme |
| 879 | 879 | /// 0 ≤ eval out1 < m |
| 880 | 880 | /// |
| 881 | 881 | pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void { |
| 882 | @setRuntimeSafety(mode == .Debug); | |
| 882 | @setRuntimeSafety(mode == .debug); | |
| 883 | 883 | |
| 884 | 884 | var x1: u64 = undefined; |
| 885 | 885 | var x2: u1 = undefined; |
| ... | ... | @@ -922,7 +922,7 @@ pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme |
| 922 | 922 | /// 0 ≤ eval out1 < m |
| 923 | 923 | /// |
| 924 | 924 | pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void { |
| 925 | @setRuntimeSafety(mode == .Debug); | |
| 925 | @setRuntimeSafety(mode == .debug); | |
| 926 | 926 | |
| 927 | 927 | var x1: u64 = undefined; |
| 928 | 928 | var x2: u1 = undefined; |
| ... | ... | @@ -965,7 +965,7 @@ pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme |
| 965 | 965 | /// 0 ≤ eval out1 < m |
| 966 | 966 | /// |
| 967 | 967 | pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void { |
| 968 | @setRuntimeSafety(mode == .Debug); | |
| 968 | @setRuntimeSafety(mode == .debug); | |
| 969 | 969 | |
| 970 | 970 | const x1 = (arg1[0]); |
| 971 | 971 | var x2: u64 = undefined; |
| ... | ... | @@ -1178,7 +1178,7 @@ pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDo |
| 1178 | 1178 | /// 0 ≤ eval out1 < m |
| 1179 | 1179 | /// |
| 1180 | 1180 | pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDomainFieldElement) void { |
| 1181 | @setRuntimeSafety(mode == .Debug); | |
| 1181 | @setRuntimeSafety(mode == .debug); | |
| 1182 | 1182 | |
| 1183 | 1183 | const x1 = (arg1[1]); |
| 1184 | 1184 | const x2 = (arg1[2]); |
| ... | ... | @@ -1501,7 +1501,7 @@ pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDoma |
| 1501 | 1501 | /// Output Bounds: |
| 1502 | 1502 | /// out1: [0x0 ~> 0xffffffffffffffff] |
| 1503 | 1503 | pub fn nonzero(out1: *u64, arg1: [4]u64) void { |
| 1504 | @setRuntimeSafety(mode == .Debug); | |
| 1504 | @setRuntimeSafety(mode == .debug); | |
| 1505 | 1505 | |
| 1506 | 1506 | const x1 = ((arg1[0]) | ((arg1[1]) | ((arg1[2]) | (arg1[3])))); |
| 1507 | 1507 | out1.* = x1; |
| ... | ... | @@ -1519,7 +1519,7 @@ pub fn nonzero(out1: *u64, arg1: [4]u64) void { |
| 1519 | 1519 | /// Output Bounds: |
| 1520 | 1520 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] |
| 1521 | 1521 | pub fn selectznz(out1: *[4]u64, arg1: u1, arg2: [4]u64, arg3: [4]u64) void { |
| 1522 | @setRuntimeSafety(mode == .Debug); | |
| 1522 | @setRuntimeSafety(mode == .debug); | |
| 1523 | 1523 | |
| 1524 | 1524 | var x1: u64 = undefined; |
| 1525 | 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 | 1547 | /// Output Bounds: |
| 1548 | 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]] |
| 1549 | 1549 | pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void { |
| 1550 | @setRuntimeSafety(mode == .Debug); | |
| 1550 | @setRuntimeSafety(mode == .debug); | |
| 1551 | 1551 | |
| 1552 | 1552 | const x1 = (arg1[3]); |
| 1553 | 1553 | const x2 = (arg1[2]); |
| ... | ... | @@ -1656,7 +1656,7 @@ pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void { |
| 1656 | 1656 | /// Output Bounds: |
| 1657 | 1657 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] |
| 1658 | 1658 | pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void { |
| 1659 | @setRuntimeSafety(mode == .Debug); | |
| 1659 | @setRuntimeSafety(mode == .debug); | |
| 1660 | 1660 | |
| 1661 | 1661 | const x1 = (@as(u64, (arg1[31])) << 56); |
| 1662 | 1662 | const x2 = (@as(u64, (arg1[30])) << 48); |
| ... | ... | @@ -1731,7 +1731,7 @@ pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void { |
| 1731 | 1731 | /// 0 ≤ eval out1 < m |
| 1732 | 1732 | /// |
| 1733 | 1733 | pub fn setOne(out1: *MontgomeryDomainFieldElement) void { |
| 1734 | @setRuntimeSafety(mode == .Debug); | |
| 1734 | @setRuntimeSafety(mode == .debug); | |
| 1735 | 1735 | |
| 1736 | 1736 | out1[0] = 0xc46353d039cdaaf; |
| 1737 | 1737 | out1[1] = 0x4319055258e8617b; |
| ... | ... | @@ -1748,7 +1748,7 @@ pub fn setOne(out1: *MontgomeryDomainFieldElement) void { |
| 1748 | 1748 | /// Output Bounds: |
| 1749 | 1749 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] |
| 1750 | 1750 | pub fn msat(out1: *[5]u64) void { |
| 1751 | @setRuntimeSafety(mode == .Debug); | |
| 1751 | @setRuntimeSafety(mode == .debug); | |
| 1752 | 1752 | |
| 1753 | 1753 | out1[0] = 0xf3b9cac2fc632551; |
| 1754 | 1754 | out1[1] = 0xbce6faada7179e84; |
| ... | ... | @@ -1786,7 +1786,7 @@ pub fn msat(out1: *[5]u64) void { |
| 1786 | 1786 | /// out4: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] |
| 1787 | 1787 | /// out5: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] |
| 1788 | 1788 | pub fn divstep(out1: *u64, out2: *[5]u64, out3: *[5]u64, out4: *[4]u64, out5: *[4]u64, arg1: u64, arg2: [5]u64, arg3: [5]u64, arg4: [4]u64, arg5: [4]u64) void { |
| 1789 | @setRuntimeSafety(mode == .Debug); | |
| 1789 | @setRuntimeSafety(mode == .debug); | |
| 1790 | 1790 | |
| 1791 | 1791 | var x1: u64 = undefined; |
| 1792 | 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 | 2020 | /// Output Bounds: |
| 2021 | 2021 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] |
| 2022 | 2022 | pub fn divstepPrecomp(out1: *[4]u64) void { |
| 2023 | @setRuntimeSafety(mode == .Debug); | |
| 2023 | @setRuntimeSafety(mode == .debug); | |
| 2024 | 2024 | |
| 2025 | 2025 | out1[0] = 0xd739262fb7fcfbb5; |
| 2026 | 2026 | out1[1] = 0x8ac6f75d20074414; |
lib/std/crypto/pcurves/p384.zig+4-6| ... | ... | @@ -56,7 +56,7 @@ pub const P384 = struct { |
| 56 | 56 | } |
| 57 | 57 | |
| 58 | 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 | 60 | const x = try Fe.fromBytes(xs, endian); |
| 61 | 61 | const y = try Fe.fromBytes(ys, endian); |
| 62 | 62 | return fromAffineCoordinates(.{ .x = x, .y = y }); |
| ... | ... | @@ -395,7 +395,7 @@ pub const P384 = struct { |
| 395 | 395 | |
| 396 | 396 | /// Multiply an elliptic curve point by a scalar. |
| 397 | 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 | 399 | const s = if (endian == .little) s_ else Fe.orderSwap(s_); |
| 400 | 400 | if (p.is_base) { |
| 401 | 401 | return pcMul16(&basePointPc, s, false); |
| ... | ... | @@ -407,7 +407,7 @@ pub const P384 = struct { |
| 407 | 407 | |
| 408 | 408 | /// Multiply an elliptic curve point by a *PUBLIC* scalar *IN VARIABLE TIME* |
| 409 | 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 | 411 | const s = if (endian == .little) s_ else Fe.orderSwap(s_); |
| 412 | 412 | if (p.is_base) { |
| 413 | 413 | return pcMul16(&basePointPc, s, true); |
| ... | ... | @@ -419,7 +419,7 @@ pub const P384 = struct { |
| 419 | 419 | |
| 420 | 420 | /// Double-base multiplication of public parameters - Compute (p1*s1)+(p2*s2) *IN VARIABLE TIME* |
| 421 | 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 | 423 | const s1 = if (endian == .little) s1_ else Fe.orderSwap(s1_); |
| 424 | 424 | const s2 = if (endian == .little) s2_ else Fe.orderSwap(s2_); |
| 425 | 425 | try p1.rejectIdentity(); |
| ... | ... | @@ -478,7 +478,5 @@ pub const AffineCoordinates = struct { |
| 478 | 478 | }; |
| 479 | 479 | |
| 480 | 480 | test { |
| 481 | if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; | |
| 482 | ||
| 483 | 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 | 79 | /// out1: [0x0 ~> 0xffffffffffffffff] |
| 80 | 80 | /// out2: [0x0 ~> 0xffffffffffffffff] |
| 81 | 81 | fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void { |
| 82 | @setRuntimeSafety(mode == .Debug); | |
| 82 | @setRuntimeSafety(mode == .debug); | |
| 83 | 83 | |
| 84 | 84 | const x = @as(u128, arg1) * @as(u128, arg2); |
| 85 | 85 | out1.* = @as(u64, @truncate(x)); |
| ... | ... | @@ -98,7 +98,7 @@ fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void { |
| 98 | 98 | /// Output Bounds: |
| 99 | 99 | /// out1: [0x0 ~> 0xffffffffffffffff] |
| 100 | 100 | fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void { |
| 101 | @setRuntimeSafety(mode == .Debug); | |
| 101 | @setRuntimeSafety(mode == .debug); | |
| 102 | 102 | |
| 103 | 103 | const mask = 0 -% @as(u64, arg1); |
| 104 | 104 | out1.* = (mask & arg3) | ((~mask) & arg2); |
| ... | ... | @@ -114,7 +114,7 @@ fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void { |
| 114 | 114 | /// 0 ≤ eval out1 < m |
| 115 | 115 | /// |
| 116 | 116 | pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void { |
| 117 | @setRuntimeSafety(mode == .Debug); | |
| 117 | @setRuntimeSafety(mode == .debug); | |
| 118 | 118 | |
| 119 | 119 | const x1 = (arg1[1]); |
| 120 | 120 | const x2 = (arg1[2]); |
| ... | ... | @@ -834,7 +834,7 @@ pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme |
| 834 | 834 | /// 0 ≤ eval out1 < m |
| 835 | 835 | /// |
| 836 | 836 | pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void { |
| 837 | @setRuntimeSafety(mode == .Debug); | |
| 837 | @setRuntimeSafety(mode == .debug); | |
| 838 | 838 | |
| 839 | 839 | const x1 = (arg1[1]); |
| 840 | 840 | const x2 = (arg1[2]); |
| ... | ... | @@ -1555,7 +1555,7 @@ pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEl |
| 1555 | 1555 | /// 0 ≤ eval out1 < m |
| 1556 | 1556 | /// |
| 1557 | 1557 | pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void { |
| 1558 | @setRuntimeSafety(mode == .Debug); | |
| 1558 | @setRuntimeSafety(mode == .debug); | |
| 1559 | 1559 | |
| 1560 | 1560 | var x1: u64 = undefined; |
| 1561 | 1561 | var x2: u1 = undefined; |
| ... | ... | @@ -1626,7 +1626,7 @@ pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme |
| 1626 | 1626 | /// 0 ≤ eval out1 < m |
| 1627 | 1627 | /// |
| 1628 | 1628 | pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void { |
| 1629 | @setRuntimeSafety(mode == .Debug); | |
| 1629 | @setRuntimeSafety(mode == .debug); | |
| 1630 | 1630 | |
| 1631 | 1631 | var x1: u64 = undefined; |
| 1632 | 1632 | var x2: u1 = undefined; |
| ... | ... | @@ -1683,7 +1683,7 @@ pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme |
| 1683 | 1683 | /// 0 ≤ eval out1 < m |
| 1684 | 1684 | /// |
| 1685 | 1685 | pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void { |
| 1686 | @setRuntimeSafety(mode == .Debug); | |
| 1686 | @setRuntimeSafety(mode == .debug); | |
| 1687 | 1687 | |
| 1688 | 1688 | var x1: u64 = undefined; |
| 1689 | 1689 | var x2: u1 = undefined; |
| ... | ... | @@ -1740,7 +1740,7 @@ pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme |
| 1740 | 1740 | /// 0 ≤ eval out1 < m |
| 1741 | 1741 | /// |
| 1742 | 1742 | pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void { |
| 1743 | @setRuntimeSafety(mode == .Debug); | |
| 1743 | @setRuntimeSafety(mode == .debug); | |
| 1744 | 1744 | |
| 1745 | 1745 | const x1 = (arg1[0]); |
| 1746 | 1746 | var x2: u64 = undefined; |
| ... | ... | @@ -2225,7 +2225,7 @@ pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDo |
| 2225 | 2225 | /// 0 ≤ eval out1 < m |
| 2226 | 2226 | /// |
| 2227 | 2227 | pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDomainFieldElement) void { |
| 2228 | @setRuntimeSafety(mode == .Debug); | |
| 2228 | @setRuntimeSafety(mode == .debug); | |
| 2229 | 2229 | |
| 2230 | 2230 | const x1 = (arg1[1]); |
| 2231 | 2231 | const x2 = (arg1[2]); |
| ... | ... | @@ -2862,7 +2862,7 @@ pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDoma |
| 2862 | 2862 | /// Output Bounds: |
| 2863 | 2863 | /// out1: [0x0 ~> 0xffffffffffffffff] |
| 2864 | 2864 | pub fn nonzero(out1: *u64, arg1: [6]u64) void { |
| 2865 | @setRuntimeSafety(mode == .Debug); | |
| 2865 | @setRuntimeSafety(mode == .debug); | |
| 2866 | 2866 | |
| 2867 | 2867 | const x1 = ((arg1[0]) | ((arg1[1]) | ((arg1[2]) | ((arg1[3]) | ((arg1[4]) | (arg1[5])))))); |
| 2868 | 2868 | out1.* = x1; |
| ... | ... | @@ -2880,7 +2880,7 @@ pub fn nonzero(out1: *u64, arg1: [6]u64) void { |
| 2880 | 2880 | /// Output Bounds: |
| 2881 | 2881 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] |
| 2882 | 2882 | pub fn selectznz(out1: *[6]u64, arg1: u1, arg2: [6]u64, arg3: [6]u64) void { |
| 2883 | @setRuntimeSafety(mode == .Debug); | |
| 2883 | @setRuntimeSafety(mode == .debug); | |
| 2884 | 2884 | |
| 2885 | 2885 | var x1: u64 = undefined; |
| 2886 | 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 | 2914 | /// Output Bounds: |
| 2915 | 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]] |
| 2916 | 2916 | pub fn toBytes(out1: *[48]u8, arg1: [6]u64) void { |
| 2917 | @setRuntimeSafety(mode == .Debug); | |
| 2917 | @setRuntimeSafety(mode == .debug); | |
| 2918 | 2918 | |
| 2919 | 2919 | const x1 = (arg1[5]); |
| 2920 | 2920 | const x2 = (arg1[4]); |
| ... | ... | @@ -3069,7 +3069,7 @@ pub fn toBytes(out1: *[48]u8, arg1: [6]u64) void { |
| 3069 | 3069 | /// Output Bounds: |
| 3070 | 3070 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] |
| 3071 | 3071 | pub fn fromBytes(out1: *[6]u64, arg1: [48]u8) void { |
| 3072 | @setRuntimeSafety(mode == .Debug); | |
| 3072 | @setRuntimeSafety(mode == .debug); | |
| 3073 | 3073 | |
| 3074 | 3074 | const x1 = (@as(u64, (arg1[47])) << 56); |
| 3075 | 3075 | const x2 = (@as(u64, (arg1[46])) << 48); |
| ... | ... | @@ -3176,7 +3176,7 @@ pub fn fromBytes(out1: *[6]u64, arg1: [48]u8) void { |
| 3176 | 3176 | /// 0 ≤ eval out1 < m |
| 3177 | 3177 | /// |
| 3178 | 3178 | pub fn setOne(out1: *MontgomeryDomainFieldElement) void { |
| 3179 | @setRuntimeSafety(mode == .Debug); | |
| 3179 | @setRuntimeSafety(mode == .debug); | |
| 3180 | 3180 | |
| 3181 | 3181 | out1[0] = 0xffffffff00000001; |
| 3182 | 3182 | out1[1] = 0xffffffff; |
| ... | ... | @@ -3195,7 +3195,7 @@ pub fn setOne(out1: *MontgomeryDomainFieldElement) void { |
| 3195 | 3195 | /// Output Bounds: |
| 3196 | 3196 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] |
| 3197 | 3197 | pub fn msat(out1: *[7]u64) void { |
| 3198 | @setRuntimeSafety(mode == .Debug); | |
| 3198 | @setRuntimeSafety(mode == .debug); | |
| 3199 | 3199 | |
| 3200 | 3200 | out1[0] = 0xffffffff; |
| 3201 | 3201 | out1[1] = 0xffffffff00000000; |
| ... | ... | @@ -3235,7 +3235,7 @@ pub fn msat(out1: *[7]u64) void { |
| 3235 | 3235 | /// out4: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] |
| 3236 | 3236 | /// out5: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] |
| 3237 | 3237 | pub fn divstep(out1: *u64, out2: *[7]u64, out3: *[7]u64, out4: *[6]u64, out5: *[6]u64, arg1: u64, arg2: [7]u64, arg3: [7]u64, arg4: [6]u64, arg5: [6]u64) void { |
| 3238 | @setRuntimeSafety(mode == .Debug); | |
| 3238 | @setRuntimeSafety(mode == .debug); | |
| 3239 | 3239 | |
| 3240 | 3240 | var x1: u64 = undefined; |
| 3241 | 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 | 3561 | /// Output Bounds: |
| 3562 | 3562 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] |
| 3563 | 3563 | pub fn divstepPrecomp(out1: *[6]u64) void { |
| 3564 | @setRuntimeSafety(mode == .Debug); | |
| 3564 | @setRuntimeSafety(mode == .debug); | |
| 3565 | 3565 | |
| 3566 | 3566 | out1[0] = 0xfff69400fff18fff; |
| 3567 | 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 | 79 | /// out1: [0x0 ~> 0xffffffffffffffff] |
| 80 | 80 | /// out2: [0x0 ~> 0xffffffffffffffff] |
| 81 | 81 | fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void { |
| 82 | @setRuntimeSafety(mode == .Debug); | |
| 82 | @setRuntimeSafety(mode == .debug); | |
| 83 | 83 | |
| 84 | 84 | const x = @as(u128, arg1) * @as(u128, arg2); |
| 85 | 85 | out1.* = @as(u64, @truncate(x)); |
| ... | ... | @@ -98,7 +98,7 @@ fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void { |
| 98 | 98 | /// Output Bounds: |
| 99 | 99 | /// out1: [0x0 ~> 0xffffffffffffffff] |
| 100 | 100 | fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void { |
| 101 | @setRuntimeSafety(mode == .Debug); | |
| 101 | @setRuntimeSafety(mode == .debug); | |
| 102 | 102 | |
| 103 | 103 | const mask = 0 -% @as(u64, arg1); |
| 104 | 104 | out1.* = (mask & arg3) | ((~mask) & arg2); |
| ... | ... | @@ -114,7 +114,7 @@ fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void { |
| 114 | 114 | /// 0 ≤ eval out1 < m |
| 115 | 115 | /// |
| 116 | 116 | pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void { |
| 117 | @setRuntimeSafety(mode == .Debug); | |
| 117 | @setRuntimeSafety(mode == .debug); | |
| 118 | 118 | |
| 119 | 119 | const x1 = (arg1[1]); |
| 120 | 120 | const x2 = (arg1[2]); |
| ... | ... | @@ -834,7 +834,7 @@ pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme |
| 834 | 834 | /// 0 ≤ eval out1 < m |
| 835 | 835 | /// |
| 836 | 836 | pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void { |
| 837 | @setRuntimeSafety(mode == .Debug); | |
| 837 | @setRuntimeSafety(mode == .debug); | |
| 838 | 838 | |
| 839 | 839 | const x1 = (arg1[1]); |
| 840 | 840 | const x2 = (arg1[2]); |
| ... | ... | @@ -1555,7 +1555,7 @@ pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEl |
| 1555 | 1555 | /// 0 ≤ eval out1 < m |
| 1556 | 1556 | /// |
| 1557 | 1557 | pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void { |
| 1558 | @setRuntimeSafety(mode == .Debug); | |
| 1558 | @setRuntimeSafety(mode == .debug); | |
| 1559 | 1559 | |
| 1560 | 1560 | var x1: u64 = undefined; |
| 1561 | 1561 | var x2: u1 = undefined; |
| ... | ... | @@ -1626,7 +1626,7 @@ pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme |
| 1626 | 1626 | /// 0 ≤ eval out1 < m |
| 1627 | 1627 | /// |
| 1628 | 1628 | pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void { |
| 1629 | @setRuntimeSafety(mode == .Debug); | |
| 1629 | @setRuntimeSafety(mode == .debug); | |
| 1630 | 1630 | |
| 1631 | 1631 | var x1: u64 = undefined; |
| 1632 | 1632 | var x2: u1 = undefined; |
| ... | ... | @@ -1683,7 +1683,7 @@ pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme |
| 1683 | 1683 | /// 0 ≤ eval out1 < m |
| 1684 | 1684 | /// |
| 1685 | 1685 | pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void { |
| 1686 | @setRuntimeSafety(mode == .Debug); | |
| 1686 | @setRuntimeSafety(mode == .debug); | |
| 1687 | 1687 | |
| 1688 | 1688 | var x1: u64 = undefined; |
| 1689 | 1689 | var x2: u1 = undefined; |
| ... | ... | @@ -1740,7 +1740,7 @@ pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme |
| 1740 | 1740 | /// 0 ≤ eval out1 < m |
| 1741 | 1741 | /// |
| 1742 | 1742 | pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void { |
| 1743 | @setRuntimeSafety(mode == .Debug); | |
| 1743 | @setRuntimeSafety(mode == .debug); | |
| 1744 | 1744 | |
| 1745 | 1745 | const x1 = (arg1[0]); |
| 1746 | 1746 | var x2: u64 = undefined; |
| ... | ... | @@ -2225,7 +2225,7 @@ pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDo |
| 2225 | 2225 | /// 0 ≤ eval out1 < m |
| 2226 | 2226 | /// |
| 2227 | 2227 | pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDomainFieldElement) void { |
| 2228 | @setRuntimeSafety(mode == .Debug); | |
| 2228 | @setRuntimeSafety(mode == .debug); | |
| 2229 | 2229 | |
| 2230 | 2230 | const x1 = (arg1[1]); |
| 2231 | 2231 | const x2 = (arg1[2]); |
| ... | ... | @@ -2916,7 +2916,7 @@ pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDoma |
| 2916 | 2916 | /// Output Bounds: |
| 2917 | 2917 | /// out1: [0x0 ~> 0xffffffffffffffff] |
| 2918 | 2918 | pub fn nonzero(out1: *u64, arg1: [6]u64) void { |
| 2919 | @setRuntimeSafety(mode == .Debug); | |
| 2919 | @setRuntimeSafety(mode == .debug); | |
| 2920 | 2920 | |
| 2921 | 2921 | const x1 = ((arg1[0]) | ((arg1[1]) | ((arg1[2]) | ((arg1[3]) | ((arg1[4]) | (arg1[5])))))); |
| 2922 | 2922 | out1.* = x1; |
| ... | ... | @@ -2934,7 +2934,7 @@ pub fn nonzero(out1: *u64, arg1: [6]u64) void { |
| 2934 | 2934 | /// Output Bounds: |
| 2935 | 2935 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] |
| 2936 | 2936 | pub fn selectznz(out1: *[6]u64, arg1: u1, arg2: [6]u64, arg3: [6]u64) void { |
| 2937 | @setRuntimeSafety(mode == .Debug); | |
| 2937 | @setRuntimeSafety(mode == .debug); | |
| 2938 | 2938 | |
| 2939 | 2939 | var x1: u64 = undefined; |
| 2940 | 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 | 2968 | /// Output Bounds: |
| 2969 | 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]] |
| 2970 | 2970 | pub fn toBytes(out1: *[48]u8, arg1: [6]u64) void { |
| 2971 | @setRuntimeSafety(mode == .Debug); | |
| 2971 | @setRuntimeSafety(mode == .debug); | |
| 2972 | 2972 | |
| 2973 | 2973 | const x1 = (arg1[5]); |
| 2974 | 2974 | const x2 = (arg1[4]); |
| ... | ... | @@ -3123,7 +3123,7 @@ pub fn toBytes(out1: *[48]u8, arg1: [6]u64) void { |
| 3123 | 3123 | /// Output Bounds: |
| 3124 | 3124 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] |
| 3125 | 3125 | pub fn fromBytes(out1: *[6]u64, arg1: [48]u8) void { |
| 3126 | @setRuntimeSafety(mode == .Debug); | |
| 3126 | @setRuntimeSafety(mode == .debug); | |
| 3127 | 3127 | |
| 3128 | 3128 | const x1 = (@as(u64, (arg1[47])) << 56); |
| 3129 | 3129 | const x2 = (@as(u64, (arg1[46])) << 48); |
| ... | ... | @@ -3230,7 +3230,7 @@ pub fn fromBytes(out1: *[6]u64, arg1: [48]u8) void { |
| 3230 | 3230 | /// 0 ≤ eval out1 < m |
| 3231 | 3231 | /// |
| 3232 | 3232 | pub fn setOne(out1: *MontgomeryDomainFieldElement) void { |
| 3233 | @setRuntimeSafety(mode == .Debug); | |
| 3233 | @setRuntimeSafety(mode == .debug); | |
| 3234 | 3234 | |
| 3235 | 3235 | out1[0] = 0x1313e695333ad68d; |
| 3236 | 3236 | out1[1] = 0xa7e5f24db74f5885; |
| ... | ... | @@ -3249,7 +3249,7 @@ pub fn setOne(out1: *MontgomeryDomainFieldElement) void { |
| 3249 | 3249 | /// Output Bounds: |
| 3250 | 3250 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] |
| 3251 | 3251 | pub fn msat(out1: *[7]u64) void { |
| 3252 | @setRuntimeSafety(mode == .Debug); | |
| 3252 | @setRuntimeSafety(mode == .debug); | |
| 3253 | 3253 | |
| 3254 | 3254 | out1[0] = 0xecec196accc52973; |
| 3255 | 3255 | out1[1] = 0x581a0db248b0a77a; |
| ... | ... | @@ -3289,7 +3289,7 @@ pub fn msat(out1: *[7]u64) void { |
| 3289 | 3289 | /// out4: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] |
| 3290 | 3290 | /// out5: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] |
| 3291 | 3291 | pub fn divstep(out1: *u64, out2: *[7]u64, out3: *[7]u64, out4: *[6]u64, out5: *[6]u64, arg1: u64, arg2: [7]u64, arg3: [7]u64, arg4: [6]u64, arg5: [6]u64) void { |
| 3292 | @setRuntimeSafety(mode == .Debug); | |
| 3292 | @setRuntimeSafety(mode == .debug); | |
| 3293 | 3293 | |
| 3294 | 3294 | var x1: u64 = undefined; |
| 3295 | 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 | 3615 | /// Output Bounds: |
| 3616 | 3616 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] |
| 3617 | 3617 | pub fn divstepPrecomp(out1: *[6]u64) void { |
| 3618 | @setRuntimeSafety(mode == .Debug); | |
| 3618 | @setRuntimeSafety(mode == .debug); | |
| 3619 | 3619 | |
| 3620 | 3620 | out1[0] = 0x49589ae0e6045b6a; |
| 3621 | 3621 | out1[1] = 0x3c9a5352870040ed; |
lib/std/crypto/pcurves/secp256k1.zig+5-7| ... | ... | @@ -51,7 +51,7 @@ pub const Secp256k1 = struct { |
| 51 | 51 | }; |
| 52 | 52 | |
| 53 | 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 | 55 | const b1_neg_s = comptime s: { |
| 56 | 56 | var buf: [32]u8 = undefined; |
| 57 | 57 | mem.writeInt(u256, &buf, 303414439467246543595250775667605759171, .little); |
| ... | ... | @@ -109,7 +109,7 @@ pub const Secp256k1 = struct { |
| 109 | 109 | } |
| 110 | 110 | |
| 111 | 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 | 113 | const x = try Fe.fromBytes(xs, endian); |
| 114 | 114 | const y = try Fe.fromBytes(ys, endian); |
| 115 | 115 | return fromAffineCoordinates(.{ .x = x, .y = y }); |
| ... | ... | @@ -423,7 +423,7 @@ pub const Secp256k1 = struct { |
| 423 | 423 | |
| 424 | 424 | /// Multiply an elliptic curve point by a scalar. |
| 425 | 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 | 427 | const s = if (endian == .little) s_ else Fe.orderSwap(s_); |
| 428 | 428 | if (p.is_base) { |
| 429 | 429 | return pcMul16(&basePointPc, s, false); |
| ... | ... | @@ -435,7 +435,7 @@ pub const Secp256k1 = struct { |
| 435 | 435 | |
| 436 | 436 | /// Multiply an elliptic curve point by a *PUBLIC* scalar *IN VARIABLE TIME* |
| 437 | 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 | 439 | const s = if (endian == .little) s_ else Fe.orderSwap(s_); |
| 440 | 440 | const zero = comptime scalar.Scalar.zero.toBytes(.little); |
| 441 | 441 | if (mem.eql(u8, &zero, &s)) { |
| ... | ... | @@ -497,7 +497,7 @@ pub const Secp256k1 = struct { |
| 497 | 497 | |
| 498 | 498 | /// Double-base multiplication of public parameters - Compute (p1*s1)+(p2*s2) *IN VARIABLE TIME* |
| 499 | 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 | 501 | const s1 = if (endian == .little) s1_ else Fe.orderSwap(s1_); |
| 502 | 502 | const s2 = if (endian == .little) s2_ else Fe.orderSwap(s2_); |
| 503 | 503 | try p1.rejectIdentity(); |
| ... | ... | @@ -556,7 +556,5 @@ pub const AffineCoordinates = struct { |
| 556 | 556 | }; |
| 557 | 557 | |
| 558 | 558 | test { |
| 559 | if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; | |
| 560 | ||
| 561 | 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 | 79 | /// out1: [0x0 ~> 0xffffffffffffffff] |
| 80 | 80 | /// out2: [0x0 ~> 0xffffffffffffffff] |
| 81 | 81 | fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void { |
| 82 | @setRuntimeSafety(mode == .Debug); | |
| 82 | @setRuntimeSafety(mode == .debug); | |
| 83 | 83 | |
| 84 | 84 | const x = @as(u128, arg1) * @as(u128, arg2); |
| 85 | 85 | out1.* = @as(u64, @truncate(x)); |
| ... | ... | @@ -98,7 +98,7 @@ fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void { |
| 98 | 98 | /// Output Bounds: |
| 99 | 99 | /// out1: [0x0 ~> 0xffffffffffffffff] |
| 100 | 100 | fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void { |
| 101 | @setRuntimeSafety(mode == .Debug); | |
| 101 | @setRuntimeSafety(mode == .debug); | |
| 102 | 102 | |
| 103 | 103 | const mask = 0 -% @as(u64, arg1); |
| 104 | 104 | out1.* = (mask & arg3) | ((~mask) & arg2); |
| ... | ... | @@ -114,7 +114,7 @@ fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void { |
| 114 | 114 | /// 0 ≤ eval out1 < m |
| 115 | 115 | /// |
| 116 | 116 | pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void { |
| 117 | @setRuntimeSafety(mode == .Debug); | |
| 117 | @setRuntimeSafety(mode == .debug); | |
| 118 | 118 | |
| 119 | 119 | const x1 = (arg1[1]); |
| 120 | 120 | const x2 = (arg1[2]); |
| ... | ... | @@ -454,7 +454,7 @@ pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme |
| 454 | 454 | /// 0 ≤ eval out1 < m |
| 455 | 455 | /// |
| 456 | 456 | pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void { |
| 457 | @setRuntimeSafety(mode == .Debug); | |
| 457 | @setRuntimeSafety(mode == .debug); | |
| 458 | 458 | |
| 459 | 459 | const x1 = (arg1[1]); |
| 460 | 460 | const x2 = (arg1[2]); |
| ... | ... | @@ -795,7 +795,7 @@ pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEl |
| 795 | 795 | /// 0 ≤ eval out1 < m |
| 796 | 796 | /// |
| 797 | 797 | pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void { |
| 798 | @setRuntimeSafety(mode == .Debug); | |
| 798 | @setRuntimeSafety(mode == .debug); | |
| 799 | 799 | |
| 800 | 800 | var x1: u64 = undefined; |
| 801 | 801 | var x2: u1 = undefined; |
| ... | ... | @@ -848,7 +848,7 @@ pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme |
| 848 | 848 | /// 0 ≤ eval out1 < m |
| 849 | 849 | /// |
| 850 | 850 | pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void { |
| 851 | @setRuntimeSafety(mode == .Debug); | |
| 851 | @setRuntimeSafety(mode == .debug); | |
| 852 | 852 | |
| 853 | 853 | var x1: u64 = undefined; |
| 854 | 854 | var x2: u1 = undefined; |
| ... | ... | @@ -891,7 +891,7 @@ pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme |
| 891 | 891 | /// 0 ≤ eval out1 < m |
| 892 | 892 | /// |
| 893 | 893 | pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void { |
| 894 | @setRuntimeSafety(mode == .Debug); | |
| 894 | @setRuntimeSafety(mode == .debug); | |
| 895 | 895 | |
| 896 | 896 | var x1: u64 = undefined; |
| 897 | 897 | var x2: u1 = undefined; |
| ... | ... | @@ -934,7 +934,7 @@ pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme |
| 934 | 934 | /// 0 ≤ eval out1 < m |
| 935 | 935 | /// |
| 936 | 936 | pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void { |
| 937 | @setRuntimeSafety(mode == .Debug); | |
| 937 | @setRuntimeSafety(mode == .debug); | |
| 938 | 938 | |
| 939 | 939 | const x1 = (arg1[0]); |
| 940 | 940 | var x2: u64 = undefined; |
| ... | ... | @@ -1167,7 +1167,7 @@ pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDo |
| 1167 | 1167 | /// 0 ≤ eval out1 < m |
| 1168 | 1168 | /// |
| 1169 | 1169 | pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDomainFieldElement) void { |
| 1170 | @setRuntimeSafety(mode == .Debug); | |
| 1170 | @setRuntimeSafety(mode == .debug); | |
| 1171 | 1171 | |
| 1172 | 1172 | const x1 = (arg1[1]); |
| 1173 | 1173 | const x2 = (arg1[2]); |
| ... | ... | @@ -1430,7 +1430,7 @@ pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDoma |
| 1430 | 1430 | /// Output Bounds: |
| 1431 | 1431 | /// out1: [0x0 ~> 0xffffffffffffffff] |
| 1432 | 1432 | pub fn nonzero(out1: *u64, arg1: [4]u64) void { |
| 1433 | @setRuntimeSafety(mode == .Debug); | |
| 1433 | @setRuntimeSafety(mode == .debug); | |
| 1434 | 1434 | |
| 1435 | 1435 | const x1 = ((arg1[0]) | ((arg1[1]) | ((arg1[2]) | (arg1[3])))); |
| 1436 | 1436 | out1.* = x1; |
| ... | ... | @@ -1448,7 +1448,7 @@ pub fn nonzero(out1: *u64, arg1: [4]u64) void { |
| 1448 | 1448 | /// Output Bounds: |
| 1449 | 1449 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] |
| 1450 | 1450 | pub fn selectznz(out1: *[4]u64, arg1: u1, arg2: [4]u64, arg3: [4]u64) void { |
| 1451 | @setRuntimeSafety(mode == .Debug); | |
| 1451 | @setRuntimeSafety(mode == .debug); | |
| 1452 | 1452 | |
| 1453 | 1453 | var x1: u64 = undefined; |
| 1454 | 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 | 1476 | /// Output Bounds: |
| 1477 | 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]] |
| 1478 | 1478 | pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void { |
| 1479 | @setRuntimeSafety(mode == .Debug); | |
| 1479 | @setRuntimeSafety(mode == .debug); | |
| 1480 | 1480 | |
| 1481 | 1481 | const x1 = (arg1[3]); |
| 1482 | 1482 | const x2 = (arg1[2]); |
| ... | ... | @@ -1585,7 +1585,7 @@ pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void { |
| 1585 | 1585 | /// Output Bounds: |
| 1586 | 1586 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] |
| 1587 | 1587 | pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void { |
| 1588 | @setRuntimeSafety(mode == .Debug); | |
| 1588 | @setRuntimeSafety(mode == .debug); | |
| 1589 | 1589 | |
| 1590 | 1590 | const x1 = (@as(u64, (arg1[31])) << 56); |
| 1591 | 1591 | const x2 = (@as(u64, (arg1[30])) << 48); |
| ... | ... | @@ -1660,7 +1660,7 @@ pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void { |
| 1660 | 1660 | /// 0 ≤ eval out1 < m |
| 1661 | 1661 | /// |
| 1662 | 1662 | pub fn setOne(out1: *MontgomeryDomainFieldElement) void { |
| 1663 | @setRuntimeSafety(mode == .Debug); | |
| 1663 | @setRuntimeSafety(mode == .debug); | |
| 1664 | 1664 | |
| 1665 | 1665 | out1[0] = 0x1000003d1; |
| 1666 | 1666 | out1[1] = 0x0; |
| ... | ... | @@ -1677,7 +1677,7 @@ pub fn setOne(out1: *MontgomeryDomainFieldElement) void { |
| 1677 | 1677 | /// Output Bounds: |
| 1678 | 1678 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] |
| 1679 | 1679 | pub fn msat(out1: *[5]u64) void { |
| 1680 | @setRuntimeSafety(mode == .Debug); | |
| 1680 | @setRuntimeSafety(mode == .debug); | |
| 1681 | 1681 | |
| 1682 | 1682 | out1[0] = 0xfffffffefffffc2f; |
| 1683 | 1683 | out1[1] = 0xffffffffffffffff; |
| ... | ... | @@ -1715,7 +1715,7 @@ pub fn msat(out1: *[5]u64) void { |
| 1715 | 1715 | /// out4: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] |
| 1716 | 1716 | /// out5: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] |
| 1717 | 1717 | pub fn divstep(out1: *u64, out2: *[5]u64, out3: *[5]u64, out4: *[4]u64, out5: *[4]u64, arg1: u64, arg2: [5]u64, arg3: [5]u64, arg4: [4]u64, arg5: [4]u64) void { |
| 1718 | @setRuntimeSafety(mode == .Debug); | |
| 1718 | @setRuntimeSafety(mode == .debug); | |
| 1719 | 1719 | |
| 1720 | 1720 | var x1: u64 = undefined; |
| 1721 | 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 | 1949 | /// Output Bounds: |
| 1950 | 1950 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] |
| 1951 | 1951 | pub fn divstepPrecomp(out1: *[4]u64) void { |
| 1952 | @setRuntimeSafety(mode == .Debug); | |
| 1952 | @setRuntimeSafety(mode == .debug); | |
| 1953 | 1953 | |
| 1954 | 1954 | out1[0] = 0xf201a41831525e0a; |
| 1955 | 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 | 79 | /// out1: [0x0 ~> 0xffffffffffffffff] |
| 80 | 80 | /// out2: [0x0 ~> 0xffffffffffffffff] |
| 81 | 81 | fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void { |
| 82 | @setRuntimeSafety(mode == .Debug); | |
| 82 | @setRuntimeSafety(mode == .debug); | |
| 83 | 83 | |
| 84 | 84 | const x = @as(u128, arg1) * @as(u128, arg2); |
| 85 | 85 | out1.* = @as(u64, @truncate(x)); |
| ... | ... | @@ -98,7 +98,7 @@ fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) void { |
| 98 | 98 | /// Output Bounds: |
| 99 | 99 | /// out1: [0x0 ~> 0xffffffffffffffff] |
| 100 | 100 | fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void { |
| 101 | @setRuntimeSafety(mode == .Debug); | |
| 101 | @setRuntimeSafety(mode == .debug); | |
| 102 | 102 | |
| 103 | 103 | const mask = 0 -% @as(u64, arg1); |
| 104 | 104 | out1.* = (mask & arg3) | ((~mask) & arg2); |
| ... | ... | @@ -114,7 +114,7 @@ fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) void { |
| 114 | 114 | /// 0 ≤ eval out1 < m |
| 115 | 115 | /// |
| 116 | 116 | pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void { |
| 117 | @setRuntimeSafety(mode == .Debug); | |
| 117 | @setRuntimeSafety(mode == .debug); | |
| 118 | 118 | |
| 119 | 119 | const x1 = (arg1[1]); |
| 120 | 120 | const x2 = (arg1[2]); |
| ... | ... | @@ -454,7 +454,7 @@ pub fn mul(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme |
| 454 | 454 | /// 0 ≤ eval out1 < m |
| 455 | 455 | /// |
| 456 | 456 | pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void { |
| 457 | @setRuntimeSafety(mode == .Debug); | |
| 457 | @setRuntimeSafety(mode == .debug); | |
| 458 | 458 | |
| 459 | 459 | const x1 = (arg1[1]); |
| 460 | 460 | const x2 = (arg1[2]); |
| ... | ... | @@ -795,7 +795,7 @@ pub fn square(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEl |
| 795 | 795 | /// 0 ≤ eval out1 < m |
| 796 | 796 | /// |
| 797 | 797 | pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void { |
| 798 | @setRuntimeSafety(mode == .Debug); | |
| 798 | @setRuntimeSafety(mode == .debug); | |
| 799 | 799 | |
| 800 | 800 | var x1: u64 = undefined; |
| 801 | 801 | var x2: u1 = undefined; |
| ... | ... | @@ -848,7 +848,7 @@ pub fn add(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme |
| 848 | 848 | /// 0 ≤ eval out1 < m |
| 849 | 849 | /// |
| 850 | 850 | pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement, arg2: MontgomeryDomainFieldElement) void { |
| 851 | @setRuntimeSafety(mode == .Debug); | |
| 851 | @setRuntimeSafety(mode == .debug); | |
| 852 | 852 | |
| 853 | 853 | var x1: u64 = undefined; |
| 854 | 854 | var x2: u1 = undefined; |
| ... | ... | @@ -891,7 +891,7 @@ pub fn sub(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme |
| 891 | 891 | /// 0 ≤ eval out1 < m |
| 892 | 892 | /// |
| 893 | 893 | pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void { |
| 894 | @setRuntimeSafety(mode == .Debug); | |
| 894 | @setRuntimeSafety(mode == .debug); | |
| 895 | 895 | |
| 896 | 896 | var x1: u64 = undefined; |
| 897 | 897 | var x2: u1 = undefined; |
| ... | ... | @@ -934,7 +934,7 @@ pub fn opp(out1: *MontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldEleme |
| 934 | 934 | /// 0 ≤ eval out1 < m |
| 935 | 935 | /// |
| 936 | 936 | pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDomainFieldElement) void { |
| 937 | @setRuntimeSafety(mode == .Debug); | |
| 937 | @setRuntimeSafety(mode == .debug); | |
| 938 | 938 | |
| 939 | 939 | const x1 = (arg1[0]); |
| 940 | 940 | var x2: u64 = undefined; |
| ... | ... | @@ -1167,7 +1167,7 @@ pub fn fromMontgomery(out1: *NonMontgomeryDomainFieldElement, arg1: MontgomeryDo |
| 1167 | 1167 | /// 0 ≤ eval out1 < m |
| 1168 | 1168 | /// |
| 1169 | 1169 | pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDomainFieldElement) void { |
| 1170 | @setRuntimeSafety(mode == .Debug); | |
| 1170 | @setRuntimeSafety(mode == .debug); | |
| 1171 | 1171 | |
| 1172 | 1172 | const x1 = (arg1[1]); |
| 1173 | 1173 | const x2 = (arg1[2]); |
| ... | ... | @@ -1490,7 +1490,7 @@ pub fn toMontgomery(out1: *MontgomeryDomainFieldElement, arg1: NonMontgomeryDoma |
| 1490 | 1490 | /// Output Bounds: |
| 1491 | 1491 | /// out1: [0x0 ~> 0xffffffffffffffff] |
| 1492 | 1492 | pub fn nonzero(out1: *u64, arg1: [4]u64) void { |
| 1493 | @setRuntimeSafety(mode == .Debug); | |
| 1493 | @setRuntimeSafety(mode == .debug); | |
| 1494 | 1494 | |
| 1495 | 1495 | const x1 = ((arg1[0]) | ((arg1[1]) | ((arg1[2]) | (arg1[3])))); |
| 1496 | 1496 | out1.* = x1; |
| ... | ... | @@ -1508,7 +1508,7 @@ pub fn nonzero(out1: *u64, arg1: [4]u64) void { |
| 1508 | 1508 | /// Output Bounds: |
| 1509 | 1509 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] |
| 1510 | 1510 | pub fn selectznz(out1: *[4]u64, arg1: u1, arg2: [4]u64, arg3: [4]u64) void { |
| 1511 | @setRuntimeSafety(mode == .Debug); | |
| 1511 | @setRuntimeSafety(mode == .debug); | |
| 1512 | 1512 | |
| 1513 | 1513 | var x1: u64 = undefined; |
| 1514 | 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 | 1536 | /// Output Bounds: |
| 1537 | 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]] |
| 1538 | 1538 | pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void { |
| 1539 | @setRuntimeSafety(mode == .Debug); | |
| 1539 | @setRuntimeSafety(mode == .debug); | |
| 1540 | 1540 | |
| 1541 | 1541 | const x1 = (arg1[3]); |
| 1542 | 1542 | const x2 = (arg1[2]); |
| ... | ... | @@ -1645,7 +1645,7 @@ pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void { |
| 1645 | 1645 | /// Output Bounds: |
| 1646 | 1646 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] |
| 1647 | 1647 | pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void { |
| 1648 | @setRuntimeSafety(mode == .Debug); | |
| 1648 | @setRuntimeSafety(mode == .debug); | |
| 1649 | 1649 | |
| 1650 | 1650 | const x1 = (@as(u64, (arg1[31])) << 56); |
| 1651 | 1651 | const x2 = (@as(u64, (arg1[30])) << 48); |
| ... | ... | @@ -1720,7 +1720,7 @@ pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void { |
| 1720 | 1720 | /// 0 ≤ eval out1 < m |
| 1721 | 1721 | /// |
| 1722 | 1722 | pub fn setOne(out1: *MontgomeryDomainFieldElement) void { |
| 1723 | @setRuntimeSafety(mode == .Debug); | |
| 1723 | @setRuntimeSafety(mode == .debug); | |
| 1724 | 1724 | |
| 1725 | 1725 | out1[0] = 0x402da1732fc9bebf; |
| 1726 | 1726 | out1[1] = 0x4551231950b75fc4; |
| ... | ... | @@ -1737,7 +1737,7 @@ pub fn setOne(out1: *MontgomeryDomainFieldElement) void { |
| 1737 | 1737 | /// Output Bounds: |
| 1738 | 1738 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] |
| 1739 | 1739 | pub fn msat(out1: *[5]u64) void { |
| 1740 | @setRuntimeSafety(mode == .Debug); | |
| 1740 | @setRuntimeSafety(mode == .debug); | |
| 1741 | 1741 | |
| 1742 | 1742 | out1[0] = 0xbfd25e8cd0364141; |
| 1743 | 1743 | out1[1] = 0xbaaedce6af48a03b; |
| ... | ... | @@ -1775,7 +1775,7 @@ pub fn msat(out1: *[5]u64) void { |
| 1775 | 1775 | /// out4: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] |
| 1776 | 1776 | /// out5: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] |
| 1777 | 1777 | pub fn divstep(out1: *u64, out2: *[5]u64, out3: *[5]u64, out4: *[4]u64, out5: *[4]u64, arg1: u64, arg2: [5]u64, arg3: [5]u64, arg4: [4]u64, arg5: [4]u64) void { |
| 1778 | @setRuntimeSafety(mode == .Debug); | |
| 1778 | @setRuntimeSafety(mode == .debug); | |
| 1779 | 1779 | |
| 1780 | 1780 | var x1: u64 = undefined; |
| 1781 | 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 | 2009 | /// Output Bounds: |
| 2010 | 2010 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] |
| 2011 | 2011 | pub fn divstepPrecomp(out1: *[4]u64) void { |
| 2012 | @setRuntimeSafety(mode == .Debug); | |
| 2012 | @setRuntimeSafety(mode == .debug); | |
| 2013 | 2013 | |
| 2014 | 2014 | out1[0] = 0xd7431a4d2b9cb4e9; |
| 2015 | 2015 | out1[1] = 0xab67d35a32d9c503; |
lib/std/crypto/tls/Client.zig+1-1| ... | ... | @@ -1588,7 +1588,7 @@ const CertificatePublicKey = struct { |
| 1588 | 1588 | inline 128, 256, 384, 512 => |modulus_len| { |
| 1589 | 1589 | const key: PublicKey = try .fromBytes(exponent, modulus); |
| 1590 | 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 | 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 | 151 | @branchHint(.cold); |
| 152 | 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 | 158 | pub fn integerOutOfBounds() noreturn { |
| 155 | 159 | @branchHint(.cold); |
| 156 | 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 | 211 | @branchHint(.cold); |
| 208 | 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 | } |
| 212 | 220 | |
| ... | ... | @@ -237,13 +245,12 @@ pub const Symbol = struct { |
| 237 | 245 | }; |
| 238 | 246 | }; |
| 239 | 247 | |
| 240 | /// Deprecated because it returns the optimization mode of the standard | |
| 241 | /// library, when the caller probably wants to use the optimization mode of | |
| 242 | /// their own module. | |
| 243 | pub const runtime_safety = switch (builtin.mode) { | |
| 244 | .Debug, .ReleaseSafe => true, | |
| 245 | .ReleaseFast, .ReleaseSmall => false, | |
| 246 | }; | |
| 248 | /// Deprecated in favor of `std.lang.Optimize.runtimeSafety`, to be removed after 0.18.0 | |
| 249 | /// | |
| 250 | /// Returns whether the standard library has safety checks enabled. Callsites | |
| 251 | /// likely would rather know whether their own module's optimization mode | |
| 252 | /// (found via `@import("builtin").optimize`) has safety checks enabled. | |
| 253 | pub const runtime_safety = builtin.mode.runtimeSafety(); | |
| 247 | 254 | |
| 248 | 255 | /// Whether we can unwind the stack on this target, allowing capturing and/or printing the current |
| 249 | 256 | /// 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 | 264 | // because Emscripten's implementation is very slow. |
| 258 | 265 | .wasm32, |
| 259 | 266 | .wasm64, |
| 260 | => native_os == .emscripten and builtin.mode == .Debug, | |
| 267 | => native_os == .emscripten and builtin.mode == .debug, | |
| 261 | 268 | |
| 262 | 269 | // `@returnAddress()` is unsupported in LLVM 21. |
| 263 | 270 | .bpfel, |
| ... | ... | @@ -419,16 +426,16 @@ pub const CpuContextPtr = if (cpu_context.Native == noreturn) noreturn else *con |
| 419 | 426 | |
| 420 | 427 | /// Invokes detectable illegal behavior when `ok` is `false`. |
| 421 | 428 | /// |
| 422 | /// In Debug and ReleaseSafe modes, calls to this function are always | |
| 429 | /// In debug and safe modes, calls to this function are always | |
| 423 | 430 | /// generated, and the `unreachable` statement triggers a panic. |
| 424 | 431 | /// |
| 425 | /// In ReleaseFast and ReleaseSmall modes, calls to this function are optimized | |
| 432 | /// In fast and small modes, calls to this function are optimized | |
| 426 | 433 | /// away, and in fact the optimizer is able to use the assertion in its |
| 427 | 434 | /// heuristics. |
| 428 | 435 | /// |
| 429 | 436 | /// Inside a test block, it is best to use the `testing` module rather than |
| 430 | 437 | /// this function, because this function may not detect a test failure in |
| 431 | /// ReleaseFast and ReleaseSmall mode. Outside of a test block, this assert | |
| 438 | /// fast and small mode. Outside of a test block, this assert | |
| 432 | 439 | /// function is the correct function to use. |
| 433 | 440 | pub fn assert(ok: bool) void { |
| 434 | 441 | @disableInstrumentation(); |
| ... | ... | @@ -1760,7 +1767,7 @@ test "manage resources correctly" { |
| 1760 | 1767 | /// In release mode, it is size 0 and all methods are no-ops. |
| 1761 | 1768 | /// This is a pre-made type with default settings. |
| 1762 | 1769 | /// For more advanced usage, see `ConfigurableTrace`. |
| 1763 | pub const Trace = ConfigurableTrace(2, 4, builtin.mode == .Debug); | |
| 1770 | pub const Trace = ConfigurableTrace(2, 4, builtin.mode == .debug); | |
| 1764 | 1771 | |
| 1765 | 1772 | pub fn ConfigurableTrace(comptime size: usize, comptime stack_frame_count: usize, comptime is_enabled: bool) type { |
| 1766 | 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 | 450 | unit_header.format, |
| 451 | 451 | endian, |
| 452 | 452 | address_size, |
| 453 | version, | |
| 453 | 454 | )) orelse continue; |
| 454 | 455 | |
| 455 | 456 | switch (die_obj.tag_id) { |
| ... | ... | @@ -485,6 +486,7 @@ fn scanAllFunctions(di: *Dwarf, gpa: Allocator, endian: Endian) ScanError!void { |
| 485 | 486 | unit_header.format, |
| 486 | 487 | endian, |
| 487 | 488 | address_size, |
| 489 | version, | |
| 488 | 490 | )) orelse return bad(); |
| 489 | 491 | } else if (this_die_obj.getAttr(AT.specification)) |_| { |
| 490 | 492 | const after_die_offset = fr.seek; |
| ... | ... | @@ -500,6 +502,7 @@ fn scanAllFunctions(di: *Dwarf, gpa: Allocator, endian: Endian) ScanError!void { |
| 500 | 502 | unit_header.format, |
| 501 | 503 | endian, |
| 502 | 504 | address_size, |
| 505 | version, | |
| 503 | 506 | )) orelse return bad(); |
| 504 | 507 | } else { |
| 505 | 508 | break :x null; |
| ... | ... | @@ -611,6 +614,7 @@ fn scanAllCompileUnits(di: *Dwarf, gpa: Allocator, endian: Endian) ScanError!voi |
| 611 | 614 | unit_header.format, |
| 612 | 615 | endian, |
| 613 | 616 | address_size, |
| 617 | version, | |
| 614 | 618 | )) orelse return bad(); |
| 615 | 619 | |
| 616 | 620 | if (compile_unit_die.tag_id != DW.TAG.compile_unit) return bad(); |
| ... | ... | @@ -931,6 +935,7 @@ fn parseDie( |
| 931 | 935 | format: Format, |
| 932 | 936 | endian: Endian, |
| 933 | 937 | addr_size_bytes: u8, |
| 938 | version: u16, | |
| 934 | 939 | ) ScanError!?Die { |
| 935 | 940 | const abbrev_code = try fr.takeLeb128(u64); |
| 936 | 941 | if (abbrev_code == 0) return null; |
| ... | ... | @@ -939,7 +944,7 @@ fn parseDie( |
| 939 | 944 | const attrs = attrs_buf[0..table_entry.attrs.len]; |
| 940 | 945 | for (attrs, table_entry.attrs) |*result_attr, attr| result_attr.* = .{ |
| 941 | 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 | 949 | return .{ |
| 945 | 950 | .tag_id = table_entry.tag_id, |
| ... | ... | @@ -1042,7 +1047,7 @@ fn runLineNumberProgram(d: *Dwarf, gpa: Allocator, endian: Endian, compile_unit: |
| 1042 | 1047 | for (try directories.addManyAsSlice(gpa, directories_count)) |*e| { |
| 1043 | 1048 | e.* = .{ .path = &.{} }; |
| 1044 | 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 | 1051 | switch (ent_fmt.content_type_code) { |
| 1047 | 1052 | DW.LNCT.path => e.path = try form_value.getString(d.*), |
| 1048 | 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 | 1079 | for (try file_entries.addManyAsSlice(gpa, file_names_count)) |*e| { |
| 1075 | 1080 | e.* = .{ .path = &.{} }; |
| 1076 | 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 | 1083 | switch (ent_fmt.content_type_code) { |
| 1079 | 1084 | DW.LNCT.path => e.path = try form_value.getString(d.*), |
| 1080 | 1085 | DW.LNCT.directory_index => e.dir_index = try form_value.getUInt(u32), |
| ... | ... | @@ -1285,6 +1290,7 @@ fn parseFormValue( |
| 1285 | 1290 | endian: Endian, |
| 1286 | 1291 | addr_size_bytes: u8, |
| 1287 | 1292 | implicit_const: ?i64, |
| 1293 | version: u16, | |
| 1288 | 1294 | ) ScanError!FormValue { |
| 1289 | 1295 | return switch (form_id) { |
| 1290 | 1296 | // DWARF5.pdf page 213: the size of this value is encoded in the |
| ... | ... | @@ -1319,7 +1325,12 @@ fn parseFormValue( |
| 1319 | 1325 | FORM.ref8 => .{ .ref = try r.takeInt(u64, endian) }, |
| 1320 | 1326 | FORM.ref_udata => .{ .ref = try r.takeLeb128(u64) }, |
| 1321 | 1327 | |
| 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 | 1334 | FORM.ref_sig8 => .{ .ref = try r.takeInt(u64, endian) }, |
| 1324 | 1335 | |
| 1325 | 1336 | FORM.string => .{ .string = try r.takeSentinel(0) }, |
| ... | ... | @@ -1330,7 +1341,7 @@ fn parseFormValue( |
| 1330 | 1341 | FORM.strx4 => .{ .strx = try r.takeInt(u32, endian) }, |
| 1331 | 1342 | FORM.strx => .{ .strx = try r.takeLeb128(usize) }, |
| 1332 | 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 | 1345 | FORM.implicit_const => .{ .sdata = implicit_const orelse return bad() }, |
| 1335 | 1346 | FORM.loclistx => .{ .loclistx = try r.takeLeb128(u64) }, |
| 1336 | 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 | 2 | symbols: []const Symbol, |
| 3 | 3 | strings: []const u8, |
| 4 | 4 | text_vmaddr: u64, |
| 5 | uuid: ?Uuid, | |
| 6 | adjacent_dsym: ?DsymFile, | |
| 5 | 7 | |
| 6 | 8 | /// Key is index into `strings` of the file path. |
| 7 | 9 | ofiles: std.array_hash_map.Auto(u32, Error!OFile), |
| ... | ... | @@ -16,6 +18,7 @@ pub const Error = error{ |
| 16 | 18 | }; |
| 17 | 19 | |
| 18 | 20 | pub fn deinit(mf: *MachOFile, gpa: Allocator) void { |
| 21 | if (mf.adjacent_dsym) |*dsym| dsym.deinit(gpa); | |
| 19 | 22 | for (mf.ofiles.values()) |*maybe_of| { |
| 20 | 23 | const of = &(maybe_of.* catch continue); |
| 21 | 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 | 39 | const all_mapped_memory = try mapDebugInfoFile(io, path); |
| 37 | 40 | errdefer posix.munmap(all_mapped_memory); |
| 38 | 41 | |
| 39 | // In most cases, the file we just mapped is a Mach-O binary. However, it could be a "universal | |
| 40 | // binary": a simple file format which contains Mach-O binaries for multiple targets. For | |
| 41 | // instance, `/usr/lib/dyld` is currently distributed as a universal binary containing images | |
| 42 | // for both ARM64 macOS and x86_64 macOS. | |
| 43 | if (all_mapped_memory.len < 4) return error.InvalidMachO; | |
| 44 | const magic = std.mem.readInt(u32, all_mapped_memory.ptr[0..4], .little); | |
| 45 | ||
| 46 | // The contents of a Mach-O file, which may or may not be the whole of `all_mapped_memory`. | |
| 47 | const mapped_macho = switch (magic) { | |
| 48 | macho.MH_MAGIC_64 => all_mapped_memory, | |
| 49 | ||
| 50 | macho.FAT_CIGAM => mapped_macho: { | |
| 51 | // This is the universal binary format (aka a "fat binary"). | |
| 52 | var fat_r: Io.Reader = .fixed(all_mapped_memory); | |
| 53 | const hdr = fat_r.takeStruct(macho.fat_header, .big) catch |err| switch (err) { | |
| 54 | error.ReadFailed => unreachable, | |
| 55 | error.EndOfStream => return error.InvalidMachO, | |
| 56 | }; | |
| 57 | const want_cpu_type = switch (arch) { | |
| 58 | .x86_64 => macho.CPU_TYPE_X86_64, | |
| 59 | .aarch64 => macho.CPU_TYPE_ARM64, | |
| 60 | else => unreachable, | |
| 61 | }; | |
| 62 | for (0..hdr.nfat_arch) |_| { | |
| 63 | const fat_arch = fat_r.takeStruct(macho.fat_arch, .big) catch |err| switch (err) { | |
| 64 | error.ReadFailed => unreachable, | |
| 65 | error.EndOfStream => return error.InvalidMachO, | |
| 66 | }; | |
| 67 | if (fat_arch.cputype != want_cpu_type) continue; | |
| 68 | if (fat_arch.offset + fat_arch.size > all_mapped_memory.len) return error.InvalidMachO; | |
| 69 | break :mapped_macho all_mapped_memory[fat_arch.offset..][0..fat_arch.size]; | |
| 70 | } | |
| 71 | // `arch` was not present in the fat binary. | |
| 72 | return error.MissingDebugInfo; | |
| 73 | }, | |
| 74 | ||
| 75 | // Even on modern 64-bit targets, this format doesn't seem to be too extensively used. It | |
| 76 | // will be fairly easy to add support here if necessary; it's very similar to above. | |
| 77 | macho.FAT_CIGAM_64 => return error.UnsupportedDebugInfo, | |
| 78 | ||
| 79 | else => return error.InvalidMachO, | |
| 80 | }; | |
| 42 | const mapped_macho = try selectMachOSlice(all_mapped_memory, arch); | |
| 81 | 43 | |
| 82 | 44 | var r: Io.Reader = .fixed(mapped_macho); |
| 83 | 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 | 50 | if (hdr.magic != macho.MH_MAGIC_64) |
| 89 | 51 | return error.InvalidMachO; |
| 90 | 52 | |
| 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 | 54 | var it: macho.LoadCommandIterator = try .init(&hdr, mapped_macho[@sizeOf(macho.mach_header_64)..]); |
| 93 | 55 | var symtab: ?macho.symtab_command = null; |
| 94 | 56 | var text_vmaddr: ?u64 = null; |
| 57 | var uuid: ?Uuid = null; | |
| 95 | 58 | while (try it.next()) |cmd| switch (cmd.hdr.cmd) { |
| 96 | 59 | .SYMTAB => symtab = cmd.cast(macho.symtab_command) orelse return error.InvalidMachO, |
| 97 | 60 | .SEGMENT_64 => if (cmd.cast(macho.segment_command_64)) |seg_cmd| { |
| 98 | 61 | if (!mem.eql(u8, seg_cmd.segName(), "__TEXT")) continue; |
| 99 | 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 | 67 | else => {}, |
| 102 | 68 | }; |
| 103 | 69 | break :lcs .{ |
| 104 | 70 | symtab orelse return error.MissingDebugInfo, |
| 105 | 71 | text_vmaddr orelse return error.MissingDebugInfo, |
| 72 | uuid, | |
| 106 | 73 | }; |
| 107 | 74 | }; |
| 108 | 75 | |
| ... | ... | @@ -253,15 +220,27 @@ pub fn load(gpa: Allocator, io: Io, path: []const u8, arch: std.Target.Cpu.Arch) |
| 253 | 220 | // This sort is so that we can binary search later. |
| 254 | 221 | mem.sort(Symbol, symbols_slice, {}, Symbol.addressLessThan); |
| 255 | 222 | |
| 223 | const adjacent_dsym = if (uuid) |expected_uuid| | |
| 224 | try loadAdjacentDsym(gpa, io, path, arch, expected_uuid) | |
| 225 | else | |
| 226 | null; | |
| 227 | ||
| 256 | 228 | return .{ |
| 257 | 229 | .mapped_memory = all_mapped_memory, |
| 258 | 230 | .symbols = symbols_slice, |
| 259 | 231 | .strings = strings, |
| 260 | 232 | .ofiles = .empty, |
| 261 | 233 | .text_vmaddr = text_vmaddr, |
| 234 | .uuid = uuid, | |
| 235 | .adjacent_dsym = adjacent_dsym, | |
| 262 | 236 | }; |
| 263 | 237 | } |
| 238 | ||
| 264 | 239 | pub 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 | 244 | const symbol = Symbol.find(mf.symbols, vaddr) orelse return error.MissingDebugInfo; |
| 266 | 245 | |
| 267 | 246 | if (symbol.ofile == Symbol.unknown_ofile) return error.MissingDebugInfo; |
| ... | ... | @@ -324,6 +303,16 @@ const OFile = struct { |
| 324 | 303 | }; |
| 325 | 304 | }; |
| 326 | 305 | |
| 306 | const 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 | ||
| 327 | 316 | const Symbol = struct { |
| 328 | 317 | strx: u32, |
| 329 | 318 | addr: u64, |
| ... | ... | @@ -394,6 +383,74 @@ fn appendStabSymbol( |
| 394 | 383 | } |
| 395 | 384 | } |
| 396 | 385 | |
| 386 | fn 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 | ||
| 411 | fn 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 | ||
| 397 | 454 | fn loadOFile(gpa: Allocator, io: Io, o_file_name: []const u8) !OFile { |
| 398 | 455 | const all_mapped_memory, const mapped_ofile = map: { |
| 399 | 456 | const open_paren = paren: { |
| ... | ... | @@ -497,19 +554,38 @@ fn loadOFile(gpa: Allocator, io: Io, o_file_name: []const u8) !OFile { |
| 497 | 554 | gop.key_ptr.* = @intCast(sym_index); |
| 498 | 555 | } |
| 499 | 556 | |
| 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 | ||
| 568 | fn loadDwarfFromSections( | |
| 569 | gpa: Allocator, | |
| 570 | mapped_macho: []const u8, | |
| 571 | section_headers: []align(1) const macho.section_64, | |
| 572 | ) !Dwarf { | |
| 500 | 573 | var sections: Dwarf.SectionArray = @splat(null); |
| 501 | for (seg_cmd.getSections()) |sect_raw| { | |
| 574 | for (section_headers) |sect_raw| { | |
| 502 | 575 | var sect = sect_raw; |
| 503 | 576 | if (builtin.cpu.arch.endian() != .little) std.mem.byteSwapAllFields(macho.section_64, &sect); |
| 504 | 577 | |
| 505 | 578 | if (!std.mem.eql(u8, "__DWARF", sect.segName())) continue; |
| 506 | 579 | |
| 507 | const section_index: usize = inline for (@typeInfo(Dwarf.Section.Id).@"enum".field_names, 0..) |section_name, i| { | |
| 508 | if (mem.eql(u8, "__" ++ section_name, sect.sectName())) break i; | |
| 580 | const section_index: usize = inline for (@typeInfo(Dwarf.Section.Id).@"enum".field_names, 0..) |field_name, i| { | |
| 581 | const section_name_long = "__" ++ field_name; | |
| 582 | // Some dwarf section names don't fit in the `sectname` buffer, so they are truncated. | |
| 583 | const section_name_trunc = section_name_long[0..@min(section_name_long.len, sect.sectname.len)]; | |
| 584 | if (mem.eql(u8, section_name_trunc, sect.sectName())) break i; | |
| 509 | 585 | } else continue; |
| 510 | 586 | |
| 511 | if (mapped_ofile.len < sect.offset + sect.size) return error.InvalidMachO; | |
| 512 | const section_bytes = mapped_ofile[sect.offset..][0..sect.size]; | |
| 587 | if (mapped_macho.len < sect.offset + sect.size) return error.InvalidMachO; | |
| 588 | const section_bytes = mapped_macho[sect.offset..][0..sect.size]; | |
| 513 | 589 | sections[section_index] = .{ |
| 514 | 590 | .data = section_bytes, |
| 515 | 591 | .owned = false, |
| ... | ... | @@ -539,13 +615,56 @@ fn loadOFile(gpa: Allocator, io: Io, o_file_name: []const u8) !OFile { |
| 539 | 615 | => |e| return e, |
| 540 | 616 | }; |
| 541 | 617 | |
| 542 | return .{ | |
| 543 | .mapped_memory = all_mapped_memory, | |
| 544 | .dwarf = dwarf, | |
| 545 | .strtab = strtab, | |
| 546 | .symtab_raw = symtab_raw, | |
| 547 | .symbols_by_name = symbols_by_name.move(), | |
| 618 | return dwarf; | |
| 619 | } | |
| 620 | ||
| 621 | fn selectMachOSlice( | |
| 622 | all_mapped_memory: []align(std.heap.page_size_min) const u8, | |
| 623 | arch: std.Target.Cpu.Arch, | |
| 624 | ) Error![]const u8 { | |
| 625 | // In most cases, the file we just mapped is a Mach-O binary. However, it could be a "universal | |
| 626 | // binary": a simple file format which contains Mach-O binaries for multiple targets. For | |
| 627 | // instance, `/usr/lib/dyld` is currently distributed as a universal binary containing images | |
| 628 | // for both ARM64 macOS and x86_64 macOS. | |
| 629 | if (all_mapped_memory.len < 4) return error.InvalidMachO; | |
| 630 | const magic = std.mem.readInt(u32, all_mapped_memory.ptr[0..4], .little); | |
| 631 | ||
| 632 | // The contents of a Mach-O file, which may or may not be the whole of `all_mapped_memory`. | |
| 633 | const mapped_macho = switch (magic) { | |
| 634 | macho.MH_MAGIC_64 => all_mapped_memory, | |
| 635 | ||
| 636 | macho.FAT_CIGAM => mapped_macho: { | |
| 637 | // This is the universal binary format (aka a "fat binary"). | |
| 638 | var fat_r: Io.Reader = .fixed(all_mapped_memory); | |
| 639 | const hdr = fat_r.takeStruct(macho.fat_header, .big) catch |err| switch (err) { | |
| 640 | error.ReadFailed => unreachable, | |
| 641 | error.EndOfStream => return error.InvalidMachO, | |
| 642 | }; | |
| 643 | const want_cpu_type = switch (arch) { | |
| 644 | .x86_64 => macho.CPU_TYPE_X86_64, | |
| 645 | .aarch64 => macho.CPU_TYPE_ARM64, | |
| 646 | else => unreachable, | |
| 647 | }; | |
| 648 | for (0..hdr.nfat_arch) |_| { | |
| 649 | const fat_arch = fat_r.takeStruct(macho.fat_arch, .big) catch |err| switch (err) { | |
| 650 | error.ReadFailed => unreachable, | |
| 651 | error.EndOfStream => return error.InvalidMachO, | |
| 652 | }; | |
| 653 | if (fat_arch.cputype != want_cpu_type) continue; | |
| 654 | if (fat_arch.offset + fat_arch.size > all_mapped_memory.len) return error.InvalidMachO; | |
| 655 | break :mapped_macho all_mapped_memory[fat_arch.offset..][0..fat_arch.size]; | |
| 656 | } | |
| 657 | // `arch` was not present in the fat binary. | |
| 658 | return error.MissingDebugInfo; | |
| 659 | }, | |
| 660 | ||
| 661 | // Even on modern 64-bit targets, this format doesn't seem to be too extensively used. It | |
| 662 | // will be fairly easy to add support here if necessary; it's very similar to above. | |
| 663 | macho.FAT_CIGAM_64 => return error.UnsupportedDebugInfo, | |
| 664 | ||
| 665 | else => return error.InvalidMachO, | |
| 548 | 666 | }; |
| 667 | return mapped_macho; | |
| 549 | 668 | } |
| 550 | 669 | |
| 551 | 670 | /// Uses `mmap` to map the file at `path` into memory. |
| ... | ... | @@ -583,4 +702,5 @@ const testing = std.testing; |
| 583 | 702 | |
| 584 | 703 | const builtin = @import("builtin"); |
| 585 | 704 | |
| 705 | const Uuid = @FieldType(macho.uuid_command, "uuid"); | |
| 586 | 706 | const 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 | 428 | // Rebuild module list with the exclusive lock. |
| 429 | 429 | { |
| 430 | 430 | errdefer si.rwlock.unlock(io); |
| 431 | if (si.unwind_cache) |cache| { | |
| 432 | @memset(cache, .empty); | |
| 433 | } | |
| 431 | 434 | for (si.modules.items) |*mod| { |
| 432 | 435 | unwind: { |
| 433 | 436 | const u = &(mod.unwind orelse break :unwind catch break :unwind); |
| ... | ... | @@ -515,7 +518,7 @@ const DlIterContext = struct { |
| 515 | 518 | for (info.phdr[0..info.phnum]) |phdr| { |
| 516 | 519 | if (phdr.type != .LOAD) continue; |
| 517 | 520 | try context.si.ranges.append(gpa, .{ |
| 518 | // Overflowing addition handles VSDOs having p_vaddr = 0xffffffffff700000 | |
| 521 | // Overflowing addition handles VSDOs having vaddr = 0xffffffffff700000 | |
| 519 | 522 | .start = info.addr +% phdr.vaddr, |
| 520 | 523 | .len = phdr.memsz, |
| 521 | 524 | .module_index = module_index, |
lib/std/debug/cpu_context.zig+2| ... | ... | @@ -2020,6 +2020,8 @@ const signal_ucontext_t = switch (native_os) { |
| 2020 | 2020 | .mips64el, |
| 2021 | 2021 | .or1k, |
| 2022 | 2022 | .s390x, |
| 2023 | .sh, | |
| 2024 | .sheb, | |
| 2023 | 2025 | .x86, |
| 2024 | 2026 | .x86_64, |
| 2025 | 2027 | .xtensa, |
lib/std/debug/no_panic.zig+10| ... | ... | @@ -65,6 +65,11 @@ pub fn invalidErrorCode() noreturn { |
| 65 | 65 | @trap(); |
| 66 | 66 | } |
| 67 | 67 | |
| 68 | pub fn unexpectedErrorCode(_: anyerror) noreturn { | |
| 69 | @branchHint(.cold); | |
| 70 | @trap(); | |
| 71 | } | |
| 72 | ||
| 68 | 73 | pub fn integerOutOfBounds() noreturn { |
| 69 | 74 | @branchHint(.cold); |
| 70 | 75 | @trap(); |
| ... | ... | @@ -134,3 +139,8 @@ pub fn noreturnReturned() noreturn { |
| 134 | 139 | @branchHint(.cold); |
| 135 | 140 | @trap(); |
| 136 | 141 | } |
| 142 | ||
| 143 | pub 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 | 20 | } |
| 21 | 21 | |
| 22 | 22 | pub fn sentinelMismatch(expected: anytype, found: @TypeOf(expected)) noreturn { |
| 23 | @branchHint(.cold); | |
| 23 | 24 | _ = found; |
| 24 | 25 | call("sentinel mismatch", null); |
| 25 | 26 | } |
| 26 | 27 | |
| 27 | 28 | pub fn unwrapError(err: anyerror) noreturn { |
| 29 | @branchHint(.cold); | |
| 28 | 30 | _ = &err; |
| 29 | 31 | call("attempt to unwrap error", null); |
| 30 | 32 | } |
| 31 | 33 | |
| 32 | 34 | pub fn outOfBounds(index: usize, len: usize) noreturn { |
| 35 | @branchHint(.cold); | |
| 33 | 36 | _ = index; |
| 34 | 37 | _ = len; |
| 35 | 38 | call("index out of bounds", null); |
| 36 | 39 | } |
| 37 | 40 | |
| 38 | 41 | pub fn startGreaterThanEnd(start: usize, end: usize) noreturn { |
| 42 | @branchHint(.cold); | |
| 39 | 43 | _ = start; |
| 40 | 44 | _ = end; |
| 41 | 45 | call("start index is larger than end index", null); |
| 42 | 46 | } |
| 43 | 47 | |
| 44 | 48 | pub fn inactiveUnionField(active: anytype, accessed: @TypeOf(active)) noreturn { |
| 49 | @branchHint(.cold); | |
| 45 | 50 | _ = accessed; |
| 46 | 51 | call("access of inactive union field", null); |
| 47 | 52 | } |
| 48 | 53 | |
| 49 | 54 | pub fn sliceCastLenRemainder(src_len: usize) noreturn { |
| 55 | @branchHint(.cold); | |
| 50 | 56 | _ = src_len; |
| 51 | 57 | call("slice length does not divide exactly into destination elements", null); |
| 52 | 58 | } |
| 53 | 59 | |
| 54 | 60 | pub fn reachedUnreachable() noreturn { |
| 61 | @branchHint(.cold); | |
| 55 | 62 | call("reached unreachable code", null); |
| 56 | 63 | } |
| 57 | 64 | |
| 58 | 65 | pub fn unwrapNull() noreturn { |
| 66 | @branchHint(.cold); | |
| 59 | 67 | call("attempt to use null value", null); |
| 60 | 68 | } |
| 61 | 69 | |
| 62 | 70 | pub fn castToNull() noreturn { |
| 71 | @branchHint(.cold); | |
| 63 | 72 | call("cast causes pointer to be null", null); |
| 64 | 73 | } |
| 65 | 74 | |
| 66 | 75 | pub fn incorrectAlignment() noreturn { |
| 76 | @branchHint(.cold); | |
| 67 | 77 | call("incorrect alignment", null); |
| 68 | 78 | } |
| 69 | 79 | |
| 70 | 80 | pub fn invalidErrorCode() noreturn { |
| 81 | @branchHint(.cold); | |
| 71 | 82 | call("invalid error code", null); |
| 72 | 83 | } |
| 73 | 84 | |
| 85 | pub fn unexpectedErrorCode(err: anyerror) noreturn { | |
| 86 | @branchHint(.cold); | |
| 87 | _ = err; | |
| 88 | call("unexpected error code", null); | |
| 89 | } | |
| 90 | ||
| 74 | 91 | pub fn integerOutOfBounds() noreturn { |
| 92 | @branchHint(.cold); | |
| 75 | 93 | call("integer does not fit in destination type", null); |
| 76 | 94 | } |
| 77 | 95 | |
| 78 | 96 | pub fn integerOverflow() noreturn { |
| 97 | @branchHint(.cold); | |
| 79 | 98 | call("integer overflow", null); |
| 80 | 99 | } |
| 81 | 100 | |
| 82 | 101 | pub fn shlOverflow() noreturn { |
| 102 | @branchHint(.cold); | |
| 83 | 103 | call("left shift overflowed bits", null); |
| 84 | 104 | } |
| 85 | 105 | |
| 86 | 106 | pub fn shrOverflow() noreturn { |
| 107 | @branchHint(.cold); | |
| 87 | 108 | call("right shift overflowed bits", null); |
| 88 | 109 | } |
| 89 | 110 | |
| 90 | 111 | pub fn divideByZero() noreturn { |
| 112 | @branchHint(.cold); | |
| 91 | 113 | call("division by zero", null); |
| 92 | 114 | } |
| 93 | 115 | |
| 94 | 116 | pub fn exactDivisionRemainder() noreturn { |
| 117 | @branchHint(.cold); | |
| 95 | 118 | call("exact division produced remainder", null); |
| 96 | 119 | } |
| 97 | 120 | |
| 98 | 121 | pub fn integerPartOutOfBounds() noreturn { |
| 122 | @branchHint(.cold); | |
| 99 | 123 | call("integer part of floating point value out of bounds", null); |
| 100 | 124 | } |
| 101 | 125 | |
| 102 | 126 | pub fn corruptSwitch() noreturn { |
| 127 | @branchHint(.cold); | |
| 103 | 128 | call("switch on corrupt value", null); |
| 104 | 129 | } |
| 105 | 130 | |
| 106 | 131 | pub fn shiftRhsTooBig() noreturn { |
| 132 | @branchHint(.cold); | |
| 107 | 133 | call("shift amount is greater than the type size", null); |
| 108 | 134 | } |
| 109 | 135 | |
| 110 | 136 | pub fn invalidEnumValue() noreturn { |
| 137 | @branchHint(.cold); | |
| 111 | 138 | call("invalid enum value", null); |
| 112 | 139 | } |
| 113 | 140 | |
| 114 | 141 | pub fn forLenMismatch() noreturn { |
| 142 | @branchHint(.cold); | |
| 115 | 143 | call("for loop over objects with non-equal lengths", null); |
| 116 | 144 | } |
| 117 | 145 | |
| 118 | 146 | pub fn copyLenMismatch() noreturn { |
| 147 | @branchHint(.cold); | |
| 119 | 148 | call("source and destination have non-equal lengths", null); |
| 120 | 149 | } |
| 121 | 150 | |
| 122 | 151 | pub fn memcpyAlias() noreturn { |
| 152 | @branchHint(.cold); | |
| 123 | 153 | call("@memcpy arguments alias", null); |
| 124 | 154 | } |
| 125 | 155 | |
| 126 | 156 | pub fn noreturnReturned() noreturn { |
| 157 | @branchHint(.cold); | |
| 127 | 158 | call("'noreturn' function returned", null); |
| 128 | 159 | } |
| 160 | ||
| 161 | pub 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 | 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 | 700 | try testing.expectEqual( |
| 701 | 701 | if (l.items.len > 0) l.items[0] else null, |
| 702 | 702 | q.front(), |
lib/std/dynamic_library.zig+17-17| ... | ... | @@ -103,7 +103,7 @@ pub fn get_DYNAMIC() ?[*]const elf.Dyn { |
| 103 | 103 | |
| 104 | 104 | pub fn linkmap_iterator() error{InvalidExe}!LinkMap.Iterator { |
| 105 | 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 | 107 | return .{ .current = null }; |
| 108 | 108 | }; |
| 109 | 109 | |
| ... | ... | @@ -261,10 +261,10 @@ pub const ElfDynLib = struct { |
| 261 | 261 | i += 1; |
| 262 | 262 | ph_addr += eh.e_phentsize; |
| 263 | 263 | }) { |
| 264 | const ph = @as(*elf.Phdr, @ptrFromInt(ph_addr)); | |
| 265 | switch (ph.p_type) { | |
| 266 | elf.PT_LOAD => virt_addr_end = @max(virt_addr_end, ph.p_vaddr + ph.p_memsz), | |
| 267 | elf.PT_DYNAMIC => maybe_dynv = @as([*]usize, @ptrFromInt(elf_addr + ph.p_offset)), | |
| 264 | const ph = @as(*elf.ElfN.Phdr, @ptrFromInt(ph_addr)); | |
| 265 | switch (ph.type) { | |
| 266 | .LOAD => virt_addr_end = @max(virt_addr_end, ph.vaddr + ph.memsz), | |
| 267 | .DYNAMIC => maybe_dynv = @as([*]usize, @ptrFromInt(elf_addr + ph.offset)), | |
| 268 | 268 | else => {}, |
| 269 | 269 | } |
| 270 | 270 | } |
| ... | ... | @@ -292,23 +292,23 @@ pub const ElfDynLib = struct { |
| 292 | 292 | i += 1; |
| 293 | 293 | ph_addr += eh.e_phentsize; |
| 294 | 294 | }) { |
| 295 | const ph = @as(*elf.Phdr, @ptrFromInt(ph_addr)); | |
| 296 | switch (ph.p_type) { | |
| 297 | elf.PT_LOAD => { | |
| 295 | const ph = @as(*elf.ElfN.Phdr, @ptrFromInt(ph_addr)); | |
| 296 | switch (ph.type) { | |
| 297 | .LOAD => { | |
| 298 | 298 | // The VirtAddr may not be page-aligned; in such case there will be |
| 299 | 299 | // extra nonsense mapped before/after the VirtAddr,MemSiz |
| 300 | const aligned_addr = (base + ph.p_vaddr) & ~(@as(usize, page_size) - 1); | |
| 301 | const extra_bytes = (base + ph.p_vaddr) - aligned_addr; | |
| 302 | const extended_memsz = mem.alignForward(usize, ph.p_memsz + extra_bytes, page_size); | |
| 300 | const aligned_addr = (base + ph.vaddr) & ~(@as(usize, page_size) - 1); | |
| 301 | const extra_bytes = (base + ph.vaddr) - aligned_addr; | |
| 302 | const extended_memsz = mem.alignForward(usize, ph.memsz + extra_bytes, page_size); | |
| 303 | 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 | 305 | _ = try posix.mmap( |
| 306 | 306 | ptr, |
| 307 | 307 | extended_memsz, |
| 308 | 308 | prot, |
| 309 | 309 | .{ .TYPE = .PRIVATE, .FIXED = true }, |
| 310 | 310 | file.handle, |
| 311 | ph.p_offset - extra_bytes, | |
| 311 | ph.offset - extra_bytes, | |
| 312 | 312 | ); |
| 313 | 313 | }, |
| 314 | 314 | else => {}, |
| ... | ... | @@ -517,11 +517,11 @@ pub const ElfDynLib = struct { |
| 517 | 517 | return null; |
| 518 | 518 | } |
| 519 | 519 | |
| 520 | fn elfToProt(elf_prot: u64) posix.PROT { | |
| 520 | fn elfToProt(elf_prot: elf.PF) posix.PROT { | |
| 521 | 521 | return .{ |
| 522 | .READ = (elf_prot & elf.PF_R) != 0, | |
| 523 | .WRITE = (elf_prot & elf.PF_W) != 0, | |
| 524 | .EXEC = (elf_prot & elf.PF_X) != 0, | |
| 522 | .READ = elf_prot.R, | |
| 523 | .WRITE = elf_prot.W, | |
| 524 | .EXEC = elf_prot.X, | |
| 525 | 525 | }; |
| 526 | 526 | } |
| 527 | 527 | }; |
lib/std/elf.zig+19-88| ... | ... | @@ -290,47 +290,6 @@ pub const VER_FLG_BASE = 1; |
| 290 | 290 | /// Weak version identifier |
| 291 | 291 | pub const VER_FLG_WEAK = 2; |
| 292 | 292 | |
| 293 | /// Deprecated, use `@intFromEnum(std.elf.PT.NULL)` | |
| 294 | pub const PT_NULL = @backingInt(std.elf.PT.NULL); | |
| 295 | /// Deprecated, use `@intFromEnum(std.elf.PT.LOAD)` | |
| 296 | pub const PT_LOAD = @backingInt(std.elf.PT.LOAD); | |
| 297 | /// Deprecated, use `@intFromEnum(std.elf.PT.DYNAMIC)` | |
| 298 | pub const PT_DYNAMIC = @backingInt(std.elf.PT.DYNAMIC); | |
| 299 | /// Deprecated, use `@intFromEnum(std.elf.PT.INTERP)` | |
| 300 | pub const PT_INTERP = @backingInt(std.elf.PT.INTERP); | |
| 301 | /// Deprecated, use `@intFromEnum(std.elf.PT.NOTE)` | |
| 302 | pub const PT_NOTE = @backingInt(std.elf.PT.NOTE); | |
| 303 | /// Deprecated, use `@intFromEnum(std.elf.PT.SHLIB)` | |
| 304 | pub const PT_SHLIB = @backingInt(std.elf.PT.SHLIB); | |
| 305 | /// Deprecated, use `@intFromEnum(std.elf.PT.PHDR)` | |
| 306 | pub const PT_PHDR = @backingInt(std.elf.PT.PHDR); | |
| 307 | /// Deprecated, use `@intFromEnum(std.elf.PT.TLS)` | |
| 308 | pub const PT_TLS = @backingInt(std.elf.PT.TLS); | |
| 309 | /// Deprecated, use `std.elf.PT.NUM`. | |
| 310 | pub const PT_NUM = PT.NUM; | |
| 311 | /// Deprecated, use `@intFromEnum(std.elf.PT.LOOS)` | |
| 312 | pub const PT_LOOS = @backingInt(std.elf.PT.LOOS); | |
| 313 | /// Deprecated, use `@intFromEnum(std.elf.PT.GNU_EH_FRAME)` | |
| 314 | pub const PT_GNU_EH_FRAME = @backingInt(std.elf.PT.GNU_EH_FRAME); | |
| 315 | /// Deprecated, use `@intFromEnum(std.elf.PT.GNU_STACK)` | |
| 316 | pub const PT_GNU_STACK = @backingInt(std.elf.PT.GNU_STACK); | |
| 317 | /// Deprecated, use `@intFromEnum(std.elf.PT.GNU_RELRO)` | |
| 318 | pub const PT_GNU_RELRO = @backingInt(std.elf.PT.GNU_RELRO); | |
| 319 | /// Deprecated, use `@intFromEnum(std.elf.PT.LOSUNW)` | |
| 320 | pub const PT_LOSUNW = @backingInt(std.elf.PT.LOSUNW); | |
| 321 | /// Deprecated, use `@intFromEnum(std.elf.PT.SUNWBSS)` | |
| 322 | pub const PT_SUNWBSS = @backingInt(std.elf.PT.SUNWBSS); | |
| 323 | /// Deprecated, use `@intFromEnum(std.elf.PT.SUNWSTACK)` | |
| 324 | pub const PT_SUNWSTACK = @backingInt(std.elf.PT.SUNWSTACK); | |
| 325 | /// Deprecated, use `@intFromEnum(std.elf.PT.HISUNW)` | |
| 326 | pub const PT_HISUNW = @backingInt(std.elf.PT.HISUNW); | |
| 327 | /// Deprecated, use `@intFromEnum(std.elf.PT.HIOS)` | |
| 328 | pub const PT_HIOS = @backingInt(std.elf.PT.HIOS); | |
| 329 | /// Deprecated, use `@intFromEnum(std.elf.PT.LOPROC)` | |
| 330 | pub const PT_LOPROC = @backingInt(std.elf.PT.LOPROC); | |
| 331 | /// Deprecated, use `@intFromEnum(std.elf.PT.HIPROC)` | |
| 332 | pub const PT_HIPROC = @backingInt(std.elf.PT.HIPROC); | |
| 333 | ||
| 334 | 293 | pub const PN_XNUM = 0xffff; |
| 335 | 294 | |
| 336 | 295 | /// Deprecated, use `@intFromEnum(std.elf.SHT.NULL)` |
| ... | ... | @@ -848,11 +807,11 @@ pub const ProgramHeaderIterator = struct { |
| 848 | 807 | file_reader: *Io.File.Reader, |
| 849 | 808 | index: usize = 0, |
| 850 | 809 | |
| 851 | pub fn next(it: *ProgramHeaderIterator) !?Elf64_Phdr { | |
| 810 | pub fn next(it: *ProgramHeaderIterator) !?Elf64.Phdr { | |
| 852 | 811 | if (it.index >= it.phnum) return null; |
| 853 | 812 | defer it.index += 1; |
| 854 | 813 | |
| 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 | 815 | const offset = it.phoff + size * it.index; |
| 857 | 816 | try it.file_reader.seekTo(offset); |
| 858 | 817 | |
| ... | ... | @@ -869,11 +828,11 @@ pub const ProgramHeaderBufferIterator = struct { |
| 869 | 828 | buf: []const u8, |
| 870 | 829 | index: usize = 0, |
| 871 | 830 | |
| 872 | pub fn next(it: *ProgramHeaderBufferIterator) !?Elf64_Phdr { | |
| 831 | pub fn next(it: *ProgramHeaderBufferIterator) !?Elf64.Phdr { | |
| 873 | 832 | if (it.index >= it.phnum) return null; |
| 874 | 833 | defer it.index += 1; |
| 875 | 834 | |
| 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 | 836 | const offset = @as(usize, @intCast(it.phoff)) + size * it.index; |
| 878 | 837 | var reader = Io.Reader.fixed(it.buf[offset..]); |
| 879 | 838 | |
| ... | ... | @@ -881,22 +840,22 @@ pub const ProgramHeaderBufferIterator = struct { |
| 881 | 840 | } |
| 882 | 841 | }; |
| 883 | 842 | |
| 884 | pub fn takeProgramHeader(reader: *Io.Reader, is_64: bool, endian: Endian) !Elf64_Phdr { | |
| 843 | pub fn takeProgramHeader(reader: *Io.Reader, is_64: bool, endian: Endian) !Elf64.Phdr { | |
| 885 | 844 | if (is_64) { |
| 886 | const phdr = try reader.takeStruct(Elf64_Phdr, endian); | |
| 845 | const phdr = try reader.takeStruct(Elf64.Phdr, endian); | |
| 887 | 846 | return phdr; |
| 888 | 847 | } |
| 889 | 848 | |
| 890 | const phdr = try reader.takeStruct(Elf32_Phdr, endian); | |
| 849 | const phdr = try reader.takeStruct(Elf32.Phdr, endian); | |
| 891 | 850 | return .{ |
| 892 | .p_type = phdr.p_type, | |
| 893 | .p_offset = phdr.p_offset, | |
| 894 | .p_vaddr = phdr.p_vaddr, | |
| 895 | .p_paddr = phdr.p_paddr, | |
| 896 | .p_filesz = phdr.p_filesz, | |
| 897 | .p_memsz = phdr.p_memsz, | |
| 898 | .p_flags = phdr.p_flags, | |
| 899 | .p_align = phdr.p_align, | |
| 851 | .type = phdr.type, | |
| 852 | .offset = phdr.offset, | |
| 853 | .vaddr = phdr.vaddr, | |
| 854 | .paddr = phdr.paddr, | |
| 855 | .filesz = phdr.filesz, | |
| 856 | .memsz = phdr.memsz, | |
| 857 | .flags = phdr.flags, | |
| 858 | .@"align" = phdr.@"align", | |
| 900 | 859 | }; |
| 901 | 860 | } |
| 902 | 861 | |
| ... | ... | @@ -1276,28 +1235,6 @@ pub const Elf64_Ehdr = extern struct { |
| 1276 | 1235 | e_shnum: Half, |
| 1277 | 1236 | e_shstrndx: Half, |
| 1278 | 1237 | }; |
| 1279 | /// Deprecated, use `std.elf.Elf32.Phdr` | |
| 1280 | pub 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` | |
| 1291 | pub 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 | 1238 | /// Deprecated, use `std.elf.Elf32.Shdr` |
| 1302 | 1239 | pub const Elf32_Shdr = extern struct { |
| 1303 | 1240 | sh_name: Word, |
| ... | ... | @@ -1568,12 +1505,6 @@ pub const Ehdr = switch (@sizeOf(usize)) { |
| 1568 | 1505 | 8 => Elf64_Ehdr, |
| 1569 | 1506 | else => @compileError("expected pointer size of 32 or 64"), |
| 1570 | 1507 | }; |
| 1571 | /// Deprecated, use `std.elf.ElfN.Phdr` | |
| 1572 | pub const Phdr = switch (@sizeOf(usize)) { | |
| 1573 | 4 => Elf32_Phdr, | |
| 1574 | 8 => Elf64_Phdr, | |
| 1575 | else => @compileError("expected pointer size of 32 or 64"), | |
| 1576 | }; | |
| 1577 | 1508 | pub const Dyn = switch (@sizeOf(usize)) { |
| 1578 | 1509 | 4 => Elf32_Dyn, |
| 1579 | 1510 | 8 => Elf64_Dyn, |
| ... | ... | @@ -3272,12 +3203,12 @@ pub const ar_hdr = extern struct { |
| 3272 | 3203 | ar_fmag: [2]u8, |
| 3273 | 3204 | |
| 3274 | 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 | 3207 | return std.fmt.parseInt(u64, value, 10); |
| 3277 | 3208 | } |
| 3278 | 3209 | |
| 3279 | 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 | 3212 | return std.fmt.parseInt(u32, value, 10); |
| 3282 | 3213 | } |
| 3283 | 3214 | |
| ... | ... | @@ -3311,7 +3242,7 @@ pub const ar_hdr = extern struct { |
| 3311 | 3242 | pub fn nameOffset(self: ar_hdr) std.fmt.ParseIntError!?u32 { |
| 3312 | 3243 | const value = &self.ar_name; |
| 3313 | 3244 | if (value[0] != '/') return null; |
| 3314 | const trimmed = mem.trimEnd(u8, value, &[_]u8{0x20}); | |
| 3245 | const trimmed = mem.trimEnd(u8, value, " "); | |
| 3315 | 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 | 3250 | fn genSpecialMemberName(comptime name: []const u8) *const [16]u8 { |
| 3320 | 3251 | assert(name.len <= 16); |
| 3321 | 3252 | const padding = 16 - name.len; |
| 3322 | return name ++ @as([padding]u8, @splat(0x20)); | |
| 3253 | return name ++ @as([padding]u8, @splat(' ')); | |
| 3323 | 3254 | } |
| 3324 | 3255 | |
| 3325 | 3256 | // 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 | 33 | pub fn EnumFieldStruct(comptime E: type, comptime Data: type, comptime field_default: ?Data) type { |
| 34 | 34 | @setEvalBranchQuota(@typeInfo(E).@"enum".field_names.len + eval_branch_quota_cushion); |
| 35 | 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 | } |
| 38 | 39 | |
| 39 | 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 | 455 | } |
| 455 | 456 | } |
| 456 | 457 | } else { |
| 457 | inline for (std.meta.fieldNames(E)) |field_name| { | |
| 458 | inline for (@typeInfo(E).@"enum".field_names) |field_name| { | |
| 458 | 459 | const key = @field(E, field_name); |
| 459 | 460 | if (@field(init_values, field_name)) |*v| { |
| 460 | 461 | const i = comptime Indexer.indexOf(key); |
lib/std/fmt.zig+2-4| ... | ... | @@ -261,7 +261,7 @@ test printInt { |
| 261 | 261 | |
| 262 | 262 | /// Converts values in the range [0, 100) to a base 10 string. |
| 263 | 263 | pub fn digits2(value: u8) [2]u8 { |
| 264 | if (builtin.mode == .ReleaseSmall) { | |
| 264 | if (builtin.mode == .small) { | |
| 265 | 265 | return .{ @intCast('0' + value / 10), @intCast('0' + value % 10) }; |
| 266 | 266 | } else { |
| 267 | 267 | return "00010203040506070809101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899"[value * 2 ..][0..2].*; |
| ... | ... | @@ -924,7 +924,7 @@ test "enum" { |
| 924 | 924 | |
| 925 | 925 | // test very large enum to verify ct branch quota is large enough |
| 926 | 926 | // 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 | 928 | try expectFmt("enum: .INVALID_FUNCTION\n", "enum: {}\n", .{std.os.windows.Win32Error.INVALID_FUNCTION}); |
| 929 | 929 | } |
| 930 | 930 | |
| ... | ... | @@ -1082,8 +1082,6 @@ test "float.libc.sanity" { |
| 1082 | 1082 | } |
| 1083 | 1083 | |
| 1084 | 1084 | test "union" { |
| 1085 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 1086 | ||
| 1087 | 1085 | const TU = union(enum) { |
| 1088 | 1086 | float: f32, |
| 1089 | 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 | 65 | |
| 66 | 66 | const DT = if (@bitSizeOf(T) <= 64) u64 else u128; |
| 67 | 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 | 69 | u128 => &Backend128_Tables, |
| 70 | 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 | 1830 | /// pointer address range of `path`, even if it is length zero. |
| 1831 | 1831 | pub fn extension(path: []const u8) []const u8 { |
| 1832 | 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 | 1834 | if (index == 0) return path[path.len..]; |
| 1835 | 1835 | return filename[index..]; |
| 1836 | 1836 | } |
| ... | ... | @@ -1887,8 +1887,8 @@ test extension { |
| 1887 | 1887 | /// - "hello/world/lib" ⇒ "lib" |
| 1888 | 1888 | pub fn stem(path: []const u8) []const u8 { |
| 1889 | 1889 | const filename = basename(path); |
| 1890 | const index = mem.lastIndexOfScalar(u8, filename, '.') orelse return filename[0..]; | |
| 1891 | if (index == 0) return path; | |
| 1890 | const index = mem.findScalarLast(u8, filename, '.') orelse return filename; | |
| 1891 | if (index == 0) return filename; | |
| 1892 | 1892 | return filename[0..index]; |
| 1893 | 1893 | } |
| 1894 | 1894 | |
| ... | ... | @@ -1904,8 +1904,14 @@ test stem { |
| 1904 | 1904 | try testStem("hello...", "hello.."); |
| 1905 | 1905 | try testStem("hello.", "hello"); |
| 1906 | 1906 | try testStem("/hello.", "hello"); |
| 1907 | try testStem("hello/world/.gitignore", ".gitignore"); | |
| 1908 | try testStem("/.gitignore", ".gitignore"); | |
| 1907 | 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 | 1913 | try testStem(".image.png", ".image"); |
| 1914 | try testStem(".image.png/", ".image"); | |
| 1909 | 1915 | try testStem("file.ext", "file"); |
| 1910 | 1916 | try testStem("file.ext.", "file.ext"); |
| 1911 | 1917 | try testStem("a.b.c", "a.b"); |
lib/std/fs/test.zig+41-3| ... | ... | @@ -758,6 +758,43 @@ test "readFileAlloc" { |
| 758 | 758 | ); |
| 759 | 759 | } |
| 760 | 760 | |
| 761 | test "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 | ||
| 761 | 798 | test "Dir.statFile" { |
| 762 | 799 | try testWithAllSupportedPathTypes(struct { |
| 763 | 800 | fn impl(ctx: *TestContext) !void { |
| ... | ... | @@ -902,6 +939,8 @@ test "createDirPathOpen parent dirs do not exist" { |
| 902 | 939 | } |
| 903 | 940 | |
| 904 | 941 | test "deleteDir" { |
| 942 | if (builtin.target.os.tag == .windows) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/35686 | |
| 943 | ||
| 905 | 944 | try testWithAllSupportedPathTypes(struct { |
| 906 | 945 | fn impl(ctx: *TestContext) !void { |
| 907 | 946 | const io = ctx.io; |
| ... | ... | @@ -2168,7 +2207,7 @@ test "'.' and '..' in absolute functions" { |
| 2168 | 2207 | } |
| 2169 | 2208 | |
| 2170 | 2209 | test "chmod" { |
| 2171 | if (native_os == .windows or native_os == .wasi) return; | |
| 2210 | if (native_os == .windows or native_os == .wasi) return error.SkipZigTest; | |
| 2172 | 2211 | |
| 2173 | 2212 | const io = testing.io; |
| 2174 | 2213 | |
| ... | ... | @@ -2191,8 +2230,7 @@ test "chmod" { |
| 2191 | 2230 | } |
| 2192 | 2231 | |
| 2193 | 2232 | test "change ownership" { |
| 2194 | if (native_os == .windows or native_os == .wasi) | |
| 2195 | return error.SkipZigTest; | |
| 2233 | if (native_os == .windows or native_os == .wasi) return error.SkipZigTest; | |
| 2196 | 2234 | |
| 2197 | 2235 | const io = testing.io; |
| 2198 | 2236 |
lib/std/hash/auto_hash.zig+1-1| ... | ... | @@ -225,7 +225,7 @@ fn testHashDeepRecursive(key: anytype) u64 { |
| 225 | 225 | |
| 226 | 226 | test "typeContainsSlice" { |
| 227 | 227 | comptime { |
| 228 | try testing.expect(!typeContainsSlice(std.meta.Tag(std.builtin.Type))); | |
| 228 | try testing.expect(!typeContainsSlice(std.meta.Tag(std.lang.Type))); | |
| 229 | 229 | |
| 230 | 230 | try testing.expect(typeContainsSlice([]const u8)); |
| 231 | 231 | try testing.expect(!typeContainsSlice(u8)); |
lib/std/hash/benchmark.zig+1-1| ... | ... | @@ -355,7 +355,7 @@ fn usage() void { |
| 355 | 355 | } |
| 356 | 356 | |
| 357 | 357 | fn 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 | } |
| 360 | 360 | |
| 361 | 361 | pub 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 | 16 | pub const CityHash32 = struct { |
| 17 | 17 | const Self = @This(); |
| 18 | 18 | |
| 19 | // Magic numbers for 32-bit hashing. Copied from Murmur3. | |
| 19 | // Magic numbers for 32-bit hashing. Copied from Murmur3. | |
| 20 | 20 | const c1: u32 = 0xcc9e2d51; |
| 21 | 21 | const c2: u32 = 0x1b873593; |
| 22 | 22 |
lib/std/hash/xxhash.zig+1-5| ... | ... | @@ -1,5 +1,4 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | const builtin = @import("builtin"); | |
| 3 | 2 | const mem = std.mem; |
| 4 | 3 | const expectEqual = std.testing.expectEqual; |
| 5 | 4 | |
| ... | ... | @@ -761,7 +760,7 @@ pub const XxHash3 = struct { |
| 761 | 760 | var accumulator_copy = self.accumulator; |
| 762 | 761 | var last_block_copy: [block_bytes]u8 = undefined; |
| 763 | 762 | |
| 764 | // Digest the last block onthe Accumulator copy. | |
| 763 | // Digest the last block on the Accumulator copy. | |
| 765 | 764 | return accumulator_copy.digest(self.total_len, last_block: { |
| 766 | 765 | if (self.buffered >= block_bytes) { |
| 767 | 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 | 787 | } |
| 789 | 788 | |
| 790 | 789 | test "xxhash3" { |
| 791 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 792 | 790 | const H = XxHash3; |
| 793 | 791 | // Non-Seeded Tests |
| 794 | 792 | try testExpect(H, 0, "", 0x2d06800538d394c2); |
| ... | ... | @@ -820,7 +818,6 @@ test "xxhash3" { |
| 820 | 818 | } |
| 821 | 819 | |
| 822 | 820 | test "xxhash3 smhasher" { |
| 823 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 824 | 821 | const Test = struct { |
| 825 | 822 | fn do() !void { |
| 826 | 823 | try expectEqual(verify.smhasher(XxHash3.hash), 0x9a636405); |
| ... | ... | @@ -832,7 +829,6 @@ test "xxhash3 smhasher" { |
| 832 | 829 | } |
| 833 | 830 | |
| 834 | 831 | test "xxhash3 iterative api" { |
| 835 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 836 | 832 | const Test = struct { |
| 837 | 833 | fn do() !void { |
| 838 | 834 | try verify.iterativeApi(XxHash3); |
lib/std/hash_map.zig+1-1| ... | ... | @@ -1518,7 +1518,7 @@ fn Custom( |
| 1518 | 1518 | self.available = 0; |
| 1519 | 1519 | } |
| 1520 | 1520 | |
| 1521 | /// This function is used in the debugger pretty formatters in tools/ to fetch the | |
| 1521 | /// This function is used in the debugger pretty formatters in lib/lldb/ to fetch the | |
| 1522 | 1522 | /// header type to facilitate fancy debug printing for this type. |
| 1523 | 1523 | fn dbHelper(self: *Self, hdr: *Header, entry: *Entry) void { |
| 1524 | 1524 | _ = self; |
lib/std/heap/PageAllocator.zig+1| ... | ... | @@ -24,6 +24,7 @@ pub const vtable: Allocator.VTable = .{ |
| 24 | 24 | /// that don't provide a hint (for security reasons, but it serves our needs |
| 25 | 25 | /// too). |
| 26 | 26 | const enable_hints = switch (builtin.target.os.tag) { |
| 27 | .linux => !builtin.target.cpu.arch.isSPARC(), // https://bugzilla.kernel.org/show_bug.cgi?id=221820 | |
| 27 | 28 | .openbsd => false, |
| 28 | 29 | else => true, |
| 29 | 30 | }; |
lib/std/heap/SafeAllocator.zig+2-2| ... | ... | @@ -39,7 +39,7 @@ const SafeAllocator = @This(); |
| 39 | 39 | const scoped_log = std.log.scoped(.SafeAllocator); |
| 40 | 40 | |
| 41 | 41 | pub const Options = struct { |
| 42 | const is_debug = @import("builtin").mode == .Debug; | |
| 42 | const is_debug = @import("builtin").mode == .debug; | |
| 43 | 43 | const page_size_log2 = @max(math.log2_int(usize, std.heap.page_size_max), 8); |
| 44 | 44 | |
| 45 | 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 | 1519 | @disableInstrumentation(); |
| 1520 | 1520 | |
| 1521 | 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 | 1523 | "invalid SafeAllocator free of {f}", |
| 1524 | 1524 | .{FormatMemory{ .memory = memory, .alignment = alignment }}, |
| 1525 | 1525 | ); |
lib/std/http.zig+8-5| ... | ... | @@ -20,6 +20,8 @@ pub const Version = enum { |
| 20 | 20 | /// https://datatracker.ietf.org/doc/html/rfc7231#section-4 Initial definition |
| 21 | 21 | /// |
| 22 | 22 | /// https://datatracker.ietf.org/doc/html/rfc5789#section-2 PATCH |
| 23 | /// | |
| 24 | /// https://datatracker.ietf.org/doc/html/rfc10008#name-query-method QUERY | |
| 23 | 25 | pub const Method = enum { |
| 24 | 26 | GET, |
| 25 | 27 | HEAD, |
| ... | ... | @@ -30,12 +32,13 @@ pub const Method = enum { |
| 30 | 32 | OPTIONS, |
| 31 | 33 | TRACE, |
| 32 | 34 | PATCH, |
| 35 | QUERY, | |
| 33 | 36 | |
| 34 | 37 | /// Returns true if a request of this method is allowed to have a body |
| 35 | 38 | /// Actual behavior from servers may vary and should still be checked |
| 36 | 39 | pub fn requestHasBody(m: Method) bool { |
| 37 | 40 | return switch (m) { |
| 38 | .POST, .PUT, .PATCH => true, | |
| 41 | .POST, .PUT, .PATCH, .QUERY => true, | |
| 39 | 42 | .GET, .HEAD, .DELETE, .CONNECT, .OPTIONS, .TRACE => false, |
| 40 | 43 | }; |
| 41 | 44 | } |
| ... | ... | @@ -44,7 +47,7 @@ pub const Method = enum { |
| 44 | 47 | /// Actual behavior from clients may vary and should still be checked |
| 45 | 48 | pub fn responseHasBody(m: Method) bool { |
| 46 | 49 | return switch (m) { |
| 47 | .GET, .POST, .PUT, .DELETE, .CONNECT, .OPTIONS, .PATCH => true, | |
| 50 | .GET, .POST, .PUT, .DELETE, .CONNECT, .OPTIONS, .PATCH, .QUERY => true, | |
| 48 | 51 | .HEAD, .TRACE => false, |
| 49 | 52 | }; |
| 50 | 53 | } |
| ... | ... | @@ -56,7 +59,7 @@ pub const Method = enum { |
| 56 | 59 | /// https://datatracker.ietf.org/doc/html/rfc7231#section-4.2.1 |
| 57 | 60 | pub fn safe(m: Method) bool { |
| 58 | 61 | return switch (m) { |
| 59 | .GET, .HEAD, .OPTIONS, .TRACE => true, | |
| 62 | .GET, .HEAD, .OPTIONS, .TRACE, .QUERY => true, | |
| 60 | 63 | .POST, .PUT, .DELETE, .CONNECT, .PATCH => false, |
| 61 | 64 | }; |
| 62 | 65 | } |
| ... | ... | @@ -70,7 +73,7 @@ pub const Method = enum { |
| 70 | 73 | /// https://datatracker.ietf.org/doc/html/rfc7231#section-4.2.2 |
| 71 | 74 | pub fn idempotent(m: Method) bool { |
| 72 | 75 | return switch (m) { |
| 73 | .GET, .HEAD, .PUT, .DELETE, .OPTIONS, .TRACE => true, | |
| 76 | .GET, .HEAD, .PUT, .DELETE, .OPTIONS, .TRACE, .QUERY => true, | |
| 74 | 77 | .CONNECT, .POST, .PATCH => false, |
| 75 | 78 | }; |
| 76 | 79 | } |
| ... | ... | @@ -83,7 +86,7 @@ pub const Method = enum { |
| 83 | 86 | /// https://datatracker.ietf.org/doc/html/rfc7231#section-4.2.3 |
| 84 | 87 | pub fn cacheable(m: Method) bool { |
| 85 | 88 | return switch (m) { |
| 86 | .GET, .HEAD => true, | |
| 89 | .GET, .HEAD, .QUERY => true, | |
| 87 | 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 | 102 | const method = std.meta.stringToEnum(http.Method, first_line[0..method_end]) orelse |
| 103 | 103 | return error.UnknownHttpMethod; |
| 104 | 104 | |
| 105 | const version_start = mem.lastIndexOfScalar(u8, first_line, ' ') orelse | |
| 105 | const version_start = mem.findScalarLast(u8, first_line, ' ') orelse | |
| 106 | 106 | return error.HttpHeadersInvalid; |
| 107 | 107 | if (version_start == method_end) return error.HttpHeadersInvalid; |
| 108 | 108 |
lib/std/http/test.zig+1-20| ... | ... | @@ -1,5 +1,4 @@ |
| 1 | 1 | const builtin = @import("builtin"); |
| 2 | const native_endian = builtin.cpu.arch.endian(); | |
| 3 | 2 | |
| 4 | 3 | const std = @import("std"); |
| 5 | 4 | const http = std.http; |
| ... | ... | @@ -34,7 +33,6 @@ test "content length reader state update" { |
| 34 | 33 | } |
| 35 | 34 | |
| 36 | 35 | test "trailers" { |
| 37 | if (builtin.cpu.arch.isPowerPC64() and builtin.mode != .Debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/194257 | |
| 38 | 36 | if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806 |
| 39 | 37 | |
| 40 | 38 | const io = std.testing.io; |
| ... | ... | @@ -121,7 +119,6 @@ test "trailers" { |
| 121 | 119 | } |
| 122 | 120 | |
| 123 | 121 | test "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 | 122 | if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806 |
| 126 | 123 | |
| 127 | 124 | const io = std.testing.io; |
| ... | ... | @@ -190,7 +187,6 @@ test "HTTP server handles a chunked transfer coding request" { |
| 190 | 187 | } |
| 191 | 188 | |
| 192 | 189 | test "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 | 190 | if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806 |
| 195 | 191 | |
| 196 | 192 | const io = std.testing.io; |
| ... | ... | @@ -281,12 +277,11 @@ test "echo content server" { |
| 281 | 277 | } |
| 282 | 278 | |
| 283 | 279 | test "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 | 280 | if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806 |
| 286 | 281 | |
| 287 | 282 | const io = std.testing.io; |
| 288 | 283 | |
| 289 | if (builtin.os.tag == .windows) { | |
| 284 | if (builtin.cpu.arch == .aarch64 and builtin.os.tag == .windows) { | |
| 290 | 285 | // https://github.com/ziglang/zig/issues/21457 |
| 291 | 286 | return error.SkipZigTest; |
| 292 | 287 | } |
| ... | ... | @@ -360,7 +355,6 @@ test "Server.Request.respondStreaming non-chunked, unknown content-length" { |
| 360 | 355 | } |
| 361 | 356 | |
| 362 | 357 | test "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 | 358 | if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806 |
| 365 | 359 | |
| 366 | 360 | const io = std.testing.io; |
| ... | ... | @@ -426,16 +420,10 @@ test "receiving arbitrary http headers from the client" { |
| 426 | 420 | } |
| 427 | 421 | |
| 428 | 422 | test "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 | 423 | if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806 |
| 431 | 424 | |
| 432 | 425 | const io = std.testing.io; |
| 433 | 426 | |
| 434 | if (builtin.os.tag == .windows) { | |
| 435 | // This test was never passing on Windows. | |
| 436 | return error.SkipZigTest; | |
| 437 | } | |
| 438 | ||
| 439 | 427 | const test_server = try createTestServer(io, struct { |
| 440 | 428 | fn run(test_server: *TestServer) anyerror!void { |
| 441 | 429 | const net_server = &test_server.net_server; |
| ... | ... | @@ -922,7 +910,6 @@ test "general client/server API coverage" { |
| 922 | 910 | } |
| 923 | 911 | |
| 924 | 912 | test "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 | 913 | if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806 |
| 927 | 914 | |
| 928 | 915 | const io = std.testing.io; |
| ... | ... | @@ -1162,10 +1149,6 @@ const TestServer = struct { |
| 1162 | 1149 | |
| 1163 | 1150 | fn createTestServer(io: Io, S: type) !*TestServer { |
| 1164 | 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 | } | |
| 1169 | 1152 | |
| 1170 | 1153 | const address = try net.IpAddress.parse("127.0.0.1", 0); |
| 1171 | 1154 | |
| ... | ... | @@ -1192,7 +1175,6 @@ fn createTestServer(io: Io, S: type) !*TestServer { |
| 1192 | 1175 | } |
| 1193 | 1176 | |
| 1194 | 1177 | test "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 | 1178 | if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806 |
| 1197 | 1179 | |
| 1198 | 1180 | const io = std.testing.io; |
| ... | ... | @@ -1280,7 +1262,6 @@ test "redirect to different connection" { |
| 1280 | 1262 | } |
| 1281 | 1263 | |
| 1282 | 1264 | test "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 | 1265 | if (builtin.os.tag == .openbsd) return error.SkipZigTest; // https://codeberg.org/ziglang/zig/issues/30806 |
| 1285 | 1266 | |
| 1286 | 1267 | const io = std.testing.io; |
lib/std/json/Stringify.zig+3-3| ... | ... | @@ -54,8 +54,8 @@ else |
| 54 | 54 | void = if (build_mode_has_safety) .none else {}, |
| 55 | 55 | |
| 56 | 56 | const build_mode_has_safety = switch (@import("builtin").mode) { |
| 57 | .Debug, .ReleaseSafe => true, | |
| 58 | .ReleaseFast, .ReleaseSmall => false, | |
| 57 | .debug, .safe => true, | |
| 58 | .fast, .small => false, | |
| 59 | 59 | }; |
| 60 | 60 | |
| 61 | 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 | 66 | /// If `.checked_to_fixed_depth` is used, there is additionally an assertion that the nesting depth never exceeds the given limit. |
| 67 | 67 | /// `.checked_to_fixed_depth` embeds the storage required in the `Stringify` struct. |
| 68 | 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`. | |
| 70 | 70 | const safety_checks_hint: union(enum) { |
| 71 | 71 | /// Rounded up to the nearest multiple of 8. |
| 72 | 72 | checked_to_fixed_depth: usize, |
lib/std/lang.zig+47-5| ... | ... | @@ -107,13 +107,52 @@ pub const CodeModel = enum(u4) { |
| 107 | 107 | tiny, |
| 108 | 108 | }; |
| 109 | 109 | |
| 110 | /// Deprecated, to be removed after 0.18.0 | |
| 111 | pub const OptimizeMode = Optimize; | |
| 112 | ||
| 110 | 113 | /// This data structure is used by the Zig language code generation and |
| 111 | 114 | /// therefore must be kept in sync with the compiler implementation. |
| 112 | pub const OptimizeMode = enum { | |
| 113 | Debug, | |
| 114 | ReleaseSafe, | |
| 115 | ReleaseFast, | |
| 116 | ReleaseSmall, | |
| 115 | pub const Optimize = enum { | |
| 116 | /// Safety checks enabled. Optimize for bug detection, accurate debug info, | |
| 117 | /// and compilation speed (in that order). | |
| 118 | debug, | |
| 119 | /// Safety checks enabled. Optimize for runtime performance. | |
| 120 | safe, | |
| 121 | /// Safety checks disabled. Optimize for runtime performance. | |
| 122 | fast, | |
| 123 | /// Safety checks disabled. Optimize for machine code size, then runtime performance. | |
| 124 | small, | |
| 125 | ||
| 126 | /// Deprecated, to be removed after 0.18.0 | |
| 127 | pub const Debug: @This() = .debug; | |
| 128 | /// Deprecated, to be removed after 0.18.0 | |
| 129 | pub const ReleaseSafe: @This() = .safe; | |
| 130 | /// Deprecated, to be removed after 0.18.0 | |
| 131 | pub const ReleaseFast: @This() = .fast; | |
| 132 | /// Deprecated, to be removed after 0.18.0 | |
| 133 | pub const ReleaseSmall: @This() = .small; | |
| 134 | /// Deprecated, to be removed after 0.18.0 | |
| 135 | pub fn fromString(s: []const u8) ?@This() { | |
| 136 | return std.StaticStringMap(@This()).initComptime(&.{ | |
| 137 | .{ "Debug", .debug }, | |
| 138 | .{ "ReleaseSafe", .safe }, | |
| 139 | .{ "ReleaseFast", .fast }, | |
| 140 | .{ "ReleaseSmall", .small }, | |
| 141 | .{ "debug", .debug }, | |
| 142 | .{ "safe", .safe }, | |
| 143 | .{ "fast", .fast }, | |
| 144 | .{ "small", .small }, | |
| 145 | }).get(s); | |
| 146 | } | |
| 147 | ||
| 148 | /// Returns whether illegal behavior safety checks are enabled based on the | |
| 149 | /// provided optimization mode. | |
| 150 | pub fn runtimeSafety(o: @This()) bool { | |
| 151 | return switch (o) { | |
| 152 | .debug, .safe => true, | |
| 153 | .fast, .small => false, | |
| 154 | }; | |
| 155 | } | |
| 117 | 156 | }; |
| 118 | 157 | |
| 119 | 158 | /// 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 | 210 | x86_64_regcall_v4_win: CommonOptions, |
| 172 | 211 | x86_64_vectorcall: CommonOptions, |
| 173 | 212 | x86_64_interrupt: CommonOptions, |
| 213 | x86_64_preserve_none: CommonOptions, | |
| 174 | 214 | |
| 175 | 215 | // Calling conventions for the `x86` architecture. |
| 176 | 216 | x86_sysv: X86RegparmOptions, |
| 177 | 217 | x86_win: X86RegparmOptions, |
| 218 | x86_mingw: X86RegparmOptions, | |
| 178 | 219 | x86_stdcall: X86RegparmOptions, |
| 179 | 220 | x86_fastcall: CommonOptions, |
| 180 | 221 | x86_thiscall: CommonOptions, |
| ... | ... | @@ -197,6 +238,7 @@ pub const CallingConvention = union(enum(u8)) { |
| 197 | 238 | aarch64_aapcs_win: CommonOptions, |
| 198 | 239 | aarch64_vfabi: CommonOptions, |
| 199 | 240 | aarch64_vfabi_sve: CommonOptions, |
| 241 | aarch64_preserve_none: CommonOptions, | |
| 200 | 242 | |
| 201 | 243 | /// The standard `alpha` calling convention. |
| 202 | 244 | alpha_osf: CommonOptions, |
lib/std/log.zig+1-1| ... | ... | @@ -53,7 +53,7 @@ pub const Level = enum { |
| 53 | 53 | /// The default log level is based on build mode. |
| 54 | 54 | pub const default_level: Level = switch (builtin.mode) { |
| 55 | 55 | .Debug => .debug, |
| 56 | .ReleaseSafe, .ReleaseFast, .ReleaseSmall => .info, | |
| 56 | .safe, .fast, .small => .info, | |
| 57 | 57 | }; |
| 58 | 58 | |
| 59 | 59 | pub const ScopeLevel = struct { |
lib/std/macho.zig+19| ... | ... | @@ -588,6 +588,25 @@ pub const rpath_command = extern struct { |
| 588 | 588 | path: u32, |
| 589 | 589 | }; |
| 590 | 590 | |
| 591 | pub 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 | ||
| 600 | pub 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 | 610 | /// The segment load command indicates that a part of this file is to be |
| 592 | 611 | /// mapped into the task's address space. The size of this segment in memory, |
| 593 | 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 | 75 | /// |
| 76 | 76 | /// NaN values are never considered equal to any value. |
| 77 | 77 | pub 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 | 79 | assert(tolerance >= 0); |
| 80 | 80 | |
| 81 | 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 | 103 | /// |
| 104 | 104 | /// NaN values are never considered equal to any value. |
| 105 | 105 | pub 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 | 107 | assert(tolerance > 0); |
| 108 | 108 | |
| 109 | 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 | 461 | } |
| 462 | 462 | } |
| 463 | 463 | test 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 | 465 | // https://codeberg.org/ziglang/zig/issues/35520 |
| 466 | 466 | return error.SkipZigTest; |
| 467 | 467 | } |
| ... | ... | @@ -1385,7 +1385,8 @@ pub fn lerp(a: anytype, b: anytype, t: anytype) @TypeOf(a, b, t) { |
| 1385 | 1385 | } |
| 1386 | 1386 | |
| 1387 | 1387 | test lerp { |
| 1388 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/17884 | |
| 1388 | if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isArm()) return error.SkipZigTest; | |
| 1389 | if (builtin.zig_backend == .stage2_c and builtin.cpu.arch.isX86()) return error.SkipZigTest; | |
| 1389 | 1390 | if (builtin.zig_backend == .stage2_x86_64 and !comptime builtin.cpu.has(.x86, .fma)) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/17884 |
| 1390 | 1391 | |
| 1391 | 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 | 337 | } |
| 338 | 338 | |
| 339 | 339 | test "acosBinary16.special" { |
| 340 | if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest; | |
| 341 | ||
| 342 | 340 | try testing.expectApproxEqAbs(0x1.92p0, acosBinary16(0x0p+0), math.floatEpsAt(f16, 0x1.92p0)); |
| 343 | 341 | try testing.expectApproxEqAbs(0x1.92p1, acosBinary16(-0x1p+0), math.floatEpsAt(f16, 0x1.92p1)); |
| 344 | 342 | try testing.expectEqual(0x0p+0, acosBinary16(0x1p+0)); |
| ... | ... | @@ -350,8 +348,6 @@ test "acosBinary16.special" { |
| 350 | 348 | } |
| 351 | 349 | |
| 352 | 350 | test "acosBinary16" { |
| 353 | if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest; | |
| 354 | ||
| 355 | 351 | try testing.expectApproxEqAbs(0x1.834p0, acosBinary16(0x1.db4p-5), math.floatEpsAt(f16, 0x1.834p0)); |
| 356 | 352 | try testing.expectApproxEqAbs(0x1.d48p0, acosBinary16(-0x1.068p-2), math.floatEpsAt(f16, 0x1.d48p0)); |
| 357 | 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 | 326 | } |
| 327 | 327 | |
| 328 | 328 | test "asinBinary16.special" { |
| 329 | if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest; | |
| 330 | ||
| 331 | 329 | try testing.expectApproxEqAbs(0x1.92p0, asinBinary16(0x1p+0), math.floatEpsAt(f16, 0x1.92p0)); |
| 332 | 330 | try testing.expectApproxEqAbs(-0x1.92p0, asinBinary16(-0x1p+0), math.floatEpsAt(f16, -0x1.92p0)); |
| 333 | 331 | try testing.expectEqual(0x0p+0, asinBinary16(0x0p+0)); |
| ... | ... | @@ -340,8 +338,6 @@ test "asinBinary16.special" { |
| 340 | 338 | } |
| 341 | 339 | |
| 342 | 340 | test "asinBinary16" { |
| 343 | if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest; | |
| 344 | ||
| 345 | 341 | try testing.expectApproxEqAbs(-0x1.e4cp-6, asinBinary16(-0x1.e4cp-6), math.floatEpsAt(f16, -0x1.e4cp-6)); |
| 346 | 342 | try testing.expectApproxEqAbs(0x1.2a8p0, asinBinary16(0x1.d68p-1), math.floatEpsAt(f16, 0x1.2a8p0)); |
| 347 | 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 | 481 | } |
| 482 | 482 | |
| 483 | 483 | test "atanBinary16.special" { |
| 484 | if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest; | |
| 485 | ||
| 486 | 484 | try testing.expectEqual(0x0p+0, atanBinary16(0x0p+0)); |
| 487 | 485 | try testing.expectEqual(-0x0p+0, atanBinary16(-0x0p+0)); |
| 488 | 486 | try testing.expectApproxEqAbs(0x1.92p-1, atanBinary16(0x1p+0), math.floatEpsAt(f16, 0x1.92p-1)); |
| ... | ... | @@ -493,8 +491,6 @@ test "atanBinary16.special" { |
| 493 | 491 | } |
| 494 | 492 | |
| 495 | 493 | test "atanBinary16" { |
| 496 | if (builtin.target.cpu.arch == .x86_64 and builtin.target.os.tag == .macos) return error.SkipZigTest; | |
| 497 | ||
| 498 | 494 | try testing.expectApproxEqAbs(-0x1.74cp-2, atanBinary16(-0x1.864p-2), math.floatEpsAt(f16, -0x1.74cp-2)); |
| 499 | 495 | try testing.expectApproxEqAbs(-0x1.374p0, atanBinary16(-0x1.59cp1), math.floatEpsAt(f16, -0x1.374p0)); |
| 500 | 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 | 252 | |
| 253 | 253 | try expect(math.isNan(atan2_32(1.0, math.nan(f32)))); |
| 254 | 254 | try expect(math.isNan(atan2_32(math.nan(f32), 1.0))); |
| 255 | try expect(atan2_32(0.0, 5.0) == 0.0); | |
| 256 | try expect(atan2_32(-0.0, 5.0) == -0.0); | |
| 255 | try expect(math.isPositiveZero(atan2_32(0.0, 5.0))); | |
| 256 | try expect(math.isNegativeZero(atan2_32(-0.0, 5.0))); | |
| 257 | 257 | try expect(math.approxEqAbs(f32, atan2_32(0.0, -5.0), math.pi, epsilon)); |
| 258 | 258 | //expect(math.approxEqAbs(f32, atan2_32(-0.0, -5.0), -math.pi, .{.rel=0,.abs=epsilon})); TODO support negative zero? |
| 259 | 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 | 276 | |
| 277 | 277 | try expect(math.isNan(atan2_64(1.0, math.nan(f64)))); |
| 278 | 278 | try expect(math.isNan(atan2_64(math.nan(f64), 1.0))); |
| 279 | try expect(atan2_64(0.0, 5.0) == 0.0); | |
| 280 | try expect(atan2_64(-0.0, 5.0) == -0.0); | |
| 279 | try expect(math.isPositiveZero(atan2_64(0.0, 5.0))); | |
| 280 | try expect(math.isNegativeZero(atan2_64(-0.0, 5.0))); | |
| 281 | 281 | try expect(math.approxEqAbs(f64, atan2_64(0.0, -5.0), math.pi, epsilon)); |
| 282 | 282 | //expect(math.approxEqAbs(f64, atan2_64(-0.0, -5.0), -math.pi, .{.rel=0,.abs=epsilon})); TODO support negative zero? |
| 283 | 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 | 1 | const std = @import("../../std.zig"); |
| 2 | const builtin = @import("builtin"); | |
| 3 | 2 | const mem = std.mem; |
| 4 | 3 | const testing = std.testing; |
| 5 | 4 | const Managed = std.math.big.int.Managed; |
| ... | ... | @@ -276,8 +275,6 @@ fn setFloat(comptime Float: type) !void { |
| 276 | 275 | try expectNormalized(1 << 10, res.toConst()); |
| 277 | 276 | } |
| 278 | 277 | test setFloat { |
| 279 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 280 | ||
| 281 | 278 | try setFloat(f16); |
| 282 | 279 | try setFloat(f32); |
| 283 | 280 | try setFloat(f64); |
| ... | ... | @@ -484,7 +481,6 @@ fn toFloat(comptime Float: type) !void { |
| 484 | 481 | ); |
| 485 | 482 | } |
| 486 | 483 | test toFloat { |
| 487 | if (builtin.cpu.arch == .x86) return error.SkipZigTest; | |
| 488 | 484 | try toFloat(f16); |
| 489 | 485 | try toFloat(f32); |
| 490 | 486 | try toFloat(f64); |
| ... | ... | @@ -1391,8 +1387,6 @@ test "mul multi-single" { |
| 1391 | 1387 | } |
| 1392 | 1388 | |
| 1393 | 1389 | test "mul multi-multi" { |
| 1394 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 1395 | ||
| 1396 | 1390 | var op1: u256 = 0x998888efefefefefefefef; |
| 1397 | 1391 | var op2: u256 = 0x333000abababababababab; |
| 1398 | 1392 | _ = .{ &op1, &op2 }; |
| ... | ... | @@ -1514,8 +1508,6 @@ test "mulWrap single-single signed" { |
| 1514 | 1508 | } |
| 1515 | 1509 | |
| 1516 | 1510 | test "mulWrap multi-multi unsigned" { |
| 1517 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 1518 | ||
| 1519 | 1511 | var op1: u256 = 0x998888efefefefefefefef; |
| 1520 | 1512 | var op2: u256 = 0x333000abababababababab; |
| 1521 | 1513 | _ = .{ &op1, &op2 }; |
| ... | ... | @@ -1533,11 +1525,6 @@ test "mulWrap multi-multi unsigned" { |
| 1533 | 1525 | } |
| 1534 | 1526 | |
| 1535 | 1527 | test "mulWrap multi-multi signed" { |
| 1536 | switch (builtin.zig_backend) { | |
| 1537 | .stage2_c => return error.SkipZigTest, | |
| 1538 | else => {}, | |
| 1539 | } | |
| 1540 | ||
| 1541 | 1528 | var a = try Managed.initSet(testing.allocator, maxInt(SignedDoubleLimb) - 1); |
| 1542 | 1529 | defer a.deinit(); |
| 1543 | 1530 | var b = try Managed.initSet(testing.allocator, maxInt(SignedDoubleLimb)); |
| ... | ... | @@ -1744,8 +1731,6 @@ test "div q=0 alias" { |
| 1744 | 1731 | } |
| 1745 | 1732 | |
| 1746 | 1733 | test "div multi-multi q < r" { |
| 1747 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 1748 | ||
| 1749 | 1734 | const op1 = 0x1ffffffff0078f432; |
| 1750 | 1735 | const op2 = 0x1ffffffff01000000; |
| 1751 | 1736 | var a = try Managed.initSet(testing.allocator, op1); |
| ... | ... | @@ -2166,8 +2151,6 @@ test "div ceil multi-limb" { |
| 2166 | 2151 | } |
| 2167 | 2152 | |
| 2168 | 2153 | test "div multi-multi with rem" { |
| 2169 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 2170 | ||
| 2171 | 2154 | var a = try Managed.initSet(testing.allocator, 0x8888999911110000ffffeeeeddddccccbbbbaaaa9999); |
| 2172 | 2155 | defer a.deinit(); |
| 2173 | 2156 | var b = try Managed.initSet(testing.allocator, 0x99990000111122223333); |
| ... | ... | @@ -2184,8 +2167,6 @@ test "div multi-multi with rem" { |
| 2184 | 2167 | } |
| 2185 | 2168 | |
| 2186 | 2169 | test "div multi-multi no rem" { |
| 2187 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 2188 | ||
| 2189 | 2170 | var a = try Managed.initSet(testing.allocator, 0x8888999911110000ffffeeeedb4fec200ee3a4286361); |
| 2190 | 2171 | defer a.deinit(); |
| 2191 | 2172 | var b = try Managed.initSet(testing.allocator, 0x99990000111122223333); |
| ... | ... | @@ -2202,8 +2183,6 @@ test "div multi-multi no rem" { |
| 2202 | 2183 | } |
| 2203 | 2184 | |
| 2204 | 2185 | test "div multi-multi (2 branch)" { |
| 2205 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 2206 | ||
| 2207 | 2186 | var a = try Managed.initSet(testing.allocator, 0x866666665555555588888887777777761111111111111111); |
| 2208 | 2187 | defer a.deinit(); |
| 2209 | 2188 | var b = try Managed.initSet(testing.allocator, 0x86666666555555554444444433333333); |
| ... | ... | @@ -2220,8 +2199,6 @@ test "div multi-multi (2 branch)" { |
| 2220 | 2199 | } |
| 2221 | 2200 | |
| 2222 | 2201 | test "div multi-multi (3.1/3.3 branch)" { |
| 2223 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 2224 | ||
| 2225 | 2202 | var a = try Managed.initSet(testing.allocator, 0x11111111111111111111111111111111111111111111111111111111111111); |
| 2226 | 2203 | defer a.deinit(); |
| 2227 | 2204 | var b = try Managed.initSet(testing.allocator, 0x1111111111111111111111111111111111111111171); |
| ... | ... | @@ -2238,8 +2215,6 @@ test "div multi-multi (3.1/3.3 branch)" { |
| 2238 | 2215 | } |
| 2239 | 2216 | |
| 2240 | 2217 | test "div multi-single zero-limb trailing" { |
| 2241 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 2242 | ||
| 2243 | 2218 | var a = try Managed.initSet(testing.allocator, 0x60000000000000000000000000000000000000000000000000000000000000000); |
| 2244 | 2219 | defer a.deinit(); |
| 2245 | 2220 | var b = try Managed.initSet(testing.allocator, 0x10000000000000000); |
| ... | ... | @@ -2258,8 +2233,6 @@ test "div multi-single zero-limb trailing" { |
| 2258 | 2233 | } |
| 2259 | 2234 | |
| 2260 | 2235 | test "div multi-multi zero-limb trailing (with rem)" { |
| 2261 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 2262 | ||
| 2263 | 2236 | var a = try Managed.initSet(testing.allocator, 0x86666666555555558888888777777776111111111111111100000000000000000000000000000000); |
| 2264 | 2237 | defer a.deinit(); |
| 2265 | 2238 | var b = try Managed.initSet(testing.allocator, 0x8666666655555555444444443333333300000000000000000000000000000000); |
| ... | ... | @@ -2279,8 +2252,6 @@ test "div multi-multi zero-limb trailing (with rem)" { |
| 2279 | 2252 | } |
| 2280 | 2253 | |
| 2281 | 2254 | test "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 | 2255 | var a = try Managed.initSet(testing.allocator, 0x8666666655555555888888877777777611111111111111110000000000000000); |
| 2285 | 2256 | defer a.deinit(); |
| 2286 | 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 | 2271 | } |
| 2301 | 2272 | |
| 2302 | 2273 | test "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 | 2274 | var a = try Managed.initSet(testing.allocator, 0x86666666555555558888888777777776111111111111111100000000000000000000000000000000); |
| 2306 | 2275 | defer a.deinit(); |
| 2307 | 2276 | var b = try Managed.initSet(testing.allocator, 0x866666665555555544444444333333330000000000000000); |
| ... | ... | @@ -2832,10 +2801,6 @@ test "bitNotWrap signed multi" { |
| 2832 | 2801 | } |
| 2833 | 2802 | |
| 2834 | 2803 | test "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 | 2804 | var a = try Managed.initSet(testing.allocator, maxInt(Limb)); |
| 2840 | 2805 | defer a.deinit(); |
| 2841 | 2806 | |
| ... | ... | @@ -3179,8 +3144,6 @@ test "gcd non-one large" { |
| 3179 | 3144 | } |
| 3180 | 3145 | |
| 3181 | 3146 | test "gcd large multi-limb result" { |
| 3182 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 3183 | ||
| 3184 | 3147 | var a = try Managed.initSet(testing.allocator, 0x12345678123456781234567812345678123456781234567812345678); |
| 3185 | 3148 | defer a.deinit(); |
| 3186 | 3149 | var b = try Managed.initSet(testing.allocator, 0x12345671234567123456712345671234567123456712345671234567); |
| ... | ... | @@ -3431,7 +3394,7 @@ test "big int conversion read/write twos complement" { |
| 3431 | 3394 | var buffer1 = try testing.allocator.alloc(u8, 64); |
| 3432 | 3395 | defer testing.allocator.free(buffer1); |
| 3433 | 3396 | |
| 3434 | const endians = [_]std.builtin.Endian{ .little, .big }; | |
| 3397 | const endians = [_]std.lang.Endian{ .little, .big }; | |
| 3435 | 3398 | const abi_size = 64; |
| 3436 | 3399 | |
| 3437 | 3400 | for (endians) |endian| { |
lib/std/math/float.zig+3-3| ... | ... | @@ -112,17 +112,17 @@ pub fn FloatRepr(comptime Float: type) type { |
| 112 | 112 | /// This currently truncates denormal values, which needs to be fixed before this can be used to |
| 113 | 113 | /// produce a rounded value. |
| 114 | 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 | 116 | .mantissa = 0, |
| 117 | 117 | .exponent = .infinite, |
| 118 | 118 | .sign = sign, |
| 119 | 119 | }); |
| 120 | 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 | 122 | .mantissa = @truncate(std.math.shr( |
| 123 | 123 | Mantissa, |
| 124 | 124 | mantissa, |
| 125 | BiasedExponent.min_normal.unbias() - normalized.exponent, | |
| 125 | (comptime BiasedExponent.min_normal.unbias()) - normalized.exponent, | |
| 126 | 126 | )), |
| 127 | 127 | .exponent = .denormal, |
| 128 | 128 | .sign = sign, |
lib/std/math/gamma.zig-2| ... | ... | @@ -263,8 +263,6 @@ test gamma { |
| 263 | 263 | } |
| 264 | 264 | |
| 265 | 265 | test "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 | 266 | inline for (&.{ f32, f64 }) |T| { |
| 269 | 267 | try expect(std.math.isNan(gamma(T, -std.math.nan(T)))); |
| 270 | 268 | try expect(std.math.isNan(gamma(T, std.math.nan(T)))); |
lib/std/math/hypot.zig-9| ... | ... | @@ -1,4 +1,3 @@ |
| 1 | const builtin = @import("builtin"); | |
| 2 | 1 | const std = @import("../std.zig"); |
| 3 | 2 | const math = std.math; |
| 4 | 3 | const expect = std.testing.expect; |
| ... | ... | @@ -93,14 +92,10 @@ const hypot_test_cases = .{ |
| 93 | 92 | }; |
| 94 | 93 | |
| 95 | 94 | test hypot { |
| 96 | if (builtin.cpu.arch.isPowerPC() and builtin.mode != .Debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/171869 | |
| 97 | 95 | try expect(hypot(0.3, 0.4) == 0.5); |
| 98 | 96 | } |
| 99 | 97 | |
| 100 | 98 | test "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 | 99 | inline for (.{ f16, f32, f64, f128 }) |T| { |
| 105 | 100 | inline for (hypot_test_cases) |v| { |
| 106 | 101 | const a: T, const b: T, const c: T = v; |
| ... | ... | @@ -110,9 +105,6 @@ test "hypot.correct" { |
| 110 | 105 | } |
| 111 | 106 | |
| 112 | 107 | test "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 | 108 | inline for (.{ f16, f32, f64 }) |T| { // f128 seems to be 5 ulp |
| 117 | 109 | inline for (hypot_test_cases) |v| { |
| 118 | 110 | const a: T, const b: T, const c: T = v; |
| ... | ... | @@ -122,7 +114,6 @@ test "hypot.precise" { |
| 122 | 114 | } |
| 123 | 115 | |
| 124 | 116 | test "hypot.special" { |
| 125 | if (builtin.cpu.arch.isPowerPC() and builtin.mode != .Debug) return error.SkipZigTest; // https://github.com/llvm/llvm-project/issues/171869 | |
| 126 | 117 | @setEvalBranchQuota(2000); |
| 127 | 118 | inline for (.{ f16, f32, f64, f128 }) |T| { |
| 128 | 119 | try expect(math.isNan(hypot(nan(T), 0.0))); |
lib/std/math/isnan.zig+1-7| ... | ... | @@ -27,13 +27,6 @@ test isNan { |
| 27 | 27 | } |
| 28 | 28 | |
| 29 | 29 | test 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 | 30 | inline for ([_]type{ f16, f32, f64, f80, f128, c_longdouble }) |T| { |
| 38 | 31 | // TODO: Signalling NaN values get converted to quiet NaN values in |
| 39 | 32 | // some cases where they shouldn't such that this can fail. |
| ... | ... | @@ -43,6 +36,7 @@ test isSignalNan { |
| 43 | 36 | builtin.cpu.arch != .hexagon and |
| 44 | 37 | !builtin.cpu.arch.isMIPS32() and |
| 45 | 38 | !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 | 40 | builtin.zig_backend != .stage2_c) |
| 47 | 41 | { |
| 48 | 42 | try expect(isSignalNan(math.snan(T))); |
lib/std/math/log10.zig-5| ... | ... | @@ -1,5 +1,4 @@ |
| 1 | 1 | const std = @import("../std.zig"); |
| 2 | const builtin = @import("builtin"); | |
| 3 | 2 | const testing = std.testing; |
| 4 | 3 | |
| 5 | 4 | /// Returns the base-10 logarithm of x. |
| ... | ... | @@ -135,10 +134,6 @@ inline fn less_than_5(x: u32) u32 { |
| 135 | 134 | } |
| 136 | 135 | |
| 137 | 136 | test 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 | 137 | inline for ( |
| 143 | 138 | .{ u8, u16, u32, u64, u128, u256, u512 }, |
| 144 | 139 | .{ 2, 4, 9, 19, 38, 77, 154 }, |
lib/std/math/modf.zig-4| ... | ... | @@ -1,5 +1,4 @@ |
| 1 | 1 | const std = @import("../std.zig"); |
| 2 | const builtin = @import("builtin"); | |
| 3 | 2 | const math = std.math; |
| 4 | 3 | const expect = std.testing.expect; |
| 5 | 4 | const expectEqual = std.testing.expectEqual; |
| ... | ... | @@ -85,9 +84,6 @@ fn ModfTests(comptime T: type) type { |
| 85 | 84 | try expectApproxEqAbs(expected_c, r.fpart, epsilon); |
| 86 | 85 | } |
| 87 | 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 | 87 | const widths = [_]comptime_int{ 1, 2, 3, 4, 8, 16 }; |
| 92 | 88 | |
| 93 | 89 | inline for (widths) |len| { |
lib/std/math/signbit.zig+1| ... | ... | @@ -1,3 +1,4 @@ |
| 1 | const builtin = @import("builtin"); | |
| 1 | 2 | const std = @import("../std.zig"); |
| 2 | 3 | const math = std.math; |
| 3 | 4 | const expect = std.testing.expect; |
lib/std/mem.zig+166-127| ... | ... | @@ -9,6 +9,7 @@ const assert = debug.assert; |
| 9 | 9 | const math = std.math; |
| 10 | 10 | const testing = std.testing; |
| 11 | 11 | const Endian = std.lang.Endian; |
| 12 | const AbsorbSentinel = std.meta.AbsorbSentinel; | |
| 12 | 13 | |
| 13 | 14 | /// The standard library currently thoroughly depends on byte size |
| 14 | 15 | /// 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 | 757 | } |
| 757 | 758 | |
| 758 | 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; | |
| 760 | 762 | |
| 761 | 763 | for (a, b) |a_elem, b_elem| { |
| 762 | 764 | if (a_elem != b_elem) return false; |
| ... | ... | @@ -781,6 +783,9 @@ test eql { |
| 781 | 783 | |
| 782 | 784 | try testing.expect(eql(void, &.{ {}, {} }, &.{ {}, {} })); |
| 783 | 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 | } |
| 785 | 790 | |
| 786 | 791 | /// std.mem.eql heavily optimized for slices of bytes. |
| ... | ... | @@ -850,20 +855,25 @@ pub const indexOfDiff = findDiff; |
| 850 | 855 | /// Compares two slices and returns the index of the first inequality. |
| 851 | 856 | /// Returns null if the slices are equal. |
| 852 | 857 | pub fn findDiff(comptime T: type, a: []const T, b: []const T) ?usize { |
| 853 | const shortest = @min(a.len, b.len); | |
| 854 | if (a.ptr == b.ptr) | |
| 855 | return if (a.len == b.len) null else shortest; | |
| 856 | var index: usize = 0; | |
| 857 | while (index < shortest) : (index += 1) if (a[index] != b[index]) return index; | |
| 858 | return if (a.len == b.len) null else shortest; | |
| 858 | const shorter = @min(a.len, b.len); | |
| 859 | if (@typeInfo(T) != .float and a.ptr == b.ptr) { | |
| 860 | return if (a.len == b.len) null else shorter; | |
| 861 | } | |
| 862 | for (a[0..shorter], b[0..shorter], 0..) |a_elem, b_elem, i| { | |
| 863 | if (a_elem != b_elem) return i; | |
| 864 | } | |
| 865 | return if (a.len == b.len) null else shorter; | |
| 859 | 866 | } |
| 860 | 867 | |
| 861 | 868 | test findDiff { |
| 862 | try testing.expectEqual(findDiff(u8, "one", "one"), null); | |
| 863 | try testing.expectEqual(findDiff(u8, "one two", "one"), 3); | |
| 864 | try testing.expectEqual(findDiff(u8, "one", "one two"), 3); | |
| 865 | try testing.expectEqual(findDiff(u8, "one twx", "one two"), 6); | |
| 866 | try testing.expectEqual(findDiff(u8, "xne", "one"), 0); | |
| 869 | try testing.expectEqual(null, findDiff(u8, "one", "one")); | |
| 870 | try testing.expectEqual(3, findDiff(u8, "one two", "one")); | |
| 871 | try testing.expectEqual(3, findDiff(u8, "one", "one two")); | |
| 872 | try testing.expectEqual(6, findDiff(u8, "one twx", "one two")); | |
| 873 | try testing.expectEqual(0, findDiff(u8, "xne", "one")); | |
| 874 | ||
| 875 | const x: [3]f64 = .{ 42.0, math.nan(f64), 3.1415 }; | |
| 876 | try testing.expectEqual(1, findDiff(f64, &x, &x)); | |
| 867 | 877 | } |
| 868 | 878 | |
| 869 | 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 | 1529 | if (needle.len == 0) return haystack.len; |
| 1520 | 1530 | |
| 1521 | 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); | |
| 1523 | 1533 | |
| 1524 | 1534 | const haystack_bytes = sliceAsBytes(haystack); |
| 1525 | 1535 | const needle_bytes = sliceAsBytes(needle); |
| ... | ... | @@ -1574,26 +1584,26 @@ pub fn findPos(comptime T: type, haystack: []const T, start_index: usize, needle |
| 1574 | 1584 | |
| 1575 | 1585 | test find { |
| 1576 | 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 | 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); | |
| 1580 | 1590 | |
| 1581 | 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); | |
| 1583 | 1593 | |
| 1584 | 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 | 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 | 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 | 1600 | try testing.expect(find(u8, "foo", "fool") == null); |
| 1591 | try testing.expect(lastIndexOf(u8, "foo", "lfoo") == null); | |
| 1592 | try testing.expect(lastIndexOf(u8, "foo", "fool") == null); | |
| 1601 | try testing.expect(findLast(u8, "foo", "lfoo") == null); | |
| 1602 | try testing.expect(findLast(u8, "foo", "fool") == null); | |
| 1593 | 1603 | |
| 1594 | 1604 | try testing.expect(find(u8, "foo foo", "foo").? == 0); |
| 1595 | try testing.expect(lastIndexOf(u8, "foo foo", "foo").? == 4); | |
| 1596 | try testing.expect(lastIndexOfAny(u8, "boo, cat", "abo").? == 6); | |
| 1605 | try testing.expect(findLast(u8, "foo foo", "foo").? == 4); | |
| 1606 | try testing.expect(findLastAny(u8, "boo, cat", "abo").? == 6); | |
| 1597 | 1607 | try testing.expect(findScalarLast(u8, "boo", 'o').? == 2); |
| 1598 | 1608 | } |
| 1599 | 1609 | |
| ... | ... | @@ -1615,13 +1625,13 @@ test "find multibyte" { |
| 1615 | 1625 | // make haystack and needle long enough to trigger Boyer-Moore-Horspool algorithm |
| 1616 | 1626 | const haystack = [_]u16{ 0xbbaa, 0xccbb, 0xddcc, 0xeedd, 0xffee, 0x00ff } ++ @as([100]u16, @splat(0)); |
| 1617 | 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); | |
| 1619 | 1629 | |
| 1620 | 1630 | // check for misaligned false positives (little and big endian) |
| 1621 | 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 | 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 | } |
| 1627 | 1637 | |
| ... | ... | @@ -2215,33 +2225,54 @@ test writeVarPackedInt { |
| 2215 | 2225 | try testing.expectEqual(T{ .a = 1, .b = value, .c = 4 }, st); |
| 2216 | 2226 | } |
| 2217 | 2227 | |
| 2218 | /// Swap the byte order of all the members of the fields of a struct | |
| 2219 | /// (Changing their endianness) | |
| 2220 | pub fn byteSwapAllFields(comptime S: type, ptr: *S) void { | |
| 2221 | byteSwapAllFieldsAligned(S, .of(S), ptr); | |
| 2228 | /// Deprecated: use `byteSwap` instead. | |
| 2229 | pub const byteSwapAllFields = byteSwap; | |
| 2230 | ||
| 2231 | /// Deprecated: use `byteSwapAligned` instead. | |
| 2232 | pub 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. | |
| 2239 | pub fn byteSwap(comptime S: type, ptr: *S) void { | |
| 2240 | byteSwapAligned(S, .of(S), ptr); | |
| 2222 | 2241 | } |
| 2223 | 2242 | |
| 2224 | /// Swap the byte order of all the members of the fields of a struct | |
| 2225 | /// (Changing their endianness) | |
| 2226 | pub fn byteSwapAllFieldsAligned(comptime S: type, comptime a: Alignment, ptr: *align(a.toByteUnits()) S) void { | |
| 2243 | /// Reverses the byte order. | |
| 2244 | /// Handles structs, unions, arrays, enums, floats, and integers recursively. | |
| 2245 | /// The order of extern struct fields and array elements remains unchanged and | |
| 2246 | /// will be byte swapped recursively. | |
| 2247 | /// Useful for converting between little-endian and big-endian representations. | |
| 2248 | pub fn byteSwapAligned( | |
| 2249 | comptime S: type, | |
| 2250 | comptime a: Alignment, | |
| 2251 | ptr: *align(a.toByteUnits()) S, | |
| 2252 | ) void { | |
| 2227 | 2253 | switch (@typeInfo(S)) { |
| 2228 | 2254 | .@"struct" => |@"struct"| { |
| 2229 | 2255 | if (@"struct".backing_integer) |Int| { |
| 2230 | 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| { | |
| 2232 | switch (@typeInfo(f_type)) { | |
| 2233 | .@"struct" => byteSwapAllFieldsAligned(f_type, .fromByteUnits(f_attr.@"align" orelse @alignOf(f_type)), &@field(ptr, f_name)), | |
| 2234 | .@"union", .array => byteSwapAllFieldsAligned(f_type, .fromByteUnits(f_attr.@"align" orelse @alignOf(f_type)), &@field(ptr, f_name)), | |
| 2235 | .@"enum" => { | |
| 2236 | @field(ptr, f_name) = @fromBackingInt(@intCast(@byteSwap(@backingInt(@field(ptr, f_name))))); | |
| 2237 | }, | |
| 2238 | .bool => {}, | |
| 2239 | .float => |float| { | |
| 2240 | @field(ptr, f_name) = @bitCast(@byteSwap(@as(@Int(.unsigned, float.bits), @bitCast(@field(ptr, f_name))))); | |
| 2241 | }, | |
| 2242 | else => { | |
| 2243 | @field(ptr, f_name) = @byteSwap(@field(ptr, f_name)); | |
| 2244 | }, | |
| 2257 | } else { | |
| 2258 | if (@"struct".layout != .@"extern") { | |
| 2259 | @compileError("byteSwapAligned expects a packed or extern struct"); | |
| 2260 | } | |
| 2261 | inline for (@"struct".field_types, @"struct".field_names, @"struct".field_attrs) |f_type, f_name, f_attr| { | |
| 2262 | switch (@typeInfo(f_type)) { | |
| 2263 | .@"struct" => byteSwapAligned(f_type, .fromByteUnits(f_attr.@"align" orelse @alignOf(f_type)), &@field(ptr, f_name)), | |
| 2264 | .@"union", .array => byteSwapAligned(f_type, .fromByteUnits(f_attr.@"align" orelse @alignOf(f_type)), &@field(ptr, f_name)), | |
| 2265 | .@"enum" => { | |
| 2266 | @field(ptr, f_name) = @fromBackingInt(@byteSwap(@backingInt(@field(ptr, f_name)))); | |
| 2267 | }, | |
| 2268 | .bool => {}, | |
| 2269 | .float => |float| { | |
| 2270 | @field(ptr, f_name) = @bitCast(@byteSwap(@as(@Int(.unsigned, float.bits), @bitCast(@field(ptr, f_name))))); | |
| 2271 | }, | |
| 2272 | else => { | |
| 2273 | @field(ptr, f_name) = @byteSwap(@field(ptr, f_name)); | |
| 2274 | }, | |
| 2275 | } | |
| 2245 | 2276 | } |
| 2246 | 2277 | } |
| 2247 | 2278 | }, |
| ... | ... | @@ -2249,7 +2280,7 @@ pub fn byteSwapAllFieldsAligned(comptime S: type, comptime a: Alignment, ptr: *a |
| 2249 | 2280 | ptr.* = @bitCast(@byteSwap(@as(Int, @bitCast(ptr.*)))); |
| 2250 | 2281 | } else { |
| 2251 | 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 | } |
| 2254 | 2285 | |
| 2255 | 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 | 2297 | .array => |array| { |
| 2267 | 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 | 2308 | else => { |
| 2270 | 2309 | ptr.* = @byteSwap(ptr.*); |
| 2271 | 2310 | }, |
| 2272 | 2311 | } |
| 2273 | 2312 | } |
| 2274 | 2313 | |
| 2275 | test byteSwapAllFields { | |
| 2314 | test byteSwap { | |
| 2276 | 2315 | const T = extern struct { |
| 2277 | 2316 | f0: u8, |
| 2278 | 2317 | f1: u16, |
| ... | ... | @@ -2304,6 +2343,9 @@ test byteSwapAllFields { |
| 2304 | 2343 | } align(4), |
| 2305 | 2344 | f2: u32, |
| 2306 | 2345 | }; |
| 2346 | const E = enum(u32) { | |
| 2347 | _, | |
| 2348 | }; | |
| 2307 | 2349 | var s = T{ |
| 2308 | 2350 | .f0 = 0x12, |
| 2309 | 2351 | .f1 = 0x1234, |
| ... | ... | @@ -2327,10 +2369,14 @@ test byteSwapAllFields { |
| 2327 | 2369 | .f1 = .{ .f0 = 0x123456789ABCDEF0 }, |
| 2328 | 2370 | .f2 = 0x87654321, |
| 2329 | 2371 | }; |
| 2330 | byteSwapAllFields(T, &s); | |
| 2331 | byteSwapAllFields(K, &k); | |
| 2332 | byteSwapAllFields(P, &p); | |
| 2333 | byteSwapAllFields(A, &a); | |
| 2372 | var e: E = @fromBackingInt(0x12345678); | |
| 2373 | var f: f32 = @bitCast(@as(u32, 0x4640e400)); | |
| 2374 | byteSwap(T, &s); | |
| 2375 | byteSwap(K, &k); | |
| 2376 | byteSwap(P, &p); | |
| 2377 | byteSwap(A, &a); | |
| 2378 | byteSwap(E, &e); | |
| 2379 | byteSwap(f32, &f); | |
| 2334 | 2380 | try std.testing.expectEqual(T{ |
| 2335 | 2381 | .f0 = 0x12, |
| 2336 | 2382 | .f1 = 0x3412, |
| ... | ... | @@ -2354,28 +2400,15 @@ test byteSwapAllFields { |
| 2354 | 2400 | .f1 = .{ .f0 = 0xF0DEBC9A78563412 }, |
| 2355 | 2401 | .f2 = 0x21436587, |
| 2356 | 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 | } |
| 2358 | 2406 | |
| 2359 | 2407 | /// Reverses the byte order of all elements in a slice. |
| 2360 | 2408 | /// Handles structs, unions, arrays, enums, floats, and integers recursively. |
| 2361 | 2409 | /// Useful for converting between little-endian and big-endian representations. |
| 2362 | 2410 | pub fn byteSwapAllElements(comptime Elem: type, slice: []Elem) void { |
| 2363 | for (slice) |*elem| { | |
| 2364 | switch (@typeInfo(@TypeOf(elem.*))) { | |
| 2365 | .@"struct", .@"union", .array => byteSwapAllFields(@TypeOf(elem.*), elem), | |
| 2366 | .@"enum" => { | |
| 2367 | elem.* = @fromBackingInt(@intCast(@byteSwap(@backingInt(elem.*)))); | |
| 2368 | }, | |
| 2369 | .bool => {}, | |
| 2370 | .float => |float| { | |
| 2371 | const int_repr: @Int(.unsigned, float.bits) = @bitCast(elem.*); | |
| 2372 | elem.* = @bitCast(@byteSwap(int_repr)); | |
| 2373 | }, | |
| 2374 | else => { | |
| 2375 | elem.* = @byteSwap(elem.*); | |
| 2376 | }, | |
| 2377 | } | |
| 2378 | } | |
| 2411 | for (slice) |*elem| byteSwap(Elem, elem); | |
| 2379 | 2412 | } |
| 2380 | 2413 | |
| 2381 | 2414 | /// 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 | 3486 | pub fn next(self: *Self) ?[]const T { |
| 3454 | 3487 | const end = self.index orelse return null; |
| 3455 | 3488 | const start = if (switch (delimiter_type) { |
| 3456 | .sequence => lastIndexOf(T, self.buffer[0..end], self.delimiter), | |
| 3457 | .any => lastIndexOfAny(T, self.buffer[0..end], self.delimiter), | |
| 3489 | .sequence => findLast(T, self.buffer[0..end], self.delimiter), | |
| 3490 | .any => findLastAny(T, self.buffer[0..end], self.delimiter), | |
| 3458 | 3491 | .scalar => findScalarLast(T, self.buffer[0..end], self.delimiter), |
| 3459 | 3492 | }) |delim_start| blk: { |
| 3460 | 3493 | self.index = delim_start; |
| ... | ... | @@ -4706,22 +4739,28 @@ test "sliceAsBytes preserves pointer attributes" { |
| 4706 | 4739 | try testing.expectEqual(in_attrs.@"align", out_attrs.@"align"); |
| 4707 | 4740 | } |
| 4708 | 4741 | |
| 4709 | fn 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 | 4742 | /// If the provided slice is not sentinel terminated, do nothing and return that slice. |
| 4716 | 4743 | /// If it is sentinel-terminated, return a non-sentinel-terminated slice with the |
| 4717 | 4744 | /// length increased by one to include the absorbed sentinel element. |
| 4718 | pub fn absorbSentinel(slice: anytype) AbsorbSentinelReturnType(@TypeOf(slice)) { | |
| 4745 | pub fn absorbSentinel(slice: anytype) AbsorbSentinel(@TypeOf(slice)) { | |
| 4719 | 4746 | const info = @typeInfo(@TypeOf(slice)).pointer; |
| 4720 | comptime assert(info.size == .slice); | |
| 4721 | if (info.sentinel_ptr == null) { | |
| 4722 | return slice; | |
| 4723 | } else { | |
| 4724 | return slice.ptr[0 .. slice.len + 1]; | |
| 4747 | switch (info.size) { | |
| 4748 | .slice => { | |
| 4749 | if (info.sentinel_ptr == null) { | |
| 4750 | return slice; | |
| 4751 | } else { | |
| 4752 | return slice.ptr[0 .. slice.len + 1]; | |
| 4753 | } | |
| 4754 | }, | |
| 4755 | .one => { | |
| 4756 | const child_info = @typeInfo(info.child).array; | |
| 4757 | if (child_info.sentinel_ptr == null) { | |
| 4758 | return slice; | |
| 4759 | } else { | |
| 4760 | return slice[0 .. child_info.len + 1]; | |
| 4761 | } | |
| 4762 | }, | |
| 4763 | else => unreachable, | |
| 4725 | 4764 | } |
| 4726 | 4765 | } |
| 4727 | 4766 | |
| ... | ... | @@ -4730,21 +4769,28 @@ test absorbSentinel { |
| 4730 | 4769 | var buffer: [3:0]u8 = .{ 1, 2, 3 }; |
| 4731 | 4770 | const foo: [:0]const u8 = &buffer; |
| 4732 | 4771 | const bar: []const u8 = &buffer; |
| 4772 | const baz: *const [3:0]u8 = &buffer; | |
| 4733 | 4773 | try testing.expectEqual([]const u8, @TypeOf(absorbSentinel(foo))); |
| 4734 | 4774 | try testing.expectEqual([]const u8, @TypeOf(absorbSentinel(bar))); |
| 4775 | try testing.expectEqual(*const [4]u8, @TypeOf(absorbSentinel(baz))); | |
| 4735 | 4776 | try testing.expectEqualSlices(u8, &.{ 1, 2, 3, 0 }, absorbSentinel(foo)); |
| 4736 | 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 | 4781 | var buffer: [3:0]u8 = .{ 1, 2, 3 }; |
| 4740 | 4782 | const foo: [:0]u8 = &buffer; |
| 4741 | 4783 | const bar: []u8 = &buffer; |
| 4784 | const baz: *[3:0]u8 = &buffer; | |
| 4742 | 4785 | try testing.expectEqual([]u8, @TypeOf(absorbSentinel(foo))); |
| 4743 | 4786 | try testing.expectEqual([]u8, @TypeOf(absorbSentinel(bar))); |
| 4787 | try testing.expectEqual(*[4]u8, @TypeOf(absorbSentinel(baz))); | |
| 4744 | 4788 | var expected_foo = [_]u8{ 1, 2, 3, 0 }; |
| 4745 | 4789 | try testing.expectEqualSlices(u8, &expected_foo, absorbSentinel(foo)); |
| 4746 | 4790 | var expected_bar = [_]u8{ 1, 2, 3 }; |
| 4747 | 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 | } |
| 4750 | 4796 | |
| ... | ... | @@ -4780,62 +4826,58 @@ pub fn alignForwardLog2(addr: usize, log2_alignment: u8) usize { |
| 4780 | 4826 | pub fn doNotOptimizeAway(val: anytype) void { |
| 4781 | 4827 | if (@inComptime()) return; |
| 4782 | 4828 | |
| 4783 | const max_gp_register_bits = @bitSizeOf(c_long); | |
| 4784 | const t = @typeInfo(@TypeOf(val)); | |
| 4785 | switch (t) { | |
| 4829 | if (builtin.zig_backend == .stage2_c and builtin.abi == .msvc) { | |
| 4830 | _ = @atomicRmw(*const anyopaque, @as(*volatile *const anyopaque, &struct { | |
| 4831 | var escape: *const anyopaque = undefined; | |
| 4832 | }.escape), .Xchg, &val, .acq_rel); // TODO: syncscope("singlethreaded") | |
| 4833 | return; | |
| 4834 | } | |
| 4835 | ||
| 4836 | switch (@typeInfo(@TypeOf(val))) { | |
| 4786 | 4837 | .void, .null, .comptime_int, .comptime_float => return, |
| 4787 | 4838 | .@"enum" => doNotOptimizeAway(@backingInt(val)), |
| 4788 | 4839 | .bool => doNotOptimizeAway(@intFromBool(val)), |
| 4789 | .int => { | |
| 4790 | const bits = t.int.bits; | |
| 4791 | if (bits <= max_gp_register_bits and builtin.zig_backend != .stage2_c) { | |
| 4840 | .int => |int| { | |
| 4841 | // SPIR-V targets do not have registers per se, they have values | |
| 4842 | // tied to IDs that can be passed to valid instructions. Some | |
| 4843 | // SPIR-V targets do not define c_long, so we just allow any sized | |
| 4844 | // integer on these targets | |
| 4845 | const val_fits_in_gp_register = builtin.target.cpu.arch.isSpirV() or fits: { | |
| 4846 | const max_gp_register_bits = @bitSizeOf(c_long); | |
| 4847 | break :fits int.bits <= max_gp_register_bits; | |
| 4848 | }; | |
| 4849 | if (val_fits_in_gp_register) { | |
| 4792 | 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 | 4852 | val, |
| 4795 | 4853 | ); |
| 4796 | 4854 | asm volatile ("" |
| 4797 | 4855 | : |
| 4798 | 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 | 4858 | } else { |
| 4814 | asm volatile ("" | |
| 4815 | : | |
| 4816 | : [_] "m" (val), | |
| 4817 | : .{ .memory = true }); | |
| 4859 | doNotOptimizeAway(&val); | |
| 4818 | 4860 | } |
| 4819 | 4861 | }, |
| 4820 | .array => { | |
| 4821 | if (t.array.len * @sizeOf(t.array.child) <= 64) { | |
| 4822 | for (val) |v| doNotOptimizeAway(v); | |
| 4823 | } else doNotOptimizeAway(&val); | |
| 4862 | .float => |float| switch (float.bits) { | |
| 4863 | else => comptime unreachable, | |
| 4864 | 16, 80, 128 => doNotOptimizeAway(&val), | |
| 4865 | 32, 64 => asm volatile ("" | |
| 4866 | : | |
| 4867 | : [_] "rm" (val), | |
| 4868 | ), | |
| 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 | 4877 | else => doNotOptimizeAway(&val), |
| 4826 | 4878 | } |
| 4827 | 4879 | } |
| 4828 | 4880 | |
| 4829 | /// .stage2_c doesn't support asm blocks yet, so use volatile stores instead | |
| 4830 | var deopt_target: if (builtin.zig_backend == .stage2_c) u8 else void = undefined; | |
| 4831 | fn 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 | ||
| 4839 | 4881 | test doNotOptimizeAway { |
| 4840 | 4882 | comptime doNotOptimizeAway("test"); |
| 4841 | 4883 | |
| ... | ... | @@ -4994,12 +5036,9 @@ pub fn alignInSlice(slice: anytype, comptime new_alignment: usize) ?AlignedSlice |
| 4994 | 5036 | } |
| 4995 | 5037 | |
| 4996 | 5038 | test "read/write(Var)PackedInt" { |
| 4997 | switch (builtin.cpu.arch) { | |
| 4998 | // This test generates too much code to execute on WASI. | |
| 4999 | // LLVM backend fails with "too many locals: locals exceed maximum" | |
| 5000 | .wasm32, .wasm64 => return error.SkipZigTest, | |
| 5001 | else => {}, | |
| 5002 | } | |
| 5039 | // This test generates too much code to execute on WASI. | |
| 5040 | // LLVM backend fails with "too many locals: locals exceed maximum" | |
| 5041 | if (builtin.cpu.arch.isWasm()) return error.SkipZigTest; | |
| 5003 | 5042 | |
| 5004 | 5043 | const foreign_endian: Endian = if (native_endian == .big) .little else .big; |
| 5005 | 5044 | const expect = std.testing.expect; |
lib/std/mem/Allocator.zig+56-16| ... | ... | @@ -8,6 +8,8 @@ const assert = std.debug.assert; |
| 8 | 8 | const math = std.math; |
| 9 | 9 | const mem = std.mem; |
| 10 | 10 | const Alignment = std.mem.Alignment; |
| 11 | const Slice = std.meta.Slice; | |
| 12 | const AbsorbSentinel = std.meta.AbsorbSentinel; | |
| 11 | 13 | |
| 12 | 14 | pub const Error = error{OutOfMemory}; |
| 13 | 15 | pub const Log2Align = math.Log2Int(usize); |
| ... | ... | @@ -316,8 +318,10 @@ pub fn allocBytesAligned( |
| 316 | 318 | /// `new_len` may be zero, in which case the allocation is freed. |
| 317 | 319 | pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool { |
| 318 | 320 | const slice_info = @typeInfo(@TypeOf(allocation)).pointer; |
| 319 | comptime assert(slice_info.size == .slice); | |
| 320 | const T = slice_info.child; | |
| 321 | const T = if (slice_info.size != .slice) comptime T: { | |
| 322 | assert(slice_info.size == .one); | |
| 323 | break :T @typeInfo(slice_info.child).array.child; | |
| 324 | } else slice_info.child; | |
| 321 | 325 | if (new_len == 0) { |
| 322 | 326 | self.free(allocation); |
| 323 | 327 | return true; |
| ... | ... | @@ -326,9 +330,6 @@ pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool { |
| 326 | 330 | return false; |
| 327 | 331 | } |
| 328 | 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 | 333 | const new_len_bytes = math.mul(usize, @sizeOf(T), new_len) catch return false; |
| 333 | 334 | return self.rawResize( |
| 334 | 335 | old_memory, |
| ... | ... | @@ -354,10 +355,12 @@ pub fn resize(self: Allocator, allocation: anytype, new_len: usize) bool { |
| 354 | 355 | /// `new_len` may be zero, in which case the allocation is freed. |
| 355 | 356 | /// |
| 356 | 357 | /// If the allocation's elements' type is zero bytes sized, `allocation.len` is set to `new_len`. |
| 357 | pub fn remap(self: Allocator, allocation: anytype, new_len: usize) ?@TypeOf(allocation) { | |
| 358 | pub fn remap(self: Allocator, allocation: anytype, new_len: usize) ?Slice(AbsorbSentinel(@TypeOf(allocation))) { | |
| 358 | 359 | const slice_info = @typeInfo(@TypeOf(allocation)).pointer; |
| 359 | comptime assert(slice_info.size == .slice); | |
| 360 | const T = slice_info.child; | |
| 360 | const T = if (slice_info.size != .slice) comptime T: { | |
| 361 | assert(slice_info.size == .one); | |
| 362 | break :T @typeInfo(slice_info.child).array.child; | |
| 363 | } else slice_info.child; | |
| 361 | 364 | |
| 362 | 365 | if (new_len == 0) { |
| 363 | 366 | self.free(allocation); |
| ... | ... | @@ -372,9 +375,6 @@ pub fn remap(self: Allocator, allocation: anytype, new_len: usize) ?@TypeOf(allo |
| 372 | 375 | return new_memory; |
| 373 | 376 | } |
| 374 | 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 | 378 | const new_len_bytes = math.mul(usize, @sizeOf(T), new_len) catch return null; |
| 379 | 379 | const new_ptr = self.rawRemap( |
| 380 | 380 | old_memory, |
| ... | ... | @@ -399,7 +399,7 @@ pub fn remap(self: Allocator, allocation: anytype, new_len: usize) ?@TypeOf(allo |
| 399 | 399 | /// do the realloc more efficiently than the caller |
| 400 | 400 | /// * `resize` which returns `false` when the `Allocator` implementation cannot |
| 401 | 401 | /// change the size without relocating the allocation. |
| 402 | pub fn realloc(self: Allocator, old_mem: anytype, new_n: usize) Error!@TypeOf(old_mem) { | |
| 402 | pub fn realloc(self: Allocator, old_mem: anytype, new_n: usize) Error!Slice(AbsorbSentinel(@TypeOf(old_mem))) { | |
| 403 | 403 | return self.reallocAdvanced(old_mem, new_n, @returnAddress()); |
| 404 | 404 | } |
| 405 | 405 | |
| ... | ... | @@ -408,10 +408,12 @@ pub fn reallocAdvanced( |
| 408 | 408 | old_mem: anytype, |
| 409 | 409 | new_n: usize, |
| 410 | 410 | return_address: usize, |
| 411 | ) Error!@TypeOf(old_mem) { | |
| 411 | ) Error!Slice(AbsorbSentinel(@TypeOf(old_mem))) { | |
| 412 | 412 | const slice_info = @typeInfo(@TypeOf(old_mem)).pointer; |
| 413 | comptime assert(slice_info.size == .slice); | |
| 414 | const T = slice_info.child; | |
| 413 | const T = if (slice_info.size != .slice) comptime T: { | |
| 414 | assert(slice_info.size == .one); | |
| 415 | break :T @typeInfo(slice_info.child).array.child; | |
| 416 | } else slice_info.child; | |
| 415 | 417 | if (old_mem.len == 0) { |
| 416 | 418 | return self.allocAdvancedWithRetAddr(T, .fromByteUnitsOptional(slice_info.attrs.@"align"), new_n, return_address); |
| 417 | 419 | } |
| ... | ... | @@ -446,7 +448,6 @@ pub fn reallocAdvanced( |
| 446 | 448 | pub fn free(self: Allocator, memory: anytype) void { |
| 447 | 449 | const slice_info = @typeInfo(@TypeOf(memory)).pointer; |
| 448 | 450 | if (slice_info.size != .slice) { |
| 449 | // slicing with comptime-known start and end results in *[len]T, which may be free'd | |
| 450 | 451 | comptime assert(slice_info.size == .one and @typeInfo(slice_info.child) == .array); |
| 451 | 452 | } |
| 452 | 453 | const bytes: []u8 = @ptrCast(@constCast(mem.absorbSentinel(memory))); |
| ... | ... | @@ -587,4 +588,43 @@ fn unreachableFree( |
| 587 | 588 | test failing { |
| 588 | 589 | const f: Allocator = .failing; |
| 589 | 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 | ||
| 596 | test "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 | 1 | const builtin = @import("builtin"); |
| 2 | ||
| 2 | 3 | const std = @import("std.zig"); |
| 3 | const debug = std.debug; | |
| 4 | const assert = std.debug.assert; | |
| 4 | 5 | const mem = std.mem; |
| 5 | const math = std.math; | |
| 6 | 6 | const testing = std.testing; |
| 7 | const root = @import("root"); | |
| 8 | 7 | |
| 9 | 8 | pub const TrailerFlags = @import("meta/trailer_flags.zig").TrailerFlags; |
| 10 | 9 | |
| ... | ... | @@ -198,15 +197,17 @@ test containerLayout { |
| 198 | 197 | try testing.expect(containerLayout(U3) == .@"extern"); |
| 199 | 198 | } |
| 200 | 199 | |
| 201 | /// Instead of this function, prefer to use e.g. `@typeInfo(foo).@"struct".decl_names` | |
| 202 | /// directly when you know what kind of type it is. | |
| 200 | /// Returns the list of declaration names of namespace types. | |
| 201 | /// | |
| 202 | /// This function is only useful when the callsite does not know statically | |
| 203 | /// which kind of container it is. | |
| 203 | 204 | pub fn declarations(comptime T: type) []const [:0]const u8 { |
| 204 | 205 | return switch (@typeInfo(T)) { |
| 205 | 206 | .@"struct" => |info| info.decl_names, |
| 206 | 207 | .@"enum" => |info| info.decl_names, |
| 207 | 208 | .@"union" => |info| info.decl_names, |
| 208 | 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 | } |
| 212 | 213 | |
| ... | ... | @@ -242,10 +243,13 @@ test declarations { |
| 242 | 243 | } |
| 243 | 244 | |
| 244 | 245 | /// To be removed after Zig 0.17.0 is tagged. |
| 245 | pub const declarationInfo = @compileError("Deprecated; use '@hasDecl' instead"); | |
| 246 | pub const declarationInfo = @compileError("deprecated in favor of @hasDecl"); | |
| 246 | 247 | /// To be removed after Zig 0.17.0 is tagged. |
| 247 | pub const fields = @compileError("Deprecated; use 'fieldNames' and 'fieldTypes' instead"); | |
| 248 | pub const fields = @compileError("deprecated in favor of @typeInfo"); | |
| 248 | 249 | |
| 250 | /// Deprecated in favor of `@typeInfo`. | |
| 251 | /// | |
| 252 | /// To be removed after 0.17.0 is tagged. | |
| 249 | 253 | pub fn fieldInfo(comptime T: type, comptime field: FieldEnum(T)) switch (@typeInfo(T)) { |
| 250 | 254 | .@"struct" => struct { name: [:0]const u8, type: type, attrs: Type.Struct.FieldAttributes }, |
| 251 | 255 | .@"union" => struct { name: [:0]const u8, type: type, attrs: Type.Union.FieldAttributes }, |
| ... | ... | @@ -299,13 +303,16 @@ test fieldInfo { |
| 299 | 303 | try testing.expect(comptime uf.type == u8); |
| 300 | 304 | } |
| 301 | 305 | |
| 306 | /// Deprecated in favor of `@typeInfo`. | |
| 307 | /// | |
| 308 | /// To be removed after 0.17.0 is tagged. | |
| 302 | 309 | pub fn fieldNames(comptime T: type) []const [:0]const u8 { |
| 303 | 310 | return switch (@typeInfo(T)) { |
| 304 | 311 | .@"struct" => |s| s.field_names, |
| 305 | 312 | .@"union" => |u| u.field_names, |
| 306 | 313 | .@"enum" => |e| e.field_names, |
| 307 | 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 | } |
| 311 | 318 | |
| ... | ... | @@ -337,11 +344,14 @@ test fieldNames { |
| 337 | 344 | try testing.expectEqualSlices(u8, u1names[1], "b"); |
| 338 | 345 | } |
| 339 | 346 | |
| 347 | /// Deprecated in favor of `@typeInfo`. | |
| 348 | /// | |
| 349 | /// To be removed after 0.17.0 is tagged. | |
| 340 | 350 | pub fn fieldTypes(comptime T: type) []const type { |
| 341 | 351 | return switch (@typeInfo(T)) { |
| 342 | 352 | .@"struct" => |s| s.field_types, |
| 343 | 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 | } |
| 347 | 357 | |
| ... | ... | @@ -821,8 +831,8 @@ pub fn isError(error_union: anytype) bool { |
| 821 | 831 | } |
| 822 | 832 | |
| 823 | 833 | test isError { |
| 824 | try std.testing.expect(isError(math.divTrunc(u8, 5, 0))); | |
| 825 | try std.testing.expect(!isError(math.divTrunc(u8, 5, 5))); | |
| 834 | try std.testing.expect(isError(std.math.divTrunc(u8, 5, 0))); | |
| 835 | try std.testing.expect(!isError(std.math.divTrunc(u8, 5, 5))); | |
| 826 | 836 | } |
| 827 | 837 | |
| 828 | 838 | /// Returns true if a type has a namespace and the namespace contains `name`; |
| ... | ... | @@ -1070,3 +1080,50 @@ test hasUniqueRepresentation { |
| 1070 | 1080 | |
| 1071 | 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. | |
| 1086 | pub 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 | |
| 1107 | pub 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 | ||
| 1123 | test Slice { | |
| 1124 | try testing.expectEqual([]i32, Slice(*[10]i32)); | |
| 1125 | } | |
| 1126 | ||
| 1127 | test 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 | 39 | break :blk @Struct(.auto, null, &field_names, &field_types, &field_attrs); |
| 40 | 40 | }; |
| 41 | 41 | |
| 42 | pub const Self = @This(); | |
| 42 | const Self = @This(); | |
| 43 | 43 | |
| 44 | 44 | pub fn has(self: Self, comptime field: FieldEnum) bool { |
| 45 | 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 | 163 | }; |
| 164 | 164 | } |
| 165 | 165 | |
| 166 | /// This function is used in the debugger pretty formatters in tools/ to fetch the | |
| 166 | /// This function is used in the debugger pretty formatters in lib/lldb/ to fetch the | |
| 167 | 167 | /// child field order and entry type to facilitate fancy debug printing for this type. |
| 168 | 168 | fn dbHelper(self: *Slice, child: *Elem, field: *Field, entry: *Entry) void { |
| 169 | 169 | _ = self; |
| ... | ... | @@ -681,7 +681,7 @@ pub fn MultiArrayList(comptime T: type) type { |
| 681 | 681 | } |
| 682 | 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 the | |
| 684 | /// This function is used in the debugger pretty formatters in lib/lldb/ to fetch the | |
| 685 | 685 | /// child field order and entry type to facilitate fancy debug printing for this type. |
| 686 | 686 | fn dbHelper(self: *Self, child: *Elem, field: *Field, entry: *Entry) void { |
| 687 | 687 | _ = self; |
lib/std/os/emscripten.zig+1-1| ... | ... | @@ -730,7 +730,7 @@ pub const clock_t = i32; |
| 730 | 730 | pub const dl_phdr_info = extern struct { |
| 731 | 731 | addr: usize, |
| 732 | 732 | name: ?[*:0]const u8, |
| 733 | phdr: [*]std.elf.Phdr, | |
| 733 | phdr: [*]std.elf.ElfN.Phdr, | |
| 734 | 734 | phnum: u16, |
| 735 | 735 | }; |
| 736 | 736 |
lib/std/os/linux.zig+4-6| ... | ... | @@ -2058,8 +2058,8 @@ pub const F = struct { |
| 2058 | 2058 | }, |
| 2059 | 2059 | }; |
| 2060 | 2060 | |
| 2061 | pub const SETSIG = if (is_hppa or native_arch == .alpha) 13 else 11; | |
| 2062 | pub const GETSIG = if (is_hppa or native_arch == .alpha) 14 else 12; | |
| 2061 | pub const SETSIG = if (is_hppa) 13 else 10; | |
| 2062 | pub const GETSIG = if (is_hppa) 14 else 11; | |
| 2063 | 2063 | |
| 2064 | 2064 | pub const SETOWN_EX = 15; |
| 2065 | 2065 | pub const GETOWN_EX = 16; |
| ... | ... | @@ -8181,13 +8181,11 @@ pub const rusage = extern struct { |
| 8181 | 8181 | |
| 8182 | 8182 | pub const NCC = if (is_ppc) 10 else 8; |
| 8183 | 8183 | pub const NCCS = if (is_mips) |
| 8184 | 32 | |
| 8185 | else if (is_ppc or native_arch == .alpha) | |
| 8186 | 19 | |
| 8184 | 23 | |
| 8187 | 8185 | else if (is_sparc) |
| 8188 | 8186 | 17 |
| 8189 | 8187 | else |
| 8190 | 32; | |
| 8188 | 19; | |
| 8191 | 8189 | |
| 8192 | 8190 | pub const speed_t = if (is_ppc) enum(c_uint) { |
| 8193 | 8191 | B0 = 0x0000000, |
lib/std/os/linux/IoUring.zig+1-1| ... | ... | @@ -267,7 +267,7 @@ pub fn cq_ready(self: *IoUring) u32 { |
| 267 | 267 | } |
| 268 | 268 | |
| 269 | 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 | 271 | /// Returns the number of CQEs copied, advancing the CQ ring. |
| 272 | 272 | /// Provides all the wait/peek methods found in liburing, but with batching and a single method. |
| 273 | 273 | /// 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 | 475 | } |
| 476 | 476 | |
| 477 | 477 | test "accept/connect/send/recv" { |
| 478 | const io = testing.io; | |
| 479 | _ = io; | |
| 480 | ||
| 481 | 478 | var ring = IoUring.init(16, 0) catch |err| switch (err) { |
| 482 | 479 | error.SystemOutdated => return error.SkipZigTest, |
| 483 | 480 | error.PermissionDenied => return error.SkipZigTest, |
| ... | ... | @@ -620,7 +617,7 @@ test "timeout (after a relative time)" { |
| 620 | 617 | |
| 621 | 618 | const ms = 10; |
| 622 | 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 }; | |
| 624 | 621 | |
| 625 | 622 | const started = std.Io.Clock.awake.now(io); |
| 626 | 623 | const sqe = try ring.timeout(0x55555555, &ts, 0, 0); |
| ... | ... | @@ -730,9 +727,6 @@ test "timeout_remove" { |
| 730 | 727 | } |
| 731 | 728 | |
| 732 | 729 | test "accept/connect/recv/link_timeout" { |
| 733 | const io = testing.io; | |
| 734 | _ = io; | |
| 735 | ||
| 736 | 730 | var ring = IoUring.init(16, 0) catch |err| switch (err) { |
| 737 | 731 | error.SystemOutdated => return error.SkipZigTest, |
| 738 | 732 | error.PermissionDenied => return error.SkipZigTest, |
| ... | ... | @@ -748,7 +742,7 @@ test "accept/connect/recv/link_timeout" { |
| 748 | 742 | const sqe_recv = try ring.recv(0xffffffff, socket_test_harness.server, .{ .buffer = buffer_recv[0..] }, 0); |
| 749 | 743 | sqe_recv.flags |= linux.IOSQE_IO_LINK; |
| 750 | 744 | |
| 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 | 746 | _ = try ring.link_timeout(0x22222222, &ts, 0); |
| 753 | 747 | |
| 754 | 748 | const nr_wait = try ring.submit(); |
| ... | ... | @@ -883,9 +877,6 @@ test "statx" { |
| 883 | 877 | } |
| 884 | 878 | |
| 885 | 879 | test "accept/connect/recv/cancel" { |
| 886 | const io = testing.io; | |
| 887 | _ = io; | |
| 888 | ||
| 889 | 880 | var ring = IoUring.init(16, 0) catch |err| switch (err) { |
| 890 | 881 | error.SystemOutdated => return error.SkipZigTest, |
| 891 | 882 | error.PermissionDenied => return error.SkipZigTest, |
| ... | ... | @@ -1568,9 +1559,6 @@ test "remove_buffers" { |
| 1568 | 1559 | } |
| 1569 | 1560 | |
| 1570 | 1561 | test "provide_buffers: accept/connect/send/recv" { |
| 1571 | const io = testing.io; | |
| 1572 | _ = io; | |
| 1573 | ||
| 1574 | 1562 | var ring = IoUring.init(16, 0) catch |err| switch (err) { |
| 1575 | 1563 | error.SystemOutdated => return error.SkipZigTest, |
| 1576 | 1564 | error.PermissionDenied => return error.SkipZigTest, |
| ... | ... | @@ -1777,11 +1765,6 @@ test "accept multishot" { |
| 1777 | 1765 | } |
| 1778 | 1766 | |
| 1779 | 1767 | test "accept/connect/send_zc/recv" { |
| 1780 | try skipKernelLessThan(.{ .major = 6, .minor = 0, .patch = 0 }); | |
| 1781 | ||
| 1782 | const io = testing.io; | |
| 1783 | _ = io; | |
| 1784 | ||
| 1785 | 1768 | var ring = IoUring.init(16, 0) catch |err| switch (err) { |
| 1786 | 1769 | error.SystemOutdated => return error.SkipZigTest, |
| 1787 | 1770 | error.PermissionDenied => return error.SkipZigTest, |
| ... | ... | @@ -1789,6 +1772,13 @@ test "accept/connect/send_zc/recv" { |
| 1789 | 1772 | }; |
| 1790 | 1773 | defer ring.deinit(); |
| 1791 | 1774 | |
| 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 | 1782 | const socket_test_harness = try createSocketTestHarness(&ring); |
| 1793 | 1783 | defer socket_test_harness.close(); |
| 1794 | 1784 | |
| ... | ... | @@ -1836,16 +1826,16 @@ test "accept/connect/send_zc/recv" { |
| 1836 | 1826 | } |
| 1837 | 1827 | |
| 1838 | 1828 | test "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 | 1829 | var ring = IoUring.init(1, 0) catch |err| switch (err) { |
| 1844 | 1830 | error.SystemOutdated => return error.SkipZigTest, |
| 1845 | 1831 | error.PermissionDenied => return error.SkipZigTest, |
| 1846 | 1832 | else => return err, |
| 1847 | 1833 | }; |
| 1848 | 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 | 1839 | var address: linux.sockaddr.in = .{ |
| 1850 | 1840 | .port = 0, |
| 1851 | 1841 | .addr = @as(*align(1) const u32, @ptrCast( |
| ... | ... | @@ -1923,13 +1913,6 @@ test "accept_direct" { |
| 1923 | 1913 | } |
| 1924 | 1914 | |
| 1925 | 1915 | test "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 | 1916 | var ring = IoUring.init(1, 0) catch |err| switch (err) { |
| 1934 | 1917 | error.SystemOutdated => return error.SkipZigTest, |
| 1935 | 1918 | error.PermissionDenied => return error.SkipZigTest, |
| ... | ... | @@ -1937,6 +1920,9 @@ test "accept_multishot_direct" { |
| 1937 | 1920 | }; |
| 1938 | 1921 | defer ring.deinit(); |
| 1939 | 1922 | |
| 1923 | const probe = ring.get_probe() catch return error.SkipZigTest; | |
| 1924 | if (!probe.is_supported(.ACCEPT)) return error.SkipZigTest; | |
| 1925 | ||
| 1940 | 1926 | var address: linux.sockaddr.in = .{ |
| 1941 | 1927 | .port = 0, |
| 1942 | 1928 | .addr = @as(*align(1) const u32, @ptrCast( |
| ... | ... | @@ -1991,8 +1977,6 @@ test "accept_multishot_direct" { |
| 1991 | 1977 | } |
| 1992 | 1978 | |
| 1993 | 1979 | test "socket" { |
| 1994 | try skipKernelLessThan(.{ .major = 5, .minor = 19, .patch = 0 }); | |
| 1995 | ||
| 1996 | 1980 | var ring = IoUring.init(1, 0) catch |err| switch (err) { |
| 1997 | 1981 | error.SystemOutdated => return error.SkipZigTest, |
| 1998 | 1982 | error.PermissionDenied => return error.SkipZigTest, |
| ... | ... | @@ -2000,6 +1984,9 @@ test "socket" { |
| 2000 | 1984 | }; |
| 2001 | 1985 | defer ring.deinit(); |
| 2002 | 1986 | |
| 1987 | const probe = ring.get_probe() catch return error.SkipZigTest; | |
| 1988 | if (!probe.is_supported(.SOCKET)) return error.SkipZigTest; | |
| 1989 | ||
| 2003 | 1990 | // prepare, submit socket operation |
| 2004 | 1991 | _ = try ring.socket(0, linux.AF.INET, posix.SOCK.STREAM, 0, 0); |
| 2005 | 1992 | try testing.expectEqual(@as(u32, 1), try ring.submit()); |
| ... | ... | @@ -2014,8 +2001,6 @@ test "socket" { |
| 2014 | 2001 | } |
| 2015 | 2002 | |
| 2016 | 2003 | test "socket_direct/socket_direct_alloc/close_direct" { |
| 2017 | try skipKernelLessThan(.{ .major = 5, .minor = 19, .patch = 0 }); | |
| 2018 | ||
| 2019 | 2004 | var ring = IoUring.init(2, 0) catch |err| switch (err) { |
| 2020 | 2005 | error.SystemOutdated => return error.SkipZigTest, |
| 2021 | 2006 | error.PermissionDenied => return error.SkipZigTest, |
| ... | ... | @@ -2023,6 +2008,9 @@ test "socket_direct/socket_direct_alloc/close_direct" { |
| 2023 | 2008 | }; |
| 2024 | 2009 | defer ring.deinit(); |
| 2025 | 2010 | |
| 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 | 2014 | var registered_fds: [3]linux.fd_t = @splat(-1); |
| 2027 | 2015 | try ring.register_files(registered_fds[0..]); |
| 2028 | 2016 | |
| ... | ... | @@ -2097,8 +2085,6 @@ test "socket_direct/socket_direct_alloc/close_direct" { |
| 2097 | 2085 | } |
| 2098 | 2086 | |
| 2099 | 2087 | test "openat_direct/close_direct" { |
| 2100 | try skipKernelLessThan(.{ .major = 5, .minor = 19, .patch = 0 }); | |
| 2101 | ||
| 2102 | 2088 | var ring = IoUring.init(2, 0) catch |err| switch (err) { |
| 2103 | 2089 | error.SystemOutdated => return error.SkipZigTest, |
| 2104 | 2090 | error.PermissionDenied => return error.SkipZigTest, |
| ... | ... | @@ -2106,6 +2092,9 @@ test "openat_direct/close_direct" { |
| 2106 | 2092 | }; |
| 2107 | 2093 | defer ring.deinit(); |
| 2108 | 2094 | |
| 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 | 2098 | var registered_fds: [3]linux.fd_t = @splat(-1); |
| 2110 | 2099 | try ring.register_files(registered_fds[0..]); |
| 2111 | 2100 | |
| ... | ... | @@ -2148,9 +2137,6 @@ test "openat_direct/close_direct" { |
| 2148 | 2137 | } |
| 2149 | 2138 | |
| 2150 | 2139 | test "ring mapped buffers recv" { |
| 2151 | const io = testing.io; | |
| 2152 | _ = io; | |
| 2153 | ||
| 2154 | 2140 | var ring = IoUring.init(16, 0) catch |err| switch (err) { |
| 2155 | 2141 | error.SystemOutdated => return error.SkipZigTest, |
| 2156 | 2142 | error.PermissionDenied => return error.SkipZigTest, |
| ... | ... | @@ -2238,9 +2224,6 @@ test "ring mapped buffers recv" { |
| 2238 | 2224 | } |
| 2239 | 2225 | |
| 2240 | 2226 | test "ring mapped buffers multishot recv" { |
| 2241 | const io = testing.io; | |
| 2242 | _ = io; | |
| 2243 | ||
| 2244 | 2227 | var ring = IoUring.init(16, 0) catch |err| switch (err) { |
| 2245 | 2228 | error.SystemOutdated => return error.SkipZigTest, |
| 2246 | 2229 | error.PermissionDenied => return error.SkipZigTest, |
| ... | ... | @@ -2672,7 +2655,7 @@ pub fn createSocketTestHarness(ring: *IoUring) !SocketTestHarness { |
| 2672 | 2655 | |
| 2673 | 2656 | // All good |
| 2674 | 2657 | |
| 2675 | return SocketTestHarness{ | |
| 2658 | return .{ | |
| 2676 | 2659 | .listener = listener_socket, |
| 2677 | 2660 | .server = cqe_accept.res, |
| 2678 | 2661 | .client = client, |
| ... | ... | @@ -2695,27 +2678,6 @@ fn createListenerSocket(address: *linux.sockaddr.in) !posix.socket_t { |
| 2695 | 2678 | return listener_socket; |
| 2696 | 2679 | } |
| 2697 | 2680 | |
| 2698 | /// For use in tests. Returns SkipZigTest if kernel version is less than required. | |
| 2699 | inline 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 | ||
| 2719 | 2681 | fn addrAny(addr: *linux.sockaddr.in) *linux.sockaddr { |
| 2720 | 2682 | return @ptrCast(addr); |
| 2721 | 2683 | } |
lib/std/os/linux/aarch64.zig+1-1| ... | ... | @@ -154,7 +154,7 @@ pub const restore = restore_rt; |
| 154 | 154 | pub fn restore_rt() callconv(.naked) noreturn { |
| 155 | 155 | switch (builtin.zig_backend) { |
| 156 | 156 | .stage2_c => asm volatile ( |
| 157 | \\ mov x8, %[number] | |
| 157 | \\ mov w8, %[number] | |
| 158 | 158 | \\ svc #0 |
| 159 | 159 | : |
| 160 | 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 | 174 | } |
| 175 | 175 | |
| 176 | 176 | pub fn restore() callconv(.naked) noreturn { |
| 177 | asm volatile ( | |
| 178 | \\svc 0 | |
| 179 | : | |
| 180 | : [number] "{r1}" (@backingInt(SYS.sigreturn)), | |
| 181 | ); | |
| 177 | switch (builtin.zig_backend) { | |
| 178 | .stage2_c => asm volatile ( | |
| 179 | \\lghi %%r1, %[number] | |
| 180 | \\svc 0 | |
| 181 | : | |
| 182 | : [number] "K" (@backingInt(SYS.sigreturn)), | |
| 183 | ), | |
| 184 | else => asm volatile ( | |
| 185 | \\svc 0 | |
| 186 | : | |
| 187 | : [number] "{r1}" (@backingInt(SYS.sigreturn)), | |
| 188 | ), | |
| 189 | } | |
| 182 | 190 | } |
| 183 | 191 | |
| 184 | 192 | pub fn restore_rt() callconv(.naked) noreturn { |
| 185 | asm volatile ( | |
| 186 | \\svc 0 | |
| 187 | : | |
| 188 | : [number] "{r1}" (@backingInt(SYS.rt_sigreturn)), | |
| 189 | ); | |
| 193 | switch (builtin.zig_backend) { | |
| 194 | .stage2_c => asm volatile ( | |
| 195 | \\lghi %%r1, %[number] | |
| 196 | \\svc 0 | |
| 197 | : | |
| 198 | : [number] "K" (@backingInt(SYS.rt_sigreturn)), | |
| 199 | ), | |
| 200 | else => asm volatile ( | |
| 201 | \\svc 0 | |
| 202 | : | |
| 203 | : [number] "{r1}" (@backingInt(SYS.rt_sigreturn)), | |
| 204 | ), | |
| 205 | } | |
| 190 | 206 | } |
| 191 | 207 | |
| 192 | 208 | pub const time_t = i64; |
lib/std/os/linux/sparc.zig+8-5| ... | ... | @@ -260,13 +260,16 @@ pub fn clone() callconv(.naked) u32 { |
| 260 | 260 | |
| 261 | 261 | pub const restore = restore_rt; |
| 262 | 262 | |
| 263 | // Need to use C ABI here instead of naked | |
| 264 | // to prevent an infinite loop when calling rt_sigreturn. | |
| 265 | pub fn restore_rt() callconv(.c) void { | |
| 266 | return asm volatile ("t 0x10" | |
| 263 | pub fn restore_rt() callconv(.naked) noreturn { | |
| 264 | asm volatile ( | |
| 265 | \\ nop | |
| 266 | \\ nop | |
| 267 | ); | |
| 268 | asm volatile ( | |
| 269 | \\ t 0x10 | |
| 267 | 270 | : |
| 268 | 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 | } |
| 271 | 274 | |
| 272 | 275 | pub const VDSO = struct { |
lib/std/os/linux/sparc64.zig+8-5| ... | ... | @@ -259,13 +259,16 @@ pub fn clone() callconv(.naked) u64 { |
| 259 | 259 | |
| 260 | 260 | pub const restore = restore_rt; |
| 261 | 261 | |
| 262 | // Need to use C ABI here instead of naked | |
| 263 | // to prevent an infinite loop when calling rt_sigreturn. | |
| 264 | pub fn restore_rt() callconv(.c) void { | |
| 265 | return asm volatile ("t 0x6d" | |
| 262 | pub fn restore_rt() callconv(.naked) noreturn { | |
| 263 | asm volatile ( | |
| 264 | \\ nop | |
| 265 | \\ nop | |
| 266 | ); | |
| 267 | asm volatile ( | |
| 268 | \\ t 0x6d | |
| 266 | 269 | : |
| 267 | 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 | } |
| 270 | 273 | |
| 271 | 274 | pub 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 | 22 | /// Represents an ELF TLS variant. |
| 23 | 23 | /// |
| 24 | 24 | /// 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 | 27 | /// The location of the DTV does not actually matter. For simplicity, we put it in the TLS area, but |
| 28 | 28 | /// there is no actual ABI requirement that it reside there. |
| ... | ... | @@ -480,17 +480,17 @@ pub fn getThreadPointer() usize { |
| 480 | 480 | }; |
| 481 | 481 | } |
| 482 | 482 | |
| 483 | fn computeAreaDesc(phdrs: []elf.Phdr) void { | |
| 483 | fn computeAreaDesc(phdrs: []elf.ElfN.Phdr) void { | |
| 484 | 484 | @setRuntimeSafety(false); |
| 485 | 485 | @disableInstrumentation(); |
| 486 | 486 | |
| 487 | var tls_phdr: ?*elf.Phdr = null; | |
| 487 | var tls_phdr: ?*elf.ElfN.Phdr = null; | |
| 488 | 488 | var img_base: usize = 0; |
| 489 | 489 | |
| 490 | 490 | for (phdrs) |*phdr| { |
| 491 | switch (phdr.p_type) { | |
| 492 | elf.PT_PHDR => img_base = @intFromPtr(phdrs.ptr) - phdr.p_vaddr, | |
| 493 | elf.PT_TLS => tls_phdr = phdr, | |
| 491 | switch (phdr.type) { | |
| 492 | .PHDR => img_base = @intFromPtr(phdrs.ptr) - phdr.vaddr, | |
| 493 | .TLS => tls_phdr = phdr, | |
| 494 | 494 | else => {}, |
| 495 | 495 | } |
| 496 | 496 | } |
| ... | ... | @@ -500,12 +500,12 @@ fn computeAreaDesc(phdrs: []elf.Phdr) void { |
| 500 | 500 | var block_size: usize = undefined; |
| 501 | 501 | |
| 502 | 502 | if (tls_phdr) |phdr| { |
| 503 | align_factor = phdr.p_align; | |
| 503 | align_factor = phdr.@"align"; | |
| 504 | 504 | |
| 505 | // The effective size in memory is represented by `p_memsz`; the length of the data stored | |
| 506 | // in the `PT_TLS` segment is `p_filesz` and may be less than the former. | |
| 507 | block_init = @as([*]u8, @ptrFromInt(img_base + phdr.p_vaddr))[0..phdr.p_filesz]; | |
| 508 | block_size = phdr.p_memsz; | |
| 505 | // The effective size in memory is represented by `memsz`; the length of the data stored | |
| 506 | // in the `PT.TLS` segment is `filesz` and may be less than the former. | |
| 507 | block_init = @as([*]u8, @ptrFromInt(img_base + phdr.vaddr))[0..phdr.filesz]; | |
| 508 | block_size = phdr.memsz; | |
| 509 | 509 | } else { |
| 510 | 510 | align_factor = @alignOf(usize); |
| 511 | 511 | |
| ... | ... | @@ -651,7 +651,7 @@ var main_thread_area_buffer: [0x1000]u8 align(page_size_min) = undefined; |
| 651 | 651 | |
| 652 | 652 | /// Computes the layout of the static TLS area, allocates the area, initializes all of its fields, |
| 653 | 653 | /// and assigns the architecture-specific value to the TP register. |
| 654 | pub fn initStatic(phdrs: []elf.Phdr) void { | |
| 654 | pub fn initStatic(phdrs: []elf.ElfN.Phdr) void { | |
| 655 | 655 | @setRuntimeSafety(false); |
| 656 | 656 | @disableInstrumentation(); |
| 657 | 657 | |
| ... | ... | @@ -726,12 +726,14 @@ comptime { |
| 726 | 726 | // function for the GD and LD models. This function is unlikely to actually be used, since |
| 727 | 727 | // the linker should be able to relax every TLS access to the LE model and therefore |
| 728 | 728 | // eliminate all calls to this function, but that isn't guaranteed. |
| 729 | _ = struct { | |
| 729 | const Fns = struct { | |
| 730 | 730 | const TlsIndex = switch (native_arch) { |
| 731 | 731 | .x86_64 => extern struct { module: u64, offset: u64 }, // Even for x32... |
| 732 | 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 | 737 | assert(ti.module == 1); // The executable's module ID is always 1 |
| 736 | 738 | const tp = getThreadPointer(); |
| 737 | 739 | const block: [*]u8 = switch (current_variant) { |
| ... | ... | @@ -743,6 +745,25 @@ comptime { |
| 743 | 745 | }; |
| 744 | 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 | 19 | i += 1; |
| 20 | 20 | ph_addr += eh.e_phentsize; |
| 21 | 21 | }) { |
| 22 | const this_ph = @as(*elf.Phdr, @ptrFromInt(ph_addr)); | |
| 23 | switch (this_ph.p_type) { | |
| 22 | const this_ph = @as(*elf.ElfN.Phdr, @ptrFromInt(ph_addr)); | |
| 23 | switch (this_ph.type) { | |
| 24 | 24 | // 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 | 26 | // Wrapping operations are used on this line as well as subsequent calculations relative to base |
| 27 | 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, | |
| 29 | elf.PT_DYNAMIC => maybe_dynv = @as([*]usize, @ptrFromInt(vdso_addr + this_ph.p_offset)), | |
| 28 | .LOAD => base = vdso_addr +% this_ph.offset -% this_ph.vaddr, | |
| 29 | .DYNAMIC => maybe_dynv = @as([*]usize, @ptrFromInt(vdso_addr + this_ph.offset)), | |
| 30 | 30 | else => {}, |
| 31 | 31 | } |
| 32 | 32 | } |
lib/std/pie.zig+3-3| ... | ... | @@ -293,7 +293,7 @@ inline fn getDynamicSymbol() [*]const elf.Dyn { |
| 293 | 293 | }; |
| 294 | 294 | } |
| 295 | 295 | |
| 296 | pub fn relocate(phdrs: []const elf.Phdr) void { | |
| 296 | pub fn relocate(phdrs: []const elf.ElfN.Phdr) void { | |
| 297 | 297 | @setRuntimeSafety(false); |
| 298 | 298 | @disableInstrumentation(); |
| 299 | 299 | |
| ... | ... | @@ -303,8 +303,8 @@ pub fn relocate(phdrs: []const elf.Phdr) void { |
| 303 | 303 | // the theoretical load addresses for the `_DYNAMIC` symbol. |
| 304 | 304 | const base_addr = base: { |
| 305 | 305 | for (phdrs) |*phdr| { |
| 306 | if (phdr.p_type != elf.PT_DYNAMIC) continue; | |
| 307 | break :base @intFromPtr(dynv) - phdr.p_vaddr; | |
| 306 | if (phdr.type != .DYNAMIC) continue; | |
| 307 | break :base @intFromPtr(dynv) - phdr.vaddr; | |
| 308 | 308 | } |
| 309 | 309 | // This is not supposed to happen for well-formed binaries. |
| 310 | 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 | 75 | // Count how many libraries are loaded |
| 76 | 76 | counter.* += @as(usize, 1); |
| 77 | 77 | |
| 78 | // The image should contain at least a PT_LOAD segment | |
| 78 | // The image should contain at least a PT.LOAD segment | |
| 79 | 79 | if (info.phnum < 1) return error.MissingPtLoadSegment; |
| 80 | 80 | |
| 81 | 81 | // 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 | 100 | }; |
| 101 | 101 | |
| 102 | 102 | /// POSIX function which gets a uid from username. |
| 103 | pub fn getUserInfo(name: []const u8) !UserInfo { | |
| 103 | pub fn getUserInfo(io: Io, name: []const u8) !UserInfo { | |
| 104 | 104 | return switch (native_os) { |
| 105 | 105 | .linux, |
| 106 | 106 | .driverkit, |
| ... | ... | @@ -116,7 +116,7 @@ pub fn getUserInfo(name: []const u8) !UserInfo { |
| 116 | 116 | .haiku, |
| 117 | 117 | .illumos, |
| 118 | 118 | .serenity, |
| 119 | => posixGetUserInfo(name), | |
| 119 | => posixGetUserInfo(io, name), | |
| 120 | 120 | else => @compileError("Unsupported OS"), |
| 121 | 121 | }; |
| 122 | 122 | } |
| ... | ... | @@ -127,7 +127,7 @@ pub fn posixGetUserInfo(io: Io, name: []const u8) !UserInfo { |
| 127 | 127 | const file = try Io.Dir.openFileAbsolute(io, "/etc/passwd", .{}); |
| 128 | 128 | defer file.close(io); |
| 129 | 129 | var buffer: [4096]u8 = undefined; |
| 130 | var file_reader = file.reader(&buffer); | |
| 130 | var file_reader = file.reader(io, &buffer); | |
| 131 | 131 | return posixGetUserInfoPasswdStream(name, &file_reader.interface) catch |err| switch (err) { |
| 132 | 132 | error.ReadFailed => return file_reader.err.?, |
| 133 | 133 | error.EndOfStream => return error.UserNotFound, |
| ... | ... | @@ -644,7 +644,7 @@ pub fn totalSystemMemory() TotalSystemMemoryError!u64 { |
| 644 | 644 | /// leaks can be accurate. In release builds, this calls `exit` with code zero, |
| 645 | 645 | /// and does not return. |
| 646 | 646 | pub fn cleanExit(io: Io) void { |
| 647 | if (builtin.mode == .Debug) return; | |
| 647 | if (builtin.mode == .debug) return; | |
| 648 | 648 | _ = io.lockStderr(&.{}, .no_color) catch {}; |
| 649 | 649 | exit(0); |
| 650 | 650 | } |
| ... | ... | @@ -809,7 +809,7 @@ pub fn abort() noreturn { |
| 809 | 809 | // even when linking libc on Windows we use our own abort implementation. |
| 810 | 810 | // See https://github.com/ziglang/zig/issues/2071 for more details. |
| 811 | 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 | 813 | @breakpoint(); |
| 814 | 814 | } |
| 815 | 815 | windows.ntdll.RtlExitUserProcess(3); |
lib/std/process/Args.zig+1-1| ... | ... | @@ -752,7 +752,7 @@ pub fn IteratorGeneral(comptime options: IteratorGeneralOptions) type { |
| 752 | 752 | start: usize = 0, |
| 753 | 753 | end: usize = 0, |
| 754 | 754 | |
| 755 | pub const Self = @This(); | |
| 755 | const Self = @This(); | |
| 756 | 756 | |
| 757 | 757 | pub const InitError = error{OutOfMemory}; |
| 758 | 758 |
lib/std/sort/block.zig+1-1| ... | ... | @@ -103,7 +103,7 @@ pub fn block( |
| 103 | 103 | context: anytype, |
| 104 | 104 | comptime lessThanFn: fn (@TypeOf(context), lhs: T, rhs: T) bool, |
| 105 | 105 | ) void { |
| 106 | const lessThan = if (builtin.mode == .Debug) struct { | |
| 106 | const lessThan = if (builtin.mode == .debug) struct { | |
| 107 | 107 | fn lessThan(ctx: @TypeOf(context), lhs: T, rhs: T) bool { |
| 108 | 108 | const lt = lessThanFn(ctx, lhs, rhs); |
| 109 | 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 | 97 | }, |
| 98 | 98 | .int, .float => return asm ( |
| 99 | 99 | \\%ret = OpSpecConstant %ty $default_value |
| 100 | \\ OpDecorate %ret SpecId $spec_id" | |
| 100 | \\ OpDecorate %ret SpecId $spec_id | |
| 101 | 101 | : [ret] "" (-> T), |
| 102 | 102 | : [ty] "t" (T), |
| 103 | 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 | 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 | }; |
| 594 | 594 | |
| 595 | 595 | // 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 | 621 | std.os.linux.tls.initStatic(phdrs); |
| 622 | 622 | } |
| 623 | 623 | |
| 624 | // The way Linux executables represent stack size is via the PT_GNU_STACK | |
| 624 | // The way Linux executables represent stack size is via the PT.GNU_STACK | |
| 625 | 625 | // program header. However the kernel does not recognize it; it always gives 8 MiB. |
| 626 | 626 | // Here we look for the stack size in our program headers and use setrlimit |
| 627 | 627 | // to ask for more stack space. |
| ... | ... | @@ -645,19 +645,19 @@ fn posixCallMainAndExit(argc_argv_ptr: [*]usize) callconv(.c) noreturn { |
| 645 | 645 | std.process.exit(callMainWithArgs(argc, argv, envp)); |
| 646 | 646 | } |
| 647 | 647 | |
| 648 | fn expandStackSize(phdrs: []elf.Phdr) void { | |
| 648 | fn expandStackSize(phdrs: []elf.ElfN.Phdr) void { | |
| 649 | 649 | @disableInstrumentation(); |
| 650 | 650 | for (phdrs) |*phdr| { |
| 651 | switch (phdr.p_type) { | |
| 652 | elf.PT_GNU_STACK => { | |
| 653 | if (phdr.p_memsz == 0) break; | |
| 654 | assert(phdr.p_memsz % std.heap.page_size_min == 0); | |
| 651 | switch (phdr.type) { | |
| 652 | .GNU_STACK => { | |
| 653 | if (phdr.memsz == 0) break; | |
| 654 | assert(phdr.memsz % std.heap.page_size_min == 0); | |
| 655 | 655 | |
| 656 | 656 | // Silently fail if we are unable to get limits. |
| 657 | 657 | const limits = std.posix.getrlimit(.STACK) catch break; |
| 658 | 658 | |
| 659 | 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); | |
| 661 | 661 | |
| 662 | 662 | if (wanted_stack_size > limits.cur) { |
| 663 | 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 | 702 | .linux => { |
| 703 | 703 | const at_phdr = std.c.getauxval(elf.AT_PHDR); |
| 704 | 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 | 706 | expandStackSize(phdrs); |
| 707 | 707 | }, |
| 708 | 708 | .windows => { |
| ... | ... | @@ -742,8 +742,8 @@ fn mainWithoutEnv(c_argc: c_int, c_argv: [*][*:0]c_char) callconv(.c) c_int { |
| 742 | 742 | const bad_main_ret = "expected return type of main to be 'void', '!void', 'noreturn', 'u8', or '!u8'"; |
| 743 | 743 | |
| 744 | 744 | const use_safe_allocator = !is_wasm and switch (builtin.mode) { |
| 745 | .Debug, .ReleaseSafe => true, | |
| 746 | .ReleaseFast, .ReleaseSmall => !builtin.link_libc and builtin.single_threaded, // Also not ideal. | |
| 745 | .debug, .safe => true, | |
| 746 | .fast, .small => !builtin.link_libc and builtin.single_threaded, // Also not ideal. | |
| 747 | 747 | }; |
| 748 | 748 | var safe_allocator: std.heap.SafeAllocator = .init(std.heap.page_allocator, .{}); |
| 749 | 749 |
lib/std/std.zig+2-2| ... | ... | @@ -162,7 +162,7 @@ pub const Options = struct { |
| 162 | 162 | /// This enables `std.http.Client` to log ssl secrets to the file specified by the SSLKEYLOGFILE |
| 163 | 163 | /// env var. Creating such a log file allows other programs with access to that file to decrypt |
| 164 | 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, | |
| 166 | 166 | |
| 167 | 167 | side_channels_mitigations: crypto.SideChannelsMitigations = crypto.default_side_channels_mitigations, |
| 168 | 168 | |
| ... | ... | @@ -192,7 +192,7 @@ pub const Options = struct { |
| 192 | 192 | /// If this happens the fix is to add the error code to the corresponding |
| 193 | 193 | /// switch expression, possibly introduce a new error in the error set, and |
| 194 | 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 | 196 | .stage2_llvm, .stage2_x86_64 => true, |
| 197 | 197 | else => false, |
| 198 | 198 | }, |
lib/std/tar/Writer.zig+1-1| ... | ... | @@ -312,7 +312,7 @@ pub const Header = extern struct { |
| 312 | 312 | |
| 313 | 313 | // add as much to prefix as you can, must split at / |
| 314 | 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 | 316 | @memcpy(w.prefix[prefix_pos..][0..sep_pos], sub_path[0..sep_pos]); |
| 317 | 317 | if ((sub_path.len - sep_pos - 1) > max_name) return error.NameTooLong; |
| 318 | 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 | 474 | defer root.cleanup(); |
| 475 | 475 | try testing.expectError( |
| 476 | 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 | ); |
| 479 | 479 | |
| 480 | 480 | // Unpack with strip_components = 0 should pass |
| 481 | 481 | r = .fixed(data); |
| 482 | 482 | var root2 = std.testing.tmpDir(.{}); |
| 483 | 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 | } |
| 486 | 486 | |
| 487 | 487 | test "case sensitivity" { |
| ... | ... | @@ -501,7 +501,7 @@ test "case sensitivity" { |
| 501 | 501 | var root = std.testing.tmpDir(.{}); |
| 502 | 502 | defer root.cleanup(); |
| 503 | 503 | |
| 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 | 505 | // on case insensitive fs we fail on overwrite existing file |
| 506 | 506 | try testing.expectEqual(error.PathAlreadyExists, err); |
| 507 | 507 | return; |
lib/std/testing.zig+1-1| ... | ... | @@ -999,7 +999,7 @@ test "expectEqualDeep composite type" { |
| 999 | 999 | } |
| 1000 | 1000 | |
| 1001 | 1001 | fn 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 | 1003 | line_begin + 1 |
| 1004 | 1004 | else |
| 1005 | 1005 | 0; |
lib/std/testing/Smith.zig+2-2| ... | ... | @@ -52,7 +52,7 @@ pub inline fn baselineWeights(T: type) []const Weight { |
| 52 | 52 | .bool, .int, .float => i: { |
| 53 | 53 | // Reject types that don't have a fixed bitsize (esp. usize) |
| 54 | 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 | 56 | isize, usize, |
| 57 | 57 | c_char, c_longdouble, |
| 58 | 58 | c_short, c_ushort, |
| ... | ... | @@ -708,7 +708,7 @@ fn constructInput(comptime values: []const union(enum) { |
| 708 | 708 | } |
| 709 | 709 | |
| 710 | 710 | test value { |
| 711 | if (@import("builtin").zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 711 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 712 | 712 | |
| 713 | 713 | const S = struct { |
| 714 | 714 | v: void = {}, |
lib/std/unicode.zig+35| ... | ... | @@ -425,6 +425,15 @@ pub const Utf8Iterator = struct { |
| 425 | 425 | |
| 426 | 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 | }; |
| 429 | 438 | |
| 430 | 439 | pub fn utf16IsHighSurrogate(c: u16) bool { |
| ... | ... | @@ -768,6 +777,9 @@ fn testMiscInvalidUtf8() !void { |
| 768 | 777 | test "utf8 iterator peeking" { |
| 769 | 778 | try comptime testUtf8Peeking(); |
| 770 | 779 | try testUtf8Peeking(); |
| 780 | ||
| 781 | comptime try testUtf8PeekCodepoint(); | |
| 782 | try testUtf8PeekCodepoint(); | |
| 771 | 783 | } |
| 772 | 784 | |
| 773 | 785 | fn testUtf8Peeking() !void { |
| ... | ... | @@ -790,6 +802,20 @@ fn testUtf8Peeking() !void { |
| 790 | 802 | try testing.expect(mem.eql(u8, &[_]u8{}, it.peek(1))); |
| 791 | 803 | } |
| 792 | 804 | |
| 805 | fn 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 | ||
| 793 | 819 | fn testError(bytes: []const u8, expected_err: anyerror) !void { |
| 794 | 820 | try testing.expectError(expected_err, testDecode(bytes)); |
| 795 | 821 | } |
| ... | ... | @@ -1758,6 +1784,15 @@ pub const Wtf8Iterator = struct { |
| 1758 | 1784 | |
| 1759 | 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 | }; |
| 1762 | 1797 | |
| 1763 | 1798 | pub 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 | 386 | efi_boot_service_driver, |
| 387 | 387 | efi_rom, |
| 388 | 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 | }; |
| 407 | 390 | |
| 408 | 391 | pub const CompressDebugSections = enum(u2) { none, zlib, zstd }; |
| ... | ... | @@ -562,8 +545,7 @@ pub fn stringEscape(bytes: []const u8, w: *Writer) Writer.Error!void { |
| 562 | 545 | '\t' => try w.writeAll("\\t"), |
| 563 | 546 | '\\' => try w.writeAll("\\\\"), |
| 564 | 547 | '"' => try w.writeAll("\\\""), |
| 565 | '\'' => try w.writeByte('\''), | |
| 566 | ' ', '!', '#'...'&', '('...'[', ']'...'~' => try w.writeByte(byte), | |
| 548 | ' ', '!', '#'...'[', ']'...'~' => try w.writeByte(byte), | |
| 567 | 549 | else => { |
| 568 | 550 | try w.writeAll("\\x"); |
| 569 | 551 | try w.printInt(byte, 16, .lower, .{ .width = 2, .fill = '0' }); |
| ... | ... | @@ -780,11 +762,11 @@ pub const EnvVar = enum { |
| 780 | 762 | ZIG_LIBC, |
| 781 | 763 | ZIG_BUILD_ERROR_STYLE, |
| 782 | 764 | ZIG_BUILD_MULTILINE_ERRORS, |
| 765 | ZIG_BUILD_SUMMARY, | |
| 783 | 766 | ZIG_VERBOSE_LINK, |
| 784 | 767 | ZIG_VERBOSE_CC, |
| 785 | 768 | ZIG_VERBOSE_CMD, |
| 786 | 769 | ZIG_DEBUG_CMD, |
| 787 | ZIG_DEBUG_MAKER, | |
| 788 | 770 | ZIG_IS_DETECTING_LIBC_PATHS, |
| 789 | 771 | ZIG_IS_AVOIDING_CALLING_ITSELF, |
| 790 | 772 | |
| ... | ... | @@ -1577,7 +1559,7 @@ pub fn resolvePath( |
| 1577 | 1559 | // Heuristic for a fast path: if no component is absolute and ".." never appears, we just need to resolve `paths`. |
| 1578 | 1560 | for (paths) |p| { |
| 1579 | 1561 | if (Dir.path.isAbsolute(p)) break; // absolute path |
| 1580 | if (mem.indexOf(u8, p, "..") != null) break; // may contain up-dir | |
| 1562 | if (mem.find(u8, p, "..") != null) break; // may contain up-dir | |
| 1581 | 1563 | } else { |
| 1582 | 1564 | // no absolute path, no "..". |
| 1583 | 1565 | const res = try Dir.path.resolve(gpa, paths); |
| ... | ... | @@ -1675,31 +1657,32 @@ pub fn buildExeSubprocess( |
| 1675 | 1657 | }; |
| 1676 | 1658 | defer child.kill(io); |
| 1677 | 1659 | |
| 1678 | var stderr_task = io.concurrent(readStreamAlloc, .{ gpa, io, child.stderr.?, .unlimited }) catch | |
| 1679 | @panic("TODO use multireader instead"); | |
| 1680 | defer if (stderr_task.cancel(io)) |slice| gpa.free(slice) else |_| {}; | |
| 1660 | var multi_reader_buffer: Io.File.MultiReader.Buffer(2) = undefined; | |
| 1661 | var multi_reader: Io.File.MultiReader = undefined; | |
| 1662 | multi_reader.init(gpa, io, multi_reader_buffer.toStreams(), &.{ child.stdout.?, child.stderr.? }); | |
| 1663 | defer multi_reader.deinit(); | |
| 1664 | const stdout = multi_reader.reader(0); | |
| 1665 | const stderr = multi_reader.reader(1); | |
| 1681 | 1666 | |
| 1682 | var stdout_buffer: [512]u8 = undefined; | |
| 1683 | var stdout_reader: Io.File.Reader = .initStreaming(child.stdout.?, io, &stdout_buffer); | |
| 1684 | const stdout = &stdout_reader.interface; | |
| 1667 | var stdin_buffer: [8]u8 = undefined; | |
| 1668 | var stdin_writer = child.stdin.?.writerStreaming(io, &stdin_buffer); | |
| 1685 | 1669 | |
| 1686 | { | |
| 1687 | var w = child.stdin.?.writer(io, &.{}); | |
| 1688 | w.interface.writeStruct(Client.Message.Header{ .tag = .update, .bytes_len = 0 }, .little) catch |err| switch (err) { | |
| 1689 | error.WriteFailed => { | |
| 1690 | log.err("{t} writing to command: {f}", .{ w.err.?, cmd }); | |
| 1691 | return error.AlreadyReported; | |
| 1692 | }, | |
| 1693 | }; | |
| 1694 | w.interface.writeStruct(Client.Message.Header{ .tag = .exit, .bytes_len = 0 }, .little) catch |err| switch (err) { | |
| 1695 | error.WriteFailed => { | |
| 1696 | log.err("{t} writing to command: {f}", .{ w.err.?, cmd }); | |
| 1697 | return error.AlreadyReported; | |
| 1698 | }, | |
| 1699 | }; | |
| 1700 | } | |
| 1670 | var client: Client = .{ | |
| 1671 | .in = stdout, | |
| 1672 | .out = &stdin_writer.interface, | |
| 1673 | }; | |
| 1701 | 1674 | |
| 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 | }; | |
| 1703 | 1686 | |
| 1704 | 1687 | var result: ?Cache.Path = null; |
| 1705 | 1688 | defer if (result) |r| gpa.free(r.sub_path); |
| ... | ... | @@ -1707,33 +1690,29 @@ pub fn buildExeSubprocess( |
| 1707 | 1690 | var result_error_bundle: ErrorBundle = .empty; |
| 1708 | 1691 | defer result_error_bundle.deinit(gpa); |
| 1709 | 1692 | |
| 1710 | var body_buffer: std.ArrayList(u8) = .empty; | |
| 1711 | defer body_buffer.deinit(gpa); | |
| 1712 | ||
| 1713 | 1693 | var received_fs_inputs = false; |
| 1714 | 1694 | var cache_hit = false; |
| 1715 | 1695 | |
| 1696 | var eos_err: error{EndOfStream}!void = {}; | |
| 1697 | ||
| 1716 | 1698 | while (true) { |
| 1717 | const header = stdout.takeStruct(Header, .little) catch |err| switch (err) { | |
| 1718 | error.ReadFailed => { | |
| 1719 | log.err("{t} reading from command: {f}", .{ stdout_reader.err.?, cmd }); | |
| 1720 | return error.AlreadyReported; | |
| 1721 | }, | |
| 1722 | error.EndOfStream => break, | |
| 1723 | }; | |
| 1724 | body_buffer.clearRetainingCapacity(); | |
| 1725 | stdout.appendExact(gpa, &body_buffer, header.bytes_len) catch |err| switch (err) { | |
| 1726 | error.ReadFailed => { | |
| 1727 | log.err("{t} reading from command: {f}", .{ stdout_reader.err.?, cmd }); | |
| 1728 | return error.AlreadyReported; | |
| 1699 | const header = client.receiveMessageWithMultiReader(&multi_reader, .none) catch |err| switch (err) { | |
| 1700 | error.Timeout => unreachable, | |
| 1701 | error.EndOfStream => |e| { | |
| 1702 | if (client.in.bufferedLen() == 0) break; | |
| 1703 | // Better to report the crash with stderr below, but we set | |
| 1704 | // this in case the child exits successfully while violating | |
| 1705 | // this protocol. | |
| 1706 | eos_err = e; | |
| 1707 | break; | |
| 1729 | 1708 | }, |
| 1730 | error.OutOfMemory => |e| return e, | |
| 1731 | error.EndOfStream => { | |
| 1732 | log.err("unexpected end of stream from command: {f}", .{cmd}); | |
| 1709 | error.Canceled, error.OutOfMemory => |e| return e, | |
| 1710 | else => |e| { | |
| 1711 | log.err("{t} reading from command: {f}", .{ e, cmd }); | |
| 1733 | 1712 | return error.AlreadyReported; |
| 1734 | 1713 | }, |
| 1735 | 1714 | }; |
| 1736 | const body = body_buffer.items; | |
| 1715 | const body = stdout.take(header.bytes_len) catch unreachable; | |
| 1737 | 1716 | |
| 1738 | 1717 | switch (header.tag) { |
| 1739 | 1718 | .zig_version => { |
| ... | ... | @@ -1784,16 +1763,15 @@ pub fn buildExeSubprocess( |
| 1784 | 1763 | } |
| 1785 | 1764 | } |
| 1786 | 1765 | |
| 1787 | const stderr_contents = stderr_task.await(io) catch |err| switch (err) { | |
| 1788 | error.Canceled, error.OutOfMemory => |e| return e, | |
| 1789 | else => |e| c: { | |
| 1790 | log.warn("{t} reading stderr from command: {f}", .{ e, cmd }); | |
| 1791 | break :c ""; | |
| 1792 | }, | |
| 1793 | }; | |
| 1766 | const stderr_contents = stderr.buffered(); | |
| 1794 | 1767 | if (stderr_contents.len > 0) |
| 1795 | 1768 | log.warn("unexpected stderr from {s} command:\n{s}", .{ options.argv[0], stderr_contents }); |
| 1796 | 1769 | |
| 1770 | eos_err catch { | |
| 1771 | log.err("unexpected end of stream from command: {f}", .{cmd}); | |
| 1772 | return error.AlreadyReported; | |
| 1773 | }; | |
| 1774 | ||
| 1797 | 1775 | // Send EOF to stdin. |
| 1798 | 1776 | child.stdin.?.close(io); |
| 1799 | 1777 | child.stdin = null; |
| ... | ... | @@ -1851,14 +1829,6 @@ pub fn buildExeSubprocess( |
| 1851 | 1829 | }; |
| 1852 | 1830 | } |
| 1853 | 1831 | |
| 1854 | fn 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 | ||
| 1862 | 1832 | test { |
| 1863 | 1833 | _ = Ast; |
| 1864 | 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 | 941 | } |
| 942 | 942 | |
| 943 | 943 | fn 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 | 945 | return error.WriteFailed; |
| 946 | 946 | } |
| 947 | 947 | |
| 948 | 948 | var n: usize = 0; |
| 949 | 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 | 951 | return error.WriteFailed; |
| 952 | 952 | } |
| 953 | 953 | n += v.len; |
| 954 | 954 | } |
| 955 | 955 | |
| 956 | 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 | 958 | return error.WriteFailed; |
| 959 | 959 | } |
| 960 | 960 | n += pattern.len * splat; |
| ... | ... | @@ -990,7 +990,7 @@ fn rendersMultiline(r: *const Render, node: Ast.Node.Index) error{OutOfMemory}!b |
| 990 | 990 | error.WriteFailed => return true, |
| 991 | 991 | }; |
| 992 | 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 | 994 | return true; |
| 995 | 995 | } |
| 996 | 996 | |
| ... | ... | @@ -2993,7 +2993,7 @@ fn hasMultilineString(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.Tok |
| 2993 | 2993 | /// Returns true if there exists a doc comment between the start |
| 2994 | 2994 | /// of token `start_token` and the start of token `end_token`. |
| 2995 | 2995 | fn hasDocComment(tree: Ast, start_token: Ast.TokenIndex, end_token: Ast.TokenIndex) bool { |
| 2996 | return std.mem.indexOfScalar( | |
| 2996 | return std.mem.findScalar( | |
| 2997 | 2997 | Token.Tag, |
| 2998 | 2998 | tree.tokens.items(.tag)[start_token..end_token], |
| 2999 | 2999 | .doc_comment, |
| ... | ... | @@ -3459,7 +3459,7 @@ const AutoIndentingStream = struct { |
| 3459 | 3459 | /// Sets current indentation level to be the same as that of the last pushSpace. |
| 3460 | 3460 | pub fn enableSpaceMode(ais: *AutoIndentingStream, space: Space) void { |
| 3461 | 3461 | if (ais.space_stack.items.len == 0) return; |
| 3462 | const curr = ais.space_stack.getLast().?; | |
| 3462 | const curr = ais.space_stack.last().?; | |
| 3463 | 3463 | if (curr.space != space) return; |
| 3464 | 3464 | ais.space_mode = curr.indent_count; |
| 3465 | 3465 | } |
| ... | ... | @@ -3470,7 +3470,7 @@ const AutoIndentingStream = struct { |
| 3470 | 3470 | |
| 3471 | 3471 | pub fn lastSpaceModeIndent(ais: *AutoIndentingStream) usize { |
| 3472 | 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 | } |
| 3475 | 3475 | |
| 3476 | 3476 | /// Push default indentation |
lib/std/zig/AstGen.zig+3-2| ... | ... | @@ -74,13 +74,13 @@ src_hasher: std.zig.SrcHasher, |
| 74 | 74 | const InnerError = error{ OutOfMemory, AnalysisFail }; |
| 75 | 75 | |
| 76 | 76 | fn 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 | 78 | try astgen.extra.ensureUnusedCapacity(astgen.gpa, field_count); |
| 79 | 79 | return addExtraAssumeCapacity(astgen, extra); |
| 80 | 80 | } |
| 81 | 81 | |
| 82 | 82 | fn 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 | 84 | const extra_index: u32 = @intCast(astgen.extra.items.len); |
| 85 | 85 | astgen.extra.items.len += field_count; |
| 86 | 86 | setExtra(astgen, extra_index, extra); |
| ... | ... | @@ -7453,6 +7453,7 @@ fn switchExpr( |
| 7453 | 7453 | const ident_name = try astgen.identAsString(ident_token); |
| 7454 | 7454 | const ident_name_str = tree.tokenSlice(ident_token); |
| 7455 | 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 | 7457 | break :scope &scratch_scope.base; |
| 7457 | 7458 | } |
| 7458 | 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 | const Client = @This(); | |
| 2 | ||
| 3 | const std = @import("std"); | |
| 4 | const Io = std.Io; | |
| 5 | const Allocator = std.mem.Allocator; | |
| 6 | const assert = std.debug.assert; | |
| 7 | const Configuration = std.Build.Configuration; | |
| 8 | const OutMessage = std.zig.Client.Message; | |
| 9 | const InMessage = std.zig.Server.Message; | |
| 10 | const Reader = Io.Reader; | |
| 11 | const Writer = Io.Writer; | |
| 12 | ||
| 13 | in: *Reader, | |
| 14 | out: *Writer, | |
| 15 | ||
| 1 | 16 | pub const Message = struct { |
| 2 | 17 | pub const Header = extern struct { |
| 3 | 18 | tag: Tag, |
| ... | ... | @@ -46,11 +61,120 @@ pub const Message = struct { |
| 46 | 61 | /// The message body has the same format as in Server. |
| 47 | 62 | new_fuzz_input, |
| 48 | 63 | |
| 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 | }; |
| 51 | 71 | |
| 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 | 86 | comptime { |
| 53 | const std = @import("std"); | |
| 54 | std.debug.assert(@sizeOf(std.Build.abi.fuzz.LimitKind) == 1); | |
| 87 | assert(@sizeOf(std.Build.abi.fuzz.LimitKind) == 1); | |
| 55 | 88 | } |
| 56 | 89 | }; |
| 90 | ||
| 91 | pub 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. | |
| 97 | pub 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! | |
| 120 | pub fn serveMessageHeader(c: *const Client, header: OutMessage.Header) Writer.Error!void { | |
| 121 | try c.out.writeStruct(header, .little); | |
| 122 | } | |
| 123 | ||
| 124 | pub 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 | ||
| 129 | pub 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 | ||
| 138 | pub 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 | ||
| 164 | pub 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 | 43 | pub fn parse(allocator: Allocator, io: Io, libc_file: []const u8, target: *const std.Target) !LibCInstallation { |
| 44 | 44 | var self: LibCInstallation = .{}; |
| 45 | 45 | |
| 46 | const field_names = comptime std.meta.fieldNames(LibCInstallation); | |
| 46 | const field_names = @typeInfo(LibCInstallation).@"struct".field_names; | |
| 47 | 47 | const FoundKey = struct { |
| 48 | 48 | found: bool, |
| 49 | 49 | allocated: ?[]u8, |
lib/std/zig/Server.zig+66-19| ... | ... | @@ -1,12 +1,8 @@ |
| 1 | 1 | const Server = @This(); |
| 2 | 2 | |
| 3 | const builtin = @import("builtin"); | |
| 4 | ||
| 5 | 3 | const std = @import("std"); |
| 6 | 4 | const Allocator = std.mem.Allocator; |
| 7 | 5 | const assert = std.debug.assert; |
| 8 | const native_endian = builtin.target.cpu.arch.endian(); | |
| 9 | const need_bswap = native_endian != .little; | |
| 10 | 6 | const Cache = std.Build.Cache; |
| 11 | 7 | const OutMessage = std.zig.Server.Message; |
| 12 | 8 | const InMessage = std.zig.Client.Message; |
| ... | ... | @@ -16,6 +12,14 @@ const Writer = std.Io.Writer; |
| 16 | 12 | in: *Reader, |
| 17 | 13 | out: *Writer, |
| 18 | 14 | |
| 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`. | |
| 21 | pub const build_system_version: u32 = 1; | |
| 22 | ||
| 19 | 23 | pub const Message = struct { |
| 20 | 24 | pub const Header = extern struct { |
| 21 | 25 | tag: Tag, |
| ... | ... | @@ -70,9 +74,62 @@ pub const Message = struct { |
| 70 | 74 | /// Body is a TimeReport. |
| 71 | 75 | time_report, |
| 72 | 76 | |
| 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 | }; |
| 75 | 100 | |
| 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 | 133 | pub const PathPrefix = enum(u8) { |
| 77 | 134 | cwd, |
| 78 | 135 | zig_lib, |
| ... | ... | @@ -140,21 +197,6 @@ pub const Message = struct { |
| 140 | 197 | }; |
| 141 | 198 | }; |
| 142 | 199 | |
| 143 | pub const Options = struct { | |
| 144 | in: *Reader, | |
| 145 | out: *Writer, | |
| 146 | zig_version: []const u8, | |
| 147 | }; | |
| 148 | ||
| 149 | pub 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 | ||
| 158 | 200 | pub fn receiveMessage(s: *Server) !InMessage.Header { |
| 159 | 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 | 225 | try s.out.writeStruct(header, .little); |
| 184 | 226 | } |
| 185 | 227 | |
| 228 | pub 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 | ||
| 186 | 233 | pub fn serveU32Message(s: *const Server, tag: OutMessage.Tag, int: u32) !void { |
| 187 | 234 | try serveMessageHeader(s, .{ |
| 188 | 235 | .tag = tag, |
lib/std/zig/WindowsSdk.zig+4-4| ... | ... | @@ -891,7 +891,7 @@ const MsvcLibDir = struct { |
| 891 | 891 | |
| 892 | 892 | lib_dir_buf.appendSliceAssumeCapacity(installation_path); |
| 893 | 893 | |
| 894 | if (!Dir.path.isSep(lib_dir_buf.getLast().?)) { | |
| 894 | if (!Dir.path.isSep(lib_dir_buf.last().?)) { | |
| 895 | 895 | try lib_dir_buf.append('\\'); |
| 896 | 896 | } |
| 897 | 897 | const installation_path_with_trailing_sep_len = lib_dir_buf.items.len; |
| ... | ... | @@ -1064,7 +1064,7 @@ const MsvcLibDir = struct { |
| 1064 | 1064 | errdefer msvc_dir.deinit(); |
| 1065 | 1065 | |
| 1066 | 1066 | // 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(); | |
| 1068 | 1068 | |
| 1069 | 1069 | // Remove `\include` at the end of path |
| 1070 | 1070 | if (std.mem.endsWith(u8, msvc_dir.items, "\\include")) { |
| ... | ... | @@ -1108,7 +1108,7 @@ const MsvcLibDir = struct { |
| 1108 | 1108 | |
| 1109 | 1109 | try list.appendSlice(VS140COMNTOOLS); // C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Tools |
| 1110 | 1110 | // 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 | 1112 | list.shrinkRetainingCapacity(list.items.len - "\\Common7\\Tools".len); // C:\Program Files (x86)\Microsoft Visual Studio 14.0 |
| 1113 | 1113 | break :base_path list; |
| 1114 | 1114 | } |
| ... | ... | @@ -1131,7 +1131,7 @@ const MsvcLibDir = struct { |
| 1131 | 1131 | errdefer path.deinit(); |
| 1132 | 1132 | |
| 1133 | 1133 | // 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 | 1135 | break :base_path path; |
| 1136 | 1136 | } |
| 1137 | 1137 | return error.PathNotFound; |
lib/std/zig/Zir.zig+2-2| ... | ... | @@ -584,7 +584,7 @@ pub const Inst = struct { |
| 584 | 584 | /// containing the instruction. |
| 585 | 585 | /// Uses the `un_tok` union field. |
| 586 | 586 | ref, |
| 587 | /// Implements the dereference operand (`.*`). Checks that operand is a pointer | |
| 587 | /// Implements the dereference operator (`.*`). Checks that operand is a pointer | |
| 588 | 588 | /// that supports being directly dereferenced. |
| 589 | 589 | /// Uses the `un_node` union field. |
| 590 | 590 | deref, |
| ... | ... | @@ -2522,7 +2522,7 @@ pub const Inst = struct { |
| 2522 | 2522 | // bigger than expected. Note that in Debug builds, Zig is allowed |
| 2523 | 2523 | // to insert a secret field for safety checks. |
| 2524 | 2524 | comptime { |
| 2525 | if (builtin.mode != .Debug and builtin.mode != .ReleaseSafe) { | |
| 2525 | if (builtin.mode != .debug and builtin.mode != .safe) { | |
| 2526 | 2526 | assert(@sizeOf(Data) == 8); |
| 2527 | 2527 | } |
| 2528 | 2528 | } |
lib/std/zig/llvm/Builder.zig+1320-479| ... | ... | @@ -17,7 +17,7 @@ gpa: Allocator, |
| 17 | 17 | strip: bool, |
| 18 | 18 | |
| 19 | 19 | source_filename: String, |
| 20 | data_layout: String, | |
| 20 | data_layout: DataLayout, | |
| 21 | 21 | target_triple: String, |
| 22 | 22 | module_asm: std.ArrayList(u8), |
| 23 | 23 | |
| ... | ... | @@ -87,6 +87,455 @@ pub const Options = struct { |
| 87 | 87 | triple: []const u8 = &.{}, |
| 88 | 88 | }; |
| 89 | 89 | |
| 90 | pub 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 | ||
| 90 | 539 | pub const String = enum(u32) { |
| 91 | 540 | none = maxInt(u31), |
| 92 | 541 | empty, |
| ... | ... | @@ -142,8 +591,8 @@ pub const String = enum(u32) { |
| 142 | 591 | } |
| 143 | 592 | |
| 144 | 593 | fn fromIndex(index: ?usize) String { |
| 145 | return @fromBackingInt(@intCast(@as(u32, @intCast((index orelse return .none) + | |
| 146 | @backingInt(String.empty))))); | |
| 594 | return @fromBackingInt(@as(u32, @intCast((index orelse return .none) + | |
| 595 | @backingInt(String.empty)))); | |
| 147 | 596 | } |
| 148 | 597 | |
| 149 | 598 | fn toIndex(self: String) ?usize { |
| ... | ... | @@ -489,7 +938,10 @@ pub const Type = enum(u32) { |
| 489 | 938 | .double, .i64, .x86_mmx => 64, |
| 490 | 939 | .x86_fp80, .i80 => 80, |
| 491 | 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 | 946 | const item = builder.type_items.items[@backingInt(self)]; |
| 495 | 947 | return switch (item.tag) { |
| ... | ... | @@ -498,7 +950,9 @@ pub const Type = enum(u32) { |
| 498 | 950 | .vararg_function, |
| 499 | 951 | => unreachable, |
| 500 | 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 | 956 | .target => unreachable, |
| 503 | 957 | .vector, |
| 504 | 958 | .scalable_vector, |
| ... | ... | @@ -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 | }; |
| 935 | 1450 | |
| 936 | 1451 | pub const Attribute = union(Kind) { |
| 937 | 1452 | // Parameter Attributes |
| 938 | 1453 | zeroext, |
| 939 | 1454 | signext, |
| 1455 | noext, | |
| 940 | 1456 | inreg, |
| 941 | 1457 | byval: Type, |
| 942 | 1458 | byref: Type, |
| ... | ... | @@ -947,6 +1463,7 @@ pub const Attribute = union(Kind) { |
| 947 | 1463 | @"align": Alignment.Lazy, |
| 948 | 1464 | @"noalias", |
| 949 | 1465 | nocapture, |
| 1466 | captures: Captures, | |
| 950 | 1467 | nofree, |
| 951 | 1468 | nest, |
| 952 | 1469 | returned, |
| ... | ... | @@ -965,6 +1482,11 @@ pub const Attribute = union(Kind) { |
| 965 | 1482 | readnone, |
| 966 | 1483 | readonly, |
| 967 | 1484 | writeonly, |
| 1485 | writable, | |
| 1486 | initializes: []const [2]u64, | |
| 1487 | dead_on_unwind, | |
| 1488 | dead_on_return: ?u32, | |
| 1489 | range: [2]Constant, | |
| 968 | 1490 | |
| 969 | 1491 | // Function Attributes |
| 970 | 1492 | //alignstack: Alignment.Lazy, |
| ... | ... | @@ -974,7 +1496,7 @@ pub const Attribute = union(Kind) { |
| 974 | 1496 | builtin, |
| 975 | 1497 | cold, |
| 976 | 1498 | convergent, |
| 977 | disable_sanitizer_information, | |
| 1499 | disable_sanitizer_instrumentation, | |
| 978 | 1500 | fn_ret_thunk_extern, |
| 979 | 1501 | hot, |
| 980 | 1502 | inlinehint, |
| ... | ... | @@ -984,6 +1506,7 @@ pub const Attribute = union(Kind) { |
| 984 | 1506 | naked, |
| 985 | 1507 | nobuiltin, |
| 986 | 1508 | nocallback, |
| 1509 | nodivergencesource, | |
| 987 | 1510 | noduplicate, |
| 988 | 1511 | //nofree, |
| 989 | 1512 | noimplicitfloat, |
| ... | ... | @@ -1001,6 +1524,7 @@ pub const Attribute = union(Kind) { |
| 1001 | 1524 | nosanitize_bounds, |
| 1002 | 1525 | nosanitize_coverage, |
| 1003 | 1526 | null_pointer_is_valid, |
| 1527 | optdebug, | |
| 1004 | 1528 | optforfuzzing, |
| 1005 | 1529 | optnone, |
| 1006 | 1530 | optsize, |
| ... | ... | @@ -1012,23 +1536,23 @@ pub const Attribute = union(Kind) { |
| 1012 | 1536 | sanitize_thread, |
| 1013 | 1537 | sanitize_hwaddress, |
| 1014 | 1538 | sanitize_memtag, |
| 1539 | sanitize_realtime, | |
| 1540 | sanitize_realtime_blocking, | |
| 1541 | sanitize_alloc_token, | |
| 1015 | 1542 | speculative_load_hardening, |
| 1016 | 1543 | speculatable, |
| 1017 | 1544 | ssp, |
| 1018 | 1545 | sspstrong, |
| 1019 | 1546 | sspreq, |
| 1020 | 1547 | strictfp, |
| 1548 | denormal_fpenv, | |
| 1021 | 1549 | uwtable: UwTable, |
| 1022 | 1550 | nocf_check, |
| 1023 | 1551 | shadowcallstack, |
| 1024 | 1552 | mustprogress, |
| 1025 | 1553 | vscale_range: VScaleRange, |
| 1026 | ||
| 1027 | // Global Attributes | |
| 1028 | no_sanitize_address, | |
| 1029 | no_sanitize_hwaddress, | |
| 1030 | //sanitize_memtag, | |
| 1031 | sanitize_address_dyninit, | |
| 1554 | nooutline, | |
| 1555 | nocreateundeforpoison, | |
| 1032 | 1556 | |
| 1033 | 1557 | string: struct { kind: String, value: String }, |
| 1034 | 1558 | none: noreturn, |
| ... | ... | @@ -1045,100 +1569,11 @@ pub const Attribute = union(Kind) { |
| 1045 | 1569 | const storage = self.toStorage(builder); |
| 1046 | 1570 | if (storage.kind.toString()) |kind| return .{ .string = .{ |
| 1047 | 1571 | .kind = kind, |
| 1048 | .value = @fromBackingInt(@intCast(storage.value)), | |
| 1572 | .value = @fromBackingInt(storage.value), | |
| 1049 | 1573 | } } else return switch (storage.kind) { |
| 1050 | inline .zeroext, | |
| 1051 | .signext, | |
| 1052 | .inreg, | |
| 1053 | .byval, | |
| 1054 | .byref, | |
| 1055 | .preallocated, | |
| 1056 | .inalloca, | |
| 1057 | .sret, | |
| 1058 | .elementtype, | |
| 1059 | .@"align", | |
| 1060 | .@"noalias", | |
| 1061 | .nocapture, | |
| 1062 | .nofree, | |
| 1063 | .nest, | |
| 1064 | .returned, | |
| 1065 | .nonnull, | |
| 1066 | .dereferenceable, | |
| 1067 | .dereferenceable_or_null, | |
| 1068 | .swiftself, | |
| 1069 | .swiftasync, | |
| 1070 | .swifterror, | |
| 1071 | .immarg, | |
| 1072 | .noundef, | |
| 1073 | .nofpclass, | |
| 1074 | .alignstack, | |
| 1075 | .allocalign, | |
| 1076 | .allocptr, | |
| 1077 | .readnone, | |
| 1078 | .readonly, | |
| 1079 | .writeonly, | |
| 1080 | //.alignstack, | |
| 1081 | .allockind, | |
| 1082 | .allocsize, | |
| 1083 | .alwaysinline, | |
| 1084 | .builtin, | |
| 1085 | .cold, | |
| 1086 | .convergent, | |
| 1087 | .disable_sanitizer_information, | |
| 1088 | .fn_ret_thunk_extern, | |
| 1089 | .hot, | |
| 1090 | .inlinehint, | |
| 1091 | .jumptable, | |
| 1092 | .memory, | |
| 1093 | .minsize, | |
| 1094 | .naked, | |
| 1095 | .nobuiltin, | |
| 1096 | .nocallback, | |
| 1097 | .noduplicate, | |
| 1098 | //.nofree, | |
| 1099 | .noimplicitfloat, | |
| 1100 | .@"noinline", | |
| 1101 | .nomerge, | |
| 1102 | .nonlazybind, | |
| 1103 | .noprofile, | |
| 1104 | .skipprofile, | |
| 1105 | .noredzone, | |
| 1106 | .noreturn, | |
| 1107 | .norecurse, | |
| 1108 | .willreturn, | |
| 1109 | .nosync, | |
| 1110 | .nounwind, | |
| 1111 | .nosanitize_bounds, | |
| 1112 | .nosanitize_coverage, | |
| 1113 | .null_pointer_is_valid, | |
| 1114 | .optforfuzzing, | |
| 1115 | .optnone, | |
| 1116 | .optsize, | |
| 1117 | //.preallocated, | |
| 1118 | .returns_twice, | |
| 1119 | .safestack, | |
| 1120 | .sanitize_address, | |
| 1121 | .sanitize_memory, | |
| 1122 | .sanitize_thread, | |
| 1123 | .sanitize_hwaddress, | |
| 1124 | .sanitize_memtag, | |
| 1125 | .speculative_load_hardening, | |
| 1126 | .speculatable, | |
| 1127 | .ssp, | |
| 1128 | .sspstrong, | |
| 1129 | .sspreq, | |
| 1130 | .strictfp, | |
| 1131 | .uwtable, | |
| 1132 | .nocf_check, | |
| 1133 | .shadowcallstack, | |
| 1134 | .mustprogress, | |
| 1135 | .vscale_range, | |
| 1136 | .no_sanitize_address, | |
| 1137 | .no_sanitize_hwaddress, | |
| 1138 | .sanitize_address_dyninit, | |
| 1139 | => |kind| { | |
| 1574 | inline else => |kind| { | |
| 1140 | 1575 | const field_name, const field_type = comptime blk: { |
| 1141 | @setEvalBranchQuota(10_000); | |
| 1576 | @setEvalBranchQuota(12_000); | |
| 1142 | 1577 | const info = @typeInfo(Attribute).@"union"; |
| 1143 | 1578 | for (info.field_names, info.field_types) |field_name, field_type| { |
| 1144 | 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 | 1584 | return @unionInit(Attribute, field_name, switch (field_type) { |
| 1150 | 1585 | void => {}, |
| 1151 | 1586 | u32 => storage.value, |
| 1152 | Alignment.Lazy, String, Type, UwTable => @fromBackingInt(@intCast(storage.value)), | |
| 1153 | AllocKind, AllocSize, FpClass, Memory, VScaleRange => @bitCast(storage.value), | |
| 1587 | Alignment.Lazy, String, Type, UwTable => @fromBackingInt(storage.value), | |
| 1588 | AllocKind, AllocSize, Captures, FpClass, Memory, VScaleRange => @bitCast(storage.value), | |
| 1154 | 1589 | else => @compileError("bad payload type: " ++ field_name ++ ": " ++ |
| 1155 | 1590 | @typeName(field_type)), |
| 1156 | 1591 | }); |
| 1157 | 1592 | }, |
| 1158 | .string, .none => unreachable, | |
| 1159 | _ => unreachable, | |
| 1593 | .initializes, | |
| 1594 | .dead_on_return, | |
| 1595 | .range, | |
| 1596 | => @panic("TODO"), | |
| 1597 | .string, .none, _ => unreachable, | |
| 1160 | 1598 | }; |
| 1161 | 1599 | } |
| 1162 | 1600 | |
| ... | ... | @@ -1174,6 +1612,7 @@ pub const Attribute = union(Kind) { |
| 1174 | 1612 | switch (attribute) { |
| 1175 | 1613 | .zeroext, |
| 1176 | 1614 | .signext, |
| 1615 | .noext, | |
| 1177 | 1616 | .inreg, |
| 1178 | 1617 | .@"noalias", |
| 1179 | 1618 | .nocapture, |
| ... | ... | @@ -1191,11 +1630,13 @@ pub const Attribute = union(Kind) { |
| 1191 | 1630 | .readnone, |
| 1192 | 1631 | .readonly, |
| 1193 | 1632 | .writeonly, |
| 1633 | .writable, | |
| 1634 | .dead_on_unwind, | |
| 1194 | 1635 | .alwaysinline, |
| 1195 | 1636 | .builtin, |
| 1196 | 1637 | .cold, |
| 1197 | 1638 | .convergent, |
| 1198 | .disable_sanitizer_information, | |
| 1639 | .disable_sanitizer_instrumentation, | |
| 1199 | 1640 | .fn_ret_thunk_extern, |
| 1200 | 1641 | .hot, |
| 1201 | 1642 | .inlinehint, |
| ... | ... | @@ -1204,6 +1645,7 @@ pub const Attribute = union(Kind) { |
| 1204 | 1645 | .naked, |
| 1205 | 1646 | .nobuiltin, |
| 1206 | 1647 | .nocallback, |
| 1648 | .nodivergencesource, | |
| 1207 | 1649 | .noduplicate, |
| 1208 | 1650 | .noimplicitfloat, |
| 1209 | 1651 | .@"noinline", |
| ... | ... | @@ -1220,6 +1662,7 @@ pub const Attribute = union(Kind) { |
| 1220 | 1662 | .nosanitize_bounds, |
| 1221 | 1663 | .nosanitize_coverage, |
| 1222 | 1664 | .null_pointer_is_valid, |
| 1665 | .optdebug, | |
| 1223 | 1666 | .optforfuzzing, |
| 1224 | 1667 | .optnone, |
| 1225 | 1668 | .optsize, |
| ... | ... | @@ -1230,18 +1673,21 @@ pub const Attribute = union(Kind) { |
| 1230 | 1673 | .sanitize_thread, |
| 1231 | 1674 | .sanitize_hwaddress, |
| 1232 | 1675 | .sanitize_memtag, |
| 1676 | .sanitize_realtime, | |
| 1677 | .sanitize_realtime_blocking, | |
| 1678 | .sanitize_alloc_token, | |
| 1233 | 1679 | .speculative_load_hardening, |
| 1234 | 1680 | .speculatable, |
| 1235 | 1681 | .ssp, |
| 1236 | 1682 | .sspstrong, |
| 1237 | 1683 | .sspreq, |
| 1238 | 1684 | .strictfp, |
| 1685 | .denormal_fpenv, | |
| 1239 | 1686 | .nocf_check, |
| 1240 | 1687 | .shadowcallstack, |
| 1241 | 1688 | .mustprogress, |
| 1242 | .no_sanitize_address, | |
| 1243 | .no_sanitize_hwaddress, | |
| 1244 | .sanitize_address_dyninit, | |
| 1689 | .nooutline, | |
| 1690 | .nocreateundeforpoison, | |
| 1245 | 1691 | => try w.print(" {s}", .{@tagName(attribute)}), |
| 1246 | 1692 | .byval, |
| 1247 | 1693 | .byref, |
| ... | ... | @@ -1254,6 +1700,45 @@ pub const Attribute = union(Kind) { |
| 1254 | 1700 | .dereferenceable, |
| 1255 | 1701 | .dereferenceable_or_null, |
| 1256 | 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 | 1742 | .nofpclass => |fpclass| { |
| 1258 | 1743 | const Int = @typeInfo(FpClass).@"struct".backing_integer.?; |
| 1259 | 1744 | try w.print(" {s}(", .{@tagName(attribute)}); |
| ... | ... | @@ -1281,6 +1766,9 @@ pub const Attribute = union(Kind) { |
| 1281 | 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 | 1772 | .allockind => |allockind| { |
| 1285 | 1773 | try w.print(" {t}(\"", .{attribute}); |
| 1286 | 1774 | var any = false; |
| ... | ... | @@ -1344,100 +1832,109 @@ pub const Attribute = union(Kind) { |
| 1344 | 1832 | |
| 1345 | 1833 | pub const Kind = enum(u32) { |
| 1346 | 1834 | // Parameter Attributes |
| 1347 | zeroext = 34, | |
| 1348 | signext = 24, | |
| 1349 | inreg = 5, | |
| 1350 | byval = 3, | |
| 1351 | byref = 69, | |
| 1352 | preallocated = 65, | |
| 1353 | inalloca = 38, | |
| 1354 | sret = 29, // TODO: ? | |
| 1355 | elementtype = 77, | |
| 1356 | @"align" = 1, | |
| 1357 | @"noalias" = 9, | |
| 1358 | nocapture = 11, | |
| 1359 | nofree = 62, | |
| 1360 | nest = 8, | |
| 1361 | returned = 22, | |
| 1362 | nonnull = 39, | |
| 1363 | dereferenceable = 41, | |
| 1364 | dereferenceable_or_null = 42, | |
| 1365 | swiftself = 46, | |
| 1366 | swiftasync = 75, | |
| 1367 | swifterror = 47, | |
| 1368 | immarg = 60, | |
| 1369 | noundef = 68, | |
| 1370 | nofpclass = 87, | |
| 1371 | alignstack = 25, | |
| 1372 | allocalign = 80, | |
| 1373 | allocptr = 81, | |
| 1374 | readnone = 20, | |
| 1375 | readonly = 21, | |
| 1376 | writeonly = 52, | |
| 1835 | zeroext = @backingInt(ATTR_KIND.Z_EXT), | |
| 1836 | signext = @backingInt(ATTR_KIND.S_EXT), | |
| 1837 | noext = @backingInt(ATTR_KIND.NO_EXT), | |
| 1838 | inreg = @backingInt(ATTR_KIND.IN_REG), | |
| 1839 | byval = @backingInt(ATTR_KIND.BY_VAL), | |
| 1840 | byref = @backingInt(ATTR_KIND.BYREF), | |
| 1841 | preallocated = @backingInt(ATTR_KIND.PREALLOCATED), | |
| 1842 | inalloca = @backingInt(ATTR_KIND.IN_ALLOCA), | |
| 1843 | sret = @backingInt(ATTR_KIND.STRUCT_RET), | |
| 1844 | elementtype = @backingInt(ATTR_KIND.ELEMENTTYPE), | |
| 1845 | @"align" = @backingInt(ATTR_KIND.ALIGNMENT), | |
| 1846 | @"noalias" = @backingInt(ATTR_KIND.NO_ALIAS), | |
| 1847 | nocapture = @backingInt(ATTR_KIND.NO_CAPTURE), | |
| 1848 | captures = @backingInt(ATTR_KIND.CAPTURES), | |
| 1849 | nofree = @backingInt(ATTR_KIND.NOFREE), | |
| 1850 | nest = @backingInt(ATTR_KIND.NEST), | |
| 1851 | returned = @backingInt(ATTR_KIND.RETURNED), | |
| 1852 | nonnull = @backingInt(ATTR_KIND.NON_NULL), | |
| 1853 | dereferenceable = @backingInt(ATTR_KIND.DEREFERENCEABLE), | |
| 1854 | dereferenceable_or_null = @backingInt(ATTR_KIND.DEREFERENCEABLE_OR_NULL), | |
| 1855 | swiftself = @backingInt(ATTR_KIND.SWIFT_SELF), | |
| 1856 | swiftasync = @backingInt(ATTR_KIND.SWIFT_ASYNC), | |
| 1857 | swifterror = @backingInt(ATTR_KIND.SWIFT_ERROR), | |
| 1858 | immarg = @backingInt(ATTR_KIND.IMMARG), | |
| 1859 | noundef = @backingInt(ATTR_KIND.NOUNDEF), | |
| 1860 | nofpclass = @backingInt(ATTR_KIND.NOFPCLASS), | |
| 1861 | alignstack = @backingInt(ATTR_KIND.STACK_ALIGNMENT), | |
| 1862 | allocalign = @backingInt(ATTR_KIND.ALLOC_ALIGN), | |
| 1863 | allocptr = @backingInt(ATTR_KIND.ALLOCATED_POINTER), | |
| 1864 | readnone = @backingInt(ATTR_KIND.READ_NONE), | |
| 1865 | readonly = @backingInt(ATTR_KIND.READ_ONLY), | |
| 1866 | writeonly = @backingInt(ATTR_KIND.WRITEONLY), | |
| 1867 | writable = @backingInt(ATTR_KIND.WRITABLE), | |
| 1868 | initializes = @backingInt(ATTR_KIND.INITIALIZES), | |
| 1869 | dead_on_unwind = @backingInt(ATTR_KIND.DEAD_ON_UNWIND), | |
| 1870 | dead_on_return = @backingInt(ATTR_KIND.DEAD_ON_RETURN), | |
| 1871 | range = @backingInt(ATTR_KIND.RANGE), | |
| 1377 | 1872 | |
| 1378 | 1873 | // Function Attributes |
| 1379 | //alignstack, | |
| 1380 | allockind = 82, | |
| 1381 | allocsize = 51, | |
| 1382 | alwaysinline = 2, | |
| 1383 | builtin = 35, | |
| 1384 | cold = 36, | |
| 1385 | convergent = 43, | |
| 1386 | disable_sanitizer_information = 78, | |
| 1387 | fn_ret_thunk_extern = 84, | |
| 1388 | hot = 72, | |
| 1389 | inlinehint = 4, | |
| 1390 | jumptable = 40, | |
| 1391 | memory = 86, | |
| 1392 | minsize = 6, | |
| 1393 | naked = 7, | |
| 1394 | nobuiltin = 10, | |
| 1395 | nocallback = 71, | |
| 1396 | noduplicate = 12, | |
| 1397 | //nofree, | |
| 1398 | noimplicitfloat = 13, | |
| 1399 | @"noinline" = 14, | |
| 1400 | nomerge = 66, | |
| 1401 | nonlazybind = 15, | |
| 1402 | noprofile = 73, | |
| 1403 | skipprofile = 85, | |
| 1404 | noredzone = 16, | |
| 1405 | noreturn = 17, | |
| 1406 | norecurse = 48, | |
| 1407 | willreturn = 61, | |
| 1408 | nosync = 63, | |
| 1409 | nounwind = 18, | |
| 1410 | nosanitize_bounds = 79, | |
| 1411 | nosanitize_coverage = 76, | |
| 1412 | null_pointer_is_valid = 67, | |
| 1413 | optforfuzzing = 57, | |
| 1414 | optnone = 37, | |
| 1415 | optsize = 19, | |
| 1416 | //preallocated, | |
| 1417 | returns_twice = 23, | |
| 1418 | safestack = 44, | |
| 1419 | sanitize_address = 30, | |
| 1420 | sanitize_memory = 32, | |
| 1421 | sanitize_thread = 31, | |
| 1422 | sanitize_hwaddress = 55, | |
| 1423 | sanitize_memtag = 64, | |
| 1424 | speculative_load_hardening = 59, | |
| 1425 | speculatable = 53, | |
| 1426 | ssp = 26, | |
| 1427 | sspstrong = 28, | |
| 1428 | sspreq = 27, | |
| 1429 | strictfp = 54, | |
| 1430 | uwtable = 33, | |
| 1431 | nocf_check = 56, | |
| 1432 | shadowcallstack = 58, | |
| 1433 | mustprogress = 70, | |
| 1434 | vscale_range = 74, | |
| 1435 | ||
| 1436 | // Global Attributes | |
| 1437 | no_sanitize_address = 100, | |
| 1438 | no_sanitize_hwaddress = 101, | |
| 1439 | //sanitize_memtag, | |
| 1440 | sanitize_address_dyninit = 102, | |
| 1874 | //alignstack = @intFromEnum(ATTR_KIND.STACK_ALIGNMENT), | |
| 1875 | allockind = @backingInt(ATTR_KIND.ALLOC_KIND), | |
| 1876 | allocsize = @backingInt(ATTR_KIND.ALLOC_SIZE), | |
| 1877 | alwaysinline = @backingInt(ATTR_KIND.ALWAYS_INLINE), | |
| 1878 | builtin = @backingInt(ATTR_KIND.BUILTIN), | |
| 1879 | cold = @backingInt(ATTR_KIND.COLD), | |
| 1880 | convergent = @backingInt(ATTR_KIND.CONVERGENT), | |
| 1881 | disable_sanitizer_instrumentation = @backingInt(ATTR_KIND.DISABLE_SANITIZER_INSTRUMENTATION), | |
| 1882 | fn_ret_thunk_extern = @backingInt(ATTR_KIND.FNRETTHUNK_EXTERN), | |
| 1883 | hot = @backingInt(ATTR_KIND.HOT), | |
| 1884 | inlinehint = @backingInt(ATTR_KIND.INLINE_HINT), | |
| 1885 | jumptable = @backingInt(ATTR_KIND.JUMP_TABLE), | |
| 1886 | memory = @backingInt(ATTR_KIND.MEMORY), | |
| 1887 | minsize = @backingInt(ATTR_KIND.MIN_SIZE), | |
| 1888 | naked = @backingInt(ATTR_KIND.NAKED), | |
| 1889 | nobuiltin = @backingInt(ATTR_KIND.NO_BUILTIN), | |
| 1890 | nocallback = @backingInt(ATTR_KIND.NO_CALLBACK), | |
| 1891 | nodivergencesource = @backingInt(ATTR_KIND.NO_DIVERGENCE_SOURCE), | |
| 1892 | noduplicate = @backingInt(ATTR_KIND.NO_DUPLICATE), | |
| 1893 | //nofree = @intFromEnum(ATTR_KIND.NOFREE), | |
| 1894 | noimplicitfloat = @backingInt(ATTR_KIND.NO_IMPLICIT_FLOAT), | |
| 1895 | @"noinline" = @backingInt(ATTR_KIND.NO_INLINE), | |
| 1896 | nomerge = @backingInt(ATTR_KIND.NO_MERGE), | |
| 1897 | nonlazybind = @backingInt(ATTR_KIND.NON_LAZY_BIND), | |
| 1898 | noprofile = @backingInt(ATTR_KIND.NO_PROFILE), | |
| 1899 | skipprofile = @backingInt(ATTR_KIND.SKIP_PROFILE), | |
| 1900 | noredzone = @backingInt(ATTR_KIND.NO_RED_ZONE), | |
| 1901 | noreturn = @backingInt(ATTR_KIND.NO_RETURN), | |
| 1902 | norecurse = @backingInt(ATTR_KIND.NO_RECURSE), | |
| 1903 | willreturn = @backingInt(ATTR_KIND.WILLRETURN), | |
| 1904 | nosync = @backingInt(ATTR_KIND.NOSYNC), | |
| 1905 | nounwind = @backingInt(ATTR_KIND.NO_UNWIND), | |
| 1906 | nosanitize_bounds = @backingInt(ATTR_KIND.NO_SANITIZE_BOUNDS), | |
| 1907 | nosanitize_coverage = @backingInt(ATTR_KIND.NO_SANITIZE_COVERAGE), | |
| 1908 | null_pointer_is_valid = @backingInt(ATTR_KIND.NULL_POINTER_IS_VALID), | |
| 1909 | optdebug = @backingInt(ATTR_KIND.OPTIMIZE_FOR_DEBUGGING), | |
| 1910 | optforfuzzing = @backingInt(ATTR_KIND.OPT_FOR_FUZZING), | |
| 1911 | optnone = @backingInt(ATTR_KIND.OPTIMIZE_NONE), | |
| 1912 | optsize = @backingInt(ATTR_KIND.OPTIMIZE_FOR_SIZE), | |
| 1913 | //preallocated = @intFromEnum(ATTR_KIND.PREALLOCATED), | |
| 1914 | returns_twice = @backingInt(ATTR_KIND.RETURNS_TWICE), | |
| 1915 | safestack = @backingInt(ATTR_KIND.SAFESTACK), | |
| 1916 | sanitize_address = @backingInt(ATTR_KIND.SANITIZE_ADDRESS), | |
| 1917 | sanitize_memory = @backingInt(ATTR_KIND.SANITIZE_MEMORY), | |
| 1918 | sanitize_thread = @backingInt(ATTR_KIND.SANITIZE_THREAD), | |
| 1919 | sanitize_hwaddress = @backingInt(ATTR_KIND.SANITIZE_HWADDRESS), | |
| 1920 | sanitize_memtag = @backingInt(ATTR_KIND.SANITIZE_MEMTAG), | |
| 1921 | sanitize_realtime = @backingInt(ATTR_KIND.SANITIZE_REALTIME), | |
| 1922 | sanitize_realtime_blocking = @backingInt(ATTR_KIND.SANITIZE_REALTIME_BLOCKING), | |
| 1923 | sanitize_alloc_token = @backingInt(ATTR_KIND.SANITIZE_ALLOC_TOKEN), | |
| 1924 | speculative_load_hardening = @backingInt(ATTR_KIND.SPECULATIVE_LOAD_HARDENING), | |
| 1925 | speculatable = @backingInt(ATTR_KIND.SPECULATABLE), | |
| 1926 | ssp = @backingInt(ATTR_KIND.STACK_PROTECT), | |
| 1927 | sspstrong = @backingInt(ATTR_KIND.STACK_PROTECT_STRONG), | |
| 1928 | sspreq = @backingInt(ATTR_KIND.STACK_PROTECT_REQ), | |
| 1929 | strictfp = @backingInt(ATTR_KIND.STRICT_FP), | |
| 1930 | denormal_fpenv = @backingInt(ATTR_KIND.DENORMAL_FPENV), | |
| 1931 | uwtable = @backingInt(ATTR_KIND.UW_TABLE), | |
| 1932 | nocf_check = @backingInt(ATTR_KIND.NOCF_CHECK), | |
| 1933 | shadowcallstack = @backingInt(ATTR_KIND.SHADOWCALLSTACK), | |
| 1934 | mustprogress = @backingInt(ATTR_KIND.MUSTPROGRESS), | |
| 1935 | vscale_range = @backingInt(ATTR_KIND.VSCALE_RANGE), | |
| 1936 | nooutline = @backingInt(ATTR_KIND.NOOUTLINE), | |
| 1937 | nocreateundeforpoison = @backingInt(ATTR_KIND.NO_CREATE_UNDEF_OR_POISON), | |
| 1441 | 1938 | |
| 1442 | 1939 | string = maxInt(u31), |
| 1443 | 1940 | none = maxInt(u32), |
| ... | ... | @@ -1447,16 +1944,128 @@ pub const Attribute = union(Kind) { |
| 1447 | 1944 | |
| 1448 | 1945 | pub fn fromString(str: String) Kind { |
| 1449 | 1946 | assert(!str.isAnon()); |
| 1450 | const kind: Kind = @fromBackingInt(@intCast(@backingInt(str))); | |
| 1947 | const kind: Kind = @fromBackingInt(@backingInt(str)); | |
| 1451 | 1948 | assert(kind != .none); |
| 1452 | 1949 | return kind; |
| 1453 | 1950 | } |
| 1454 | 1951 | |
| 1455 | 1952 | fn toString(self: Kind) ?String { |
| 1456 | 1953 | assert(self != .none); |
| 1457 | const str: String = @fromBackingInt(@intCast(@backingInt(self))); | |
| 1954 | const str: String = @fromBackingInt(@backingInt(self)); | |
| 1458 | 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 | }; |
| 1461 | 2070 | |
| 1462 | 2071 | pub const FpClass = packed struct(u32) { |
| ... | ... | @@ -1506,6 +2115,29 @@ pub const Attribute = union(Kind) { |
| 1506 | 2115 | pub const pnorm = FpClass{ .positive_normal = true }; |
| 1507 | 2116 | }; |
| 1508 | 2117 | |
| 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 | 2141 | pub const AllocKind = packed struct(u32) { |
| 1510 | 2142 | alloc: bool, |
| 1511 | 2143 | realloc: bool, |
| ... | ... | @@ -1582,9 +2214,13 @@ pub const Attribute = union(Kind) { |
| 1582 | 2214 | void => 0, |
| 1583 | 2215 | u32 => value, |
| 1584 | 2216 | Alignment.Lazy, String, Type, UwTable => @backingInt(value), |
| 1585 | AllocKind, AllocSize, FpClass, Memory, VScaleRange => @bitCast(value), | |
| 1586 | else => @compileError("bad payload type: " ++ @tagName(tag) ++ @typeName(@TypeOf(value))), | |
| 2217 | AllocKind, AllocSize, Captures, FpClass, Memory, VScaleRange => @bitCast(value), | |
| 2218 | else => @compileError("bad payload type: " ++ @tagName(tag) ++ ": " ++ @typeName(@TypeOf(value))), | |
| 1587 | 2219 | } }, |
| 2220 | .initializes, | |
| 2221 | .dead_on_return, | |
| 2222 | .range, | |
| 2223 | => @panic("TODO"), | |
| 1588 | 2224 | .string => |string_attr| .{ |
| 1589 | 2225 | .kind = Kind.fromString(string_attr.kind), |
| 1590 | 2226 | .value = @backingInt(string_attr.value), |
| ... | ... | @@ -1907,87 +2543,87 @@ pub const AddrSpace = enum(u24) { |
| 1907 | 2543 | |
| 1908 | 2544 | // See llvm/lib/Target/X86/X86.h |
| 1909 | 2545 | pub const x86 = struct { |
| 1910 | pub const gs: AddrSpace = @fromBackingInt(@intCast(256)); | |
| 1911 | pub const fs: AddrSpace = @fromBackingInt(@intCast(257)); | |
| 1912 | pub const ss: AddrSpace = @fromBackingInt(@intCast(258)); | |
| 2546 | pub const gs: AddrSpace = @fromBackingInt(256); | |
| 2547 | pub const fs: AddrSpace = @fromBackingInt(257); | |
| 2548 | pub const ss: AddrSpace = @fromBackingInt(258); | |
| 1913 | 2549 | |
| 1914 | pub const ptr32_sptr: AddrSpace = @fromBackingInt(@intCast(270)); | |
| 1915 | pub const ptr32_uptr: AddrSpace = @fromBackingInt(@intCast(271)); | |
| 1916 | pub const ptr64: AddrSpace = @fromBackingInt(@intCast(272)); | |
| 2550 | pub const ptr32_sptr: AddrSpace = @fromBackingInt(270); | |
| 2551 | pub const ptr32_uptr: AddrSpace = @fromBackingInt(271); | |
| 2552 | pub const ptr64: AddrSpace = @fromBackingInt(272); | |
| 1917 | 2553 | }; |
| 1918 | 2554 | pub const x86_64 = x86; |
| 1919 | 2555 | |
| 1920 | 2556 | // See llvm/lib/Target/AVR/AVR.h |
| 1921 | 2557 | pub const avr = struct { |
| 1922 | pub const data: AddrSpace = @fromBackingInt(@intCast(0)); | |
| 1923 | pub const program: AddrSpace = @fromBackingInt(@intCast(1)); | |
| 1924 | pub const program1: AddrSpace = @fromBackingInt(@intCast(2)); | |
| 1925 | pub const program2: AddrSpace = @fromBackingInt(@intCast(3)); | |
| 1926 | pub const program3: AddrSpace = @fromBackingInt(@intCast(4)); | |
| 1927 | pub const program4: AddrSpace = @fromBackingInt(@intCast(5)); | |
| 1928 | pub const program5: AddrSpace = @fromBackingInt(@intCast(6)); | |
| 2558 | pub const data: AddrSpace = @fromBackingInt(0); | |
| 2559 | pub const program: AddrSpace = @fromBackingInt(1); | |
| 2560 | pub const program1: AddrSpace = @fromBackingInt(2); | |
| 2561 | pub const program2: AddrSpace = @fromBackingInt(3); | |
| 2562 | pub const program3: AddrSpace = @fromBackingInt(4); | |
| 2563 | pub const program4: AddrSpace = @fromBackingInt(5); | |
| 2564 | pub const program5: AddrSpace = @fromBackingInt(6); | |
| 1929 | 2565 | }; |
| 1930 | 2566 | |
| 1931 | 2567 | // See llvm/lib/Target/NVPTX/NVPTX.h |
| 1932 | 2568 | pub const nvptx = struct { |
| 1933 | pub const generic: AddrSpace = @fromBackingInt(@intCast(0)); | |
| 1934 | pub const global: AddrSpace = @fromBackingInt(@intCast(1)); | |
| 1935 | pub const constant: AddrSpace = @fromBackingInt(@intCast(2)); | |
| 1936 | pub const shared: AddrSpace = @fromBackingInt(@intCast(3)); | |
| 1937 | pub const param: AddrSpace = @fromBackingInt(@intCast(4)); | |
| 1938 | pub const local: AddrSpace = @fromBackingInt(@intCast(5)); | |
| 2569 | pub const generic: AddrSpace = @fromBackingInt(0); | |
| 2570 | pub const global: AddrSpace = @fromBackingInt(1); | |
| 2571 | pub const constant: AddrSpace = @fromBackingInt(2); | |
| 2572 | pub const shared: AddrSpace = @fromBackingInt(3); | |
| 2573 | pub const param: AddrSpace = @fromBackingInt(4); | |
| 2574 | pub const local: AddrSpace = @fromBackingInt(5); | |
| 1939 | 2575 | }; |
| 1940 | 2576 | |
| 1941 | 2577 | // See llvm/lib/Target/AMDGPU/AMDGPU.h |
| 1942 | 2578 | pub const amdgpu = struct { |
| 1943 | pub const flat: AddrSpace = @fromBackingInt(@intCast(0)); | |
| 1944 | pub const global: AddrSpace = @fromBackingInt(@intCast(1)); | |
| 1945 | pub const region: AddrSpace = @fromBackingInt(@intCast(2)); | |
| 1946 | pub const local: AddrSpace = @fromBackingInt(@intCast(3)); | |
| 1947 | pub const constant: AddrSpace = @fromBackingInt(@intCast(4)); | |
| 1948 | pub const private: AddrSpace = @fromBackingInt(@intCast(5)); | |
| 1949 | pub const constant_32bit: AddrSpace = @fromBackingInt(@intCast(6)); | |
| 1950 | pub const buffer_fat_pointer: AddrSpace = @fromBackingInt(@intCast(7)); | |
| 1951 | pub const buffer_resource: AddrSpace = @fromBackingInt(@intCast(8)); | |
| 1952 | pub const buffer_strided_pointer: AddrSpace = @fromBackingInt(@intCast(9)); | |
| 1953 | pub const param_d: AddrSpace = @fromBackingInt(@intCast(6)); | |
| 1954 | pub const param_i: AddrSpace = @fromBackingInt(@intCast(7)); | |
| 1955 | pub const constant_buffer_0: AddrSpace = @fromBackingInt(@intCast(8)); | |
| 1956 | pub const constant_buffer_1: AddrSpace = @fromBackingInt(@intCast(9)); | |
| 1957 | pub const constant_buffer_2: AddrSpace = @fromBackingInt(@intCast(10)); | |
| 1958 | pub const constant_buffer_3: AddrSpace = @fromBackingInt(@intCast(11)); | |
| 1959 | pub const constant_buffer_4: AddrSpace = @fromBackingInt(@intCast(12)); | |
| 1960 | pub const constant_buffer_5: AddrSpace = @fromBackingInt(@intCast(13)); | |
| 1961 | pub const constant_buffer_6: AddrSpace = @fromBackingInt(@intCast(14)); | |
| 1962 | pub const constant_buffer_7: AddrSpace = @fromBackingInt(@intCast(15)); | |
| 1963 | pub const constant_buffer_8: AddrSpace = @fromBackingInt(@intCast(16)); | |
| 1964 | pub const constant_buffer_9: AddrSpace = @fromBackingInt(@intCast(17)); | |
| 1965 | pub const constant_buffer_10: AddrSpace = @fromBackingInt(@intCast(18)); | |
| 1966 | pub const constant_buffer_11: AddrSpace = @fromBackingInt(@intCast(19)); | |
| 1967 | pub const constant_buffer_12: AddrSpace = @fromBackingInt(@intCast(20)); | |
| 1968 | pub const constant_buffer_13: AddrSpace = @fromBackingInt(@intCast(21)); | |
| 1969 | pub const constant_buffer_14: AddrSpace = @fromBackingInt(@intCast(22)); | |
| 1970 | pub const constant_buffer_15: AddrSpace = @fromBackingInt(@intCast(23)); | |
| 1971 | pub const streamout_register: AddrSpace = @fromBackingInt(@intCast(128)); | |
| 2579 | pub const flat: AddrSpace = @fromBackingInt(0); | |
| 2580 | pub const global: AddrSpace = @fromBackingInt(1); | |
| 2581 | pub const region: AddrSpace = @fromBackingInt(2); | |
| 2582 | pub const local: AddrSpace = @fromBackingInt(3); | |
| 2583 | pub const constant: AddrSpace = @fromBackingInt(4); | |
| 2584 | pub const private: AddrSpace = @fromBackingInt(5); | |
| 2585 | pub const constant_32bit: AddrSpace = @fromBackingInt(6); | |
| 2586 | pub const buffer_fat_pointer: AddrSpace = @fromBackingInt(7); | |
| 2587 | pub const buffer_resource: AddrSpace = @fromBackingInt(8); | |
| 2588 | pub const buffer_strided_pointer: AddrSpace = @fromBackingInt(9); | |
| 2589 | pub const param_d: AddrSpace = @fromBackingInt(6); | |
| 2590 | pub const param_i: AddrSpace = @fromBackingInt(7); | |
| 2591 | pub const constant_buffer_0: AddrSpace = @fromBackingInt(8); | |
| 2592 | pub const constant_buffer_1: AddrSpace = @fromBackingInt(9); | |
| 2593 | pub const constant_buffer_2: AddrSpace = @fromBackingInt(10); | |
| 2594 | pub const constant_buffer_3: AddrSpace = @fromBackingInt(11); | |
| 2595 | pub const constant_buffer_4: AddrSpace = @fromBackingInt(12); | |
| 2596 | pub const constant_buffer_5: AddrSpace = @fromBackingInt(13); | |
| 2597 | pub const constant_buffer_6: AddrSpace = @fromBackingInt(14); | |
| 2598 | pub const constant_buffer_7: AddrSpace = @fromBackingInt(15); | |
| 2599 | pub const constant_buffer_8: AddrSpace = @fromBackingInt(16); | |
| 2600 | pub const constant_buffer_9: AddrSpace = @fromBackingInt(17); | |
| 2601 | pub const constant_buffer_10: AddrSpace = @fromBackingInt(18); | |
| 2602 | pub const constant_buffer_11: AddrSpace = @fromBackingInt(19); | |
| 2603 | pub const constant_buffer_12: AddrSpace = @fromBackingInt(20); | |
| 2604 | pub const constant_buffer_13: AddrSpace = @fromBackingInt(21); | |
| 2605 | pub const constant_buffer_14: AddrSpace = @fromBackingInt(22); | |
| 2606 | pub const constant_buffer_15: AddrSpace = @fromBackingInt(23); | |
| 2607 | pub const streamout_register: AddrSpace = @fromBackingInt(128); | |
| 1972 | 2608 | }; |
| 1973 | 2609 | |
| 1974 | 2610 | pub const spirv = struct { |
| 1975 | pub const function: AddrSpace = @fromBackingInt(@intCast(0)); | |
| 1976 | pub const cross_workgroup: AddrSpace = @fromBackingInt(@intCast(1)); | |
| 1977 | pub const uniform_constant: AddrSpace = @fromBackingInt(@intCast(2)); | |
| 1978 | pub const workgroup: AddrSpace = @fromBackingInt(@intCast(3)); | |
| 1979 | pub const generic: AddrSpace = @fromBackingInt(@intCast(4)); | |
| 1980 | pub const device_only_intel: AddrSpace = @fromBackingInt(@intCast(5)); | |
| 1981 | pub const host_only_intel: AddrSpace = @fromBackingInt(@intCast(6)); | |
| 1982 | pub const input: AddrSpace = @fromBackingInt(@intCast(7)); | |
| 2611 | pub const function: AddrSpace = @fromBackingInt(0); | |
| 2612 | pub const cross_workgroup: AddrSpace = @fromBackingInt(1); | |
| 2613 | pub const uniform_constant: AddrSpace = @fromBackingInt(2); | |
| 2614 | pub const workgroup: AddrSpace = @fromBackingInt(3); | |
| 2615 | pub const generic: AddrSpace = @fromBackingInt(4); | |
| 2616 | pub const device_only_intel: AddrSpace = @fromBackingInt(5); | |
| 2617 | pub const host_only_intel: AddrSpace = @fromBackingInt(6); | |
| 2618 | pub const input: AddrSpace = @fromBackingInt(7); | |
| 1983 | 2619 | }; |
| 1984 | 2620 | |
| 1985 | 2621 | // See llvm/include/llvm/CodeGen/WasmAddressSpaces.h |
| 1986 | 2622 | pub const wasm = struct { |
| 1987 | pub const default: AddrSpace = @fromBackingInt(@intCast(0)); | |
| 1988 | pub const variable: AddrSpace = @fromBackingInt(@intCast(1)); | |
| 1989 | pub const externref: AddrSpace = @fromBackingInt(@intCast(10)); | |
| 1990 | pub const funcref: AddrSpace = @fromBackingInt(@intCast(20)); | |
| 2623 | pub const default: AddrSpace = @fromBackingInt(0); | |
| 2624 | pub const variable: AddrSpace = @fromBackingInt(1); | |
| 2625 | pub const externref: AddrSpace = @fromBackingInt(10); | |
| 2626 | pub const funcref: AddrSpace = @fromBackingInt(20); | |
| 1991 | 2627 | }; |
| 1992 | 2628 | |
| 1993 | 2629 | pub fn format(addr_space: AddrSpace, w: *Writer) Writer.Error!void { |
| ... | ... | @@ -2030,7 +2666,7 @@ pub const Alignment = enum(u6) { |
| 2030 | 2666 | _, |
| 2031 | 2667 | |
| 2032 | 2668 | pub fn wrap(a: Alignment) Lazy { |
| 2033 | return @fromBackingInt(@intCast(@backingInt(a))); | |
| 2669 | return @fromBackingInt(@backingInt(a)); | |
| 2034 | 2670 | } |
| 2035 | 2671 | pub fn resolve(l: Lazy, b: *const Builder) Alignment { |
| 2036 | 2672 | return switch (@backingInt(l)) { |
| ... | ... | @@ -2061,11 +2697,18 @@ pub const Alignment = enum(u6) { |
| 2061 | 2697 | }; |
| 2062 | 2698 | } |
| 2063 | 2699 | |
| 2064 | /// Asserts that neither `a` nor `b` is `.default`. | |
| 2065 | pub fn max(a: Alignment, b: Alignment) Alignment { | |
| 2066 | assert(a != .default); | |
| 2067 | assert(b != .default); | |
| 2068 | return @fromBackingInt(@intCast(@max(@backingInt(a), @backingInt(b)))); | |
| 2700 | /// Asserts that neither `lhs` nor `rhs` is `.default`. | |
| 2701 | pub fn max(lhs: Alignment, rhs: Alignment) Alignment { | |
| 2702 | assert(lhs != .default); | |
| 2703 | assert(rhs != .default); | |
| 2704 | return @fromBackingInt(@max(@backingInt(lhs), @backingInt(rhs))); | |
| 2705 | } | |
| 2706 | ||
| 2707 | /// Asserts that neither `lhs` nor `rhs` is `.default`. | |
| 2708 | pub fn order(lhs: Alignment, rhs: Alignment) std.math.Order { | |
| 2709 | assert(lhs != .default); | |
| 2710 | assert(rhs != .default); | |
| 2711 | return std.math.order(@backingInt(lhs), @backingInt(rhs)); | |
| 2069 | 2712 | } |
| 2070 | 2713 | |
| 2071 | 2714 | pub fn toLlvm(self: Alignment) u6 { |
| ... | ... | @@ -2106,6 +2749,7 @@ pub const CallConv = enum(u10) { |
| 2106 | 2749 | tailcc, |
| 2107 | 2750 | cfguard_checkcc, |
| 2108 | 2751 | swifttailcc, |
| 2752 | preserve_nonecc, | |
| 2109 | 2753 | |
| 2110 | 2754 | x86_stdcallcc = 64, |
| 2111 | 2755 | x86_fastcallcc, |
| ... | ... | @@ -2174,6 +2818,7 @@ pub const CallConv = enum(u10) { |
| 2174 | 2818 | .tailcc, |
| 2175 | 2819 | .cfguard_checkcc, |
| 2176 | 2820 | .swifttailcc, |
| 2821 | .preserve_nonecc, | |
| 2177 | 2822 | .x86_stdcallcc, |
| 2178 | 2823 | .x86_fastcallcc, |
| 2179 | 2824 | .arm_apcscc, |
| ... | ... | @@ -2261,8 +2906,7 @@ pub const StrtabString = enum(u32) { |
| 2261 | 2906 | } |
| 2262 | 2907 | |
| 2263 | 2908 | fn fromIndex(index: ?usize) StrtabString { |
| 2264 | return @fromBackingInt(@intCast(@as(u32, @intCast((index orelse return .none) + | |
| 2265 | @backingInt(StrtabString.empty))))); | |
| 2909 | return @fromBackingInt(@intCast((index orelse return .none) + @backingInt(StrtabString.empty))); | |
| 2266 | 2910 | } |
| 2267 | 2911 | |
| 2268 | 2912 | fn toIndex(self: StrtabString) ?usize { |
| ... | ... | @@ -2318,7 +2962,7 @@ pub fn trailingStrtabString(self: *Builder) Allocator.Error!StrtabString { |
| 2318 | 2962 | } |
| 2319 | 2963 | |
| 2320 | 2964 | pub fn trailingStrtabStringAssumeCapacity(self: *Builder) StrtabString { |
| 2321 | const start = self.strtab_string_indices.getLast().?; | |
| 2965 | const start = self.strtab_string_indices.last().?; | |
| 2322 | 2966 | const bytes: []const u8 = self.strtab_string_bytes.items[start..]; |
| 2323 | 2967 | const gop = self.strtab_string_map.getOrPutAssumeCapacityAdapted(bytes, StrtabString.Adapter{ .builder = self }); |
| 2324 | 2968 | if (gop.found_existing) { |
| ... | ... | @@ -2398,7 +3042,7 @@ pub const Global = struct { |
| 2398 | 3042 | } |
| 2399 | 3043 | |
| 2400 | 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 | } |
| 2403 | 3047 | |
| 2404 | 3048 | pub fn toValue(global: Index) Value { |
| ... | ... | @@ -2526,7 +3170,7 @@ pub const Global = struct { |
| 2526 | 3170 | _ = builder.addGlobalAssumeCapacity(new_name, builder.globals.values()[index]); |
| 2527 | 3171 | builder.globals.swapRemoveAt(index); |
| 2528 | 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 | 3174 | if (builder.next_unnamed_global == old_name) return; |
| 2531 | 3175 | builder.getGlobal(builder.next_unnamed_global).?.renameAssumeCapacity(old_name, builder); |
| 2532 | 3176 | } |
| ... | ... | @@ -2539,7 +3183,7 @@ pub const Global = struct { |
| 2539 | 3183 | |
| 2540 | 3184 | fn replaceAssumeCapacity(self: Index, other: Index, builder: *Builder) void { |
| 2541 | 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 | 3187 | self.renameAssumeCapacity(builder.next_replaced_global, builder); |
| 2544 | 3188 | self.ptr(builder).kind = .{ .replaced = other.unwrap(builder) }; |
| 2545 | 3189 | } |
| ... | ... | @@ -2699,6 +3343,8 @@ pub const Intrinsic = enum { |
| 2699 | 3343 | smin, |
| 2700 | 3344 | umax, |
| 2701 | 3345 | umin, |
| 3346 | scmp, | |
| 3347 | ucmp, | |
| 2702 | 3348 | memcpy, |
| 2703 | 3349 | @"memcpy.inline", |
| 2704 | 3350 | memmove, |
| ... | ... | @@ -2708,10 +3354,21 @@ pub const Intrinsic = enum { |
| 2708 | 3354 | powi, |
| 2709 | 3355 | sin, |
| 2710 | 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 | 3368 | pow, |
| 2712 | 3369 | exp, |
| 2713 | exp10, | |
| 2714 | 3370 | exp2, |
| 3371 | exp10, | |
| 2715 | 3372 | ldexp, |
| 2716 | 3373 | frexp, |
| 2717 | 3374 | log, |
| ... | ... | @@ -2723,6 +3380,8 @@ pub const Intrinsic = enum { |
| 2723 | 3380 | maxnum, |
| 2724 | 3381 | minimum, |
| 2725 | 3382 | maximum, |
| 3383 | minimumnum, | |
| 3384 | maximumnum, | |
| 2726 | 3385 | copysign, |
| 2727 | 3386 | floor, |
| 2728 | 3387 | ceil, |
| ... | ... | @@ -2744,6 +3403,7 @@ pub const Intrinsic = enum { |
| 2744 | 3403 | cttz, |
| 2745 | 3404 | fshl, |
| 2746 | 3405 | fshr, |
| 3406 | clmul, | |
| 2747 | 3407 | |
| 2748 | 3408 | // Arithmetic with Overflow |
| 2749 | 3409 | @"sadd.with.overflow", |
| ... | ... | @@ -2904,21 +3564,21 @@ pub const Intrinsic = enum { |
| 2904 | 3564 | .{ .kind = .{ .type = .ptr } }, |
| 2905 | 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 | 3569 | .addressofreturnaddress = .{ |
| 2910 | 3570 | .ret_len = 1, |
| 2911 | 3571 | .params = &.{ |
| 2912 | 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 | 3576 | .sponentry = .{ |
| 2917 | 3577 | .ret_len = 1, |
| 2918 | 3578 | .params = &.{ |
| 2919 | 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 | 3583 | .frameaddress = .{ |
| 2924 | 3584 | .ret_len = 1, |
| ... | ... | @@ -2926,7 +3586,7 @@ pub const Intrinsic = enum { |
| 2926 | 3586 | .{ .kind = .overloaded }, |
| 2927 | 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 | 3591 | .prefetch = .{ |
| 2932 | 3592 | .ret_len = 0, |
| ... | ... | @@ -2936,14 +3596,14 @@ pub const Intrinsic = enum { |
| 2936 | 3596 | .{ .kind = .{ .type = .i32 }, .attrs = &.{.immarg} }, |
| 2937 | 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 | 3601 | .@"thread.pointer" = .{ |
| 2942 | 3602 | .ret_len = 1, |
| 2943 | 3603 | .params = &.{ |
| 2944 | 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 | }, |
| 2948 | 3608 | |
| 2949 | 3609 | .abs = .{ |
| ... | ... | @@ -2953,7 +3613,7 @@ pub const Intrinsic = enum { |
| 2953 | 3613 | .{ .kind = .{ .matches = 0 } }, |
| 2954 | 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 | 3618 | .smax = .{ |
| 2959 | 3619 | .ret_len = 1, |
| ... | ... | @@ -2962,7 +3622,7 @@ pub const Intrinsic = enum { |
| 2962 | 3622 | .{ .kind = .{ .matches = 0 } }, |
| 2963 | 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 | 3627 | .smin = .{ |
| 2968 | 3628 | .ret_len = 1, |
| ... | ... | @@ -2971,7 +3631,7 @@ pub const Intrinsic = enum { |
| 2971 | 3631 | .{ .kind = .{ .matches = 0 } }, |
| 2972 | 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 | 3636 | .umax = .{ |
| 2977 | 3637 | .ret_len = 1, |
| ... | ... | @@ -2980,7 +3640,7 @@ pub const Intrinsic = enum { |
| 2980 | 3640 | .{ .kind = .{ .matches = 0 } }, |
| 2981 | 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 | 3645 | .umin = .{ |
| 2986 | 3646 | .ret_len = 1, |
| ... | ... | @@ -2989,7 +3649,25 @@ pub const Intrinsic = enum { |
| 2989 | 3649 | .{ .kind = .{ .matches = 0 } }, |
| 2990 | 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 | 3672 | .memcpy = .{ |
| 2995 | 3673 | .ret_len = 0, |
| ... | ... | @@ -3047,7 +3725,7 @@ pub const Intrinsic = enum { |
| 3047 | 3725 | .{ .kind = .overloaded }, |
| 3048 | 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 | 3730 | .powi = .{ |
| 3053 | 3731 | .ret_len = 1, |
| ... | ... | @@ -3056,7 +3734,7 @@ pub const Intrinsic = enum { |
| 3056 | 3734 | .{ .kind = .{ .matches = 0 } }, |
| 3057 | 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 | 3739 | .sin = .{ |
| 3062 | 3740 | .ret_len = 1, |
| ... | ... | @@ -3064,7 +3742,7 @@ pub const Intrinsic = enum { |
| 3064 | 3742 | .{ .kind = .overloaded }, |
| 3065 | 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 | 3747 | .cos = .{ |
| 3070 | 3748 | .ret_len = 1, |
| ... | ... | @@ -3072,7 +3750,99 @@ pub const Intrinsic = enum { |
| 3072 | 3750 | .{ .kind = .overloaded }, |
| 3073 | 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 | 3847 | .pow = .{ |
| 3078 | 3848 | .ret_len = 1, |
| ... | ... | @@ -3081,7 +3851,7 @@ pub const Intrinsic = enum { |
| 3081 | 3851 | .{ .kind = .{ .matches = 0 } }, |
| 3082 | 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 | 3856 | .exp = .{ |
| 3087 | 3857 | .ret_len = 1, |
| ... | ... | @@ -3089,7 +3859,7 @@ pub const Intrinsic = enum { |
| 3089 | 3859 | .{ .kind = .overloaded }, |
| 3090 | 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 | 3864 | .exp2 = .{ |
| 3095 | 3865 | .ret_len = 1, |
| ... | ... | @@ -3097,7 +3867,7 @@ pub const Intrinsic = enum { |
| 3097 | 3867 | .{ .kind = .overloaded }, |
| 3098 | 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 | 3872 | .exp10 = .{ |
| 3103 | 3873 | .ret_len = 1, |
| ... | ... | @@ -3105,7 +3875,7 @@ pub const Intrinsic = enum { |
| 3105 | 3875 | .{ .kind = .overloaded }, |
| 3106 | 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 | 3880 | .ldexp = .{ |
| 3111 | 3881 | .ret_len = 1, |
| ... | ... | @@ -3114,7 +3884,7 @@ pub const Intrinsic = enum { |
| 3114 | 3884 | .{ .kind = .{ .matches = 0 } }, |
| 3115 | 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 | 3889 | .frexp = .{ |
| 3120 | 3890 | .ret_len = 2, |
| ... | ... | @@ -3123,7 +3893,7 @@ pub const Intrinsic = enum { |
| 3123 | 3893 | .{ .kind = .overloaded }, |
| 3124 | 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 | 3898 | .log = .{ |
| 3129 | 3899 | .ret_len = 1, |
| ... | ... | @@ -3131,7 +3901,7 @@ pub const Intrinsic = enum { |
| 3131 | 3901 | .{ .kind = .overloaded }, |
| 3132 | 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 | 3906 | .log10 = .{ |
| 3137 | 3907 | .ret_len = 1, |
| ... | ... | @@ -3139,7 +3909,7 @@ pub const Intrinsic = enum { |
| 3139 | 3909 | .{ .kind = .overloaded }, |
| 3140 | 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 | 3914 | .log2 = .{ |
| 3145 | 3915 | .ret_len = 1, |
| ... | ... | @@ -3147,7 +3917,7 @@ pub const Intrinsic = enum { |
| 3147 | 3917 | .{ .kind = .overloaded }, |
| 3148 | 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 | 3922 | .fma = .{ |
| 3153 | 3923 | .ret_len = 1, |
| ... | ... | @@ -3157,7 +3927,7 @@ pub const Intrinsic = enum { |
| 3157 | 3927 | .{ .kind = .{ .matches = 0 } }, |
| 3158 | 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 | 3932 | .fabs = .{ |
| 3163 | 3933 | .ret_len = 1, |
| ... | ... | @@ -3165,7 +3935,7 @@ pub const Intrinsic = enum { |
| 3165 | 3935 | .{ .kind = .overloaded }, |
| 3166 | 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 | 3940 | .minnum = .{ |
| 3171 | 3941 | .ret_len = 1, |
| ... | ... | @@ -3174,7 +3944,7 @@ pub const Intrinsic = enum { |
| 3174 | 3944 | .{ .kind = .{ .matches = 0 } }, |
| 3175 | 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 | 3949 | .maxnum = .{ |
| 3180 | 3950 | .ret_len = 1, |
| ... | ... | @@ -3183,7 +3953,7 @@ pub const Intrinsic = enum { |
| 3183 | 3953 | .{ .kind = .{ .matches = 0 } }, |
| 3184 | 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 | 3958 | .minimum = .{ |
| 3189 | 3959 | .ret_len = 1, |
| ... | ... | @@ -3192,7 +3962,7 @@ pub const Intrinsic = enum { |
| 3192 | 3962 | .{ .kind = .{ .matches = 0 } }, |
| 3193 | 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 | 3967 | .maximum = .{ |
| 3198 | 3968 | .ret_len = 1, |
| ... | ... | @@ -3201,7 +3971,25 @@ pub const Intrinsic = enum { |
| 3201 | 3971 | .{ .kind = .{ .matches = 0 } }, |
| 3202 | 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 | 3994 | .copysign = .{ |
| 3207 | 3995 | .ret_len = 1, |
| ... | ... | @@ -3210,7 +3998,7 @@ pub const Intrinsic = enum { |
| 3210 | 3998 | .{ .kind = .{ .matches = 0 } }, |
| 3211 | 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 | 4003 | .floor = .{ |
| 3216 | 4004 | .ret_len = 1, |
| ... | ... | @@ -3218,7 +4006,7 @@ pub const Intrinsic = enum { |
| 3218 | 4006 | .{ .kind = .overloaded }, |
| 3219 | 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 | 4011 | .ceil = .{ |
| 3224 | 4012 | .ret_len = 1, |
| ... | ... | @@ -3226,7 +4014,7 @@ pub const Intrinsic = enum { |
| 3226 | 4014 | .{ .kind = .overloaded }, |
| 3227 | 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 | 4019 | .trunc = .{ |
| 3232 | 4020 | .ret_len = 1, |
| ... | ... | @@ -3234,7 +4022,7 @@ pub const Intrinsic = enum { |
| 3234 | 4022 | .{ .kind = .overloaded }, |
| 3235 | 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 | 4027 | .rint = .{ |
| 3240 | 4028 | .ret_len = 1, |
| ... | ... | @@ -3242,7 +4030,7 @@ pub const Intrinsic = enum { |
| 3242 | 4030 | .{ .kind = .overloaded }, |
| 3243 | 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 | 4035 | .nearbyint = .{ |
| 3248 | 4036 | .ret_len = 1, |
| ... | ... | @@ -3250,7 +4038,7 @@ pub const Intrinsic = enum { |
| 3250 | 4038 | .{ .kind = .overloaded }, |
| 3251 | 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 | 4043 | .round = .{ |
| 3256 | 4044 | .ret_len = 1, |
| ... | ... | @@ -3258,7 +4046,7 @@ pub const Intrinsic = enum { |
| 3258 | 4046 | .{ .kind = .overloaded }, |
| 3259 | 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 | 4051 | .roundeven = .{ |
| 3264 | 4052 | .ret_len = 1, |
| ... | ... | @@ -3266,7 +4054,7 @@ pub const Intrinsic = enum { |
| 3266 | 4054 | .{ .kind = .overloaded }, |
| 3267 | 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 | 4059 | .lround = .{ |
| 3272 | 4060 | .ret_len = 1, |
| ... | ... | @@ -3274,7 +4062,7 @@ pub const Intrinsic = enum { |
| 3274 | 4062 | .{ .kind = .overloaded }, |
| 3275 | 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 | 4067 | .llround = .{ |
| 3280 | 4068 | .ret_len = 1, |
| ... | ... | @@ -3282,7 +4070,7 @@ pub const Intrinsic = enum { |
| 3282 | 4070 | .{ .kind = .overloaded }, |
| 3283 | 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 | 4075 | .lrint = .{ |
| 3288 | 4076 | .ret_len = 1, |
| ... | ... | @@ -3290,7 +4078,7 @@ pub const Intrinsic = enum { |
| 3290 | 4078 | .{ .kind = .overloaded }, |
| 3291 | 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 | 4083 | .llrint = .{ |
| 3296 | 4084 | .ret_len = 1, |
| ... | ... | @@ -3298,7 +4086,7 @@ pub const Intrinsic = enum { |
| 3298 | 4086 | .{ .kind = .overloaded }, |
| 3299 | 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 | }, |
| 3303 | 4091 | |
| 3304 | 4092 | .bitreverse = .{ |
| ... | ... | @@ -3307,7 +4095,7 @@ pub const Intrinsic = enum { |
| 3307 | 4095 | .{ .kind = .overloaded }, |
| 3308 | 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 | 4100 | .bswap = .{ |
| 3313 | 4101 | .ret_len = 1, |
| ... | ... | @@ -3315,7 +4103,7 @@ pub const Intrinsic = enum { |
| 3315 | 4103 | .{ .kind = .overloaded }, |
| 3316 | 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 | 4108 | .ctpop = .{ |
| 3321 | 4109 | .ret_len = 1, |
| ... | ... | @@ -3323,7 +4111,7 @@ pub const Intrinsic = enum { |
| 3323 | 4111 | .{ .kind = .overloaded }, |
| 3324 | 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 | 4116 | .ctlz = .{ |
| 3329 | 4117 | .ret_len = 1, |
| ... | ... | @@ -3332,7 +4120,7 @@ pub const Intrinsic = enum { |
| 3332 | 4120 | .{ .kind = .{ .matches = 0 } }, |
| 3333 | 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 | 4125 | .cttz = .{ |
| 3338 | 4126 | .ret_len = 1, |
| ... | ... | @@ -3341,7 +4129,7 @@ pub const Intrinsic = enum { |
| 3341 | 4129 | .{ .kind = .{ .matches = 0 } }, |
| 3342 | 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 | 4134 | .fshl = .{ |
| 3347 | 4135 | .ret_len = 1, |
| ... | ... | @@ -3351,7 +4139,7 @@ pub const Intrinsic = enum { |
| 3351 | 4139 | .{ .kind = .{ .matches = 0 } }, |
| 3352 | 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 | 4144 | .fshr = .{ |
| 3357 | 4145 | .ret_len = 1, |
| ... | ... | @@ -3361,7 +4149,16 @@ pub const Intrinsic = enum { |
| 3361 | 4149 | .{ .kind = .{ .matches = 0 } }, |
| 3362 | 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 | }, |
| 3366 | 4163 | |
| 3367 | 4164 | .@"sadd.with.overflow" = .{ |
| ... | ... | @@ -3372,7 +4169,7 @@ pub const Intrinsic = enum { |
| 3372 | 4169 | .{ .kind = .{ .matches = 0 } }, |
| 3373 | 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 | 4174 | .@"uadd.with.overflow" = .{ |
| 3378 | 4175 | .ret_len = 2, |
| ... | ... | @@ -3382,7 +4179,7 @@ pub const Intrinsic = enum { |
| 3382 | 4179 | .{ .kind = .{ .matches = 0 } }, |
| 3383 | 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 | 4184 | .@"ssub.with.overflow" = .{ |
| 3388 | 4185 | .ret_len = 2, |
| ... | ... | @@ -3392,7 +4189,7 @@ pub const Intrinsic = enum { |
| 3392 | 4189 | .{ .kind = .{ .matches = 0 } }, |
| 3393 | 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 | 4194 | .@"usub.with.overflow" = .{ |
| 3398 | 4195 | .ret_len = 2, |
| ... | ... | @@ -3402,7 +4199,7 @@ pub const Intrinsic = enum { |
| 3402 | 4199 | .{ .kind = .{ .matches = 0 } }, |
| 3403 | 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 | 4204 | .@"smul.with.overflow" = .{ |
| 3408 | 4205 | .ret_len = 2, |
| ... | ... | @@ -3412,7 +4209,7 @@ pub const Intrinsic = enum { |
| 3412 | 4209 | .{ .kind = .{ .matches = 0 } }, |
| 3413 | 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 | 4214 | .@"umul.with.overflow" = .{ |
| 3418 | 4215 | .ret_len = 2, |
| ... | ... | @@ -3422,7 +4219,7 @@ pub const Intrinsic = enum { |
| 3422 | 4219 | .{ .kind = .{ .matches = 0 } }, |
| 3423 | 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 | }, |
| 3427 | 4224 | |
| 3428 | 4225 | .@"sadd.sat" = .{ |
| ... | ... | @@ -3432,7 +4229,7 @@ pub const Intrinsic = enum { |
| 3432 | 4229 | .{ .kind = .{ .matches = 0 } }, |
| 3433 | 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 | 4234 | .@"uadd.sat" = .{ |
| 3438 | 4235 | .ret_len = 1, |
| ... | ... | @@ -3441,7 +4238,7 @@ pub const Intrinsic = enum { |
| 3441 | 4238 | .{ .kind = .{ .matches = 0 } }, |
| 3442 | 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 | 4243 | .@"ssub.sat" = .{ |
| 3447 | 4244 | .ret_len = 1, |
| ... | ... | @@ -3450,7 +4247,7 @@ pub const Intrinsic = enum { |
| 3450 | 4247 | .{ .kind = .{ .matches = 0 } }, |
| 3451 | 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 | 4252 | .@"usub.sat" = .{ |
| 3456 | 4253 | .ret_len = 1, |
| ... | ... | @@ -3459,7 +4256,7 @@ pub const Intrinsic = enum { |
| 3459 | 4256 | .{ .kind = .{ .matches = 0 } }, |
| 3460 | 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 | 4261 | .@"sshl.sat" = .{ |
| 3465 | 4262 | .ret_len = 1, |
| ... | ... | @@ -3468,7 +4265,7 @@ pub const Intrinsic = enum { |
| 3468 | 4265 | .{ .kind = .{ .matches = 0 } }, |
| 3469 | 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 | 4270 | .@"ushl.sat" = .{ |
| 3474 | 4271 | .ret_len = 1, |
| ... | ... | @@ -3477,7 +4274,7 @@ pub const Intrinsic = enum { |
| 3477 | 4274 | .{ .kind = .{ .matches = 0 } }, |
| 3478 | 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 | }, |
| 3482 | 4279 | |
| 3483 | 4280 | .@"smul.fix" = .{ |
| ... | ... | @@ -3488,7 +4285,7 @@ pub const Intrinsic = enum { |
| 3488 | 4285 | .{ .kind = .{ .matches = 0 } }, |
| 3489 | 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 | 4290 | .@"umul.fix" = .{ |
| 3494 | 4291 | .ret_len = 1, |
| ... | ... | @@ -3498,7 +4295,7 @@ pub const Intrinsic = enum { |
| 3498 | 4295 | .{ .kind = .{ .matches = 0 } }, |
| 3499 | 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 | 4300 | .@"smul.fix.sat" = .{ |
| 3504 | 4301 | .ret_len = 1, |
| ... | ... | @@ -3508,7 +4305,7 @@ pub const Intrinsic = enum { |
| 3508 | 4305 | .{ .kind = .{ .matches = 0 } }, |
| 3509 | 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 | 4310 | .@"umul.fix.sat" = .{ |
| 3514 | 4311 | .ret_len = 1, |
| ... | ... | @@ -3518,7 +4315,7 @@ pub const Intrinsic = enum { |
| 3518 | 4315 | .{ .kind = .{ .matches = 0 } }, |
| 3519 | 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 | 4320 | .@"sdiv.fix" = .{ |
| 3524 | 4321 | .ret_len = 1, |
| ... | ... | @@ -3528,7 +4325,7 @@ pub const Intrinsic = enum { |
| 3528 | 4325 | .{ .kind = .{ .matches = 0 } }, |
| 3529 | 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 | 4330 | .@"udiv.fix" = .{ |
| 3534 | 4331 | .ret_len = 1, |
| ... | ... | @@ -3538,7 +4335,7 @@ pub const Intrinsic = enum { |
| 3538 | 4335 | .{ .kind = .{ .matches = 0 } }, |
| 3539 | 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 | 4340 | .@"sdiv.fix.sat" = .{ |
| 3544 | 4341 | .ret_len = 1, |
| ... | ... | @@ -3548,7 +4345,7 @@ pub const Intrinsic = enum { |
| 3548 | 4345 | .{ .kind = .{ .matches = 0 } }, |
| 3549 | 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 | 4350 | .@"udiv.fix.sat" = .{ |
| 3554 | 4351 | .ret_len = 1, |
| ... | ... | @@ -3558,7 +4355,7 @@ pub const Intrinsic = enum { |
| 3558 | 4355 | .{ .kind = .{ .matches = 0 } }, |
| 3559 | 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 | }, |
| 3563 | 4360 | |
| 3564 | 4361 | .canonicalize = .{ |
| ... | ... | @@ -3567,7 +4364,7 @@ pub const Intrinsic = enum { |
| 3567 | 4364 | .{ .kind = .overloaded }, |
| 3568 | 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 | 4369 | .fmuladd = .{ |
| 3573 | 4370 | .ret_len = 1, |
| ... | ... | @@ -3577,7 +4374,7 @@ pub const Intrinsic = enum { |
| 3577 | 4374 | .{ .kind = .{ .matches = 0 } }, |
| 3578 | 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 | }, |
| 3582 | 4379 | |
| 3583 | 4380 | .@"vector.reduce.add" = .{ |
| ... | ... | @@ -3586,7 +4383,7 @@ pub const Intrinsic = enum { |
| 3586 | 4383 | .{ .kind = .{ .matches_scalar = 1 } }, |
| 3587 | 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 | 4388 | .@"vector.reduce.fadd" = .{ |
| 3592 | 4389 | .ret_len = 1, |
| ... | ... | @@ -3595,7 +4392,7 @@ pub const Intrinsic = enum { |
| 3595 | 4392 | .{ .kind = .{ .matches_scalar = 2 } }, |
| 3596 | 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 | 4397 | .@"vector.reduce.mul" = .{ |
| 3601 | 4398 | .ret_len = 1, |
| ... | ... | @@ -3603,7 +4400,7 @@ pub const Intrinsic = enum { |
| 3603 | 4400 | .{ .kind = .{ .matches_scalar = 1 } }, |
| 3604 | 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 | 4405 | .@"vector.reduce.fmul" = .{ |
| 3609 | 4406 | .ret_len = 1, |
| ... | ... | @@ -3612,7 +4409,7 @@ pub const Intrinsic = enum { |
| 3612 | 4409 | .{ .kind = .{ .matches_scalar = 2 } }, |
| 3613 | 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 | 4414 | .@"vector.reduce.and" = .{ |
| 3618 | 4415 | .ret_len = 1, |
| ... | ... | @@ -3620,7 +4417,7 @@ pub const Intrinsic = enum { |
| 3620 | 4417 | .{ .kind = .{ .matches_scalar = 1 } }, |
| 3621 | 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 | 4422 | .@"vector.reduce.or" = .{ |
| 3626 | 4423 | .ret_len = 1, |
| ... | ... | @@ -3628,7 +4425,7 @@ pub const Intrinsic = enum { |
| 3628 | 4425 | .{ .kind = .{ .matches_scalar = 1 } }, |
| 3629 | 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 | 4430 | .@"vector.reduce.xor" = .{ |
| 3634 | 4431 | .ret_len = 1, |
| ... | ... | @@ -3636,7 +4433,7 @@ pub const Intrinsic = enum { |
| 3636 | 4433 | .{ .kind = .{ .matches_scalar = 1 } }, |
| 3637 | 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 | 4438 | .@"vector.reduce.smax" = .{ |
| 3642 | 4439 | .ret_len = 1, |
| ... | ... | @@ -3644,7 +4441,7 @@ pub const Intrinsic = enum { |
| 3644 | 4441 | .{ .kind = .{ .matches_scalar = 1 } }, |
| 3645 | 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 | 4446 | .@"vector.reduce.smin" = .{ |
| 3650 | 4447 | .ret_len = 1, |
| ... | ... | @@ -3652,7 +4449,7 @@ pub const Intrinsic = enum { |
| 3652 | 4449 | .{ .kind = .{ .matches_scalar = 1 } }, |
| 3653 | 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 | 4454 | .@"vector.reduce.umax" = .{ |
| 3658 | 4455 | .ret_len = 1, |
| ... | ... | @@ -3660,7 +4457,7 @@ pub const Intrinsic = enum { |
| 3660 | 4457 | .{ .kind = .{ .matches_scalar = 1 } }, |
| 3661 | 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 | 4462 | .@"vector.reduce.umin" = .{ |
| 3666 | 4463 | .ret_len = 1, |
| ... | ... | @@ -3668,7 +4465,7 @@ pub const Intrinsic = enum { |
| 3668 | 4465 | .{ .kind = .{ .matches_scalar = 1 } }, |
| 3669 | 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 | 4470 | .@"vector.reduce.fmax" = .{ |
| 3674 | 4471 | .ret_len = 1, |
| ... | ... | @@ -3676,7 +4473,7 @@ pub const Intrinsic = enum { |
| 3676 | 4473 | .{ .kind = .{ .matches_scalar = 1 } }, |
| 3677 | 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 | 4478 | .@"vector.reduce.fmin" = .{ |
| 3682 | 4479 | .ret_len = 1, |
| ... | ... | @@ -3684,7 +4481,7 @@ pub const Intrinsic = enum { |
| 3684 | 4481 | .{ .kind = .{ .matches_scalar = 1 } }, |
| 3685 | 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 | 4486 | .@"vector.reduce.fmaximum" = .{ |
| 3690 | 4487 | .ret_len = 1, |
| ... | ... | @@ -3692,7 +4489,7 @@ pub const Intrinsic = enum { |
| 3692 | 4489 | .{ .kind = .{ .matches_scalar = 1 } }, |
| 3693 | 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 | 4494 | .@"vector.reduce.fminimum" = .{ |
| 3698 | 4495 | .ret_len = 1, |
| ... | ... | @@ -3700,7 +4497,7 @@ pub const Intrinsic = enum { |
| 3700 | 4497 | .{ .kind = .{ .matches_scalar = 1 } }, |
| 3701 | 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 | 4502 | .@"vector.insert" = .{ |
| 3706 | 4503 | .ret_len = 1, |
| ... | ... | @@ -3710,7 +4507,7 @@ pub const Intrinsic = enum { |
| 3710 | 4507 | .{ .kind = .overloaded }, |
| 3711 | 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 | 4512 | .@"vector.extract" = .{ |
| 3716 | 4513 | .ret_len = 1, |
| ... | ... | @@ -3719,7 +4516,7 @@ pub const Intrinsic = enum { |
| 3719 | 4516 | .{ .kind = .overloaded }, |
| 3720 | 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 | }, |
| 3724 | 4521 | |
| 3725 | 4522 | .@"is.fpclass" = .{ |
| ... | ... | @@ -3729,7 +4526,7 @@ pub const Intrinsic = enum { |
| 3729 | 4526 | .{ .kind = .overloaded }, |
| 3730 | 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 | }, |
| 3734 | 4531 | |
| 3735 | 4532 | .@"var.annotation" = .{ |
| ... | ... | @@ -3814,7 +4611,7 @@ pub const Intrinsic = enum { |
| 3814 | 4611 | .{ .kind = .{ .type = .i1 }, .attrs = &.{.immarg} }, |
| 3815 | 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 | 4616 | .expect = .{ |
| 3820 | 4617 | .ret_len = 1, |
| ... | ... | @@ -3823,7 +4620,7 @@ pub const Intrinsic = enum { |
| 3823 | 4620 | .{ .kind = .{ .matches = 0 } }, |
| 3824 | 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 | 4625 | .@"expect.with.probability" = .{ |
| 3829 | 4626 | .ret_len = 1, |
| ... | ... | @@ -3833,7 +4630,7 @@ pub const Intrinsic = enum { |
| 3833 | 4630 | .{ .kind = .{ .matches = 0 } }, |
| 3834 | 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 | 4635 | .assume = .{ |
| 3839 | 4636 | .ret_len = 0, |
| ... | ... | @@ -3848,7 +4645,7 @@ pub const Intrinsic = enum { |
| 3848 | 4645 | .{ .kind = .overloaded }, |
| 3849 | 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 | 4650 | .@"type.test" = .{ |
| 3854 | 4651 | .ret_len = 1, |
| ... | ... | @@ -3857,7 +4654,7 @@ pub const Intrinsic = enum { |
| 3857 | 4654 | .{ .kind = .{ .type = .ptr } }, |
| 3858 | 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 | 4659 | .@"type.checked.load" = .{ |
| 3863 | 4660 | .ret_len = 2, |
| ... | ... | @@ -3868,7 +4665,7 @@ pub const Intrinsic = enum { |
| 3868 | 4665 | .{ .kind = .{ .type = .i32 } }, |
| 3869 | 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 | 4670 | .@"type.checked.load.relative" = .{ |
| 3874 | 4671 | .ret_len = 2, |
| ... | ... | @@ -3879,7 +4676,7 @@ pub const Intrinsic = enum { |
| 3879 | 4676 | .{ .kind = .{ .type = .i32 } }, |
| 3880 | 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 | 4681 | .@"arithmetic.fence" = .{ |
| 3885 | 4682 | .ret_len = 1, |
| ... | ... | @@ -3887,12 +4684,12 @@ pub const Intrinsic = enum { |
| 3887 | 4684 | .{ .kind = .overloaded }, |
| 3888 | 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 | 4689 | .donothing = .{ |
| 3893 | 4690 | .ret_len = 0, |
| 3894 | 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 | 4694 | .@"load.relative" = .{ |
| 3898 | 4695 | .ret_len = 1, |
| ... | ... | @@ -3914,7 +4711,7 @@ pub const Intrinsic = enum { |
| 3914 | 4711 | .{ .kind = .{ .type = .i1 } }, |
| 3915 | 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 | 4716 | .ptrmask = .{ |
| 3920 | 4717 | .ret_len = 1, |
| ... | ... | @@ -3923,7 +4720,7 @@ pub const Intrinsic = enum { |
| 3923 | 4720 | .{ .kind = .{ .matches = 0 } }, |
| 3924 | 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 | 4725 | .@"threadlocal.address" = .{ |
| 3929 | 4726 | .ret_len = 1, |
| ... | ... | @@ -3931,14 +4728,14 @@ pub const Intrinsic = enum { |
| 3931 | 4728 | .{ .kind = .overloaded, .attrs = &.{.nonnull} }, |
| 3932 | 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 | 4733 | .vscale = .{ |
| 3937 | 4734 | .ret_len = 1, |
| 3938 | 4735 | .params = &.{ |
| 3939 | 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 | }, |
| 3943 | 4740 | |
| 3944 | 4741 | .@"dbg.declare" = .{ |
| ... | ... | @@ -3948,7 +4745,7 @@ pub const Intrinsic = enum { |
| 3948 | 4745 | .{ .kind = .{ .type = .metadata } }, |
| 3949 | 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 | 4750 | .@"dbg.value" = .{ |
| 3954 | 4751 | .ret_len = 0, |
| ... | ... | @@ -3957,7 +4754,7 @@ pub const Intrinsic = enum { |
| 3957 | 4754 | .{ .kind = .{ .type = .metadata } }, |
| 3958 | 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 | }, |
| 3962 | 4759 | |
| 3963 | 4760 | .@"amdgcn.workitem.id.x" = .{ |
| ... | ... | @@ -3965,42 +4762,42 @@ pub const Intrinsic = enum { |
| 3965 | 4762 | .params = &.{ |
| 3966 | 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 | 4767 | .@"amdgcn.workitem.id.y" = .{ |
| 3971 | 4768 | .ret_len = 1, |
| 3972 | 4769 | .params = &.{ |
| 3973 | 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 | 4774 | .@"amdgcn.workitem.id.z" = .{ |
| 3978 | 4775 | .ret_len = 1, |
| 3979 | 4776 | .params = &.{ |
| 3980 | 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 | 4781 | .@"amdgcn.workgroup.id.x" = .{ |
| 3985 | 4782 | .ret_len = 1, |
| 3986 | 4783 | .params = &.{ |
| 3987 | 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 | 4788 | .@"amdgcn.workgroup.id.y" = .{ |
| 3992 | 4789 | .ret_len = 1, |
| 3993 | 4790 | .params = &.{ |
| 3994 | 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 | 4795 | .@"amdgcn.workgroup.id.z" = .{ |
| 3999 | 4796 | .ret_len = 1, |
| 4000 | 4797 | .params = &.{ |
| 4001 | 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 | 4802 | .@"amdgcn.dispatch.ptr" = .{ |
| 4006 | 4803 | .ret_len = 1, |
| ... | ... | @@ -4010,7 +4807,7 @@ pub const Intrinsic = enum { |
| 4010 | 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 | }, |
| 4015 | 4812 | |
| 4016 | 4813 | .@"nvvm.read.ptx.sreg.tid.x" = .{ |
| ... | ... | @@ -4085,7 +4882,7 @@ pub const Intrinsic = enum { |
| 4085 | 4882 | .{ .kind = .overloaded }, |
| 4086 | 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 | 4887 | .@"wasm.memory.grow" = .{ |
| 4091 | 4888 | .ret_len = 1, |
| ... | ... | @@ -4166,6 +4963,10 @@ pub const Function = struct { |
| 4166 | 4963 | self.ptr(builder).attributes = new_function_attributes; |
| 4167 | 4964 | } |
| 4168 | 4965 | |
| 4966 | pub fn getAttributes(self: Index, builder: *Builder) FunctionAttributes { | |
| 4967 | return self.ptr(builder).attributes; | |
| 4968 | } | |
| 4969 | ||
| 4169 | 4970 | pub fn setSection(self: Index, section: String, builder: *Builder) void { |
| 4170 | 4971 | self.ptr(builder).section = section; |
| 4171 | 4972 | } |
| ... | ... | @@ -4487,7 +5288,7 @@ pub const Function = struct { |
| 4487 | 5288 | } |
| 4488 | 5289 | |
| 4489 | 5290 | pub fn toValue(self: Instruction.Index) Value { |
| 4490 | return @fromBackingInt(@intCast(@backingInt(self))); | |
| 5291 | return @fromBackingInt(@backingInt(self)); | |
| 4491 | 5292 | } |
| 4492 | 5293 | |
| 4493 | 5294 | pub fn isTerminatorWip(self: Instruction.Index, wip: *const WipFunction) bool { |
| ... | ... | @@ -4679,7 +5480,7 @@ pub const Function = struct { |
| 4679 | 5480 | .changeScalarAssumeCapacity(.i1, wip.builder), |
| 4680 | 5481 | .fneg, |
| 4681 | 5482 | .@"fneg fast", |
| 4682 | => @as(Value, @fromBackingInt(@intCast(instruction.data))).typeOfWip(wip), | |
| 5483 | => @as(Value, @fromBackingInt(instruction.data)).typeOfWip(wip), | |
| 4683 | 5484 | .getelementptr, |
| 4684 | 5485 | .@"getelementptr inbounds", |
| 4685 | 5486 | => { |
| ... | ... | @@ -4871,7 +5672,7 @@ pub const Function = struct { |
| 4871 | 5672 | .changeScalarAssumeCapacity(.i1, builder), |
| 4872 | 5673 | .fneg, |
| 4873 | 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 | 5676 | .getelementptr, |
| 4876 | 5677 | .@"getelementptr inbounds", |
| 4877 | 5678 | => { |
| ... | ... | @@ -4963,7 +5764,7 @@ pub const Function = struct { |
| 4963 | 5764 | |
| 4964 | 5765 | pub fn fromMetadata(metadata: Metadata) Weights { |
| 4965 | 5766 | assert(metadata.kind == .node); |
| 4966 | return @fromBackingInt(@intCast(metadata.index)); | |
| 5767 | return @fromBackingInt(metadata.index); | |
| 4967 | 5768 | } |
| 4968 | 5769 | |
| 4969 | 5770 | pub fn toMetadata(weights: Weights) Metadata { |
| ... | ... | @@ -5156,7 +5957,7 @@ pub const Function = struct { |
| 5156 | 5957 | assert(argument.tag == .arg); |
| 5157 | 5958 | assert(argument.data == index); |
| 5158 | 5959 | |
| 5159 | const argument_index: Instruction.Index = @fromBackingInt(@intCast(index)); | |
| 5960 | const argument_index: Instruction.Index = @fromBackingInt(index); | |
| 5160 | 5961 | return argument_index.toValue(); |
| 5161 | 5962 | } |
| 5162 | 5963 | |
| ... | ... | @@ -5202,7 +6003,7 @@ pub const Function = struct { |
| 5202 | 6003 | Type, |
| 5203 | 6004 | Value, |
| 5204 | 6005 | Instruction.BrCond.Weights, |
| 5205 | => @fromBackingInt(@intCast(value)), | |
| 6006 | => @fromBackingInt(value), | |
| 5206 | 6007 | MemoryAccessInfo, |
| 5207 | 6008 | Instruction.Alloca.Info, |
| 5208 | 6009 | Instruction.Call.Info, |
| ... | ... | @@ -5327,7 +6128,7 @@ pub const WipFunction = struct { |
| 5327 | 6128 | assert(argument.tag == .arg); |
| 5328 | 6129 | assert(argument.data == index); |
| 5329 | 6130 | |
| 5330 | const argument_index: Instruction.Index = @fromBackingInt(@intCast(index)); | |
| 6131 | const argument_index: Instruction.Index = @fromBackingInt(index); | |
| 5331 | 6132 | return argument_index.toValue(); |
| 5332 | 6133 | } |
| 5333 | 6134 | |
| ... | ... | @@ -5722,7 +6523,7 @@ pub const WipFunction = struct { |
| 5722 | 6523 | alignment: Alignment, |
| 5723 | 6524 | name: []const u8, |
| 5724 | 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 | } |
| 5727 | 6528 | |
| 5728 | 6529 | pub fn loadAtomic( |
| ... | ... | @@ -5766,7 +6567,7 @@ pub const WipFunction = struct { |
| 5766 | 6567 | ptr: Value, |
| 5767 | 6568 | alignment: Alignment, |
| 5768 | 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 | } |
| 5771 | 6572 | |
| 5772 | 6573 | pub fn storeAtomic( |
| ... | ... | @@ -6414,24 +7215,24 @@ pub const WipFunction = struct { |
| 6414 | 7215 | errdefer function.instructions.shrinkRetainingCapacity(0); |
| 6415 | 7216 | |
| 6416 | 7217 | { |
| 6417 | var final_instruction_index: Instruction.Index = @fromBackingInt(@intCast(0)); | |
| 7218 | var final_instruction_index: Instruction.Index = @fromBackingInt(0); | |
| 6418 | 7219 | for (0..params_len) |param_index| { |
| 6419 | 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 | 7223 | for (blocks, self.blocks.items) |*final_block, current_block| { |
| 6423 | 7224 | assert(current_block.incoming == current_block.branches); |
| 6424 | 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 | 7227 | for (current_block.instructions.items) |instruction| { |
| 6427 | 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 | } |
| 6432 | 7233 | |
| 6433 | 7234 | var wip_name: struct { |
| 6434 | next_name: String = @fromBackingInt(@intCast(0)), | |
| 7235 | next_name: String = @fromBackingInt(0), | |
| 6435 | 7236 | next_unique_name: std.AutoHashMap(String, String), |
| 6436 | 7237 | builder: *Builder, |
| 6437 | 7238 | |
| ... | ... | @@ -6440,19 +7241,19 @@ pub const WipFunction = struct { |
| 6440 | 7241 | .none => return .none, |
| 6441 | 7242 | .empty => { |
| 6442 | 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 | 7245 | return wip_name.next_name; |
| 6445 | 7246 | }, |
| 6446 | 7247 | _ => { |
| 6447 | 7248 | assert(!name.isAnon()); |
| 6448 | 7249 | const gop = try wip_name.next_unique_name.getOrPut(name); |
| 6449 | 7250 | if (!gop.found_existing) { |
| 6450 | gop.value_ptr.* = @fromBackingInt(@intCast(0)); | |
| 7251 | gop.value_ptr.* = @fromBackingInt(0); | |
| 6451 | 7252 | return name; |
| 6452 | 7253 | } |
| 6453 | 7254 | |
| 6454 | 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 | 7257 | const unique_name = try wip_name.builder.fmt("{f}{s}{f}", .{ |
| 6457 | 7258 | name.fmtRaw(wip_name.builder), |
| 6458 | 7259 | sep, |
| ... | ... | @@ -6460,7 +7261,7 @@ pub const WipFunction = struct { |
| 6460 | 7261 | }); |
| 6461 | 7262 | const unique_gop = try wip_name.next_unique_name.getOrPut(unique_name); |
| 6462 | 7263 | if (!unique_gop.found_existing) { |
| 6463 | unique_gop.value_ptr.* = @fromBackingInt(@intCast(0)); | |
| 7264 | unique_gop.value_ptr.* = @fromBackingInt(0); | |
| 6464 | 7265 | return unique_name; |
| 6465 | 7266 | } |
| 6466 | 7267 | } |
| ... | ... | @@ -6702,7 +7503,7 @@ pub const WipFunction = struct { |
| 6702 | 7503 | .fneg, |
| 6703 | 7504 | .@"fneg fast", |
| 6704 | 7505 | .ret, |
| 6705 | => instruction.data = @backingInt(instructions.map(@fromBackingInt(@intCast(instruction.data)))), | |
| 7506 | => instruction.data = @backingInt(instructions.map(@fromBackingInt(instruction.data))), | |
| 6706 | 7507 | .getelementptr, |
| 6707 | 7508 | .@"getelementptr inbounds", |
| 6708 | 7509 | => { |
| ... | ... | @@ -7079,7 +7880,7 @@ pub const WipFunction = struct { |
| 7079 | 7880 | Type, |
| 7080 | 7881 | Value, |
| 7081 | 7882 | Instruction.BrCond.Weights, |
| 7082 | => @fromBackingInt(@intCast(value)), | |
| 7883 | => @fromBackingInt(value), | |
| 7083 | 7884 | MemoryAccessInfo, |
| 7084 | 7885 | Instruction.Alloca.Info, |
| 7085 | 7886 | Instruction.Call.Info, |
| ... | ... | @@ -7268,7 +8069,7 @@ pub const Constant = enum(u32) { |
| 7268 | 8069 | no_init = (1 << 30) - 1, |
| 7269 | 8070 | _, |
| 7270 | 8071 | |
| 7271 | const first_global: Constant = @fromBackingInt(@intCast(1 << 29)); | |
| 8072 | const first_global: Constant = @fromBackingInt(1 << 29); | |
| 7272 | 8073 | |
| 7273 | 8074 | pub const Tag = enum(u7) { |
| 7274 | 8075 | positive_integer, |
| ... | ... | @@ -7405,7 +8206,18 @@ pub const Constant = enum(u32) { |
| 7405 | 8206 | val: Constant, |
| 7406 | 8207 | type: Type, |
| 7407 | 8208 | |
| 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 | }; |
| 7410 | 8222 | |
| 7411 | 8223 | pub const GetElementPtr = struct { |
| ... | ... | @@ -7444,11 +8256,11 @@ pub const Constant = enum(u32) { |
| 7444 | 8256 | return if (@backingInt(self) < @backingInt(first_global)) |
| 7445 | 8257 | .{ .constant = @intCast(@backingInt(self)) } |
| 7446 | 8258 | else |
| 7447 | .{ .global = @fromBackingInt(@intCast(@backingInt(self) - @backingInt(first_global))) }; | |
| 8259 | .{ .global = @fromBackingInt(@backingInt(self) - @backingInt(first_global)) }; | |
| 7448 | 8260 | } |
| 7449 | 8261 | |
| 7450 | 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 | } |
| 7453 | 8265 | |
| 7454 | 8266 | pub fn typeOf(self: Constant, builder: *Builder) Type { |
| ... | ... | @@ -7474,7 +8286,7 @@ pub const Constant = enum(u32) { |
| 7474 | 8286 | .zeroinitializer, |
| 7475 | 8287 | .undef, |
| 7476 | 8288 | .poison, |
| 7477 | => @fromBackingInt(@intCast(item.data)), | |
| 8289 | => @fromBackingInt(item.data), | |
| 7478 | 8290 | .structure, |
| 7479 | 8291 | .packed_structure, |
| 7480 | 8292 | .array, |
| ... | ... | @@ -7482,7 +8294,7 @@ pub const Constant = enum(u32) { |
| 7482 | 8294 | => builder.constantExtraData(Aggregate, item.data).type, |
| 7483 | 8295 | .splat => builder.constantExtraData(Splat, item.data).type, |
| 7484 | 8296 | .string => builder.arrayTypeAssumeCapacity( |
| 7485 | @as(String, @fromBackingInt(@intCast(item.data))).slice(builder).?.len, | |
| 8297 | @as(String, @fromBackingInt(item.data)).slice(builder).?.len, | |
| 7486 | 8298 | .i8, |
| 7487 | 8299 | ), |
| 7488 | 8300 | .blockaddress => builder.ptrTypeAssumeCapacity( |
| ... | ... | @@ -7491,7 +8303,7 @@ pub const Constant = enum(u32) { |
| 7491 | 8303 | ), |
| 7492 | 8304 | .dso_local_equivalent, |
| 7493 | 8305 | .no_cfi, |
| 7494 | => builder.ptrTypeAssumeCapacity(@as(Function.Index, @fromBackingInt(@intCast(item.data))) | |
| 8306 | => builder.ptrTypeAssumeCapacity(@as(Function.Index, @fromBackingInt(item.data)) | |
| 7495 | 8307 | .ptrConst(builder).global.ptrConst(builder).addr_space), |
| 7496 | 8308 | .trunc, |
| 7497 | 8309 | .ptrtoint, |
| ... | ... | @@ -7802,7 +8614,7 @@ pub const Constant = enum(u32) { |
| 7802 | 8614 | try w.writeByte('>'); |
| 7803 | 8615 | }, |
| 7804 | 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 | 8619 | .blockaddress => |tag| { |
| 7808 | 8620 | const extra = data.builder.constantExtraData(BlockAddress, item.data); |
| ... | ... | @@ -7816,7 +8628,7 @@ pub const Constant = enum(u32) { |
| 7816 | 8628 | .dso_local_equivalent, |
| 7817 | 8629 | .no_cfi, |
| 7818 | 8630 | => |tag| { |
| 7819 | const function: Function.Index = @fromBackingInt(@intCast(item.data)); | |
| 8631 | const function: Function.Index = @fromBackingInt(item.data); | |
| 7820 | 8632 | try w.print("{s} {f}", .{ |
| 7821 | 8633 | @tagName(tag), |
| 7822 | 8634 | function.ptrConst(data.builder).global.fmt(data.builder), |
| ... | ... | @@ -7920,9 +8732,9 @@ pub const Value = enum(u32) { |
| 7920 | 8732 | metadata: Metadata, |
| 7921 | 8733 | } { |
| 7922 | 8734 | return if (@backingInt(self) < first_constant) |
| 7923 | .{ .instruction = @fromBackingInt(@intCast(@backingInt(self))) } | |
| 8735 | .{ .instruction = @fromBackingInt(@backingInt(self)) } | |
| 7924 | 8736 | else if (@backingInt(self) < first_metadata) |
| 7925 | .{ .constant = @fromBackingInt(@intCast(@backingInt(self) - first_constant)) } | |
| 8737 | .{ .constant = @fromBackingInt(@backingInt(self) - first_constant) } | |
| 7926 | 8738 | else |
| 7927 | 8739 | .{ .metadata = @bitCast(@backingInt(self) - first_metadata) }; |
| 7928 | 8740 | } |
| ... | ... | @@ -8016,7 +8828,7 @@ pub const Metadata = packed struct(u32) { |
| 8016 | 8828 | return .{ .index = metadata.index, .kind = metadata.kind, .is_none = false }; |
| 8017 | 8829 | } |
| 8018 | 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 | } |
| 8021 | 8833 | |
| 8022 | 8834 | pub const String = enum(u32) { |
| ... | ... | @@ -8032,7 +8844,7 @@ pub const Metadata = packed struct(u32) { |
| 8032 | 8844 | pub fn unwrap(metadata: Metadata.String.Optional) ?Metadata.String { |
| 8033 | 8845 | return switch (metadata) { |
| 8034 | 8846 | .none => null, |
| 8035 | else => @fromBackingInt(@intCast(@backingInt(metadata))), | |
| 8847 | else => @fromBackingInt(@backingInt(metadata)), | |
| 8036 | 8848 | }; |
| 8037 | 8849 | } |
| 8038 | 8850 | pub fn toMetadata(metadata: Metadata.String.Optional) Metadata.Optional { |
| ... | ... | @@ -8040,7 +8852,7 @@ pub const Metadata = packed struct(u32) { |
| 8040 | 8852 | } |
| 8041 | 8853 | }; |
| 8042 | 8854 | pub fn toOptional(metadata: Metadata.String) Metadata.String.Optional { |
| 8043 | return @fromBackingInt(@intCast(@backingInt(metadata))); | |
| 8855 | return @fromBackingInt(@backingInt(metadata)); | |
| 8044 | 8856 | } |
| 8045 | 8857 | pub fn toMetadata(metadata: Metadata.String) Metadata { |
| 8046 | 8858 | return .{ .index = @intCast(@backingInt(metadata)), .kind = .string }; |
| ... | ... | @@ -8077,7 +8889,7 @@ pub const Metadata = packed struct(u32) { |
| 8077 | 8889 | }; |
| 8078 | 8890 | pub fn toString(metadata: Metadata) Metadata.String { |
| 8079 | 8891 | assert(metadata.kind == .string); |
| 8080 | return @fromBackingInt(@intCast(metadata.index)); | |
| 8892 | return @fromBackingInt(metadata.index); | |
| 8081 | 8893 | } |
| 8082 | 8894 | |
| 8083 | 8895 | pub const Tag = enum(u6) { |
| ... | ... | @@ -8542,7 +9354,7 @@ pub const Metadata = packed struct(u32) { |
| 8542 | 9354 | try w.writeByte(')'); |
| 8543 | 9355 | }, |
| 8544 | 9356 | .constant => try Constant.format(.{ |
| 8545 | .constant = @fromBackingInt(@intCast(node_item.data)), | |
| 9357 | .constant = @fromBackingInt(node_item.data), | |
| 8546 | 9358 | .builder = builder, |
| 8547 | 9359 | .flags = data.specialized orelse .{}, |
| 8548 | 9360 | }, w), |
| ... | ... | @@ -8705,7 +9517,7 @@ pub const Metadata = packed struct(u32) { |
| 8705 | 9517 | nodes: anytype, |
| 8706 | 9518 | w: *Writer, |
| 8707 | 9519 | ) !void { |
| 8708 | const names = comptime std.meta.fieldNames(@TypeOf(nodes)); | |
| 9520 | const names = @typeInfo(@TypeOf(nodes)).@"struct".field_names; | |
| 8709 | 9521 | |
| 8710 | 9522 | comptime var fmt_str: []const u8 = "{[distinct]s}{[node]s}("; |
| 8711 | 9523 | inline for (names) |name| fmt_str = fmt_str ++ "{[" ++ name ++ "]f}"; |
| ... | ... | @@ -8735,7 +9547,14 @@ pub fn init(options: Options) Allocator.Error!Builder { |
| 8735 | 9547 | .strip = options.strip, |
| 8736 | 9548 | |
| 8737 | 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 | 9558 | .target_triple = .none, |
| 8740 | 9559 | .module_asm = .empty, |
| 8741 | 9560 | |
| ... | ... | @@ -8744,7 +9563,7 @@ pub fn init(options: Options) Allocator.Error!Builder { |
| 8744 | 9563 | .string_bytes = .empty, |
| 8745 | 9564 | |
| 8746 | 9565 | .types = .empty, |
| 8747 | .next_unnamed_type = @fromBackingInt(@intCast(0)), | |
| 9566 | .next_unnamed_type = @fromBackingInt(0), | |
| 8748 | 9567 | .next_unique_type_id = .empty, |
| 8749 | 9568 | .type_map = .empty, |
| 8750 | 9569 | .type_items = .empty, |
| ... | ... | @@ -8758,7 +9577,7 @@ pub fn init(options: Options) Allocator.Error!Builder { |
| 8758 | 9577 | .function_attributes_set = .empty, |
| 8759 | 9578 | |
| 8760 | 9579 | .globals = .empty, |
| 8761 | .next_unnamed_global = @fromBackingInt(@intCast(0)), | |
| 9580 | .next_unnamed_global = @fromBackingInt(0), | |
| 8762 | 9581 | .next_replaced_global = .none, |
| 8763 | 9582 | .next_unique_global_id = .empty, |
| 8764 | 9583 | .aliases = .empty, |
| ... | ... | @@ -8791,14 +9610,14 @@ pub fn init(options: Options) Allocator.Error!Builder { |
| 8791 | 9610 | try self.string_indices.append(self.gpa, 0); |
| 8792 | 9611 | assert(try self.string("") == .empty); |
| 8793 | 9612 | |
| 9613 | self.data_layout = try .parseString(try self.string(DataLayout.stringForTarget(options.target)), &self); | |
| 9614 | ||
| 8794 | 9615 | try self.strtab_string_indices.append(self.gpa, 0); |
| 8795 | 9616 | assert(try self.strtabString("") == .empty); |
| 8796 | 9617 | |
| 8797 | 9618 | if (options.name.len > 0) self.source_filename = try self.string(options.name); |
| 8798 | 9619 | |
| 8799 | if (options.triple.len > 0) { | |
| 8800 | self.target_triple = try self.string(options.triple); | |
| 8801 | } | |
| 9620 | if (options.triple.len > 0) self.target_triple = try self.string(options.triple); | |
| 8802 | 9621 | |
| 8803 | 9622 | { |
| 8804 | 9623 | const static_len = @typeInfo(Type).@"enum".field_names.len - 1; |
| ... | ... | @@ -8815,7 +9634,7 @@ pub fn init(options: Options) Allocator.Error!Builder { |
| 8815 | 9634 | assert(self.intTypeAssumeCapacity(bits) == |
| 8816 | 9635 | @field(Type, std.fmt.comptimePrint("i{d}", .{bits}))); |
| 8817 | 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 | 9638 | assert(self.ptrTypeAssumeCapacity(addr_space) == |
| 8820 | 9639 | @field(Type, std.fmt.comptimePrint("ptr{f}", .{addr_space.fmt(" ")}))); |
| 8821 | 9640 | } |
| ... | ... | @@ -8891,6 +9710,8 @@ pub fn clearAndFree(self: *Builder) void { |
| 8891 | 9710 | pub fn deinit(self: *Builder) void { |
| 8892 | 9711 | const gpa = self.gpa; |
| 8893 | 9712 | |
| 9713 | self.data_layout.deinit(gpa); | |
| 9714 | ||
| 8894 | 9715 | self.module_asm.deinit(gpa); |
| 8895 | 9716 | |
| 8896 | 9717 | self.string_map.deinit(gpa); |
| ... | ... | @@ -8944,7 +9765,7 @@ pub fn deinit(self: *Builder) void { |
| 8944 | 9765 | |
| 8945 | 9766 | pub fn finishModuleAsm(self: *Builder, aw: *Writer.Allocating) Allocator.Error!void { |
| 8946 | 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 | 9769 | try self.module_asm.append(self.gpa, '\n'); |
| 8949 | 9770 | } |
| 8950 | 9771 | |
| ... | ... | @@ -8990,7 +9811,7 @@ pub fn trailingString(self: *Builder) Allocator.Error!String { |
| 8990 | 9811 | } |
| 8991 | 9812 | |
| 8992 | 9813 | pub fn trailingStringAssumeCapacity(self: *Builder) String { |
| 8993 | const start = self.string_indices.getLast().?; | |
| 9814 | const start = self.string_indices.last().?; | |
| 8994 | 9815 | const bytes: []const u8 = self.string_bytes.items[start..]; |
| 8995 | 9816 | const gop = self.string_map.getOrPutAssumeCapacityAdapted(bytes, String.Adapter{ .builder = self }); |
| 8996 | 9817 | if (gop.found_existing) { |
| ... | ... | @@ -9092,17 +9913,17 @@ pub fn attrs(self: *Builder, attributes: []Attribute.Index) Allocator.Error!Attr |
| 9092 | 9913 | return @backingInt(lhs_kind) < @backingInt(rhs_kind); |
| 9093 | 9914 | } |
| 9094 | 9915 | }.lessThan); |
| 9095 | return @fromBackingInt(@intCast(try self.attrGeneric(@ptrCast(attributes)))); | |
| 9916 | return @fromBackingInt(try self.attrGeneric(@ptrCast(attributes))); | |
| 9096 | 9917 | } |
| 9097 | 9918 | |
| 9098 | 9919 | pub fn fnAttrs(self: *Builder, fn_attributes: []const Attributes) Allocator.Error!FunctionAttributes { |
| 9099 | 9920 | try self.function_attributes_set.ensureUnusedCapacity(self.gpa, 1); |
| 9100 | const function_attributes: FunctionAttributes = @fromBackingInt(@intCast(try self.attrGeneric(@ptrCast( | |
| 9101 | fn_attributes[0..if (std.mem.lastIndexOfNone(Attributes, fn_attributes, &.{.none})) |last| | |
| 9921 | const function_attributes: FunctionAttributes = @fromBackingInt(try self.attrGeneric(@ptrCast( | |
| 9922 | fn_attributes[0..if (std.mem.findLastNone(Attributes, fn_attributes, &.{.none})) |last| | |
| 9102 | 9923 | last + 1 |
| 9103 | 9924 | else |
| 9104 | 9925 | 0], |
| 9105 | )))); | |
| 9926 | ))); | |
| 9106 | 9927 | |
| 9107 | 9928 | _ = self.function_attributes_set.getOrPutAssumeCapacity(function_attributes); |
| 9108 | 9929 | return function_attributes; |
| ... | ... | @@ -9121,7 +9942,7 @@ pub fn addGlobalAssumeCapacity(self: *Builder, name: StrtabString, global: Globa |
| 9121 | 9942 | if (name == .empty) { |
| 9122 | 9943 | id = self.next_unnamed_global; |
| 9123 | 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 | 9947 | while (true) { |
| 9127 | 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 | 10531 | var metadata_formatter: Metadata.Formatter = .{ .builder = self, .need_comma = undefined }; |
| 9711 | 10532 | defer metadata_formatter.map.deinit(self.gpa); |
| 9712 | 10533 | |
| 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 | 10535 | if (need_newline) try w.writeByte('\n') else need_newline = true; |
| 9715 | 10536 | if (self.source_filename != .none) try w.print( |
| 9716 | 10537 | \\; ModuleID = '{s}' |
| 9717 | 10538 | \\source_filename = {f} |
| 9718 | 10539 | \\ |
| 9719 | 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 | 10542 | \\target datalayout = {f} |
| 9722 | 10543 | \\ |
| 9723 | , .{self.data_layout.fmtQ(self)}); | |
| 10544 | , .{self.data_layout.string_repr.fmtQ(self)}); | |
| 9724 | 10545 | if (self.target_triple != .none) try w.print( |
| 9725 | 10546 | \\target triple = {f} |
| 9726 | 10547 | \\ |
| ... | ... | @@ -10058,7 +10879,7 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void |
| 10058 | 10879 | continue; |
| 10059 | 10880 | }, |
| 10060 | 10881 | .br => |tag| { |
| 10061 | const target: Function.Block.Index = @fromBackingInt(@intCast(instruction.data)); | |
| 10882 | const target: Function.Block.Index = @fromBackingInt(instruction.data); | |
| 10062 | 10883 | try w.print(" {s} {f}", .{ |
| 10063 | 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 | 11008 | .fneg, |
| 10188 | 11009 | .@"fneg fast", |
| 10189 | 11010 | => |tag| { |
| 10190 | const val: Value = @fromBackingInt(@intCast(instruction.data)); | |
| 11011 | const val: Value = @fromBackingInt(instruction.data); | |
| 10191 | 11012 | try w.print(" %{f} = {s} {f}", .{ |
| 10192 | 11013 | instruction_index.name(&function).fmt(self), |
| 10193 | 11014 | @tagName(tag), |
| ... | ... | @@ -10288,7 +11109,7 @@ pub fn print(self: *Builder, w: *Writer) (Writer.Error || Allocator.Error)!void |
| 10288 | 11109 | } |
| 10289 | 11110 | }, |
| 10290 | 11111 | .ret => |tag| { |
| 10291 | const val: Value = @fromBackingInt(@intCast(instruction.data)); | |
| 11112 | const val: Value = @fromBackingInt(instruction.data); | |
| 10292 | 11113 | try w.print(" {s} {f}", .{ |
| 10293 | 11114 | @tagName(tag), |
| 10294 | 11115 | val.fmt(function_index, self, .{ .percent = true }), |
| ... | ... | @@ -11020,7 +11841,7 @@ fn opaqueTypeAssumeCapacity(self: *Builder, name: String) Type { |
| 11020 | 11841 | if (name == .empty) { |
| 11021 | 11842 | id = self.next_unnamed_type; |
| 11022 | 11843 | assert(id != .none); |
| 11023 | self.next_unnamed_type = @fromBackingInt(@intCast(@backingInt(id) + 1)); | |
| 11844 | self.next_unnamed_type = @fromBackingInt(@backingInt(id) + 1); | |
| 11024 | 11845 | } else assert(!name.isAnon()); |
| 11025 | 11846 | while (true) { |
| 11026 | 11847 | const type_gop = self.types.getOrPutAssumeCapacity(id); |
| ... | ... | @@ -11135,7 +11956,7 @@ fn typeExtraDataTrail( |
| 11135 | 11956 | ) |field_name, field_type, value| |
| 11136 | 11957 | @field(result, field_name) = switch (field_type) { |
| 11137 | 11958 | u32 => value, |
| 11138 | String, Type => @fromBackingInt(@intCast(value)), | |
| 11959 | String, Type => @fromBackingInt(value), | |
| 11139 | 11960 | else => @compileError("bad field type: " ++ @typeName(field_type)), |
| 11140 | 11961 | }; |
| 11141 | 11962 | return .{ |
| ... | ... | @@ -11746,7 +12567,7 @@ fn castConstAssumeCapacity(self: *Builder, tag: Constant.Tag, val: Constant, ty: |
| 11746 | 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 | 12571 | const gop = self.constant_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self }); |
| 11751 | 12572 | if (!gop.found_existing) { |
| 11752 | 12573 | gop.key_ptr.* = {}; |
| ... | ... | @@ -11828,10 +12649,10 @@ fn gepConstAssumeCapacity( |
| 11828 | 12649 | std.mem.eql(Constant, lhs_key.indices, rhs_indices); |
| 11829 | 12650 | } |
| 11830 | 12651 | }; |
| 11831 | const data = Key{ | |
| 12652 | const data: Key = .{ | |
| 11832 | 12653 | .type = ty, |
| 11833 | 12654 | .base = base, |
| 11834 | .inrange = if (inrange) |index| @fromBackingInt(@intCast(index)) else .none, | |
| 12655 | .inrange = if (inrange) |index| @fromBackingInt(index) else .none, | |
| 11835 | 12656 | .indices = indices, |
| 11836 | 12657 | }; |
| 11837 | 12658 | const gop = self.constant_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self }); |
| ... | ... | @@ -11885,7 +12706,7 @@ fn binConstAssumeCapacity( |
| 11885 | 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 | 12710 | const gop = self.constant_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self }); |
| 11890 | 12711 | if (!gop.found_existing) { |
| 11891 | 12712 | gop.key_ptr.* = {}; |
| ... | ... | @@ -11924,8 +12745,8 @@ fn asmConstAssumeCapacity( |
| 11924 | 12745 | } |
| 11925 | 12746 | }; |
| 11926 | 12747 | |
| 11927 | const data = Key{ | |
| 11928 | .tag = @fromBackingInt(@intCast(@backingInt(Constant.Tag.@"asm") + @as(u4, @bitCast(info)))), | |
| 12748 | const data: Key = .{ | |
| 12749 | .tag = @fromBackingInt(@backingInt(Constant.Tag.@"asm") + @as(u4, @bitCast(info))), | |
| 11929 | 12750 | .extra = .{ .type = ty, .assembly = assembly, .constraints = constraints }, |
| 11930 | 12751 | }; |
| 11931 | 12752 | const gop = self.constant_map.getOrPutAssumeCapacityAdapted(data, Adapter{ .builder = self }); |
| ... | ... | @@ -12073,7 +12894,7 @@ fn constantExtraDataTrail( |
| 12073 | 12894 | ) |field_name, field_type, value| |
| 12074 | 12895 | @field(result, field_name) = switch (field_type) { |
| 12075 | 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 | 12898 | Constant.GetElementPtr.Info => @bitCast(value), |
| 12078 | 12899 | else => @compileError("bad field type: " ++ @typeName(field_type)), |
| 12079 | 12900 | }; |
| ... | ... | @@ -12151,7 +12972,7 @@ fn metadataExtraDataTrail( |
| 12151 | 12972 | ) |field_name, field_type, value| |
| 12152 | 12973 | @field(result, field_name) = switch (field_type) { |
| 12153 | 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 | 12976 | Metadata, Metadata.Optional, Metadata.DIFlags => @bitCast(value), |
| 12156 | 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 | 13042 | } |
| 12222 | 13043 | |
| 12223 | 13044 | pub fn trailingMetadataStringAssumeCapacity(self: *Builder) Metadata.String { |
| 12224 | const start = self.metadata_string_indices.getLast().?; | |
| 13045 | const start = self.metadata_string_indices.last().?; | |
| 12225 | 13046 | const bytes: []const u8 = self.metadata_string_bytes.items[start..]; |
| 12226 | 13047 | assert(bytes.len > 0); |
| 12227 | 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 | 13484 | builder: *const Builder, |
| 12664 | 13485 | pub fn hash(_: @This(), key: Key) u32 { |
| 12665 | 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 | 13488 | hasher.update(std.mem.asBytes(&@field(key.value, field_name))); |
| 12668 | 13489 | } |
| 12669 | 13490 | return @truncate(hasher.final()); |
| ... | ... | @@ -12759,8 +13580,8 @@ fn debugSubprogramAssumeCapacity( |
| 12759 | 13580 | compile_unit: ?Metadata, |
| 12760 | 13581 | ) Metadata { |
| 12761 | 13582 | assert(!self.strip); |
| 12762 | const tag: Metadata.Tag = @fromBackingInt(@intCast(@backingInt(Metadata.Tag.subprogram) + | |
| 12763 | @as(u3, @truncate(@as(u32, @bitCast(options.sp_flags)) >> 2)))); | |
| 13583 | const tag: Metadata.Tag = @fromBackingInt(@backingInt(Metadata.Tag.subprogram) + | |
| 13584 | @as(u3, @truncate(@as(u32, @bitCast(options.sp_flags)) >> 2))); | |
| 12764 | 13585 | return self.metadataDistinctAssumeCapacity(tag, Metadata.Subprogram{ |
| 12765 | 13586 | .file = .wrap(file), |
| 12766 | 13587 | .name = .wrap(name), |
| ... | ... | @@ -13345,7 +14166,7 @@ fn metadataConstantAssumeCapacity(self: *Builder, constant: Constant) Metadata { |
| 13345 | 14166 | |
| 13346 | 14167 | pub fn eql(ctx: @This(), lhs_key: Constant, _: void, rhs_index: usize) bool { |
| 13347 | 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 | 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 | 14239 | }); |
| 13419 | 14240 | } |
| 13420 | 14241 | |
| 13421 | if (self.data_layout.slice(self)) |data_layout| { | |
| 14242 | if (self.data_layout.string_repr.slice(self)) |data_layout| { | |
| 13422 | 14243 | try module_block.writeAbbrev(ModuleBlock.String{ |
| 13423 | 14244 | .code = 3, |
| 13424 | 14245 | .string = data_layout, |
| ... | ... | @@ -13577,6 +14398,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco |
| 13577 | 14398 | switch (attr_index.toAttribute(self)) { |
| 13578 | 14399 | .zeroext, |
| 13579 | 14400 | .signext, |
| 14401 | .noext, | |
| 13580 | 14402 | .inreg, |
| 13581 | 14403 | .@"noalias", |
| 13582 | 14404 | .nocapture, |
| ... | ... | @@ -13594,11 +14416,13 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco |
| 13594 | 14416 | .readnone, |
| 13595 | 14417 | .readonly, |
| 13596 | 14418 | .writeonly, |
| 14419 | .writable, | |
| 14420 | .dead_on_unwind, | |
| 13597 | 14421 | .alwaysinline, |
| 13598 | 14422 | .builtin, |
| 13599 | 14423 | .cold, |
| 13600 | 14424 | .convergent, |
| 13601 | .disable_sanitizer_information, | |
| 14425 | .disable_sanitizer_instrumentation, | |
| 13602 | 14426 | .fn_ret_thunk_extern, |
| 13603 | 14427 | .hot, |
| 13604 | 14428 | .inlinehint, |
| ... | ... | @@ -13607,6 +14431,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco |
| 13607 | 14431 | .naked, |
| 13608 | 14432 | .nobuiltin, |
| 13609 | 14433 | .nocallback, |
| 14434 | .nodivergencesource, | |
| 13610 | 14435 | .noduplicate, |
| 13611 | 14436 | .noimplicitfloat, |
| 13612 | 14437 | .@"noinline", |
| ... | ... | @@ -13623,6 +14448,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco |
| 13623 | 14448 | .nosanitize_bounds, |
| 13624 | 14449 | .nosanitize_coverage, |
| 13625 | 14450 | .null_pointer_is_valid, |
| 14451 | .optdebug, | |
| 13626 | 14452 | .optforfuzzing, |
| 13627 | 14453 | .optnone, |
| 13628 | 14454 | .optsize, |
| ... | ... | @@ -13633,18 +14459,21 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco |
| 13633 | 14459 | .sanitize_thread, |
| 13634 | 14460 | .sanitize_hwaddress, |
| 13635 | 14461 | .sanitize_memtag, |
| 14462 | .sanitize_realtime, | |
| 14463 | .sanitize_realtime_blocking, | |
| 14464 | .sanitize_alloc_token, | |
| 13636 | 14465 | .speculative_load_hardening, |
| 13637 | 14466 | .speculatable, |
| 13638 | 14467 | .ssp, |
| 13639 | 14468 | .sspstrong, |
| 13640 | 14469 | .sspreq, |
| 13641 | 14470 | .strictfp, |
| 14471 | .denormal_fpenv, | |
| 13642 | 14472 | .nocf_check, |
| 13643 | 14473 | .shadowcallstack, |
| 13644 | 14474 | .mustprogress, |
| 13645 | .no_sanitize_address, | |
| 13646 | .no_sanitize_hwaddress, | |
| 13647 | .sanitize_address_dyninit, | |
| 14475 | .nooutline, | |
| 14476 | .nocreateundeforpoison, | |
| 13648 | 14477 | => { |
| 13649 | 14478 | try record.ensureUnusedCapacity(self.gpa, 2); |
| 13650 | 14479 | record.appendAssumeCapacity(0); |
| ... | ... | @@ -13670,6 +14499,12 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco |
| 13670 | 14499 | record.appendAssumeCapacity(@backingInt(kind)); |
| 13671 | 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 | 14508 | .dereferenceable, |
| 13674 | 14509 | .dereferenceable_or_null, |
| 13675 | 14510 | => |size| { |
| ... | ... | @@ -13684,6 +14519,9 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco |
| 13684 | 14519 | record.appendAssumeCapacity(@backingInt(kind)); |
| 13685 | 14520 | record.appendAssumeCapacity(@as(u32, @bitCast(fpclass))); |
| 13686 | 14521 | }, |
| 14522 | .initializes => @panic("TODO"), | |
| 14523 | .dead_on_return => @panic("TODO"), | |
| 14524 | .range => @panic("TODO"), | |
| 13687 | 14525 | .allockind => |allockind| { |
| 13688 | 14526 | try record.ensureUnusedCapacity(self.gpa, 3); |
| 13689 | 14527 | record.appendAssumeCapacity(1); |
| ... | ... | @@ -13955,8 +14793,11 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco |
| 13955 | 14793 | } |
| 13956 | 14794 | |
| 13957 | 14795 | const strtab = alias.global.strtab(self); |
| 13958 | ||
| 13959 | 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 | 14801 | try module_block.writeAbbrev(ModuleBlock.Alias{ |
| 13961 | 14802 | .strtab_offset = strtab.offset, |
| 13962 | 14803 | .strtab_size = strtab.size, |
| ... | ... | @@ -14096,7 +14937,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco |
| 14096 | 14937 | } |
| 14097 | 14938 | }, |
| 14098 | 14939 | .string => { |
| 14099 | const str: String = @fromBackingInt(@intCast(data)); | |
| 14940 | const str: String = @fromBackingInt(data); | |
| 14100 | 14941 | if (str == .none) { |
| 14101 | 14942 | try constants_block.writeAbbrev(ConstantsBlock.Null{}); |
| 14102 | 14943 | } else { |
| ... | ... | @@ -14223,7 +15064,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco |
| 14223 | 15064 | .dso_local_equivalent, |
| 14224 | 15065 | .no_cfi, |
| 14225 | 15066 | => |tag| { |
| 14226 | const function: Function.Index = @fromBackingInt(@intCast(data)); | |
| 15067 | const function: Function.Index = @fromBackingInt(data); | |
| 14227 | 15068 | try constants_block.writeAbbrev(ConstantsBlock.DsoLocalEquivalentOrNoCfi{ |
| 14228 | 15069 | .code = switch (tag) { |
| 14229 | 15070 | .dso_local_equivalent => .DSO_LOCAL_EQUIVALENT, |
| ... | ... | @@ -14606,7 +15447,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco |
| 14606 | 15447 | }, metadata_adapter); |
| 14607 | 15448 | }, |
| 14608 | 15449 | .constant => { |
| 14609 | const constant: Constant = @fromBackingInt(@intCast(data)); | |
| 15450 | const constant: Constant = @fromBackingInt(data); | |
| 14610 | 15451 | try metadata_block.writeAbbrevAdapted(MetadataBlock.Constant{ |
| 14611 | 15452 | .ty = constant.typeOf(self), |
| 14612 | 15453 | .constant = constant, |
| ... | ... | @@ -14775,7 +15616,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco |
| 14775 | 15616 | var adapter: FunctionAdapter = .{ |
| 14776 | 15617 | .metadata_adapter = metadata_adapter, |
| 14777 | 15618 | .func = &func, |
| 14778 | .instruction_index = @fromBackingInt(@intCast(0)), | |
| 15619 | .instruction_index = @fromBackingInt(0), | |
| 14779 | 15620 | }; |
| 14780 | 15621 | |
| 14781 | 15622 | // Emit function level metadata block |
| ... | ... | @@ -14786,7 +15627,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco |
| 14786 | 15627 | for (func.debug_values) |value| { |
| 14787 | 15628 | try metadata_block.writeAbbrev(MetadataBlock.Value{ |
| 14788 | 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 | } |
| 14792 | 15633 | |
| ... | ... | @@ -15068,10 +15909,10 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco |
| 15068 | 15909 | }); |
| 15069 | 15910 | }, |
| 15070 | 15911 | .fneg => try function_block.writeAbbrev(FunctionBlock.FNeg{ |
| 15071 | .val = adapter.getOffsetValueIndex(@fromBackingInt(@intCast(data))), | |
| 15912 | .val = adapter.getOffsetValueIndex(@fromBackingInt(data)), | |
| 15072 | 15913 | }), |
| 15073 | 15914 | .@"fneg fast" => try function_block.writeAbbrev(FunctionBlock.FNegFast{ |
| 15074 | .val = adapter.getOffsetValueIndex(@fromBackingInt(@intCast(data))), | |
| 15915 | .val = adapter.getOffsetValueIndex(@fromBackingInt(data)), | |
| 15075 | 15916 | .fast_math = FastMath.fast, |
| 15076 | 15917 | }), |
| 15077 | 15918 | .extractvalue => { |
| ... | ... | @@ -15271,7 +16112,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator, producer: Producer) bitco |
| 15271 | 16112 | try function_block.writeUnabbrev(16, record.items); |
| 15272 | 16113 | }, |
| 15273 | 16114 | .ret => try function_block.writeAbbrev(FunctionBlock.Ret{ |
| 15274 | .val = adapter.getOffsetValueIndex(@fromBackingInt(@intCast(data))), | |
| 16115 | .val = adapter.getOffsetValueIndex(@fromBackingInt(data)), | |
| 15275 | 16116 | }), |
| 15276 | 16117 | .@"ret void" => try function_block.writeAbbrev(FunctionBlock.RetVoid{}), |
| 15277 | 16118 | .atomicrmw => { |
lib/std/zig/llvm/bitcode_writer.zig+1-1| ... | ... | @@ -246,7 +246,7 @@ pub fn BitcodeWriter(comptime types: []const type) type { |
| 246 | 246 | |
| 247 | 247 | try self.bitcode.writeBits(comptime abbrevId(Abbrev), abbrev_len); |
| 248 | 248 | |
| 249 | const field_names = comptime std.meta.fieldNames(Abbrev); | |
| 249 | const field_names = @typeInfo(Abbrev).@"struct".field_names; | |
| 250 | 250 | |
| 251 | 251 | // This abbreviation might only contain literals |
| 252 | 252 | if (field_names.len == 0) return; |
lib/std/zig/system.zig+9-9| ... | ... | @@ -597,23 +597,23 @@ fn abiAndDynamicLinkerFromFile( |
| 597 | 597 | .ofmt = query.ofmt orelse Target.ObjectFormat.default(os.tag, cpu.arch), |
| 598 | 598 | .dynamic_linker = query.dynamic_linker orelse .none, |
| 599 | 599 | }; |
| 600 | var rpath_offset: ?u64 = null; // Found inside PT_DYNAMIC | |
| 600 | var rpath_offset: ?u64 = null; // Found inside PT.DYNAMIC | |
| 601 | 601 | const look_for_ld = query.dynamic_linker == null; |
| 602 | 602 | |
| 603 | 603 | var got_dyn_section: bool = false; |
| 604 | 604 | { |
| 605 | 605 | var it = header.iterateProgramHeaders(file_reader); |
| 606 | while (try it.next()) |phdr| switch (phdr.p_type) { | |
| 607 | elf.PT_INTERP => { | |
| 606 | while (try it.next()) |phdr| switch (phdr.type) { | |
| 607 | .INTERP => { | |
| 608 | 608 | got_dyn_section = true; |
| 609 | 609 | |
| 610 | 610 | if (look_for_ld) { |
| 611 | const p_filesz = phdr.p_filesz; | |
| 611 | const p_filesz = phdr.filesz; | |
| 612 | 612 | if (p_filesz > result.dynamic_linker.buffer.len) return error.NameTooLong; |
| 613 | 613 | const filesz: usize = @intCast(p_filesz); |
| 614 | try file_reader.seekTo(phdr.p_offset); | |
| 614 | try file_reader.seekTo(phdr.offset); | |
| 615 | 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 | 617 | const len = filesz - 1; |
| 618 | 618 | // dynamic_linker.max_byte is "max", not "len". |
| 619 | 619 | // We know it will fit in u8 because we check against dynamic_linker.buffer.len above. |
| ... | ... | @@ -631,11 +631,11 @@ fn abiAndDynamicLinkerFromFile( |
| 631 | 631 | } |
| 632 | 632 | }, |
| 633 | 633 | // We only need this for detecting glibc version. |
| 634 | elf.PT_DYNAMIC => { | |
| 634 | .DYNAMIC => { | |
| 635 | 635 | got_dyn_section = true; |
| 636 | 636 | |
| 637 | 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 | 639 | while (try dyn_it.next()) |dyn| { |
| 640 | 640 | if (dyn.d_tag == elf.DT_RUNPATH) { |
| 641 | 641 | rpath_offset = dyn.d_val; |
| ... | ... | @@ -973,7 +973,7 @@ fn detectAbiAndDynamicLinker(io: Io, cpu: Target.Cpu, os: Target.Os, query: Targ |
| 973 | 973 | // relying on `builtin.target`. |
| 974 | 974 | const all_abis = comptime blk: { |
| 975 | 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 | 977 | var array: [field_names.len]Target.Abi = undefined; |
| 978 | 978 | for (field_names, 0..) |field_name, i| { |
| 979 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 501 | } |
| 500 | 502 | |
| 501 | 503 | pub fn intAlignment(target: *const std.Target, bits: u16) u16 { |
| 502 | return switch (target.cpu.arch) { | |
| 503 | .x86 => switch (bits) { | |
| 504 | 0...8 => 1, | |
| 505 | 9...16 => 2, | |
| 506 | 17...32 => 4, | |
| 507 | 33...64 => switch (target.os.tag) { | |
| 508 | .uefi, .windows => 8, | |
| 509 | else => 4, | |
| 510 | }, | |
| 511 | else => 16, | |
| 512 | }, | |
| 513 | .x86_64 => switch (bits) { | |
| 514 | 0...8 => 1, | |
| 515 | 9...16 => 2, | |
| 516 | 17...32 => 4, | |
| 517 | 33...64 => 8, | |
| 518 | else => 16, | |
| 519 | }, | |
| 520 | else => switch (bits) { | |
| 521 | 0 => 1, | |
| 522 | else => @min( | |
| 523 | std.math.ceilPowerOfTwoPromote(u16, @intCast((@as(u17, bits) + 7) / 8)), | |
| 524 | target.cMaxIntAlignment(), | |
| 525 | ), | |
| 526 | }, | |
| 504 | return switch (bits) { | |
| 505 | 0 => 1, | |
| 506 | else => @min( | |
| 507 | std.math.ceilPowerOfTwoPromote(u16, @intCast((@as(u17, bits) + 7) / 8)), | |
| 508 | target.cMaxIntAlignment(), | |
| 509 | ), | |
| 527 | 510 | }; |
| 528 | 511 | } |
| 529 | 512 | |
| 513 | pub 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 | ||
| 530 | 530 | const std = @import("std"); |
| 531 | 531 | const assert = std.debug.assert; |
| 532 | 532 | const Allocator = std.mem.Allocator; |
lib/std/zip.zig+1-1| ... | ... | @@ -109,7 +109,7 @@ pub const EndRecord = extern struct { |
| 109 | 109 | |
| 110 | 110 | /// TODO audit this logic |
| 111 | 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 | 113 | if (pos + @sizeOf(EndRecord) > buffer.len) return error.EndOfStream; |
| 114 | 114 | const record_ptr: *EndRecord = @ptrCast(buffer[pos..][0..@sizeOf(EndRecord)]); |
| 115 | 115 | var record = record_ptr.*; |
lib/std/zon.zig+41| ... | ... | @@ -37,10 +37,51 @@ |
| 37 | 37 | //! ZON does not have syntax for pointers, but the parsers will allocate as needed to match the |
| 38 | 38 | //! given Zig types. Similarly, the serializer will traverse pointers. |
| 39 | 39 | |
| 40 | const std = @import("std"); | |
| 41 | ||
| 40 | 42 | pub const parse = @import("zon/parse.zig"); |
| 41 | 43 | pub const stringify = @import("zon/stringify.zig"); |
| 42 | 44 | pub const Serializer = @import("zon/Serializer.zig"); |
| 43 | 45 | |
| 46 | /// Returns a formatter that formats the given value using stringify. | |
| 47 | pub fn fmt(value: anytype, options: stringify.SerializeOptions) Formatter(@TypeOf(value)) { | |
| 48 | return Formatter(@TypeOf(value)){ .value = value, .options = options }; | |
| 49 | } | |
| 50 | ||
| 51 | test 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. | |
| 74 | pub 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 | ||
| 44 | 85 | test { |
| 45 | 86 | _ = parse; |
| 46 | 87 | _ = stringify; |
lib/std/zon/parse.zig+1-6| ... | ... | @@ -9,7 +9,6 @@ |
| 9 | 9 | //! For lower level control over parsing, see `std.zig.Zoir`. |
| 10 | 10 | |
| 11 | 11 | const std = @import("std"); |
| 12 | const builtin = @import("builtin"); | |
| 13 | 12 | const Allocator = std.mem.Allocator; |
| 14 | 13 | const Ast = std.zig.Ast; |
| 15 | 14 | const Zoir = std.zig.Zoir; |
| ... | ... | @@ -1868,8 +1867,6 @@ test "std.zon tuples" { |
| 1868 | 1867 | |
| 1869 | 1868 | // Test sizes 0 to 3 since small sizes get parsed differently |
| 1870 | 1869 | test "std.zon arrays and slices" { |
| 1871 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/20881 | |
| 1872 | ||
| 1873 | 1870 | const gpa = std.testing.allocator; |
| 1874 | 1871 | |
| 1875 | 1872 | // Literals |
| ... | ... | @@ -2802,8 +2799,6 @@ test "std.zon negative char" { |
| 2802 | 2799 | } |
| 2803 | 2800 | |
| 2804 | 2801 | test "std.zon parse float" { |
| 2805 | if (builtin.cpu.arch == .x86) return error.SkipZigTest; | |
| 2806 | ||
| 2807 | 2802 | const gpa = std.testing.allocator; |
| 2808 | 2803 | |
| 2809 | 2804 | // Test decimals |
| ... | ... | @@ -3135,7 +3130,7 @@ test "std.zon free on error" { |
| 3135 | 3130 | } |
| 3136 | 3131 | |
| 3137 | 3132 | test "std.zon vector" { |
| 3138 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/15330 | |
| 3133 | const builtin = @import("builtin"); | |
| 3139 | 3134 | if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .s390x) return error.SkipZigTest; // https://github.com/ziglang/zig/issues/25957 |
| 3140 | 3135 | |
| 3141 | 3136 | const gpa = std.testing.allocator; |
lib/std/zon/stringify.zig-3| ... | ... | @@ -1151,9 +1151,6 @@ test "std.zon depth limits" { |
| 1151 | 1151 | } |
| 1152 | 1152 | |
| 1153 | 1153 | test "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 | 1154 | try expectSerializeEqual( |
| 1158 | 1155 | \\.{ |
| 1159 | 1156 | \\ .a = 1.5, |
lib/zig.h+3079-991| ... | ... | @@ -166,6 +166,12 @@ |
| 166 | 166 | #endif |
| 167 | 167 | #define zig_expand_has_builtin(b) zig_has_builtin(b) |
| 168 | 168 | |
| 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 | 175 | #if defined(__has_attribute) |
| 170 | 176 | #define zig_has_attribute(attribute) __has_attribute(attribute) |
| 171 | 177 | #else |
| ... | ... | @@ -175,9 +181,9 @@ |
| 175 | 181 | #if __STDC_VERSION__ >= 201112L |
| 176 | 182 | #define zig_static_assert(cond, msg) _Static_assert(cond, msg) |
| 177 | 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 | 185 | #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 | 187 | #endif |
| 182 | 188 | |
| 183 | 189 | #if __STDC_VERSION__ >= 202311L |
| ... | ... | @@ -193,10 +199,8 @@ |
| 193 | 199 | #endif |
| 194 | 200 | |
| 195 | 201 | #if defined(zig_msvc) |
| 196 | #define zig_const_arr | |
| 197 | 202 | #define zig_callconv(c) __##c |
| 198 | 203 | #else |
| 199 | #define zig_const_arr static const | |
| 200 | 204 | #define zig_callconv(c) __attribute__((c)) |
| 201 | 205 | #endif |
| 202 | 206 | |
| ... | ... | @@ -267,12 +271,20 @@ |
| 267 | 271 | |
| 268 | 272 | #if __STDC_VERSION__ >= 202311L |
| 269 | 273 | #define zig_align(alignment) alignas(alignment) |
| 270 | #elif __STDC_VERSION__ >= 201112L | |
| 274 | #elif __STDC_VERSION__ >= 201112L || zig_has_feature(c_alignas) | |
| 271 | 275 | #define zig_align(alignment) _Alignas(alignment) |
| 272 | 276 | #else |
| 273 | 277 | #define zig_align(alignment) zig_under_align(alignment) |
| 274 | 278 | #endif |
| 275 | 279 | |
| 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 | 288 | #if zig_has_attribute(aligned) || defined(zig_tinyc) |
| 277 | 289 | #define zig_align_fn(alignment) __attribute__((aligned(alignment))) |
| 278 | 290 | #elif defined(zig_msvc) |
| ... | ... | @@ -350,11 +362,9 @@ |
| 350 | 362 | #define zig_export(symbol, name) __attribute__((alias(symbol))) |
| 351 | 363 | #else |
| 352 | 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 | 366 | #endif |
| 355 | 367 | |
| 356 | #define zig_mangled_tentative zig_mangled | |
| 357 | #define zig_mangled_final zig_mangled | |
| 358 | 368 | #if defined(zig_msvc) |
| 359 | 369 | #define zig_mangled(mangled, unmangled) ; \ |
| 360 | 370 | zig_export(#mangled, unmangled) |
| ... | ... | @@ -364,7 +374,7 @@ |
| 364 | 374 | #else /* zig_msvc */ |
| 365 | 375 | #define zig_mangled(mangled, unmangled) __asm(zig_mangle_c(unmangled)) |
| 366 | 376 | #define zig_mangled_export(mangled, unmangled, symbol) \ |
| 367 | zig_mangled_final(mangled, unmangled) \ | |
| 377 | zig_mangled(mangled, unmangled) \ | |
| 368 | 378 | zig_export(symbol, unmangled) |
| 369 | 379 | #endif /* zig_msvc */ |
| 370 | 380 | |
| ... | ... | @@ -550,6 +560,9 @@ |
| 550 | 560 | #define zig_noreturn |
| 551 | 561 | #endif |
| 552 | 562 | |
| 563 | #define zig_has_always 1 | |
| 564 | #define zig_has_never 0 | |
| 565 | ||
| 553 | 566 | #define zig_compiler_rt_abbrev_uint32_t si |
| 554 | 567 | #define zig_compiler_rt_abbrev_int32_t si |
| 555 | 568 | #define zig_compiler_rt_abbrev_uint64_t di |
| ... | ... | @@ -560,7 +573,11 @@ |
| 560 | 573 | #define zig_compiler_rt_abbrev_zig_f32 sf |
| 561 | 574 | #define zig_compiler_rt_abbrev_zig_f64 df |
| 562 | 575 | #define zig_compiler_rt_abbrev_zig_f80 xf |
| 576 | #ifdef zig_powerpc | |
| 577 | #define zig_compiler_rt_abbrev_zig_f128 kf | |
| 578 | #else | |
| 563 | 579 | #define zig_compiler_rt_abbrev_zig_f128 tf |
| 580 | #endif | |
| 564 | 581 | |
| 565 | 582 | zig_extern void *memcpy (void *zig_restrict, void const *zig_restrict, size_t); |
| 566 | 583 | zig_extern void *memset (void *, int, size_t); |
| ... | ... | @@ -645,16 +662,6 @@ typedef signed long long int16_t; |
| 645 | 662 | #define INT16_MAX ( INT16_C(0x7FFF)) |
| 646 | 663 | #define UINT16_MAX ( INT16_C(0xFFFF)) |
| 647 | 664 | |
| 648 | #if defined(zig_ez80) | |
| 649 | typedef unsigned int uint24_t; | |
| 650 | typedef 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 | 665 | #if SCHAR_MIN == ~0x7FFFFFFF && SCHAR_MAX == 0x7FFFFFFF && UCHAR_MAX == 0xFFFFFFFF |
| 659 | 666 | typedef unsigned char uint32_t; |
| 660 | 667 | typedef signed char int32_t; |
| ... | ... | @@ -685,17 +692,6 @@ typedef signed long long int32_t; |
| 685 | 692 | #define INT32_MAX ( INT32_C(0x7FFFFFFF)) |
| 686 | 693 | #define UINT32_MAX ( INT32_C(0xFFFFFFFF)) |
| 687 | 694 | |
| 688 | #if defined(zig_ez80) | |
| 689 | typedef unsigned __int48 uint48_t; | |
| 690 | typedef 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 | 695 | #if SCHAR_MIN == ~0x7FFFFFFFFFFFFFFF && SCHAR_MAX == 0x7FFFFFFFFFFFFFFF && UCHAR_MAX == 0xFFFFFFFFFFFFFFFF |
| 700 | 696 | typedef unsigned char uint64_t; |
| 701 | 697 | typedef signed char int64_t; |
| ... | ... | @@ -726,6 +722,27 @@ typedef signed long long int64_t; |
| 726 | 722 | #define INT64_MAX ( INT64_C(0x7FFFFFFFFFFFFFFF)) |
| 727 | 723 | #define UINT64_MAX ( INT64_C(0xFFFFFFFFFFFFFFFF)) |
| 728 | 724 | |
| 725 | #if defined(zig_ez80) | |
| 726 | ||
| 727 | typedef unsigned int uint24_t; | |
| 728 | typedef 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 | ||
| 735 | typedef unsigned __int48 uint48_t; | |
| 736 | typedef 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 | ||
| 729 | 746 | typedef size_t uintptr_t; |
| 730 | 747 | typedef ptrdiff_t intptr_t; |
| 731 | 748 | |
| ... | ... | @@ -739,23 +756,145 @@ typedef ptrdiff_t intptr_t; |
| 739 | 756 | #define zig_maxInt_i16 INT16_MAX |
| 740 | 757 | #define zig_minInt_u16 UINT16_C(0) |
| 741 | 758 | #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 | 759 | #define zig_minInt_i32 INT32_MIN |
| 747 | 760 | #define zig_maxInt_i32 INT32_MAX |
| 748 | 761 | #define zig_minInt_u32 UINT32_C(0) |
| 749 | 762 | #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 | 763 | #define zig_minInt_i64 INT64_MIN |
| 755 | 764 | #define zig_maxInt_i64 INT64_MAX |
| 756 | 765 | #define zig_minInt_u64 UINT64_C(0) |
| 757 | 766 | #define zig_maxInt_u64 UINT64_MAX |
| 758 | 767 | |
| 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 | |
| 772 | typedef unsigned int zig_promoted_i8; | |
| 773 | #elif INT8_MAX <= LONG_MAX | |
| 774 | typedef unsigned long zig_promoted_i8; | |
| 775 | #elif INT8_MAX <= LLONG_MAX | |
| 776 | typedef unsigned long long zig_promoted_i8; | |
| 777 | #else | |
| 778 | typedef int8_t zig_promoted_i8; | |
| 779 | #endif | |
| 780 | #if UINT8_MAX <= UINT_MAX | |
| 781 | typedef unsigned int zig_promoted_u8; | |
| 782 | #elif UINT8_MAX <= ULONG_MAX | |
| 783 | typedef unsigned long zig_promoted_u8; | |
| 784 | #elif UINT8_MAX <= ULLONG_MAX | |
| 785 | typedef unsigned long long zig_promoted_u8; | |
| 786 | #else | |
| 787 | typedef uint8_t zig_promoted_u8; | |
| 788 | #endif | |
| 789 | ||
| 790 | #if INT16_MAX <= INT_MAX | |
| 791 | typedef unsigned int zig_promoted_i16; | |
| 792 | #elif INT16_MAX <= LONG_MAX | |
| 793 | typedef unsigned long zig_promoted_i16; | |
| 794 | #elif INT16_MAX <= LLONG_MAX | |
| 795 | typedef unsigned long long zig_promoted_i16; | |
| 796 | #else | |
| 797 | typedef int16_t zig_promoted_i16; | |
| 798 | #endif | |
| 799 | #if UINT16_MAX <= UINT_MAX | |
| 800 | typedef unsigned int zig_promoted_u16; | |
| 801 | #elif UINT16_MAX <= ULONG_MAX | |
| 802 | typedef unsigned long zig_promoted_u16; | |
| 803 | #elif UINT16_MAX <= ULLONG_MAX | |
| 804 | typedef unsigned long long zig_promoted_u16; | |
| 805 | #else | |
| 806 | typedef uint16_t zig_promoted_u16; | |
| 807 | #endif | |
| 808 | ||
| 809 | #if INT32_MAX <= INT_MAX | |
| 810 | typedef unsigned int zig_promoted_i32; | |
| 811 | #elif INT32_MAX <= LONG_MAX | |
| 812 | typedef unsigned long zig_promoted_i32; | |
| 813 | #elif INT32_MAX <= LLONG_MAX | |
| 814 | typedef unsigned long long zig_promoted_i32; | |
| 815 | #else | |
| 816 | typedef int32_t zig_promoted_i32; | |
| 817 | #endif | |
| 818 | #if UINT32_MAX <= UINT_MAX | |
| 819 | typedef unsigned int zig_promoted_u32; | |
| 820 | #elif UINT32_MAX <= ULONG_MAX | |
| 821 | typedef unsigned long zig_promoted_u32; | |
| 822 | #elif UINT32_MAX <= ULLONG_MAX | |
| 823 | typedef unsigned long long zig_promoted_u32; | |
| 824 | #else | |
| 825 | typedef uint32_t zig_promoted_u32; | |
| 826 | #endif | |
| 827 | ||
| 828 | #if INT64_MAX <= INT_MAX | |
| 829 | typedef unsigned int zig_promoted_i64; | |
| 830 | #elif INT64_MAX <= LONG_MAX | |
| 831 | typedef unsigned long zig_promoted_i64; | |
| 832 | #elif INT64_MAX <= LLONG_MAX | |
| 833 | typedef unsigned long long zig_promoted_i64; | |
| 834 | #else | |
| 835 | typedef int64_t zig_promoted_i64; | |
| 836 | #endif | |
| 837 | #if UINT64_MAX <= UINT_MAX | |
| 838 | typedef unsigned int zig_promoted_u64; | |
| 839 | #elif UINT64_MAX <= ULONG_MAX | |
| 840 | typedef unsigned long zig_promoted_u64; | |
| 841 | #elif UINT64_MAX <= ULLONG_MAX | |
| 842 | typedef unsigned long long zig_promoted_u64; | |
| 843 | #else | |
| 844 | typedef 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 | |
| 859 | typedef unsigned int zig_promoted_i24; | |
| 860 | #elif INT24_MAX <= LONG_MAX | |
| 861 | typedef unsigned long zig_promoted_i24; | |
| 862 | #elif INT24_MAX <= LLONG_MAX | |
| 863 | typedef unsigned long long zig_promoted_i24; | |
| 864 | #else | |
| 865 | typedef int24_t zig_promoted_i24; | |
| 866 | #endif | |
| 867 | #if UINT24_MAX <= UINT_MAX | |
| 868 | typedef unsigned int zig_promoted_u24; | |
| 869 | #elif UINT24_MAX <= ULONG_MAX | |
| 870 | typedef unsigned long zig_promoted_u24; | |
| 871 | #elif UINT24_MAX <= ULLONG_MAX | |
| 872 | typedef unsigned long long zig_promoted_u24; | |
| 873 | #else | |
| 874 | typedef uint24_t zig_promoted_u24; | |
| 875 | #endif | |
| 876 | ||
| 877 | #if INT48_MAX <= INT_MAX | |
| 878 | typedef unsigned int zig_promoted_i48; | |
| 879 | #elif INT48_MAX <= LONG_MAX | |
| 880 | typedef unsigned long zig_promoted_i48; | |
| 881 | #elif INT48_MAX <= LLONG_MAX | |
| 882 | typedef unsigned long long zig_promoted_i48; | |
| 883 | #else | |
| 884 | typedef int48_t zig_promoted_i48; | |
| 885 | #endif | |
| 886 | #if UINT48_MAX <= UINT_MAX | |
| 887 | typedef unsigned int zig_promoted_u48; | |
| 888 | #elif UINT48_MAX <= ULONG_MAX | |
| 889 | typedef unsigned long zig_promoted_u48; | |
| 890 | #elif UINT48_MAX <= ULLONG_MAX | |
| 891 | typedef unsigned long long zig_promoted_u48; | |
| 892 | #else | |
| 893 | typedef uint48_t zig_promoted_u48; | |
| 894 | #endif | |
| 895 | ||
| 896 | #endif | |
| 897 | ||
| 759 | 898 | #define zig_intLimit(s, w, limit, bits) zig_shr_##s##w(zig_##limit##Int_##s##w, w - (bits)) |
| 760 | 899 | #define zig_minInt_i(w, bits) zig_intLimit(i, w, min, bits) |
| 761 | 900 | #define zig_maxInt_i(w, bits) zig_intLimit(i, w, max, bits) |
| ... | ... | @@ -770,7 +909,33 @@ typedef ptrdiff_t intptr_t; |
| 770 | 909 | zig_operator(Type, Type, operation, operator) |
| 771 | 910 | #define zig_shift_operator(Type, operation, operator) \ |
| 772 | 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 | 939 | zig_basic_operator(uint##w##_t, and_u##w, &) \ |
| 775 | 940 | zig_basic_operator( int##w##_t, and_i##w, &) \ |
| 776 | 941 | zig_basic_operator(uint##w##_t, or_u##w, |) \ |
| ... | ... | @@ -786,44 +951,48 @@ typedef ptrdiff_t intptr_t; |
| 786 | 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) { \ | |
| 790 | return val ^ zig_maxInt_u(w, bits); \ | |
| 954 | static inline uint##w##_t zig_not_u##w(uint##w##_t arg, uint8_t bits) { \ | |
| 955 | return arg ^ zig_maxInt_u(w, bits); \ | |
| 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 | 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) { \ | |
| 799 | return val & zig_maxInt_u(w, bits); \ | |
| 963 | zig_basic_operator(uint##w##_t, divFloor_u##w, /) \ | |
| 964 | \ | |
| 965 | static inline int##w##_t zig_divFloor_i##w(int##w##_t lhs, int##w##_t rhs) { \ | |
| 966 | return lhs / rhs + (lhs % rhs != INT##w##_C(0) ? zig_shr_i##w(lhs ^ rhs, UINT8_C(w) - UINT8_C(1)) : INT##w##_C(0)); \ | |
| 800 | 967 | } \ |
| 801 | 968 | \ |
| 802 | static inline int##w##_t zig_wrap_i##w(int##w##_t val, uint8_t bits) { \ | |
| 803 | return (val & UINT##w##_C(1) << (bits - UINT8_C(1))) != 0 \ | |
| 804 | ? val | zig_minInt_i(w, bits) : val & zig_maxInt_i(w, bits); \ | |
| 969 | static inline uint##w##_t zig_divCeil_u##w(uint##w##_t lhs, uint##w##_t rhs) { \ | |
| 970 | return lhs / rhs + (lhs % rhs != UINT##w##_C(0) ? UINT##w##_C(1) : UINT##w##_C(0)); \ | |
| 805 | 971 | } \ |
| 806 | 972 | \ |
| 807 | static inline uint##w##_t zig_abs_i##w(int##w##_t val) { \ | |
| 808 | return (val < 0) ? -(uint##w##_t)val : (uint##w##_t)val; \ | |
| 973 | static inline int##w##_t zig_divCeil_i##w(int##w##_t lhs, int##w##_t rhs) { \ | |
| 974 | return lhs / rhs + (lhs % rhs != INT##w##_C(0) \ | |
| 975 | ? zig_shr_i##w(lhs ^ rhs, UINT8_C(w) - UINT8_C(1)) + INT##w##_C(1) : INT##w##_C(0)); \ | |
| 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) { \ | |
| 814 | return lhs / rhs + (lhs % rhs != INT##w##_C(0) ? zig_shr_i##w(lhs ^ rhs, UINT8_C(w) - UINT8_C(1)) : INT##w##_C(0)); \ | |
| 981 | static inline uint##w##_t zig_u##w##_bitCast_u##w(uint##w##_t arg, uint8_t bits) { \ | |
| 982 | return zig_u##w##_truncate_u##w(arg, bits); \ | |
| 815 | 983 | } \ |
| 816 | 984 | \ |
| 817 | static inline uint##w##_t zig_div_ceil_u##w(uint##w##_t lhs, uint##w##_t rhs) { \ | |
| 818 | return lhs / rhs + (lhs % rhs != UINT##w##_C(0) ? UINT##w##_C(1) : UINT##w##_C(0)); \ | |
| 985 | static inline uint##w##_t zig_u##w##_bitCast_i##w(int##w##_t arg, uint8_t bits) { \ | |
| 986 | return zig_u##w##_bitCast_u##w((uint##w##_t)arg, bits); \ | |
| 819 | 987 | } \ |
| 820 | 988 | \ |
| 821 | static inline int##w##_t zig_div_ceil_i##w(int##w##_t lhs, int##w##_t rhs) { \ | |
| 822 | return lhs / rhs + (lhs % rhs != INT##w##_C(0) \ | |
| 823 | ? zig_shr_i##w(lhs ^ rhs, UINT8_C(w) - UINT8_C(1)) + INT##w##_C(1) : INT##w##_C(0)); \ | |
| 989 | static inline int##w##_t zig_i##w##_bitCast_i##w(int##w##_t arg, uint8_t bits) { \ | |
| 990 | return zig_i##w##_truncate_i##w(arg, bits); \ | |
| 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 | 997 | static inline int##w##_t zig_mod_i##w(int##w##_t lhs, int##w##_t rhs) { \ |
| 829 | 998 | int##w##_t rem = lhs % rhs; \ |
| ... | ... | @@ -831,100 +1000,102 @@ typedef ptrdiff_t intptr_t; |
| 831 | 1000 | } \ |
| 832 | 1001 | \ |
| 833 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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_MAX | |
| 865 | zig_int_helpers(8, unsigned int) | |
| 866 | #elif UINT8_MAX <= ULONG_MAX | |
| 867 | zig_int_helpers(8, unsigned long) | |
| 868 | #elif UINT8_MAX <= ULLONG_MAX | |
| 869 | zig_int_helpers(8, unsigned long long) | |
| 870 | #else | |
| 871 | zig_int_helpers(8, uint8_t) | |
| 872 | #endif | |
| 873 | #if UINT16_MAX <= UINT_MAX | |
| 874 | zig_int_helpers(16, unsigned int) | |
| 875 | #elif UINT16_MAX <= ULONG_MAX | |
| 876 | zig_int_helpers(16, unsigned long) | |
| 877 | #elif UINT16_MAX <= ULLONG_MAX | |
| 878 | zig_int_helpers(16, unsigned long long) | |
| 879 | #else | |
| 880 | zig_int_helpers(16, uint16_t) | |
| 881 | #endif | |
| 882 | #if defined(zig_ez80) | |
| 883 | #if UINT24_MAX <= UINT_MAX | |
| 884 | zig_int_helpers(24, unsigned int) | |
| 885 | #elif UINT24_MAX <= ULONG_MAX | |
| 886 | zig_int_helpers(24, unsigned long) | |
| 887 | #elif UINT24_MAX <= ULLONG_MAX | |
| 888 | zig_int_helpers(24, unsigned long long) | |
| 889 | #else | |
| 890 | zig_int_helpers(24, uint24_t) | |
| 891 | #endif | |
| 892 | #endif | |
| 893 | #if UINT32_MAX <= UINT_MAX | |
| 894 | zig_int_helpers(32, unsigned int) | |
| 895 | #elif UINT32_MAX <= ULONG_MAX | |
| 896 | zig_int_helpers(32, unsigned long) | |
| 897 | #elif UINT32_MAX <= ULLONG_MAX | |
| 898 | zig_int_helpers(32, unsigned long long) | |
| 899 | #else | |
| 900 | zig_int_helpers(32, uint32_t) | |
| 901 | #endif | |
| 902 | #if defined(zig_ez80) | |
| 903 | #if UINT24_MAX <= UINT_MAX | |
| 904 | zig_int_helpers(48, unsigned int) | |
| 905 | #elif UINT24_MAX <= ULONG_MAX | |
| 906 | zig_int_helpers(48, unsigned long) | |
| 907 | #elif UINT24_MAX <= ULLONG_MAX | |
| 908 | zig_int_helpers(48, unsigned long long) | |
| 909 | #else | |
| 910 | zig_int_helpers(48, uint48_t) | |
| 911 | #endif | |
| 912 | #endif | |
| 913 | #if UINT64_MAX <= UINT_MAX | |
| 914 | zig_int_helpers(64, unsigned int) | |
| 915 | #elif UINT64_MAX <= ULONG_MAX | |
| 916 | zig_int_helpers(64, unsigned long) | |
| 917 | #elif UINT64_MAX <= ULLONG_MAX | |
| 918 | zig_int_helpers(64, unsigned long long) | |
| 919 | #else | |
| 920 | zig_int_helpers(64, uint64_t) | |
| 1054 | zig_int_operators(8) | |
| 1055 | zig_int_operators(16) | |
| 1056 | zig_int_operators(32) | |
| 1057 | zig_int_operators(64) | |
| 1058 | #ifdef zig_ez80 | |
| 1059 | zig_int_operators(24) | |
| 1060 | zig_int_operators(48) | |
| 1061 | #endif | |
| 1062 | ||
| 1063 | #define zig_int_casts(bw, sw) \ | |
| 1064 | static inline uint##sw##_t zig_u##sw##_intCast_u##bw(uint##bw##_t arg) { \ | |
| 1065 | return (uint##sw##_t)arg; \ | |
| 1066 | } \ | |
| 1067 | \ | |
| 1068 | static inline uint##sw##_t zig_u##sw##_intCast_i##bw(int##bw##_t arg) { \ | |
| 1069 | return (uint##sw##_t)arg; \ | |
| 1070 | } \ | |
| 1071 | \ | |
| 1072 | static inline int##sw##_t zig_i##sw##_intCast_u##bw(uint##bw##_t arg) { \ | |
| 1073 | return (int##sw##_t)arg; \ | |
| 1074 | } \ | |
| 1075 | \ | |
| 1076 | static inline int##sw##_t zig_i##sw##_intCast_i##bw(int##bw##_t arg) { \ | |
| 1077 | return (int##sw##_t)arg; \ | |
| 1078 | } \ | |
| 1079 | \ | |
| 1080 | zig_int_casts_common(bw, sw) | |
| 1081 | zig_int_casts(16, 8) | |
| 1082 | zig_int_casts(32, 8) | |
| 1083 | zig_int_casts(64, 8) | |
| 1084 | zig_int_casts(32, 16) | |
| 1085 | zig_int_casts(64, 16) | |
| 1086 | zig_int_casts(64, 32) | |
| 1087 | #ifdef zig_ez80 | |
| 1088 | zig_int_casts(32, 24) | |
| 1089 | zig_int_casts(48, 24) | |
| 1090 | zig_int_casts(64, 24) | |
| 1091 | zig_int_casts(64, 48) | |
| 921 | 1092 | #endif |
| 922 | 1093 | |
| 923 | 1094 | static inline bool zig_addo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) { |
| 924 | 1095 | #if zig_has_builtin(add_overflow) || defined(zig_gcc) |
| 925 | 1096 | uint32_t full_res; |
| 926 | 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 | 1099 | return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits); |
| 929 | 1100 | #else |
| 930 | 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 | 1107 | #if zig_has_builtin(add_overflow) || defined(zig_gcc) |
| 937 | 1108 | int32_t full_res; |
| 938 | 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 | 1112 | #else |
| 940 | int32_t full_res = (int32_t)((uint32_t)lhs + (uint32_t)rhs); | |
| 941 | bool overflow = ((full_res ^ lhs) & (full_res ^ rhs)) < 0; | |
| 1113 | *res = zig_addw_i32(lhs, rhs, bits); | |
| 1114 | return ((*res ^ lhs) & (*res ^ rhs)) < INT32_C(0); | |
| 942 | 1115 | #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 | } |
| 946 | 1117 | |
| 947 | 1118 | static inline bool zig_addo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8_t bits) { |
| 948 | 1119 | #if zig_has_builtin(add_overflow) || defined(zig_gcc) |
| 949 | 1120 | uint64_t full_res; |
| 950 | 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 | 1123 | return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits); |
| 953 | 1124 | #else |
| 954 | 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 | 1131 | #if zig_has_builtin(add_overflow) || defined(zig_gcc) |
| 961 | 1132 | int64_t full_res; |
| 962 | 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 | 1136 | #else |
| 964 | int64_t full_res = (int64_t)((uint64_t)lhs + (uint64_t)rhs); | |
| 965 | bool overflow = ((full_res ^ lhs) & (full_res ^ rhs)) < 0; | |
| 1137 | *res = zig_addw_i64(lhs, rhs, bits); | |
| 1138 | return ((*res ^ lhs) & (*res ^ rhs)) < INT64_C(0); | |
| 966 | 1139 | #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 | } |
| 970 | 1141 | |
| 971 | 1142 | static inline bool zig_addo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t bits) { |
| 972 | 1143 | #if zig_has_builtin(add_overflow) || defined(zig_gcc) |
| 973 | 1144 | uint8_t full_res; |
| 974 | 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 | 1147 | return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits); |
| 977 | 1148 | #else |
| 978 | 1149 | uint32_t full_res; |
| 979 | 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 | 1152 | return overflow; |
| 982 | 1153 | #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 | 1157 | #if zig_has_builtin(add_overflow) || defined(zig_gcc) |
| 987 | 1158 | int8_t full_res; |
| 988 | 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 | 1161 | return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits); |
| 991 | 1162 | #else |
| 992 | 1163 | int32_t full_res; |
| 993 | 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 | 1166 | return overflow; |
| 996 | 1167 | #endif |
| 997 | 1168 | } |
| ... | ... | @@ -1000,12 +1171,12 @@ static inline bool zig_addo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8 |
| 1000 | 1171 | #if zig_has_builtin(add_overflow) || defined(zig_gcc) |
| 1001 | 1172 | uint16_t full_res; |
| 1002 | 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 | 1175 | return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits); |
| 1005 | 1176 | #else |
| 1006 | 1177 | uint32_t full_res; |
| 1007 | 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 | 1180 | return overflow; |
| 1010 | 1181 | #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 | 1185 | #if zig_has_builtin(add_overflow) || defined(zig_gcc) |
| 1015 | 1186 | int16_t full_res; |
| 1016 | 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 | 1189 | return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits); |
| 1019 | 1190 | #else |
| 1020 | 1191 | int32_t full_res; |
| 1021 | 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 | 1194 | return overflow; |
| 1024 | 1195 | #endif |
| 1025 | 1196 | } |
| 1026 | 1197 | |
| 1027 | 1198 | #if defined(zig_ez80) |
| 1199 | ||
| 1028 | 1200 | static inline bool zig_addo_u24(uint24_t *res, uint24_t lhs, uint24_t rhs, uint8_t bits) { |
| 1029 | 1201 | #if zig_has_builtin(add_overflow) || defined(zig_gcc) |
| 1030 | 1202 | uint24_t full_res; |
| 1031 | 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 | 1205 | return overflow || full_res < zig_minInt_u(24, bits) || full_res > zig_maxInt_u(24, bits); |
| 1034 | 1206 | #else |
| 1035 | 1207 | uint32_t full_res; |
| 1036 | 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 | 1210 | return overflow; |
| 1039 | 1211 | #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 | 1215 | #if zig_has_builtin(add_overflow) || defined(zig_gcc) |
| 1044 | 1216 | int24_t full_res; |
| 1045 | 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 | 1219 | return overflow || full_res < zig_minInt_i(24, bits) || full_res > zig_maxInt_i(24, bits); |
| 1048 | 1220 | #else |
| 1049 | 1221 | int32_t full_res; |
| 1050 | 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 | 1224 | return overflow; |
| 1053 | 1225 | #endif |
| 1054 | 1226 | } |
| 1055 | #endif | |
| 1056 | 1227 | |
| 1057 | #if defined(zig_ez80) | |
| 1058 | 1228 | static inline bool zig_addo_u48(uint48_t *res, uint48_t lhs, uint48_t rhs, uint8_t bits) { |
| 1059 | 1229 | #if zig_has_builtin(add_overflow) || defined(zig_gcc) |
| 1060 | 1230 | uint48_t full_res; |
| 1061 | 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 | 1233 | return overflow || full_res < zig_minInt_u(48, bits) || full_res > zig_maxInt_u(48, bits); |
| 1064 | 1234 | #else |
| 1065 | 1235 | uint64_t full_res; |
| 1066 | 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 | 1238 | return overflow; |
| 1069 | 1239 | #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 | 1243 | #if zig_has_builtin(add_overflow) || defined(zig_gcc) |
| 1074 | 1244 | int48_t full_res; |
| 1075 | 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 | 1247 | return overflow || full_res < zig_minInt_i(48, bits) || full_res > zig_maxInt_i(48, bits); |
| 1078 | 1248 | #else |
| 1079 | 1249 | int64_t full_res; |
| 1080 | 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 | 1252 | return overflow; |
| 1083 | 1253 | #endif |
| 1084 | 1254 | } |
| 1255 | ||
| 1085 | 1256 | #endif |
| 1086 | 1257 | |
| 1087 | 1258 | static inline bool zig_subo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) { |
| 1088 | 1259 | #if zig_has_builtin(sub_overflow) || defined(zig_gcc) |
| 1089 | 1260 | uint32_t full_res; |
| 1090 | 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 | 1263 | return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits); |
| 1093 | 1264 | #else |
| 1094 | 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 | 1271 | #if zig_has_builtin(sub_overflow) || defined(zig_gcc) |
| 1101 | 1272 | int32_t full_res; |
| 1102 | 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 | 1276 | #else |
| 1104 | int32_t full_res = (int32_t)((uint32_t)lhs - (uint32_t)rhs); | |
| 1105 | bool overflow = ((lhs ^ rhs) & (full_res ^ lhs)) < 0; | |
| 1277 | *res = zig_subw_i32(lhs, rhs, bits); | |
| 1278 | return ((lhs ^ rhs) & (*res ^ lhs)) < INT32_C(0); | |
| 1106 | 1279 | #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 | } |
| 1110 | 1281 | |
| 1111 | ||
| 1112 | 1282 | static inline bool zig_subo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8_t bits) { |
| 1113 | 1283 | #if zig_has_builtin(sub_overflow) || defined(zig_gcc) |
| 1114 | 1284 | uint64_t full_res; |
| 1115 | 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 | 1287 | return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits); |
| 1118 | 1288 | #else |
| 1119 | 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 | 1295 | #if zig_has_builtin(sub_overflow) || defined(zig_gcc) |
| 1126 | 1296 | int64_t full_res; |
| 1127 | 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 | 1300 | #else |
| 1129 | int64_t full_res = (int64_t)((uint64_t)lhs - (uint64_t)rhs); | |
| 1130 | bool overflow = ((lhs ^ rhs) & (full_res ^ lhs)) < 0; | |
| 1301 | *res = zig_subw_i64(lhs, rhs, bits); | |
| 1302 | return ((lhs ^ rhs) & (*res ^ lhs)) < INT64_C(0); | |
| 1131 | 1303 | #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 | } |
| 1135 | 1305 | |
| 1136 | 1306 | static inline bool zig_subo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t bits) { |
| 1137 | 1307 | #if zig_has_builtin(sub_overflow) || defined(zig_gcc) |
| 1138 | 1308 | uint8_t full_res; |
| 1139 | 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 | 1311 | return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits); |
| 1142 | 1312 | #else |
| 1143 | 1313 | uint32_t full_res; |
| 1144 | 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 | 1316 | return overflow; |
| 1147 | 1317 | #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 | 1321 | #if zig_has_builtin(sub_overflow) || defined(zig_gcc) |
| 1152 | 1322 | int8_t full_res; |
| 1153 | 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 | 1325 | return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits); |
| 1156 | 1326 | #else |
| 1157 | 1327 | int32_t full_res; |
| 1158 | 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 | 1330 | return overflow; |
| 1161 | 1331 | #endif |
| 1162 | 1332 | } |
| ... | ... | @@ -1165,12 +1335,12 @@ static inline bool zig_subo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8 |
| 1165 | 1335 | #if zig_has_builtin(sub_overflow) || defined(zig_gcc) |
| 1166 | 1336 | uint16_t full_res; |
| 1167 | 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 | 1339 | return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits); |
| 1170 | 1340 | #else |
| 1171 | 1341 | uint32_t full_res; |
| 1172 | 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 | 1344 | return overflow; |
| 1175 | 1345 | #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 | 1349 | #if zig_has_builtin(sub_overflow) || defined(zig_gcc) |
| 1180 | 1350 | int16_t full_res; |
| 1181 | 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 | 1353 | return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits); |
| 1184 | 1354 | #else |
| 1185 | 1355 | int32_t full_res; |
| 1186 | 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 | 1358 | return overflow; |
| 1189 | 1359 | #endif |
| 1190 | 1360 | } |
| 1191 | 1361 | |
| 1192 | 1362 | #if defined(zig_ez80) |
| 1363 | ||
| 1193 | 1364 | static inline bool zig_subo_u24(uint24_t *res, uint24_t lhs, uint24_t rhs, uint8_t bits) { |
| 1194 | 1365 | #if zig_has_builtin(sub_overflow) || defined(zig_gcc) |
| 1195 | 1366 | uint24_t full_res; |
| 1196 | 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 | 1369 | return overflow || full_res < zig_minInt_u(24, bits) || full_res > zig_maxInt_u(24, bits); |
| 1199 | 1370 | #else |
| 1200 | 1371 | uint32_t full_res; |
| 1201 | 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 | 1374 | return overflow; |
| 1204 | 1375 | #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 | 1379 | #if zig_has_builtin(sub_overflow) || defined(zig_gcc) |
| 1209 | 1380 | int24_t full_res; |
| 1210 | 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 | 1383 | return overflow || full_res < zig_minInt_i(24, bits) || full_res > zig_maxInt_i(24, bits); |
| 1213 | 1384 | #else |
| 1214 | 1385 | int32_t full_res; |
| 1215 | 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 | 1388 | return overflow; |
| 1218 | 1389 | #endif |
| 1219 | 1390 | } |
| 1220 | #endif | |
| 1221 | 1391 | |
| 1222 | #if defined(zig_ez80) | |
| 1223 | 1392 | static inline bool zig_subo_u48(uint48_t *res, uint48_t lhs, uint48_t rhs, uint8_t bits) { |
| 1224 | 1393 | #if zig_has_builtin(sub_overflow) || defined(zig_gcc) |
| 1225 | 1394 | uint48_t full_res; |
| 1226 | 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 | 1397 | return overflow || full_res < zig_minInt_u(48, bits) || full_res > zig_maxInt_u(48, bits); |
| 1229 | 1398 | #else |
| 1230 | 1399 | uint64_t full_res; |
| 1231 | 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 | 1402 | return overflow; |
| 1234 | 1403 | #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 | 1407 | #if zig_has_builtin(sub_overflow) || defined(zig_gcc) |
| 1239 | 1408 | int48_t full_res; |
| 1240 | 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 | 1411 | return overflow || full_res < zig_minInt_i(48, bits) || full_res > zig_maxInt_i(48, bits); |
| 1243 | 1412 | #else |
| 1244 | 1413 | int64_t full_res; |
| 1245 | 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 | 1416 | return overflow; |
| 1248 | 1417 | #endif |
| 1249 | 1418 | } |
| 1419 | ||
| 1250 | 1420 | #endif |
| 1251 | 1421 | |
| 1252 | 1422 | static inline bool zig_mulo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) { |
| 1253 | 1423 | #if zig_has_builtin(mul_overflow) || defined(zig_gcc) |
| 1254 | 1424 | uint32_t full_res; |
| 1255 | 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 | 1427 | return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits); |
| 1258 | 1428 | #else |
| 1259 | 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 | 1431 | #endif |
| 1262 | 1432 | } |
| 1263 | 1433 | |
| 1264 | zig_extern int32_t __mulosi4(int32_t lhs, int32_t rhs, int *overflow); | |
| 1265 | 1434 | static 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 | 1436 | #if zig_has_builtin(mul_overflow) || defined(zig_gcc) |
| 1267 | 1437 | int32_t full_res; |
| 1268 | 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 | 1441 | int32_t full_res = __mulosi4(lhs, rhs, &overflow_int); |
| 1272 | 1442 | bool overflow = overflow_int != 0; |
| 1273 | 1443 | #endif |
| 1274 | *res = zig_wrap_i32(full_res, bits); | |
| 1444 | *res = zig_i32_truncate_i32(full_res, bits); | |
| 1275 | 1445 | return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits); |
| 1276 | 1446 | } |
| 1277 | 1447 | |
| ... | ... | @@ -1279,7 +1449,7 @@ static inline bool zig_mulo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8 |
| 1279 | 1449 | #if zig_has_builtin(mul_overflow) || defined(zig_gcc) |
| 1280 | 1450 | uint64_t full_res; |
| 1281 | 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 | 1453 | return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits); |
| 1284 | 1454 | #else |
| 1285 | 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 | 1457 | #endif |
| 1288 | 1458 | } |
| 1289 | 1459 | |
| 1290 | zig_extern int64_t __mulodi4(int64_t lhs, int64_t rhs, int *overflow); | |
| 1291 | 1460 | static 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 | 1462 | #if zig_has_builtin(mul_overflow) || defined(zig_gcc) |
| 1293 | 1463 | int64_t full_res; |
| 1294 | 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 | 1467 | int64_t full_res = __mulodi4(lhs, rhs, &overflow_int); |
| 1298 | 1468 | bool overflow = overflow_int != 0; |
| 1299 | 1469 | #endif |
| 1300 | *res = zig_wrap_i64(full_res, bits); | |
| 1470 | *res = zig_i64_truncate_i64(full_res, bits); | |
| 1301 | 1471 | return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits); |
| 1302 | 1472 | } |
| 1303 | 1473 | |
| ... | ... | @@ -1305,12 +1475,12 @@ static inline bool zig_mulo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t b |
| 1305 | 1475 | #if zig_has_builtin(mul_overflow) || defined(zig_gcc) |
| 1306 | 1476 | uint8_t full_res; |
| 1307 | 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 | 1479 | return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits); |
| 1310 | 1480 | #else |
| 1311 | 1481 | uint32_t full_res; |
| 1312 | 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 | 1484 | return overflow; |
| 1315 | 1485 | #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 | 1489 | #if zig_has_builtin(mul_overflow) || defined(zig_gcc) |
| 1320 | 1490 | int8_t full_res; |
| 1321 | 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 | 1493 | return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits); |
| 1324 | 1494 | #else |
| 1325 | 1495 | int32_t full_res; |
| 1326 | 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 | 1498 | return overflow; |
| 1329 | 1499 | #endif |
| 1330 | 1500 | } |
| ... | ... | @@ -1333,12 +1503,12 @@ static inline bool zig_mulo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8 |
| 1333 | 1503 | #if zig_has_builtin(mul_overflow) || defined(zig_gcc) |
| 1334 | 1504 | uint16_t full_res; |
| 1335 | 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 | 1507 | return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits); |
| 1338 | 1508 | #else |
| 1339 | 1509 | uint32_t full_res; |
| 1340 | 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 | 1512 | return overflow; |
| 1343 | 1513 | #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 | 1517 | #if zig_has_builtin(mul_overflow) || defined(zig_gcc) |
| 1348 | 1518 | int16_t full_res; |
| 1349 | 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 | 1521 | return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits); |
| 1352 | 1522 | #else |
| 1353 | 1523 | int32_t full_res; |
| 1354 | 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 | 1526 | return overflow; |
| 1357 | 1527 | #endif |
| 1358 | 1528 | } |
| 1359 | 1529 | |
| 1360 | 1530 | #if defined(zig_ez80) |
| 1531 | ||
| 1361 | 1532 | static inline bool zig_mulo_u24(uint24_t *res, uint24_t lhs, uint24_t rhs, uint8_t bits) { |
| 1362 | 1533 | #if zig_has_builtin(mul_overflow) || defined(zig_gcc) |
| 1363 | 1534 | uint24_t full_res; |
| 1364 | 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 | 1537 | return overflow || full_res < zig_minInt_u(24, bits) || full_res > zig_maxInt_u(24, bits); |
| 1367 | 1538 | #else |
| 1368 | 1539 | uint32_t full_res; |
| 1369 | 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 | 1542 | return overflow; |
| 1372 | 1543 | #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 | 1547 | #if zig_has_builtin(mul_overflow) || defined(zig_gcc) |
| 1377 | 1548 | int24_t full_res; |
| 1378 | 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 | 1551 | return overflow || full_res < zig_minInt_i(24, bits) || full_res > zig_maxInt_i(24, bits); |
| 1381 | 1552 | #else |
| 1382 | 1553 | int32_t full_res; |
| 1383 | 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 | 1556 | return overflow; |
| 1386 | 1557 | #endif |
| 1387 | 1558 | } |
| 1388 | #endif | |
| 1389 | 1559 | |
| 1390 | #if defined(zig_ez80) | |
| 1391 | 1560 | static inline bool zig_mulo_u48(uint48_t *res, uint48_t lhs, uint48_t rhs, uint8_t bits) { |
| 1392 | 1561 | #if zig_has_builtin(mul_overflow) || defined(zig_gcc) |
| 1393 | 1562 | uint48_t full_res; |
| 1394 | 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 | 1565 | return overflow || full_res < zig_minInt_u(48, bits) || full_res > zig_maxInt_u(48, bits); |
| 1397 | 1566 | #else |
| 1398 | 1567 | uint64_t full_res; |
| 1399 | 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 | 1570 | return overflow; |
| 1402 | 1571 | #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 | 1575 | #if zig_has_builtin(mul_overflow) || defined(zig_gcc) |
| 1407 | 1576 | int48_t full_res; |
| 1408 | 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 | 1579 | return overflow || full_res < zig_minInt_i(48, bits) || full_res > zig_maxInt_i(48, bits); |
| 1411 | 1580 | #else |
| 1412 | 1581 | int64_t full_res; |
| 1413 | 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 | 1584 | return overflow; |
| 1416 | 1585 | #endif |
| 1417 | 1586 | } |
| 1587 | ||
| 1418 | 1588 | #endif |
| 1419 | 1589 | |
| 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 | 1604 | static inline bool zig_shlo_u##w(uint##w##_t *res, uint##w##_t lhs, uint8_t rhs, uint8_t bits) { \ |
| 1422 | 1605 | *res = zig_shlw_u##w(lhs, rhs, bits); \ |
| 1423 | 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 | 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) { \ | |
| 1433 | uint##w##_t res; \ | |
| 1434 | if (rhs < bits && !zig_shlo_u##w(&res, lhs, rhs, bits)) return res; \ | |
| 1435 | return lhs == INT##w##_C(0) ? INT##w##_C(0) : zig_maxInt_u(w, bits); \ | |
| 1436 | } \ | |
| 1437 | \ | |
| 1438 | static inline int##w##_t zig_shls_i##w(int##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \ | |
| 1439 | int##w##_t res; \ | |
| 1440 | if (rhs < bits && !zig_shlo_i##w(&res, lhs, rhs, bits)) return res; \ | |
| 1441 | return lhs == INT##w##_C(0) ? INT##w##_C(0) : \ | |
| 1442 | lhs < INT##w##_C(0) ? zig_minInt_i(w, bits) : zig_maxInt_i(w, bits); \ | |
| 1443 | } \ | |
| 1615 | zig_shls_builtins(w, 8) \ | |
| 1616 | zig_shls_builtins(w, 16) \ | |
| 1617 | zig_shls_builtins(w, 32) \ | |
| 1618 | zig_shls_builtins(w, 64) \ | |
| 1444 | 1619 | \ |
| 1445 | 1620 | static inline uint##w##_t zig_adds_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \ |
| 1446 | 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 | 1649 | if (!zig_mulo_i##w(&res, lhs, rhs, bits)) return res; \ |
| 1475 | 1650 | return (lhs ^ rhs) < INT##w##_C(0) ? zig_minInt_i(w, bits) : zig_maxInt_i(w, bits); \ |
| 1476 | 1651 | } |
| 1477 | zig_int_builtins(8) | |
| 1478 | zig_int_builtins(16) | |
| 1479 | #if defined(zig_ez80) | |
| 1480 | zig_int_builtins(24) | |
| 1481 | #endif | |
| 1482 | zig_int_builtins(32) | |
| 1652 | zig_int_sat_builtins(8) | |
| 1653 | zig_int_sat_builtins(16) | |
| 1654 | zig_int_sat_builtins(32) | |
| 1655 | zig_int_sat_builtins(64) | |
| 1483 | 1656 | #if defined(zig_ez80) |
| 1484 | zig_int_builtins(48) | |
| 1657 | zig_int_sat_builtins(24) | |
| 1658 | zig_int_sat_builtins(48) | |
| 1485 | 1659 | #endif |
| 1486 | zig_int_builtins(64) | |
| 1487 | 1660 | |
| 1488 | #define zig_builtin8(name, val) __builtin_##name(val) | |
| 1661 | #define zig_builtin8(name, arg) __builtin_##name(arg) | |
| 1489 | 1662 | typedef unsigned int zig_Builtin8; |
| 1490 | 1663 | |
| 1491 | #define zig_builtin16(name, val) __builtin_##name(val) | |
| 1664 | #define zig_builtin16(name, arg) __builtin_##name(arg) | |
| 1492 | 1665 | typedef unsigned int zig_Builtin16; |
| 1493 | 1666 | |
| 1494 | #if defined(zig_ez80) | |
| 1495 | #define zig_builtin24(name, val) __builtin_##name(val) | |
| 1496 | typedef unsigned int zig_Builtin24; | |
| 1497 | #endif | |
| 1498 | ||
| 1499 | 1667 | #if INT_MIN <= INT32_MIN |
| 1500 | #define zig_builtin32(name, val) __builtin_##name(val) | |
| 1668 | #define zig_builtin32(name, arg) __builtin_##name(arg) | |
| 1501 | 1669 | typedef unsigned int zig_Builtin32; |
| 1502 | 1670 | #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) | |
| 1504 | 1672 | typedef unsigned long zig_Builtin32; |
| 1505 | 1673 | #endif |
| 1506 | 1674 | |
| 1507 | #if defined(zig_ez80) | |
| 1508 | #define zig_builtin48(name, val) __builtin_##name(val) | |
| 1509 | typedef unsigned long long zig_Builtin48; | |
| 1510 | #endif | |
| 1511 | ||
| 1512 | 1675 | #if INT_MIN <= INT64_MIN |
| 1513 | #define zig_builtin64(name, val) __builtin_##name(val) | |
| 1676 | #define zig_builtin64(name, arg) __builtin_##name(arg) | |
| 1514 | 1677 | typedef unsigned int zig_Builtin64; |
| 1515 | 1678 | #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) | |
| 1517 | 1680 | typedef unsigned long zig_Builtin64; |
| 1518 | 1681 | #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) | |
| 1520 | 1683 | typedef unsigned long long zig_Builtin64; |
| 1521 | 1684 | #endif |
| 1522 | 1685 | |
| 1523 | static inline uint8_t zig_byte_swap_u8(uint8_t val, uint8_t bits) { | |
| 1524 | return zig_wrap_u8(val >> (8 - bits), bits); | |
| 1686 | #if defined(zig_ez80) | |
| 1687 | #define zig_builtin24(name, arg) __builtin_##name(arg) | |
| 1688 | typedef unsigned int zig_Builtin24; | |
| 1689 | #define zig_builtin48(name, arg) __builtin_##name(arg) | |
| 1690 | typedef unsigned long long zig_Builtin48; | |
| 1691 | #endif | |
| 1692 | ||
| 1693 | static inline uint8_t zig_byteSwap_u8(uint8_t arg, uint8_t bits) { | |
| 1694 | return zig_u8_truncate_u8(arg >> (8 - bits), bits); | |
| 1525 | 1695 | } |
| 1526 | 1696 | |
| 1527 | static inline int8_t zig_byte_swap_i8(int8_t val, uint8_t bits) { | |
| 1528 | return zig_wrap_i8((int8_t)zig_byte_swap_u8((uint8_t)val, bits), bits); | |
| 1697 | static inline int8_t zig_byteSwap_i8(int8_t arg, uint8_t bits) { | |
| 1698 | return zig_i8_truncate_i8((int8_t)zig_byteSwap_u8((uint8_t)arg, bits), bits); | |
| 1529 | 1699 | } |
| 1530 | 1700 | |
| 1531 | static inline uint16_t zig_byte_swap_u16(uint16_t val, uint8_t bits) { | |
| 1701 | static inline uint16_t zig_byteSwap_u16(uint16_t arg, uint8_t bits) { | |
| 1532 | 1702 | uint16_t full_res; |
| 1533 | 1703 | #if zig_has_builtin(bswap16) || defined(zig_gcc) |
| 1534 | full_res = __builtin_bswap16(val); | |
| 1704 | full_res = __builtin_bswap16(arg); | |
| 1535 | 1705 | #else |
| 1536 | full_res = (uint16_t)zig_byte_swap_u8((uint8_t)(val >> 0), 8) << 8 | | |
| 1537 | (uint16_t)zig_byte_swap_u8((uint8_t)(val >> 8), 8) >> 0; | |
| 1706 | full_res = (uint16_t)zig_byteSwap_u8((uint8_t)(arg >> 0), 8) << 8 | | |
| 1707 | (uint16_t)zig_byteSwap_u8((uint8_t)(arg >> 8), 8) >> 0; | |
| 1538 | 1708 | #endif |
| 1539 | return zig_wrap_u16(full_res >> (16 - bits), bits); | |
| 1709 | return zig_u16_truncate_u16(full_res >> (16 - bits), bits); | |
| 1540 | 1710 | } |
| 1541 | 1711 | |
| 1542 | static inline int16_t zig_byte_swap_i16(int16_t val, uint8_t bits) { | |
| 1543 | return zig_wrap_i16((int16_t)zig_byte_swap_u16((uint16_t)val, bits), bits); | |
| 1712 | static inline int16_t zig_byteSwap_i16(int16_t arg, uint8_t bits) { | |
| 1713 | return zig_i16_truncate_i16((int16_t)zig_byteSwap_u16((uint16_t)arg, bits), bits); | |
| 1544 | 1714 | } |
| 1545 | 1715 | |
| 1546 | 1716 | #if defined(zig_ez80) |
| 1547 | static inline uint16_t zig_byte_swap_u24(uint24_t val, uint8_t bits) { | |
| 1717 | static inline uint16_t zig_byteSwap_u24(uint24_t arg, uint8_t bits) { | |
| 1548 | 1718 | uint24_t full_res; |
| 1549 | 1719 | #if zig_has_builtin(bswap24) || defined(zig_gcc) |
| 1550 | full_res = __builtin_bswap24(val); | |
| 1720 | full_res = __builtin_bswap24(arg); | |
| 1551 | 1721 | #else |
| 1552 | full_res = (uint24_t)zig_byte_swap_u8((uint8_t)(val >> 0), 8) << 16 | | |
| 1553 | (uint24_t)zig_byte_swap_u16((uint16_t)(val >> 8), 16) >> 0; | |
| 1722 | full_res = (uint24_t)zig_byteSwap_u8((uint8_t)(arg >> 0), 8) << 16 | | |
| 1723 | (uint24_t)zig_byteSwap_u16((uint16_t)(arg >> 8), 16) >> 0; | |
| 1554 | 1724 | #endif |
| 1555 | return zig_wrap_u24(full_res >> (24 - bits), bits); | |
| 1725 | return zig_u24_truncate_u24(full_res >> (24 - bits), bits); | |
| 1556 | 1726 | } |
| 1557 | 1727 | |
| 1558 | static inline int16_t zig_byte_swap_i24(int24_t val, uint8_t bits) { | |
| 1559 | return zig_wrap_i24((int24_t)zig_byte_swap_u24((uint24_t)val, bits), bits); | |
| 1728 | static inline int16_t zig_byteSwap_i24(int24_t arg, uint8_t bits) { | |
| 1729 | return zig_i24_truncate_i24((int24_t)zig_byteSwap_u24((uint24_t)arg, bits), bits); | |
| 1560 | 1730 | } |
| 1561 | 1731 | #endif |
| 1562 | 1732 | |
| 1563 | static inline uint32_t zig_byte_swap_u32(uint32_t val, uint8_t bits) { | |
| 1733 | static inline uint32_t zig_byteSwap_u32(uint32_t arg, uint8_t bits) { | |
| 1564 | 1734 | uint32_t full_res; |
| 1565 | 1735 | #if zig_has_builtin(bswap32) || defined(zig_gcc) |
| 1566 | full_res = __builtin_bswap32(val); | |
| 1736 | full_res = __builtin_bswap32(arg); | |
| 1567 | 1737 | #else |
| 1568 | full_res = (uint32_t)zig_byte_swap_u16((uint16_t)(val >> 0), 16) << 16 | | |
| 1569 | (uint32_t)zig_byte_swap_u16((uint16_t)(val >> 16), 16) >> 0; | |
| 1738 | full_res = (uint32_t)zig_byteSwap_u16((uint16_t)(arg >> 0), 16) << 16 | | |
| 1739 | (uint32_t)zig_byteSwap_u16((uint16_t)(arg >> 16), 16) >> 0; | |
| 1570 | 1740 | #endif |
| 1571 | return zig_wrap_u32(full_res >> (32 - bits), bits); | |
| 1741 | return zig_u32_truncate_u32(full_res >> (32 - bits), bits); | |
| 1572 | 1742 | } |
| 1573 | 1743 | |
| 1574 | static inline int32_t zig_byte_swap_i32(int32_t val, uint8_t bits) { | |
| 1575 | return zig_wrap_i32((int32_t)zig_byte_swap_u32((uint32_t)val, bits), bits); | |
| 1744 | static inline int32_t zig_byteSwap_i32(int32_t arg, uint8_t bits) { | |
| 1745 | return zig_i32_truncate_i32((int32_t)zig_byteSwap_u32((uint32_t)arg, bits), bits); | |
| 1576 | 1746 | } |
| 1577 | 1747 | |
| 1578 | 1748 | #if defined(zig_ez80) |
| 1579 | static inline uint32_t zig_byte_swap_u48(uint48_t val, uint8_t bits) { | |
| 1749 | static inline uint32_t zig_byteSwap_u48(uint48_t arg, uint8_t bits) { | |
| 1580 | 1750 | uint48_t full_res; |
| 1581 | 1751 | #if zig_has_builtin(bswap48) || defined(zig_gcc) |
| 1582 | full_res = __builtin_bswap48(val); | |
| 1752 | full_res = __builtin_bswap48(arg); | |
| 1583 | 1753 | #else |
| 1584 | full_res = (uint48_t)zig_byte_swap_u24((uint24_t)(val >> 0), 24) << 24 | | |
| 1585 | (uint48_t)zig_byte_swap_u24((uint24_t)(val >> 24), 24) >> 0; | |
| 1754 | full_res = (uint48_t)zig_byteSwap_u24((uint24_t)(arg >> 0), 24) << 24 | | |
| 1755 | (uint48_t)zig_byteSwap_u24((uint24_t)(arg >> 24), 24) >> 0; | |
| 1586 | 1756 | #endif |
| 1587 | return zig_wrap_u48(full_res >> (48 - bits), bits); | |
| 1757 | return zig_u48_truncate_u48(full_res >> (48 - bits), bits); | |
| 1588 | 1758 | } |
| 1589 | 1759 | |
| 1590 | static inline int32_t zig_byte_swap_i48(int48_t val, uint8_t bits) { | |
| 1591 | return zig_wrap_i48((int48_t)zig_byte_swap_u48((uint48_t)val, bits), bits); | |
| 1760 | static inline int32_t zig_byteSwap_i48(int48_t arg, uint8_t bits) { | |
| 1761 | return zig_i48_truncate_i48((int48_t)zig_byteSwap_u48((uint48_t)arg, bits), bits); | |
| 1592 | 1762 | } |
| 1593 | 1763 | #endif |
| 1594 | 1764 | |
| 1595 | static inline uint64_t zig_byte_swap_u64(uint64_t val, uint8_t bits) { | |
| 1765 | static inline uint64_t zig_byteSwap_u64(uint64_t arg, uint8_t bits) { | |
| 1596 | 1766 | uint64_t full_res; |
| 1597 | 1767 | #if zig_has_builtin(bswap64) || defined(zig_gcc) |
| 1598 | full_res = __builtin_bswap64(val); | |
| 1768 | full_res = __builtin_bswap64(arg); | |
| 1599 | 1769 | #else |
| 1600 | full_res = (uint64_t)zig_byte_swap_u32((uint32_t)(val >> 0), 32) << 32 | | |
| 1601 | (uint64_t)zig_byte_swap_u32((uint32_t)(val >> 32), 32) >> 0; | |
| 1770 | full_res = (uint64_t)zig_byteSwap_u32((uint32_t)(arg >> 0), 32) << 32 | | |
| 1771 | (uint64_t)zig_byteSwap_u32((uint32_t)(arg >> 32), 32) >> 0; | |
| 1602 | 1772 | #endif |
| 1603 | return zig_wrap_u64(full_res >> (64 - bits), bits); | |
| 1773 | return zig_u64_truncate_u64(full_res >> (64 - bits), bits); | |
| 1604 | 1774 | } |
| 1605 | 1775 | |
| 1606 | static inline int64_t zig_byte_swap_i64(int64_t val, uint8_t bits) { | |
| 1607 | return zig_wrap_i64((int64_t)zig_byte_swap_u64((uint64_t)val, bits), bits); | |
| 1776 | static inline int64_t zig_byteSwap_i64(int64_t arg, uint8_t bits) { | |
| 1777 | return zig_i64_truncate_i64((int64_t)zig_byteSwap_u64((uint64_t)arg, bits), bits); | |
| 1608 | 1778 | } |
| 1609 | 1779 | |
| 1610 | static inline uint8_t zig_bit_reverse_u8(uint8_t val, uint8_t bits) { | |
| 1780 | static inline uint8_t zig_bitReverse_u8(uint8_t arg, uint8_t bits) { | |
| 1611 | 1781 | uint8_t full_res; |
| 1612 | 1782 | #if zig_has_builtin(bitreverse8) |
| 1613 | full_res = __builtin_bitreverse8(val); | |
| 1783 | full_res = __builtin_bitreverse8(arg); | |
| 1614 | 1784 | #else |
| 1615 | 1785 | static uint8_t const lut[0x10] = { |
| 1616 | 1786 | 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe, |
| 1617 | 1787 | 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 | 1790 | #endif |
| 1621 | return zig_wrap_u8(full_res >> (8 - bits), bits); | |
| 1791 | return zig_u8_truncate_u8(full_res >> (8 - bits), bits); | |
| 1622 | 1792 | } |
| 1623 | 1793 | |
| 1624 | static inline int8_t zig_bit_reverse_i8(int8_t val, uint8_t bits) { | |
| 1625 | return zig_wrap_i8((int8_t)zig_bit_reverse_u8((uint8_t)val, bits), bits); | |
| 1794 | static inline int8_t zig_bitReverse_i8(int8_t arg, uint8_t bits) { | |
| 1795 | return zig_i8_truncate_i8((int8_t)zig_bitReverse_u8((uint8_t)arg, bits), bits); | |
| 1626 | 1796 | } |
| 1627 | 1797 | |
| 1628 | static inline uint16_t zig_bit_reverse_u16(uint16_t val, uint8_t bits) { | |
| 1798 | static inline uint16_t zig_bitReverse_u16(uint16_t arg, uint8_t bits) { | |
| 1629 | 1799 | uint16_t full_res; |
| 1630 | 1800 | #if zig_has_builtin(bitreverse16) |
| 1631 | full_res = __builtin_bitreverse16(val); | |
| 1801 | full_res = __builtin_bitreverse16(arg); | |
| 1632 | 1802 | #else |
| 1633 | full_res = (uint16_t)zig_bit_reverse_u8((uint8_t)(val >> 0), 8) << 8 | | |
| 1634 | (uint16_t)zig_bit_reverse_u8((uint8_t)(val >> 8), 8) >> 0; | |
| 1803 | full_res = (uint16_t)zig_bitReverse_u8((uint8_t)(arg >> 0), 8) << 8 | | |
| 1804 | (uint16_t)zig_bitReverse_u8((uint8_t)(arg >> 8), 8) >> 0; | |
| 1635 | 1805 | #endif |
| 1636 | return zig_wrap_u16(full_res >> (16 - bits), bits); | |
| 1806 | return zig_u16_truncate_u16(full_res >> (16 - bits), bits); | |
| 1637 | 1807 | } |
| 1638 | 1808 | |
| 1639 | static inline int16_t zig_bit_reverse_i16(int16_t val, uint8_t bits) { | |
| 1640 | return zig_wrap_i16((int16_t)zig_bit_reverse_u16((uint16_t)val, bits), bits); | |
| 1809 | static inline int16_t zig_bitReverse_i16(int16_t arg, uint8_t bits) { | |
| 1810 | return zig_i16_truncate_i16((int16_t)zig_bitReverse_u16((uint16_t)arg, bits), bits); | |
| 1641 | 1811 | } |
| 1642 | 1812 | |
| 1643 | 1813 | #if defined(zig_ez80) |
| 1644 | static inline uint24_t zig_bit_reverse_u24(uint24_t val, uint8_t bits) { | |
| 1814 | static inline uint24_t zig_bitReverse_u24(uint24_t arg, uint8_t bits) { | |
| 1645 | 1815 | uint24_t full_res; |
| 1646 | 1816 | #if zig_has_builtin(bitreverse24) |
| 1647 | full_res = __builtin_bitreverse24(val); | |
| 1817 | full_res = __builtin_bitreverse24(arg); | |
| 1648 | 1818 | #else |
| 1649 | full_res = (uint24_t)zig_bit_reverse_u8((uint8_t)(val >> 0), 8) << 16 | | |
| 1650 | (uint24_t)zig_bit_reverse_u16((uint16_t)(val >> 8), 16) >> 0; | |
| 1819 | full_res = (uint24_t)zig_bitReverse_u8((uint8_t)(arg >> 0), 8) << 16 | | |
| 1820 | (uint24_t)zig_bitReverse_u16((uint16_t)(arg >> 8), 16) >> 0; | |
| 1651 | 1821 | #endif |
| 1652 | return zig_wrap_u24(full_res >> (24 - bits), bits); | |
| 1822 | return zig_u24_truncate_u24(full_res >> (24 - bits), bits); | |
| 1653 | 1823 | } |
| 1654 | 1824 | |
| 1655 | static inline int24_t zig_bit_reverse_i24(int24_t val, uint8_t bits) { | |
| 1656 | return zig_wrap_i24((int24_t)zig_bit_reverse_u24((uint24_t)val, bits), bits); | |
| 1825 | static inline int24_t zig_bitReverse_i24(int24_t arg, uint8_t bits) { | |
| 1826 | return zig_i24_truncate_i24((int24_t)zig_bitReverse_u24((uint24_t)arg, bits), bits); | |
| 1657 | 1827 | } |
| 1658 | 1828 | #endif |
| 1659 | 1829 | |
| 1660 | static inline uint32_t zig_bit_reverse_u32(uint32_t val, uint8_t bits) { | |
| 1830 | static inline uint32_t zig_bitReverse_u32(uint32_t arg, uint8_t bits) { | |
| 1661 | 1831 | uint32_t full_res; |
| 1662 | 1832 | #if zig_has_builtin(bitreverse32) |
| 1663 | full_res = __builtin_bitreverse32(val); | |
| 1833 | full_res = __builtin_bitreverse32(arg); | |
| 1664 | 1834 | #else |
| 1665 | full_res = (uint32_t)zig_bit_reverse_u16((uint16_t)(val >> 0), 16) << 16 | | |
| 1666 | (uint32_t)zig_bit_reverse_u16((uint16_t)(val >> 16), 16) >> 0; | |
| 1835 | full_res = (uint32_t)zig_bitReverse_u16((uint16_t)(arg >> 0), 16) << 16 | | |
| 1836 | (uint32_t)zig_bitReverse_u16((uint16_t)(arg >> 16), 16) >> 0; | |
| 1667 | 1837 | #endif |
| 1668 | return zig_wrap_u32(full_res >> (32 - bits), bits); | |
| 1838 | return zig_u32_truncate_u32(full_res >> (32 - bits), bits); | |
| 1669 | 1839 | } |
| 1670 | 1840 | |
| 1671 | static inline int32_t zig_bit_reverse_i32(int32_t val, uint8_t bits) { | |
| 1672 | return zig_wrap_i32((int32_t)zig_bit_reverse_u32((uint32_t)val, bits), bits); | |
| 1841 | static inline int32_t zig_bitReverse_i32(int32_t arg, uint8_t bits) { | |
| 1842 | return zig_i32_truncate_i32((int32_t)zig_bitReverse_u32((uint32_t)arg, bits), bits); | |
| 1673 | 1843 | } |
| 1674 | 1844 | |
| 1675 | 1845 | #if defined(zig_ez80) |
| 1676 | static inline uint32_t zig_bit_reverse_u48(uint48_t val, uint8_t bits) { | |
| 1846 | static inline uint32_t zig_bitReverse_u48(uint48_t arg, uint8_t bits) { | |
| 1677 | 1847 | uint48_t full_res; |
| 1678 | 1848 | #if zig_has_builtin(bitreverse48) |
| 1679 | full_res = __builtin_bitreverse48(val); | |
| 1849 | full_res = __builtin_bitreverse48(arg); | |
| 1680 | 1850 | #else |
| 1681 | full_res = (uint48_t)zig_bit_reverse_u24((uint24_t)(val >> 0), 24) << 24 | | |
| 1682 | (uint48_t)zig_bit_reverse_u24((uint24_t)(val >> 24), 24) >> 0; | |
| 1851 | full_res = (uint48_t)zig_bitReverse_u24((uint24_t)(arg >> 0), 24) << 24 | | |
| 1852 | (uint48_t)zig_bitReverse_u24((uint24_t)(arg >> 24), 24) >> 0; | |
| 1683 | 1853 | #endif |
| 1684 | return zig_wrap_u32(full_res >> (48 - bits), bits); | |
| 1854 | return zig_u48_truncate_u48(full_res >> (48 - bits), bits); | |
| 1685 | 1855 | } |
| 1686 | 1856 | |
| 1687 | static inline int32_t zig_bit_reverse_i48(int48_t val, uint8_t bits) { | |
| 1688 | return zig_wrap_i48((int48_t)zig_bit_reverse_u48((uint48_t)val, bits), bits); | |
| 1857 | static inline int32_t zig_bitReverse_i48(int48_t arg, uint8_t bits) { | |
| 1858 | return zig_i48_truncate_i48((int48_t)zig_bitReverse_u48((uint48_t)arg, bits), bits); | |
| 1689 | 1859 | } |
| 1690 | 1860 | #endif |
| 1691 | 1861 | |
| 1692 | static inline uint64_t zig_bit_reverse_u64(uint64_t val, uint8_t bits) { | |
| 1862 | static inline uint64_t zig_bitReverse_u64(uint64_t arg, uint8_t bits) { | |
| 1693 | 1863 | uint64_t full_res; |
| 1694 | 1864 | #if zig_has_builtin(bitreverse64) |
| 1695 | full_res = __builtin_bitreverse64(val); | |
| 1865 | full_res = __builtin_bitreverse64(arg); | |
| 1696 | 1866 | #else |
| 1697 | full_res = (uint64_t)zig_bit_reverse_u32((uint32_t)(val >> 0), 32) << 32 | | |
| 1698 | (uint64_t)zig_bit_reverse_u32((uint32_t)(val >> 32), 32) >> 0; | |
| 1867 | full_res = (uint64_t)zig_bitReverse_u32((uint32_t)(arg >> 0), 32) << 32 | | |
| 1868 | (uint64_t)zig_bitReverse_u32((uint32_t)(arg >> 32), 32) >> 0; | |
| 1699 | 1869 | #endif |
| 1700 | return zig_wrap_u64(full_res >> (64 - bits), bits); | |
| 1870 | return zig_u64_truncate_u64(full_res >> (64 - bits), bits); | |
| 1701 | 1871 | } |
| 1702 | 1872 | |
| 1703 | static inline int64_t zig_bit_reverse_i64(int64_t val, uint8_t bits) { | |
| 1704 | return zig_wrap_i64((int64_t)zig_bit_reverse_u64((uint64_t)val, bits), bits); | |
| 1873 | static inline int64_t zig_bitReverse_i64(int64_t arg, uint8_t bits) { | |
| 1874 | return zig_i64_truncate_i64((int64_t)zig_bitReverse_u64((uint64_t)arg, bits), bits); | |
| 1705 | 1875 | } |
| 1706 | 1876 | |
| 1707 | #define zig_builtin_popcount_common(w) \ | |
| 1708 | static inline uint8_t zig_popcount_i##w(int##w##_t val, uint8_t bits) { \ | |
| 1709 | return zig_popcount_u##w((uint##w##_t)val, bits); \ | |
| 1877 | #define zig_builtin_popCount_common(w) \ | |
| 1878 | static inline uint8_t zig_popCount_i##w(int##w##_t arg, uint8_t bits) { \ | |
| 1879 | return zig_popCount_u##w((uint##w##_t)arg, bits); \ | |
| 1710 | 1880 | } |
| 1711 | #if zig_has_builtin(popcount) || defined(zig_gcc) || defined(zig_tinyc) | |
| 1712 | #define zig_builtin_popcount(w) \ | |
| 1713 | static inline uint8_t zig_popcount_u##w(uint##w##_t val, uint8_t bits) { \ | |
| 1881 | #if zig_has_builtin(popCount) || defined(zig_gcc) || defined(zig_tinyc) | |
| 1882 | #define zig_builtin_popCount(w) \ | |
| 1883 | static inline uint8_t zig_popCount_u##w(uint##w##_t arg, uint8_t bits) { \ | |
| 1714 | 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 | 1889 | #else |
| 1720 | #define zig_builtin_popcount(w) \ | |
| 1721 | static inline uint8_t zig_popcount_u##w(uint##w##_t val, uint8_t bits) { \ | |
| 1890 | #define zig_builtin_popCount(w) \ | |
| 1891 | static inline uint8_t zig_popCount_u##w(uint##w##_t arg, uint8_t bits) { \ | |
| 1722 | 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 | 1894 | temp = (temp & (UINT##w##_MAX / 5)) + ((temp >> 2) & (UINT##w##_MAX / 5)); \ |
| 1725 | 1895 | temp = (temp + (temp >> 4)) & (UINT##w##_MAX / 17); \ |
| 1726 | 1896 | return temp * (UINT##w##_MAX / 255) >> (UINT8_C(w) - UINT8_C(8)); \ |
| 1727 | 1897 | } \ |
| 1728 | 1898 | \ |
| 1729 | zig_builtin_popcount_common(w) | |
| 1730 | #endif | |
| 1731 | zig_builtin_popcount(8) | |
| 1732 | zig_builtin_popcount(16) | |
| 1733 | #if defined(zig_ez80) | |
| 1734 | zig_builtin_popcount(24) | |
| 1899 | zig_builtin_popCount_common(w) | |
| 1735 | 1900 | #endif |
| 1736 | zig_builtin_popcount(32) | |
| 1901 | zig_builtin_popCount(8) | |
| 1902 | zig_builtin_popCount(16) | |
| 1903 | zig_builtin_popCount(32) | |
| 1904 | zig_builtin_popCount(64) | |
| 1737 | 1905 | #if defined(zig_ez80) |
| 1738 | zig_builtin_popcount(48) | |
| 1906 | zig_builtin_popCount(24) | |
| 1907 | zig_builtin_popCount(48) | |
| 1739 | 1908 | #endif |
| 1740 | zig_builtin_popcount(64) | |
| 1741 | 1909 | |
| 1742 | 1910 | #define zig_builtin_ctz_common(w) \ |
| 1743 | static inline uint8_t zig_ctz_i##w(int##w##_t val, uint8_t bits) { \ | |
| 1744 | return zig_ctz_u##w((uint##w##_t)val, bits); \ | |
| 1911 | static inline uint8_t zig_ctz_i##w(int##w##_t arg, uint8_t bits) { \ | |
| 1912 | return zig_ctz_u##w((uint##w##_t)arg, bits); \ | |
| 1745 | 1913 | } |
| 1746 | 1914 | #if zig_has_builtin(ctz) || defined(zig_gcc) || defined(zig_tinyc) |
| 1747 | 1915 | #define zig_builtin_ctz(w) \ |
| 1748 | static inline uint8_t zig_ctz_u##w(uint##w##_t val, uint8_t bits) { \ | |
| 1749 | if (val == 0) return bits; \ | |
| 1750 | return zig_builtin##w(ctz, val); \ | |
| 1916 | static inline uint8_t zig_ctz_u##w(uint##w##_t arg, uint8_t bits) { \ | |
| 1917 | if (arg == 0) return bits; \ | |
| 1918 | return zig_builtin##w(ctz, arg); \ | |
| 1751 | 1919 | } \ |
| 1752 | 1920 | \ |
| 1753 | 1921 | zig_builtin_ctz_common(w) |
| 1754 | 1922 | #else |
| 1755 | 1923 | #define zig_builtin_ctz(w) \ |
| 1756 | static inline uint8_t zig_ctz_u##w(uint##w##_t val, uint8_t bits) { \ | |
| 1757 | return zig_popcount_u##w(zig_not_u##w(val, bits) & zig_subw_u##w(val, 1, bits), bits); \ | |
| 1924 | static inline uint8_t zig_ctz_u##w(uint##w##_t arg, uint8_t bits) { \ | |
| 1925 | return zig_popCount_u##w(zig_not_u##w(arg, bits) & zig_subw_u##w(arg, 1, bits), bits); \ | |
| 1758 | 1926 | } \ |
| 1759 | 1927 | \ |
| 1760 | 1928 | zig_builtin_ctz_common(w) |
| 1761 | 1929 | #endif |
| 1762 | 1930 | zig_builtin_ctz(8) |
| 1763 | 1931 | zig_builtin_ctz(16) |
| 1764 | #if defined(zig_ez80) | |
| 1765 | zig_builtin_ctz(24) | |
| 1766 | #endif | |
| 1767 | 1932 | zig_builtin_ctz(32) |
| 1933 | zig_builtin_ctz(64) | |
| 1768 | 1934 | #if defined(zig_ez80) |
| 1935 | zig_builtin_ctz(24) | |
| 1769 | 1936 | zig_builtin_ctz(48) |
| 1770 | 1937 | #endif |
| 1771 | zig_builtin_ctz(64) | |
| 1772 | 1938 | |
| 1773 | 1939 | #define zig_builtin_clz_common(w) \ |
| 1774 | static inline uint8_t zig_clz_i##w(int##w##_t val, uint8_t bits) { \ | |
| 1775 | return zig_clz_u##w((uint##w##_t)val, bits); \ | |
| 1940 | static inline uint8_t zig_clz_i##w(int##w##_t arg, uint8_t bits) { \ | |
| 1941 | return zig_clz_u##w((uint##w##_t)arg, bits); \ | |
| 1776 | 1942 | } |
| 1777 | 1943 | #if zig_has_builtin(clz) || defined(zig_gcc) || defined(zig_tinyc) |
| 1778 | 1944 | #define zig_builtin_clz(w) \ |
| 1779 | static inline uint8_t zig_clz_u##w(uint##w##_t val, uint8_t bits) { \ | |
| 1780 | if (val == 0) return bits; \ | |
| 1781 | return zig_builtin##w(clz, val) - (zig_bitSizeOf(zig_Builtin##w) - bits); \ | |
| 1945 | static inline uint8_t zig_clz_u##w(uint##w##_t arg, uint8_t bits) { \ | |
| 1946 | if (arg == 0) return bits; \ | |
| 1947 | return zig_builtin##w(clz, arg) - (zig_bitSizeOf(zig_Builtin##w) - bits); \ | |
| 1782 | 1948 | } \ |
| 1783 | 1949 | \ |
| 1784 | 1950 | zig_builtin_clz_common(w) |
| 1785 | 1951 | #else |
| 1786 | 1952 | #define zig_builtin_clz(w) \ |
| 1787 | static inline uint8_t zig_clz_u##w(uint##w##_t val, uint8_t bits) { \ | |
| 1788 | return zig_ctz_u##w(zig_bit_reverse_u##w(val, bits), bits); \ | |
| 1953 | static inline uint8_t zig_clz_u##w(uint##w##_t arg, uint8_t bits) { \ | |
| 1954 | return zig_ctz_u##w(zig_bitReverse_u##w(arg, bits), bits); \ | |
| 1789 | 1955 | } \ |
| 1790 | 1956 | \ |
| 1791 | 1957 | zig_builtin_clz_common(w) |
| 1792 | 1958 | #endif |
| 1793 | 1959 | zig_builtin_clz(8) |
| 1794 | 1960 | zig_builtin_clz(16) |
| 1795 | #if defined(zig_ez80) | |
| 1796 | zig_builtin_clz(24) | |
| 1797 | #endif | |
| 1798 | 1961 | zig_builtin_clz(32) |
| 1962 | zig_builtin_clz(64) | |
| 1799 | 1963 | #if defined(zig_ez80) |
| 1964 | zig_builtin_clz(24) | |
| 1800 | 1965 | zig_builtin_clz(48) |
| 1801 | 1966 | #endif |
| 1802 | zig_builtin_clz(64) | |
| 1803 | 1967 | |
| 1804 | 1968 | /* ======================== 128-bit Integer Support ========================= */ |
| 1805 | 1969 | |
| ... | ... | @@ -1816,16 +1980,14 @@ zig_builtin_clz(64) |
| 1816 | 1980 | typedef unsigned __int128 zig_u128; |
| 1817 | 1981 | typedef signed __int128 zig_i128; |
| 1818 | 1982 | |
| 1819 | #define zig_make_u128(hi, lo) ((zig_u128)(hi)<<64|(lo)) | |
| 1820 | #define zig_make_i128(hi, lo) ((zig_i128)zig_make_u128(hi, lo)) | |
| 1821 | #define zig_init_u128(hi, lo) zig_make_u128(hi, lo) | |
| 1822 | #define zig_init_i128(hi, lo) zig_make_i128(hi, lo) | |
| 1823 | #define zig_hi_u128(val) ((uint64_t)((val) >> 64)) | |
| 1824 | #define zig_lo_u128(val) ((uint64_t)((val) >> 0)) | |
| 1825 | #define zig_hi_i128(val) (( int64_t)((val) >> 64)) | |
| 1826 | #define zig_lo_i128(val) ((uint64_t)((val) >> 0)) | |
| 1827 | #define zig_bitCast_u128(val) ((zig_u128)(val)) | |
| 1828 | #define zig_bitCast_i128(val) ((zig_i128)(val)) | |
| 1983 | #define zig_init_u128(hi, lo) ((zig_u128)(hi)<<64|(lo)) | |
| 1984 | #define zig_init_i128(hi, lo) ((zig_i128)zig_make_u128(hi, lo)) | |
| 1985 | #define zig_make_u128(hi, lo) zig_init_u128(hi, lo) | |
| 1986 | #define zig_make_i128(hi, lo) zig_init_i128(hi, lo) | |
| 1987 | #define zig_hi_u128(arg) ((uint64_t)((arg) >> 64)) | |
| 1988 | #define zig_lo_u128(arg) ((uint64_t)((arg) >> 0)) | |
| 1989 | #define zig_hi_i128(arg) (( int64_t)((arg) >> 64)) | |
| 1990 | #define zig_lo_i128(arg) ((uint64_t)((arg) >> 0)) | |
| 1829 | 1991 | #define zig_cmp_int128(Type) \ |
| 1830 | 1992 | static inline int32_t zig_cmp_##Type(zig_##Type lhs, zig_##Type rhs) { \ |
| 1831 | 1993 | return (lhs > rhs) - (lhs < rhs); \ |
| ... | ... | @@ -1835,32 +1997,49 @@ typedef signed __int128 zig_i128; |
| 1835 | 1997 | return lhs operator rhs; \ |
| 1836 | 1998 | } |
| 1837 | 1999 | |
| 1838 | #else /* zig_has_int128 */ | |
| 2000 | static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) { | |
| 2001 | return lhs << rhs; | |
| 2002 | } | |
| 1839 | 2003 | |
| 1840 | #if zig_little_endian | |
| 1841 | typedef struct { zig_align(16) uint64_t lo; uint64_t hi; } zig_u128; | |
| 1842 | typedef struct { zig_align(16) uint64_t lo; int64_t hi; } zig_i128; | |
| 2004 | static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs) { | |
| 2005 | return lhs >> rhs; | |
| 2006 | } | |
| 2007 | ||
| 2008 | static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) { | |
| 2009 | return lhs << rhs; | |
| 2010 | } | |
| 2011 | ||
| 2012 | static 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 | 2019 | #else |
| 1844 | typedef struct { zig_align(16) uint64_t hi; uint64_t lo; } zig_u128; | |
| 1845 | typedef struct { zig_align(16) int64_t hi; uint64_t lo; } zig_i128; | |
| 2020 | zig_i128 sign_mask = lhs < zig_make_i128(0, 0) ? -zig_make_i128(0, 1) : zig_make_i128(0, 0); | |
| 2021 | return ((lhs ^ sign_mask) >> rhs) ^ sign_mask; | |
| 1846 | 2022 | #endif |
| 2023 | } | |
| 1847 | 2024 | |
| 1848 | #define zig_make_u128(hi, lo) ((zig_u128){ .h##i = (hi), .l##o = (lo) }) | |
| 1849 | #define zig_make_i128(hi, lo) ((zig_i128){ .h##i = (hi), .l##o = (lo) }) | |
| 2025 | #else /* zig_has_int128 */ | |
| 1850 | 2026 | |
| 1851 | #if defined(zig_msvc) /* MSVC doesn't allow struct literals in constant expressions */ | |
| 1852 | #define zig_init_u128(hi, lo) { .h##i = (hi), .l##o = (lo) } | |
| 1853 | #define zig_init_i128(hi, lo) { .h##i = (hi), .l##o = (lo) } | |
| 1854 | #else /* But non-MSVC doesn't like the unprotected commas */ | |
| 1855 | #define zig_init_u128(hi, lo) zig_make_u128(hi, lo) | |
| 1856 | #define zig_init_i128(hi, lo) zig_make_i128(hi, lo) | |
| 1857 | #endif | |
| 1858 | #define zig_hi_u128(val) ((val).hi) | |
| 1859 | #define zig_lo_u128(val) ((val).lo) | |
| 1860 | #define zig_hi_i128(val) ((val).hi) | |
| 1861 | #define zig_lo_i128(val) ((val).lo) | |
| 1862 | #define zig_bitCast_u128(val) zig_make_u128((uint64_t)(val).hi, (val).lo) | |
| 1863 | #define zig_bitCast_i128(val) zig_make_i128(( int64_t)(val).hi, (val).lo) | |
| 2027 | #if zig_little_endian | |
| 2028 | typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) uint64_t lo; uint64_t hi; } zig_u128; | |
| 2029 | typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) uint64_t lo; int64_t hi; } zig_i128; | |
| 2030 | #else | |
| 2031 | typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) uint64_t hi; uint64_t lo; } zig_u128; | |
| 2032 | typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) int64_t hi; uint64_t lo; } zig_i128; | |
| 2033 | #endif | |
| 2034 | ||
| 2035 | #define zig_init_u128(hi, lo) { .h##i = hi, .l##o = lo } | |
| 2036 | #define zig_init_i128(hi, lo) { .h##i = hi, .l##o = lo } | |
| 2037 | #define zig_make_u128(hi, lo) (zig_u128)zig_init_u128(hi, lo) | |
| 2038 | #define zig_make_i128(hi, lo) (zig_i128)zig_init_i128(hi, lo) | |
| 2039 | #define zig_hi_u128(arg) (arg).hi | |
| 2040 | #define zig_lo_u128(arg) (arg).lo | |
| 2041 | #define zig_hi_i128(arg) (arg).hi | |
| 2042 | #define zig_lo_i128(arg) (arg).lo | |
| 1864 | 2043 | #define zig_cmp_int128(Type) \ |
| 1865 | 2044 | static inline int32_t zig_cmp_##Type(zig_##Type lhs, zig_##Type rhs) { \ |
| 1866 | 2045 | return (lhs.hi == rhs.hi) \ |
| ... | ... | @@ -1872,6 +2051,30 @@ typedef struct { zig_align(16) int64_t hi; uint64_t lo; } zig_i128; |
| 1872 | 2051 | return (zig_##Type){ .hi = lhs.hi operator rhs.hi, .lo = lhs.lo operator rhs.lo }; \ |
| 1873 | 2052 | } |
| 1874 | 2053 | |
| 2054 | static 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 | ||
| 2060 | static 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 | ||
| 2066 | static 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 | ||
| 2072 | static 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 | 2078 | #endif /* zig_has_int128 */ |
| 1876 | 2079 | |
| 1877 | 2080 | #define zig_minInt_u128 zig_make_u128(zig_minInt_u64, zig_minInt_u64) |
| ... | ... | @@ -1891,42 +2094,177 @@ zig_bit_int128(i128, or, |) |
| 1891 | 2094 | zig_bit_int128(u128, xor, ^) |
| 1892 | 2095 | zig_bit_int128(i128, xor, ^) |
| 1893 | 2096 | |
| 1894 | static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs); | |
| 2097 | static inline uint8_t zig_u8_intCast_u128(zig_u128 arg) { | |
| 2098 | return (uint8_t)zig_lo_u128(arg); | |
| 2099 | } | |
| 2100 | static inline uint8_t zig_u8_intCast_i128(zig_i128 arg) { | |
| 2101 | return (uint8_t)zig_lo_i128(arg); | |
| 2102 | } | |
| 2103 | static inline int8_t zig_i8_intCast_i128(zig_i128 arg) { | |
| 2104 | return (int8_t)zig_lo_i128(arg); | |
| 2105 | } | |
| 2106 | static inline int8_t zig_i8_intCast_u128(zig_u128 arg) { | |
| 2107 | return (int8_t)zig_lo_u128(arg); | |
| 2108 | } | |
| 1895 | 2109 | |
| 1896 | #if zig_has_int128 | |
| 2110 | static inline uint16_t zig_u16_intCast_u128(zig_u128 arg) { | |
| 2111 | return (uint16_t)zig_lo_u128(arg); | |
| 2112 | } | |
| 2113 | static inline uint16_t zig_u16_intCast_i128(zig_i128 arg) { | |
| 2114 | return (uint16_t)zig_lo_i128(arg); | |
| 2115 | } | |
| 2116 | static inline int16_t zig_i16_intCast_i128(zig_i128 arg) { | |
| 2117 | return (int16_t)zig_lo_i128(arg); | |
| 2118 | } | |
| 2119 | static inline int16_t zig_i16_intCast_u128(zig_u128 arg) { | |
| 2120 | return (int16_t)zig_lo_u128(arg); | |
| 2121 | } | |
| 1897 | 2122 | |
| 1898 | static inline zig_u128 zig_not_u128(zig_u128 val, uint8_t bits) { | |
| 1899 | return val ^ zig_maxInt_u(128, bits); | |
| 2123 | static inline uint32_t zig_u32_intCast_u128(zig_u128 arg) { | |
| 2124 | return (uint32_t)zig_lo_u128(arg); | |
| 2125 | } | |
| 2126 | static inline uint32_t zig_u32_intCast_i128(zig_i128 arg) { | |
| 2127 | return (uint32_t)zig_lo_i128(arg); | |
| 2128 | } | |
| 2129 | static inline int32_t zig_i32_intCast_i128(zig_i128 arg) { | |
| 2130 | return (int32_t)zig_lo_i128(arg); | |
| 2131 | } | |
| 2132 | static inline int32_t zig_i32_intCast_u128(zig_u128 arg) { | |
| 2133 | return (int32_t)zig_lo_u128(arg); | |
| 1900 | 2134 | } |
| 1901 | 2135 | |
| 1902 | static inline zig_i128 zig_not_i128(zig_i128 val, uint8_t bits) { | |
| 1903 | (void)bits; | |
| 1904 | return ~val; | |
| 2136 | static inline uint64_t zig_u64_intCast_u128(zig_u128 arg) { | |
| 2137 | return zig_lo_u128(arg); | |
| 2138 | } | |
| 2139 | static inline uint64_t zig_u64_intCast_i128(zig_i128 arg) { | |
| 2140 | return zig_lo_i128(arg); | |
| 2141 | } | |
| 2142 | static inline int64_t zig_i64_intCast_i128(zig_i128 arg) { | |
| 2143 | return (int64_t)zig_lo_i128(arg); | |
| 2144 | } | |
| 2145 | static inline int64_t zig_i64_intCast_u128(zig_u128 arg) { | |
| 2146 | return (int64_t)zig_lo_u128(arg); | |
| 1905 | 2147 | } |
| 1906 | 2148 | |
| 1907 | static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs) { | |
| 1908 | return lhs >> rhs; | |
| 2149 | static inline zig_u128 zig_u128_intCast_u8(uint8_t arg) { | |
| 2150 | return zig_make_u128(UINT8_C(0), arg); | |
| 2151 | } | |
| 2152 | static inline zig_u128 zig_u128_intCast_i8(int8_t arg) { | |
| 2153 | return zig_make_u128(UINT8_C(0), (uint8_t)arg); | |
| 2154 | } | |
| 2155 | static inline zig_i128 zig_i128_intCast_i8(int8_t arg) { | |
| 2156 | return zig_make_i128(zig_shr_i64(arg, 63), (uint8_t)arg); | |
| 2157 | } | |
| 2158 | static inline zig_i128 zig_i128_intCast_u8(uint8_t arg) { | |
| 2159 | return zig_make_i128(INT8_C(0), arg); | |
| 1909 | 2160 | } |
| 1910 | 2161 | |
| 1911 | static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) { | |
| 1912 | return lhs << rhs; | |
| 2162 | static inline zig_u128 zig_u128_intCast_u16(uint16_t arg) { | |
| 2163 | return zig_make_u128(UINT16_C(0), arg); | |
| 2164 | } | |
| 2165 | static inline zig_u128 zig_u128_intCast_i16(int16_t arg) { | |
| 2166 | return zig_make_u128(UINT16_C(0), (uint16_t)arg); | |
| 2167 | } | |
| 2168 | static inline zig_i128 zig_i128_intCast_i16(int16_t arg) { | |
| 2169 | return zig_make_i128(zig_shr_i64(arg, 63), (uint16_t)arg); | |
| 2170 | } | |
| 2171 | static inline zig_i128 zig_i128_intCast_u16(uint16_t arg) { | |
| 2172 | return zig_make_i128(INT16_C(0), arg); | |
| 1913 | 2173 | } |
| 1914 | 2174 | |
| 1915 | static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) { | |
| 1916 | // This works around a GCC miscompilation, but it has the side benefit of | |
| 1917 | // emitting better code. It is behind the `#if` because it depends on | |
| 1918 | // arithmetic right shift, which is implementation-defined in C, but should | |
| 1919 | // be guaranteed on any GCC-compatible compiler. | |
| 1920 | #if defined(zig_gnuc) | |
| 1921 | return lhs >> rhs; | |
| 2175 | static inline zig_u128 zig_u128_intCast_u32(uint32_t arg) { | |
| 2176 | return zig_make_u128(UINT32_C(0), arg); | |
| 2177 | } | |
| 2178 | static inline zig_u128 zig_u128_intCast_i32(int32_t arg) { | |
| 2179 | return zig_make_u128(UINT32_C(0), (uint32_t)arg); | |
| 2180 | } | |
| 2181 | static inline zig_i128 zig_i128_intCast_i32(int32_t arg) { | |
| 2182 | return zig_make_i128(zig_shr_i64(arg, 63), (uint32_t)arg); | |
| 2183 | } | |
| 2184 | static inline zig_i128 zig_i128_intCast_u32(uint32_t arg) { | |
| 2185 | return zig_make_i128(INT32_C(0), arg); | |
| 2186 | } | |
| 2187 | ||
| 2188 | static inline zig_u128 zig_u128_intCast_u64(uint64_t arg) { | |
| 2189 | return zig_make_u128(UINT64_C(0), arg); | |
| 2190 | } | |
| 2191 | static inline zig_u128 zig_u128_intCast_i64(int64_t arg) { | |
| 2192 | return zig_make_u128(UINT64_C(0), (uint64_t)arg); | |
| 2193 | } | |
| 2194 | static inline zig_i128 zig_i128_intCast_i64(int64_t arg) { | |
| 2195 | return zig_make_i128(zig_shr_i64(arg, 63), (uint64_t)arg); | |
| 2196 | } | |
| 2197 | static inline zig_i128 zig_i128_intCast_u64(uint64_t arg) { | |
| 2198 | return zig_make_i128(INT64_C(0), arg); | |
| 2199 | } | |
| 2200 | ||
| 2201 | static inline zig_u128 zig_u128_intCast_u128(zig_u128 arg) { | |
| 2202 | return arg; | |
| 2203 | } | |
| 2204 | static inline zig_u128 zig_u128_intCast_i128(zig_i128 arg) { | |
| 2205 | #if zig_has_int128 | |
| 2206 | return (zig_u128)arg; | |
| 1922 | 2207 | #else |
| 1923 | zig_i128 sign_mask = lhs < zig_make_i128(0, 0) ? -zig_make_i128(0, 1) : zig_make_i128(0, 0); | |
| 1924 | return ((lhs ^ sign_mask) >> rhs) ^ sign_mask; | |
| 2208 | return zig_make_u128(zig_u64_bitCast_i64(zig_hi_i128(arg), UINT8_C(64)), zig_lo_u128(arg)); | |
| 2209 | #endif | |
| 2210 | } | |
| 2211 | static inline zig_i128 zig_i128_intCast_i128(zig_i128 arg) { | |
| 2212 | return arg; | |
| 2213 | } | |
| 2214 | static 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 | 2219 | #endif |
| 1926 | 2220 | } |
| 1927 | 2221 | |
| 1928 | static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) { | |
| 1929 | return lhs << rhs; | |
| 2222 | #define zig_int128_cast_builtins(w) \ | |
| 2223 | static inline uint##w##_t zig_u##w##_truncate_u128(zig_u128 arg, uint8_t bits) { \ | |
| 2224 | return zig_u##w##_truncate_u##w((uint##w##_t)zig_lo_u128(arg), bits); \ | |
| 2225 | } \ | |
| 2226 | \ | |
| 2227 | static inline int##w##_t zig_i##w##_truncate_i128(zig_i128 arg, uint8_t bits) { \ | |
| 2228 | return zig_i##w##_truncate_i##w((int##w##_t)zig_lo_i128(arg), bits); \ | |
| 2229 | } | |
| 2230 | zig_int128_cast_builtins(8) | |
| 2231 | zig_int128_cast_builtins(16) | |
| 2232 | zig_int128_cast_builtins(32) | |
| 2233 | zig_int128_cast_builtins(64) | |
| 2234 | ||
| 2235 | static 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 | } | |
| 2238 | static 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 | ||
| 2244 | static inline zig_u128 zig_u128_bitCast_u128(zig_u128 arg, uint8_t bits) { | |
| 2245 | (void)bits; | |
| 2246 | return arg; | |
| 2247 | } | |
| 2248 | static 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 | } | |
| 2251 | static inline zig_i128 zig_i128_bitCast_i128(zig_i128 arg, uint8_t bits) { | |
| 2252 | (void)bits; | |
| 2253 | return arg; | |
| 2254 | } | |
| 2255 | static 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 | ||
| 2261 | static inline zig_u128 zig_not_u128(zig_u128 arg, uint8_t bits) { | |
| 2262 | return arg ^ zig_maxInt_u(128, bits); | |
| 2263 | } | |
| 2264 | ||
| 2265 | static inline zig_i128 zig_not_i128(zig_i128 arg, uint8_t bits) { | |
| 2266 | (void)bits; | |
| 2267 | return ~arg; | |
| 1930 | 2268 | } |
| 1931 | 2269 | |
| 1932 | 2270 | static inline zig_u128 zig_add_u128(zig_u128 lhs, zig_u128 rhs) { |
| ... | ... | @@ -1953,11 +2291,11 @@ static inline zig_i128 zig_mul_i128(zig_i128 lhs, zig_i128 rhs) { |
| 1953 | 2291 | return lhs * rhs; |
| 1954 | 2292 | } |
| 1955 | 2293 | |
| 1956 | static inline zig_u128 zig_div_trunc_u128(zig_u128 lhs, zig_u128 rhs) { | |
| 2294 | static inline zig_u128 zig_divTrunc_u128(zig_u128 lhs, zig_u128 rhs) { | |
| 1957 | 2295 | return lhs / rhs; |
| 1958 | 2296 | } |
| 1959 | 2297 | |
| 1960 | static inline zig_i128 zig_div_trunc_i128(zig_i128 lhs, zig_i128 rhs) { | |
| 2298 | static inline zig_i128 zig_divTrunc_i128(zig_i128 lhs, zig_i128 rhs) { | |
| 1961 | 2299 | return lhs / rhs; |
| 1962 | 2300 | } |
| 1963 | 2301 | |
| ... | ... | @@ -1971,36 +2309,14 @@ static inline zig_i128 zig_rem_i128(zig_i128 lhs, zig_i128 rhs) { |
| 1971 | 2309 | |
| 1972 | 2310 | #else /* zig_has_int128 */ |
| 1973 | 2311 | |
| 1974 | static inline zig_u128 zig_not_u128(zig_u128 val, uint8_t bits) { | |
| 1975 | return (zig_u128){ .hi = zig_not_u64(val.hi, bits - UINT8_C(64)), .lo = zig_not_u64(val.lo, UINT8_C(64)) }; | |
| 1976 | } | |
| 1977 | ||
| 1978 | static 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 | ||
| 1982 | static 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 | ||
| 1988 | static 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 | ||
| 1994 | static 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) }; | |
| 2312 | static inline zig_u128 zig_not_u128(zig_u128 arg, uint8_t bits) { | |
| 2313 | if (bits <= UINT8_C(64)) return (zig_u128){ .hi = UINT64_C(0), .lo = zig_not_u64(arg.lo, bits) }; | |
| 2314 | return (zig_u128){ .hi = zig_not_u64(arg.hi, bits - UINT8_C(64)), .lo = zig_not_u64(arg.lo, UINT8_C(64)) }; | |
| 1998 | 2315 | } |
| 1999 | 2316 | |
| 2000 | static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) { | |
| 2001 | if (rhs == UINT8_C(0)) return lhs; | |
| 2002 | if (rhs >= UINT8_C(64)) return (zig_i128){ .hi = lhs.lo << (rhs - UINT8_C(64)), .lo = zig_minInt_u64 }; | |
| 2003 | return (zig_i128){ .hi = lhs.hi << rhs | lhs.lo >> (UINT8_C(64) - rhs), .lo = lhs.lo << rhs }; | |
| 2317 | static inline zig_i128 zig_not_i128(zig_i128 arg, uint8_t bits) { | |
| 2318 | (void)bits; | |
| 2319 | return (zig_i128){ .hi = ~arg.hi, .lo = ~arg.lo }; | |
| 2004 | 2320 | } |
| 2005 | 2321 | |
| 2006 | 2322 | static inline zig_u128 zig_add_u128(zig_u128 lhs, zig_u128 rhs) { |
| ... | ... | @@ -2027,59 +2343,59 @@ static inline zig_i128 zig_sub_i128(zig_i128 lhs, zig_i128 rhs) { |
| 2027 | 2343 | return res; |
| 2028 | 2344 | } |
| 2029 | 2345 | |
| 2030 | zig_extern zig_i128 __multi3(zig_i128 lhs, zig_i128 rhs); | |
| 2031 | 2346 | static zig_i128 zig_mul_i128(zig_i128 lhs, zig_i128 rhs) { |
| 2347 | zig_extern zig_i128 __multi3(zig_i128 lhs, zig_i128 rhs); | |
| 2032 | 2348 | return __multi3(lhs, rhs); |
| 2033 | 2349 | } |
| 2034 | 2350 | |
| 2035 | 2351 | static 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 | } |
| 2038 | 2354 | |
| 2039 | zig_extern zig_u128 __udivti3(zig_u128 lhs, zig_u128 rhs); | |
| 2040 | static zig_u128 zig_div_trunc_u128(zig_u128 lhs, zig_u128 rhs) { | |
| 2355 | static zig_u128 zig_divTrunc_u128(zig_u128 lhs, zig_u128 rhs) { | |
| 2356 | zig_extern zig_u128 __udivti3(zig_u128 lhs, zig_u128 rhs); | |
| 2041 | 2357 | return __udivti3(lhs, rhs); |
| 2042 | 2358 | } |
| 2043 | 2359 | |
| 2044 | zig_extern zig_i128 __divti3(zig_i128 lhs, zig_i128 rhs); | |
| 2045 | static zig_i128 zig_div_trunc_i128(zig_i128 lhs, zig_i128 rhs) { | |
| 2360 | static zig_i128 zig_divTrunc_i128(zig_i128 lhs, zig_i128 rhs) { | |
| 2361 | zig_extern zig_i128 __divti3(zig_i128 lhs, zig_i128 rhs); | |
| 2046 | 2362 | return __divti3(lhs, rhs); |
| 2047 | 2363 | } |
| 2048 | 2364 | |
| 2049 | zig_extern zig_u128 __umodti3(zig_u128 lhs, zig_u128 rhs); | |
| 2050 | 2365 | static zig_u128 zig_rem_u128(zig_u128 lhs, zig_u128 rhs) { |
| 2366 | zig_extern zig_u128 __umodti3(zig_u128 lhs, zig_u128 rhs); | |
| 2051 | 2367 | return __umodti3(lhs, rhs); |
| 2052 | 2368 | } |
| 2053 | 2369 | |
| 2054 | zig_extern zig_i128 __modti3(zig_i128 lhs, zig_i128 rhs); | |
| 2055 | 2370 | static zig_i128 zig_rem_i128(zig_i128 lhs, zig_i128 rhs) { |
| 2371 | zig_extern zig_i128 __modti3(zig_i128 lhs, zig_i128 rhs); | |
| 2056 | 2372 | return __modti3(lhs, rhs); |
| 2057 | 2373 | } |
| 2058 | 2374 | |
| 2059 | 2375 | #endif /* zig_has_int128 */ |
| 2060 | 2376 | |
| 2061 | #define zig_div_floor_u128 zig_div_trunc_u128 | |
| 2377 | #define zig_divFloor_u128 zig_divTrunc_u128 | |
| 2062 | 2378 | |
| 2063 | static inline zig_i128 zig_div_floor_i128(zig_i128 lhs, zig_i128 rhs) { | |
| 2379 | static inline zig_i128 zig_divFloor_i128(zig_i128 lhs, zig_i128 rhs) { | |
| 2064 | 2380 | zig_i128 rem = zig_rem_i128(lhs, rhs); |
| 2065 | 2381 | int64_t mask = zig_or_u64((uint64_t)zig_hi_i128(rem), zig_lo_i128(rem)) != UINT64_C(0) |
| 2066 | 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 | } |
| 2069 | 2385 | |
| 2070 | static inline zig_u128 zig_div_ceil_u128(zig_u128 lhs, zig_u128 rhs) { | |
| 2386 | static inline zig_u128 zig_divCeil_u128(zig_u128 lhs, zig_u128 rhs) { | |
| 2071 | 2387 | zig_u128 rem = zig_rem_u128(lhs, rhs); |
| 2072 | 2388 | uint64_t mask = zig_or_u64(zig_hi_u128(rem), zig_lo_u128(rem)) != UINT64_C(0) |
| 2073 | 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 | } |
| 2076 | 2392 | |
| 2077 | static inline zig_i128 zig_div_ceil_i128(zig_i128 lhs, zig_i128 rhs) { | |
| 2393 | static inline zig_i128 zig_divCeil_i128(zig_i128 lhs, zig_i128 rhs) { | |
| 2078 | 2394 | zig_i128 rem = zig_rem_i128(lhs, rhs); |
| 2079 | 2395 | int64_t mask = zig_or_u64((uint64_t)zig_hi_i128(rem), zig_lo_i128(rem)) != UINT64_C(0) |
| 2080 | 2396 | ? zig_shr_i64(zig_xor_i64(zig_hi_i128(lhs), zig_hi_i128(rhs)), UINT8_C(63)) + INT64_C(1) |
| 2081 | 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 | } |
| 2084 | 2400 | |
| 2085 | 2401 | #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 | 2423 | return zig_cmp_i128(lhs, rhs) > INT32_C(0) ? lhs : rhs; |
| 2108 | 2424 | } |
| 2109 | 2425 | |
| 2110 | static 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 | ||
| 2114 | static 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 | ||
| 2120 | 2426 | static 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 | } |
| 2123 | 2429 | |
| 2124 | 2430 | static 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 | } |
| 2127 | 2433 | |
| 2128 | 2434 | static 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 | } |
| 2131 | 2437 | |
| 2132 | 2438 | static 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 | } |
| 2135 | 2441 | |
| 2136 | 2442 | static 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 | } |
| 2139 | 2445 | |
| 2140 | 2446 | static 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 | } |
| 2143 | 2449 | |
| 2144 | 2450 | static 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 | } |
| 2147 | 2453 | |
| 2148 | 2454 | static 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 | } |
| 2151 | 2457 | |
| 2152 | static inline zig_u128 zig_abs_i128(zig_i128 val) { | |
| 2153 | zig_i128 tmp = zig_shr_i128(val, 127); | |
| 2154 | return zig_bitCast_u128(zig_sub_i128(zig_xor_i128(val, tmp), tmp)); | |
| 2458 | static inline zig_u128 zig_abs_i128(zig_i128 arg) { | |
| 2459 | zig_u128 tmp = zig_u128_bitCast_i128(zig_shr_i128(arg, 127), UINT8_C(128)); | |
| 2460 | return zig_sub_u128(zig_xor_u128(zig_u128_bitCast_i128(arg, UINT8_C(128)), tmp), tmp); | |
| 2155 | 2461 | } |
| 2156 | 2462 | |
| 2157 | 2463 | #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 | 2466 | #if zig_has_builtin(add_overflow) |
| 2161 | 2467 | zig_u128 full_res; |
| 2162 | 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 | 2470 | return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits); |
| 2165 | 2471 | #else |
| 2166 | 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 | 2482 | zig_i128 full_res = (zig_i128)((zig_u128)lhs + (zig_u128)rhs); |
| 2177 | 2483 | bool overflow = ((full_res ^ lhs) & (full_res ^ rhs)) < 0; |
| 2178 | 2484 | #endif |
| 2179 | *res = zig_wrap_i128(full_res, bits); | |
| 2485 | *res = zig_i128_truncate_i128(full_res, bits); | |
| 2180 | 2486 | return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits); |
| 2181 | 2487 | } |
| 2182 | 2488 | |
| ... | ... | @@ -2184,7 +2490,7 @@ static inline bool zig_subo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint |
| 2184 | 2490 | #if zig_has_builtin(sub_overflow) |
| 2185 | 2491 | zig_u128 full_res; |
| 2186 | 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 | 2494 | return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits); |
| 2189 | 2495 | #else |
| 2190 | 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 | 2506 | zig_i128 full_res = (zig_i128)((zig_u128)lhs - (zig_u128)rhs); |
| 2201 | 2507 | bool overflow = ((lhs ^ rhs) & (full_res ^ lhs)) < 0; |
| 2202 | 2508 | #endif |
| 2203 | *res = zig_wrap_i128(full_res, bits); | |
| 2509 | *res = zig_i128_truncate_i128(full_res, bits); | |
| 2204 | 2510 | return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits); |
| 2205 | 2511 | } |
| 2206 | 2512 | |
| ... | ... | @@ -2208,7 +2514,7 @@ static inline bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint |
| 2208 | 2514 | #if zig_has_builtin(mul_overflow) |
| 2209 | 2515 | zig_u128 full_res; |
| 2210 | 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 | 2518 | return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits); |
| 2213 | 2519 | #else |
| 2214 | 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 | 2522 | #endif |
| 2217 | 2523 | } |
| 2218 | 2524 | |
| 2219 | zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow); | |
| 2220 | 2525 | static 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 | 2527 | #if zig_has_builtin(mul_overflow) |
| 2222 | 2528 | zig_i128 full_res; |
| 2223 | 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 | 2532 | zig_i128 full_res = __muloti4(lhs, rhs, &overflow_int); |
| 2227 | 2533 | bool overflow = overflow_int != 0; |
| 2228 | 2534 | #endif |
| 2229 | *res = zig_wrap_i128(full_res, bits); | |
| 2535 | *res = zig_i128_truncate_i128(full_res, bits); | |
| 2230 | 2536 | return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits); |
| 2231 | 2537 | } |
| 2232 | 2538 | |
| 2233 | 2539 | #else /* zig_has_int128 */ |
| 2234 | 2540 | |
| 2235 | 2541 | static inline bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) { |
| 2236 | uint64_t hi; | |
| 2237 | bool overflow = zig_addo_u64(&hi, lhs.hi, rhs.hi, bits - 64); | |
| 2238 | return overflow ^ zig_addo_u64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64); | |
| 2542 | if (bits <= UINT8_C(64)) { | |
| 2543 | uint64_t lo; | |
| 2544 | bool overflow = zig_addo_u64(&lo, zig_u64_intCast_u128(lhs), zig_u64_intCast_u128(rhs), bits); | |
| 2545 | *res = zig_u128_intCast_u64(lo); | |
| 2546 | return overflow; | |
| 2547 | } else { | |
| 2548 | uint64_t hi; | |
| 2549 | bool overflow = zig_addo_u64(&hi, lhs.hi, rhs.hi, bits - UINT8_C(64)); | |
| 2550 | return overflow ^ zig_addo_u64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, UINT8_C(64)), bits - UINT8_C(64)); | |
| 2551 | } | |
| 2239 | 2552 | } |
| 2240 | 2553 | |
| 2241 | 2554 | static inline bool zig_addo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) { |
| 2242 | int64_t hi; | |
| 2243 | bool overflow = zig_addo_i64(&hi, lhs.hi, rhs.hi, bits - 64); | |
| 2244 | return overflow ^ zig_addo_i64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64); | |
| 2555 | if (bits <= UINT8_C(64)) { | |
| 2556 | int64_t lo; | |
| 2557 | bool overflow = zig_addo_i64(&lo, zig_i64_intCast_i128(lhs), zig_i64_intCast_i128(rhs), bits); | |
| 2558 | *res = zig_i128_intCast_i64(lo); | |
| 2559 | return overflow; | |
| 2560 | } else { | |
| 2561 | int64_t hi; | |
| 2562 | bool overflow = zig_addo_i64(&hi, lhs.hi, rhs.hi, bits - UINT8_C(64)); | |
| 2563 | return overflow ^ zig_addo_i64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, UINT8_C(64)), bits - UINT8_C(64)); | |
| 2564 | } | |
| 2245 | 2565 | } |
| 2246 | 2566 | |
| 2247 | 2567 | static inline bool zig_subo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) { |
| 2248 | uint64_t hi; | |
| 2249 | bool overflow = zig_subo_u64(&hi, lhs.hi, rhs.hi, bits - 64); | |
| 2250 | return overflow ^ zig_subo_u64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64); | |
| 2568 | if (bits <= UINT8_C(64)) { | |
| 2569 | uint64_t lo; | |
| 2570 | bool overflow = zig_subo_u64(&lo, zig_u64_intCast_u128(lhs), zig_u64_intCast_u128(rhs), bits); | |
| 2571 | *res = zig_u128_intCast_u64(lo); | |
| 2572 | return overflow; | |
| 2573 | } else { | |
| 2574 | uint64_t hi; | |
| 2575 | bool overflow = zig_subo_u64(&hi, lhs.hi, rhs.hi, bits - UINT8_C(64)); | |
| 2576 | return overflow ^ zig_subo_u64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, UINT8_C(64)), bits - UINT8_C(64)); | |
| 2577 | } | |
| 2251 | 2578 | } |
| 2252 | 2579 | |
| 2253 | 2580 | static inline bool zig_subo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) { |
| 2254 | int64_t hi; | |
| 2255 | bool overflow = zig_subo_i64(&hi, lhs.hi, rhs.hi, bits - 64); | |
| 2256 | return overflow ^ zig_subo_i64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64); | |
| 2581 | if (bits <= UINT8_C(64)) { | |
| 2582 | int64_t lo; | |
| 2583 | bool overflow = zig_subo_i64(&lo, zig_i64_intCast_i128(lhs), zig_i64_intCast_i128(rhs), bits); | |
| 2584 | *res = zig_i128_intCast_i64(lo); | |
| 2585 | return overflow; | |
| 2586 | } else { | |
| 2587 | int64_t hi; | |
| 2588 | bool overflow = zig_subo_i64(&hi, lhs.hi, rhs.hi, bits - UINT8_C(64)); | |
| 2589 | return overflow ^ zig_subo_i64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, UINT8_C(64)), bits - UINT8_C(64)); | |
| 2590 | } | |
| 2257 | 2591 | } |
| 2258 | 2592 | |
| 2259 | 2593 | static inline bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) { |
| 2260 | 2594 | *res = zig_mulw_u128(lhs, rhs, bits); |
| 2261 | return zig_cmp_u128(*res, zig_make_u128(0, 0)) != INT32_C(0) && | |
| 2262 | zig_cmp_u128(lhs, zig_div_trunc_u128(zig_maxInt_u(128, bits), rhs)) > INT32_C(0); | |
| 2595 | return zig_cmp_u128(rhs, zig_make_u128(0, 0)) != INT32_C(0) && | |
| 2596 | zig_cmp_u128(lhs, zig_divTrunc_u128(zig_maxInt_u(128, bits), rhs)) > INT32_C(0); | |
| 2263 | 2597 | } |
| 2264 | 2598 | |
| 2265 | zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow); | |
| 2266 | 2599 | static 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 | 2601 | int overflow_int; |
| 2268 | 2602 | zig_i128 full_res = __muloti4(lhs, rhs, &overflow_int); |
| 2269 | 2603 | bool overflow = overflow_int != 0 || |
| 2270 | 2604 | zig_cmp_i128(full_res, zig_minInt_i(128, bits)) < INT32_C(0) || |
| 2271 | 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 | 2607 | return overflow; |
| 2274 | 2608 | } |
| 2275 | 2609 | |
| ... | ... | @@ -2282,28 +2616,54 @@ static inline bool zig_shlo_u128(zig_u128 *res, zig_u128 lhs, uint8_t rhs, uint8 |
| 2282 | 2616 | |
| 2283 | 2617 | static inline bool zig_shlo_i128(zig_i128 *res, zig_i128 lhs, uint8_t rhs, uint8_t bits) { |
| 2284 | 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 | 2620 | return zig_cmp_i128(zig_and_i128(lhs, mask), zig_make_i128(0, 0)) != INT32_C(0) && |
| 2287 | 2621 | zig_cmp_i128(zig_and_i128(lhs, mask), mask) != INT32_C(0); |
| 2288 | 2622 | } |
| 2289 | 2623 | |
| 2290 | static 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 | } | |
| 2645 | zig_int128_shls_builtins(8) | |
| 2646 | zig_int128_shls_builtins(16) | |
| 2647 | zig_int128_shls_builtins(32) | |
| 2648 | zig_int128_shls_builtins(64) | |
| 2649 | ||
| 2650 | static inline zig_u128 zig_shls_u128_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) { | |
| 2291 | 2651 | zig_u128 res; |
| 2292 | 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 | 2653 | switch (zig_cmp_u128(lhs, zig_make_u128(0, 0))) { |
| 2294 | case 0: return zig_make_u128(0, 0); | |
| 2295 | case 1: return zig_maxInt_u(128, bits); | |
| 2654 | case INT32_C(0): return zig_make_u128(0, 0); | |
| 2655 | case INT32_C(1): return zig_maxInt_u(128, bits); | |
| 2296 | 2656 | default: zig_unreachable(); |
| 2297 | 2657 | } |
| 2298 | 2658 | } |
| 2299 | 2659 | |
| 2300 | static inline zig_i128 zig_shls_i128(zig_i128 lhs, zig_u128 rhs, uint8_t bits) { | |
| 2660 | static inline zig_i128 zig_shls_i128_u128(zig_i128 lhs, zig_u128 rhs, uint8_t bits) { | |
| 2301 | 2661 | zig_i128 res; |
| 2302 | 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 | 2663 | switch (zig_cmp_i128(lhs, zig_make_i128(0, 0))) { |
| 2304 | case -1: return zig_minInt_i(128, bits); | |
| 2305 | case 0: return zig_make_i128(0, 0); | |
| 2306 | case 1: return zig_maxInt_i(128, bits); | |
| 2664 | case -INT32_C(1): return zig_minInt_i(128, bits); | |
| 2665 | case INT32_C(0): return zig_make_i128(0, 0); | |
| 2666 | case INT32_C(1): return zig_maxInt_i(128, bits); | |
| 2307 | 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 | 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 | } |
| 2343 | 2703 | |
| 2344 | static inline uint8_t zig_clz_u128(zig_u128 val, uint8_t bits) { | |
| 2345 | if (bits <= UINT8_C(64)) return zig_clz_u64(zig_lo_u128(val), bits); | |
| 2346 | if (zig_hi_u128(val) != 0) return zig_clz_u64(zig_hi_u128(val), bits - UINT8_C(64)); | |
| 2347 | return zig_clz_u64(zig_lo_u128(val), UINT8_C(64)) + (bits - UINT8_C(64)); | |
| 2704 | static inline uint8_t zig_clz_u128(zig_u128 arg, uint8_t bits) { | |
| 2705 | if (bits <= UINT8_C(64)) return zig_clz_u64(zig_lo_u128(arg), bits); | |
| 2706 | if (zig_hi_u128(arg) != 0) return zig_clz_u64(zig_hi_u128(arg), bits - UINT8_C(64)); | |
| 2707 | return zig_clz_u64(zig_lo_u128(arg), UINT8_C(64)) + (bits - UINT8_C(64)); | |
| 2348 | 2708 | } |
| 2349 | 2709 | |
| 2350 | static inline uint8_t zig_clz_i128(zig_i128 val, uint8_t bits) { | |
| 2351 | return zig_clz_u128(zig_bitCast_u128(val), bits); | |
| 2710 | static inline uint8_t zig_clz_i128(zig_i128 arg, uint8_t bits) { | |
| 2711 | return zig_clz_u128(zig_u128_bitCast_i128(arg, bits), bits); | |
| 2352 | 2712 | } |
| 2353 | 2713 | |
| 2354 | static inline uint8_t zig_ctz_u128(zig_u128 val, uint8_t bits) { | |
| 2355 | if (zig_lo_u128(val) != 0) return zig_ctz_u64(zig_lo_u128(val), UINT8_C(64)); | |
| 2356 | return zig_ctz_u64(zig_hi_u128(val), bits - UINT8_C(64)) + UINT8_C(64); | |
| 2714 | static inline uint8_t zig_ctz_u128(zig_u128 arg, uint8_t bits) { | |
| 2715 | if (zig_lo_u128(arg) != 0) return zig_ctz_u64(zig_lo_u128(arg), UINT8_C(64)); | |
| 2716 | return zig_ctz_u64(zig_hi_u128(arg), bits - UINT8_C(64)) + UINT8_C(64); | |
| 2357 | 2717 | } |
| 2358 | 2718 | |
| 2359 | static inline uint8_t zig_ctz_i128(zig_i128 val, uint8_t bits) { | |
| 2360 | return zig_ctz_u128(zig_bitCast_u128(val), bits); | |
| 2719 | static inline uint8_t zig_ctz_i128(zig_i128 arg, uint8_t bits) { | |
| 2720 | return zig_ctz_u128(zig_u128_bitCast_i128(arg, bits), bits); | |
| 2361 | 2721 | } |
| 2362 | 2722 | |
| 2363 | static inline uint8_t zig_popcount_u128(zig_u128 val, uint8_t bits) { | |
| 2364 | return zig_popcount_u64(zig_hi_u128(val), bits - UINT8_C(64)) + | |
| 2365 | zig_popcount_u64(zig_lo_u128(val), UINT8_C(64)); | |
| 2723 | static inline uint8_t zig_popCount_u128(zig_u128 arg, uint8_t bits) { | |
| 2724 | return (bits > UINT8_C(64) ? zig_popCount_u64(zig_hi_u128(arg), bits - UINT8_C(64)) : UINT8_C(0)) + | |
| 2725 | zig_popCount_u64(zig_lo_u128(arg), UINT8_C(64)); | |
| 2366 | 2726 | } |
| 2367 | 2727 | |
| 2368 | static inline uint8_t zig_popcount_i128(zig_i128 val, uint8_t bits) { | |
| 2369 | return zig_popcount_u128(zig_bitCast_u128(val), bits); | |
| 2728 | static inline uint8_t zig_popCount_i128(zig_i128 arg, uint8_t bits) { | |
| 2729 | return zig_popCount_u128(zig_u128_bitCast_i128(arg, bits), bits); | |
| 2370 | 2730 | } |
| 2371 | 2731 | |
| 2372 | static inline zig_u128 zig_byte_swap_u128(zig_u128 val, uint8_t bits) { | |
| 2732 | static inline zig_u128 zig_byteSwap_u128(zig_u128 arg, uint8_t bits) { | |
| 2373 | 2733 | zig_u128 full_res; |
| 2374 | 2734 | #if zig_has_builtin(bswap128) |
| 2375 | full_res = __builtin_bswap128(val); | |
| 2735 | full_res = __builtin_bswap128(arg); | |
| 2376 | 2736 | #else |
| 2377 | full_res = zig_make_u128(zig_byte_swap_u64(zig_lo_u128(val), UINT8_C(64)), | |
| 2378 | zig_byte_swap_u64(zig_hi_u128(val), UINT8_C(64))); | |
| 2737 | full_res = zig_make_u128( | |
| 2738 | zig_byteSwap_u64(zig_lo_u128(arg), UINT8_C(64)), | |
| 2739 | zig_byteSwap_u64(zig_hi_u128(arg), UINT8_C(64)) | |
| 2740 | ); | |
| 2379 | 2741 | #endif |
| 2380 | 2742 | return zig_shr_u128(full_res, UINT8_C(128) - bits); |
| 2381 | 2743 | } |
| 2382 | 2744 | |
| 2383 | static inline zig_i128 zig_byte_swap_i128(zig_i128 val, uint8_t bits) { | |
| 2384 | return zig_bitCast_i128(zig_byte_swap_u128(zig_bitCast_u128(val), bits)); | |
| 2745 | static inline zig_i128 zig_byteSwap_i128(zig_i128 arg, uint8_t bits) { | |
| 2746 | return zig_i128_bitCast_u128(zig_byteSwap_u128(zig_u128_bitCast_i128(arg, bits), bits), bits); | |
| 2385 | 2747 | } |
| 2386 | 2748 | |
| 2387 | static inline zig_u128 zig_bit_reverse_u128(zig_u128 val, uint8_t bits) { | |
| 2388 | return zig_shr_u128(zig_make_u128(zig_bit_reverse_u64(zig_lo_u128(val), UINT8_C(64)), | |
| 2389 | zig_bit_reverse_u64(zig_hi_u128(val), UINT8_C(64))), | |
| 2390 | UINT8_C(128) - bits); | |
| 2749 | static inline zig_u128 zig_bitReverse_u128(zig_u128 arg, uint8_t bits) { | |
| 2750 | return zig_shr_u128(zig_make_u128( | |
| 2751 | zig_bitReverse_u64(zig_lo_u128(arg), UINT8_C(64)), | |
| 2752 | zig_bitReverse_u64(zig_hi_u128(arg), UINT8_C(64)) | |
| 2753 | ), UINT8_C(128) - bits); | |
| 2391 | 2754 | } |
| 2392 | 2755 | |
| 2393 | static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, uint8_t bits) { | |
| 2394 | return zig_bitCast_i128(zig_bit_reverse_u128(zig_bitCast_u128(val), bits)); | |
| 2756 | static inline zig_i128 zig_bitReverse_i128(zig_i128 arg, uint8_t bits) { | |
| 2757 | return zig_i128_bitCast_u128(zig_bitReverse_u128(zig_u128_bitCast_i128(arg, bits), bits), bits); | |
| 2395 | 2758 | } |
| 2396 | 2759 | |
| 2397 | 2760 | #if zig_has_int128 |
| ... | ... | @@ -2411,15 +2774,218 @@ static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, uint8_t bits) { |
| 2411 | 2774 | /* ========================== Big Integer Support =========================== */ |
| 2412 | 2775 | |
| 2413 | 2776 | static 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 | 2778 | uint16_t alignment = ZIG_TARGET_MAX_INT_ALIGNMENT; |
| 2779 | ||
| 2416 | 2780 | while (alignment / 2 >= bytes) alignment /= 2; |
| 2417 | 2781 | return (bytes + alignment - 1) / alignment * alignment; |
| 2418 | 2782 | } |
| 2419 | 2783 | |
| 2420 | static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { | |
| 2784 | static 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 | ||
| 2816 | static 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 | ||
| 2848 | static 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 | ||
| 2859 | static inline void zig_big_intCast_big(void *res, const void *arg, bool res_is_signed, uint16_t res_bits, bool arg_is_signed, uint16_t arg_bits) { | |
| 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 | ||
| 2876 | static inline void zig_big_truncate_big(void *res, const void *arg, bool res_is_signed, uint16_t res_bits, bool arg_is_signed, uint16_t arg_bits) { | |
| 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 | } | |
| 2940 | zig_big_casts(false, u, 8, uint8_t) | |
| 2941 | zig_big_casts(true , i, 8, int8_t) | |
| 2942 | zig_big_casts(false, u, 16, uint16_t) | |
| 2943 | zig_big_casts(true , i, 16, int16_t) | |
| 2944 | zig_big_casts(false, u, 32, uint32_t) | |
| 2945 | zig_big_casts(true , i, 32, int32_t) | |
| 2946 | zig_big_casts(false, u, 64, uint64_t) | |
| 2947 | zig_big_casts(true , i, 64, int64_t) | |
| 2948 | zig_big_casts(false, u, 128, zig_u128) | |
| 2949 | zig_big_casts(true , i, 128, zig_i128) | |
| 2950 | ||
| 2951 | static 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 | ||
| 2987 | static inline int32_t zig_cmp_big_u8(const void *lhs, uint8_t rhs, bool is_signed, uint16_t bits) { | |
| 2421 | 2988 | const uint8_t *lhs_bytes = lhs; |
| 2422 | const uint8_t *rhs_bytes = rhs; | |
| 2423 | 2989 | uint16_t byte_offset = 0; |
| 2424 | 2990 | bool do_signed = is_signed; |
| 2425 | 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 | 2995 | #endif |
| 2430 | 2996 | |
| 2431 | 2997 | while (remaining_bytes >= 128 / CHAR_BIT) { |
| 2998 | uint8_t rhs_byte = remaining_bytes == 128 / CHAR_BIT ? rhs : UINT8_C(0); | |
| 2432 | 2999 | int32_t limb_cmp; |
| 2433 | 3000 | |
| 2434 | 3001 | #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 | 3004 | |
| 2438 | 3005 | if (do_signed) { |
| 2439 | 3006 | zig_i128 lhs_limb; |
| 2440 | zig_i128 rhs_limb; | |
| 3007 | zig_i128 rhs_limb = zig_i128_intCast_u8(rhs_byte); | |
| 2441 | 3008 | |
| 2442 | 3009 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); |
| 2443 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 2444 | 3010 | limb_cmp = zig_cmp_i128(lhs_limb, rhs_limb); |
| 2445 | 3011 | do_signed = false; |
| 2446 | 3012 | } else { |
| 2447 | 3013 | zig_u128 lhs_limb; |
| 2448 | zig_u128 rhs_limb; | |
| 3014 | zig_u128 rhs_limb = zig_u128_intCast_u8(rhs_byte); | |
| 2449 | 3015 | |
| 2450 | 3016 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); |
| 2451 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 2452 | 3017 | limb_cmp = zig_cmp_u128(lhs_limb, rhs_limb); |
| 2453 | 3018 | } |
| 2454 | 3019 | |
| ... | ... | @@ -2461,24 +3026,24 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign |
| 2461 | 3026 | } |
| 2462 | 3027 | |
| 2463 | 3028 | while (remaining_bytes >= 64 / CHAR_BIT) { |
| 3029 | uint8_t rhs_byte = remaining_bytes == 64 / CHAR_BIT ? rhs : UINT8_C(0); | |
| 3030 | ||
| 2464 | 3031 | #if zig_little_endian |
| 2465 | 3032 | byte_offset -= 64 / CHAR_BIT; |
| 2466 | 3033 | #endif |
| 2467 | 3034 | |
| 2468 | 3035 | if (do_signed) { |
| 2469 | 3036 | int64_t lhs_limb; |
| 2470 | int64_t rhs_limb; | |
| 3037 | int64_t rhs_limb = zig_i64_intCast_u8(rhs_byte); | |
| 2471 | 3038 | |
| 2472 | 3039 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); |
| 2473 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 2474 | 3040 | if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); |
| 2475 | 3041 | do_signed = false; |
| 2476 | 3042 | } else { |
| 2477 | 3043 | uint64_t lhs_limb; |
| 2478 | uint64_t rhs_limb; | |
| 3044 | uint64_t rhs_limb = zig_u64_intCast_u8(rhs_byte); | |
| 2479 | 3045 | |
| 2480 | 3046 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); |
| 2481 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 2482 | 3047 | if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); |
| 2483 | 3048 | } |
| 2484 | 3049 | |
| ... | ... | @@ -2490,24 +3055,24 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign |
| 2490 | 3055 | } |
| 2491 | 3056 | |
| 2492 | 3057 | while (remaining_bytes >= 32 / CHAR_BIT) { |
| 3058 | uint8_t rhs_byte = remaining_bytes == 32 / CHAR_BIT ? rhs : UINT8_C(0); | |
| 3059 | ||
| 2493 | 3060 | #if zig_little_endian |
| 2494 | 3061 | byte_offset -= 32 / CHAR_BIT; |
| 2495 | 3062 | #endif |
| 2496 | 3063 | |
| 2497 | 3064 | if (do_signed) { |
| 2498 | 3065 | int32_t lhs_limb; |
| 2499 | int32_t rhs_limb; | |
| 3066 | int32_t rhs_limb = zig_i32_intCast_u8(rhs_byte); | |
| 2500 | 3067 | |
| 2501 | 3068 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); |
| 2502 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 2503 | 3069 | if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); |
| 2504 | 3070 | do_signed = false; |
| 2505 | 3071 | } else { |
| 2506 | 3072 | uint32_t lhs_limb; |
| 2507 | uint32_t rhs_limb; | |
| 3073 | uint32_t rhs_limb = zig_u32_intCast_u8(rhs_byte); | |
| 2508 | 3074 | |
| 2509 | 3075 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); |
| 2510 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 2511 | 3076 | if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); |
| 2512 | 3077 | } |
| 2513 | 3078 | |
| ... | ... | @@ -2519,24 +3084,24 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign |
| 2519 | 3084 | } |
| 2520 | 3085 | |
| 2521 | 3086 | while (remaining_bytes >= 16 / CHAR_BIT) { |
| 3087 | uint8_t rhs_byte = remaining_bytes == 16 / CHAR_BIT ? rhs : UINT8_C(0); | |
| 3088 | ||
| 2522 | 3089 | #if zig_little_endian |
| 2523 | 3090 | byte_offset -= 16 / CHAR_BIT; |
| 2524 | 3091 | #endif |
| 2525 | 3092 | |
| 2526 | 3093 | if (do_signed) { |
| 2527 | 3094 | int16_t lhs_limb; |
| 2528 | int16_t rhs_limb; | |
| 3095 | int16_t rhs_limb = zig_i16_intCast_u8(rhs_byte); | |
| 2529 | 3096 | |
| 2530 | 3097 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); |
| 2531 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 2532 | 3098 | if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); |
| 2533 | 3099 | do_signed = false; |
| 2534 | 3100 | } else { |
| 2535 | 3101 | uint16_t lhs_limb; |
| 2536 | uint16_t rhs_limb; | |
| 3102 | uint16_t rhs_limb = zig_u16_intCast_u8(rhs_byte); | |
| 2537 | 3103 | |
| 2538 | 3104 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); |
| 2539 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 2540 | 3105 | if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); |
| 2541 | 3106 | } |
| 2542 | 3107 | |
| ... | ... | @@ -2548,24 +3113,26 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign |
| 2548 | 3113 | } |
| 2549 | 3114 | |
| 2550 | 3115 | while (remaining_bytes >= 8 / CHAR_BIT) { |
| 3116 | uint8_t rhs_byte = remaining_bytes == 16 / CHAR_BIT ? rhs : UINT8_C(0); | |
| 3117 | ||
| 2551 | 3118 | #if zig_little_endian |
| 2552 | 3119 | byte_offset -= 8 / CHAR_BIT; |
| 2553 | 3120 | #endif |
| 2554 | 3121 | |
| 2555 | 3122 | if (do_signed) { |
| 2556 | 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); | |
| 2558 | 3126 | |
| 2559 | 3127 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); |
| 2560 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 2561 | if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); | |
| 3128 | lhs_cmp_limb = zig_i16_intCast_i8(lhs_limb); | |
| 3129 | if (lhs_cmp_limb != rhs_cmp_limb) return (lhs_cmp_limb > rhs_cmp_limb) - (lhs_cmp_limb < rhs_cmp_limb); | |
| 2562 | 3130 | do_signed = false; |
| 2563 | 3131 | } else { |
| 2564 | 3132 | uint8_t lhs_limb; |
| 2565 | uint8_t rhs_limb; | |
| 3133 | uint8_t rhs_limb = rhs_byte; | |
| 2566 | 3134 | |
| 2567 | 3135 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); |
| 2568 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 2569 | 3136 | if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); |
| 2570 | 3137 | } |
| 2571 | 3138 | |
| ... | ... | @@ -2579,148 +3146,472 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign |
| 2579 | 3146 | return 0; |
| 2580 | 3147 | } |
| 2581 | 3148 | |
| 2582 | static inline void zig_and_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { | |
| 2583 | uint8_t *res_bytes = res; | |
| 3149 | static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { | |
| 2584 | 3150 | const uint8_t *lhs_bytes = lhs; |
| 2585 | 3151 | const uint8_t *rhs_bytes = rhs; |
| 2586 | 3152 | uint16_t byte_offset = 0; |
| 3153 | bool do_signed = is_signed; | |
| 2587 | 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 | |
| 2589 | 3159 | |
| 2590 | 3160 | while (remaining_bytes >= 128 / CHAR_BIT) { |
| 2591 | zig_u128 res_limb; | |
| 2592 | zig_u128 lhs_limb; | |
| 2593 | zig_u128 rhs_limb; | |
| 3161 | int32_t limb_cmp; | |
| 2594 | 3162 | |
| 2595 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); | |
| 2596 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 2597 | res_limb = zig_and_u128(lhs_limb, rhs_limb); | |
| 2598 | memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); | |
| 3163 | #if zig_little_endian | |
| 3164 | byte_offset -= 128 / CHAR_BIT; | |
| 3165 | #endif | |
| 3166 | ||
| 3167 | if (do_signed) { | |
| 3168 | zig_i128 lhs_limb; | |
| 3169 | zig_i128 rhs_limb; | |
| 3170 | ||
| 3171 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); | |
| 3172 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 3173 | limb_cmp = zig_cmp_i128(lhs_limb, rhs_limb); | |
| 3174 | do_signed = false; | |
| 3175 | } else { | |
| 3176 | zig_u128 lhs_limb; | |
| 3177 | zig_u128 rhs_limb; | |
| 3178 | ||
| 3179 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); | |
| 3180 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 3181 | limb_cmp = zig_cmp_u128(lhs_limb, rhs_limb); | |
| 3182 | } | |
| 2599 | 3183 | |
| 3184 | if (limb_cmp != 0) return limb_cmp; | |
| 2600 | 3185 | remaining_bytes -= 128 / CHAR_BIT; |
| 3186 | ||
| 3187 | #if zig_big_endian | |
| 2601 | 3188 | byte_offset += 128 / CHAR_BIT; |
| 3189 | #endif | |
| 2602 | 3190 | } |
| 2603 | 3191 | |
| 2604 | 3192 | while (remaining_bytes >= 64 / CHAR_BIT) { |
| 2605 | uint64_t res_limb; | |
| 2606 | uint64_t lhs_limb; | |
| 2607 | uint64_t rhs_limb; | |
| 3193 | #if zig_little_endian | |
| 3194 | byte_offset -= 64 / CHAR_BIT; | |
| 3195 | #endif | |
| 2608 | 3196 | |
| 2609 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); | |
| 2610 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 2611 | res_limb = zig_and_u64(lhs_limb, rhs_limb); | |
| 2612 | memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); | |
| 3197 | if (do_signed) { | |
| 3198 | int64_t lhs_limb; | |
| 3199 | int64_t rhs_limb; | |
| 3200 | ||
| 3201 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); | |
| 3202 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 3203 | if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); | |
| 3204 | do_signed = false; | |
| 3205 | } else { | |
| 3206 | uint64_t lhs_limb; | |
| 3207 | uint64_t rhs_limb; | |
| 3208 | ||
| 3209 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); | |
| 3210 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 3211 | if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); | |
| 3212 | } | |
| 2613 | 3213 | |
| 2614 | 3214 | remaining_bytes -= 64 / CHAR_BIT; |
| 3215 | ||
| 3216 | #if zig_big_endian | |
| 2615 | 3217 | byte_offset += 64 / CHAR_BIT; |
| 3218 | #endif | |
| 2616 | 3219 | } |
| 2617 | 3220 | |
| 2618 | 3221 | while (remaining_bytes >= 32 / CHAR_BIT) { |
| 2619 | uint32_t res_limb; | |
| 2620 | uint32_t lhs_limb; | |
| 2621 | uint32_t rhs_limb; | |
| 3222 | #if zig_little_endian | |
| 3223 | byte_offset -= 32 / CHAR_BIT; | |
| 3224 | #endif | |
| 2622 | 3225 | |
| 2623 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); | |
| 2624 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 2625 | res_limb = zig_and_u32(lhs_limb, rhs_limb); | |
| 2626 | memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); | |
| 3226 | if (do_signed) { | |
| 3227 | int32_t lhs_limb; | |
| 3228 | int32_t rhs_limb; | |
| 3229 | ||
| 3230 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); | |
| 3231 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 3232 | if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); | |
| 3233 | do_signed = false; | |
| 3234 | } else { | |
| 3235 | uint32_t lhs_limb; | |
| 3236 | uint32_t rhs_limb; | |
| 3237 | ||
| 3238 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); | |
| 3239 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 3240 | if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); | |
| 3241 | } | |
| 2627 | 3242 | |
| 2628 | 3243 | remaining_bytes -= 32 / CHAR_BIT; |
| 3244 | ||
| 3245 | #if zig_big_endian | |
| 2629 | 3246 | byte_offset += 32 / CHAR_BIT; |
| 3247 | #endif | |
| 2630 | 3248 | } |
| 2631 | 3249 | |
| 2632 | 3250 | while (remaining_bytes >= 16 / CHAR_BIT) { |
| 2633 | uint16_t res_limb; | |
| 2634 | uint16_t lhs_limb; | |
| 2635 | uint16_t rhs_limb; | |
| 3251 | #if zig_little_endian | |
| 3252 | byte_offset -= 16 / CHAR_BIT; | |
| 3253 | #endif | |
| 2636 | 3254 | |
| 2637 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); | |
| 2638 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 2639 | res_limb = zig_and_u16(lhs_limb, rhs_limb); | |
| 2640 | memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); | |
| 3255 | if (do_signed) { | |
| 3256 | int16_t lhs_limb; | |
| 3257 | int16_t rhs_limb; | |
| 3258 | ||
| 3259 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); | |
| 3260 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 3261 | if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); | |
| 3262 | do_signed = false; | |
| 3263 | } else { | |
| 3264 | uint16_t lhs_limb; | |
| 3265 | uint16_t rhs_limb; | |
| 3266 | ||
| 3267 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); | |
| 3268 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 3269 | if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); | |
| 3270 | } | |
| 2641 | 3271 | |
| 2642 | 3272 | remaining_bytes -= 16 / CHAR_BIT; |
| 3273 | ||
| 3274 | #if zig_big_endian | |
| 2643 | 3275 | byte_offset += 16 / CHAR_BIT; |
| 3276 | #endif | |
| 2644 | 3277 | } |
| 2645 | 3278 | |
| 2646 | 3279 | while (remaining_bytes >= 8 / CHAR_BIT) { |
| 2647 | uint8_t res_limb; | |
| 2648 | uint8_t lhs_limb; | |
| 2649 | uint8_t rhs_limb; | |
| 3280 | #if zig_little_endian | |
| 3281 | byte_offset -= 8 / CHAR_BIT; | |
| 3282 | #endif | |
| 2650 | 3283 | |
| 2651 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); | |
| 2652 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 2653 | res_limb = zig_and_u8(lhs_limb, rhs_limb); | |
| 2654 | memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); | |
| 3284 | if (do_signed) { | |
| 3285 | int8_t lhs_limb; | |
| 3286 | int8_t rhs_limb; | |
| 3287 | ||
| 3288 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); | |
| 3289 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 3290 | if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); | |
| 3291 | do_signed = false; | |
| 3292 | } else { | |
| 3293 | uint8_t lhs_limb; | |
| 3294 | uint8_t rhs_limb; | |
| 3295 | ||
| 3296 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); | |
| 3297 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 3298 | if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); | |
| 3299 | } | |
| 2655 | 3300 | |
| 2656 | 3301 | remaining_bytes -= 8 / CHAR_BIT; |
| 3302 | ||
| 3303 | #if zig_big_endian | |
| 2657 | 3304 | byte_offset += 8 / CHAR_BIT; |
| 3305 | #endif | |
| 2658 | 3306 | } |
| 3307 | ||
| 3308 | return 0; | |
| 2659 | 3309 | } |
| 2660 | 3310 | |
| 2661 | static inline void zig_or_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { | |
| 3311 | static inline void zig_not_big(void *res, const void *arg, bool is_signed, uint16_t bits) { | |
| 2662 | 3312 | uint8_t *res_bytes = res; |
| 2663 | const uint8_t *lhs_bytes = lhs; | |
| 2664 | const uint8_t *rhs_bytes = rhs; | |
| 3313 | const uint8_t *arg_bytes = arg; | |
| 2665 | 3314 | uint16_t byte_offset = 0; |
| 2666 | 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 | |
| 2668 | 3321 | |
| 2669 | 3322 | while (remaining_bytes >= 128 / CHAR_BIT) { |
| 2670 | zig_u128 res_limb; | |
| 2671 | zig_u128 lhs_limb; | |
| 2672 | zig_u128 rhs_limb; | |
| 3323 | uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0); | |
| 2673 | 3324 | |
| 2674 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); | |
| 2675 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 2676 | res_limb = zig_or_u128(lhs_limb, rhs_limb); | |
| 2677 | memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); | |
| 3325 | #if zig_big_endian | |
| 3326 | byte_offset -= 128 / CHAR_BIT; | |
| 3327 | #endif | |
| 3328 | ||
| 3329 | if (remaining_bytes != 128 / CHAR_BIT || is_signed) { | |
| 3330 | zig_i128 res_limb; | |
| 3331 | zig_i128 arg_limb; | |
| 3332 | ||
| 3333 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 3334 | res_limb = zig_not_i128(arg_limb, limb_bits); | |
| 3335 | memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); | |
| 3336 | } else { | |
| 3337 | zig_u128 res_limb; | |
| 3338 | zig_u128 arg_limb; | |
| 3339 | ||
| 3340 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 3341 | res_limb = zig_not_u128(arg_limb, limb_bits); | |
| 3342 | memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); | |
| 3343 | } | |
| 2678 | 3344 | |
| 2679 | 3345 | remaining_bytes -= 128 / CHAR_BIT; |
| 3346 | ||
| 3347 | #if zig_little_endian | |
| 2680 | 3348 | byte_offset += 128 / CHAR_BIT; |
| 3349 | #endif | |
| 2681 | 3350 | } |
| 2682 | 3351 | |
| 2683 | 3352 | while (remaining_bytes >= 64 / CHAR_BIT) { |
| 2684 | uint64_t res_limb; | |
| 2685 | uint64_t lhs_limb; | |
| 2686 | uint64_t rhs_limb; | |
| 3353 | uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0); | |
| 2687 | 3354 | |
| 2688 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); | |
| 2689 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 2690 | res_limb = zig_or_u64(lhs_limb, rhs_limb); | |
| 2691 | memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); | |
| 3355 | #if zig_big_endian | |
| 3356 | byte_offset -= 64 / CHAR_BIT; | |
| 3357 | #endif | |
| 3358 | ||
| 3359 | if (remaining_bytes != 64 / CHAR_BIT || is_signed) { | |
| 3360 | int64_t res_limb; | |
| 3361 | int64_t arg_limb; | |
| 3362 | ||
| 3363 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 3364 | res_limb = zig_not_i64(arg_limb, limb_bits); | |
| 3365 | memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); | |
| 3366 | } else { | |
| 3367 | uint64_t res_limb; | |
| 3368 | uint64_t arg_limb; | |
| 3369 | ||
| 3370 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 3371 | res_limb = zig_not_u64(arg_limb, limb_bits); | |
| 3372 | memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); | |
| 3373 | } | |
| 2692 | 3374 | |
| 2693 | 3375 | remaining_bytes -= 64 / CHAR_BIT; |
| 3376 | ||
| 3377 | #if zig_little_endian | |
| 2694 | 3378 | byte_offset += 64 / CHAR_BIT; |
| 3379 | #endif | |
| 2695 | 3380 | } |
| 2696 | 3381 | |
| 2697 | 3382 | while (remaining_bytes >= 32 / CHAR_BIT) { |
| 2698 | uint32_t res_limb; | |
| 2699 | uint32_t lhs_limb; | |
| 2700 | uint32_t rhs_limb; | |
| 3383 | uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0); | |
| 2701 | 3384 | |
| 2702 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); | |
| 2703 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 2704 | res_limb = zig_or_u32(lhs_limb, rhs_limb); | |
| 2705 | memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); | |
| 3385 | #if zig_big_endian | |
| 3386 | byte_offset -= 32 / CHAR_BIT; | |
| 3387 | #endif | |
| 3388 | ||
| 3389 | if (remaining_bytes != 32 / CHAR_BIT || is_signed) { | |
| 3390 | int32_t res_limb; | |
| 3391 | int32_t arg_limb; | |
| 3392 | ||
| 3393 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 3394 | res_limb = zig_not_i32(arg_limb, limb_bits); | |
| 3395 | memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); | |
| 3396 | } else { | |
| 3397 | uint32_t res_limb; | |
| 3398 | uint32_t arg_limb; | |
| 3399 | ||
| 3400 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 3401 | res_limb = zig_not_u32(arg_limb, limb_bits); | |
| 3402 | memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); | |
| 3403 | } | |
| 2706 | 3404 | |
| 2707 | 3405 | remaining_bytes -= 32 / CHAR_BIT; |
| 3406 | ||
| 3407 | #if zig_little_endian | |
| 2708 | 3408 | byte_offset += 32 / CHAR_BIT; |
| 3409 | #endif | |
| 2709 | 3410 | } |
| 2710 | 3411 | |
| 2711 | 3412 | while (remaining_bytes >= 16 / CHAR_BIT) { |
| 2712 | uint16_t res_limb; | |
| 2713 | uint16_t lhs_limb; | |
| 2714 | uint16_t rhs_limb; | |
| 3413 | uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0); | |
| 2715 | 3414 | |
| 2716 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); | |
| 2717 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 2718 | res_limb = zig_or_u16(lhs_limb, rhs_limb); | |
| 2719 | memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); | |
| 3415 | #if zig_big_endian | |
| 3416 | byte_offset -= 16 / CHAR_BIT; | |
| 3417 | #endif | |
| 2720 | 3418 | |
| 2721 | remaining_bytes -= 16 / CHAR_BIT; | |
| 2722 | byte_offset += 16 / CHAR_BIT; | |
| 2723 | } | |
| 3419 | if (remaining_bytes != 16 / CHAR_BIT || is_signed) { | |
| 3420 | int16_t res_limb; | |
| 3421 | int16_t arg_limb; | |
| 3422 | ||
| 3423 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 3424 | res_limb = zig_not_i16(arg_limb, limb_bits); | |
| 3425 | memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); | |
| 3426 | } else { | |
| 3427 | uint16_t res_limb; | |
| 3428 | uint16_t arg_limb; | |
| 3429 | ||
| 3430 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 3431 | res_limb = zig_not_u16(arg_limb, limb_bits); | |
| 3432 | memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); | |
| 3433 | } | |
| 3434 | ||
| 3435 | remaining_bytes -= 16 / CHAR_BIT; | |
| 3436 | ||
| 3437 | #if zig_little_endian | |
| 3438 | byte_offset += 16 / CHAR_BIT; | |
| 3439 | #endif | |
| 3440 | } | |
| 3441 | ||
| 3442 | while (remaining_bytes >= 8 / CHAR_BIT) { | |
| 3443 | uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0); | |
| 3444 | ||
| 3445 | #if zig_big_endian | |
| 3446 | byte_offset -= 8 / CHAR_BIT; | |
| 3447 | #endif | |
| 3448 | ||
| 3449 | if (remaining_bytes != 8 / CHAR_BIT || is_signed) { | |
| 3450 | int8_t res_limb; | |
| 3451 | int8_t arg_limb; | |
| 3452 | ||
| 3453 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 3454 | res_limb = zig_not_i8(arg_limb, limb_bits); | |
| 3455 | memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); | |
| 3456 | } else { | |
| 3457 | uint8_t res_limb; | |
| 3458 | uint8_t arg_limb; | |
| 3459 | ||
| 3460 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 3461 | res_limb = zig_not_u8(arg_limb, limb_bits); | |
| 3462 | memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); | |
| 3463 | } | |
| 3464 | ||
| 3465 | remaining_bytes -= 8 / CHAR_BIT; | |
| 3466 | ||
| 3467 | #if zig_little_endian | |
| 3468 | byte_offset += 8 / CHAR_BIT; | |
| 3469 | #endif | |
| 3470 | } | |
| 3471 | } | |
| 3472 | ||
| 3473 | static 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 | ||
| 3552 | static 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 | } | |
| 2724 | 3615 | |
| 2725 | 3616 | while (remaining_bytes >= 8 / CHAR_BIT) { |
| 2726 | 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 | 3707 | } |
| 2817 | 3708 | } |
| 2818 | 3709 | |
| 3710 | static 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 | ||
| 3841 | static 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 | ||
| 3972 | static 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 | ||
| 4104 | static 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 | ||
| 4108 | static 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 | ||
| 2819 | 4112 | static inline bool zig_addo_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { |
| 2820 | 4113 | uint8_t *res_bytes = res; |
| 2821 | 4114 | const uint8_t *lhs_bytes = lhs; |
| 2822 | 4115 | const uint8_t *rhs_bytes = rhs; |
| 2823 | 4116 | uint16_t byte_offset = 0; |
| 2824 | 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 | 4119 | bool overflow = false; |
| 2827 | 4120 | |
| 2828 | 4121 | #if zig_big_endian |
| ... | ... | @@ -3038,7 +4331,7 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo |
| 3038 | 4331 | const uint8_t *rhs_bytes = rhs; |
| 3039 | 4332 | uint16_t byte_offset = 0; |
| 3040 | 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 | 4335 | bool overflow = false; |
| 3043 | 4336 | |
| 3044 | 4337 | #if zig_big_endian |
| ... | ... | @@ -3238,218 +4531,890 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo |
| 3238 | 4531 | memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); |
| 3239 | 4532 | } |
| 3240 | 4533 | |
| 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 | ||
| 4544 | static 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 | ||
| 4548 | static 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 | ||
| 4552 | static 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 | ||
| 4562 | static 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 | ||
| 4566 | static 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 | ||
| 4570 | static 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 | ||
| 4580 | static 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 | ||
| 4801 | static 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 | ||
| 4805 | static 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 | ||
| 4809 | static 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 | ||
| 4819 | static 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 | ||
| 4829 | static 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 | ||
| 4839 | static 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 | ||
| 4853 | static 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 | ||
| 4865 | static 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 | ||
| 4875 | static 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 | ||
| 4950 | static 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 | ||
| 5094 | static 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 | ||
| 5098 | static 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 | } | |
| 5132 | zig_big_shls_builtin(8) | |
| 5133 | zig_big_shls_builtin(16) | |
| 5134 | zig_big_shls_builtin(32) | |
| 5135 | zig_big_shls_builtin(64) | |
| 5136 | ||
| 5137 | static 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]; | |
| 3242 | 5159 | |
| 3243 | 5160 | #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 | 5164 | #endif |
| 3246 | 5165 | } |
| 3247 | 5166 | |
| 3248 | return overflow; | |
| 3249 | } | |
| 5167 | { | |
| 5168 | #if zig_little_endian | |
| 5169 | arg_byte_offset -= UINT16_C(1); | |
| 5170 | #else | |
| 5171 | res_byte_offset -= UINT16_C(1); | |
| 5172 | #endif | |
| 3250 | 5173 | |
| 3251 | static inline void zig_addw_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { | |
| 3252 | (void)zig_addo_big(res, lhs, rhs, is_signed, bits); | |
| 3253 | } | |
| 5174 | { | |
| 5175 | uint8_t byte = arg_bytes[arg_byte_offset]; | |
| 5176 | uint8_t fill = is_signed | |
| 5177 | ? zig_u8_bitCast_i8(zig_shr_i8(zig_i8_bitCast_u8(byte, UINT8_C(8)), UINT8_C(7)), UINT8_C(8)) | |
| 5178 | : UINT8_C(0); | |
| 3254 | 5179 | |
| 3255 | static inline void zig_subw_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { | |
| 3256 | (void)zig_subo_big(res, lhs, rhs, is_signed, bits); | |
| 3257 | } | |
| 5180 | res_bytes[res_byte_offset] = byte; | |
| 3258 | 5181 | |
| 3259 | zig_extern void __udivei4(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uintptr_t bits); | |
| 3260 | static inline void zig_div_trunc_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { | |
| 3261 | if (!is_signed) { | |
| 3262 | __udivei4(res, lhs, rhs, bits); | |
| 3263 | return; | |
| 5182 | #if zig_little_endian | |
| 5183 | res_byte_offset += UINT16_C(1); | |
| 5184 | memset(&res_bytes[res_byte_offset], fill, size - res_byte_offset); | |
| 5185 | #else | |
| 5186 | memset(&res_bytes[0], fill, res_byte_offset); | |
| 5187 | #endif | |
| 5188 | } | |
| 3264 | 5189 | } |
| 3265 | ||
| 3266 | zig_trap(); | |
| 3267 | 5190 | } |
| 3268 | 5191 | |
| 3269 | static inline void zig_div_floor_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { | |
| 3270 | if (!is_signed) { | |
| 3271 | zig_div_trunc_big(res, lhs, rhs, is_signed, bits); | |
| 3272 | return; | |
| 3273 | } | |
| 5192 | static inline void zig_bitReverse_big(void *res, const void *arg, bool is_signed, uint16_t bits) { | |
| 5193 | uint8_t *res_bytes = res; | |
| 5194 | const uint8_t *arg_bytes = arg; | |
| 5195 | uint16_t size = zig_int_bytes(bits); | |
| 5196 | uint16_t res_byte_offset = UINT16_C(0); | |
| 5197 | uint16_t arg_byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1); | |
| 5198 | uint16_t end_byte_offset = UINT16_C(0); | |
| 5199 | uint8_t arg_prev_byte; | |
| 5200 | uint8_t byte_shift = zig_u8_intCast_u16(zig_subw_u16(UINT16_C(0), bits, UINT8_C(3))); | |
| 3274 | 5201 | |
| 3275 | zig_trap(); | |
| 3276 | } | |
| 5202 | #if zig_big_endian | |
| 5203 | res_byte_offset = size - res_byte_offset; | |
| 5204 | arg_byte_offset = size - arg_byte_offset; | |
| 5205 | end_byte_offset = size - end_byte_offset; | |
| 5206 | #endif | |
| 3277 | 5207 | |
| 3278 | static inline void zig_div_ceil_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { | |
| 3279 | zig_trap(); | |
| 3280 | } | |
| 5208 | { | |
| 5209 | #if zig_little_endian | |
| 5210 | arg_byte_offset -= UINT16_C(1); | |
| 5211 | #endif | |
| 3281 | 5212 | |
| 3282 | zig_extern void __umodei4(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uintptr_t bits); | |
| 3283 | static inline void zig_rem_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { | |
| 3284 | if (!is_signed) { | |
| 3285 | __umodei4(res, lhs, rhs, bits); | |
| 3286 | return; | |
| 5213 | arg_prev_byte = zig_bitReverse_u8(arg_bytes[arg_byte_offset], UINT8_C(8)); | |
| 5214 | ||
| 5215 | #if zig_big_endian | |
| 5216 | arg_byte_offset += UINT16_C(1); | |
| 5217 | #endif | |
| 3287 | 5218 | } |
| 3288 | 5219 | |
| 3289 | zig_trap(); | |
| 3290 | } | |
| 5220 | while (arg_byte_offset != end_byte_offset) { | |
| 5221 | #if zig_big_endian | |
| 5222 | res_byte_offset -= UINT16_C(1); | |
| 5223 | #else | |
| 5224 | arg_byte_offset -= UINT16_C(1); | |
| 5225 | #endif | |
| 3291 | 5226 | |
| 3292 | static inline void zig_mod_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { | |
| 3293 | if (!is_signed) { | |
| 3294 | zig_rem_big(res, lhs, rhs, is_signed, bits); | |
| 3295 | return; | |
| 5227 | { | |
| 5228 | uint8_t arg_byte = zig_bitReverse_u8(arg_bytes[arg_byte_offset], UINT8_C(8)); | |
| 5229 | ||
| 5230 | res_bytes[res_byte_offset] = zig_u8_intCast_u16(zig_shr_u16(zig_or_u16( | |
| 5231 | zig_shl_u16(zig_u16_intCast_u8(arg_byte), UINT8_C(8)), | |
| 5232 | zig_u16_intCast_u8(arg_prev_byte) | |
| 5233 | ), byte_shift)); | |
| 5234 | arg_prev_byte = arg_byte; | |
| 5235 | } | |
| 5236 | ||
| 5237 | #if zig_little_endian | |
| 5238 | res_byte_offset += UINT16_C(1); | |
| 5239 | #else | |
| 5240 | arg_byte_offset += UINT16_C(1); | |
| 5241 | #endif | |
| 3296 | 5242 | } |
| 3297 | 5243 | |
| 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 | } |
| 3300 | 5268 | |
| 3301 | static inline uint16_t zig_clz_big(const void *val, bool is_signed, uint16_t bits) { | |
| 3302 | const uint8_t *val_bytes = val; | |
| 5269 | static inline uint16_t zig_popCount_big(const void *arg, bool is_signed, uint16_t bits) { | |
| 5270 | const uint8_t *arg_bytes = arg; | |
| 3303 | 5271 | uint16_t byte_offset = 0; |
| 3304 | uint16_t remaining_bytes = zig_int_bytes(bits); | |
| 3305 | uint16_t skip_bits = remaining_bytes * 8 - bits; | |
| 3306 | uint16_t total_lz = 0; | |
| 3307 | uint16_t limb_lz; | |
| 5272 | uint16_t remaining_bytes = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1); | |
| 5273 | uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); | |
| 5274 | uint16_t total_pc = 0; | |
| 3308 | 5275 | (void)is_signed; |
| 3309 | 5276 | |
| 3310 | #if zig_little_endian | |
| 3311 | byte_offset = remaining_bytes; | |
| 5277 | #if zig_big_endian | |
| 5278 | byte_offset = zig_int_bytes(bits); | |
| 3312 | 5279 | #endif |
| 3313 | 5280 | |
| 3314 | 5281 | while (remaining_bytes >= 128 / CHAR_BIT) { |
| 3315 | #if zig_little_endian | |
| 5282 | uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0); | |
| 5283 | ||
| 5284 | #if zig_big_endian | |
| 3316 | 5285 | byte_offset -= 128 / CHAR_BIT; |
| 3317 | 5286 | #endif |
| 3318 | 5287 | |
| 3319 | 5288 | { |
| 3320 | zig_u128 val_limb; | |
| 5289 | zig_u128 arg_limb; | |
| 3321 | 5290 | |
| 3322 | memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); | |
| 3323 | limb_lz = zig_clz_u128(val_limb, 128 - skip_bits); | |
| 5291 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 5292 | total_pc += zig_popCount_u128(zig_u128_truncate_u128(arg_limb, limb_bits), limb_bits); | |
| 3324 | 5293 | } |
| 3325 | 5294 | |
| 3326 | total_lz += limb_lz; | |
| 3327 | if (limb_lz < 128 - skip_bits) return total_lz; | |
| 3328 | skip_bits = 0; | |
| 3329 | 5295 | remaining_bytes -= 128 / CHAR_BIT; |
| 3330 | 5296 | |
| 3331 | #if zig_big_endian | |
| 5297 | #if zig_little_endian | |
| 3332 | 5298 | byte_offset += 128 / CHAR_BIT; |
| 3333 | 5299 | #endif |
| 3334 | 5300 | } |
| 3335 | 5301 | |
| 3336 | 5302 | while (remaining_bytes >= 64 / CHAR_BIT) { |
| 3337 | #if zig_little_endian | |
| 5303 | uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0); | |
| 5304 | ||
| 5305 | #if zig_big_endian | |
| 3338 | 5306 | byte_offset -= 64 / CHAR_BIT; |
| 3339 | 5307 | #endif |
| 3340 | 5308 | |
| 3341 | 5309 | { |
| 3342 | uint64_t val_limb; | |
| 5310 | uint64_t arg_limb; | |
| 3343 | 5311 | |
| 3344 | memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); | |
| 3345 | limb_lz = zig_clz_u64(val_limb, 64 - skip_bits); | |
| 5312 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 5313 | total_pc += zig_popCount_u64(zig_u64_truncate_u64(arg_limb, limb_bits), limb_bits); | |
| 3346 | 5314 | } |
| 3347 | 5315 | |
| 3348 | total_lz += limb_lz; | |
| 3349 | if (limb_lz < 64 - skip_bits) return total_lz; | |
| 3350 | skip_bits = 0; | |
| 3351 | 5316 | remaining_bytes -= 64 / CHAR_BIT; |
| 3352 | 5317 | |
| 3353 | #if zig_big_endian | |
| 5318 | #if zig_little_endian | |
| 3354 | 5319 | byte_offset += 64 / CHAR_BIT; |
| 3355 | 5320 | #endif |
| 3356 | 5321 | } |
| 3357 | 5322 | |
| 3358 | 5323 | while (remaining_bytes >= 32 / CHAR_BIT) { |
| 3359 | #if zig_little_endian | |
| 5324 | uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0); | |
| 5325 | ||
| 5326 | #if zig_big_endian | |
| 3360 | 5327 | byte_offset -= 32 / CHAR_BIT; |
| 3361 | 5328 | #endif |
| 3362 | 5329 | |
| 3363 | 5330 | { |
| 3364 | uint32_t val_limb; | |
| 5331 | uint32_t arg_limb; | |
| 3365 | 5332 | |
| 3366 | memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); | |
| 3367 | limb_lz = zig_clz_u32(val_limb, 32 - skip_bits); | |
| 5333 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 5334 | total_pc += zig_popCount_u32(zig_u32_truncate_u32(arg_limb, limb_bits), limb_bits); | |
| 3368 | 5335 | } |
| 3369 | 5336 | |
| 3370 | total_lz += limb_lz; | |
| 3371 | if (limb_lz < 32 - skip_bits) return total_lz; | |
| 3372 | skip_bits = 0; | |
| 3373 | 5337 | remaining_bytes -= 32 / CHAR_BIT; |
| 3374 | 5338 | |
| 3375 | #if zig_big_endian | |
| 5339 | #if zig_little_endian | |
| 3376 | 5340 | byte_offset += 32 / CHAR_BIT; |
| 3377 | 5341 | #endif |
| 3378 | 5342 | } |
| 3379 | 5343 | |
| 3380 | 5344 | while (remaining_bytes >= 16 / CHAR_BIT) { |
| 3381 | #if zig_little_endian | |
| 5345 | uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0); | |
| 5346 | ||
| 5347 | #if zig_big_endian | |
| 3382 | 5348 | byte_offset -= 16 / CHAR_BIT; |
| 3383 | 5349 | #endif |
| 3384 | 5350 | |
| 3385 | 5351 | { |
| 3386 | uint16_t val_limb; | |
| 5352 | uint16_t arg_limb; | |
| 3387 | 5353 | |
| 3388 | memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); | |
| 3389 | limb_lz = zig_clz_u16(val_limb, 16 - skip_bits); | |
| 5354 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 5355 | total_pc += zig_popCount_u16(zig_u16_truncate_u16(arg_limb, limb_bits), limb_bits); | |
| 3390 | 5356 | } |
| 3391 | 5357 | |
| 3392 | total_lz += limb_lz; | |
| 3393 | if (limb_lz < 16 - skip_bits) return total_lz; | |
| 3394 | skip_bits = 0; | |
| 3395 | 5358 | remaining_bytes -= 16 / CHAR_BIT; |
| 3396 | 5359 | |
| 3397 | #if zig_big_endian | |
| 5360 | #if zig_little_endian | |
| 3398 | 5361 | byte_offset += 16 / CHAR_BIT; |
| 3399 | 5362 | #endif |
| 3400 | 5363 | } |
| 3401 | 5364 | |
| 3402 | 5365 | while (remaining_bytes >= 8 / CHAR_BIT) { |
| 3403 | #if zig_little_endian | |
| 5366 | uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0); | |
| 5367 | ||
| 5368 | #if zig_big_endian | |
| 3404 | 5369 | byte_offset -= 8 / CHAR_BIT; |
| 3405 | 5370 | #endif |
| 3406 | 5371 | |
| 3407 | 5372 | { |
| 3408 | uint8_t val_limb; | |
| 5373 | uint8_t arg_limb; | |
| 3409 | 5374 | |
| 3410 | memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); | |
| 3411 | limb_lz = zig_clz_u8(val_limb, 8 - skip_bits); | |
| 5375 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 5376 | total_pc += zig_popCount_u8(zig_u8_truncate_u8(arg_limb, limb_bits), limb_bits); | |
| 3412 | 5377 | } |
| 3413 | 5378 | |
| 3414 | total_lz += limb_lz; | |
| 3415 | if (limb_lz < 8 - skip_bits) return total_lz; | |
| 3416 | skip_bits = 0; | |
| 3417 | 5379 | remaining_bytes -= 8 / CHAR_BIT; |
| 3418 | 5380 | |
| 3419 | #if zig_big_endian | |
| 5381 | #if zig_little_endian | |
| 3420 | 5382 | byte_offset += 8 / CHAR_BIT; |
| 3421 | 5383 | #endif |
| 3422 | 5384 | } |
| 3423 | 5385 | |
| 3424 | return total_lz; | |
| 5386 | return total_pc; | |
| 3425 | 5387 | } |
| 3426 | 5388 | |
| 3427 | static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bits) { | |
| 3428 | const uint8_t *val_bytes = val; | |
| 3429 | uint16_t byte_offset = 0; | |
| 3430 | uint16_t remaining_bytes = zig_int_bytes(bits); | |
| 3431 | uint16_t total_tz = 0; | |
| 5389 | static inline uint16_t zig_ctz_big(const void *arg, bool is_signed, uint16_t bits) { | |
| 5390 | const uint8_t *arg_bytes = arg; | |
| 5391 | uint16_t byte_offset = UINT16_C(0); | |
| 5392 | uint16_t remaining_bytes = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1); | |
| 5393 | uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); | |
| 5394 | uint16_t total_tz = UINT16_C(0); | |
| 3432 | 5395 | uint16_t limb_tz; |
| 3433 | 5396 | (void)is_signed; |
| 3434 | 5397 | |
| 3435 | 5398 | #if zig_big_endian |
| 3436 | byte_offset = remaining_bytes; | |
| 5399 | byte_offset = zig_int_bytes(bits); | |
| 3437 | 5400 | #endif |
| 3438 | 5401 | |
| 3439 | 5402 | while (remaining_bytes >= 128 / CHAR_BIT) { |
| 5403 | uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0); | |
| 5404 | ||
| 3440 | 5405 | #if zig_big_endian |
| 3441 | 5406 | byte_offset -= 128 / CHAR_BIT; |
| 3442 | 5407 | #endif |
| 3443 | 5408 | |
| 3444 | 5409 | { |
| 3445 | zig_u128 val_limb; | |
| 5410 | zig_u128 arg_limb; | |
| 3446 | 5411 | |
| 3447 | memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); | |
| 3448 | limb_tz = zig_ctz_u128(val_limb, 128); | |
| 5412 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 5413 | limb_tz = zig_ctz_u128(zig_u128_truncate_u128(arg_limb, limb_bits), limb_bits); | |
| 3449 | 5414 | } |
| 3450 | 5415 | |
| 3451 | 5416 | total_tz += limb_tz; |
| 3452 | if (limb_tz < 128) return total_tz; | |
| 5417 | if (limb_tz < limb_bits) return total_tz; | |
| 3453 | 5418 | remaining_bytes -= 128 / CHAR_BIT; |
| 3454 | 5419 | |
| 3455 | 5420 | #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 | 5423 | } |
| 3459 | 5424 | |
| 3460 | 5425 | while (remaining_bytes >= 64 / CHAR_BIT) { |
| 5426 | uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0); | |
| 5427 | ||
| 3461 | 5428 | #if zig_big_endian |
| 3462 | 5429 | byte_offset -= 64 / CHAR_BIT; |
| 3463 | 5430 | #endif |
| 3464 | 5431 | |
| 3465 | 5432 | { |
| 3466 | uint64_t val_limb; | |
| 5433 | uint64_t arg_limb; | |
| 3467 | 5434 | |
| 3468 | memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); | |
| 3469 | limb_tz = zig_ctz_u64(val_limb, 64); | |
| 5435 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 5436 | limb_tz = zig_ctz_u64(zig_u64_truncate_u64(arg_limb, limb_bits), limb_bits); | |
| 3470 | 5437 | } |
| 3471 | 5438 | |
| 3472 | 5439 | total_tz += limb_tz; |
| 3473 | if (limb_tz < 64) return total_tz; | |
| 5440 | if (limb_tz < limb_bits) return total_tz; | |
| 3474 | 5441 | remaining_bytes -= 64 / CHAR_BIT; |
| 3475 | 5442 | |
| 3476 | 5443 | #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 | 5446 | } |
| 3480 | 5447 | |
| 3481 | 5448 | while (remaining_bytes >= 32 / CHAR_BIT) { |
| 5449 | uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0); | |
| 5450 | ||
| 3482 | 5451 | #if zig_big_endian |
| 3483 | 5452 | byte_offset -= 32 / CHAR_BIT; |
| 3484 | 5453 | #endif |
| 3485 | 5454 | |
| 3486 | 5455 | { |
| 3487 | uint32_t val_limb; | |
| 5456 | uint32_t arg_limb; | |
| 3488 | 5457 | |
| 3489 | memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); | |
| 3490 | limb_tz = zig_ctz_u32(val_limb, 32); | |
| 5458 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 5459 | limb_tz = zig_ctz_u32(zig_u32_truncate_u32(arg_limb, limb_bits), limb_bits); | |
| 3491 | 5460 | } |
| 3492 | 5461 | |
| 3493 | 5462 | total_tz += limb_tz; |
| 3494 | if (limb_tz < 32) return total_tz; | |
| 5463 | if (limb_tz < limb_bits) return total_tz; | |
| 3495 | 5464 | remaining_bytes -= 32 / CHAR_BIT; |
| 3496 | 5465 | |
| 3497 | 5466 | #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 | 5469 | } |
| 3501 | 5470 | |
| 3502 | 5471 | while (remaining_bytes >= 16 / CHAR_BIT) { |
| 5472 | uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0); | |
| 5473 | ||
| 3503 | 5474 | #if zig_big_endian |
| 3504 | 5475 | byte_offset -= 16 / CHAR_BIT; |
| 3505 | 5476 | #endif |
| 3506 | 5477 | |
| 3507 | 5478 | { |
| 3508 | uint16_t val_limb; | |
| 5479 | uint16_t arg_limb; | |
| 3509 | 5480 | |
| 3510 | memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); | |
| 3511 | limb_tz = zig_ctz_u16(val_limb, 16); | |
| 5481 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 5482 | limb_tz = zig_ctz_u16(zig_u16_truncate_u16(arg_limb, limb_bits), limb_bits); | |
| 3512 | 5483 | } |
| 3513 | 5484 | |
| 3514 | 5485 | total_tz += limb_tz; |
| 3515 | if (limb_tz < 16) return total_tz; | |
| 5486 | if (limb_tz < limb_bits) return total_tz; | |
| 3516 | 5487 | remaining_bytes -= 16 / CHAR_BIT; |
| 3517 | 5488 | |
| 3518 | 5489 | #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 | 5492 | } |
| 3522 | 5493 | |
| 3523 | 5494 | while (remaining_bytes >= 8 / CHAR_BIT) { |
| 5495 | uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0); | |
| 5496 | ||
| 3524 | 5497 | #if zig_big_endian |
| 3525 | 5498 | byte_offset -= 8 / CHAR_BIT; |
| 3526 | 5499 | #endif |
| 3527 | 5500 | |
| 3528 | 5501 | { |
| 3529 | uint8_t val_limb; | |
| 5502 | uint8_t arg_limb; | |
| 3530 | 5503 | |
| 3531 | memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); | |
| 3532 | limb_tz = zig_ctz_u8(val_limb, 8); | |
| 5504 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 5505 | limb_tz = zig_ctz_u8(zig_u8_truncate_u8(arg_limb, limb_bits), limb_bits); | |
| 3533 | 5506 | } |
| 3534 | 5507 | |
| 3535 | 5508 | total_tz += limb_tz; |
| 3536 | if (limb_tz < 8) return total_tz; | |
| 5509 | if (limb_tz < limb_bits) return total_tz; | |
| 3537 | 5510 | remaining_bytes -= 8 / CHAR_BIT; |
| 3538 | 5511 | |
| 3539 | 5512 | #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 | 5517 | return total_tz; |
| 3545 | 5518 | } |
| 3546 | 5519 | |
| 3547 | static inline uint16_t zig_popcount_big(const void *val, bool is_signed, uint16_t bits) { | |
| 3548 | const uint8_t *val_bytes = val; | |
| 3549 | uint16_t byte_offset = 0; | |
| 3550 | uint16_t remaining_bytes = zig_int_bytes(bits); | |
| 3551 | uint16_t total_pc = 0; | |
| 5520 | static inline uint16_t zig_clz_big(const void *arg, bool is_signed, uint16_t bits) { | |
| 5521 | const uint8_t *arg_bytes = arg; | |
| 5522 | uint16_t byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1); | |
| 5523 | uint16_t remaining_bytes = byte_offset; | |
| 5524 | uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); | |
| 5525 | bool sign_limb = true; | |
| 5526 | uint16_t total_lz = UINT16_C(0); | |
| 5527 | uint16_t limb_lz; | |
| 3552 | 5528 | (void)is_signed; |
| 3553 | 5529 | |
| 3554 | 5530 | #if zig_big_endian |
| 3555 | byte_offset = remaining_bytes; | |
| 5531 | byte_offset = zig_int_bytes(bits) - remaining_bytes; | |
| 3556 | 5532 | #endif |
| 3557 | 5533 | |
| 3558 | 5534 | while (remaining_bytes >= 128 / CHAR_BIT) { |
| 3559 | #if zig_big_endian | |
| 5535 | uint8_t limb_bits = UINT8_C(128) - (sign_limb ? top_bits : UINT8_C(0)); | |
| 5536 | ||
| 5537 | #if zig_little_endian | |
| 3560 | 5538 | byte_offset -= 128 / CHAR_BIT; |
| 3561 | 5539 | #endif |
| 3562 | 5540 | |
| 3563 | 5541 | { |
| 3564 | zig_u128 val_limb; | |
| 5542 | zig_u128 arg_limb; | |
| 3565 | 5543 | |
| 3566 | memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); | |
| 3567 | total_pc += zig_popcount_u128(val_limb, 128); | |
| 5544 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 5545 | limb_lz = zig_clz_u128(zig_u128_truncate_u128(arg_limb, limb_bits), limb_bits); | |
| 3568 | 5546 | } |
| 3569 | 5547 | |
| 5548 | total_lz += limb_lz; | |
| 5549 | if (limb_lz < limb_bits) return total_lz; | |
| 5550 | sign_limb = false; | |
| 3570 | 5551 | remaining_bytes -= 128 / CHAR_BIT; |
| 3571 | 5552 | |
| 3572 | #if zig_little_endian | |
| 5553 | #if zig_big_endian | |
| 3573 | 5554 | byte_offset += 128 / CHAR_BIT; |
| 3574 | 5555 | #endif |
| 3575 | 5556 | } |
| 3576 | 5557 | |
| 3577 | 5558 | while (remaining_bytes >= 64 / CHAR_BIT) { |
| 3578 | #if zig_big_endian | |
| 5559 | uint8_t limb_bits = UINT8_C(64) - (sign_limb ? top_bits : UINT8_C(0)); | |
| 5560 | ||
| 5561 | #if zig_little_endian | |
| 3579 | 5562 | byte_offset -= 64 / CHAR_BIT; |
| 3580 | 5563 | #endif |
| 3581 | 5564 | |
| 3582 | 5565 | { |
| 3583 | uint64_t val_limb; | |
| 5566 | uint64_t arg_limb; | |
| 3584 | 5567 | |
| 3585 | memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); | |
| 3586 | total_pc += zig_popcount_u64(val_limb, 64); | |
| 5568 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 5569 | limb_lz = zig_clz_u64(zig_u64_truncate_u64(arg_limb, limb_bits), limb_bits); | |
| 3587 | 5570 | } |
| 3588 | 5571 | |
| 5572 | total_lz += limb_lz; | |
| 5573 | if (limb_lz < limb_bits) return total_lz; | |
| 5574 | sign_limb = false; | |
| 3589 | 5575 | remaining_bytes -= 64 / CHAR_BIT; |
| 3590 | 5576 | |
| 3591 | #if zig_little_endian | |
| 5577 | #if zig_big_endian | |
| 3592 | 5578 | byte_offset += 64 / CHAR_BIT; |
| 3593 | 5579 | #endif |
| 3594 | 5580 | } |
| 3595 | 5581 | |
| 3596 | 5582 | while (remaining_bytes >= 32 / CHAR_BIT) { |
| 3597 | #if zig_big_endian | |
| 5583 | uint8_t limb_bits = UINT8_C(32) - (sign_limb ? top_bits : UINT8_C(0)); | |
| 5584 | ||
| 5585 | #if zig_little_endian | |
| 3598 | 5586 | byte_offset -= 32 / CHAR_BIT; |
| 3599 | 5587 | #endif |
| 3600 | 5588 | |
| 3601 | 5589 | { |
| 3602 | uint32_t val_limb; | |
| 5590 | uint32_t arg_limb; | |
| 3603 | 5591 | |
| 3604 | memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); | |
| 3605 | total_pc += zig_popcount_u32(val_limb, 32); | |
| 5592 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 5593 | limb_lz = zig_clz_u32(zig_u32_truncate_u32(arg_limb, limb_bits), limb_bits); | |
| 3606 | 5594 | } |
| 3607 | 5595 | |
| 5596 | total_lz += limb_lz; | |
| 5597 | if (limb_lz < limb_bits) return total_lz; | |
| 5598 | sign_limb = false; | |
| 3608 | 5599 | remaining_bytes -= 32 / CHAR_BIT; |
| 3609 | 5600 | |
| 3610 | #if zig_little_endian | |
| 5601 | #if zig_big_endian | |
| 3611 | 5602 | byte_offset += 32 / CHAR_BIT; |
| 3612 | 5603 | #endif |
| 3613 | 5604 | } |
| 3614 | 5605 | |
| 3615 | 5606 | while (remaining_bytes >= 16 / CHAR_BIT) { |
| 3616 | #if zig_big_endian | |
| 5607 | uint8_t limb_bits = UINT8_C(16) - (sign_limb ? top_bits : UINT8_C(0)); | |
| 5608 | ||
| 5609 | #if zig_little_endian | |
| 3617 | 5610 | byte_offset -= 16 / CHAR_BIT; |
| 3618 | 5611 | #endif |
| 3619 | 5612 | |
| 3620 | 5613 | { |
| 3621 | uint16_t val_limb; | |
| 5614 | uint16_t arg_limb; | |
| 3622 | 5615 | |
| 3623 | memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); | |
| 3624 | total_pc = zig_popcount_u16(val_limb, 16); | |
| 5616 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 5617 | limb_lz = zig_clz_u16(zig_u16_truncate_u16(arg_limb, limb_bits), limb_bits); | |
| 3625 | 5618 | } |
| 3626 | 5619 | |
| 5620 | total_lz += limb_lz; | |
| 5621 | if (limb_lz < limb_bits) return total_lz; | |
| 5622 | sign_limb = false; | |
| 3627 | 5623 | remaining_bytes -= 16 / CHAR_BIT; |
| 3628 | 5624 | |
| 3629 | #if zig_little_endian | |
| 5625 | #if zig_big_endian | |
| 3630 | 5626 | byte_offset += 16 / CHAR_BIT; |
| 3631 | 5627 | #endif |
| 3632 | 5628 | } |
| 3633 | 5629 | |
| 3634 | 5630 | while (remaining_bytes >= 8 / CHAR_BIT) { |
| 3635 | #if zig_big_endian | |
| 5631 | uint8_t limb_bits = UINT8_C(8) - (sign_limb ? top_bits : UINT8_C(0)); | |
| 5632 | ||
| 5633 | #if zig_little_endian | |
| 3636 | 5634 | byte_offset -= 8 / CHAR_BIT; |
| 3637 | 5635 | #endif |
| 3638 | 5636 | |
| 3639 | 5637 | { |
| 3640 | uint8_t val_limb; | |
| 5638 | uint8_t arg_limb; | |
| 3641 | 5639 | |
| 3642 | memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); | |
| 3643 | total_pc = zig_popcount_u8(val_limb, 8); | |
| 5640 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 5641 | limb_lz = zig_clz_u8(zig_u8_truncate_u8(arg_limb, limb_bits), limb_bits); | |
| 3644 | 5642 | } |
| 3645 | 5643 | |
| 5644 | total_lz += limb_lz; | |
| 5645 | if (limb_lz < limb_bits) return total_lz; | |
| 5646 | sign_limb = false; | |
| 3646 | 5647 | remaining_bytes -= 8 / CHAR_BIT; |
| 3647 | 5648 | |
| 3648 | #if zig_little_endian | |
| 5649 | #if zig_big_endian | |
| 3649 | 5650 | byte_offset += 8 / CHAR_BIT; |
| 3650 | 5651 | #endif |
| 3651 | 5652 | } |
| 3652 | 5653 | |
| 3653 | return total_pc; | |
| 5654 | return total_lz; | |
| 3654 | 5655 | } |
| 3655 | 5656 | |
| 3656 | 5657 | /* ========================= Floating Point Support ========================= */ |
| ... | ... | @@ -3687,29 +5688,29 @@ long double __cdecl nanl(char const* input); |
| 3687 | 5688 | #define zig_make_special_f80(sign, name, arg, repr) sign zig_make_f80 (__builtin_##name, )(arg) |
| 3688 | 5689 | #define zig_make_special_f128(sign, name, arg, repr) sign zig_make_f128(__builtin_##name, )(arg) |
| 3689 | 5690 | #else |
| 3690 | #define zig_make_special_f16(sign, name, arg, repr) zig_bitCast_f16 (repr) | |
| 3691 | #define zig_make_special_f32(sign, name, arg, repr) zig_bitCast_f32 (repr) | |
| 3692 | #define zig_make_special_f64(sign, name, arg, repr) zig_bitCast_f64 (repr) | |
| 3693 | #define zig_make_special_f80(sign, name, arg, repr) zig_bitCast_f80 (repr) | |
| 3694 | #define zig_make_special_f128(sign, name, arg, repr) zig_bitCast_f128(repr) | |
| 5691 | #define zig_make_special_f16(sign, name, arg, repr) zig_f16_bitCast_u16 (repr) | |
| 5692 | #define zig_make_special_f32(sign, name, arg, repr) zig_f32_bitCast_u32 (repr) | |
| 5693 | #define zig_make_special_f64(sign, name, arg, repr) zig_f64_bitCast_u64 (repr) | |
| 5694 | #define zig_make_special_f80(sign, name, arg, repr) zig_f80_bitCast_u128(repr) | |
| 5695 | #define zig_make_special_f128(sign, name, arg, repr) zig_f128_bitCast_u128(repr) | |
| 3695 | 5696 | #endif |
| 3696 | 5697 | |
| 3697 | 5698 | #define zig_has_f16 1 |
| 3698 | 5699 | #define zig_libc_name_f16(name) __##name##h |
| 3699 | 5700 | #define zig_init_special_f16(sign, name, arg, repr) zig_make_special_f16(sign, name, arg, repr) |
| 3700 | #if FLT_MANT_DIG == 11 | |
| 5701 | #if !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && FLT_MANT_DIG == 11 | |
| 3701 | 5702 | typedef float zig_f16; |
| 3702 | 5703 | #define zig_make_f16(fp, repr) fp##f |
| 3703 | #elif DBL_MANT_DIG == 11 | |
| 5704 | #elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && DBL_MANT_DIG == 11 | |
| 3704 | 5705 | typedef double zig_f16; |
| 3705 | 5706 | #define zig_make_f16(fp, repr) fp |
| 3706 | #elif LDBL_MANT_DIG == 11 | |
| 5707 | #elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && LDBL_MANT_DIG == 11 | |
| 3707 | 5708 | typedef long double zig_f16; |
| 3708 | 5709 | #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)) | |
| 3710 | 5711 | typedef _Float16 zig_f16; |
| 3711 | 5712 | #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__) | |
| 3713 | 5714 | typedef __fp16 zig_f16; |
| 3714 | 5715 | #define zig_make_f16(fp, repr) fp##f16 |
| 3715 | 5716 | #else |
| ... | ... | @@ -3723,11 +5724,6 @@ typedef uint16_t zig_f16; |
| 3723 | 5724 | #undef zig_init_special_f16 |
| 3724 | 5725 | #define zig_init_special_f16(sign, name, arg, repr) repr |
| 3725 | 5726 | #endif |
| 3726 | #if defined(zig_darwin) && defined(zig_x86) | |
| 3727 | typedef uint16_t zig_compiler_rt_f16; | |
| 3728 | #else | |
| 3729 | typedef zig_f16 zig_compiler_rt_f16; | |
| 3730 | #endif | |
| 3731 | 5727 | |
| 3732 | 5728 | #define zig_has_f32 1 |
| 3733 | 5729 | #define zig_libc_name_f32(name) name##f |
| ... | ... | @@ -3736,16 +5732,16 @@ typedef zig_f16 zig_compiler_rt_f16; |
| 3736 | 5732 | #else |
| 3737 | 5733 | #define zig_init_special_f32(sign, name, arg, repr) zig_make_special_f32(sign, name, arg, repr) |
| 3738 | 5734 | #endif |
| 3739 | #if FLT_MANT_DIG == 24 | |
| 5735 | #if !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && FLT_MANT_DIG == 24 | |
| 3740 | 5736 | typedef float zig_f32; |
| 3741 | 5737 | #define zig_make_f32(fp, repr) fp##f |
| 3742 | #elif DBL_MANT_DIG == 24 | |
| 5738 | #elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && DBL_MANT_DIG == 24 | |
| 3743 | 5739 | typedef double zig_f32; |
| 3744 | 5740 | #define zig_make_f32(fp, repr) fp |
| 3745 | #elif LDBL_MANT_DIG == 24 | |
| 5741 | #elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && LDBL_MANT_DIG == 24 | |
| 3746 | 5742 | typedef long double zig_f32; |
| 3747 | 5743 | #define zig_make_f32(fp, repr) fp##l |
| 3748 | #elif FLT32_MANT_DIG == 24 | |
| 5744 | #elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && FLT32_MANT_DIG == 24 | |
| 3749 | 5745 | typedef _Float32 zig_f32; |
| 3750 | 5746 | #define zig_make_f32(fp, repr) fp##f32 |
| 3751 | 5747 | #else |
| ... | ... | @@ -3768,19 +5764,19 @@ typedef uint32_t zig_f32; |
| 3768 | 5764 | #else |
| 3769 | 5765 | #define zig_init_special_f64(sign, name, arg, repr) zig_make_special_f64(sign, name, arg, repr) |
| 3770 | 5766 | #endif |
| 3771 | #if FLT_MANT_DIG == 53 | |
| 5767 | #if !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && FLT_MANT_DIG == 53 | |
| 3772 | 5768 | typedef float zig_f64; |
| 3773 | 5769 | #define zig_make_f64(fp, repr) fp##f |
| 3774 | #elif DBL_MANT_DIG == 53 | |
| 5770 | #elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && DBL_MANT_DIG == 53 | |
| 3775 | 5771 | typedef double zig_f64; |
| 3776 | 5772 | #define zig_make_f64(fp, repr) fp |
| 3777 | #elif LDBL_MANT_DIG == 53 | |
| 5773 | #elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && LDBL_MANT_DIG == 53 | |
| 3778 | 5774 | typedef long double zig_f64; |
| 3779 | 5775 | #define zig_make_f64(fp, repr) fp##l |
| 3780 | #elif FLT64_MANT_DIG == 53 | |
| 5776 | #elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && FLT64_MANT_DIG == 53 | |
| 3781 | 5777 | typedef _Float64 zig_f64; |
| 3782 | 5778 | #define zig_make_f64(fp, repr) fp##f64 |
| 3783 | #elif FLT32X_MANT_DIG == 53 | |
| 5779 | #elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && FLT32X_MANT_DIG == 53 | |
| 3784 | 5780 | typedef _Float32x zig_f64; |
| 3785 | 5781 | #define zig_make_f64(fp, repr) fp##f32x |
| 3786 | 5782 | #else |
| ... | ... | @@ -3798,7 +5794,14 @@ typedef uint64_t zig_f64; |
| 3798 | 5794 | #define zig_has_f80 1 |
| 3799 | 5795 | #define zig_libc_name_f80(name) __##name##x |
| 3800 | 5796 | #define zig_init_special_f80(sign, name, arg, repr) zig_make_special_f80(sign, name, arg, repr) |
| 3801 | #if FLT_MANT_DIG == 64 | |
| 5797 | #ifdef ZIG_TARGET_SOFT_COMPILER_RT_F80_ABI | |
| 5798 | #undef zig_has_f80 | |
| 5799 | typedef 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 | |
| 3802 | 5805 | typedef float zig_f80; |
| 3803 | 5806 | #define zig_make_f80(fp, repr) fp##f |
| 3804 | 5807 | #elif DBL_MANT_DIG == 64 |
| ... | ... | @@ -3818,68 +5821,91 @@ typedef __float80 zig_f80; |
| 3818 | 5821 | #define zig_make_f80(fp, repr) fp##l |
| 3819 | 5822 | #else |
| 3820 | 5823 | #undef zig_has_f80 |
| 3821 | #define zig_has_f80 0 | |
| 3822 | #define zig_repr_f80 u128 | |
| 3823 | 5824 | typedef 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 | 5832 | #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 | 5836 | #undef zig_make_special_f80 |
| 3826 | 5837 | #define zig_make_special_f80(sign, name, arg, repr) repr |
| 3827 | 5838 | #undef zig_init_special_f80 |
| 3828 | 5839 | #define zig_init_special_f80(sign, name, arg, repr) repr |
| 3829 | 5840 | #endif |
| 3830 | 5841 | |
| 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 | 5842 | #define zig_has_f128 1 |
| 3838 | #define zig_libc_name_f128(name) name##q | |
| 5843 | #define zig_libc_name_f128(name) name##f128 | |
| 3839 | 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 == 113 | |
| 5845 | #ifdef ZIG_TARGET_SOFT_COMPILER_RT_F128_ABI | |
| 5846 | #undef zig_has_f128 | |
| 5847 | #if zig_little_endian | |
| 5848 | typedef struct { uint64_t lo, hi; } zig_f128; | |
| 5849 | #else | |
| 5850 | typedef 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 | |
| 3841 | 5856 | typedef float zig_f128; |
| 3842 | 5857 | #define zig_make_f128(fp, repr) fp##f |
| 3843 | #elif !zig_f128_has_miscompilations && DBL_MANT_DIG == 113 | |
| 5858 | #elif DBL_MANT_DIG == 113 | |
| 3844 | 5859 | typedef double zig_f128; |
| 3845 | 5860 | #define zig_make_f128(fp, repr) fp |
| 3846 | #elif !zig_f128_has_miscompilations && LDBL_MANT_DIG == 113 | |
| 5861 | #elif LDBL_MANT_DIG == 113 | |
| 3847 | 5862 | typedef long double zig_f128; |
| 3848 | 5863 | #define zig_make_f128(fp, repr) fp##l |
| 3849 | #elif !zig_f128_has_miscompilations && FLT128_MANT_DIG == 113 | |
| 5864 | #elif FLT128_MANT_DIG == 113 | |
| 3850 | 5865 | typedef _Float128 zig_f128; |
| 3851 | 5866 | #define zig_make_f128(fp, repr) fp##f128 |
| 3852 | #elif !zig_f128_has_miscompilations && FLT64X_MANT_DIG == 113 | |
| 5867 | #elif FLT64X_MANT_DIG == 113 | |
| 3853 | 5868 | typedef _Float64x zig_f128; |
| 3854 | 5869 | #define zig_make_f128(fp, repr) fp##f64x |
| 3855 | #elif !zig_f128_has_miscompilations && defined(__SIZEOF_FLOAT128__) | |
| 5870 | #elif defined(__SIZEOF_FLOAT128__) | |
| 3856 | 5871 | typedef __float128 zig_f128; |
| 3857 | 5872 | #define zig_make_f128(fp, repr) fp##q |
| 3858 | 5873 | #undef zig_make_special_f128 |
| 3859 | 5874 | #define zig_make_special_f128(sign, name, arg, repr) sign __builtin_##name##f128(arg) |
| 3860 | 5875 | #else |
| 3861 | 5876 | #undef zig_has_f128 |
| 3862 | #define zig_has_f128 0 | |
| 3863 | #undef zig_make_special_f128 | |
| 3864 | #undef zig_init_special_f128 | |
| 3865 | #if defined(zig_darwin) || defined(zig_aarch64) | |
| 3866 | typedef __attribute__((__vector_size__(2 * sizeof(uint64_t)))) uint64_t zig_v2u64; | |
| 3867 | zig_basic_operator(zig_v2u64, xor_v2u64, ^) | |
| 3868 | #define zig_repr_f128 v2u64 | |
| 3869 | typedef zig_v2u64 zig_f128; | |
| 3870 | #define zig_make_f128_zig_make_u128(hi, lo) (zig_f128){ lo, hi } | |
| 3871 | #define zig_make_f128_zig_init_u128 zig_make_f128_zig_make_u128 | |
| 3872 | #define zig_make_f128(fp, repr) zig_make_f128_##repr | |
| 3873 | #define zig_make_special_f128(sign, name, arg, repr) zig_make_f128_##repr | |
| 3874 | #define zig_init_special_f128(sign, name, arg, repr) zig_make_f128_##repr | |
| 3875 | #else | |
| 3876 | #define zig_repr_f128 u128 | |
| 5877 | #if defined(zig_x86_64) && defined(ZIG_TARGET_ABI_MSVC) | |
| 5878 | #if defined(zig_msvc) && !defined(__clang__) | |
| 5879 | #include <emmintrin.h> | |
| 5880 | typedef __m128i zig_f128; | |
| 5881 | #define zig_init_repr_f128(hi, lo) { .m128i_u64 = { lo, hi } } | |
| 5882 | #define zig_lo_repr_f128(arg) (arg).m128i_u64[0] | |
| 5883 | #define zig_hi_repr_f128(arg) (arg).m128i_u64[1] | |
| 5884 | #else | |
| 5885 | typedef __attribute__((__vector_size__(2 * sizeof(uint64_t)))) uint64_t zig_f128; | |
| 5886 | #define zig_init_repr_f128(hi, lo) { lo, hi } | |
| 5887 | #define zig_lo_repr_f128(arg) (arg)[0] | |
| 5888 | #define zig_hi_repr_f128(arg) (arg)[1] | |
| 5889 | #endif | |
| 5890 | #else | |
| 3877 | 5891 | typedef 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 | 5900 | #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 | 5905 | #define zig_make_special_f128(sign, name, arg, repr) repr |
| 5906 | #undef zig_init_special_f128 | |
| 3880 | 5907 | #define zig_init_special_f128(sign, name, arg, repr) repr |
| 3881 | 5908 | #endif |
| 3882 | #endif | |
| 3883 | 5909 | |
| 3884 | 5910 | #if !defined(zig_msvc) && defined(ZIG_TARGET_ABI_MSVC) |
| 3885 | 5911 | /* Emulate msvc abi on a gnu compiler */ |
| ... | ... | @@ -3892,84 +5918,141 @@ typedef zig_f128 zig_c_longdouble; |
| 3892 | 5918 | typedef long double zig_c_longdouble; |
| 3893 | 5919 | #endif |
| 3894 | 5920 | |
| 3895 | #define zig_bitCast_float(Type, ReprType) \ | |
| 3896 | static inline zig_##Type zig_bitCast_##Type(ReprType repr) { \ | |
| 3897 | zig_##Type result; \ | |
| 3898 | memcpy(&result, &repr, sizeof(result)); \ | |
| 3899 | return result; \ | |
| 5921 | #if __AVR__ | |
| 5922 | typedef signed char zig_FloatCompareResult; | |
| 5923 | #elif defined(zig_aarch64) | |
| 5924 | typedef signed int zig_FloatCompareResult; | |
| 5925 | #elif __SIZEOF_LONG__ >= __SIZEOF_POINTER__ | |
| 5926 | typedef signed long zig_FloatCompareResult; | |
| 5927 | #else | |
| 5928 | typedef 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 | } |
| 3901 | zig_bitCast_float(f16, uint16_t) | |
| 3902 | zig_bitCast_float(f32, uint32_t) | |
| 3903 | zig_bitCast_float(f64, uint64_t) | |
| 3904 | zig_bitCast_float(f80, zig_u128) | |
| 3905 | zig_bitCast_float(f128, zig_u128) | |
| 5952 | zig_bitCast_float(16, 16, uint16_t, int16_t) | |
| 5953 | zig_bitCast_float(32, 32, uint32_t, int32_t) | |
| 5954 | zig_bitCast_float(64, 64, uint64_t, int64_t) | |
| 5955 | #if zig_has_f80 | |
| 5956 | zig_bitCast_float(80, 128, zig_u128, zig_i128) | |
| 5957 | #else | |
| 5958 | static 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 | } | |
| 5961 | static 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 | } | |
| 5964 | static 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 | } | |
| 5967 | static 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 | |
| 5971 | static 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 | } | |
| 5974 | static 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 | |
| 5982 | zig_bitCast_float(128, 128, zig_u128, zig_i128) | |
| 5983 | #else | |
| 5984 | static 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 | } | |
| 5987 | static 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 | } | |
| 5990 | static 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 | } | |
| 5993 | static 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 | |
| 3906 | 5997 | |
| 3907 | #define zig_convert_builtin(ExternResType, ResType, operation, ExternArgType, ArgType, version) \ | |
| 3908 | zig_extern ExternResType zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \ | |
| 3909 | zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(ExternArgType); \ | |
| 5998 | #define zig_convert_float_00(ResType, operation, ArgType, version) \ | |
| 5999 | zig_extern ResType zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \ | |
| 6000 | zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(ArgType arg); \ | |
| 6001 | return zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \ | |
| 6002 | zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(arg) | |
| 6003 | #define zig_convert_float_01(ResType, operation, ArgType, version) \ | |
| 6004 | zig_convert_float_00(ResType, operation, ArgType, version) | |
| 6005 | #define zig_convert_float_10(ResType, operation, ArgType, version) \ | |
| 6006 | zig_convert_float_00(ResType, operation, ArgType, version) | |
| 6007 | #define zig_convert_float_11(ResType, operation, ArgType, version) \ | |
| 6008 | return (ResType)arg | |
| 6009 | #define zig_convert_float(res_when, ResType, operation, arg_when, ArgType, version) \ | |
| 3910 | 6010 | static inline ResType zig_expand_concat(zig_expand_concat(zig_##operation, \ |
| 3911 | 6011 | zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType)(ArgType arg) { \ |
| 3912 | ResType res; \ | |
| 3913 | ExternResType extern_res; \ | |
| 3914 | ExternArgType extern_arg; \ | |
| 3915 | memcpy(&extern_arg, &arg, sizeof(extern_arg)); \ | |
| 3916 | extern_res = zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \ | |
| 3917 | zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(extern_arg); \ | |
| 3918 | memcpy(&res, &extern_res, sizeof(res)); \ | |
| 3919 | return extern_res; \ | |
| 3920 | } | |
| 3921 | zig_convert_builtin(zig_compiler_rt_f16, zig_f16, trunc, zig_f32, zig_f32, 2) | |
| 3922 | zig_convert_builtin(zig_compiler_rt_f16, zig_f16, trunc, zig_f64, zig_f64, 2) | |
| 3923 | zig_convert_builtin(zig_f16, zig_f16, trunc, zig_f80, zig_f80, 2) | |
| 3924 | zig_convert_builtin(zig_f16, zig_f16, trunc, zig_f128, zig_f128, 2) | |
| 3925 | zig_convert_builtin(zig_f32, zig_f32, extend, zig_compiler_rt_f16, zig_f16, 2) | |
| 3926 | zig_convert_builtin(zig_f32, zig_f32, trunc, zig_f80, zig_f80, 2) | |
| 3927 | zig_convert_builtin(zig_f32, zig_f32, trunc, zig_f128, zig_f128, 2) | |
| 3928 | zig_convert_builtin(zig_f64, zig_f64, extend, zig_compiler_rt_f16, zig_f16, 2) | |
| 3929 | zig_convert_builtin(zig_f64, zig_f64, trunc, zig_f80, zig_f80, 2) | |
| 3930 | zig_convert_builtin(zig_f64, zig_f64, trunc, zig_f128, zig_f128, 2) | |
| 3931 | zig_convert_builtin(zig_f80, zig_f80, extend, zig_f16, zig_f16, 2) | |
| 3932 | zig_convert_builtin(zig_f80, zig_f80, extend, zig_f32, zig_f32, 2) | |
| 3933 | zig_convert_builtin(zig_f80, zig_f80, extend, zig_f64, zig_f64, 2) | |
| 3934 | zig_convert_builtin(zig_f80, zig_f80, trunc, zig_f128, zig_f128, 2) | |
| 3935 | zig_convert_builtin(zig_f128, zig_f128, extend, zig_f16, zig_f16, 2) | |
| 3936 | zig_convert_builtin(zig_f128, zig_f128, extend, zig_f32, zig_f32, 2) | |
| 3937 | zig_convert_builtin(zig_f128, zig_f128, extend, zig_f64, zig_f64, 2) | |
| 3938 | zig_convert_builtin(zig_f128, zig_f128, extend, zig_f80, zig_f80, 2) | |
| 3939 | ||
| 3940 | #ifdef __ARM_EABI__ | |
| 3941 | ||
| 3942 | zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_d2f(zig_f64); | |
| 3943 | static inline zig_f32 zig_truncdfsf(zig_f64 arg) { return __aeabi_d2f(arg); } | |
| 3944 | ||
| 3945 | zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_f2d(zig_f32); | |
| 3946 | static inline zig_f64 zig_extendsfdf(zig_f32 arg) { return __aeabi_f2d(arg); } | |
| 3947 | ||
| 3948 | #else /* __ARM_EABI__ */ | |
| 3949 | ||
| 3950 | zig_convert_builtin(zig_f32, zig_f32, trunc, zig_f64, zig_f64, 2) | |
| 3951 | zig_convert_builtin(zig_f64, zig_f64, extend, zig_f32, zig_f32, 2) | |
| 3952 | ||
| 3953 | #endif /* __ARM_EABI__ */ | |
| 3954 | ||
| 3955 | #define zig_float_negate_builtin_0(w, c, sb) \ | |
| 3956 | zig_expand_concat(zig_xor_, zig_repr_f##w)(arg, zig_make_f##w(-0x0.0p0, c sb)) | |
| 3957 | #define zig_float_negate_builtin_1(w, c, sb) -arg | |
| 3958 | #define zig_float_negate_builtin(w, c, sb) \ | |
| 6012 | zig_expand_concat(zig_expand_concat(zig_convert_float_, zig_has_##res_when), \ | |
| 6013 | zig_has_##arg_when)(ResType, operation, ArgType, version); \ | |
| 6014 | } | |
| 6015 | ||
| 6016 | #define zig_convert_floats(SmallType, BigType) \ | |
| 6017 | zig_convert_float(SmallType, zig_##SmallType, trunc, BigType, zig_##BigType, 2) \ | |
| 6018 | zig_convert_float(BigType, zig_##BigType, extend, SmallType, zig_##SmallType, 2) | |
| 6019 | zig_convert_floats(f16, f32) | |
| 6020 | zig_convert_floats(f16, f64) | |
| 6021 | zig_convert_floats(f16, f80) | |
| 6022 | zig_convert_floats(f16, f128) | |
| 6023 | zig_convert_floats(f32, f64) | |
| 6024 | zig_convert_floats(f32, f80) | |
| 6025 | zig_convert_floats(f32, f128) | |
| 6026 | zig_convert_floats(f64, f80) | |
| 6027 | zig_convert_floats(f64, f128) | |
| 6028 | zig_convert_floats(f80, f128) | |
| 6029 | ||
| 6030 | #define zig_float_negate_builtin_0(w, sb) \ | |
| 6031 | zig_expand_concat(zig_xor_, zig_repr_f##w)(arg, zig_make_f##w(-0x0.0p0, sb)) | |
| 6032 | #define zig_float_negate_builtin_1(w, sb) -arg | |
| 6033 | #define zig_float_negate_builtin(w, sb) \ | |
| 3959 | 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 | } |
| 3962 | zig_float_negate_builtin(16, , UINT16_C(1) << 15 ) | |
| 3963 | zig_float_negate_builtin(32, , UINT32_C(1) << 31 ) | |
| 3964 | zig_float_negate_builtin(64, , UINT64_C(1) << 63 ) | |
| 3965 | zig_float_negate_builtin(80, zig_make_u128, (UINT64_C(1) << 15, UINT64_C(0))) | |
| 3966 | zig_float_negate_builtin(128, zig_make_u128, (UINT64_C(1) << 63, UINT64_C(0))) | |
| 6037 | zig_float_negate_builtin(16, UINT16_C(1) << 15) | |
| 6038 | zig_float_negate_builtin(32, UINT32_C(1) << 31) | |
| 6039 | zig_float_negate_builtin(64, UINT64_C(1) << 63) | |
| 6040 | ||
| 6041 | #undef zig_float_negate_builtin_0 | |
| 6042 | #define zig_float_negate_builtin_0(w, sb) \ | |
| 6043 | zig_make_repr_f##w(zig_mantissa_repr_f##w(arg), zig_xor_u16(zig_exponent_repr_f##w(arg), sb)) | |
| 6044 | zig_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)) | |
| 6049 | zig_float_negate_builtin(128, UINT64_C(1) << 63) | |
| 3967 | 6050 | |
| 3968 | 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 | 6053 | zig_compiler_rt_abbrev_zig_##Type), 2)(zig_##Type, zig_##Type); \ |
| 3971 | 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 | 6057 | #define zig_float_less_builtin_1(Type, operation) \ |
| 3975 | 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 | 6077 | return lhs operator rhs; \ |
| 3995 | 6078 | } |
| 3996 | 6079 | |
| 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 | 6084 | #define zig_common_float_builtins(w) \ |
| 3998 | zig_convert_builtin( int64_t, int64_t, fix, zig_f##w, zig_f##w, ) \ | |
| 3999 | zig_convert_builtin(zig_i128, zig_i128, fix, zig_f##w, zig_f##w, ) \ | |
| 4000 | zig_convert_builtin(zig_u128, zig_u128, fixuns, zig_f##w, zig_f##w, ) \ | |
| 4001 | zig_convert_builtin(zig_f##w, zig_f##w, float, int64_t, int64_t, ) \ | |
| 4002 | zig_convert_builtin(zig_f##w, zig_f##w, float, zig_i128, zig_i128, ) \ | |
| 4003 | zig_convert_builtin(zig_f##w, zig_f##w, floatun, zig_u128, zig_u128, ) \ | |
| 6085 | zig_convert_float(always, int32_t, fix, f##w, zig_f##w, ) \ | |
| 6086 | zig_convert_float(always, int64_t, fix, f##w, zig_f##w, ) \ | |
| 6087 | zig_convert_float(int128, zig_i128, fix, f##w, zig_f##w, ) \ | |
| 6088 | zig_convert_float(always, uint32_t, fixuns, f##w, zig_f##w, ) \ | |
| 6089 | zig_convert_float(always, uint64_t, fixuns, f##w, zig_f##w, ) \ | |
| 6090 | zig_convert_float(int128, zig_u128, fixuns, f##w, zig_f##w, ) \ | |
| 6091 | zig_convert_float(f##w, zig_f##w, float, always, int32_t, ) \ | |
| 6092 | zig_convert_float(f##w, zig_f##w, float, always, int64_t, ) \ | |
| 6093 | zig_convert_float(f##w, zig_f##w, floatun, always, uint32_t, ) \ | |
| 6094 | zig_convert_float(f##w, zig_f##w, floatun, always, uint64_t, ) \ | |
| 6095 | \ | |
| 6096 | static inline void zig_expand_concat(zig_expand_concat(zig_fix, \ | |
| 6097 | zig_compiler_rt_abbrev_zig_f##w), ei)(void *res, zig_f##w arg, uint16_t bits) { \ | |
| 6098 | zig_extern void zig_expand_concat(zig_expand_concat(__fix, \ | |
| 6099 | zig_compiler_rt_abbrev_zig_f##w), ei)(uint8_t *res, uintptr_t bits, zig_f##w arg); \ | |
| 6100 | zig_expand_concat(zig_expand_concat(__fix, \ | |
| 6101 | zig_compiler_rt_abbrev_zig_f##w), ei)(res, bits, arg); \ | |
| 6102 | } \ | |
| 6103 | \ | |
| 6104 | static inline void zig_expand_concat(zig_expand_concat(zig_fixuns, \ | |
| 6105 | zig_compiler_rt_abbrev_zig_f##w), ei)(void *res, zig_f##w arg, uint16_t bits) { \ | |
| 6106 | zig_extern void zig_expand_concat(zig_expand_concat(__fixuns, \ | |
| 6107 | zig_compiler_rt_abbrev_zig_f##w), ei)(uint8_t *res, uintptr_t bits, zig_f##w arg); \ | |
| 6108 | zig_expand_concat(zig_expand_concat(__fixuns, \ | |
| 6109 | zig_compiler_rt_abbrev_zig_f##w), ei)(res, bits, arg); \ | |
| 6110 | } \ | |
| 6111 | \ | |
| 6112 | static inline zig_f##w zig_expand_concat(zig_floatei, \ | |
| 6113 | zig_compiler_rt_abbrev_zig_f##w)(void *res, uint16_t bits) { \ | |
| 6114 | zig_extern zig_f##w zig_expand_concat(__floatei, \ | |
| 6115 | zig_compiler_rt_abbrev_zig_f##w)(const uint8_t *arg, uintptr_t bits); \ | |
| 6116 | return zig_expand_concat(__floatei, zig_compiler_rt_abbrev_zig_f##w)(res, bits); \ | |
| 6117 | } \ | |
| 6118 | \ | |
| 6119 | static inline zig_f##w zig_expand_concat(zig_floatunei, \ | |
| 6120 | zig_compiler_rt_abbrev_zig_f##w)(void *res, uint16_t bits) { \ | |
| 6121 | zig_extern zig_f##w zig_expand_concat(__floatunei, \ | |
| 6122 | zig_compiler_rt_abbrev_zig_f##w)(const uint8_t *arg, uintptr_t bits); \ | |
| 6123 | return zig_expand_concat(__floatunei, zig_compiler_rt_abbrev_zig_f##w)(res, bits); \ | |
| 6124 | } \ | |
| 6125 | \ | |
| 4004 | 6126 | zig_expand_concat(zig_float_less_builtin_, zig_has_f##w)(f##w, cmp) \ |
| 4005 | 6127 | zig_expand_concat(zig_float_less_builtin_, zig_has_f##w)(f##w, ne) \ |
| 4006 | 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 | 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 | 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 | 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 | 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 | 6165 | return zig_ceil_f##w(zig_div_f##w(lhs, rhs)); \ |
| 4044 | 6166 | } \ |
| 4045 | 6167 | \ |
| 4046 | 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 | } |
| 4049 | zig_common_float_builtins(16) | |
| 4050 | zig_common_float_builtins(32) | |
| 4051 | zig_common_float_builtins(64) | |
| 4052 | zig_common_float_builtins(80) | |
| 4053 | zig_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, ) | |
| 4062 | 6171 | zig_float_builtins(16) |
| 4063 | zig_float_builtins(80) | |
| 4064 | zig_float_builtins(128) | |
| 4065 | ||
| 4066 | #ifdef __ARM_EABI__ | |
| 4067 | ||
| 4068 | zig_extern zig_callconv(pcs("aapcs")) int32_t __aeabi_f2iz(zig_f32); | |
| 4069 | static inline int32_t zig_fixsfsi(zig_f32 arg) { return __aeabi_f2iz(arg); } | |
| 4070 | ||
| 4071 | zig_extern zig_callconv(pcs("aapcs")) uint32_t __aeabi_f2uiz(zig_f32); | |
| 4072 | static inline uint32_t zig_fixunssfsi(zig_f32 arg) { return __aeabi_f2uiz(arg); } | |
| 4073 | ||
| 4074 | zig_extern zig_callconv(pcs("aapcs")) uint64_t __aeabi_f2ulz(zig_f32); | |
| 4075 | static inline uint64_t zig_fixunssfdi(zig_f32 arg) { return __aeabi_f2ulz(arg); } | |
| 4076 | ||
| 4077 | zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_i2f(int32_t); | |
| 4078 | static inline zig_f32 zig_floatsisf(int32_t arg) { return __aeabi_i2f(arg); } | |
| 4079 | ||
| 4080 | zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_ui2f(uint32_t); | |
| 4081 | static inline zig_f32 zig_floatunsisf(uint32_t arg) { return __aeabi_ui2f(arg); } | |
| 4082 | ||
| 4083 | zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_ul2f(uint64_t); | |
| 4084 | static inline zig_f32 zig_floatundisf(uint64_t arg) { return __aeabi_ul2f(arg); } | |
| 4085 | ||
| 4086 | zig_extern zig_callconv(pcs("aapcs")) int32_t __aeabi_d2iz(zig_f64); | |
| 4087 | static inline int32_t zig_fixdfsi(zig_f64 arg) { return __aeabi_d2iz(arg); } | |
| 4088 | ||
| 4089 | zig_extern zig_callconv(pcs("aapcs")) uint32_t __aeabi_d2uiz(zig_f64); | |
| 4090 | static inline uint32_t zig_fixunsdfsi(zig_f64 arg) { return __aeabi_d2uiz(arg); } | |
| 4091 | ||
| 4092 | zig_extern zig_callconv(pcs("aapcs")) uint64_t __aeabi_d2ulz(zig_f64); | |
| 4093 | static inline uint64_t zig_fixunsdfdi(zig_f64 arg) { return __aeabi_d2ulz(arg); } | |
| 4094 | ||
| 4095 | zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_i2d(int32_t); | |
| 4096 | static inline zig_f64 zig_floatsidf(int32_t arg) { return __aeabi_i2d(arg); } | |
| 4097 | ||
| 4098 | zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_ui2d(uint32_t); | |
| 4099 | static inline zig_f64 zig_floatunsidf(uint32_t arg) { return __aeabi_ui2d(arg); } | |
| 4100 | ||
| 4101 | zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_ul2d(uint64_t); | |
| 4102 | static inline zig_f64 zig_floatundidf(uint64_t arg) { return __aeabi_ul2d(arg); } | |
| 4103 | ||
| 4104 | #else /* __ARM_EABI__ */ | |
| 4105 | ||
| 4106 | 6172 | zig_float_builtins(32) |
| 4107 | 6173 | zig_float_builtins(64) |
| 4108 | ||
| 4109 | #endif /* __ARM_EABI__ */ | |
| 6174 | zig_float_builtins(80) | |
| 6175 | #if defined(zig_x86_32) | |
| 6176 | zig_common_float_builtins(128) | |
| 6177 | static 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 | } | |
| 6181 | static 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) | |
| 6186 | zig_common_float_builtins(128) | |
| 6187 | static inline zig_f128 zig_floattitf(zig_i128 arg) { | |
| 6188 | extern zig_f128 __floattitf(zig_i128 arg); | |
| 6189 | return __floattitf(arg); | |
| 6190 | } | |
| 6191 | static 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 | |
| 6196 | zig_float_builtins(128) | |
| 6197 | #endif | |
| 4110 | 6198 | |
| 4111 | 6199 | /* ============================ Atomics Support ============================= */ |
| 4112 | 6200 | |
| ... | ... | @@ -4410,19 +6498,19 @@ typedef int zig_memory_order; |
| 4410 | 6498 | } \ |
| 4411 | 6499 | static inline void zig_msvc_atomic_store_##ZigType(Type volatile* obj, Type value) { \ |
| 4412 | 6500 | (void)_InterlockedExchange##suffix((SigType volatile*)obj, (SigType)value); \ |
| 4413 | } \ | |
| 6501 | } \ | |
| 4414 | 6502 | static inline Type zig_msvc_atomic_load_zig_memory_order_relaxed_##ZigType(Type volatile* obj) { \ |
| 4415 | 6503 | return __iso_volatile_load##iso_suffix((SigType volatile*)obj); \ |
| 4416 | 6504 | } \ |
| 4417 | 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 | 6507 | _ReadWriteBarrier(); \ |
| 4420 | return val; \ | |
| 6508 | return value; \ | |
| 4421 | 6509 | } \ |
| 4422 | 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 | 6512 | _ReadWriteBarrier(); \ |
| 4425 | return val; \ | |
| 6513 | return value; \ | |
| 4426 | 6514 | } |
| 4427 | 6515 | |
| 4428 | 6516 | zig_msvc_atomics( u8, uint8_t, char, 8, 8) |
| ... | ... | @@ -4465,14 +6553,14 @@ zig_msvc_atomics(i64, int64_t, __int64, 64, 64) |
| 4465 | 6553 | zig_##Type result; \ |
| 4466 | 6554 | SigType initial = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \ |
| 4467 | 6555 | _ReadWriteBarrier(); \ |
| 4468 | memcpy(&result, &initial, sizeof(result)); \ | |
| 6556 | memcpy(&result, &initial, sizeof(result)); \ | |
| 4469 | 6557 | return result; \ |
| 4470 | 6558 | } \ |
| 4471 | 6559 | static inline zig_##Type zig_msvc_atomic_load_zig_memory_order_seq_cst_##Type(zig_##Type volatile* obj) { \ |
| 4472 | 6560 | zig_##Type result; \ |
| 4473 | 6561 | SigType initial = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \ |
| 4474 | 6562 | _ReadWriteBarrier(); \ |
| 4475 | memcpy(&result, &initial, sizeof(result)); \ | |
| 6563 | memcpy(&result, &initial, sizeof(result)); \ | |
| 4476 | 6564 | return result; \ |
| 4477 | 6565 | } |
| 4478 | 6566 | |
| ... | ... | @@ -4502,9 +6590,9 @@ static inline void* zig_msvc_atomic_load_zig_memory_order_relaxed_p32(void volat |
| 4502 | 6590 | } |
| 4503 | 6591 | |
| 4504 | 6592 | static 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 | 6594 | _ReadWriteBarrier(); |
| 4507 | return val; | |
| 6595 | return value; | |
| 4508 | 6596 | } |
| 4509 | 6597 | |
| 4510 | 6598 | static inline void* zig_msvc_atomic_load_zig_memory_order_seq_cst_p32(void volatile* obj) { |
| ... | ... | @@ -4532,9 +6620,9 @@ static inline void* zig_msvc_atomic_load_zig_memory_order_relaxed_p64(void volat |
| 4532 | 6620 | } |
| 4533 | 6621 | |
| 4534 | 6622 | static 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 | 6624 | _ReadWriteBarrier(); |
| 4537 | return val; | |
| 6625 | return value; | |
| 4538 | 6626 | } |
| 4539 | 6627 | |
| 4540 | 6628 | static 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 | 1907 | pub fn toSlice(nts: NullTerminatedString, air: Air) [:0]const u8 { |
| 1908 | 1908 | if (nts == .none) return ""; |
| 1909 | 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 | }; |
| 1913 | 1913 |
src/Air/Legalize.zig+8-1| ... | ... | @@ -2906,12 +2906,18 @@ fn packedAggregateInitBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index) Erro |
| 2906 | 2906 | const orig_ty_pl = l.air_instructions.items(.data)[@backingInt(orig_inst)].ty_pl; |
| 2907 | 2907 | const agg_ty = orig_ty_pl.ty.toType(); |
| 2908 | 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 | } | |
| 2909 | 2915 | |
| 2910 | 2916 | var bfa_buf: [4 * 32 + 2]Air.Inst.Index = undefined; |
| 2911 | 2917 | var bfa_state: std.heap.BufferFirstAllocator = .init(@ptrCast(&bfa_buf), gpa); |
| 2912 | 2918 | const bfa = bfa_state.allocator(); |
| 2913 | 2919 | |
| 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 | 2921 | defer bfa.free(inst_buf); |
| 2916 | 2922 | |
| 2917 | 2923 | var main_block: Block = .init(inst_buf); |
| ... | ... | @@ -2927,6 +2933,7 @@ fn packedAggregateInitBlockPayload(l: *Legalize, orig_inst: Air.Inst.Index) Erro |
| 2927 | 2933 | field_idx -= 1; |
| 2928 | 2934 | const field_ty = agg_ty.fieldType(field_idx, zcu); |
| 2929 | 2935 | const field_bits: u16 = @intCast(field_ty.bitSize(zcu)); |
| 2936 | if (field_bits == 0) continue; | |
| 2930 | 2937 | assert(field_bits < num_bits); |
| 2931 | 2938 | const field_uint_ty = try pt.intType(.unsigned, field_bits); |
| 2932 | 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 | 351 | extra: std.ArrayList(u32), |
| 352 | 352 | |
| 353 | 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 | 355 | try a.extra.ensureUnusedCapacity(a.gpa, field_count); |
| 356 | 356 | return addExtraAssumeCapacity(a, extra); |
| 357 | 357 | } |
| ... | ... | @@ -1012,7 +1012,7 @@ fn analyzeInstBlock( |
| 1012 | 1012 | const block_scope = data.block_scopes.get(inst).?; |
| 1013 | 1013 | const num_deaths = data.live_set.count() - block_scope.live_set.count(); |
| 1014 | 1014 | |
| 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 | 1016 | const extra_index = a.addExtraAssumeCapacity(Block{ |
| 1017 | 1017 | .death_count = num_deaths, |
| 1018 | 1018 | }); |
| ... | ... | @@ -1275,7 +1275,7 @@ fn analyzeInstCondBr( |
| 1275 | 1275 | // Write the mirrored deaths to `extra` |
| 1276 | 1276 | const then_death_count = @as(u32, @intCast(then_mirrored_deaths.items.len)); |
| 1277 | 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 | 1279 | const extra_index = a.addExtraAssumeCapacity(CondBr{ |
| 1280 | 1280 | .then_death_count = then_death_count, |
| 1281 | 1281 | .else_death_count = else_death_count, |
src/Builtin.zig+8-2| ... | ... | @@ -7,7 +7,7 @@ is_test: bool, |
| 7 | 7 | single_threaded: bool, |
| 8 | 8 | link_libc: bool, |
| 9 | 9 | link_libcpp: bool, |
| 10 | optimize_mode: std.lang.OptimizeMode, | |
| 10 | optimize_mode: std.lang.Optimize, | |
| 11 | 11 | error_tracing: bool, |
| 12 | 12 | valgrind: bool, |
| 13 | 13 | sanitize_thread: bool, |
| ... | ... | @@ -64,7 +64,9 @@ pub fn append(opts: @This(), buffer: *std.array_list.Managed(u8)) Allocator.Erro |
| 64 | 64 | \\pub const unwind_tables: std.lang.UnwindTables = .{f}; |
| 65 | 65 | \\pub const is_test = {}; |
| 66 | 66 | \\pub const single_threaded = {}; |
| 67 | \\/// Deprecated; to be removed in 0.18.0. Use `target.abi` instead. | |
| 67 | 68 | \\pub const abi: std.Target.Abi = .{f}; |
| 69 | \\/// Deprecated; to be removed in 0.18.0. Use `target.cpu` instead. | |
| 68 | 70 | \\pub const cpu: std.Target.Cpu = .{{ |
| 69 | 71 | \\ .arch = .{f}, |
| 70 | 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 | 97 | try buffer.print( |
| 96 | 98 | \\ }}), |
| 97 | 99 | \\}}; |
| 100 | \\/// Deprecated; to be removed in 0.18.0. Use `target.os` instead. | |
| 98 | 101 | \\pub const os: std.Target.Os = .{{ |
| 99 | 102 | \\ .tag = .{f}, |
| 100 | 103 | \\ .version_range = .{{ |
| ... | ... | @@ -238,8 +241,11 @@ pub fn append(opts: @This(), buffer: *std.array_list.Managed(u8)) Allocator.Erro |
| 238 | 241 | const link_libc = opts.link_libc; |
| 239 | 242 | |
| 240 | 243 | try buffer.print( |
| 244 | \\/// Deprecated; to be removed in 0.18.0. Use `target.ofmt` instead. | |
| 241 | 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 | 249 | \\pub const link_libc = {}; |
| 244 | 250 | \\pub const link_libcpp = {}; |
| 245 | 251 | \\pub const have_error_return_tracing = {}; |
src/Compilation.zig+63-37| ... | ... | @@ -172,7 +172,7 @@ verbose_link: bool, |
| 172 | 172 | link_depfile: ?[]const u8, |
| 173 | 173 | disable_c_depfile: bool, |
| 174 | 174 | stack_report: bool, |
| 175 | debug_compiler_runtime_libs: ?std.lang.OptimizeMode, | |
| 175 | debug_compiler_runtime_libs: ?std.lang.Optimize, | |
| 176 | 176 | debug_compile_errors: bool, |
| 177 | 177 | /// Do not check this field directly. Instead, use the `debugIncremental` wrapper function. |
| 178 | 178 | debug_incremental: bool, |
| ... | ... | @@ -1232,7 +1232,6 @@ pub const cache_helpers = struct { |
| 1232 | 1232 | hh.add(mod.sanitize_thread); |
| 1233 | 1233 | hh.add(mod.fuzz); |
| 1234 | 1234 | hh.add(mod.unwind_tables); |
| 1235 | hh.add(mod.structured_cfg); | |
| 1236 | 1235 | hh.add(mod.no_builtin); |
| 1237 | 1236 | hh.addListOfBytes(mod.cc_argv); |
| 1238 | 1237 | } |
| ... | ... | @@ -1506,7 +1505,7 @@ pub const CreateOptions = struct { |
| 1506 | 1505 | verbose_llvm_bc: ?[]const u8 = null, |
| 1507 | 1506 | link_depfile: ?[]const u8 = null, |
| 1508 | 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 | 1509 | debug_compile_errors: bool = false, |
| 1511 | 1510 | debug_incremental: bool = false, |
| 1512 | 1511 | /// 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 | 2133 | comp.config.any_fuzz = any_fuzz; |
| 2135 | 2134 | |
| 2136 | 2135 | if (opt_zcu) |zcu| { |
| 2136 | // Finish initializing the `zcu` after the fields on `comp` have been initialized. | |
| 2137 | zcu.initAfterCompilation(); | |
| 2138 | ||
| 2137 | 2139 | // Populate `zcu.module_roots`. |
| 2138 | 2140 | const active = zcu.acquire(); |
| 2139 | 2141 | defer active.release(); |
| ... | ... | @@ -2160,7 +2162,7 @@ pub fn create(gpa: Allocator, arena: Allocator, io: Io, diag: *CreateDiagnostic, |
| 2160 | 2162 | .framework_dirs = options.framework_dirs, |
| 2161 | 2163 | .rpath_list = options.rpath_list, |
| 2162 | 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 | 2166 | .allow_shlib_undefined = options.linker_allow_shlib_undefined, |
| 2165 | 2167 | .bind_global_refs_locally = options.linker_bind_global_refs_locally orelse false, |
| 2166 | 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 | 2913 | // The linker progress node is set up here instead of in `performAllTheWork`, because |
| 2912 | 2914 | // we also want it around during `flush`. |
| 2913 | 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 | 2930 | lf.startProgress(comp.link_prog_node); |
| 2916 | 2931 | } |
| 2917 | 2932 | defer if (comp.bin_file) |lf| { |
| ... | ... | @@ -3189,8 +3204,8 @@ fn flush(comp: *Compilation, arena: Allocator) (Io.Cancelable || Allocator.Error |
| 3189 | 3204 | break :p try p.toStringZ(arena); |
| 3190 | 3205 | }, |
| 3191 | 3206 | |
| 3192 | .is_debug = comp.root_mod.optimize_mode == .Debug, | |
| 3193 | .is_small = comp.root_mod.optimize_mode == .ReleaseSmall, | |
| 3207 | .is_debug = comp.root_mod.optimize_mode == .debug, | |
| 3208 | .is_small = comp.root_mod.optimize_mode == .small, | |
| 3194 | 3209 | .time_report = if (comp.time_report) |*p| p else null, |
| 3195 | 3210 | .sanitize_thread = comp.config.any_sanitize_thread, |
| 3196 | 3211 | .fuzz = comp.config.any_fuzz, |
| ... | ... | @@ -3660,11 +3675,11 @@ pub fn saveState(comp: *Compilation) !void { |
| 3660 | 3675 | addBuf(&bufs, @ptrCast(wasm.object_relocations_table.values())); |
| 3661 | 3676 | addBuf(&bufs, @ptrCast(wasm.object_comdat_symbols.items(.kind))); |
| 3662 | 3677 | addBuf(&bufs, @ptrCast(wasm.object_comdat_symbols.items(.index))); |
| 3663 | addBuf(&bufs, @ptrCast(wasm.out_relocs.items(.tag))); | |
| 3664 | addBuf(&bufs, @ptrCast(wasm.out_relocs.items(.offset))); | |
| 3678 | addBuf(&bufs, @ptrCast(wasm.zcu_relocations.items(.tag))); | |
| 3679 | addBuf(&bufs, @ptrCast(wasm.zcu_relocations.items(.offset))); | |
| 3665 | 3680 | // TODO handle the union safety field |
| 3666 | //addBuf(&bufs, @ptrCast(wasm.out_relocs.items(.pointee))); | |
| 3667 | addBuf(&bufs, @ptrCast(wasm.out_relocs.items(.addend))); | |
| 3681 | //addBuf(&bufs, @ptrCast(wasm.zcu_relocations.items(.pointee))); | |
| 3682 | addBuf(&bufs, @ptrCast(wasm.zcu_relocations.items(.addend))); | |
| 3668 | 3683 | addBuf(&bufs, @ptrCast(wasm.uav_fixups.items)); |
| 3669 | 3684 | addBuf(&bufs, @ptrCast(wasm.nav_fixups.items)); |
| 3670 | 3685 | addBuf(&bufs, @ptrCast(wasm.func_table_fixups.items)); |
| ... | ... | @@ -4061,7 +4076,14 @@ pub fn getAllErrorsAlloc(comp: *Compilation) error{OutOfMemory}!ErrorBundle { |
| 4061 | 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 | }; |
| 4067 | 4089 | |
| ... | ... | @@ -4744,7 +4766,7 @@ fn workerDocsWasmFallible(comp: *Compilation, prog_node: std.Progress.Node) SubU |
| 4744 | 4766 | defer arena_allocator.deinit(); |
| 4745 | 4767 | const arena = arena_allocator.allocator(); |
| 4746 | 4768 | |
| 4747 | const optimize_mode = std.lang.OptimizeMode.ReleaseSmall; | |
| 4769 | const optimize_mode: std.lang.Optimize = .small; | |
| 4748 | 4770 | const output_mode = std.lang.OutputMode.Exe; |
| 4749 | 4771 | const resolved_target: Module.ResolvedTarget = .{ |
| 4750 | 4772 | .result = std.zig.system.resolveTargetQuery(io, .{ |
| ... | ... | @@ -5910,8 +5932,8 @@ fn updateWin32Resource(comp: *Compilation, win32_resource: *Win32Resource, win32 |
| 5910 | 5932 | // them being defined matches the behavior of how MSVC calls rc.exe which is the more |
| 5911 | 5933 | // relevant behavior in this case. |
| 5912 | 5934 | switch (rc_src.owner.optimize_mode) { |
| 5913 | .Debug, .ReleaseSafe => {}, | |
| 5914 | .ReleaseFast, .ReleaseSmall => try argv.append("-DNDEBUG"), | |
| 5935 | .debug, .safe => {}, | |
| 5936 | .fast, .small => try argv.append("-DNDEBUG"), | |
| 5915 | 5937 | } |
| 5916 | 5938 | try argv.appendSlice(rc_src.extra_flags); |
| 5917 | 5939 | try argv.appendSlice(&.{ "--", rc_src.src_path, out_res_path }); |
| ... | ... | @@ -6006,26 +6028,30 @@ fn spawnZigRc( |
| 6006 | 6028 | multi_reader.init(gpa, io, multi_reader_buffer.toStreams(), &.{ child.stdout.?, child.stderr.? }); |
| 6007 | 6029 | defer multi_reader.deinit(); |
| 6008 | 6030 | |
| 6009 | const stdout = multi_reader.fileReader(0); | |
| 6010 | const MessageHeader = std.zig.Server.Message.Header; | |
| 6031 | const stdout = multi_reader.reader(0); | |
| 6011 | 6032 | |
| 6012 | 6033 | var eos_err: error{EndOfStream}!void = {}; |
| 6013 | 6034 | |
| 6035 | var client: std.zig.Client = .{ | |
| 6036 | .in = stdout, | |
| 6037 | .out = undefined, | |
| 6038 | }; | |
| 6039 | ||
| 6014 | 6040 | while (true) { |
| 6015 | const header = stdout.interface.takeStruct(MessageHeader, .little) catch |err| switch (err) { | |
| 6016 | error.EndOfStream => break, | |
| 6017 | error.ReadFailed => return stdout.err.?, | |
| 6018 | }; | |
| 6019 | const body = stdout.interface.take(header.bytes_len) catch |err| switch (err) { | |
| 6041 | const header = client.receiveMessageWithMultiReader(&multi_reader, .none) catch |err| switch (err) { | |
| 6042 | error.Timeout => unreachable, | |
| 6020 | 6043 | error.EndOfStream => |e| { |
| 6044 | if (client.in.bufferedLen() == 0) break; | |
| 6021 | 6045 | // Better to report the crash with stderr below, but we set |
| 6022 | 6046 | // this in case the child exits successfully while violating |
| 6023 | 6047 | // this protocol. |
| 6024 | 6048 | eos_err = e; |
| 6025 | 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 | 6055 | switch (header.tag) { |
| 6030 | 6056 | // We expect exactly one ErrorBundle, and if any error_bundle header is |
| 6031 | 6057 | // sent then it's a fatal error. |
| ... | ... | @@ -6178,11 +6204,11 @@ fn addCommonCCArgs( |
| 6178 | 6204 | // LLVM IR files don't support these flags. |
| 6179 | 6205 | if (ext != .ll and ext != .bc) { |
| 6180 | 6206 | switch (mod.optimize_mode) { |
| 6181 | .Debug => {}, | |
| 6182 | .ReleaseSafe => { | |
| 6207 | .debug => {}, | |
| 6208 | .safe => { | |
| 6183 | 6209 | try argv.append("-D_FORTIFY_SOURCE=2"); |
| 6184 | 6210 | }, |
| 6185 | .ReleaseFast, .ReleaseSmall => { | |
| 6211 | .fast, .small => { | |
| 6186 | 6212 | try argv.append("-DNDEBUG"); |
| 6187 | 6213 | }, |
| 6188 | 6214 | } |
| ... | ... | @@ -6333,7 +6359,7 @@ fn addCommonCCArgs( |
| 6333 | 6359 | } |
| 6334 | 6360 | } |
| 6335 | 6361 | |
| 6336 | if (mod.optimize_mode != .Debug) { | |
| 6362 | if (mod.optimize_mode != .debug) { | |
| 6337 | 6363 | try argv.append("-Werror=date-time"); |
| 6338 | 6364 | } |
| 6339 | 6365 | }, |
| ... | ... | @@ -6412,18 +6438,18 @@ fn addCommonCCArgs( |
| 6412 | 6438 | } |
| 6413 | 6439 | |
| 6414 | 6440 | switch (mod.optimize_mode) { |
| 6415 | .Debug => { | |
| 6441 | .debug => { | |
| 6416 | 6442 | // Clang has -Og for compatibility with GCC, but currently it is just equivalent |
| 6417 | 6443 | // to -O1. Besides potentially impairing debugging, -O1/-Og significantly |
| 6418 | 6444 | // increases compile times. |
| 6419 | 6445 | try argv.append("-O0"); |
| 6420 | 6446 | }, |
| 6421 | .ReleaseSafe => { | |
| 6447 | .safe => { | |
| 6422 | 6448 | // See the comment in the BuildModeFastRelease case for why we pass -O2 rather |
| 6423 | 6449 | // than -O3 here. |
| 6424 | 6450 | try argv.append("-O2"); |
| 6425 | 6451 | }, |
| 6426 | .ReleaseFast => { | |
| 6452 | .fast => { | |
| 6427 | 6453 | // Here we pass -O2 rather than -O3 because, although we do the equivalent of |
| 6428 | 6454 | // -O3 in Zig code, the justification for the difference here is that Zig |
| 6429 | 6455 | // has better detection and prevention of undefined behavior, so -O3 is safer for |
| ... | ... | @@ -6431,7 +6457,7 @@ fn addCommonCCArgs( |
| 6431 | 6457 | // running in -O2 and thus the -O3 path has been tested less. |
| 6432 | 6458 | try argv.append("-O2"); |
| 6433 | 6459 | }, |
| 6434 | .ReleaseSmall => { | |
| 6460 | .small => { | |
| 6435 | 6461 | try argv.append("-Os"); |
| 6436 | 6462 | }, |
| 6437 | 6463 | } |
| ... | ... | @@ -6641,6 +6667,8 @@ pub fn addCCArgs( |
| 6641 | 6667 | |
| 6642 | 6668 | // Only compiled files support these flags. |
| 6643 | 6669 | switch (ext) { |
| 6670 | .assembly, | |
| 6671 | .assembly_with_cpp, | |
| 6644 | 6672 | .c, |
| 6645 | 6673 | .h, |
| 6646 | 6674 | .cpp, |
| ... | ... | @@ -7254,7 +7282,6 @@ fn buildOutputFromZig( |
| 7254 | 7282 | .unwind_tables = comp.root_mod.unwind_tables, |
| 7255 | 7283 | .pic = comp.root_mod.pic, |
| 7256 | 7284 | .optimize_mode = optimize_mode, |
| 7257 | .structured_cfg = comp.root_mod.structured_cfg, | |
| 7258 | 7285 | .no_builtin = true, |
| 7259 | 7286 | .code_model = comp.root_mod.code_model, |
| 7260 | 7287 | .error_tracing = false, |
| ... | ... | @@ -7403,7 +7430,6 @@ pub fn build_crt_file( |
| 7403 | 7430 | // Some CRT objects (e.g. musl's rcrt1.o and Scrt1.o) are opinionated about PIC. |
| 7404 | 7431 | .pic = options.pic orelse comp.root_mod.pic, |
| 7405 | 7432 | .optimize_mode = comp.compilerRtOptMode(), |
| 7406 | .structured_cfg = comp.root_mod.structured_cfg, | |
| 7407 | 7433 | // Some libcs (e.g. musl) are opinionated about -fno-builtin. |
| 7408 | 7434 | .no_builtin = options.no_builtin orelse comp.root_mod.no_builtin, |
| 7409 | 7435 | .code_model = comp.root_mod.code_model, |
| ... | ... | @@ -7557,15 +7583,15 @@ pub fn addLinkLib(comp: *Compilation, lib_name: []const u8) !void { |
| 7557 | 7583 | |
| 7558 | 7584 | /// This decides the optimization mode for all zig-provided libraries, including |
| 7559 | 7585 | /// compiler-rt, libcxx, libc, libunwind, etc. |
| 7560 | pub fn compilerRtOptMode(comp: Compilation) std.lang.OptimizeMode { | |
| 7586 | pub fn compilerRtOptMode(comp: Compilation) std.lang.Optimize { | |
| 7561 | 7587 | if (comp.debug_compiler_runtime_libs) |mode| { |
| 7562 | 7588 | return mode; |
| 7563 | 7589 | } |
| 7564 | 7590 | const target = &comp.root_mod.resolved_target.result; |
| 7565 | 7591 | switch (comp.root_mod.optimize_mode) { |
| 7566 | .Debug, .ReleaseSafe => return target_util.defaultCompilerRtOptimizeMode(target), | |
| 7567 | .ReleaseFast => return .ReleaseFast, | |
| 7568 | .ReleaseSmall => return .ReleaseSmall, | |
| 7592 | .debug, .safe => return target_util.defaultCompilerRtOptimizeMode(target), | |
| 7593 | .fast => return .fast, | |
| 7594 | .small => return .small, | |
| 7569 | 7595 | } |
| 7570 | 7596 | } |
| 7571 | 7597 |
src/Compilation/Config.zig+7-7| ... | ... | @@ -59,7 +59,7 @@ export_memory: bool, |
| 59 | 59 | shared_memory: bool, |
| 60 | 60 | is_test: bool, |
| 61 | 61 | debug_format: DebugFormat, |
| 62 | root_optimize_mode: std.lang.OptimizeMode, | |
| 62 | root_optimize_mode: std.lang.Optimize, | |
| 63 | 63 | root_strip: bool, |
| 64 | 64 | root_error_tracing: bool, |
| 65 | 65 | dll_export_fns: bool, |
| ... | ... | @@ -80,7 +80,7 @@ pub const Options = struct { |
| 80 | 80 | is_test: bool, |
| 81 | 81 | have_zcu: bool, |
| 82 | 82 | emit_bin: bool, |
| 83 | root_optimize_mode: ?std.lang.OptimizeMode = null, | |
| 83 | root_optimize_mode: ?std.lang.Optimize = null, | |
| 84 | 84 | root_strip: ?bool = null, |
| 85 | 85 | root_error_tracing: ?bool = null, |
| 86 | 86 | link_mode: ?std.lang.LinkMode = null, |
| ... | ... | @@ -196,7 +196,7 @@ pub fn resolve(options: Options) ResolveError!Config { |
| 196 | 196 | break :b options.use_lib_llvm orelse true; |
| 197 | 197 | }; |
| 198 | 198 | |
| 199 | const root_optimize_mode = options.root_optimize_mode orelse .Debug; | |
| 199 | const root_optimize_mode = options.root_optimize_mode orelse .debug; | |
| 200 | 200 | |
| 201 | 201 | // Make a decision on whether to use Clang or Aro for translate-c and compiling C files. |
| 202 | 202 | const c_frontend: CFrontend = b: { |
| ... | ... | @@ -357,7 +357,7 @@ pub fn resolve(options: Options) ResolveError!Config { |
| 357 | 357 | if (!use_lib_llvm and options.emit_bin) break :b false; |
| 358 | 358 | |
| 359 | 359 | // Prefer LLVM for release builds. |
| 360 | if (root_optimize_mode != .Debug) break :b true; | |
| 360 | if (root_optimize_mode != .debug) break :b true; | |
| 361 | 361 | |
| 362 | 362 | // load_dynamic_library standalone test not passing on this combination |
| 363 | 363 | // https://github.com/ziglang/zig/issues/24080 |
| ... | ... | @@ -486,7 +486,7 @@ pub fn resolve(options: Options) ResolveError!Config { |
| 486 | 486 | |
| 487 | 487 | const root_strip = b: { |
| 488 | 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 | 490 | if (!target_util.hasDebugInfo(target)) break :b true; |
| 491 | 491 | break :b false; |
| 492 | 492 | }; |
| ... | ... | @@ -512,8 +512,8 @@ pub fn resolve(options: Options) ResolveError!Config { |
| 512 | 512 | if (root_strip) break :b false; |
| 513 | 513 | if (!backend_supports_error_tracing) break :b false; |
| 514 | 514 | break :b switch (root_optimize_mode) { |
| 515 | .Debug => true, | |
| 516 | .ReleaseSafe, .ReleaseFast, .ReleaseSmall => false, | |
| 515 | .debug => true, | |
| 516 | .safe, .fast, .small => false, | |
| 517 | 517 | }; |
| 518 | 518 | }; |
| 519 | 519 |
src/IncrementalDebugServer.zig+24-11| ... | ... | @@ -130,7 +130,7 @@ fn serveStream( |
| 130 | 130 | try stream_writer.writeAll("zig> "); |
| 131 | 131 | const untrimmed = try stream_reader.takeSentinel('\n'); |
| 132 | 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 | 134 | .{ cmd_and_arg[0..i], cmd_and_arg[i + 1 ..] } |
| 135 | 135 | else |
| 136 | 136 | .{ cmd_and_arg, "" }; |
| ... | ... | @@ -244,7 +244,7 @@ fn handleCommand(zcu: *Zcu, w: *Io.Writer, cmd_str: []const u8, arg_str: []const |
| 244 | 244 | const ty: Type = .fromInterned(type_ip_index); |
| 245 | 245 | const ty_name = ty.containerTypeName(ip).toSlice(ip); |
| 246 | 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 | 248 | 0b01 => std.mem.endsWith(u8, ty_name, query), |
| 249 | 249 | 0b10 => std.mem.startsWith(u8, ty_name, query), |
| 250 | 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 | 265 | const nav = ip.getNav(nav_index); |
| 266 | 266 | const nav_fqn = nav.fqn.toSlice(ip); |
| 267 | 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 | 269 | 0b01 => std.mem.endsWith(u8, nav_fqn, query), |
| 270 | 270 | 0b10 => std.mem.startsWith(u8, nav_fqn, query), |
| 271 | 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 | 286 | const referencer = (ref orelse break :ref "<analysis root>").referencer; |
| 287 | 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 | 289 | try w.print( |
| 295 | 290 | \\last update generation: {d} |
| 296 | 291 | \\current referencer: {s} |
| 297 | \\has error: {s} | |
| 298 | 292 | \\ |
| 299 | 293 | , .{ |
| 300 | 294 | unit_info.last_update_gen, |
| 301 | 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 | 317 | } else if (std.mem.eql(u8, cmd_str, "unit_dependencies")) { |
| 305 | 318 | const unit = parseAnalUnit(arg_str) orelse return w.writeAll("malformed anal unit"); |
| 306 | 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 | 378 | return std.fmt.parseInt(u32, str, 10) catch null; |
| 366 | 379 | } |
| 367 | 380 | fn 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 | 382 | const kind = str[0..split_idx]; |
| 370 | 383 | const idx_str = str[split_idx + 1 ..]; |
| 371 | 384 | if (std.mem.eql(u8, kind, "comptime")) { |
src/InternPool.zig+30-30| ... | ... | @@ -1737,7 +1737,7 @@ pub const String = enum(u32) { |
| 1737 | 1737 | } |
| 1738 | 1738 | |
| 1739 | 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 | 1741 | assert(string.at(len, ip) == 0); |
| 1742 | 1742 | return @fromBackingInt(@intCast(@backingInt(string))); |
| 1743 | 1743 | } |
| ... | ... | @@ -1864,7 +1864,7 @@ pub const NullTerminatedString = enum(u32) { |
| 1864 | 1864 | pub fn toUnsigned(string: NullTerminatedString, ip: *const InternPool) ?u32 { |
| 1865 | 1865 | const slice = string.toSlice(ip); |
| 1866 | 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 | 1868 | return std.fmt.parseUnsigned(u32, slice, 10) catch null; |
| 1869 | 1869 | } |
| 1870 | 1870 | |
| ... | ... | @@ -4193,7 +4193,7 @@ pub const Index = enum(u32) { |
| 4193 | 4193 | }; |
| 4194 | 4194 | } |
| 4195 | 4195 | |
| 4196 | /// This function is used in the debugger pretty formatters in tools/ to fetch the | |
| 4196 | /// This function is used in the debugger pretty formatters in lib/lldb/ to fetch the | |
| 4197 | 4197 | /// Tag to encoding mapping to facilitate fancy debug printing for this type. |
| 4198 | 4198 | fn dbHelper(self: *Index, tag_to_encoding_map: *struct { |
| 4199 | 4199 | const DataIsIndex = struct { data: Index }; |
| ... | ... | @@ -4219,26 +4219,17 @@ pub const Index = enum(u32) { |
| 4219 | 4219 | type_inferred_error_set: DataIsIndex, |
| 4220 | 4220 | simple_type: void, |
| 4221 | 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 | 4222 | const @"data.params_len" = opaque {}; |
| 4226 | 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 | 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 | 4227 | type_tuple: struct { |
| 4234 | 4228 | const @"data.fields_len" = opaque {}; |
| 4235 | 4229 | data: *TypeTuple, |
| 4236 | 4230 | @"trailing.types.len": *@"data.fields_len", |
| 4237 | 4231 | @"trailing.values.len": *@"data.fields_len", |
| 4238 | trailing: struct { | |
| 4239 | types: []Index, | |
| 4240 | values: []Index, | |
| 4241 | }, | |
| 4232 | trailing: struct { types: []Index, values: []Index }, | |
| 4242 | 4233 | }, |
| 4243 | 4234 | |
| 4244 | 4235 | type_struct: struct { data: *Tag.TypeStruct }, |
| ... | ... | @@ -4350,7 +4341,7 @@ pub const Index = enum(u32) { |
| 4350 | 4341 | const encoding = @field(Tag.encodings, tag_name); |
| 4351 | 4342 | if (@hasField(@TypeOf(encoding), "trailing")) { |
| 4352 | 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 | 4345 | struct { |
| 4355 | 4346 | fn checkConfig(name: []const u8) void { |
| 4356 | 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 | 4350 | } |
| 4360 | 4351 | fn checkField(name: []const u8, Type: type) void { |
| 4361 | 4352 | switch (@typeInfo(Type)) { |
| 4362 | .int => {}, | |
| 4363 | .@"enum" => {}, | |
| 4364 | .@"struct" => |info| assert(info.layout == .@"packed"), | |
| 4353 | .int, .@"enum" => return, | |
| 4354 | .@"struct" => |info| switch (info.layout) { | |
| 4355 | .auto => unreachable, | |
| 4356 | .@"extern" => { | |
| 4357 | for (info.field_names, info.field_types) |field_name, field_type| checkField(name ++ "." ++ field_name, field_type); | |
| 4358 | return; | |
| 4359 | }, | |
| 4360 | .@"packed" => return, | |
| 4361 | }, | |
| 4365 | 4362 | .optional => |info| { |
| 4366 | 4363 | checkConfig(name ++ ".?"); |
| 4367 | 4364 | checkField(name ++ ".?", info.child); |
| 4365 | return; | |
| 4368 | 4366 | }, |
| 4369 | .pointer => |info| { | |
| 4370 | assert(info.size == .slice); | |
| 4367 | .pointer => |info| if (info.size == .slice) { | |
| 4371 | 4368 | checkConfig(name ++ ".len"); |
| 4372 | 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 | 5185 | .trailing = struct { |
| 5187 | 5186 | param_comptime_bits: ?[]u32, |
| 5188 | 5187 | param_noalias_bits: ?[]u32, |
| 5189 | param_cc_bits: ?[]u32, | |
| 5190 | param_type: []Index, | |
| 5188 | spirv_kernel_options: ?extern struct { x: u32, y: u32, z: u32 }, | |
| 5189 | spirv_mesh_options: ?extern struct { max_primitives: u32, max_vertices: u32 }, | |
| 5190 | param_types: []Index, | |
| 5191 | 5191 | }, |
| 5192 | 5192 | .config = .{ |
| 5193 | 5193 | .@"trailing.param_comptime_bits.?" = .@"payload.flags.has_comptime_bits", |
| 5194 | 5194 | .@"trailing.param_comptime_bits.?.len" = .@"(payload.params_len + 31) / 32", |
| 5195 | 5195 | .@"trailing.param_noalias_bits.?" = .@"payload.flags.has_noalias_bits", |
| 5196 | 5196 | .@"trailing.param_noalias_bits.?.len" = .@"(payload.params_len + 31) / 32", |
| 5197 | .@"trailing.param_cc_bits.?" = .@"payload.flags.cc.extraLen() != 0", | |
| 5198 | .@"trailing.param_cc_bits.?.len" = .@"payload.flags.cc.extraLen()", | |
| 5199 | .@"trailing.param_type.len" = .@"payload.params_len", | |
| 5197 | .@"trailing.spirv_kernel_options.?" = .@"payload.flags.cc.tag == .spirv_kernel or payload.flags.cc.tag == .spirv_task", | |
| 5198 | .@"trailing.spirv_mesh_options.?" = .@"payload.flags.cc.tag == .spirv_mesh", | |
| 5199 | .@"trailing.param_types.len" = .@"payload.params_len", | |
| 5200 | 5200 | }, |
| 5201 | 5201 | }, |
| 5202 | 5202 | |
| ... | ... | @@ -5225,7 +5225,7 @@ pub const Tag = enum(u8) { |
| 5225 | 5225 | .@"trailing.field_defaults.?" = .@"payload.flags.any_field_defaults", |
| 5226 | 5226 | .@"trailing.field_defaults.?.len" = .@"payload.fields_len", |
| 5227 | 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 | 5229 | .@"trailing.field_is_comptime_bits.?" = .@"payload.flags.any_comptime_fields", |
| 5230 | 5230 | .@"trailing.field_is_comptime_bits.?.len" = .@"(payload.fields_len + 31) / 32", |
| 5231 | 5231 | .@"trailing.field_runtime_order.?" = .@"payload.flags.layout == .auto", |
| ... | ... | @@ -5254,7 +5254,7 @@ pub const Tag = enum(u8) { |
| 5254 | 5254 | .@"trailing.captures.?.len" = .@"trailing.captures_len.?", |
| 5255 | 5255 | .@"trailing.field_types.len" = .@"payload.fields_len", |
| 5256 | 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 | 5260 | .type_union_packed_auto = union_packed_encoding, |
| ... | ... | @@ -11428,7 +11428,7 @@ pub fn getOrPutTrailingString( |
| 11428 | 11428 | .tid = tid, |
| 11429 | 11429 | .index = strings.mutate.len - 1, |
| 11430 | 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 | 11432 | switch (embedded_nulls) { |
| 11433 | 11433 | .no_embedded_nulls => assert(!has_embedded_null), |
| 11434 | 11434 | .maybe_embedded_nulls => if (has_embedded_null) { |
src/Module.zig+9-26| ... | ... | @@ -26,7 +26,7 @@ fully_qualified_name: []const u8, |
| 26 | 26 | deps: Deps = .{}, |
| 27 | 27 | |
| 28 | 28 | resolved_target: ResolvedTarget, |
| 29 | optimize_mode: std.lang.OptimizeMode, | |
| 29 | optimize_mode: std.lang.Optimize, | |
| 30 | 30 | code_model: std.lang.CodeModel, |
| 31 | 31 | single_threaded: bool, |
| 32 | 32 | error_tracing: bool, |
| ... | ... | @@ -42,8 +42,6 @@ sanitize_thread: bool, |
| 42 | 42 | fuzz: bool, |
| 43 | 43 | unwind_tables: std.lang.UnwindTables, |
| 44 | 44 | cc_argv: []const []const u8, |
| 45 | /// (SPIR-V) whether to generate a structured control flow graph or not | |
| 46 | structured_cfg: bool, | |
| 47 | 45 | no_builtin: bool, |
| 48 | 46 | |
| 49 | 47 | pub const Deps = std.array_hash_map.String(*Module); |
| ... | ... | @@ -67,7 +65,7 @@ pub const CreateOptions = struct { |
| 67 | 65 | pub const Inherited = struct { |
| 68 | 66 | /// If this is null then `parent` must be non-null. |
| 69 | 67 | resolved_target: ?ResolvedTarget = null, |
| 70 | optimize_mode: ?std.lang.OptimizeMode = null, | |
| 68 | optimize_mode: ?std.lang.Optimize = null, | |
| 71 | 69 | code_model: ?std.lang.CodeModel = null, |
| 72 | 70 | single_threaded: ?bool = null, |
| 73 | 71 | error_tracing: ?bool = null, |
| ... | ... | @@ -85,7 +83,6 @@ pub const CreateOptions = struct { |
| 85 | 83 | sanitize_c: ?std.zig.SanitizeC = null, |
| 86 | 84 | sanitize_thread: ?bool = null, |
| 87 | 85 | fuzz: ?bool = null, |
| 88 | structured_cfg: ?bool = null, | |
| 89 | 86 | no_builtin: ?bool = null, |
| 90 | 87 | }; |
| 91 | 88 | }; |
| ... | ... | @@ -144,7 +141,7 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Module { |
| 144 | 141 | if (options.inherited.valgrind) |x| break :b x; |
| 145 | 142 | if (options.parent) |p| break :b p.valgrind; |
| 146 | 143 | if (strip) break :b false; |
| 147 | break :b optimize_mode == .Debug; | |
| 144 | break :b optimize_mode == .debug; | |
| 148 | 145 | }; |
| 149 | 146 | |
| 150 | 147 | const single_threaded = b: { |
| ... | ... | @@ -212,7 +209,7 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Module { |
| 212 | 209 | const omit_frame_pointer = b: { |
| 213 | 210 | if (options.inherited.omit_frame_pointer) |x| break :b x; |
| 214 | 211 | if (options.parent) |p| break :b p.omit_frame_pointer; |
| 215 | if (optimize_mode == .ReleaseSmall) { | |
| 212 | if (optimize_mode == .small) { | |
| 216 | 213 | // On x86, in most cases, keeping the frame pointer usually results in smaller binary size. |
| 217 | 214 | // This has to do with how instructions for memory access via the stack base pointer register (when keeping the frame pointer) |
| 218 | 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 | 248 | }; |
| 252 | 249 | |
| 253 | 250 | const is_safe_mode = switch (optimize_mode) { |
| 254 | .Debug, .ReleaseSafe => true, | |
| 255 | .ReleaseFast, .ReleaseSmall => false, | |
| 251 | .debug, .safe => true, | |
| 252 | .fast, .small => false, | |
| 256 | 253 | }; |
| 257 | 254 | |
| 258 | 255 | const sanitize_c: std.zig.SanitizeC = b: { |
| 259 | 256 | if (options.inherited.sanitize_c) |x| break :b x; |
| 260 | 257 | if (options.parent) |p| break :b p.sanitize_c; |
| 261 | 258 | break :b switch (optimize_mode) { |
| 262 | .Debug => .full, | |
| 259 | .debug => .full, | |
| 263 | 260 | // It's recommended to use the minimal runtime in production |
| 264 | 261 | // environments due to the security implications of the full runtime. |
| 265 | 262 | // The minimal runtime doesn't provide much benefit over simply |
| 266 | 263 | // trapping, however, so we do that instead. |
| 267 | .ReleaseSafe => .trap, | |
| 268 | .ReleaseFast, .ReleaseSmall => .off, | |
| 264 | .safe => .trap, | |
| 265 | .fast, .small => .off, | |
| 269 | 266 | }; |
| 270 | 267 | }; |
| 271 | 268 | |
| ... | ... | @@ -320,17 +317,6 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Module { |
| 320 | 317 | break :sp target_util.default_stack_protector_buffer_size; |
| 321 | 318 | }; |
| 322 | 319 | |
| 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 | 320 | const no_builtin = b: { |
| 335 | 321 | if (options.inherited.no_builtin) |x| break :b x; |
| 336 | 322 | if (options.parent) |p| break :b p.no_builtin; |
| ... | ... | @@ -411,7 +397,6 @@ pub fn create(arena: Allocator, options: CreateOptions) !*Module { |
| 411 | 397 | .fuzz = fuzz, |
| 412 | 398 | .unwind_tables = unwind_tables, |
| 413 | 399 | .cc_argv = options.cc_argv, |
| 414 | .structured_cfg = structured_cfg, | |
| 415 | 400 | .no_builtin = no_builtin, |
| 416 | 401 | }; |
| 417 | 402 | return mod; |
| ... | ... | @@ -450,7 +435,6 @@ pub fn createLimited(gpa: Allocator, options: LimitedOptions) Allocator.Error!*M |
| 450 | 435 | .fuzz = undefined, |
| 451 | 436 | .unwind_tables = undefined, |
| 452 | 437 | .cc_argv = undefined, |
| 453 | .structured_cfg = undefined, | |
| 454 | 438 | .no_builtin = undefined, |
| 455 | 439 | }; |
| 456 | 440 | return mod; |
| ... | ... | @@ -489,7 +473,6 @@ pub fn createBuiltin(arena: Allocator, opts: Builtin, dirs: std.zig.Directories) |
| 489 | 473 | .stack_protector = 0, |
| 490 | 474 | .red_zone = false, |
| 491 | 475 | .sanitize_c = .off, |
| 492 | .structured_cfg = false, | |
| 493 | 476 | .no_builtin = false, |
| 494 | 477 | }; |
| 495 | 478 | return new; |
src/RangeSet.zig+18-23| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | const RangeSet = @This(); |
| 2 | 2 | |
| 3 | ranges: std.MultiArrayList(Range), | |
| 3 | list: std.MultiArrayList(Range), | |
| 4 | 4 | |
| 5 | 5 | pub const Range = struct { |
| 6 | 6 | first: Value, |
| ... | ... | @@ -8,41 +8,36 @@ pub const Range = struct { |
| 8 | 8 | src: LazySrcLoc, |
| 9 | 9 | }; |
| 10 | 10 | |
| 11 | pub const empty: RangeSet = .{ .ranges = .empty }; | |
| 11 | pub const empty: RangeSet = .{ .list = .empty }; | |
| 12 | 12 | |
| 13 | 13 | pub fn deinit(self: *RangeSet, allocator: Allocator) void { |
| 14 | self.ranges.deinit(allocator); | |
| 14 | self.list.deinit(allocator); | |
| 15 | 15 | self.* = undefined; |
| 16 | 16 | } |
| 17 | 17 | |
| 18 | pub fn ensureUnusedCapacity(self: *RangeSet, allocator: Allocator, additional_count: usize) Allocator.Error!void { | |
| 19 | return self.ranges.ensureUnusedCapacity(allocator, additional_count); | |
| 18 | pub fn ensureUnusedCapacity(set: *RangeSet, allocator: Allocator, additional_count: usize) Allocator.Error!void { | |
| 19 | return set.list.ensureUnusedCapacity(allocator, additional_count); | |
| 20 | 20 | } |
| 21 | 21 | |
| 22 | pub fn addAssumeCapacity(set: *RangeSet, new: Range, ty: Type, zcu: *Zcu) ?LazySrcLoc { | |
| 22 | pub fn addAssumeCapacity(set: *RangeSet, new: Range, ty: Type, zcu: *Zcu) ?Range { | |
| 23 | 23 | assert(new.first.typeOf(zcu).eql(ty)); |
| 24 | 24 | assert(new.last.typeOf(zcu).eql(ty)); |
| 25 | 25 | assert(new.first.compareScalar(.lte, new.last, ty, zcu)); |
| 26 | 26 | |
| 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 | 28 | .val = new.first, |
| 29 | 29 | .zcu = zcu, |
| 30 | 30 | }), compare); |
| 31 | 31 | |
| 32 | if (idx != set.ranges.len and // `new.first` is *not* greater than all `old.last` | |
| 33 | new.last.compareScalar(.gte, set.ranges.items(.first)[idx], ty, zcu)) | |
| 32 | if (idx != set.list.len and // `new.first` is *not* greater than all `old.last` | |
| 33 | new.last.compareScalar(.gte, set.list.items(.first)[idx], ty, zcu)) | |
| 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 | 38 | return null; |
| 39 | 39 | } |
| 40 | 40 | |
| 41 | pub 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 | ||
| 46 | 41 | pub fn spans( |
| 47 | 42 | set: *RangeSet, |
| 48 | 43 | allocator: Allocator, |
| ... | ... | @@ -53,13 +48,13 @@ pub fn spans( |
| 53 | 48 | ) Allocator.Error!bool { |
| 54 | 49 | assert(first.typeOf(zcu).eql(ty)); |
| 55 | 50 | assert(last.typeOf(zcu).eql(ty)); |
| 56 | if (set.ranges.len == 0) return false; | |
| 51 | if (set.list.len == 0) return false; | |
| 57 | 52 | |
| 58 | assert(std.sort.isSorted(Value, set.ranges.items(.first), @as(SortCtx, .{ .ty = ty, .zcu = zcu }), lessThan)); | |
| 59 | assert(std.sort.isSorted(Value, set.ranges.items(.last), @as(SortCtx, .{ .ty = ty, .zcu = zcu }), lessThan)); | |
| 53 | assert(std.sort.isSorted(Value, set.list.items(.first), @as(SortCtx, .{ .ty = ty, .zcu = zcu }), lessThan)); | |
| 54 | assert(std.sort.isSorted(Value, set.list.items(.last), @as(SortCtx, .{ .ty = ty, .zcu = zcu }), lessThan)); | |
| 60 | 55 | |
| 61 | if (!set.ranges.items(.first)[0].eql(first, ty, zcu) or | |
| 62 | !set.ranges.items(.last)[set.ranges.len - 1].eql(last, ty, zcu)) | |
| 56 | if (!set.list.items(.first)[0].eql(first, ty, zcu) or | |
| 57 | !set.list.items(.last)[set.list.len - 1].eql(last, ty, zcu)) | |
| 63 | 58 | { |
| 64 | 59 | return false; |
| 65 | 60 | } |
| ... | ... | @@ -75,8 +70,8 @@ pub fn spans( |
| 75 | 70 | |
| 76 | 71 | // look for gaps |
| 77 | 72 | for ( |
| 78 | set.ranges.items(.first)[1..], | |
| 79 | set.ranges.items(.last)[0 .. set.ranges.len - 1], | |
| 73 | set.list.items(.first)[1..], | |
| 74 | set.list.items(.last)[0 .. set.list.len - 1], | |
| 80 | 75 | ) |cur_first, prev_last| { |
| 81 | 76 | // prev_last + 1 == cur_first |
| 82 | 77 | counter.copy(prev_last.toBigInt(&space, zcu)); |
src/Sema.zig+551-262| ... | ... | @@ -532,20 +532,20 @@ pub const Block = struct { |
| 532 | 532 | |
| 533 | 533 | fn wantSafeTypes(block: *const Block) bool { |
| 534 | 534 | return block.want_safety orelse switch (block.ownerModule().optimize_mode) { |
| 535 | .Debug => true, | |
| 536 | .ReleaseSafe => true, | |
| 537 | .ReleaseFast => false, | |
| 538 | .ReleaseSmall => false, | |
| 535 | .debug => true, | |
| 536 | .safe => true, | |
| 537 | .fast => false, | |
| 538 | .small => false, | |
| 539 | 539 | }; |
| 540 | 540 | } |
| 541 | 541 | |
| 542 | 542 | fn wantSafety(block: *const Block) bool { |
| 543 | 543 | if (block.isComptime()) return false; // runtime safety checks are pointless in comptime blocks |
| 544 | 544 | return block.want_safety orelse switch (block.ownerModule().optimize_mode) { |
| 545 | .Debug => true, | |
| 546 | .ReleaseSafe => true, | |
| 547 | .ReleaseFast => false, | |
| 548 | .ReleaseSmall => false, | |
| 545 | .debug => true, | |
| 546 | .safe => true, | |
| 547 | .fast => false, | |
| 548 | .small => false, | |
| 549 | 549 | }; |
| 550 | 550 | } |
| 551 | 551 | |
| ... | ... | @@ -1472,7 +1472,7 @@ fn analyzeBodyInner( |
| 1472 | 1472 | i += 1; |
| 1473 | 1473 | continue; |
| 1474 | 1474 | }, |
| 1475 | .astgen_error => return error.AnalysisFail, | |
| 1475 | .astgen_error => return sema.failTransitive(.astgen_error), | |
| 1476 | 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 | 2247 | .inferred_alloc_comptime => unreachable, // assertion failure |
| 2248 | 2248 | else => {}, |
| 2249 | 2249 | } |
| 2250 | // LLVM fails to eliminate this `classify` call in ReleaseFast, which hurts performance, so | |
| 2250 | // LLVM fails to eliminate this `classify` call in -Ofast, which hurts performance, so | |
| 2251 | 2251 | // we must explicitly check for `std.debug.runtime_safety`. |
| 2252 | 2252 | if (std.debug.runtime_safety) switch (sema.typeOf(inst).classify(zcu)) { |
| 2253 | 2253 | .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 | 2352 | }); |
| 2353 | 2353 | } |
| 2354 | 2354 | |
| 2355 | pub 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 | ||
| 2355 | 2359 | pub fn failWithDivideByZero(sema: *Sema, block: *Block, src: LazySrcLoc) CompileError { |
| 2356 | 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 | 2701 | }); |
| 2698 | 2702 | } |
| 2699 | 2703 | |
| 2700 | pub fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Zcu.ErrorMsg) error{ AnalysisFail, OutOfMemory } { | |
| 2704 | pub fn failWithOwnedErrorMsg(sema: *Sema, block: ?*Block, err_msg: *Zcu.ErrorMsg) SemaError { | |
| 2701 | 2705 | @branchHint(.cold); |
| 2702 | 2706 | const zcu = sema.pt.zcu; |
| 2703 | 2707 | const comp = zcu.comp; |
| 2704 | 2708 | const gpa = comp.gpa; |
| 2705 | 2709 | const io = comp.io; |
| 2706 | 2710 | |
| 2711 | assert(sema.err == null); | |
| 2712 | ||
| 2707 | 2713 | if (build_options.enable_debug_extensions and comp.debug_compile_errors) { |
| 2708 | 2714 | var wip_errors: std.zig.ErrorBundle.Wip = undefined; |
| 2709 | 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 | 2735 | |
| 2730 | 2736 | err_msg.reference_trace_root = sema.owner.toOptional(); |
| 2731 | 2737 | |
| 2732 | const gop = try zcu.failed_analysis.getOrPut(gpa, sema.owner); | |
| 2733 | if (gop.found_existing) { | |
| 2734 | // If there are multiple errors for the same Decl, prefer the first one added. | |
| 2735 | sema.err = null; | |
| 2736 | err_msg.destroy(gpa); | |
| 2737 | } else { | |
| 2738 | sema.err = err_msg; | |
| 2739 | gop.value_ptr.* = err_msg; | |
| 2740 | } | |
| 2738 | try zcu.failed_analysis.putNoClobber(gpa, sema.owner, err_msg); | |
| 2739 | assert(!zcu.transitive_failed_analysis.contains(sema.owner)); | |
| 2741 | 2740 | |
| 2742 | return error.AnalysisFail; | |
| 2741 | sema.err = err_msg; | |
| 2742 | return error.AlreadyReported; | |
| 2743 | 2743 | } |
| 2744 | 2744 | |
| 2745 | 2745 | /// 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 | 3117 | try sema.validateDeref(block, src, operand, operand_ty); |
| 3118 | 3118 | |
| 3119 | 3119 | const ptr_info = operand_ty.ptrInfo(zcu); |
| 3120 | return switch (ptr_info.flags.size) { | |
| 3121 | .many, .slice => unreachable, // cannot be dereferenced | |
| 3122 | .c => single_ptr: { | |
| 3120 | return single_ptr: switch (ptr_info.flags.size) { | |
| 3121 | .many => unreachable, // cannot be dereferenced directly | |
| 3122 | .slice => { | |
| 3123 | const slice_val = sema.resolveValue(operand).?; | |
| 3124 | const slice = zcu.intern_pool.indexToKey(slice_val.toIntern()).slice; | |
| 3125 | break :single_ptr .fromValue(try pt.sliceToArrayPtr(slice)); | |
| 3126 | }, | |
| 3127 | .c => { | |
| 3123 | 3128 | const single_ptr_ty = try pt.ptrType(p: { |
| 3124 | 3129 | var p = ptr_info; |
| 3125 | 3130 | p.flags.size = .one; |
| ... | ... | @@ -3153,18 +3158,26 @@ fn validateDeref( |
| 3153 | 3158 | ) CompileError!void { |
| 3154 | 3159 | const pt = sema.pt; |
| 3155 | 3160 | const zcu = pt.zcu; |
| 3161 | const ip = &zcu.intern_pool; | |
| 3156 | 3162 | if (ty.zigTypeTag(zcu) != .pointer) { |
| 3157 | 3163 | return sema.fail(block, src, "cannot dereference non-pointer type '{f}'", .{ty.fmt(pt)}); |
| 3158 | } else switch (ty.ptrSize(zcu)) { | |
| 3159 | .one, .c => {}, | |
| 3164 | } | |
| 3165 | const size = ty.ptrSize(zcu); | |
| 3166 | switch (size) { | |
| 3160 | 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 | 3170 | if (sema.resolveValue(ref)) |val| { |
| 3164 | 3171 | // Error for deref of undef pointer, unless the pointee is OPV in which case it's legal. |
| 3165 | 3172 | if (val.isUndef(zcu) and ty.childType(zcu).classify(zcu) != .one_possible_value) { |
| 3166 | 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 | } |
| 3170 | 3183 | |
| ... | ... | @@ -3186,10 +3199,12 @@ fn ensureResultUsed( |
| 3186 | 3199 | const zcu = pt.zcu; |
| 3187 | 3200 | switch (ty.zigTypeTag(zcu)) { |
| 3188 | 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 | 3205 | .error_union => { |
| 3191 | 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 | 3208 | errdefer msg.destroy(sema.gpa); |
| 3194 | 3209 | try sema.errNote(src, msg, "consider using 'try', 'catch', or 'if'", .{}); |
| 3195 | 3210 | break :msg msg; |
| ... | ... | @@ -4745,11 +4760,14 @@ fn failWithBadMemberAccess( |
| 4745 | 4760 | .@"enum" => "enum", |
| 4746 | 4761 | else => unreachable, |
| 4747 | 4762 | }; |
| 4748 | if (agg_ty.typeDeclInst(zcu)) |inst| if ((inst.resolve(ip) orelse return error.AnalysisFail) == .main_struct_inst) { | |
| 4749 | return sema.fail(block, field_src, "root source file struct '{f}' has no member named '{f}'", .{ | |
| 4750 | agg_ty.fmt(pt), field_name.fmt(ip), | |
| 4751 | }); | |
| 4752 | }; | |
| 4763 | if (agg_ty.typeDeclInst(zcu)) |inst| { | |
| 4764 | const inst_index = inst.resolve(ip) orelse return sema.failTransitive(.{ .lost_tracking = inst }); | |
| 4765 | if (inst_index == .main_struct_inst) { | |
| 4766 | return sema.fail(block, field_src, "root source file struct '{f}' has no member named '{f}'", .{ | |
| 4767 | agg_ty.fmt(pt), field_name.fmt(ip), | |
| 4768 | }); | |
| 4769 | } | |
| 4770 | } | |
| 4753 | 4771 | |
| 4754 | 4772 | return sema.fail(block, field_src, "{s} '{f}' has no member named '{f}'", .{ |
| 4755 | 4773 | kw_name, agg_ty.fmt(pt), field_name.fmt(ip), |
| ... | ... | @@ -5997,7 +6015,14 @@ fn lookupInNamespace( |
| 5997 | 6015 | const pt = sema.pt; |
| 5998 | 6016 | const zcu = pt.zcu; |
| 5999 | 6017 | |
| 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 | }; | |
| 6001 | 6026 | |
| 6002 | 6027 | const namespace = zcu.namespacePtr(namespace_index); |
| 6003 | 6028 | |
| ... | ... | @@ -6062,7 +6087,7 @@ pub fn analyzeSaveErrRetIndex(sema: *Sema, block: *Block) SemaError!Air.Inst.Ref |
| 6062 | 6087 | const stack_trace_ty = try sema.getStdLangType(block.nodeOffset(.zero), .StackTrace); |
| 6063 | 6088 | const field_name = try zcu.intern_pool.getOrPutString(gpa, io, pt.tid, "index", .no_embedded_nulls); |
| 6064 | 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 | 6091 | error.ComptimeReturn, error.ComptimeBreak => unreachable, |
| 6067 | 6092 | error.OutOfMemory, error.Canceled => |e| return e, |
| 6068 | 6093 | }; |
| ... | ... | @@ -6724,7 +6749,9 @@ fn analyzeCall( |
| 6724 | 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 | 6750 | const info = ip.indexToKey(f.toIntern()).func; |
| 6726 | 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 | 6755 | const file = zcu.fileByIndex(resolved_func_inst.file); |
| 6729 | 6756 | const zir_info = file.zir.?.getFnInfo(resolved_func_inst.inst); |
| 6730 | 6757 | break :b .{ nav, file.zir.?, info.zir_body_inst, resolved_func_inst.inst, zir_info }; |
| ... | ... | @@ -8355,7 +8382,10 @@ fn zirFunc( |
| 8355 | 8382 | const cc: std.lang.CallingConvention = if (has_body) cc: { |
| 8356 | 8383 | const func_decl_nav = sema.owner.unwrap().nav_val; |
| 8357 | 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 | 8389 | const zir_decl = sema.code.getDeclaration(decl_inst); |
| 8360 | 8390 | break :exported zir_decl.linkage == .@"export"; |
| 8361 | 8391 | }; |
| ... | ... | @@ -8501,6 +8531,7 @@ const calling_conventions_supporting_var_args = [_]std.lang.CallingConvention.Ta |
| 8501 | 8531 | .x86_64_win, |
| 8502 | 8532 | .x86_sysv, |
| 8503 | 8533 | .x86_win, |
| 8534 | .x86_mingw, | |
| 8504 | 8535 | .aarch64_aapcs, |
| 8505 | 8536 | .aarch64_aapcs_darwin, |
| 8506 | 8537 | .aarch64_aapcs_win, |
| ... | ... | @@ -10760,7 +10791,7 @@ fn finishSwitchBr( |
| 10760 | 10791 | .@"enum" => if (else_is_named_only or |
| 10761 | 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 | 10795 | break :check_enumerable .{ undefined, undefined }; |
| 10765 | 10796 | }, |
| 10766 | 10797 | .error_set => if (!operand_ty.isAnyError(zcu)) { |
| ... | ... | @@ -10881,13 +10912,13 @@ fn finishSwitchBr( |
| 10881 | 10912 | try branch_hints.append(gpa, prong_hint); |
| 10882 | 10913 | |
| 10883 | 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 | 10916 | case_block.instructions.items.len); |
| 10886 | 10917 | const extra_case = cases_extra.addManyAsArrayAssumeCapacity( |
| 10887 | 10918 | @typeInfo(Air.SwitchBr.Case).@"struct".field_names.len, |
| 10888 | 10919 | ); |
| 10889 | 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 | 10922 | if (seen_field != null) continue; |
| 10892 | 10923 | const item_val = try pt.enumValueFieldIndex(item_ty, @intCast(field_i)); |
| 10893 | 10924 | const item_ref: Air.Inst.Ref = .fromValue(item_val); |
| ... | ... | @@ -10920,7 +10951,7 @@ fn finishSwitchBr( |
| 10920 | 10951 | } |
| 10921 | 10952 | if (tagged_union_originally) { |
| 10922 | 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 | 10955 | if (seen_field != null) continue; |
| 10925 | 10956 | const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_i]); |
| 10926 | 10957 | if (!field_ty.isNoReturn(zcu)) break :analyze_body true; |
| ... | ... | @@ -11004,17 +11035,21 @@ fn finishSwitchBr( |
| 11004 | 11035 | } |
| 11005 | 11036 | |
| 11006 | 11037 | const ValidatedSwitchBlock = struct { |
| 11007 | seen_enum_fields: []const ?LazySrcLoc, | |
| 11008 | seen_errors: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, LazySrcLoc), | |
| 11009 | seen_ranges: std.MultiArrayList(RangeSet.Range).Slice, | |
| 11010 | true_src: ?LazySrcLoc, | |
| 11011 | false_src: ?LazySrcLoc, | |
| 11012 | void_src: ?LazySrcLoc, | |
| 11013 | ||
| 11038 | seen: Seen, | |
| 11014 | 11039 | case_vals: []const Air.Inst.Ref, |
| 11015 | 11040 | else_case: Zir.UnwrappedSwitchBlock.Case.Else, |
| 11016 | 11041 | else_err_ty: ?Type, |
| 11017 | 11042 | |
| 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 | 11053 | fn iterateUnhandledItems( |
| 11019 | 11054 | validated_switch: *const ValidatedSwitchBlock, |
| 11020 | 11055 | /// May be `undefined` if `item_ty` isn't an `error_set`. |
| ... | ... | @@ -11023,28 +11058,26 @@ const ValidatedSwitchBlock = struct { |
| 11023 | 11058 | min_int: Value, |
| 11024 | 11059 | ) UnhandledIterator { |
| 11025 | 11060 | return .{ |
| 11061 | .error_names = error_names, | |
| 11062 | .seen = &validated_switch.seen, | |
| 11063 | ||
| 11026 | 11064 | .next_idx = 0, |
| 11027 | 11065 | .next_val = min_int, |
| 11028 | .error_names = error_names, | |
| 11029 | .seen_enum_fields = validated_switch.seen_enum_fields, | |
| 11030 | .seen_errors = &validated_switch.seen_errors, | |
| 11031 | .seen_ranges = validated_switch.seen_ranges, | |
| 11032 | .seen_true = validated_switch.true_src != null, | |
| 11033 | .seen_false = validated_switch.false_src != null, | |
| 11034 | .seen_void = validated_switch.void_src != null, | |
| 11066 | .handled_true = validated_switch.seen.true_src != null, | |
| 11067 | .handled_false = validated_switch.seen.false_src != null, | |
| 11068 | .handled_void = validated_switch.seen.void_src != null, | |
| 11035 | 11069 | }; |
| 11036 | 11070 | } |
| 11037 | 11071 | |
| 11038 | 11072 | const UnhandledIterator = struct { |
| 11073 | error_names: InternPool.NullTerminatedString.Slice, | |
| 11074 | seen: *const Seen, | |
| 11075 | ||
| 11039 | 11076 | next_idx: u32, |
| 11040 | 11077 | next_val: ?Value, |
| 11041 | error_names: InternPool.NullTerminatedString.Slice, | |
| 11042 | seen_enum_fields: []const ?LazySrcLoc, | |
| 11043 | seen_errors: *const std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, LazySrcLoc), | |
| 11044 | seen_ranges: std.MultiArrayList(RangeSet.Range).Slice, | |
| 11045 | seen_true: bool, | |
| 11046 | seen_false: bool, | |
| 11047 | seen_void: bool, | |
| 11078 | handled_true: bool, | |
| 11079 | handled_false: bool, | |
| 11080 | handled_void: bool, | |
| 11048 | 11081 | |
| 11049 | 11082 | fn next(it: *UnhandledIterator, sema: *Sema, item_ty: Type) CompileError!?Value { |
| 11050 | 11083 | const pt = sema.pt; |
| ... | ... | @@ -11052,7 +11085,7 @@ const ValidatedSwitchBlock = struct { |
| 11052 | 11085 | const ip = &zcu.intern_pool; |
| 11053 | 11086 | switch (item_ty.zigTypeTag(zcu)) { |
| 11054 | 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 | 11089 | if (seen_field != null) continue; |
| 11057 | 11090 | it.next_idx = @intCast(field_i + 1); |
| 11058 | 11091 | return try pt.enumValueFieldIndex(item_ty, @intCast(field_i)); |
| ... | ... | @@ -11061,7 +11094,7 @@ const ValidatedSwitchBlock = struct { |
| 11061 | 11094 | }, |
| 11062 | 11095 | .error_set => { |
| 11063 | 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 | 11098 | it.next_idx = @intCast(name_i + 1); |
| 11066 | 11099 | return .fromInterned(try pt.intern(.{ .err = .{ |
| 11067 | 11100 | .ty = item_ty.toIntern(), |
| ... | ... | @@ -11077,14 +11110,14 @@ const ValidatedSwitchBlock = struct { |
| 11077 | 11110 | .@"union", .@"struct" => item_ty.backingIntType(zcu), |
| 11078 | 11111 | else => unreachable, |
| 11079 | 11112 | }; |
| 11080 | while (it.next_idx < it.seen_ranges.len and | |
| 11081 | cur_val.eql(it.seen_ranges.items(.first)[it.next_idx], int_ty, zcu)) | |
| 11113 | while (it.next_idx < it.seen.ranges.list.len and | |
| 11114 | cur_val.eql(it.seen.ranges.list.items(.first)[it.next_idx], int_ty, zcu)) | |
| 11082 | 11115 | { |
| 11083 | 11116 | defer it.next_idx += 1; |
| 11084 | 11117 | const incr = try arith.incrementDefinedInt( |
| 11085 | 11118 | sema, |
| 11086 | 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 | 11122 | if (incr.overflow) { |
| 11090 | 11123 | it.next_val = null; |
| ... | ... | @@ -11101,19 +11134,19 @@ const ValidatedSwitchBlock = struct { |
| 11101 | 11134 | }; |
| 11102 | 11135 | }, |
| 11103 | 11136 | .bool => { |
| 11104 | if (!it.seen_true) { | |
| 11105 | it.seen_true = true; | |
| 11137 | if (!it.handled_true) { | |
| 11138 | it.handled_true = true; | |
| 11106 | 11139 | return .true; |
| 11107 | 11140 | } |
| 11108 | if (!it.seen_false) { | |
| 11109 | it.seen_false = true; | |
| 11141 | if (!it.handled_false) { | |
| 11142 | it.handled_false = true; | |
| 11110 | 11143 | return .false; |
| 11111 | 11144 | } |
| 11112 | 11145 | return null; |
| 11113 | 11146 | }, |
| 11114 | 11147 | .void => { |
| 11115 | if (!it.seen_void) { | |
| 11116 | it.seen_void = true; | |
| 11148 | if (!it.handled_void) { | |
| 11149 | it.handled_void = true; | |
| 11117 | 11150 | return .void; |
| 11118 | 11151 | } |
| 11119 | 11152 | return null; |
| ... | ... | @@ -11186,14 +11219,8 @@ fn validateSwitchBlock( |
| 11186 | 11219 | operand_ty.assertHasLayout(zcu); |
| 11187 | 11220 | const union_obj = ip.loadUnionType(operand_ty.toIntern()); |
| 11188 | 11221 | switch (union_obj.tag_usage) { |
| 11189 | .tagged => { | |
| 11190 | break :item_ty .fromInterned(union_obj.enum_tag_type); | |
| 11191 | }, | |
| 11192 | .none => { | |
| 11193 | if (union_obj.layout == .@"packed") { | |
| 11194 | break :item_ty operand_ty; | |
| 11195 | } | |
| 11196 | }, | |
| 11222 | .tagged => break :item_ty .fromInterned(union_obj.enum_tag_type), | |
| 11223 | .none => if (union_obj.layout == .@"packed") break :item_ty operand_ty, | |
| 11197 | 11224 | .safety => {}, |
| 11198 | 11225 | } |
| 11199 | 11226 | return sema.failWithOwnedErrorMsg(block, msg: { |
| ... | ... | @@ -11208,27 +11235,47 @@ fn validateSwitchBlock( |
| 11208 | 11235 | |
| 11209 | 11236 | .@"struct" => { |
| 11210 | 11237 | operand_ty.assertHasLayout(zcu); |
| 11211 | const layout = operand_ty.containerLayout(zcu); | |
| 11212 | if (layout == .@"packed") { | |
| 11213 | break :item_ty operand_ty; | |
| 11214 | } | |
| 11238 | if (operand_ty.containerLayout(zcu) == .@"packed") break :item_ty operand_ty; | |
| 11215 | 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 | 11241 | errdefer msg.destroy(sema.gpa); |
| 11218 | if (operand_ty.srcLocOrNull(zcu)) |struct_src| { | |
| 11219 | try sema.errNote(struct_src, msg, "consider 'packed struct' here", .{}); | |
| 11220 | } | |
| 11242 | try sema.addDeclaredHereNote(msg, operand_ty); | |
| 11221 | 11243 | break :msg msg; |
| 11222 | 11244 | }); |
| 11223 | 11245 | }, |
| 11224 | 11246 | |
| 11225 | .pointer => { | |
| 11226 | if (!operand_ty.isSlice(zcu)) { | |
| 11227 | break :item_ty operand_ty; | |
| 11228 | } | |
| 11229 | }, | |
| 11247 | .pointer => if (!operand_ty.isSlice(zcu)) break :item_ty operand_ty, | |
| 11230 | 11248 | |
| 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 | 11280 | return sema.fail(block, operand_src, "switch on type '{f}'", .{operand_ty.fmt(pt)}); |
| 11234 | 11281 | }; |
| ... | ... | @@ -11253,13 +11300,15 @@ fn validateSwitchBlock( |
| 11253 | 11300 | var case_vals: std.ArrayList(Air.Inst.Ref) = try .initCapacity(arena, zir_switch.item_infos.len); |
| 11254 | 11301 | |
| 11255 | 11302 | // Duplicate checking variables later also used for `inline else`. |
| 11256 | var seen_enum_fields: []?LazySrcLoc = &.{}; | |
| 11257 | var seen_errors: std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, LazySrcLoc) = .empty; | |
| 11258 | var seen_sparse_values: std.AutoHashMapUnmanaged(InternPool.Index, LazySrcLoc) = .empty; | |
| 11259 | var range_set: RangeSet = .empty; | |
| 11260 | var true_src: ?LazySrcLoc = null; | |
| 11261 | var false_src: ?LazySrcLoc = null; | |
| 11262 | var void_src: ?LazySrcLoc = null; | |
| 11303 | var seen: ValidatedSwitchBlock.Seen = .{ | |
| 11304 | .enum_fields = &.{}, | |
| 11305 | .errors = .empty, | |
| 11306 | .sparse_values = .empty, | |
| 11307 | .ranges = .empty, | |
| 11308 | .true_src = null, | |
| 11309 | .false_src = null, | |
| 11310 | .void_src = null, | |
| 11311 | }; | |
| 11263 | 11312 | |
| 11264 | 11313 | var else_err_ty: ?Type = null; |
| 11265 | 11314 | |
| ... | ... | @@ -11267,20 +11316,20 @@ fn validateSwitchBlock( |
| 11267 | 11316 | |
| 11268 | 11317 | switch (item_ty.zigTypeTag(zcu)) { |
| 11269 | 11318 | .@"enum" => { |
| 11270 | seen_enum_fields = try arena.alloc(?LazySrcLoc, item_ty.enumFieldCount(zcu)); | |
| 11271 | @memset(seen_enum_fields, null); | |
| 11272 | // `range_set` is used for non-exhaustive enum values that do not | |
| 11319 | seen.enum_fields = try arena.alloc(?LazySrcLoc, item_ty.enumFieldCount(zcu)); | |
| 11320 | @memset(seen.enum_fields, null); | |
| 11321 | // `seen.ranges` is used for non-exhaustive enum values that do not | |
| 11273 | 11322 | // correspond to any tags. Since this is rare, we only allocate on |
| 11274 | 11323 | // demand in `validateSwitchItem`. |
| 11275 | 11324 | }, |
| 11276 | 11325 | .error_set => { |
| 11277 | try seen_errors.ensureUnusedCapacity(arena, zir_switch.totalItemsLen()); | |
| 11326 | try seen.errors.ensureUnusedCapacity(arena, zir_switch.totalItemsLen()); | |
| 11278 | 11327 | }, |
| 11279 | 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 | 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 | 11334 | .bool, .void => {}, |
| 11286 | 11335 | |
| ... | ... | @@ -11323,7 +11372,7 @@ fn validateSwitchBlock( |
| 11323 | 11372 | case_vals.appendAssumeCapacity(.none); |
| 11324 | 11373 | } else { |
| 11325 | 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 | 11376 | case_vals.appendAssumeCapacity(item.ref); |
| 11328 | 11377 | } |
| 11329 | 11378 | } |
| ... | ... | @@ -11338,7 +11387,7 @@ fn validateSwitchBlock( |
| 11338 | 11387 | const last_src = block.src(.{ .switch_case_item_range_last = range_offset }); |
| 11339 | 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 | 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 | 11391 | case_vals.appendSliceAssumeCapacity(&.{ first_item.ref, last_item.ref }); |
| 11343 | 11392 | } |
| 11344 | 11393 | } |
| ... | ... | @@ -11369,13 +11418,13 @@ fn validateSwitchBlock( |
| 11369 | 11418 | // Validate for missing special prongs. |
| 11370 | 11419 | switch (item_ty.zigTypeTag(zcu)) { |
| 11371 | 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 | 11422 | if (seen_src == null) break false; |
| 11374 | 11423 | } else true; |
| 11375 | 11424 | |
| 11376 | 11425 | if (has_else) { |
| 11377 | 11426 | if (all_tags_handled) { |
| 11378 | if (item_ty.isNonexhaustiveEnum(zcu)) { | |
| 11427 | if (operand_ty.isNonexhaustiveEnum(zcu)) { | |
| 11379 | 11428 | if (has_under) return sema.fail( |
| 11380 | 11429 | block, |
| 11381 | 11430 | else_prong_src, |
| ... | ... | @@ -11397,7 +11446,7 @@ fn validateSwitchBlock( |
| 11397 | 11446 | .{}, |
| 11398 | 11447 | ); |
| 11399 | 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 | 11450 | if (seen_src != null) continue; |
| 11402 | 11451 | |
| 11403 | 11452 | const field_name = item_ty.enumFieldName(i, zcu); |
| ... | ... | @@ -11449,7 +11498,7 @@ fn validateSwitchBlock( |
| 11449 | 11498 | |
| 11450 | 11499 | var seen_errors_from_set: u32 = 0; |
| 11451 | 11500 | for (error_names.get(ip)) |error_name| { |
| 11452 | if (seen_errors.contains(error_name)) { | |
| 11501 | if (seen.errors.contains(error_name)) { | |
| 11453 | 11502 | seen_errors_from_set += 1; |
| 11454 | 11503 | } else if (!has_else) { |
| 11455 | 11504 | const msg = maybe_msg orelse blk: { |
| ... | ... | @@ -11491,7 +11540,7 @@ fn validateSwitchBlock( |
| 11491 | 11540 | var names: InferredErrorSet.NameMap = .{}; |
| 11492 | 11541 | try names.ensureUnusedCapacity(sema.arena, error_names.len); |
| 11493 | 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 | 11544 | names.putAssumeCapacityNoClobber(error_name, {}); |
| 11496 | 11545 | } |
| 11497 | 11546 | // No need to keep the hash map metadata correct; here we |
| ... | ... | @@ -11509,7 +11558,7 @@ fn validateSwitchBlock( |
| 11509 | 11558 | }; |
| 11510 | 11559 | const min_int = try int_ty.minInt(pt, int_ty); |
| 11511 | 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 | 11562 | if (has_else) { |
| 11514 | 11563 | return sema.fail( |
| 11515 | 11564 | block, |
| ... | ... | @@ -11542,8 +11591,8 @@ fn validateSwitchBlock( |
| 11542 | 11591 | }, |
| 11543 | 11592 | .bool, .void => |type_tag| { |
| 11544 | 11593 | const all_values_handled = switch (type_tag) { |
| 11545 | .bool => true_src != null and false_src != null, | |
| 11546 | .void => void_src != null, | |
| 11594 | .bool => seen.true_src != null and seen.false_src != null, | |
| 11595 | .void => seen.void_src != null, | |
| 11547 | 11596 | else => unreachable, |
| 11548 | 11597 | }; |
| 11549 | 11598 | if (has_else) { |
| ... | ... | @@ -11570,13 +11619,7 @@ fn validateSwitchBlock( |
| 11570 | 11619 | } |
| 11571 | 11620 | |
| 11572 | 11621 | return .{ |
| 11573 | .seen_enum_fields = seen_enum_fields, | |
| 11574 | .seen_errors = seen_errors, | |
| 11575 | .seen_ranges = range_set.ranges.slice(), | |
| 11576 | .true_src = true_src, | |
| 11577 | .false_src = false_src, | |
| 11578 | .void_src = void_src, | |
| 11579 | ||
| 11622 | .seen = seen, | |
| 11580 | 11623 | .case_vals = case_vals.items, |
| 11581 | 11624 | .else_case = else_case, |
| 11582 | 11625 | .else_err_ty = else_err_ty, |
| ... | ... | @@ -11754,7 +11797,7 @@ fn resolveSwitchBlock( |
| 11754 | 11797 | .{ else_case.index, else_case.body, else_case.capture, else_case.has_tag_capture, else_case.is_inline }; |
| 11755 | 11798 | if (err_set) try sema.maybeErrorUnwrapComptime(child_block, body, cond_ref); |
| 11756 | 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 | 11801 | if (maybe_seen != null) continue; |
| 11759 | 11802 | if (!operand_ty.unionFieldTypeByIndex(field_i, zcu).isNoReturn(zcu)) break; |
| 11760 | 11803 | } else { |
| ... | ... | @@ -12276,10 +12319,11 @@ fn analyzeSwitchPayloadCaptureTaggedUnion( |
| 12276 | 12319 | dummy_captures, |
| 12277 | 12320 | .{ .override = item_srcs }, |
| 12278 | 12321 | ) catch |err| switch (err) { |
| 12279 | error.AnalysisFail => { | |
| 12280 | const msg = sema.err orelse return error.AnalysisFail; | |
| 12281 | try sema.reparentOwnedErrorMsg(capture_src, msg, "capture group with incompatible types", .{}); | |
| 12282 | return error.AnalysisFail; | |
| 12322 | error.AlreadyReported => |e| { | |
| 12323 | if (sema.err) |msg| { | |
| 12324 | try sema.reparentOwnedErrorMsg(capture_src, msg, "capture group with incompatible types", .{}); | |
| 12325 | } | |
| 12326 | return e; | |
| 12283 | 12327 | }, |
| 12284 | 12328 | else => |e| return e, |
| 12285 | 12329 | }; |
| ... | ... | @@ -12315,11 +12359,12 @@ fn analyzeSwitchPayloadCaptureTaggedUnion( |
| 12315 | 12359 | dummy_captures, |
| 12316 | 12360 | .{ .override = item_srcs }, |
| 12317 | 12361 | ) catch |err| switch (err) { |
| 12318 | error.AnalysisFail => { | |
| 12319 | const msg = sema.err orelse return error.AnalysisFail; | |
| 12320 | try sema.errNote(capture_src, msg, "this coercion is only possible when capturing by value", .{}); | |
| 12321 | try sema.reparentOwnedErrorMsg(capture_src, msg, "capture group with incompatible types", .{}); | |
| 12322 | return error.AnalysisFail; | |
| 12362 | error.AlreadyReported => |e| { | |
| 12363 | if (sema.err) |msg| { | |
| 12364 | try sema.errNote(capture_src, msg, "this coercion is only possible when capturing by value", .{}); | |
| 12365 | try sema.reparentOwnedErrorMsg(capture_src, msg, "capture group with incompatible types", .{}); | |
| 12366 | } | |
| 12367 | return e; | |
| 12323 | 12368 | }, |
| 12324 | 12369 | else => |e| return e, |
| 12325 | 12370 | }; |
| ... | ... | @@ -12559,13 +12604,7 @@ fn validateSwitchItemOrRange( |
| 12559 | 12604 | item_val: Value, |
| 12560 | 12605 | opt_last_val: ?Value, |
| 12561 | 12606 | item_ty: Type, |
| 12562 | seen_enum_fields: []?LazySrcLoc, | |
| 12563 | seen_errors: *std.AutoHashMapUnmanaged(InternPool.NullTerminatedString, LazySrcLoc), | |
| 12564 | seen_sparse_values: *std.AutoHashMapUnmanaged(InternPool.Index, LazySrcLoc), | |
| 12565 | range_set: *RangeSet, | |
| 12566 | true_src: *?LazySrcLoc, | |
| 12567 | false_src: *?LazySrcLoc, | |
| 12568 | void_src: *?LazySrcLoc, | |
| 12607 | seen: *ValidatedSwitchBlock.Seen, | |
| 12569 | 12608 | ) CompileError!void { |
| 12570 | 12609 | const pt = sema.pt; |
| 12571 | 12610 | const zcu = pt.zcu; |
| ... | ... | @@ -12574,88 +12613,117 @@ fn validateSwitchItemOrRange( |
| 12574 | 12613 | .@"enum" => { |
| 12575 | 12614 | const int = ip.indexToKey(item_val.toIntern()).enum_tag.int; |
| 12576 | 12615 | if (ip.loadEnumType(item_ty.toIntern()).tagValueIndex(ip, int)) |field_index| { |
| 12577 | const maybe_prev_src = seen_enum_fields[field_index]; | |
| 12578 | seen_enum_fields[field_index] = item_src; | |
| 12616 | const maybe_prev_src = seen.enum_fields[field_index]; | |
| 12617 | seen.enum_fields[field_index] = item_src; | |
| 12579 | 12618 | break :maybe_prev_src maybe_prev_src; |
| 12580 | 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 | 12622 | .first = .fromInterned(int), |
| 12583 | 12623 | .last = .fromInterned(int), |
| 12584 | 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 | 12628 | .error_set => { |
| 12589 | 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 | 12631 | prev.value |
| 12592 | 12632 | else |
| 12593 | 12633 | null; |
| 12594 | 12634 | }, |
| 12595 | 12635 | .int, .comptime_int => { |
| 12596 | if (opt_last_val) |last_val| { | |
| 12597 | const first_val = item_val; | |
| 12636 | const first_val = item_val; | |
| 12637 | const last_val: Value = last_val: { | |
| 12638 | const last_val = opt_last_val orelse break :last_val item_val; | |
| 12598 | 12639 | if (try first_val.compareAll(.gt, last_val, item_ty, pt)) { |
| 12599 | 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(.{ | |
| 12602 | .first = first_val, | |
| 12603 | .last = last_val, | |
| 12604 | .src = item_src, | |
| 12605 | }, item_ty, zcu); | |
| 12606 | } else { | |
| 12607 | break :maybe_prev_src range_set.addAssumeCapacity(.{ | |
| 12608 | .first = item_val, | |
| 12609 | .last = item_val, | |
| 12610 | .src = item_src, | |
| 12611 | }, item_ty, zcu); | |
| 12642 | break :last_val last_val; | |
| 12643 | }; | |
| 12644 | if (seen.ranges.addAssumeCapacity(.{ | |
| 12645 | .first = first_val, | |
| 12646 | .last = last_val, | |
| 12647 | .src = item_src, | |
| 12648 | }, item_ty, zcu)) |prev_range| { | |
| 12649 | const overlap_start = first_val.numberMax(prev_range.first, zcu); | |
| 12650 | const overlap_end = last_val.numberMin(prev_range.last, zcu); | |
| 12651 | if (overlap_start.eql(overlap_end, item_ty, zcu)) { | |
| 12652 | return sema.failWithOwnedErrorMsg(block, msg: { | |
| 12653 | const msg = try sema.errMsg(item_src, "duplicate switch value '{f}'", .{ | |
| 12654 | overlap_start.fmtValueSema(pt, sema), | |
| 12655 | }); | |
| 12656 | errdefer msg.destroy(sema.gpa); | |
| 12657 | if (prev_range.first.eql(prev_range.last, item_ty, zcu)) { | |
| 12658 | try sema.errNote(prev_range.src, msg, "previous value here", .{}); | |
| 12659 | } else { | |
| 12660 | try sema.errNote(prev_range.src, msg, "previous value inside range here", .{}); | |
| 12661 | } | |
| 12662 | break :msg msg; | |
| 12663 | }); | |
| 12664 | } | |
| 12665 | assert(!prev_range.first.eql(prev_range.last, item_ty, zcu)); | |
| 12666 | return sema.failWithOwnedErrorMsg(block, msg: { | |
| 12667 | const msg = try sema.errMsg(item_src, "duplicate switch ranges", .{}); | |
| 12668 | errdefer msg.destroy(sema.gpa); | |
| 12669 | if (first_val.eql(prev_range.first, item_ty, zcu) and | |
| 12670 | last_val.eql(prev_range.last, item_ty, zcu)) | |
| 12671 | { | |
| 12672 | try sema.errNote(prev_range.src, msg, "previous range here", .{}); | |
| 12673 | } else { | |
| 12674 | try sema.errNote(prev_range.src, msg, "overlaps with previous range here", .{}); | |
| 12675 | try sema.errNote(prev_range.src, msg, "ranges overlap from '{f}' to '{f}'", .{ | |
| 12676 | overlap_start.fmtValueSema(pt, sema), overlap_end.fmtValueSema(pt, sema), | |
| 12677 | }); | |
| 12678 | } | |
| 12679 | break :msg msg; | |
| 12680 | }); | |
| 12612 | 12681 | } |
| 12682 | break :maybe_prev_src null; | |
| 12613 | 12683 | }, |
| 12614 | 12684 | .@"union", .@"struct" => { |
| 12615 | 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 | 12687 | .first = .fromInterned(backing_int_val), |
| 12618 | 12688 | .last = .fromInterned(backing_int_val), |
| 12619 | 12689 | .src = item_src, |
| 12620 | }, item_ty.backingIntType(zcu), zcu); | |
| 12690 | }, item_ty.backingIntType(zcu), zcu)) |prev| prev.src else null; | |
| 12621 | 12691 | }, |
| 12622 | 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 | 12694 | prev.value |
| 12625 | 12695 | else |
| 12626 | 12696 | null; |
| 12627 | 12697 | }, |
| 12628 | 12698 | .bool => { |
| 12629 | 12699 | if (item_val.toBool()) { |
| 12630 | if (true_src.*) |prev_src| break :maybe_prev_src prev_src; | |
| 12631 | true_src.* = item_src; | |
| 12700 | if (seen.true_src) |prev_src| break :maybe_prev_src prev_src; | |
| 12701 | seen.true_src = item_src; | |
| 12632 | 12702 | } else { |
| 12633 | if (false_src.*) |prev_src| break :maybe_prev_src prev_src; | |
| 12634 | false_src.* = item_src; | |
| 12703 | if (seen.false_src) |prev_src| break :maybe_prev_src prev_src; | |
| 12704 | seen.false_src = item_src; | |
| 12635 | 12705 | } |
| 12636 | 12706 | break :maybe_prev_src null; |
| 12637 | 12707 | }, |
| 12638 | 12708 | .void => { |
| 12639 | if (void_src.*) |prev_src| break :maybe_prev_src prev_src; | |
| 12640 | void_src.* = item_src; | |
| 12709 | if (seen.void_src) |prev_src| break :maybe_prev_src prev_src; | |
| 12710 | seen.void_src = item_src; | |
| 12641 | 12711 | break :maybe_prev_src null; |
| 12642 | 12712 | }, |
| 12643 | 12713 | else => unreachable, // should have already checked for invalid types |
| 12644 | 12714 | }; |
| 12645 | 12715 | if (maybe_prev_src) |prev_src| { |
| 12646 | 12716 | return sema.failWithOwnedErrorMsg(block, msg: { |
| 12647 | const msg = try sema.errMsg( | |
| 12648 | item_src, | |
| 12649 | "duplicate switch value", | |
| 12650 | .{}, | |
| 12651 | ); | |
| 12717 | const msg = try sema.errMsg(item_src, "duplicate switch value '{f}'", .{ | |
| 12718 | item_val.fmtValueSema(pt, sema), | |
| 12719 | }); | |
| 12652 | 12720 | errdefer msg.destroy(sema.gpa); |
| 12653 | try sema.errNote( | |
| 12654 | prev_src, | |
| 12655 | msg, | |
| 12656 | "previous value here", | |
| 12657 | .{}, | |
| 12658 | ); | |
| 12721 | try sema.errNote(prev_src, msg, "previous value here", .{}); | |
| 12722 | if (item_ty.zigTypeTag(zcu) == .type) { | |
| 12723 | try sema.addDeclaredHereNote(msg, item_val.toType()); | |
| 12724 | } else { | |
| 12725 | try sema.addDeclaredHereNote(msg, item_ty); | |
| 12726 | } | |
| 12659 | 12727 | break :msg msg; |
| 12660 | 12728 | }); |
| 12661 | 12729 | } |
| ... | ... | @@ -17171,7 +17239,14 @@ fn typeInfoNamespaceDecls( |
| 17171 | 17239 | const ip = &zcu.intern_pool; |
| 17172 | 17240 | |
| 17173 | 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 | 17250 | const namespace = zcu.namespacePtr(namespace_index); |
| 17176 | 17251 | |
| 17177 | 17252 | const gop = try seen_namespaces.getOrPut(namespace); |
| ... | ... | @@ -17897,11 +17972,12 @@ fn zirUnreachable(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError |
| 17897 | 17972 | } |
| 17898 | 17973 | // TODO Add compile error for @optimizeFor occurring too late in a scope. |
| 17899 | 17974 | sema.analyzeUnreachable(block, src, true) catch |err| switch (err) { |
| 17900 | error.AnalysisFail => { | |
| 17901 | const msg = sema.err orelse return err; | |
| 17902 | if (!mem.eql(u8, msg.msg, "runtime safety check not allowed in naked function")) return err; | |
| 17903 | try sema.errNote(src, msg, "the end of a naked function is implicitly unreachable", .{}); | |
| 17904 | return err; | |
| 17975 | error.AlreadyReported => |e| { | |
| 17976 | if (sema.err) |msg| { | |
| 17977 | if (!mem.eql(u8, msg.msg, "runtime safety check not allowed in naked function")) return err; | |
| 17978 | try sema.errNote(src, msg, "the end of a naked function is implicitly unreachable", .{}); | |
| 17979 | } | |
| 17980 | return e; | |
| 17905 | 17981 | }, |
| 17906 | 17982 | else => |e| return e, |
| 17907 | 17983 | }; |
| ... | ... | @@ -18317,11 +18393,16 @@ fn zirPtrType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air |
| 18317 | 18393 | |
| 18318 | 18394 | const elem_ty = blk: { |
| 18319 | 18395 | const air_inst = sema.resolveInst(extra.data.elem_type); |
| 18320 | const ty = sema.analyzeAsType(block, elem_ty_src, .type, air_inst) catch |err| { | |
| 18321 | if (err == error.AnalysisFail and sema.err != null and sema.typeOf(air_inst).isSinglePointer(zcu)) { | |
| 18322 | try sema.errNote(elem_ty_src, sema.err.?, "use '.*' to dereference pointer", .{}); | |
| 18323 | } | |
| 18324 | return err; | |
| 18396 | const ty = sema.analyzeAsType(block, elem_ty_src, .type, air_inst) catch |err| switch (err) { | |
| 18397 | error.AlreadyReported => |e| { | |
| 18398 | if (sema.err) |msg| { | |
| 18399 | if (sema.typeOf(air_inst).isSinglePointer(zcu)) { | |
| 18400 | try sema.errNote(elem_ty_src, msg, "use '.*' to dereference pointer", .{}); | |
| 18401 | } | |
| 18402 | } | |
| 18403 | return e; | |
| 18404 | }, | |
| 18405 | else => |e| return e, | |
| 18325 | 18406 | }; |
| 18326 | 18407 | assert(!ty.isGenericPoison()); |
| 18327 | 18408 | break :blk ty; |
| ... | ... | @@ -21103,7 +21184,10 @@ fn zirIntFromFloat(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 21103 | 21184 | const dest_scalar_ty = dest_ty.scalarType(zcu); |
| 21104 | 21185 | const operand_scalar_ty = operand_ty.scalarType(zcu); |
| 21105 | 21186 | |
| 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 | 21191 | try sema.checkFloatType(block, operand_src, operand_scalar_ty); |
| 21108 | 21192 | |
| 21109 | 21193 | if (sema.resolveValue(operand)) |operand_val| { |
| ... | ... | @@ -21279,7 +21363,10 @@ fn zirFloatFromInt(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 21279 | 21363 | const dest_scalar_ty = dest_ty.scalarType(zcu); |
| 21280 | 21364 | const operand_scalar_ty = operand_ty.scalarType(zcu); |
| 21281 | 21365 | |
| 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 | 21370 | _ = try sema.checkIntType(block, operand_src, operand_scalar_ty); |
| 21284 | 21371 | |
| 21285 | 21372 | if (sema.resolveValue(operand)) |operand_val| { |
| ... | ... | @@ -21594,16 +21681,16 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData |
| 21594 | 21681 | const is_zero = try block.addBinOp(.cmp_eq, err_int_inst, zero_err); |
| 21595 | 21682 | if (result == .disjoint) { |
| 21596 | 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 | 21685 | } else { |
| 21599 | 21686 | // Error must be in destination set or zero. |
| 21600 | 21687 | const has_value = try block.addTyOp(.error_set_has_value, dest_err_ty, err_int_inst); |
| 21601 | 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 | 21691 | } else { |
| 21605 | 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 | } |
| 21609 | 21696 | |
| ... | ... | @@ -23460,7 +23547,9 @@ fn analyzeShuffle( |
| 23460 | 23547 | // `InternPool.Index` values using the known operands. |
| 23461 | 23548 | for (mask_shuffle_two, mask_ip_index) |in, *out| { |
| 23462 | 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 | 23553 | .a_elem => |idx| try maybe_a_val.?.elemValue(pt, idx), |
| 23465 | 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 | 23598 | const a = try sema.coerce(block, vec_ty, sema.resolveInst(extra.a), a_src); |
| 23510 | 23599 | const b = try sema.coerce(block, vec_ty, sema.resolveInst(extra.b), b_src); |
| 23511 | 23600 | |
| 23601 | // special case zero bit types | |
| 23602 | if (try vec_ty.onePossibleValue(pt)) |opv| return .fromValue(opv); | |
| 23603 | ||
| 23512 | 23604 | const maybe_pred = sema.resolveValue(pred); |
| 23513 | 23605 | const maybe_a = sema.resolveValue(a); |
| 23514 | 23606 | const maybe_b = sema.resolveValue(b); |
| ... | ... | @@ -24873,7 +24965,10 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 24873 | 24965 | } else cc: { |
| 24874 | 24966 | if (has_body) { |
| 24875 | 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 | 24972 | const zir_decl = sema.code.getDeclaration(func_decl_inst); |
| 24878 | 24973 | if (zir_decl.linkage == .@"export") { |
| 24879 | 24974 | break :cc target.cCallingConvention() orelse { |
| ... | ... | @@ -25458,10 +25553,10 @@ fn zirRoundOpType(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstDa |
| 25458 | 25553 | return .generic_poison_type; |
| 25459 | 25554 | }; |
| 25460 | 25555 | |
| 25461 | const float_ty = dest_ty.optEuBaseType(zcu); | |
| 25462 | switch (float_ty.scalarType(zcu).zigTypeTag(zcu)) { | |
| 25463 | .float, .comptime_float => return .fromType(float_ty), | |
| 25464 | else => return .comptime_float_type, | |
| 25556 | const dest_base_ty = dest_ty.optEuBaseType(zcu); | |
| 25557 | switch (dest_base_ty.scalarType(zcu).zigTypeTag(zcu)) { | |
| 25558 | .float, .comptime_float => return .fromType(dest_base_ty), | |
| 25559 | else => return .generic_poison_type, | |
| 25465 | 25560 | } |
| 25466 | 25561 | } |
| 25467 | 25562 | |
| ... | ... | @@ -25640,7 +25735,6 @@ pub fn explainWhyTypeIsNotExtern( |
| 25640 | 25735 | |
| 25641 | 25736 | .@"opaque", |
| 25642 | 25737 | .bool, |
| 25643 | .float, | |
| 25644 | 25738 | .@"anyframe", |
| 25645 | 25739 | => unreachable, // these *are* allowed |
| 25646 | 25740 | |
| ... | ... | @@ -25649,6 +25743,7 @@ pub fn explainWhyTypeIsNotExtern( |
| 25649 | 25743 | try sema.errNote(src_loc, msg, "SPIR-V runtime arrays must be the last field of an extern struct", .{}); |
| 25650 | 25744 | }, |
| 25651 | 25745 | |
| 25746 | .float => try sema.errNote(src_loc, msg, "'{f}' is not extern compatible on this target", .{ty.fmt(pt)}), | |
| 25652 | 25747 | .pointer => if (ty.isSlice(zcu)) { |
| 25653 | 25748 | try sema.errNote(src_loc, msg, "slices have no guaranteed in-memory representation", .{}); |
| 25654 | 25749 | } else { |
| ... | ... | @@ -28174,9 +28269,94 @@ fn coerceExtra( |
| 28174 | 28269 | }, |
| 28175 | 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 | 28357 | .slice => to_slice: { |
| 28179 | 28358 | if (inst_ty.zigTypeTag(zcu) == .array) { |
| 28359 | if (!opts.report_err) return error.NotCoercible; | |
| 28180 | 28360 | return sema.fail( |
| 28181 | 28361 | block, |
| 28182 | 28362 | inst_src, |
| ... | ... | @@ -28204,6 +28384,7 @@ fn coerceExtra( |
| 28204 | 28384 | |
| 28205 | 28385 | // pointer to tuple to slice |
| 28206 | 28386 | if (!dest_info.flags.is_const) { |
| 28387 | if (!opts.report_err) return error.NotCoercible; | |
| 28207 | 28388 | const err_msg = err_msg: { |
| 28208 | 28389 | const err_msg = try sema.errMsg(inst_src, "cannot cast pointer to tuple to '{f}'", .{dest_ty.fmt(pt)}); |
| 28209 | 28390 | errdefer err_msg.destroy(sema.gpa); |
| ... | ... | @@ -28299,6 +28480,7 @@ fn coerceExtra( |
| 28299 | 28480 | if (maybe_inst_val) |val| { |
| 28300 | 28481 | const result_val = try val.floatCast(dest_ty, pt); |
| 28301 | 28482 | if (!val.eql(try result_val.floatCast(inst_ty, pt), inst_ty, zcu)) { |
| 28483 | if (!opts.report_err) return error.NotCoercible; | |
| 28302 | 28484 | return sema.fail( |
| 28303 | 28485 | block, |
| 28304 | 28486 | inst_src, |
| ... | ... | @@ -28356,12 +28538,15 @@ fn coerceExtra( |
| 28356 | 28538 | break :fits result_big_int.toConst().eql(operand_big_int); |
| 28357 | 28539 | }, |
| 28358 | 28540 | }; |
| 28359 | if (!fits) return sema.fail( | |
| 28360 | block, | |
| 28361 | inst_src, | |
| 28362 | "type '{f}' cannot represent integer value '{f}'", | |
| 28363 | .{ dest_ty.fmt(pt), val.fmtValue(pt) }, | |
| 28364 | ); | |
| 28541 | if (!fits) { | |
| 28542 | if (!opts.report_err) return error.NotCoercible; | |
| 28543 | return sema.fail( | |
| 28544 | block, | |
| 28545 | inst_src, | |
| 28546 | "type '{f}' cannot represent integer value '{f}'", | |
| 28547 | .{ dest_ty.fmt(pt), val.fmtValue(pt) }, | |
| 28548 | ); | |
| 28549 | } | |
| 28365 | 28550 | return .fromValue(result_val); |
| 28366 | 28551 | }, |
| 28367 | 28552 | else => {}, |
| ... | ... | @@ -28372,6 +28557,7 @@ fn coerceExtra( |
| 28372 | 28557 | const val = sema.resolveValue(inst).?; |
| 28373 | 28558 | const string = zcu.intern_pool.indexToKey(val.toIntern()).enum_literal; |
| 28374 | 28559 | const field_index = dest_ty.enumFieldIndex(string, zcu) orelse { |
| 28560 | if (!opts.report_err) return error.NotCoercible; | |
| 28375 | 28561 | return sema.fail(block, inst_src, "no field named '{f}' in enum '{f}'", .{ |
| 28376 | 28562 | string.fmt(&zcu.intern_pool), dest_ty.fmt(pt), |
| 28377 | 28563 | }); |
| ... | ... | @@ -29622,7 +29808,7 @@ fn coerceVarArgParam( |
| 29622 | 29808 | .array => return sema.fail(block, inst_src, "arrays must be passed by reference to variadic function", .{}), |
| 29623 | 29809 | .float => float: { |
| 29624 | 29810 | const target = zcu.getTarget(); |
| 29625 | const double_bits = target.cTypeBitSize(.double); | |
| 29811 | const double_bits = target.cTypeBitSize(.double) orelse break :float inst; | |
| 29626 | 29812 | const inst_bits = uncasted_ty.floatBits(target); |
| 29627 | 29813 | if (inst_bits >= double_bits) break :float inst; |
| 29628 | 29814 | switch (double_bits) { |
| ... | ... | @@ -29638,21 +29824,21 @@ fn coerceVarArgParam( |
| 29638 | 29824 | if (uncasted_info.bits <= target.cTypeBitSize(switch (uncasted_info.signedness) { |
| 29639 | 29825 | .signed => .int, |
| 29640 | 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 | 29828 | .signed => .c_int, |
| 29643 | 29829 | .unsigned => .c_uint, |
| 29644 | 29830 | }, inst, inst_src); |
| 29645 | 29831 | if (uncasted_info.bits <= target.cTypeBitSize(switch (uncasted_info.signedness) { |
| 29646 | 29832 | .signed => .long, |
| 29647 | 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 | 29835 | .signed => .c_long, |
| 29650 | 29836 | .unsigned => .c_ulong, |
| 29651 | 29837 | }, inst, inst_src); |
| 29652 | 29838 | if (uncasted_info.bits <= target.cTypeBitSize(switch (uncasted_info.signedness) { |
| 29653 | 29839 | .signed => .longlong, |
| 29654 | 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 | 29842 | .signed => .c_longlong, |
| 29657 | 29843 | .unsigned => .c_ulonglong, |
| 29658 | 29844 | }, inst, inst_src); |
| ... | ... | @@ -30048,6 +30234,19 @@ fn checkPtrAttributes(sema: *Sema, dest_ty: Type, inst_ty: Type, in_memory_resul |
| 30048 | 30234 | } }; |
| 30049 | 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 | 30250 | if (inst_info.flags.alignment == .none and dest_info.flags.alignment == .none) return true; |
| 30052 | 30251 | if (len0) return true; |
| 30053 | 30252 | |
| ... | ... | @@ -30068,19 +30267,6 @@ fn checkPtrAttributes(sema: *Sema, dest_ty: Type, inst_ty: Type, in_memory_resul |
| 30068 | 30267 | } }; |
| 30069 | 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 | 30270 | return true; |
| 30085 | 30271 | } |
| 30086 | 30272 | |
| ... | ... | @@ -30606,7 +30792,10 @@ fn ensureMemoizedStateResolved(sema: *Sema, src: LazySrcLoc, stage: InternPool.M |
| 30606 | 30792 | if (pt.zcu.analysis_in_progress.contains(unit)) { |
| 30607 | 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 | } |
| 30611 | 30800 | |
| 30612 | 30801 | pub 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 | 30831 | switch (kind) { |
| 30643 | 30832 | .type => { |
| 30644 | 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 | } |
| 30650 | 30845 | |
| ... | ... | @@ -30856,7 +31051,18 @@ fn analyzeLoad( |
| 30856 | 31051 | const comptime_only = switch (elem_ty.classify(zcu)) { |
| 30857 | 31052 | .no_possible_value => switch (elem_ty.zigTypeTag(zcu)) { |
| 30858 | 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 | 31067 | .one_possible_value => return .fromValue((try elem_ty.onePossibleValue(pt)).?), |
| 30862 | 31068 | .runtime => false, |
| ... | ... | @@ -30864,8 +31070,11 @@ fn analyzeLoad( |
| 30864 | 31070 | }; |
| 30865 | 31071 | |
| 30866 | 31072 | if (try sema.resolveDefinedValue(block, ptr_src, ptr)) |ptr_val| { |
| 30867 | if (try sema.pointerDeref(block, src, ptr_val, ptr_ty)) |elem_val| { | |
| 30868 | return Air.internedToRef(elem_val.toIntern()); | |
| 31073 | if (switch (ptr_ty.ptrSize(zcu)) { | |
| 31074 | .slice => try sema.maybeDerefSliceAsArray(block, src, ptr_val), | |
| 31075 | else => try sema.pointerDeref(block, src, ptr_val, ptr_ty), | |
| 31076 | }) |elem_val| { | |
| 31077 | return .fromValue(elem_val); | |
| 30869 | 31078 | } |
| 30870 | 31079 | } |
| 30871 | 31080 | |
| ... | ... | @@ -33707,7 +33916,10 @@ fn ensureFuncIesResolved( |
| 33707 | 33916 | return sema.failWithDependencyLoop(.wrap(.{ .func = func_index }), &reason); |
| 33708 | 33917 | } |
| 33709 | 33918 | |
| 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 | } |
| 33712 | 33924 | |
| 33713 | 33925 | pub fn resolveInferredErrorSetPtr( |
| ... | ... | @@ -33821,7 +34033,7 @@ pub fn getTmpAir(sema: Sema) Air { |
| 33821 | 34033 | } |
| 33822 | 34034 | |
| 33823 | 34035 | pub 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 | 34037 | try sema.air_extra.ensureUnusedCapacity(sema.gpa, field_count); |
| 33826 | 34038 | return sema.addExtraAssumeCapacity(extra); |
| 33827 | 34039 | } |
| ... | ... | @@ -34536,7 +34748,6 @@ fn maybeDerefSliceAsArray( |
| 34536 | 34748 | ) CompileError!?Value { |
| 34537 | 34749 | const pt = sema.pt; |
| 34538 | 34750 | const zcu = pt.zcu; |
| 34539 | const ip = &zcu.intern_pool; | |
| 34540 | 34751 | const slice_ty = slice_val.typeOf(zcu); |
| 34541 | 34752 | assert(slice_ty.zigTypeTag(zcu) == .pointer); |
| 34542 | 34753 | switch (slice_ty.ptrInfo(zcu).flags.size) { |
| ... | ... | @@ -34544,26 +34755,14 @@ fn maybeDerefSliceAsArray( |
| 34544 | 34755 | .one => return sema.pointerDeref(block, src, slice_val, slice_ty), |
| 34545 | 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 | 34759 | .undef => return sema.failWithUseOfUndef(block, src, null), |
| 34549 | 34760 | .slice => |slice| slice, |
| 34550 | 34761 | else => unreachable, |
| 34551 | 34762 | }; |
| 34552 | const elem_ty = Type.fromInterned(slice.ty).childType(zcu); | |
| 34553 | const len = Value.fromInterned(slice.len).toUnsignedInt(zcu); | |
| 34554 | const array_ty = try pt.arrayType(.{ | |
| 34555 | .child = elem_ty.toIntern(), | |
| 34556 | .len = len, | |
| 34557 | }); | |
| 34558 | const ptr_ty = try pt.ptrType(p: { | |
| 34559 | var p = Type.fromInterned(slice.ty).ptrInfo(zcu); | |
| 34560 | p.flags.size = .one; | |
| 34561 | p.child = array_ty.toIntern(); | |
| 34562 | p.sentinel = .none; | |
| 34563 | break :p p; | |
| 34564 | }); | |
| 34565 | const casted_ptr = try pt.getCoerced(Value.fromInterned(slice.ptr), ptr_ty); | |
| 34566 | return sema.pointerDeref(block, src, casted_ptr, ptr_ty); | |
| 34763 | if (slice.len == .undef_usize) return sema.failWithUndefSliceLen(block, src); | |
| 34764 | const casted_ptr = try pt.sliceToArrayPtr(slice); | |
| 34765 | return sema.pointerDeref(block, src, casted_ptr, casted_ptr.typeOf(zcu)); | |
| 34567 | 34766 | } |
| 34568 | 34767 | |
| 34569 | 34768 | fn analyzeUnreachable(sema: *Sema, block: *Block, src: LazySrcLoc, safety_check: bool) !void { |
| ... | ... | @@ -34668,7 +34867,7 @@ pub fn resolveNavPtrModifiers( |
| 34668 | 34867 | const linksection_body = zir_decl.linksection_body orelse break :ls .none; |
| 34669 | 34868 | const linksection_ref = try sema.resolveInlineBody(block, linksection_body, decl_inst); |
| 34670 | 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 | 34871 | return sema.fail(block, section_src, "linksection cannot contain null bytes", .{}); |
| 34673 | 34872 | } else if (bytes.len == 0) { |
| 34674 | 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 | 35042 | }), |
| 34844 | 35043 | |
| 34845 | 35044 | // `fn (anyerror) noreturn` |
| 34846 | .@"panic.unwrapError" => try pt.funcType(.{ | |
| 35045 | .@"panic.unwrapError", | |
| 35046 | .@"panic.unexpectedErrorCode", | |
| 35047 | => try pt.funcType(.{ | |
| 34847 | 35048 | .param_types = &.{.anyerror_type}, |
| 34848 | 35049 | .return_type = .noreturn_type, |
| 34849 | 35050 | }), |
| ... | ... | @@ -34882,12 +35083,60 @@ fn getExpectedBuiltinFnType(sema: *Sema, decl: Zcu.StdLangDecl) CompileError!Typ |
| 34882 | 35083 | .@"panic.copyLenMismatch", |
| 34883 | 35084 | .@"panic.memcpyAlias", |
| 34884 | 35085 | .@"panic.noreturnReturned", |
| 35086 | .@"panic.loadUninstantiableType", | |
| 34885 | 35087 | => try pt.funcType(.{ |
| 34886 | 35088 | .param_types = &.{}, |
| 34887 | 35089 | .return_type = .noreturn_type, |
| 34888 | 35090 | }), |
| 34889 | 35091 | |
| 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 | } |
| 34893 | 35142 | |
| ... | ... | @@ -34926,7 +35175,9 @@ pub fn setTypeName( |
| 34926 | 35175 | }, |
| 34927 | 35176 | .parent => wip.setName(ip, block.type_name_ctx, sema.owner.unwrap().nav_val.toOptional()), |
| 34928 | 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 | 35181 | const zir_tags = sema.code.instructions.items(.tag); |
| 34931 | 35182 | |
| 34932 | 35183 | var aw: std.Io.Writer.Allocating = .init(gpa); |
| ... | ... | @@ -35042,7 +35293,10 @@ fn zirStructDecl( |
| 35042 | 35293 | }; |
| 35043 | 35294 | |
| 35044 | 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 | }; | |
| 35046 | 35300 | |
| 35047 | 35301 | return .fromType(ty); |
| 35048 | 35302 | } |
| ... | ... | @@ -35115,7 +35369,10 @@ fn zirUnionDecl( |
| 35115 | 35369 | }; |
| 35116 | 35370 | |
| 35117 | 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 | }; | |
| 35119 | 35376 | |
| 35120 | 35377 | return .fromType(ty); |
| 35121 | 35378 | } |
| ... | ... | @@ -35167,7 +35424,10 @@ fn zirEnumDecl( |
| 35167 | 35424 | }; |
| 35168 | 35425 | |
| 35169 | 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 | }; | |
| 35171 | 35431 | |
| 35172 | 35432 | return .fromType(ty); |
| 35173 | 35433 | } |
| ... | ... | @@ -35216,7 +35476,10 @@ fn zirOpaqueDecl( |
| 35216 | 35476 | }; |
| 35217 | 35477 | |
| 35218 | 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 | }; | |
| 35220 | 35483 | |
| 35221 | 35484 | return .fromType(ty); |
| 35222 | 35485 | } |
| ... | ... | @@ -35257,5 +35520,31 @@ pub fn failWithDependencyLoop( |
| 35257 | 35520 | } |
| 35258 | 35521 | |
| 35259 | 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. | |
| 35535 | pub 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 | 320 | self: *LowerZon, |
| 321 | 321 | ty: Type, |
| 322 | 322 | opt_note: ?[]const u8, |
| 323 | ) error{ AnalysisFail, OutOfMemory } { | |
| 323 | ) Zcu.SemaError { | |
| 324 | 324 | @branchHint(.cold); |
| 325 | 325 | const sema = self.sema; |
| 326 | 326 | const gpa = sema.gpa; |
| ... | ... | @@ -338,7 +338,7 @@ fn fail( |
| 338 | 338 | node: Zoir.Node.Index, |
| 339 | 339 | comptime format: []const u8, |
| 340 | 340 | args: anytype, |
| 341 | ) error{ AnalysisFail, OutOfMemory } { | |
| 341 | ) Zcu.SemaError { | |
| 342 | 342 | @branchHint(.cold); |
| 343 | 343 | const err_msg = try Zcu.ErrorMsg.create(self.sema.pt.zcu.gpa, self.nodeSrc(node), format, args); |
| 344 | 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 | 116 | if (zcu.analysis_in_progress.contains(.wrap(.{ .type_layout = ty.toIntern() }))) { |
| 117 | 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 | }, |
| 121 | 124 | |
| 122 | 125 | // values, not types |
| ... | ... | @@ -166,7 +169,10 @@ pub fn ensureStructDefaultsResolved(sema: *Sema, ty: Type, src: LazySrcLoc) Sema |
| 166 | 169 | return sema.failWithDependencyLoop(.wrap(.{ .struct_defaults = ty.toIntern() }), &reason); |
| 167 | 170 | } |
| 168 | 171 | |
| 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 | } |
| 171 | 177 | |
| 172 | 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 | 194 | |
| 189 | 195 | const struct_obj = ip.loadStructType(struct_ty.toIntern()); |
| 190 | 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 | }; | |
| 192 | 200 | |
| 193 | 201 | var block: Block = .{ |
| 194 | 202 | .parent = null, |
| ... | ... | @@ -364,7 +372,7 @@ pub fn resolveStructLayout(sema: *Sema, struct_ty: Type) CompileError!void { |
| 364 | 372 | const a = struct_obj.field_aligns.get(ip)[field_idx]; |
| 365 | 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 | 377 | align_out.* = field_align; |
| 370 | 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 | 614 | struct_ty.assertHasLayout(zcu); |
| 607 | 615 | const layout_unit: InternPool.AnalUnit = .wrap(.{ .type_layout = struct_ty.toIntern() }); |
| 608 | 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 | } |
| 611 | 619 | |
| 612 | 620 | const struct_obj = ip.loadStructType(struct_ty.toIntern()); |
| ... | ... | @@ -656,7 +664,9 @@ fn resolveStructDefaultsInner( |
| 656 | 664 | assert(struct_obj.field_defaults.len > 0); |
| 657 | 665 | |
| 658 | 666 | // 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 | 670 | try sema.inst_map.ensureSpaceForInstructions(gpa, &.{zir_index}); |
| 661 | 671 | |
| 662 | 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 | 723 | |
| 714 | 724 | const union_obj = ip.loadUnionType(union_ty.toIntern()); |
| 715 | 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 | }; | |
| 717 | 729 | |
| 718 | 730 | var block: Block = .{ |
| 719 | 731 | .parent = null, |
| ... | ... | @@ -1212,7 +1224,9 @@ pub fn resolveEnumLayout(sema: *Sema, enum_ty: Type) CompileError!void { |
| 1212 | 1224 | }; |
| 1213 | 1225 | |
| 1214 | 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 | }; | |
| 1216 | 1230 | |
| 1217 | 1231 | var block: Block = .{ |
| 1218 | 1232 | .parent = null, |
src/Type.zig+107-86| ... | ... | @@ -957,12 +957,27 @@ pub fn abiAlignment(ty: Type, zcu: *const Zcu) Alignment { |
| 957 | 957 | if (vector_type.len == 0) return .@"1"; |
| 958 | 958 | switch (zcu.comp.getZigBackend()) { |
| 959 | 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 | 969 | if (elem_bits == 0) return .@"1"; |
| 962 | 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 | 981 | .stage2_x86_64 => { |
| 967 | 982 | if (vector_type.child == .bool_type) { |
| 968 | 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 | 1033 | .c_ulonglong => cTypeAlign(target, .ulonglong), |
| 1019 | 1034 | .c_longdouble => cTypeAlign(target, .longdouble), |
| 1020 | 1035 | |
| 1021 | .f16 => .@"2", | |
| 1022 | .f32 => if (target.os.tag == .opengl) .@"4" else cTypeAlign(target, .float), | |
| 1023 | .f64 => if (target.os.tag == .opengl) .@"8" else switch (target.cTypeBitSize(.double)) { | |
| 1024 | 64 => cTypeAlign(target, .double), | |
| 1025 | else => .@"8", | |
| 1026 | }, | |
| 1027 | .f80 => switch (target.cTypeBitSize(.longdouble)) { | |
| 1028 | 80 => cTypeAlign(target, .longdouble), | |
| 1029 | else => Type.u80.abiAlignment(zcu), | |
| 1030 | }, | |
| 1031 | .f128 => switch (target.cTypeBitSize(.longdouble)) { | |
| 1032 | 128 => cTypeAlign(target, .longdouble), | |
| 1033 | else => .@"16", | |
| 1036 | .f16 => .fromByteUnits(std.zig.target.intAlignment(target, 16)), // repr: u16 | |
| 1037 | .f32 => if (target.cTypeBitSize(.float) == 32) | |
| 1038 | cTypeAlign(target, .float) // abi: c_float, | |
| 1039 | else | |
| 1040 | .fromByteUnits(std.zig.target.intAlignment(target, 32)), // repr: u32, | |
| 1041 | .f64 => if (target.cTypeBitSize(.double) == 64) | |
| 1042 | cTypeAlign(target, .double) // abi: c_double, | |
| 1043 | else | |
| 1044 | .fromByteUnits(std.zig.target.intAlignment(target, 64)), // repr: u64, | |
| 1045 | .f80 => if (target.cTypeBitSize(.longdouble) == 80) | |
| 1046 | cTypeAlign(target, .longdouble) // abi: c_longdouble, | |
| 1047 | else | |
| 1048 | .fromByteUnits(switch (std.zig.target.compilerRtFloatAbi(target, 80)) { | |
| 1049 | .hard => std.zig.target.intAlignment(target, 80), // repr: u80, | |
| 1050 | .soft => @max( | |
| 1051 | std.zig.target.intAlignment(target, 64), // mantissa: u64, | |
| 1052 | std.zig.target.intAlignment(target, 16), // exponent: u16, | |
| 1053 | ), | |
| 1054 | }), | |
| 1055 | .f128 => if (target.cTypeBitSize(.longdouble) == 128) | |
| 1056 | cTypeAlign(target, .longdouble) // abi: c_longdouble, | |
| 1057 | else switch (std.zig.target.compilerRtFloatAbi(target, 128)) { | |
| 1058 | .hard => if (target.cpu.arch.isX86()) | |
| 1059 | .@"16" // abi: c___float128, | |
| 1060 | else | |
| 1061 | .fromByteUnits(std.zig.target.intAlignment(target, 128)), // repr: u128, | |
| 1062 | .soft => .fromByteUnits(std.zig.target.intAlignment(target, 64)), // lo: u64, hi: u64, | |
| 1034 | 1063 | }, |
| 1035 | 1064 | |
| 1036 | 1065 | .generic_poison => unreachable, |
| ... | ... | @@ -1111,7 +1140,13 @@ pub fn abiSize(ty: Type, zcu: *const Zcu) u64 { |
| 1111 | 1140 | .vector_type => |vec| { |
| 1112 | 1141 | const elem_ty: Type = .fromInterned(vec.child); |
| 1113 | 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 | 1150 | .stage2_c, .stage2_wasm => vec.len * elem_ty.abiSize(zcu), |
| 1116 | 1151 | .stage2_x86_64 => switch (elem_ty.toIntern()) { |
| 1117 | 1152 | .bool_type => @divCeil(vec.len, 8), |
| ... | ... | @@ -1167,25 +1202,44 @@ pub fn abiSize(ty: Type, zcu: *const Zcu) u64 { |
| 1167 | 1202 | .anyerror, .adhoc_inferred_error_set => errorAbiSize(zcu), |
| 1168 | 1203 | .usize, .isize => ptrAbiSize(target), |
| 1169 | 1204 | |
| 1170 | .c_char => target.cTypeByteSize(.char), | |
| 1171 | .c_short => target.cTypeByteSize(.short), | |
| 1172 | .c_ushort => target.cTypeByteSize(.ushort), | |
| 1173 | .c_int => target.cTypeByteSize(.int), | |
| 1174 | .c_uint => target.cTypeByteSize(.uint), | |
| 1175 | .c_long => target.cTypeByteSize(.long), | |
| 1176 | .c_ulong => target.cTypeByteSize(.ulong), | |
| 1177 | .c_longlong => target.cTypeByteSize(.longlong), | |
| 1178 | .c_ulonglong => target.cTypeByteSize(.ulonglong), | |
| 1179 | .c_longdouble => target.cTypeByteSize(.longdouble), | |
| 1180 | ||
| 1181 | .f16 => 2, | |
| 1182 | .f32 => 4, | |
| 1183 | .f64 => 8, | |
| 1184 | .f80 => switch (target.cTypeBitSize(.longdouble)) { | |
| 1185 | 80 => target.cTypeByteSize(.longdouble), | |
| 1186 | else => Type.u80.abiSize(zcu), | |
| 1205 | .c_char => target.cTypeByteSize(.char).?, | |
| 1206 | .c_short => target.cTypeByteSize(.short).?, | |
| 1207 | .c_ushort => target.cTypeByteSize(.ushort).?, | |
| 1208 | .c_int => target.cTypeByteSize(.int).?, | |
| 1209 | .c_uint => target.cTypeByteSize(.uint).?, | |
| 1210 | .c_long => target.cTypeByteSize(.long).?, | |
| 1211 | .c_ulong => target.cTypeByteSize(.ulong).?, | |
| 1212 | .c_longlong => target.cTypeByteSize(.longlong).?, | |
| 1213 | .c_ulonglong => target.cTypeByteSize(.ulonglong).?, | |
| 1214 | .c_longdouble => target.cTypeByteSize(.longdouble).?, | |
| 1215 | ||
| 1216 | .f16 => std.zig.target.intByteSize(target, 16), // repr: u16 | |
| 1217 | .f32 => if (target.cTypeBitSize(.float) == 32) | |
| 1218 | target.cTypeByteSize(.float).? // abi: c_float, | |
| 1219 | else | |
| 1220 | std.zig.target.intByteSize(target, 32), // repr: u32, | |
| 1221 | .f64 => if (target.cTypeBitSize(.double) == 64) | |
| 1222 | target.cTypeByteSize(.double).? // abi: c_double, | |
| 1223 | else | |
| 1224 | std.zig.target.intByteSize(target, 64), // repr: u64, | |
| 1225 | .f80 => if (target.cTypeBitSize(.longdouble) == 80) | |
| 1226 | target.cTypeByteSize(.longdouble).? // abi: c_longdouble, | |
| 1227 | else switch (std.zig.target.compilerRtFloatAbi(target, 80)) { | |
| 1228 | .hard => std.zig.target.intByteSize(target, 80), // repr: u80, | |
| 1229 | .soft => ty.abiAlignment(zcu).forward( | |
| 1230 | std.zig.target.intByteSize(target, 64) + // mantissa: u64, | |
| 1231 | std.zig.target.intByteSize(target, 16), // exponent: u16 | |
| 1232 | ), | |
| 1233 | }, | |
| 1234 | .f128 => if (target.cTypeBitSize(.longdouble) == 128) | |
| 1235 | target.cTypeByteSize(.longdouble).? // abi: c_longdouble, | |
| 1236 | else switch (std.zig.target.compilerRtFloatAbi(target, 128)) { | |
| 1237 | .hard => if (target.cpu.arch.isX86()) | |
| 1238 | 16 // abi: c___float128, | |
| 1239 | else | |
| 1240 | std.zig.target.intByteSize(target, 128), // repr: u128, | |
| 1241 | .soft => std.zig.target.intByteSize(target, 64) * 2, // lo: u64, hi: u64, | |
| 1187 | 1242 | }, |
| 1188 | .f128 => 16, | |
| 1189 | 1243 | |
| 1190 | 1244 | .anyopaque => unreachable, |
| 1191 | 1245 | .generic_poison => unreachable, |
| ... | ... | @@ -1733,7 +1787,7 @@ pub fn isInt(self: Type, zcu: *const Zcu) bool { |
| 1733 | 1787 | /// Returns true if and only if the type is a fixed-width, signed integer. |
| 1734 | 1788 | pub fn isSignedInt(ty: Type, zcu: *const Zcu) bool { |
| 1735 | 1789 | return switch (ty.toIntern()) { |
| 1736 | .c_char_type => zcu.getTarget().cCharSignedness() == .signed, | |
| 1790 | .c_char_type => zcu.getTarget().cCharSignedness().? == .signed, | |
| 1737 | 1791 | .isize_type, .c_short_type, .c_int_type, .c_long_type, .c_longlong_type => true, |
| 1738 | 1792 | else => switch (zcu.intern_pool.indexToKey(ty.toIntern())) { |
| 1739 | 1793 | .int_type => |int_type| int_type.signedness == .signed, |
| ... | ... | @@ -1745,7 +1799,7 @@ pub fn isSignedInt(ty: Type, zcu: *const Zcu) bool { |
| 1745 | 1799 | /// Returns true if and only if the type is a fixed-width, unsigned integer. |
| 1746 | 1800 | pub fn isUnsignedInt(ty: Type, zcu: *const Zcu) bool { |
| 1747 | 1801 | return switch (ty.toIntern()) { |
| 1748 | .c_char_type => zcu.getTarget().cCharSignedness() == .unsigned, | |
| 1802 | .c_char_type => zcu.getTarget().cCharSignedness().? == .unsigned, | |
| 1749 | 1803 | .usize_type, .c_ushort_type, .c_uint_type, .c_ulong_type, .c_ulonglong_type => true, |
| 1750 | 1804 | else => switch (zcu.intern_pool.indexToKey(ty.toIntern())) { |
| 1751 | 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 | 1830 | }, |
| 1777 | 1831 | .usize_type => return .{ .signedness = .unsigned, .bits = target.ptrBitWidth() }, |
| 1778 | 1832 | .isize_type => return .{ .signedness = .signed, .bits = target.ptrBitWidth() }, |
| 1779 | .c_char_type => return .{ .signedness = zcu.getTarget().cCharSignedness(), .bits = target.cTypeBitSize(.char) }, | |
| 1780 | .c_short_type => return .{ .signedness = .signed, .bits = target.cTypeBitSize(.short) }, | |
| 1781 | .c_ushort_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.ushort) }, | |
| 1782 | .c_int_type => return .{ .signedness = .signed, .bits = target.cTypeBitSize(.int) }, | |
| 1783 | .c_uint_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.uint) }, | |
| 1784 | .c_long_type => return .{ .signedness = .signed, .bits = target.cTypeBitSize(.long) }, | |
| 1785 | .c_ulong_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.ulong) }, | |
| 1786 | .c_longlong_type => return .{ .signedness = .signed, .bits = target.cTypeBitSize(.longlong) }, | |
| 1787 | .c_ulonglong_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.ulonglong) }, | |
| 1833 | .c_char_type => return .{ .signedness = target.cCharSignedness().?, .bits = target.cTypeBitSize(.char).? }, | |
| 1834 | .c_short_type => return .{ .signedness = .signed, .bits = target.cTypeBitSize(.short).? }, | |
| 1835 | .c_ushort_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.ushort).? }, | |
| 1836 | .c_int_type => return .{ .signedness = .signed, .bits = target.cTypeBitSize(.int).? }, | |
| 1837 | .c_uint_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.uint).? }, | |
| 1838 | .c_long_type => return .{ .signedness = .signed, .bits = target.cTypeBitSize(.long).? }, | |
| 1839 | .c_ulong_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.ulong).? }, | |
| 1840 | .c_longlong_type => return .{ .signedness = .signed, .bits = target.cTypeBitSize(.longlong).? }, | |
| 1841 | .c_ulonglong_type => return .{ .signedness = .unsigned, .bits = target.cTypeBitSize(.ulonglong).? }, | |
| 1788 | 1842 | else => switch (ip.indexToKey(ty.toIntern())) { |
| 1789 | 1843 | .int_type => |int_type| return int_type, |
| 1790 | 1844 | .struct_type => { |
| ... | ... | @@ -1882,7 +1936,7 @@ pub fn floatBits(ty: Type, target: *const Target) u16 { |
| 1882 | 1936 | .f64_type => 64, |
| 1883 | 1937 | .f80_type => 80, |
| 1884 | 1938 | .f128_type, .comptime_float_type => 128, |
| 1885 | .c_longdouble_type => target.cTypeBitSize(.longdouble), | |
| 1939 | .c_longdouble_type => target.cTypeBitSize(.longdouble).?, | |
| 1886 | 1940 | |
| 1887 | 1941 | else => unreachable, |
| 1888 | 1942 | }; |
| ... | ... | @@ -2147,13 +2201,6 @@ pub fn isVector(ty: Type, zcu: *const Zcu) bool { |
| 2147 | 2201 | return ty.zigTypeTag(zcu) == .vector; |
| 2148 | 2202 | } |
| 2149 | 2203 | |
| 2150 | /// Returns 0 if not a vector, otherwise returns @bitSizeOf(Element) * vector_len. | |
| 2151 | pub 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 | ||
| 2157 | 2204 | pub fn isArrayOrVector(ty: Type, zcu: *const Zcu) bool { |
| 2158 | 2205 | return switch (ty.zigTypeTag(zcu)) { |
| 2159 | 2206 | .array, .vector => true, |
| ... | ... | @@ -2416,34 +2463,6 @@ pub fn explicitFieldAlignment(ty: Type, index: usize, zcu: *const Zcu) Alignment |
| 2416 | 2463 | }; |
| 2417 | 2464 | } |
| 2418 | 2465 | |
| 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"`. | |
| 2424 | pub 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 | ||
| 2447 | 2466 | pub fn structFieldDefaultValue(ty: Type, index: usize, zcu: *const Zcu) ?Value { |
| 2448 | 2467 | const ip = &zcu.intern_pool; |
| 2449 | 2468 | switch (ip.indexToKey(ty.toIntern())) { |
| ... | ... | @@ -2961,8 +2980,7 @@ pub fn fieldPtrType(ptr_ty: Type, field_index: u32, pt: Zcu.PerThread) Allocator |
| 2961 | 2980 | } |
| 2962 | 2981 | const actual_field_align = switch (field_align) { |
| 2963 | 2982 | .none => switch (ip.indexToKey(aggregate_ty.toIntern())) { |
| 2964 | .tuple_type, .union_type => field_ty.abiAlignment(zcu), | |
| 2965 | .struct_type => field_ty.defaultStructFieldAlignment(.auto, zcu), | |
| 2983 | .struct_type, .tuple_type, .union_type => field_ty.abiAlignment(zcu), | |
| 2966 | 2984 | .ptr_type => Type.usize.abiAlignment(zcu), |
| 2967 | 2985 | else => unreachable, |
| 2968 | 2986 | }, |
| ... | ... | @@ -3122,7 +3140,6 @@ pub fn validateExtern(ty: Type, position: ExternPosition, zcu: *const Zcu) bool |
| 3122 | 3140 | |
| 3123 | 3141 | .@"opaque", |
| 3124 | 3142 | .bool, |
| 3125 | .float, | |
| 3126 | 3143 | .@"anyframe", |
| 3127 | 3144 | => true, |
| 3128 | 3145 | |
| ... | ... | @@ -3144,6 +3161,10 @@ pub fn validateExtern(ty: Type, position: ExternPosition, zcu: *const Zcu) bool |
| 3144 | 3161 | 24, 48 => zcu.getTarget().cpu.arch == .ez80, |
| 3145 | 3162 | else => false, |
| 3146 | 3163 | }, |
| 3164 | .float => switch (ty.floatBits(zcu.getTarget())) { | |
| 3165 | else => true, | |
| 3166 | 80 => zcu.getTarget().cTypeBitSize(.longdouble) == 80, | |
| 3167 | }, | |
| 3147 | 3168 | .@"fn" => { |
| 3148 | 3169 | if (position != .other) return false; |
| 3149 | 3170 | return validateExternCallconv(ty.fnCallingConvention(zcu)); |
| ... | ... | @@ -3600,5 +3621,5 @@ pub fn smallestUnsignedBits(max: u64) u16 { |
| 3600 | 3621 | pub const packed_struct_layout_version = 2; |
| 3601 | 3622 | |
| 3602 | 3623 | fn 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 | 611 | return switch (zcu.intern_pool.indexToKey(val.toIntern())) { |
| 612 | 612 | .int => |int| switch (int.storage) { |
| 613 | 613 | .big_int => |big_int| big_int.toFloat(T, .nearest_even)[0], |
| 614 | inline .u64, .i64 => |x| { | |
| 615 | if (T == f80) { | |
| 616 | @panic("TODO we can't lower this properly on non-x86 llvm backend yet"); | |
| 617 | } | |
| 618 | return @floatFromInt(x); | |
| 619 | }, | |
| 614 | inline .u64, .i64 => |x| @floatFromInt(x), | |
| 620 | 615 | }, |
| 621 | 616 | .float => |float| switch (float.storage) { |
| 622 | 617 | inline else => |x| @floatCast(x), |
| ... | ... | @@ -959,7 +954,7 @@ pub fn anyScalarIsZero(val: Value, zcu: *Zcu) bool { |
| 959 | 954 | .bytes => |str| { |
| 960 | 955 | const len = Type.fromInterned(agg.ty).vectorLen(zcu); |
| 961 | 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 | 959 | .elems => |elems| { |
| 965 | 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 | 182 | /// The ErrorMsg memory is owned by the `AnalUnit`, using Module's general purpose allocator. |
| 183 | 183 | failed_analysis: std.array_hash_map.Auto(AnalUnit, *ErrorMsg) = .empty, |
| 184 | 184 | /// This `AnalUnit` failed semantic analysis because it required analysis of another `AnalUnit` which itself failed. |
| 185 | transitive_failed_analysis: std.array_hash_map.Auto(AnalUnit, void) = .empty, | |
| 185 | transitive_failed_analysis: std.array_hash_map.Auto( | |
| 186 | AnalUnit, | |
| 187 | if (build_options.enable_debug_extensions) TransitiveFailureReason else void, | |
| 188 | ) = .empty, | |
| 186 | 189 | /// This `Nav` succeeded analysis, but failed codegen. |
| 187 | 190 | /// This may be a simple "value" `Nav`, or it may be a function. |
| 188 | 191 | /// The ErrorMsg memory is owned by the `AnalUnit`, using Module's general purpose allocator. |
| ... | ... | @@ -351,6 +354,18 @@ pub const DependencyReason = struct { |
| 351 | 354 | type_layout_reason: Sema.type_resolution.LayoutResolveReason, |
| 352 | 355 | }; |
| 353 | 356 | |
| 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. | |
| 361 | pub 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 | ||
| 354 | 369 | pub const IncrementalDebugState = struct { |
| 355 | 370 | /// All container types in the ZCU, even dead ones. |
| 356 | 371 | /// Value is the generation the type was created on. |
| ... | ... | @@ -488,6 +503,7 @@ pub const StdLangDecl = enum { |
| 488 | 503 | @"panic.castToNull", |
| 489 | 504 | @"panic.incorrectAlignment", |
| 490 | 505 | @"panic.invalidErrorCode", |
| 506 | @"panic.unexpectedErrorCode", | |
| 491 | 507 | @"panic.integerOutOfBounds", |
| 492 | 508 | @"panic.integerOverflow", |
| 493 | 509 | @"panic.shlOverflow", |
| ... | ... | @@ -502,6 +518,7 @@ pub const StdLangDecl = enum { |
| 502 | 518 | @"panic.copyLenMismatch", |
| 503 | 519 | @"panic.memcpyAlias", |
| 504 | 520 | @"panic.noreturnReturned", |
| 521 | @"panic.loadUninstantiableType", | |
| 505 | 522 | |
| 506 | 523 | VaList, |
| 507 | 524 | |
| ... | ... | @@ -577,6 +594,7 @@ pub const StdLangDecl = enum { |
| 577 | 594 | .@"panic.castToNull", |
| 578 | 595 | .@"panic.incorrectAlignment", |
| 579 | 596 | .@"panic.invalidErrorCode", |
| 597 | .@"panic.unexpectedErrorCode", | |
| 580 | 598 | .@"panic.integerOutOfBounds", |
| 581 | 599 | .@"panic.integerOverflow", |
| 582 | 600 | .@"panic.shlOverflow", |
| ... | ... | @@ -591,6 +609,7 @@ pub const StdLangDecl = enum { |
| 591 | 609 | .@"panic.copyLenMismatch", |
| 592 | 610 | .@"panic.memcpyAlias", |
| 593 | 611 | .@"panic.noreturnReturned", |
| 612 | .@"panic.loadUninstantiableType", | |
| 594 | 613 | => .func, |
| 595 | 614 | }; |
| 596 | 615 | } |
| ... | ... | @@ -633,7 +652,7 @@ pub const StdLangDecl = enum { |
| 633 | 652 | return switch (decl) { |
| 634 | 653 | inline else => |tag| { |
| 635 | 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 | 656 | const parent = @field(StdLangDecl, name[0..split]); |
| 638 | 657 | comptime assert(@backingInt(parent) < @backingInt(tag)); // dependencies ordered correctly |
| 639 | 658 | return .{ .nested = .{ parent, name[split + 1 ..] } }; |
| ... | ... | @@ -664,6 +683,7 @@ pub const SimplePanicId = enum { |
| 664 | 683 | copy_len_mismatch, |
| 665 | 684 | memcpy_alias, |
| 666 | 685 | noreturn_returned, |
| 686 | load_uninstantiable_type, | |
| 667 | 687 | |
| 668 | 688 | pub fn toStdLangDecl(id: SimplePanicId) StdLangDecl { |
| 669 | 689 | return switch (id) { |
| ... | ... | @@ -687,6 +707,7 @@ pub const SimplePanicId = enum { |
| 687 | 707 | .copy_len_mismatch => .@"panic.copyLenMismatch", |
| 688 | 708 | .memcpy_alias => .@"panic.memcpyAlias", |
| 689 | 709 | .noreturn_returned => .@"panic.noreturnReturned", |
| 710 | .load_uninstantiable_type => .@"panic.loadUninstantiableType", | |
| 690 | 711 | // zig fmt: on |
| 691 | 712 | }; |
| 692 | 713 | } |
| ... | ... | @@ -2808,13 +2829,13 @@ pub const LazySrcLoc = struct { |
| 2808 | 2829 | } |
| 2809 | 2830 | }; |
| 2810 | 2831 | |
| 2811 | pub const SemaError = error{ OutOfMemory, Canceled, AnalysisFail }; | |
| 2832 | pub const SemaError = error{ OutOfMemory, Canceled, AlreadyReported }; | |
| 2812 | 2833 | pub const CompileError = error{ |
| 2813 | 2834 | OutOfMemory, |
| 2814 | 2835 | /// The compilation update is no longer desired. |
| 2815 | 2836 | Canceled, |
| 2816 | 2837 | /// When this is returned, the compile error for the failure has already been recorded. |
| 2817 | AnalysisFail, | |
| 2838 | AlreadyReported, | |
| 2818 | 2839 | /// In a comptime scope, a return instruction was encountered. This error is only seen when |
| 2819 | 2840 | /// doing a comptime function call. |
| 2820 | 2841 | ComptimeReturn, |
| ... | ... | @@ -2825,6 +2846,11 @@ pub const CompileError = error{ |
| 2825 | 2846 | |
| 2826 | 2847 | pub fn init(zcu: *Zcu, gpa: Allocator, io: Io, thread_count: usize) !void { |
| 2827 | 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. | |
| 2853 | pub fn initAfterCompilation(zcu: *Zcu) void { | |
| 2828 | 2854 | zcu.initTracyPlots(); |
| 2829 | 2855 | } |
| 2830 | 2856 | |
| ... | ... | @@ -4273,7 +4299,7 @@ fn resolveReferencesInner(zcu: *Zcu) Allocator.Error!std.array_hash_map.Auto(Ana |
| 4273 | 4299 | const fqn_slice = nav.fqn.toSlice(ip); |
| 4274 | 4300 | if (comp.test_filters.len > 0) { |
| 4275 | 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 | 4303 | } else break :a false; |
| 4278 | 4304 | } |
| 4279 | 4305 | break :a true; |
| ... | ... | @@ -4597,6 +4623,7 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.lang.CallingConvention) union(enum) |
| 4597 | 4623 | .x86_64_regcall_v3_sysv, |
| 4598 | 4624 | .x86_64_regcall_v4_win, |
| 4599 | 4625 | .x86_64_interrupt, |
| 4626 | .x86_64_preserve_none, | |
| 4600 | 4627 | .x86_fastcall, |
| 4601 | 4628 | .x86_thiscall, |
| 4602 | 4629 | .x86_vectorcall, |
| ... | ... | @@ -4605,6 +4632,7 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.lang.CallingConvention) union(enum) |
| 4605 | 4632 | .x86_interrupt, |
| 4606 | 4633 | .aarch64_vfabi, |
| 4607 | 4634 | .aarch64_vfabi_sve, |
| 4635 | .aarch64_preserve_none, | |
| 4608 | 4636 | .arm_aapcs, |
| 4609 | 4637 | .csky_interrupt, |
| 4610 | 4638 | .riscv64_lp64_v, |
| ... | ... | @@ -4612,43 +4640,26 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.lang.CallingConvention) union(enum) |
| 4612 | 4640 | .m68k_rtd, |
| 4613 | 4641 | .m68k_interrupt, |
| 4614 | 4642 | .msp430_interrupt, |
| 4615 | => |opts| opts.incoming_stack_alignment == null, | |
| 4616 | ||
| 4617 | 4643 | .arm_aapcs_vfp, |
| 4618 | => |opts| opts.incoming_stack_alignment == null, | |
| 4619 | ||
| 4620 | 4644 | .arc_interrupt, |
| 4621 | => |opts| opts.incoming_stack_alignment == null, | |
| 4622 | ||
| 4623 | 4645 | .arm_interrupt, |
| 4624 | => |opts| opts.incoming_stack_alignment == null, | |
| 4625 | ||
| 4626 | 4646 | .microblaze_interrupt, |
| 4627 | => |opts| opts.incoming_stack_alignment == null, | |
| 4628 | ||
| 4629 | 4647 | .mips_interrupt, |
| 4630 | 4648 | .mips64_interrupt, |
| 4631 | => |opts| opts.incoming_stack_alignment == null, | |
| 4632 | ||
| 4633 | 4649 | .riscv32_interrupt, |
| 4634 | 4650 | .riscv64_interrupt, |
| 4635 | => |opts| opts.incoming_stack_alignment == null, | |
| 4636 | ||
| 4637 | 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 | |
| 4639 | 4657 | |
| 4640 | 4658 | .x86_sysv, |
| 4641 | 4659 | .x86_win, |
| 4660 | .x86_mingw, | |
| 4642 | 4661 | .x86_stdcall, |
| 4643 | => |opts| opts.incoming_stack_alignment == null and opts.register_params == 0, | |
| 4644 | ||
| 4645 | .avr_interrupt, | |
| 4646 | .avr_signal, | |
| 4647 | => true, | |
| 4648 | ||
| 4649 | .ez80_tiflags => true, | |
| 4650 | ||
| 4651 | .naked => true, | |
| 4662 | => |opts| opts.register_params == 0, // incoming stack alignment supported | |
| 4652 | 4663 | |
| 4653 | 4664 | else => false, |
| 4654 | 4665 | }; |
| ... | ... | @@ -4673,6 +4684,7 @@ pub fn callconvSupported(zcu: *Zcu, cc: std.lang.CallingConvention) union(enum) |
| 4673 | 4684 | .stage2_x86 => switch (cc) { |
| 4674 | 4685 | .x86_sysv, |
| 4675 | 4686 | .x86_win, |
| 4687 | .x86_mingw, | |
| 4676 | 4688 | => |opts| opts.incoming_stack_alignment == null and opts.register_params == 0, |
| 4677 | 4689 | .naked => true, |
| 4678 | 4690 | else => false, |
src/Zcu/PerThread.zig+96-93| ... | ... | @@ -320,7 +320,7 @@ pub fn update( |
| 320 | 320 | // Zig compilation pipeline. It selects some `AnalUnit` which we know needs to be analyzed, |
| 321 | 321 | // and analyzes it, which may in turn discover more `AnalUnit`s which we need to analyze. |
| 322 | 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 | 324 | .@"comptime" => |cu| pt.ensureComptimeUnitUpToDate(cu), |
| 325 | 325 | .nav_ty => |nav| pt.ensureNavTypeUpToDate(nav, null), |
| 326 | 326 | .nav_val => |nav| pt.ensureNavValUpToDate(nav, null), |
| ... | ... | @@ -332,7 +332,7 @@ pub fn update( |
| 332 | 332 | error.Canceled, |
| 333 | 333 | => |e| return e, |
| 334 | 334 | |
| 335 | error.AnalysisFail => {}, // already reported | |
| 335 | error.AnalysisFail => {}, | |
| 336 | 336 | }; |
| 337 | 337 | break :res pt.ensureStructDefaultsUpToDate(.fromInterned(ty), null); |
| 338 | 338 | }, |
| ... | ... | @@ -344,7 +344,7 @@ pub fn update( |
| 344 | 344 | error.Canceled, |
| 345 | 345 | => |e| return e, |
| 346 | 346 | |
| 347 | error.AnalysisFail => {}, // already reported | |
| 347 | error.AnalysisFail => {}, | |
| 348 | 348 | }; |
| 349 | 349 | } |
| 350 | 350 | } |
| ... | ... | @@ -455,7 +455,7 @@ fn detectEmbedFileUpdate(comp: *Compilation, tid: Zcu.PerThread.Id, ef_index: Zc |
| 455 | 455 | |
| 456 | 456 | /// Ensures that `file` has up-to-date ZIR. If not, loads the ZIR cache or runs |
| 457 | 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. | |
| 459 | 459 | pub fn updateFile( |
| 460 | 460 | pt: Zcu.PerThread, |
| 461 | 461 | file_index: Zcu.File.Index, |
| ... | ... | @@ -876,6 +876,7 @@ fn updateZirRefs(pt: Zcu.PerThread) (Io.Cancelable || Allocator.Error)!void { |
| 876 | 876 | const old_line = old_zir.getDeclaration(old_inst).src_line; |
| 877 | 877 | const new_line = new_zir.getDeclaration(new_inst).src_line; |
| 878 | 878 | if (old_line != new_line) { |
| 879 | comp.link_prog_node.increaseEstimatedTotalItems(1); | |
| 879 | 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 | 1036 | zcu.setFileRootType(file_index, wip.finish(ip, new_namespace_index)); |
| 1036 | 1037 | } |
| 1037 | 1038 | |
| 1039 | const UpdateUnitError = Allocator.Error || Io.Cancelable || error{ | |
| 1040 | /// Semantic analysis of this `AnalUnit` failed. | |
| 1041 | AnalysisFail, | |
| 1042 | }; | |
| 1043 | ||
| 1038 | 1044 | /// Ensures that all memoized state on `Zcu` is up-to-date, performing re-analysis if necessary. |
| 1039 | 1045 | /// Returns `error.AnalysisFail` if an analysis error is encountered; the caller is free to ignore |
| 1040 | 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 | 1049 | stage: InternPool.MemoizedStateStage, |
| 1044 | 1050 | /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`. |
| 1045 | 1051 | reason: ?*const Zcu.DependencyReason, |
| 1046 | ) Zcu.SemaError!void { | |
| 1052 | ) UpdateUnitError!void { | |
| 1047 | 1053 | const zcu = pt.zcu; |
| 1048 | 1054 | const gpa = zcu.gpa; |
| 1049 | 1055 | |
| ... | ... | @@ -1077,15 +1083,7 @@ pub fn ensureMemoizedStateUpToDate( |
| 1077 | 1083 | const any_changed: bool, const new_failed: bool = if (pt.analyzeMemoizedState(stage, reason)) |any_changed| |
| 1078 | 1084 | .{ any_changed or prev_failed, false } |
| 1079 | 1085 | else |err| switch (err) { |
| 1080 | error.AnalysisFail => res: { | |
| 1081 | if (!zcu.failed_analysis.contains(unit)) { | |
| 1082 | // If this unit caused the error, it would have an entry in `failed_analysis`. | |
| 1083 | // Since it does not, this must be a transitive failure. | |
| 1084 | try zcu.transitive_failed_analysis.put(gpa, unit, {}); | |
| 1085 | log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(unit)}); | |
| 1086 | } | |
| 1087 | break :res .{ !prev_failed, true }; | |
| 1088 | }, | |
| 1086 | error.AlreadyReported => .{ !prev_failed, true }, | |
| 1089 | 1087 | error.OutOfMemory => { |
| 1090 | 1088 | // TODO: same as for `ensureComptimeUnitUpToDate` etc |
| 1091 | 1089 | return error.OutOfMemory; |
| ... | ... | @@ -1153,7 +1151,7 @@ fn analyzeMemoizedState( |
| 1153 | 1151 | /// Ensures that the state of the given `ComptimeUnit` is fully up-to-date, performing re-analysis |
| 1154 | 1152 | /// if necessary. Returns `error.AnalysisFail` if an analysis error is encountered; the caller is |
| 1155 | 1153 | /// free to ignore this, since the error is already registered. |
| 1156 | pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu.SemaError!void { | |
| 1154 | pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) UpdateUnitError!void { | |
| 1157 | 1155 | const zcu = pt.zcu; |
| 1158 | 1156 | const gpa = zcu.gpa; |
| 1159 | 1157 | |
| ... | ... | @@ -1194,15 +1192,7 @@ pub fn ensureComptimeUnitUpToDate(pt: Zcu.PerThread, cu_id: InternPool.ComptimeU |
| 1194 | 1192 | defer unit_tracking.end(zcu); |
| 1195 | 1193 | |
| 1196 | 1194 | return pt.analyzeComptimeUnit(cu_id) catch |err| switch (err) { |
| 1197 | error.AnalysisFail => { | |
| 1198 | if (!zcu.failed_analysis.contains(anal_unit)) { | |
| 1199 | // If this unit caused the error, it would have an entry in `failed_analysis`. | |
| 1200 | // Since it does not, this must be a transitive failure. | |
| 1201 | try zcu.transitive_failed_analysis.put(gpa, anal_unit, {}); | |
| 1202 | log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(anal_unit)}); | |
| 1203 | } | |
| 1204 | return error.AnalysisFail; | |
| 1205 | }, | |
| 1195 | error.AlreadyReported => return error.AnalysisFail, | |
| 1206 | 1196 | error.OutOfMemory => { |
| 1207 | 1197 | // TODO: it's unclear how to gracefully handle this. |
| 1208 | 1198 | // 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 | 1210 | |
| 1221 | 1211 | /// Re-analyzes a `ComptimeUnit`. The unit has already been determined to be out-of-date, and old |
| 1222 | 1212 | /// side effects (exports/references/etc) have been dropped. If semantic analysis fails, this |
| 1223 | /// function will return `error.AnalysisFail`, and it is the caller's reponsibility to add an entry | |
| 1224 | /// to `transitive_failed_analysis` if necessary. | |
| 1213 | /// function will return `error.AlreadyReported`. | |
| 1225 | 1214 | fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu.CompileError!void { |
| 1226 | 1215 | const zcu = pt.zcu; |
| 1227 | 1216 | const ip = &zcu.intern_pool; |
| ... | ... | @@ -1238,7 +1227,14 @@ fn analyzeComptimeUnit(pt: Zcu.PerThread, cu_id: InternPool.ComptimeUnit.Id) Zcu |
| 1238 | 1227 | defer tracy_trace.end(); |
| 1239 | 1228 | tracy_trace.addTextFmt("cu_id={d}", .{cu_id}); |
| 1240 | 1229 | |
| 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 | 1238 | const file = zcu.fileByIndex(inst_resolved.file); |
| 1243 | 1239 | const zir = file.zir.?; |
| 1244 | 1240 | |
| ... | ... | @@ -1313,7 +1309,7 @@ pub fn ensureTypeLayoutUpToDate( |
| 1313 | 1309 | ty: Type, |
| 1314 | 1310 | /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`. |
| 1315 | 1311 | reason: ?*const Zcu.DependencyReason, |
| 1316 | ) Zcu.SemaError!void { | |
| 1312 | ) UpdateUnitError!void { | |
| 1317 | 1313 | const zcu = pt.zcu; |
| 1318 | 1314 | const ip = &zcu.intern_pool; |
| 1319 | 1315 | const comp = zcu.comp; |
| ... | ... | @@ -1398,15 +1394,7 @@ pub fn ensureTypeLayoutUpToDate( |
| 1398 | 1394 | const new_failed: bool = if (result) failed: { |
| 1399 | 1395 | break :failed false; |
| 1400 | 1396 | } else |err| switch (err) { |
| 1401 | error.AnalysisFail => failed: { | |
| 1402 | if (!zcu.failed_analysis.contains(anal_unit)) { | |
| 1403 | // If this unit caused the error, it would have an entry in `failed_analysis`. | |
| 1404 | // Since it does not, this must be a transitive failure. | |
| 1405 | try zcu.transitive_failed_analysis.put(gpa, anal_unit, {}); | |
| 1406 | log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(anal_unit)}); | |
| 1407 | } | |
| 1408 | break :failed true; | |
| 1409 | }, | |
| 1397 | error.AlreadyReported => true, | |
| 1410 | 1398 | error.OutOfMemory, |
| 1411 | 1399 | error.Canceled, |
| 1412 | 1400 | => |e| return e, |
| ... | ... | @@ -1441,7 +1429,7 @@ pub fn ensureStructDefaultsUpToDate( |
| 1441 | 1429 | ty: Type, |
| 1442 | 1430 | /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`. |
| 1443 | 1431 | reason: ?*const Zcu.DependencyReason, |
| 1444 | ) Zcu.SemaError!void { | |
| 1432 | ) UpdateUnitError!void { | |
| 1445 | 1433 | const zcu = pt.zcu; |
| 1446 | 1434 | const ip = &zcu.intern_pool; |
| 1447 | 1435 | const comp = zcu.comp; |
| ... | ... | @@ -1512,15 +1500,7 @@ pub fn ensureStructDefaultsUpToDate( |
| 1512 | 1500 | const new_failed: bool = if (Sema.type_resolution.resolveStructDefaults(&sema, ty)) failed: { |
| 1513 | 1501 | break :failed false; |
| 1514 | 1502 | } else |err| switch (err) { |
| 1515 | error.AnalysisFail => failed: { | |
| 1516 | if (!zcu.failed_analysis.contains(anal_unit)) { | |
| 1517 | // If this unit caused the error, it would have an entry in `failed_analysis`. | |
| 1518 | // Since it does not, this must be a transitive failure. | |
| 1519 | try zcu.transitive_failed_analysis.put(gpa, anal_unit, {}); | |
| 1520 | log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(anal_unit)}); | |
| 1521 | } | |
| 1522 | break :failed true; | |
| 1523 | }, | |
| 1503 | error.AlreadyReported => true, | |
| 1524 | 1504 | error.OutOfMemory, |
| 1525 | 1505 | error.Canceled, |
| 1526 | 1506 | => |e| return e, |
| ... | ... | @@ -1546,7 +1526,7 @@ pub fn ensureNavValUpToDate( |
| 1546 | 1526 | nav_id: InternPool.Nav.Index, |
| 1547 | 1527 | /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`. |
| 1548 | 1528 | reason: ?*const Zcu.DependencyReason, |
| 1549 | ) Zcu.SemaError!void { | |
| 1529 | ) UpdateUnitError!void { | |
| 1550 | 1530 | const zcu = pt.zcu; |
| 1551 | 1531 | const gpa = zcu.gpa; |
| 1552 | 1532 | const ip = &zcu.intern_pool; |
| ... | ... | @@ -1593,15 +1573,7 @@ pub fn ensureNavValUpToDate( |
| 1593 | 1573 | false, |
| 1594 | 1574 | }; |
| 1595 | 1575 | } else |err| switch (err) { |
| 1596 | error.AnalysisFail => res: { | |
| 1597 | if (!zcu.failed_analysis.contains(anal_unit)) { | |
| 1598 | // If this unit caused the error, it would have an entry in `failed_analysis`. | |
| 1599 | // Since it does not, this must be a transitive failure. | |
| 1600 | try zcu.transitive_failed_analysis.put(gpa, anal_unit, {}); | |
| 1601 | log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(anal_unit)}); | |
| 1602 | } | |
| 1603 | break :res .{ !prev_failed, true }; | |
| 1604 | }, | |
| 1576 | error.AlreadyReported => .{ !prev_failed, true }, | |
| 1605 | 1577 | error.OutOfMemory => { |
| 1606 | 1578 | // TODO: it's unclear how to gracefully handle this. |
| 1607 | 1579 | // To report the error cleanly, we need to add a message to `failed_analysis` and a |
| ... | ... | @@ -1654,7 +1626,14 @@ fn analyzeNavVal( |
| 1654 | 1626 | tracy_trace.addText(old_nav.fqn.toSlice(ip)); |
| 1655 | 1627 | tracy_trace.addTextFmt("nav_id={d}", .{nav_id}); |
| 1656 | 1628 | |
| 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 | 1637 | const file = zcu.fileByIndex(inst_resolved.file); |
| 1659 | 1638 | const zir = file.zir.?; |
| 1660 | 1639 | const zir_decl = zir.getDeclaration(inst_resolved.inst); |
| ... | ... | @@ -1915,7 +1894,7 @@ pub fn ensureNavTypeUpToDate( |
| 1915 | 1894 | nav_id: InternPool.Nav.Index, |
| 1916 | 1895 | /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`. |
| 1917 | 1896 | reason: ?*const Zcu.DependencyReason, |
| 1918 | ) Zcu.SemaError!void { | |
| 1897 | ) UpdateUnitError!void { | |
| 1919 | 1898 | const zcu = pt.zcu; |
| 1920 | 1899 | const gpa = zcu.gpa; |
| 1921 | 1900 | const ip = &zcu.intern_pool; |
| ... | ... | @@ -1962,15 +1941,7 @@ pub fn ensureNavTypeUpToDate( |
| 1962 | 1941 | false, |
| 1963 | 1942 | }; |
| 1964 | 1943 | } else |err| switch (err) { |
| 1965 | error.AnalysisFail => res: { | |
| 1966 | if (!zcu.failed_analysis.contains(anal_unit)) { | |
| 1967 | // If this unit caused the error, it would have an entry in `failed_analysis`. | |
| 1968 | // Since it does not, this must be a transitive failure. | |
| 1969 | try zcu.transitive_failed_analysis.put(gpa, anal_unit, {}); | |
| 1970 | log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(anal_unit)}); | |
| 1971 | } | |
| 1972 | break :res .{ !prev_failed, true }; | |
| 1973 | }, | |
| 1944 | error.AlreadyReported => .{ !prev_failed, true }, | |
| 1974 | 1945 | error.OutOfMemory => { |
| 1975 | 1946 | // TODO: it's unclear how to gracefully handle this. |
| 1976 | 1947 | // To report the error cleanly, we need to add a message to `failed_analysis` and a |
| ... | ... | @@ -2023,7 +1994,14 @@ fn analyzeNavType( |
| 2023 | 1994 | tracy_trace.addText(old_nav.fqn.toSlice(ip)); |
| 2024 | 1995 | tracy_trace.addTextFmt("nav_id={d}", .{nav_id}); |
| 2025 | 1996 | |
| 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 | 2005 | const file = zcu.fileByIndex(inst_resolved.file); |
| 2028 | 2006 | const zir = file.zir.?; |
| 2029 | 2007 | |
| ... | ... | @@ -2159,7 +2137,7 @@ pub fn ensureFuncBodyUpToDate( |
| 2159 | 2137 | func_index: InternPool.Index, |
| 2160 | 2138 | /// `null` is valid only for the "root" analysis, i.e. called from `Compilation.processOneJob`. |
| 2161 | 2139 | reason: ?*const Zcu.DependencyReason, |
| 2162 | ) Zcu.SemaError!void { | |
| 2140 | ) UpdateUnitError!void { | |
| 2163 | 2141 | dev.check(.sema); |
| 2164 | 2142 | |
| 2165 | 2143 | const zcu = pt.zcu; |
| ... | ... | @@ -2203,18 +2181,10 @@ pub fn ensureFuncBodyUpToDate( |
| 2203 | 2181 | const ies_outdated, const new_failed = if (pt.analyzeFuncBody(func_index, reason)) |result| |
| 2204 | 2182 | .{ prev_failed or result.ies_outdated, false } |
| 2205 | 2183 | else |err| switch (err) { |
| 2206 | error.AnalysisFail => res: { | |
| 2207 | if (!zcu.failed_analysis.contains(anal_unit)) { | |
| 2208 | // If this function caused the error, it would have an entry in `failed_analysis`. | |
| 2209 | // Since it does not, this must be a transitive failure. | |
| 2210 | try zcu.transitive_failed_analysis.put(gpa, anal_unit, {}); | |
| 2211 | log.debug("mark transitive analysis failure for {f}", .{zcu.fmtAnalUnit(anal_unit)}); | |
| 2212 | } | |
| 2213 | // We consider the IES to be outdated if the function previously succeeded analysis; in this case, | |
| 2214 | // we need to re-analyze dependants to ensure they hit a transitive error here, rather than reporting | |
| 2215 | // a different error later (which may now be invalid). | |
| 2216 | break :res .{ !prev_failed, true }; | |
| 2217 | }, | |
| 2184 | // We consider the IES to be outdated if the function previously succeeded analysis; in this case, | |
| 2185 | // we need to re-analyze dependants to ensure they hit a transitive error here, rather than reporting | |
| 2186 | // a different error later (which may now be invalid). | |
| 2187 | error.AlreadyReported => .{ !prev_failed, true }, | |
| 2218 | 2188 | error.OutOfMemory => { |
| 2219 | 2189 | // TODO: it's unclear how to gracefully handle this. |
| 2220 | 2190 | // To report the error cleanly, we need to add a message to `failed_analysis` and a |
| ... | ... | @@ -3206,7 +3176,7 @@ const ScanDeclIter = struct { |
| 3206 | 3176 | if (is_named and comp.test_filters.len > 0) { |
| 3207 | 3177 | const fqn_slice = fqn.toSlice(ip); |
| 3208 | 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 | 3180 | } else break :a false; |
| 3211 | 3181 | } |
| 3212 | 3182 | try zcu.test_functions.put(gpa, nav, {}); |
| ... | ... | @@ -3292,9 +3262,7 @@ fn analyzeFuncBodyInner( |
| 3292 | 3262 | defer sema.deinit(); |
| 3293 | 3263 | |
| 3294 | 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 | 3265 | try sema.declareDependency(.{ .src_hash = decl_analysis.zir_index }); |
| 3297 | try sema.declareDependency(.{ .nav_val = func.owner_nav }); | |
| 3298 | 3266 | |
| 3299 | 3267 | // Make sure that the declaration `Nav` still refers to this function (or its generic owner). |
| 3300 | 3268 | // 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 | 3273 | // If we *are* still owned by the right NAV, this analysis updates `zir_body_inst` if necessary. |
| 3306 | 3274 | |
| 3307 | 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 | 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 | 3284 | } else { |
| 3313 | 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 | 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 | } |
| 3319 | 3295 | |
| ... | ... | @@ -3343,7 +3319,9 @@ fn analyzeFuncBodyInner( |
| 3343 | 3319 | }; |
| 3344 | 3320 | defer inner_block.instructions.deinit(gpa); |
| 3345 | 3321 | |
| 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 | }); | |
| 3347 | 3325 | |
| 3348 | 3326 | // Here we are performing "runtime semantic analysis" for a function body, which means |
| 3349 | 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 | 3498 | return pt.getErrorValue(try pt.zcu.intern_pool.getOrPutString(gpa, io, name)); |
| 3521 | 3499 | } |
| 3522 | 3500 | |
| 3501 | /// Asserts that `slice.len` is *not* undef. | |
| 3502 | pub 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 | 3520 | /// Removes any entry from `Zcu.failed_files` associated with `file`. Acquires `Compilation.mutex` as needed. |
| 3524 | 3521 | /// `file.zir` must be unchanged from the last update, as it is used to determine if there is such an entry. |
| 3525 | 3522 | fn 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 | 4374 | return result.index; |
| 4378 | 4375 | } |
| 4379 | 4376 | |
| 4377 | const 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 | 4383 | /// Given a namespace, re-scan its declarations from the type definition if they have not |
| 4381 | 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 | 4386 | /// This will effectively short-circuit the caller, which will be semantic analysis of a |
| 4384 | 4387 | /// guaranteed-unreferenced `AnalUnit`, to trigger a transitive analysis error. |
| 4385 | pub fn ensureNamespaceUpToDate(pt: Zcu.PerThread, namespace_index: Zcu.Namespace.Index) Zcu.SemaError!void { | |
| 4388 | pub fn ensureNamespaceUpToDate(pt: Zcu.PerThread, namespace_index: Zcu.Namespace.Index) UpdateNamespaceError!void { | |
| 4386 | 4389 | const zcu = pt.zcu; |
| 4387 | 4390 | const ip = &zcu.intern_pool; |
| 4388 | 4391 | const namespace = zcu.namespacePtr(namespace_index); |
| ... | ... | @@ -4409,7 +4412,7 @@ pub fn ensureNamespaceUpToDate(pt: Zcu.PerThread, namespace_index: Zcu.Namespace |
| 4409 | 4412 | |
| 4410 | 4413 | // Namespace outdated -- re-scan the type if necessary. |
| 4411 | 4414 | |
| 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 | 4416 | const file = zcu.fileByIndex(inst_info.file); |
| 4414 | 4417 | const zir = &file.zir.?; |
| 4415 | 4418 |
src/codegen.zig+196-30| ... | ... | @@ -767,11 +767,9 @@ fn lowerNavRef( |
| 767 | 767 | offset: u64, |
| 768 | 768 | ) (Error || std.Io.Writer.Error)!void { |
| 769 | 769 | const zcu = pt.zcu; |
| 770 | const gpa = zcu.gpa; | |
| 771 | 770 | const ip = &zcu.intern_pool; |
| 772 | 771 | const target = &zcu.navFileScope(nav_index).mod.?.resolved_target.result; |
| 773 | 772 | const ptr_width_bytes = @divExact(target.ptrBitWidth(), 8); |
| 774 | const is_obj = lf.comp.config.output_mode == .Obj; | |
| 775 | 773 | const nav_ty = Type.fromInterned(ip.getNav(nav_index).resolved.?.type); |
| 776 | 774 | |
| 777 | 775 | if (!nav_ty.isRuntimeFnOrHasRuntimeBits(zcu) and ip.getNav(nav_index).getExtern(ip) == null) { |
| ... | ... | @@ -786,34 +784,7 @@ fn lowerNavRef( |
| 786 | 784 | dev.check(link.File.Tag.wasm.devFeature()); |
| 787 | 785 | const wasm = lf.cast(.wasm).?; |
| 788 | 786 | assert(reloc_parent == .none); |
| 789 | if (nav_ty.zigTypeTag(zcu) == .@"fn") { | |
| 790 | const gop = try wasm.zcu_indirect_function_set.getOrPut(gpa, nav_index); | |
| 791 | if (!gop.found_existing) gop.value_ptr.* = {}; | |
| 792 | if (is_obj) { | |
| 793 | @panic("TODO add out_reloc for this"); | |
| 794 | } else { | |
| 795 | try wasm.func_table_fixups.append(gpa, .{ | |
| 796 | .table_index = @fromBackingInt(@intCast(gop.index)), | |
| 797 | .offset = @intCast(w.end), | |
| 798 | }); | |
| 799 | } | |
| 800 | } else { | |
| 801 | if (is_obj) { | |
| 802 | try wasm.out_relocs.append(gpa, .{ | |
| 803 | .offset = @intCast(w.end), | |
| 804 | .pointee = .{ .symbol_index = try wasm.navSymbolIndex(nav_index) }, | |
| 805 | .tag = if (ptr_width_bytes == 4) .memory_addr_i32 else .memory_addr_i64, | |
| 806 | .addend = @intCast(offset), | |
| 807 | }); | |
| 808 | } else { | |
| 809 | try wasm.nav_fixups.ensureUnusedCapacity(gpa, 1); | |
| 810 | wasm.nav_fixups.appendAssumeCapacity(.{ | |
| 811 | .navs_exe_index = try wasm.refNavExe(nav_index), | |
| 812 | .offset = @intCast(w.end), | |
| 813 | .addend = @intCast(offset), | |
| 814 | }); | |
| 815 | } | |
| 816 | } | |
| 787 | try wasm.addNavReloc(w.end, nav_index, nav_ty, @intCast(offset)); | |
| 817 | 788 | try w.splatByteAll(0, ptr_width_bytes); |
| 818 | 789 | return; |
| 819 | 790 | }, |
| ... | ... | @@ -1124,6 +1095,201 @@ pub fn fieldOffset(ptr_agg_ty: Type, ptr_field_ty: Type, field_index: u32, zcu: |
| 1124 | 1095 | }; |
| 1125 | 1096 | } |
| 1126 | 1097 | |
| 1098 | pub const FlattenedItem = struct { offset: u64, type: ?Type }; | |
| 1099 | pub 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 | ||
| 1127 | 1293 | test { |
| 1128 | 1294 | _ = aarch64; |
| 1129 | 1295 | } |
src/codegen/aarch64/Assemble.zig+1-1| ... | ... | @@ -163,7 +163,7 @@ const matchers = matchers: { |
| 163 | 163 | arg.* = zonCast(param_type.?, instruction.encode[encode_index], symbols); |
| 164 | 164 | return @call(.auto, encode, args); |
| 165 | 165 | } else if (pattern_token[0] == '<') { |
| 166 | const symbol_name = comptime pattern_token[1 .. std.mem.indexOfScalarPos(u8, pattern_token, 1, '|') orelse | |
| 166 | const symbol_name = comptime pattern_token[1 .. std.mem.findScalarPos(u8, pattern_token, 1, '|') orelse | |
| 167 | 167 | pattern_token.len - 1]; |
| 168 | 168 | const symbol = @field(Symbol, symbol_name); |
| 169 | 169 | const symbol_ptr = &@field(symbols, symbol_name); |
src/codegen/aarch64/Mir.zig+2-2| ... | ... | @@ -70,8 +70,8 @@ pub fn emit( |
| 70 | 70 | |
| 71 | 71 | const func_align = switch (nav.resolved.?.@"align") { |
| 72 | 72 | .none => switch (mod.optimize_mode) { |
| 73 | .Debug, .ReleaseSafe, .ReleaseFast => target_util.defaultFunctionAlignment(target), | |
| 74 | .ReleaseSmall => target_util.minFunctionAlignment(target), | |
| 73 | .debug, .safe, .fast => target_util.defaultFunctionAlignment(target), | |
| 74 | .small => target_util.minFunctionAlignment(target), | |
| 75 | 75 | }, |
| 76 | 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 | 2099 | 32 => "truncf", |
| 2100 | 2100 | 64 => "trunc", |
| 2101 | 2101 | 80 => "__truncx", |
| 2102 | 128 => "truncq", | |
| 2102 | 128 => "truncf128", | |
| 2103 | 2103 | }, |
| 2104 | 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 | 2113 | 32 => "floorf", |
| 2114 | 2114 | 64 => "floor", |
| 2115 | 2115 | 80 => "__floorx", |
| 2116 | 128 => "floorq", | |
| 2116 | 128 => "floorf128", | |
| 2117 | 2117 | }, |
| 2118 | 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 | 2431 | 32 => "fmodf", |
| 2432 | 2432 | 64 => "fmod", |
| 2433 | 2433 | 80 => "__fmodx", |
| 2434 | 128 => "fmodq", | |
| 2434 | 128 => "fmodf128", | |
| 2435 | 2435 | }, |
| 2436 | 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 | 2599 | 32 => "fmaxf", |
| 2600 | 2600 | 64 => "fmax", |
| 2601 | 2601 | 80 => "__fmaxx", |
| 2602 | 128 => "fmaxq", | |
| 2602 | 128 => "fmaxf128", | |
| 2603 | 2603 | }, |
| 2604 | 2604 | .min => switch (bits) { |
| 2605 | 2605 | else => unreachable, |
| ... | ... | @@ -2607,7 +2607,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 2607 | 2607 | 32 => "fminf", |
| 2608 | 2608 | 64 => "fmin", |
| 2609 | 2609 | 80 => "__fminx", |
| 2610 | 128 => "fminq", | |
| 2610 | 128 => "fminf128", | |
| 2611 | 2611 | }, |
| 2612 | 2612 | }, |
| 2613 | 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 | 2856 | const remaining_source = std.mem.span(as.source); |
| 2857 | 2857 | return isel.fail("unable to assemble: '{s}'", .{std.mem.trim( |
| 2858 | 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 | 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 | 4055 | 32 => "sqrtf", |
| 4056 | 4056 | 64 => "sqrt", |
| 4057 | 4057 | 80 => "__sqrtx", |
| 4058 | 128 => "sqrtq", | |
| 4058 | 128 => "sqrtf128", | |
| 4059 | 4059 | }, |
| 4060 | 4060 | .floor => switch (bits) { |
| 4061 | 4061 | else => unreachable, |
| ... | ... | @@ -4063,7 +4063,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 4063 | 4063 | 32 => "floorf", |
| 4064 | 4064 | 64 => "floor", |
| 4065 | 4065 | 80 => "__floorx", |
| 4066 | 128 => "floorq", | |
| 4066 | 128 => "floorf128", | |
| 4067 | 4067 | }, |
| 4068 | 4068 | .ceil => switch (bits) { |
| 4069 | 4069 | else => unreachable, |
| ... | ... | @@ -4071,7 +4071,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 4071 | 4071 | 32 => "ceilf", |
| 4072 | 4072 | 64 => "ceil", |
| 4073 | 4073 | 80 => "__ceilx", |
| 4074 | 128 => "ceilq", | |
| 4074 | 128 => "ceilf128", | |
| 4075 | 4075 | }, |
| 4076 | 4076 | .round => switch (bits) { |
| 4077 | 4077 | else => unreachable, |
| ... | ... | @@ -4079,7 +4079,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 4079 | 4079 | 32 => "roundf", |
| 4080 | 4080 | 64 => "round", |
| 4081 | 4081 | 80 => "__roundx", |
| 4082 | 128 => "roundq", | |
| 4082 | 128 => "roundf128", | |
| 4083 | 4083 | }, |
| 4084 | 4084 | .trunc_float => switch (bits) { |
| 4085 | 4085 | else => unreachable, |
| ... | ... | @@ -4087,7 +4087,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 4087 | 4087 | 32 => "truncf", |
| 4088 | 4088 | 64 => "trunc", |
| 4089 | 4089 | 80 => "__truncx", |
| 4090 | 128 => "truncq", | |
| 4090 | 128 => "truncf128", | |
| 4091 | 4091 | }, |
| 4092 | 4092 | }, |
| 4093 | 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 | 4147 | 32 => "sinf", |
| 4148 | 4148 | 64 => "sin", |
| 4149 | 4149 | 80 => "__sinx", |
| 4150 | 128 => "sinq", | |
| 4150 | 128 => "sinf128", | |
| 4151 | 4151 | }, |
| 4152 | 4152 | .cos => switch (bits) { |
| 4153 | 4153 | else => unreachable, |
| ... | ... | @@ -4155,7 +4155,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 4155 | 4155 | 32 => "cosf", |
| 4156 | 4156 | 64 => "cos", |
| 4157 | 4157 | 80 => "__cosx", |
| 4158 | 128 => "cosq", | |
| 4158 | 128 => "cosf128", | |
| 4159 | 4159 | }, |
| 4160 | 4160 | .tan => switch (bits) { |
| 4161 | 4161 | else => unreachable, |
| ... | ... | @@ -4163,7 +4163,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 4163 | 4163 | 32 => "tanf", |
| 4164 | 4164 | 64 => "tan", |
| 4165 | 4165 | 80 => "__tanx", |
| 4166 | 128 => "tanq", | |
| 4166 | 128 => "tanf128", | |
| 4167 | 4167 | }, |
| 4168 | 4168 | .exp => switch (bits) { |
| 4169 | 4169 | else => unreachable, |
| ... | ... | @@ -4171,7 +4171,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 4171 | 4171 | 32 => "expf", |
| 4172 | 4172 | 64 => "exp", |
| 4173 | 4173 | 80 => "__expx", |
| 4174 | 128 => "expq", | |
| 4174 | 128 => "expf128", | |
| 4175 | 4175 | }, |
| 4176 | 4176 | .exp2 => switch (bits) { |
| 4177 | 4177 | else => unreachable, |
| ... | ... | @@ -4179,7 +4179,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 4179 | 4179 | 32 => "exp2f", |
| 4180 | 4180 | 64 => "exp2", |
| 4181 | 4181 | 80 => "__exp2x", |
| 4182 | 128 => "exp2q", | |
| 4182 | 128 => "exp2f128", | |
| 4183 | 4183 | }, |
| 4184 | 4184 | .log => switch (bits) { |
| 4185 | 4185 | else => unreachable, |
| ... | ... | @@ -4187,7 +4187,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 4187 | 4187 | 32 => "logf", |
| 4188 | 4188 | 64 => "log", |
| 4189 | 4189 | 80 => "__logx", |
| 4190 | 128 => "logq", | |
| 4190 | 128 => "logf128", | |
| 4191 | 4191 | }, |
| 4192 | 4192 | .log2 => switch (bits) { |
| 4193 | 4193 | else => unreachable, |
| ... | ... | @@ -4195,7 +4195,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 4195 | 4195 | 32 => "log2f", |
| 4196 | 4196 | 64 => "log2", |
| 4197 | 4197 | 80 => "__log2x", |
| 4198 | 128 => "log2q", | |
| 4198 | 128 => "log2f128", | |
| 4199 | 4199 | }, |
| 4200 | 4200 | .log10 => switch (bits) { |
| 4201 | 4201 | else => unreachable, |
| ... | ... | @@ -4203,7 +4203,7 @@ pub fn body(isel: *Select, air_body: []const Air.Inst.Index) error{ OutOfMemory, |
| 4203 | 4203 | 32 => "log10f", |
| 4204 | 4204 | 64 => "log10", |
| 4205 | 4205 | 80 => "__log10x", |
| 4206 | 128 => "log10q", | |
| 4206 | 128 => "log10f128", | |
| 4207 | 4207 | }, |
| 4208 | 4208 | }, |
| 4209 | 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 | 7118 | 32 => "fmaf", |
| 7119 | 7119 | 64 => "fma", |
| 7120 | 7120 | 80 => "__fmax", |
| 7121 | 128 => "fmaq", | |
| 7121 | 128 => "fmaf128", | |
| 7122 | 7122 | }, |
| 7123 | 7123 | .reloc = .{ .label = @intCast(isel.instructions.items.len) }, |
| 7124 | 7124 | }); |
| ... | ... | @@ -12176,9 +12176,7 @@ pub const CallAbiIterator = struct { |
| 12176 | 12176 | const loaded_struct = ip.loadStructType(ty.toIntern()); |
| 12177 | 12177 | switch (loaded_struct.layout) { |
| 12178 | 12178 | .auto, .@"extern" => {}, |
| 12179 | .@"packed" => continue :type_key .{ | |
| 12180 | .int_type = ip.indexToKey(loaded_struct.packed_backing_int_type).int_type, | |
| 12181 | }, | |
| 12179 | .@"packed" => continue :type_key ip.indexToKey(loaded_struct.packed_backing_int_type), | |
| 12182 | 12180 | } |
| 12183 | 12181 | const size = wip_vi.size(isel); |
| 12184 | 12182 | if (size <= 16 * 4) homogeneous_aggregate: { |
| ... | ... | @@ -12300,9 +12298,7 @@ pub const CallAbiIterator = struct { |
| 12300 | 12298 | } |
| 12301 | 12299 | }, |
| 12302 | 12300 | .opaque_type, .func_type => continue :type_key .{ .simple_type = .anyopaque }, |
| 12303 | .enum_type => continue :type_key .{ | |
| 12304 | .int_type = ip.indexToKey(ip.loadEnumType(ty.toIntern()).int_tag_type).int_type, | |
| 12305 | }, | |
| 12301 | .enum_type => continue :type_key ip.indexToKey(ip.loadEnumType(ty.toIntern()).int_tag_type), | |
| 12306 | 12302 | .error_set_type, |
| 12307 | 12303 | .inferred_error_set_type, |
| 12308 | 12304 | => continue :type_key .{ .simple_type = .anyerror }, |
| ... | ... | @@ -12388,7 +12384,7 @@ pub const CallAbiIterator = struct { |
| 12388 | 12384 | .f32 => .single, |
| 12389 | 12385 | .f64 => .double, |
| 12390 | 12386 | .f128 => .quad, |
| 12391 | .c_longdouble => switch (zcu.getTarget().cTypeBitSize(.longdouble)) { | |
| 12387 | .c_longdouble => switch (zcu.getTarget().cTypeBitSize(.longdouble).?) { | |
| 12392 | 12388 | else => unreachable, |
| 12393 | 12389 | 64 => .double, |
| 12394 | 12390 | 80 => null, |
src/codegen/aarch64/abi.zig+7-2| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | const assert = @import("std").debug.assert; | |
| 1 | const assert = std.debug.assert; | |
| 2 | 2 | const std = @import("std"); |
| 3 | 3 | const InternPool = @import("../../InternPool.zig"); |
| 4 | 4 | const Type = @import("../../Type.zig"); |
| ... | ... | @@ -35,7 +35,12 @@ pub fn classifyType(ty: Type, zcu: *Zcu) Class { |
| 35 | 35 | if (bit_size > 64) return .double_integer; |
| 36 | 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 | 44 | .vector => { |
| 40 | 45 | const bit_size = ty.bitSize(zcu); |
| 41 | 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 | 39 | const float_count = countFloats(ty, zcu, &maybe_float_bits); |
| 40 | 40 | if (float_count <= byval_float_count) return .byval; |
| 41 | 41 | |
| 42 | if (ty.abiAlignment(zcu).compare(.gt, .@"32")) { | |
| 42 | if (ty.abiAlignment(zcu).compare(.gt, .@"4")) { | |
| 43 | 43 | return Class.arrSize(bit_size, 64); |
| 44 | 44 | } |
| 45 | 45 | |
| ... | ... | @@ -62,7 +62,7 @@ pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class { |
| 62 | 62 | const float_count = countFloats(ty, zcu, &maybe_float_bits); |
| 63 | 63 | if (float_count <= byval_float_count) return .byval; |
| 64 | 64 | |
| 65 | if (union_obj.alignment.compareStrict(.gt, .@"32")) { | |
| 65 | if (union_obj.alignment.compareStrict(.gt, .@"4")) { | |
| 66 | 66 | return Class.arrSize(bit_size, 64); |
| 67 | 67 | } |
| 68 | 68 | |
| ... | ... | @@ -73,14 +73,16 @@ pub fn classifyType(ty: Type, zcu: *Zcu, ctx: Context) Class { |
| 73 | 73 | } |
| 74 | 74 | return Class.arrSize(bit_size, 32); |
| 75 | 75 | }, |
| 76 | .bool, .float => return .byval, | |
| 76 | .bool => return .byval, | |
| 77 | 77 | .int => { |
| 78 | // TODO this is incorrect for _BitInt(128) but implementing | |
| 79 | // this correctly makes implementing compiler-rt impossible. | |
| 80 | // const bit_size = ty.bitSize(zcu); | |
| 81 | // if (bit_size > 64) return .memory; | |
| 78 | if (ctx == .ret and ty.intInfo(zcu).bits > 64) return .memory; | |
| 82 | 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 | 86 | .@"enum", .error_set => { |
| 85 | 87 | const bit_size = ty.bitSize(zcu); |
| 86 | 88 | if (bit_size > 64) return .memory; |
src/codegen/c.zig+751-610| ... | ... | @@ -164,7 +164,8 @@ const BlockData = struct { |
| 164 | 164 | |
| 165 | 165 | const LocalType = struct { |
| 166 | 166 | type: Type, |
| 167 | alignment: Alignment, | |
| 167 | alignment: Alignment = .none, | |
| 168 | array_len: u2 = 1, | |
| 168 | 169 | }; |
| 169 | 170 | |
| 170 | 171 | const LocalIndex = u16; |
| ... | ... | @@ -184,13 +185,11 @@ const ValueRenderLocation = enum { |
| 184 | 185 | } |
| 185 | 186 | }; |
| 186 | 187 | |
| 187 | const BuiltinInfo = enum { none, bits }; | |
| 188 | const BuiltinInfo = enum { none, bits, bits_none, big_temp_bits }; | |
| 188 | 189 | |
| 189 | 190 | const reserved_idents = std.StaticStringMap(void).initComptime(.{ |
| 190 | 191 | // C language |
| 191 | .{ "alignas", { | |
| 192 | @setEvalBranchQuota(4000); | |
| 193 | } }, | |
| 192 | .{ "alignas", {} }, | |
| 194 | 193 | .{ "alignof", {} }, |
| 195 | 194 | .{ "asm", {} }, |
| 196 | 195 | .{ "atomic_bool", {} }, |
| ... | ... | @@ -302,7 +301,100 @@ const reserved_idents = std.StaticStringMap(void).initComptime(.{ |
| 302 | 301 | // stddef.h |
| 303 | 302 | .{ "offsetof", {} }, |
| 304 | 303 | |
| 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 | 382 | // 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 | 398 | .{ "max", {} }, |
| 307 | 399 | .{ "min", {} }, |
| 308 | 400 | }); |
| ... | ... | @@ -316,13 +408,6 @@ fn isReservedIdent(ident: []const u8) bool { |
| 316 | 408 | } |
| 317 | 409 | } |
| 318 | 410 | |
| 319 | // windows.h | |
| 320 | if (mem.startsWith(u8, ident, "DUMMYSTRUCTNAME") or | |
| 321 | mem.startsWith(u8, ident, "DUMMYUNIONNAME")) | |
| 322 | { | |
| 323 | return true; | |
| 324 | } | |
| 325 | ||
| 326 | 411 | // CType |
| 327 | 412 | if (mem.startsWith(u8, ident, "enum__") or |
| 328 | 413 | mem.startsWith(u8, ident, "bitpack__") or |
| ... | ... | @@ -453,8 +538,8 @@ pub const Function = struct { |
| 453 | 538 | |
| 454 | 539 | fn wantSafety(f: *Function) bool { |
| 455 | 540 | return switch (f.dg.mod.optimize_mode) { |
| 456 | .Debug, .ReleaseSafe => true, | |
| 457 | .ReleaseFast, .ReleaseSmall => false, | |
| 541 | .debug, .safe => true, | |
| 542 | .fast, .small => false, | |
| 458 | 543 | }; |
| 459 | 544 | } |
| 460 | 545 | |
| ... | ... | @@ -469,10 +554,7 @@ pub const Function = struct { |
| 469 | 554 | } |
| 470 | 555 | |
| 471 | 556 | fn allocLocal(f: *Function, inst: ?Air.Inst.Index, ty: Type) !CValue { |
| 472 | return f.allocAlignedLocal(inst, .{ | |
| 473 | .type = ty, | |
| 474 | .alignment = .none, | |
| 475 | }); | |
| 557 | return f.allocAlignedLocal(inst, .{ .type = ty }); | |
| 476 | 558 | } |
| 477 | 559 | |
| 478 | 560 | /// 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 | 646 | return f.dg.renderType(w, ty); |
| 565 | 647 | } |
| 566 | 648 | |
| 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 | 649 | fn fmtIntLiteralDec(f: *Function, val: Value) !std.fmt.Alt(FormatIntLiteralContext, formatIntLiteral) { |
| 572 | 650 | return f.dg.fmtIntLiteralDec(val, .other); |
| 573 | 651 | } |
| ... | ... | @@ -672,7 +750,9 @@ pub const DeclGen = struct { |
| 672 | 750 | // Render an undefined pointer if we have a pointer to a zero-bit or comptime type. |
| 673 | 751 | const ptr_ty: Type = .fromInterned(uav.orig_ty); |
| 674 | 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 | } |
| 677 | 757 | |
| 678 | 758 | switch (ip.indexToKey(uav.val)) { |
| ... | ... | @@ -737,8 +817,10 @@ pub const DeclGen = struct { |
| 737 | 817 | // Render an undefined pointer if we have a pointer to a zero-bit or comptime type. |
| 738 | 818 | const nav_ty: Type = .fromInterned(ip.getNav(owner_nav).resolved.?.type); |
| 739 | 819 | const ptr_ty = try pt.navPtrType(owner_nav); |
| 740 | if (!nav_ty.isRuntimeFnOrHasRuntimeBits(zcu)) { | |
| 741 | return dg.renderUndefValue(w, ptr_ty, location); | |
| 820 | if (nav_ty.zigTypeTag(zcu) != .@"opaque" and !nav_ty.isRuntimeFnOrHasRuntimeBits(zcu)) { | |
| 821 | try w.writeByte('('); | |
| 822 | try dg.renderOpvPointer(w, ptr_ty, location); | |
| 823 | return w.writeByte(')'); | |
| 742 | 824 | } |
| 743 | 825 | |
| 744 | 826 | // We shouldn't cast C function pointers as this is UB (when you call |
| ... | ... | @@ -758,6 +840,26 @@ pub const DeclGen = struct { |
| 758 | 840 | if (need_cast) try w.writeByte(')'); |
| 759 | 841 | } |
| 760 | 842 | |
| 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 | 863 | fn renderPointer( |
| 762 | 864 | dg: *DeclGen, |
| 763 | 865 | w: *Writer, |
| ... | ... | @@ -959,9 +1061,6 @@ pub const DeclGen = struct { |
| 959 | 1061 | const bits = ty.floatBits(target); |
| 960 | 1062 | const f128_val = val.toFloat(f128, zcu); |
| 961 | 1063 | |
| 962 | // All unsigned ints matching float types are pre-allocated. | |
| 963 | const repr_ty = pt.intType(.unsigned, bits) catch unreachable; | |
| 964 | ||
| 965 | 1064 | assert(bits <= 128); |
| 966 | 1065 | var repr_val_limbs: [BigInt.calcTwosCompLimbCount(128)]BigIntLimb = undefined; |
| 967 | 1066 | var repr_val_big = BigInt.Mutable{ |
| ... | ... | @@ -971,29 +1070,27 @@ pub const DeclGen = struct { |
| 971 | 1070 | }; |
| 972 | 1071 | |
| 973 | 1072 | switch (bits) { |
| 1073 | else => unreachable, | |
| 974 | 1074 | 16 => repr_val_big.set(@as(u16, @bitCast(val.toFloat(f16, zcu)))), |
| 975 | 1075 | 32 => repr_val_big.set(@as(u32, @bitCast(val.toFloat(f32, zcu)))), |
| 976 | 1076 | 64 => repr_val_big.set(@as(u64, @bitCast(val.toFloat(f64, zcu)))), |
| 977 | 1077 | 80 => repr_val_big.set(@as(u80, @bitCast(val.toFloat(f80, zcu)))), |
| 978 | 1078 | 128 => repr_val_big.set(@as(u128, @bitCast(f128_val))), |
| 979 | else => unreachable, | |
| 980 | 1079 | } |
| 981 | 1080 | |
| 982 | var empty = true; | |
| 983 | 1081 | if (std.math.isFinite(f128_val)) { |
| 984 | 1082 | try w.writeAll("zig_make_"); |
| 985 | 1083 | try dg.renderTypeForBuiltinFnName(w, ty); |
| 986 | 1084 | try w.writeByte('('); |
| 987 | 1085 | switch (bits) { |
| 1086 | else => unreachable, | |
| 988 | 1087 | 16 => try w.print("{x}", .{val.toFloat(f16, zcu)}), |
| 989 | 1088 | 32 => try w.print("{x}", .{val.toFloat(f32, zcu)}), |
| 990 | 1089 | 64 => try w.print("{x}", .{val.toFloat(f64, zcu)}), |
| 991 | 1090 | 80 => try w.print("{x}", .{val.toFloat(f80, zcu)}), |
| 992 | 1091 | 128 => try w.print("{x}", .{f128_val}), |
| 993 | else => unreachable, | |
| 994 | 1092 | } |
| 995 | 1093 | try w.writeAll(", "); |
| 996 | empty = false; | |
| 997 | 1094 | } else { |
| 998 | 1095 | // isSignalNan is equivalent to isNan currently, and MSVC doesn't have nans, so prefer nan |
| 999 | 1096 | const operation = if (std.math.isNan(f128_val)) |
| ... | ... | @@ -1028,6 +1125,7 @@ pub const DeclGen = struct { |
| 1028 | 1125 | try w.writeAll(operation); |
| 1029 | 1126 | try w.writeAll(", "); |
| 1030 | 1127 | if (std.math.isNan(f128_val)) switch (bits) { |
| 1128 | else => unreachable, | |
| 1031 | 1129 | // We only actually need to pass the significand, but it will get |
| 1032 | 1130 | // properly masked anyway, so just pass the whole value. |
| 1033 | 1131 | 16 => try w.print("\"0x{x}\"", .{@as(u16, @bitCast(val.toFloat(f16, zcu)))}), |
| ... | ... | @@ -1035,16 +1133,23 @@ pub const DeclGen = struct { |
| 1035 | 1133 | 64 => try w.print("\"0x{x}\"", .{@as(u64, @bitCast(val.toFloat(f64, zcu)))}), |
| 1036 | 1134 | 80 => try w.print("\"0x{x}\"", .{@as(u80, @bitCast(val.toFloat(f80, zcu)))}), |
| 1037 | 1135 | 128 => try w.print("\"0x{x}\"", .{@as(u128, @bitCast(f128_val))}), |
| 1038 | else => unreachable, | |
| 1039 | 1136 | }; |
| 1040 | 1137 | try w.writeAll(", "); |
| 1041 | empty = false; | |
| 1042 | 1138 | } |
| 1043 | try w.print("{f}", .{try dg.fmtIntLiteralHex( | |
| 1044 | try pt.intValue_big(repr_ty, repr_val_big.toConst()), | |
| 1045 | location, | |
| 1046 | )}); | |
| 1047 | if (!empty) try w.writeByte(')'); | |
| 1139 | switch (bits) { | |
| 1140 | else => unreachable, | |
| 1141 | 16, 32, 64 => { | |
| 1142 | // All unsigned ints matching float types are pre-allocated. | |
| 1143 | const repr_ty = pt.intType(.unsigned, bits) catch unreachable; | |
| 1144 | try w.print("{f}", .{try dg.fmtIntLiteralHex( | |
| 1145 | try pt.intValue_big(repr_ty, repr_val_big.toConst()), | |
| 1146 | location, | |
| 1147 | )}); | |
| 1148 | }, | |
| 1149 | 80 => try F80Repr.write(@bitCast(val.toFloat(f80, zcu)), w, target, location == .static_initializer), | |
| 1150 | 128 => try F128Repr.write(@bitCast(f128_val), w, target, location == .static_initializer), | |
| 1151 | } | |
| 1152 | try w.writeByte(')'); | |
| 1048 | 1153 | }, |
| 1049 | 1154 | .slice => |slice| { |
| 1050 | 1155 | if (!location.isInitializer()) { |
| ... | ... | @@ -1306,8 +1411,8 @@ pub const DeclGen = struct { |
| 1306 | 1411 | }; |
| 1307 | 1412 | |
| 1308 | 1413 | const safety_on = switch (dg.mod.optimize_mode) { |
| 1309 | .Debug, .ReleaseSafe => true, | |
| 1310 | .ReleaseFast, .ReleaseSmall => false, | |
| 1414 | .debug, .safe => true, | |
| 1415 | .fast, .small => false, | |
| 1311 | 1416 | }; |
| 1312 | 1417 | |
| 1313 | 1418 | switch (ty.toIntern()) { |
| ... | ... | @@ -1319,22 +1424,29 @@ pub const DeclGen = struct { |
| 1319 | 1424 | .f128_type, |
| 1320 | 1425 | => { |
| 1321 | 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; | |
| 1324 | 1427 | |
| 1325 | 1428 | try w.writeAll("zig_make_"); |
| 1326 | 1429 | try dg.renderTypeForBuiltinFnName(w, ty); |
| 1327 | 1430 | try w.writeByte('('); |
| 1328 | 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 | 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 | 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 | 1450 | return w.writeByte(')'); |
| 1339 | 1451 | }, |
| 1340 | 1452 | .bool_type => try w.writeAll(if (safety_on) "0xaa" else "false"), |
| ... | ... | @@ -1638,8 +1750,6 @@ pub const DeclGen = struct { |
| 1638 | 1750 | try w.writeAll("zig_no_builtin "); |
| 1639 | 1751 | } |
| 1640 | 1752 | |
| 1641 | if (fn_info.return_type == .noreturn_type) try w.writeAll("zig_noreturn "); | |
| 1642 | ||
| 1643 | 1753 | // While incomplete types are usually an acceptable substitute for "void", this is not true |
| 1644 | 1754 | // in function return types, where "void" is the only incomplete type permitted. |
| 1645 | 1755 | const actual_return_type: Type = .fromInterned(fn_info.return_type); |
| ... | ... | @@ -1651,8 +1761,9 @@ pub const DeclGen = struct { |
| 1651 | 1761 | |
| 1652 | 1762 | const ret_cty: CType = try .lower(effective_return_type, &dg.ctype_deps, dg.arena, zcu); |
| 1653 | 1763 | try w.print("{f}", .{ret_cty.fmtDeclaratorPrefix(zcu)}); |
| 1654 | if (toCallingConvention(fn_info.cc, zcu)) |call_conv| { | |
| 1655 | try w.print("zig_callconv({s}) ", .{call_conv}); | |
| 1764 | switch (CType.CallingConvention.fromLang(fn_info.cc, zcu.getTarget())) { | |
| 1765 | .c => {}, | |
| 1766 | else => |cc| try w.print("zig_callconv({t}) ", .{cc}), | |
| 1656 | 1767 | } |
| 1657 | 1768 | switch (name) { |
| 1658 | 1769 | .nav => |nav| try renderNavName(w, nav, ip), |
| ... | ... | @@ -1726,136 +1837,6 @@ pub const DeclGen = struct { |
| 1726 | 1837 | try w.print("{f}", .{cty.fmtTypeName(zcu)}); |
| 1727 | 1838 | } |
| 1728 | 1839 | |
| 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 | 1840 | /// Renders to `w` a C declarator whose type is the C lowering of the given Zig type. |
| 1860 | 1841 | fn renderTypeAndName( |
| 1861 | 1842 | dg: *DeclGen, |
| ... | ... | @@ -2000,6 +1981,7 @@ pub const DeclGen = struct { |
| 2000 | 1981 | switch (info) { |
| 2001 | 1982 | .none => if (!is_big) return, |
| 2002 | 1983 | .bits => {}, |
| 1984 | .bits_none, .big_temp_bits => unreachable, | |
| 2003 | 1985 | } |
| 2004 | 1986 | |
| 2005 | 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 | 2038 | restrict: bool = false, |
| 2057 | 2039 | }; |
| 2058 | 2040 | |
| 2041 | pub 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 | ||
| 2059 | 2107 | pub fn genGlobalAsm(zcu: *Zcu, w: *Writer) !void { |
| 2060 | 2108 | for (zcu.global_assembly.values()) |asm_source| { |
| 2061 | 2109 | try w.print("__asm({f});\n", .{fmtStringLiteral(asm_source, null)}); |
| ... | ... | @@ -2070,16 +2118,16 @@ pub fn genErrDecls( |
| 2070 | 2118 | const ip = &zcu.intern_pool; |
| 2071 | 2119 | |
| 2072 | 2120 | const names = ip.global_error_set.getNamesFromMainThread(); |
| 2073 | // Don't generate an invalid empty enum if the global error set is empty! | |
| 2074 | if (names.len > 0) { | |
| 2075 | try w.writeAll("enum {\n"); | |
| 2076 | for (names, 1..) |name_nts, value| { | |
| 2077 | try w.writeByte(' '); | |
| 2078 | try renderErrorName(w, name_nts.toSlice(ip)); | |
| 2079 | try w.print(" = {d}u,\n", .{value}); | |
| 2080 | } | |
| 2081 | try w.writeAll("};\n"); | |
| 2121 | // Don't generate an invalid empty enum/array if the global error set is empty! | |
| 2122 | if (names.len == 0) return; | |
| 2123 | ||
| 2124 | try w.writeAll("enum {\n"); | |
| 2125 | for (names, 1..) |name_nts, value| { | |
| 2126 | try w.writeByte(' '); | |
| 2127 | try renderErrorName(w, name_nts.toSlice(ip)); | |
| 2128 | try w.print(" = {d}u,\n", .{value}); | |
| 2082 | 2129 | } |
| 2130 | try w.writeAll("};\n"); | |
| 2083 | 2131 | |
| 2084 | 2132 | for (names) |name_nts| { |
| 2085 | 2133 | const name = name_nts.toSlice(ip); |
| ... | ... | @@ -2093,7 +2141,7 @@ pub fn genErrDecls( |
| 2093 | 2141 | "static {s} const zig_errorName[{d}] = {{", |
| 2094 | 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 | 2145 | for (names) |name_nts| { |
| 2098 | 2146 | const name = name_nts.toSlice(ip); |
| 2099 | 2147 | try w.print( |
| ... | ... | @@ -2114,10 +2162,18 @@ pub fn genTagNameFn( |
| 2114 | 2162 | const ip = &zcu.intern_pool; |
| 2115 | 2163 | const loaded_enum = ip.loadEnumType(enum_ty.toIntern()); |
| 2116 | 2164 | assert(loaded_enum.field_names.len > 0); |
| 2117 | if (Type.fromInterned(loaded_enum.int_tag_type).bitSize(zcu) > 64) { | |
| 2118 | @panic("TODO CBE: tagName for enum over 64 bits"); | |
| 2165 | switch (CType.classifyInt(enum_ty, zcu)) { | |
| 2166 | .void => unreachable, | |
| 2167 | .small => |int| switch (int) { | |
| 2168 | else => {}, | |
| 2169 | .zig_u128, .zig_i128 => @panic("TODO CBE: tagName for 128-bit enums"), | |
| 2170 | }, | |
| 2171 | .big => @panic("TODO CBE: tagName for bigint enums"), | |
| 2119 | 2172 | } |
| 2120 | 2173 | |
| 2174 | if (!zcu.comp.config.root_strip) try w.print("/* @tagName({f}) */\n", .{ | |
| 2175 | loaded_enum.name.fmt(ip), | |
| 2176 | }); | |
| 2121 | 2177 | try w.print("static {s} zig_tagName_{f}__{d}({s} tag) {{\n", .{ |
| 2122 | 2178 | slice_const_u8_sentinel_0_type_name, |
| 2123 | 2179 | fmtIdentUnsolo(loaded_enum.name.toSlice(ip)), |
| ... | ... | @@ -2164,6 +2220,7 @@ pub fn genLazyCallModifierFn( |
| 2164 | 2220 | |
| 2165 | 2221 | const fn_val = zcu.navValue(fn_nav); |
| 2166 | 2222 | |
| 2223 | if (fn_val.typeOf(zcu).fnReturnType(zcu).isNoReturn(zcu)) try w.writeAll("zig_noreturn "); | |
| 2167 | 2224 | try w.print("static zig_{t} ", .{kind}); |
| 2168 | 2225 | try dg.renderFunctionSignature(w, fn_val, .none, .definition, switch (kind) { |
| 2169 | 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 | 2326 | const gpa = f.dg.gpa; |
| 2270 | 2327 | const nav_index = f.dg.owner_nav.unwrap().?; |
| 2271 | 2328 | const nav_val = zcu.navValue(nav_index); |
| 2329 | const fn_info = zcu.typeToFunc(nav_val.typeOf(zcu)).?; | |
| 2272 | 2330 | const nav = ip.getNav(nav_index); |
| 2273 | 2331 | |
| 2332 | if (Type.fromInterned(fn_info.return_type).isNoReturn(zcu)) try fwd_decl_writer.writeAll("zig_noreturn "); | |
| 2274 | 2333 | try fwd_decl_writer.writeAll("static "); |
| 2275 | 2334 | try f.dg.renderFunctionSignature( |
| 2276 | 2335 | fwd_decl_writer, |
| ... | ... | @@ -2291,11 +2350,41 @@ pub fn genFunc(f: *Function, fwd_decl_writer: *Writer, header_writer: *Writer) E |
| 2291 | 2350 | .{ .nav = nav_index }, |
| 2292 | 2351 | ); |
| 2293 | 2352 | try header_writer.writeAll(" {\n "); |
| 2353 | if (!f.dg.mod.strip) try header_writer.print("/* {f} */\n ", .{nav.fqn.fmt(ip)}); | |
| 2294 | 2354 | |
| 2295 | 2355 | f.free_locals_map.clearRetainingCapacity(); |
| 2296 | 2356 | |
| 2297 | 2357 | const main_body = f.air.getMainBody(); |
| 2298 | 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 | 2388 | try genBodyResolveState(f, undefined, &.{}, main_body, true); |
| 2300 | 2389 | try f.outdent(); |
| 2301 | 2390 | try f.code.writer.writeByte('}'); |
| ... | ... | @@ -2346,6 +2435,7 @@ pub fn genFunc(f: *Function, fwd_decl_writer: *Writer, header_writer: *Writer) E |
| 2346 | 2435 | for (list.keys()) |local_index| { |
| 2347 | 2436 | const local = f.locals.items[local_index]; |
| 2348 | 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 | 2439 | try header_writer.writeAll(";\n "); |
| 2350 | 2440 | } |
| 2351 | 2441 | } |
| ... | ... | @@ -2397,10 +2487,12 @@ pub fn genDeclFwd(dg: *DeclGen, w: *Writer) Error!void { |
| 2397 | 2487 | |
| 2398 | 2488 | .@"extern" => |@"extern"| switch (nav_ty.zigTypeTag(zcu)) { |
| 2399 | 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 | 2492 | try w.writeAll("zig_extern "); |
| 2401 | 2493 | try dg.renderFunctionSignature( |
| 2402 | 2494 | w, |
| 2403 | .fromInterned(nav.resolved.?.value), | |
| 2495 | fn_val, | |
| 2404 | 2496 | nav.resolved.?.@"align", |
| 2405 | 2497 | .forward_decl, |
| 2406 | 2498 | .{ .@"export" = .{ |
| ... | ... | @@ -2461,7 +2553,12 @@ pub fn genDeclValue(dg: *DeclGen, w: *Writer, options: struct { |
| 2461 | 2553 | try dg.renderTypeAndName(w, ty, options.name, .{ .@"const" = options.@"const" }, .none); |
| 2462 | 2554 | try w.writeAll(" = "); |
| 2463 | 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 | } |
| 2466 | 2563 | pub fn genDeclValueFwd(dg: *DeclGen, w: *Writer, options: struct { |
| 2467 | 2564 | name: CValue, |
| ... | ... | @@ -2496,11 +2593,13 @@ pub fn genExports(dg: *DeclGen, w: *Writer, exported: Zcu.Exported, export_indic |
| 2496 | 2593 | const exported_val = exported.getValue(zcu); |
| 2497 | 2594 | if (ip.isFunctionType(exported_val.typeOf(zcu).toIntern())) return for (export_indices) |export_index| { |
| 2498 | 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 | 2598 | try w.writeAll("zig_extern "); |
| 2500 | 2599 | if (@"export".opts.linkage == .weak) try w.writeAll("zig_weak_linkage_fn "); |
| 2501 | 2600 | try dg.renderFunctionSignature( |
| 2502 | 2601 | w, |
| 2503 | exported.getValue(zcu), | |
| 2602 | fn_val, | |
| 2504 | 2603 | exported.getAlign(zcu), |
| 2505 | 2604 | .forward_decl, |
| 2506 | 2605 | .{ .@"export" = .{ |
| ... | ... | @@ -2662,22 +2761,22 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) Error!void { |
| 2662 | 2761 | .mul => try airBinOp(f, inst, "*", "mul", .none), |
| 2663 | 2762 | |
| 2664 | 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), | |
| 2666 | 2765 | |
| 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 | 2767 | .rem => blk: { |
| 2669 | 2768 | const bin_op = air_datas[@intFromEnum(inst)].bin_op; |
| 2670 | 2769 | const lhs_scalar_ty = f.typeOf(bin_op.lhs).scalarType(zcu); |
| 2671 | 2770 | // For binary operations @TypeOf(lhs)==@TypeOf(rhs), |
| 2672 | 2771 | // so we only check one. |
| 2673 | 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 | 2774 | else |
| 2676 | 2775 | try airBinBuiltinCall(f, inst, "fmod", .none); |
| 2677 | 2776 | }, |
| 2678 | .div_floor => try airBinBuiltinCall(f, inst, "div_floor", .none), | |
| 2679 | .div_ceil => try airBinBuiltinCall(f, inst, "div_ceil", .none), | |
| 2680 | .mod => try airBinBuiltinCall(f, inst, "mod", .none), | |
| 2777 | .div_floor => try airBinBuiltinCall(f, inst, "divFloor", .big_temp_bits), | |
| 2778 | .div_ceil => try airBinBuiltinCall(f, inst, "divCeil", .big_temp_bits), | |
| 2779 | .mod => try airBinBuiltinCall(f, inst, "mod", .big_temp_bits), | |
| 2681 | 2780 | .abs => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "abs", .none), |
| 2682 | 2781 | |
| 2683 | 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 | 2786 | .add_sat => try airBinBuiltinCall(f, inst, "adds", .bits), |
| 2688 | 2787 | .sub_sat => try airBinBuiltinCall(f, inst, "subs", .bits), |
| 2689 | 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), | |
| 2691 | 2790 | |
| 2692 | 2791 | .sqrt => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].un_op, "sqrt", .none), |
| 2693 | 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 | 2863 | .int_from_error => try airNopCast(f, inst), |
| 2765 | 2864 | .union_from_enum => try airUnionFromEnum(f, inst), |
| 2766 | 2865 | .bit_cast => try airBitCast(f, inst), |
| 2767 | .int_cast => try airIntCast(f, inst), | |
| 2768 | .trunc => try airTrunc(f, inst), | |
| 2866 | .int_cast => try airIntCast(f, inst, "intCast", .none), | |
| 2867 | .trunc => try airIntCast(f, inst, "truncate", .bits), | |
| 2769 | 2868 | .load => try airLoad(f, inst), |
| 2770 | 2869 | .store => try airStore(f, inst, false), |
| 2771 | 2870 | .store_safe => try airStore(f, inst, true), |
| ... | ... | @@ -2783,9 +2882,9 @@ fn genBodyInner(f: *Function, body: []const Air.Inst.Index) Error!void { |
| 2783 | 2882 | .get_union_tag => try airGetUnionTag(f, inst), |
| 2784 | 2883 | .clz => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "clz", .bits), |
| 2785 | 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), | |
| 2787 | .byte_swap => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "byte_swap", .bits), | |
| 2788 | .bit_reverse => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "bit_reverse", .bits), | |
| 2885 | .popcount => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "popCount", .bits), | |
| 2886 | .byte_swap => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "byteSwap", .bits), | |
| 2887 | .bit_reverse => try airUnBuiltinCall(f, inst, air_datas[@intFromEnum(inst)].ty_op.operand, "bitReverse", .bits), | |
| 2789 | 2888 | .tag_name => try airTagName(f, inst), |
| 2790 | 2889 | .error_name => try airErrorName(f, inst), |
| 2791 | 2890 | .splat => try airSplat(f, inst), |
| ... | ... | @@ -3124,7 +3223,16 @@ fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3124 | 3223 | const zcu = pt.zcu; |
| 3125 | 3224 | const inst_ty = f.typeOfIndex(inst); |
| 3126 | 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 | } | |
| 3128 | 3236 | |
| 3129 | 3237 | const local = try f.allocLocalValue(.{ |
| 3130 | 3238 | .type = elem_ty, |
| ... | ... | @@ -3298,120 +3406,57 @@ fn airRet(f: *Function, inst: Air.Inst.Index, is_ptr: bool) !void { |
| 3298 | 3406 | } |
| 3299 | 3407 | } |
| 3300 | 3408 | |
| 3301 | fn airIntCast(f: *Function, inst: Air.Inst.Index) !CValue { | |
| 3409 | fn airIntCast(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: BuiltinInfo) !CValue { | |
| 3302 | 3410 | const pt = f.dg.pt; |
| 3303 | 3411 | const zcu = pt.zcu; |
| 3304 | 3412 | const ty_op = f.air.instructions.items(.data)[@backingInt(inst)].ty_op; |
| 3305 | 3413 | |
| 3306 | const operand = try f.resolveInst(ty_op.operand); | |
| 3307 | try reap(f, inst, &.{ty_op.operand}); | |
| 3308 | ||
| 3309 | const inst_ty = f.typeOfIndex(inst); | |
| 3414 | const inst_ty = ty_op.ty.toType(); | |
| 3310 | 3415 | const inst_scalar_ty = inst_ty.scalarType(zcu); |
| 3311 | 3416 | const operand_ty = f.typeOf(ty_op.operand); |
| 3312 | const scalar_ty = operand_ty.scalarType(zcu); | |
| 3313 | ||
| 3314 | // `intCastIsNoop` doesn't apply to vectors because every vector lowers to a different C struct. | |
| 3315 | if (inst_ty.zigTypeTag(zcu) != .vector and f.dg.intCastIsNoop(inst_scalar_ty, scalar_ty)) { | |
| 3316 | return f.moveCValue(inst, inst_ty, operand); | |
| 3317 | } | |
| 3318 | ||
| 3319 | const w = &f.code.writer; | |
| 3320 | const local = try f.allocLocal(inst, inst_ty); | |
| 3321 | const v = try Vectorize.start(f, inst, w, operand_ty); | |
| 3322 | try f.writeCValue(w, local, .other); | |
| 3323 | try v.elem(f, w); | |
| 3324 | try w.writeAll(" = "); | |
| 3325 | try f.renderIntCast(w, inst_scalar_ty, operand, v, scalar_ty, .other); | |
| 3326 | try w.writeByte(';'); | |
| 3327 | try f.newline(); | |
| 3328 | try v.end(f, inst, w); | |
| 3329 | return local; | |
| 3330 | } | |
| 3331 | ||
| 3332 | fn airTrunc(f: *Function, inst: Air.Inst.Index) !CValue { | |
| 3333 | const pt = f.dg.pt; | |
| 3334 | const zcu = pt.zcu; | |
| 3335 | const ty_op = f.air.instructions.items(.data)[@backingInt(inst)].ty_op; | |
| 3417 | const operand_scalar_ty = operand_ty.scalarType(zcu); | |
| 3418 | const is_big = lowersToBigInt(operand_ty, zcu); | |
| 3336 | 3419 | |
| 3337 | 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}); | |
| 3339 | 3422 | |
| 3340 | const inst_ty = f.typeOfIndex(inst); | |
| 3341 | const inst_scalar_ty = inst_ty.scalarType(zcu); | |
| 3342 | const dest_int_info = inst_scalar_ty.intInfo(zcu); | |
| 3343 | const dest_bits = dest_int_info.bits; | |
| 3344 | const dest_c_bits = toCIntBits(dest_bits) orelse | |
| 3345 | return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{}); | |
| 3346 | const operand_ty = f.typeOf(ty_op.operand); | |
| 3347 | const scalar_ty = operand_ty.scalarType(zcu); | |
| 3348 | const scalar_int_info = scalar_ty.intInfo(zcu); | |
| 3349 | ||
| 3350 | const need_cast = dest_c_bits < 64; | |
| 3351 | const need_lo = scalar_int_info.bits > 64 and dest_bits <= 64; | |
| 3352 | const need_mask = dest_bits < 8 or !std.math.isPowerOfTwo(dest_bits); | |
| 3353 | if (!need_cast and !need_lo and !need_mask) return f.moveCValue(inst, inst_ty, operand); | |
| 3423 | const ref_ret = lowersToBigInt(inst_scalar_ty, zcu); | |
| 3424 | const ref_arg = lowersToBigInt(operand_scalar_ty, zcu); | |
| 3354 | 3425 | |
| 3355 | 3426 | const w = &f.code.writer; |
| 3356 | 3427 | const local = try f.allocLocal(inst, inst_ty); |
| 3428 | if (is_big) try reap(f, inst, &.{ty_op.operand}); | |
| 3357 | 3429 | const v = try Vectorize.start(f, inst, w, operand_ty); |
| 3358 | try f.writeCValue(w, local, .other); | |
| 3359 | try v.elem(f, w); | |
| 3360 | try w.writeAll(" = "); | |
| 3361 | if (need_cast) { | |
| 3362 | try w.writeByte('('); | |
| 3363 | try f.renderType(w, inst_scalar_ty); | |
| 3364 | try w.writeByte(')'); | |
| 3365 | } | |
| 3366 | if (need_lo) { | |
| 3367 | try w.writeAll("zig_lo_"); | |
| 3368 | try f.dg.renderTypeForBuiltinFnName(w, scalar_ty); | |
| 3369 | try w.writeByte('('); | |
| 3430 | if (!ref_ret) { | |
| 3431 | try f.writeCValue(w, local, .other); | |
| 3432 | try v.elem(f, w); | |
| 3433 | try w.writeAll(" = "); | |
| 3370 | 3434 | } |
| 3371 | if (!need_mask) { | |
| 3372 | try f.writeCValue(w, operand, .other); | |
| 3435 | try w.writeAll("zig_"); | |
| 3436 | try f.dg.renderTypeForBuiltinFnName(w, inst_scalar_ty); | |
| 3437 | try w.print("_{s}_", .{operation}); | |
| 3438 | try f.dg.renderTypeForBuiltinFnName(w, operand_scalar_ty); | |
| 3439 | try w.writeByte('('); | |
| 3440 | if (ref_ret) { | |
| 3441 | try w.writeByte('&'); | |
| 3442 | try f.writeCValue(w, local, .other); | |
| 3373 | 3443 | try v.elem(f, w); |
| 3374 | } else switch (dest_int_info.signedness) { | |
| 3375 | .unsigned => { | |
| 3376 | try w.writeAll("zig_and_"); | |
| 3377 | try f.dg.renderTypeForBuiltinFnName(w, scalar_ty); | |
| 3378 | try w.writeByte('('); | |
| 3379 | try f.writeCValue(w, operand, .other); | |
| 3380 | try v.elem(f, w); | |
| 3381 | try w.print(", {f})", .{ | |
| 3382 | try f.fmtIntLiteralHex(try inst_scalar_ty.maxIntScalar(pt, scalar_ty)), | |
| 3383 | }); | |
| 3384 | }, | |
| 3385 | .signed => { | |
| 3386 | const c_bits = toCIntBits(scalar_int_info.bits) orelse | |
| 3387 | return f.fail("TODO: C backend: implement integer types larger than 128 bits", .{}); | |
| 3388 | const shift_val = try pt.intValue(.u8, c_bits - dest_bits); | |
| 3389 | ||
| 3390 | try w.writeAll("zig_shr_"); | |
| 3391 | try f.dg.renderTypeForBuiltinFnName(w, scalar_ty); | |
| 3392 | if (c_bits == 128) { | |
| 3393 | try w.print("(zig_bitCast_i{d}(", .{c_bits}); | |
| 3394 | } else { | |
| 3395 | try w.print("((int{d}_t)", .{c_bits}); | |
| 3396 | } | |
| 3397 | try w.print("zig_shl_u{d}(", .{c_bits}); | |
| 3398 | if (c_bits == 128) { | |
| 3399 | try w.print("zig_bitCast_u{d}(", .{c_bits}); | |
| 3400 | } else { | |
| 3401 | try w.print("(uint{d}_t)", .{c_bits}); | |
| 3402 | } | |
| 3403 | try f.writeCValue(w, operand, .other); | |
| 3404 | try v.elem(f, w); | |
| 3405 | if (c_bits == 128) try w.writeByte(')'); | |
| 3406 | try w.print(", {f})", .{try f.fmtIntLiteralDec(shift_val)}); | |
| 3407 | if (c_bits == 128) try w.writeByte(')'); | |
| 3408 | try w.print(", {f})", .{try f.fmtIntLiteralDec(shift_val)}); | |
| 3409 | }, | |
| 3444 | try w.writeAll(", "); | |
| 3410 | 3445 | } |
| 3411 | if (need_lo) try w.writeByte(')'); | |
| 3412 | try w.writeByte(';'); | |
| 3446 | if (ref_arg) { | |
| 3447 | try w.writeByte('&'); | |
| 3448 | switch (operand) { | |
| 3449 | .constant => |val| try f.dg.renderValueAsLvalue(w, val), | |
| 3450 | else => try f.writeCValue(w, operand, .other), | |
| 3451 | } | |
| 3452 | } else try f.writeCValue(w, operand, .other); | |
| 3453 | try v.elem(f, w); | |
| 3454 | try f.dg.renderBuiltinInfo(w, inst_scalar_ty, info); | |
| 3455 | try f.dg.renderBuiltinInfo(w, operand_scalar_ty, .none); | |
| 3456 | try w.writeAll(");"); | |
| 3413 | 3457 | try f.newline(); |
| 3414 | 3458 | try v.end(f, inst, w); |
| 3459 | ||
| 3415 | 3460 | return local; |
| 3416 | 3461 | } |
| 3417 | 3462 | |
| ... | ... | @@ -3525,39 +3570,46 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: |
| 3525 | 3570 | const ty_pl = f.air.instructions.items(.data)[@backingInt(inst)].ty_pl; |
| 3526 | 3571 | const bin_op = f.air.extraData(Air.Bin, ty_pl.payload).data; |
| 3527 | 3572 | |
| 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 | 3577 | const lhs = try f.resolveInst(bin_op.lhs); |
| 3529 | 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 }); | |
| 3531 | 3580 | |
| 3532 | const inst_ty = f.typeOfIndex(inst); | |
| 3533 | const operand_ty = f.typeOf(bin_op.lhs); | |
| 3534 | const scalar_ty = operand_ty.scalarType(zcu); | |
| 3581 | const lhs_scalar_ty = lhs_ty.scalarType(zcu); | |
| 3582 | const rhs_scalar_ty = rhs_ty.scalarType(zcu); | |
| 3535 | 3583 | |
| 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); | |
| 3537 | 3586 | |
| 3538 | 3587 | const w = &f.code.writer; |
| 3539 | const local = try f.allocLocal(inst, inst_ty); | |
| 3540 | const v = try Vectorize.start(f, inst, w, operand_ty); | |
| 3588 | const local = try f.allocLocal(inst, f.typeOfIndex(inst)); | |
| 3589 | if (is_big) try reap(f, inst, &.{ bin_op.lhs, bin_op.rhs }); | |
| 3590 | const v = try Vectorize.start(f, inst, w, lhs_ty); | |
| 3541 | 3591 | try f.writeCValueMember(w, local, .{ .field = 1 }); |
| 3542 | 3592 | try v.elem(f, w); |
| 3543 | try w.writeAll(" = zig_"); | |
| 3593 | try w.writeAll(" = "); | |
| 3594 | try w.writeAll("zig_"); | |
| 3544 | 3595 | try w.writeAll(operation); |
| 3545 | 3596 | try w.writeAll("o_"); |
| 3546 | try f.dg.renderTypeForBuiltinFnName(w, scalar_ty); | |
| 3597 | try f.dg.renderTypeForBuiltinFnName(w, lhs_scalar_ty); | |
| 3547 | 3598 | try w.writeByte('('); |
| 3548 | 3599 | |
| 3549 | 3600 | // '&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 | 3602 | .int_type => {}, // we already have a '[u]intX_t *' |
| 3552 | 3603 | .simple_type => { |
| 3553 | 3604 | // '&dest' will be something like a 'uintptr_t *', which might be a different C type to |
| 3554 | 3605 | // the equivalent sized integer (e.g. 'uint64_t *'), so we need a cast. We don't need a |
| 3555 | 3606 | // cast on the *operands* because they are passed by value (except for big integers, |
| 3556 | 3607 | // where this issue doesn't exist because no "simple" int type needs bigint repr). |
| 3557 | try w.print("({s}int{d}_t *)", .{ | |
| 3558 | if (scalar_ty.isUnsignedInt(zcu)) "u" else "", | |
| 3559 | scalar_ty.abiSize(zcu) * 8, | |
| 3560 | }); | |
| 3608 | const inst_int_info = lhs_scalar_ty.intInfo(zcu); | |
| 3609 | try w.print("({s}int{d}_t *)", .{ switch (inst_int_info.signedness) { | |
| 3610 | .signed => "", | |
| 3611 | .unsigned => "u", | |
| 3612 | }, inst_int_info.bits }); | |
| 3561 | 3613 | }, |
| 3562 | 3614 | else => unreachable, |
| 3563 | 3615 | } |
| ... | ... | @@ -3566,14 +3618,24 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info: |
| 3566 | 3618 | try v.elem(f, w); |
| 3567 | 3619 | |
| 3568 | 3620 | try w.writeAll(", "); |
| 3569 | if (ref_arg) try w.writeByte('&'); | |
| 3570 | try f.writeCValue(w, lhs, .other); | |
| 3621 | if (ref_lhs) { | |
| 3622 | try w.writeByte('&'); | |
| 3623 | switch (lhs) { | |
| 3624 | .constant => |lhs_val| try f.dg.renderValueAsLvalue(w, lhs_val), | |
| 3625 | else => try f.writeCValue(w, lhs, .other), | |
| 3626 | } | |
| 3627 | } else try f.writeCValue(w, lhs, .other); | |
| 3571 | 3628 | try v.elem(f, w); |
| 3572 | 3629 | try w.writeAll(", "); |
| 3573 | if (ref_arg) try w.writeByte('&'); | |
| 3574 | try f.writeCValue(w, rhs, .other); | |
| 3575 | if (f.typeOf(bin_op.rhs).isVector(zcu)) try v.elem(f, w); | |
| 3576 | try f.dg.renderBuiltinInfo(w, scalar_ty, info); | |
| 3630 | if (ref_rhs) { | |
| 3631 | try w.writeByte('&'); | |
| 3632 | switch (rhs) { | |
| 3633 | .constant => |rhs_val| try f.dg.renderValueAsLvalue(w, rhs_val), | |
| 3634 | else => try f.writeCValue(w, rhs, .other), | |
| 3635 | } | |
| 3636 | } else try f.writeCValue(w, rhs, .other); | |
| 3637 | try v.elem(f, w); | |
| 3638 | try f.dg.renderBuiltinInfo(w, lhs_scalar_ty, info); | |
| 3577 | 3639 | try w.writeAll(");"); |
| 3578 | 3640 | try f.newline(); |
| 3579 | 3641 | try v.end(f, inst, w); |
| ... | ... | @@ -3622,8 +3684,18 @@ fn airBinOp( |
| 3622 | 3684 | const bin_op = f.air.instructions.items(.data)[@backingInt(inst)].bin_op; |
| 3623 | 3685 | const operand_ty = f.typeOf(bin_op.lhs); |
| 3624 | 3686 | const scalar_ty = operand_ty.scalarType(zcu); |
| 3625 | if ((scalar_ty.isInt(zcu) and scalar_ty.bitSize(zcu) > 64) or scalar_ty.isRuntimeFloat()) | |
| 3626 | return try airBinBuiltinCall(f, inst, operation, info); | |
| 3687 | ||
| 3688 | builtin: { | |
| 3689 | if (scalar_ty.isInt(zcu)) switch (CType.classifyInt(scalar_ty, zcu)) { | |
| 3690 | .void => unreachable, | |
| 3691 | .small => |int| switch (int) { | |
| 3692 | else => break :builtin, | |
| 3693 | .zig_u128, .zig_i128 => {}, | |
| 3694 | }, | |
| 3695 | .big => {}, | |
| 3696 | } else if (!scalar_ty.isRuntimeFloat()) break :builtin; | |
| 3697 | return airBinBuiltinCall(f, inst, operation, info); | |
| 3698 | } | |
| 3627 | 3699 | |
| 3628 | 3700 | const lhs = try f.resolveInst(bin_op.lhs); |
| 3629 | 3701 | const rhs = try f.resolveInst(bin_op.rhs); |
| ... | ... | @@ -3662,19 +3734,21 @@ fn airCmpOp( |
| 3662 | 3734 | const lhs_ty = f.typeOf(data.lhs); |
| 3663 | 3735 | const scalar_ty = lhs_ty.scalarType(zcu); |
| 3664 | 3736 | |
| 3665 | if (scalar_ty.isInt(zcu)) { | |
| 3666 | const scalar_bits = scalar_ty.bitSize(zcu); | |
| 3667 | if (scalar_bits > 64) return airCmpBuiltinCall( | |
| 3668 | f, | |
| 3669 | inst, | |
| 3670 | data, | |
| 3671 | operator, | |
| 3672 | .cmp, | |
| 3673 | if (scalar_bits > 128) .bits else .none, | |
| 3674 | ); | |
| 3737 | builtin: { | |
| 3738 | if (scalar_ty.isInt(zcu)) { | |
| 3739 | switch (CType.classifyInt(scalar_ty, zcu)) { | |
| 3740 | .void => unreachable, | |
| 3741 | .small => |int| switch (int) { | |
| 3742 | else => break :builtin, | |
| 3743 | .zig_u128, .zig_i128 => {}, | |
| 3744 | }, | |
| 3745 | .big => {}, | |
| 3746 | } | |
| 3747 | return airCmpBuiltinCall(f, inst, data, operator, .cmp, .none); | |
| 3748 | } | |
| 3749 | if (scalar_ty.isRuntimeFloat()) | |
| 3750 | return airCmpBuiltinCall(f, inst, data, operator, .operator, .none); | |
| 3675 | 3751 | } |
| 3676 | if (scalar_ty.isRuntimeFloat()) | |
| 3677 | return airCmpBuiltinCall(f, inst, data, operator, .operator, .none); | |
| 3678 | 3752 | |
| 3679 | 3753 | const inst_ty = f.typeOfIndex(inst); |
| 3680 | 3754 | const lhs = try f.resolveInst(data.lhs); |
| ... | ... | @@ -3716,21 +3790,23 @@ fn airEquality( |
| 3716 | 3790 | const pt = f.dg.pt; |
| 3717 | 3791 | const zcu = pt.zcu; |
| 3718 | 3792 | const bin_op = f.air.instructions.items(.data)[@backingInt(inst)].bin_op; |
| 3719 | ||
| 3720 | 3793 | const operand_ty = f.typeOf(bin_op.lhs); |
| 3721 | if (operand_ty.isAbiInt(zcu)) { | |
| 3722 | const operand_bits = operand_ty.bitSize(zcu); | |
| 3723 | if (operand_bits > 64) return airCmpBuiltinCall( | |
| 3724 | f, | |
| 3725 | inst, | |
| 3726 | bin_op, | |
| 3727 | operator, | |
| 3728 | .cmp, | |
| 3729 | if (operand_bits > 128) .bits else .none, | |
| 3730 | ); | |
| 3794 | ||
| 3795 | builtin: { | |
| 3796 | if (operand_ty.isAbiInt(zcu)) { | |
| 3797 | switch (CType.classifyInt(operand_ty, zcu)) { | |
| 3798 | .void => unreachable, | |
| 3799 | .small => |int| switch (int) { | |
| 3800 | else => break :builtin, | |
| 3801 | .zig_u128, .zig_i128 => {}, | |
| 3802 | }, | |
| 3803 | .big => {}, | |
| 3804 | } | |
| 3805 | return airCmpBuiltinCall(f, inst, bin_op, operator, .cmp, .none); | |
| 3806 | } | |
| 3807 | if (operand_ty.isRuntimeFloat()) | |
| 3808 | return airCmpBuiltinCall(f, inst, bin_op, operator, .operator, .none); | |
| 3731 | 3809 | } |
| 3732 | if (operand_ty.isRuntimeFloat()) | |
| 3733 | return airCmpBuiltinCall(f, inst, bin_op, operator, .operator, .none); | |
| 3734 | 3810 | |
| 3735 | 3811 | const lhs = try f.resolveInst(bin_op.lhs); |
| 3736 | 3812 | const rhs = try f.resolveInst(bin_op.rhs); |
| ... | ... | @@ -3809,7 +3885,7 @@ fn airCmpLteErrorsLen(f: *Function, inst: Air.Inst.Index) !CValue { |
| 3809 | 3885 | try f.writeCValue(w, local, .other); |
| 3810 | 3886 | try w.writeAll(" = "); |
| 3811 | 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 | 3889 | try f.newline(); |
| 3814 | 3890 | return local; |
| 3815 | 3891 | } |
| ... | ... | @@ -3862,8 +3938,17 @@ fn airMinMax(f: *Function, inst: Air.Inst.Index, operator: u8, operation: []cons |
| 3862 | 3938 | const inst_ty = f.typeOfIndex(inst); |
| 3863 | 3939 | const inst_scalar_ty = inst_ty.scalarType(zcu); |
| 3864 | 3940 | |
| 3865 | if ((inst_scalar_ty.isInt(zcu) and inst_scalar_ty.bitSize(zcu) > 64) or inst_scalar_ty.isRuntimeFloat()) | |
| 3866 | return try airBinBuiltinCall(f, inst, operation, .none); | |
| 3941 | builtin: { | |
| 3942 | if (inst_scalar_ty.isInt(zcu)) switch (CType.classifyInt(inst_scalar_ty, zcu)) { | |
| 3943 | .void => unreachable, | |
| 3944 | .small => |int| switch (int) { | |
| 3945 | else => break :builtin, | |
| 3946 | .zig_u128, .zig_i128 => {}, | |
| 3947 | }, | |
| 3948 | .big => {}, | |
| 3949 | } else if (!inst_scalar_ty.isRuntimeFloat()) break :builtin; | |
| 3950 | return airBinBuiltinCall(f, inst, operation, .none); | |
| 3951 | } | |
| 3867 | 3952 | |
| 3868 | 3953 | const lhs = try f.resolveInst(bin_op.lhs); |
| 3869 | 3954 | const rhs = try f.resolveInst(bin_op.rhs); |
| ... | ... | @@ -3979,10 +4064,7 @@ fn airCall( |
| 3979 | 4064 | try w.writeAll("(void)"); |
| 3980 | 4065 | break :result .none; |
| 3981 | 4066 | } else { |
| 3982 | const local = try f.allocAlignedLocal(inst, .{ | |
| 3983 | .type = ret_ty, | |
| 3984 | .alignment = .none, | |
| 3985 | }); | |
| 4067 | const local = try f.allocAlignedLocal(inst, .{ .type = ret_ty }); | |
| 3986 | 4068 | try f.writeCValue(w, local, .other); |
| 3987 | 4069 | try w.writeAll(" = "); |
| 3988 | 4070 | break :result local; |
| ... | ... | @@ -4058,16 +4140,7 @@ fn airCall( |
| 4058 | 4140 | fn airDbgStmt(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4059 | 4141 | const dbg_stmt = f.air.instructions.items(.data)[@backingInt(inst)].dbg_stmt; |
| 4060 | 4142 | const w = &f.code.writer; |
| 4061 | // TODO re-evaluate whether to emit these or not. If we naively emit | |
| 4062 | // these directives, the output file will report bogus line numbers because | |
| 4063 | // every newline after the #line directive adds one to the line. | |
| 4064 | // We also don't print the filename yet, so the output is strictly unhelpful. | |
| 4065 | // If we wanted to go this route, we would need to go all the way and not output | |
| 4066 | // newlines until the next dbg_stmt occurs. | |
| 4067 | // Perhaps an additional compilation option is in order? | |
| 4068 | //try w.print("#line {d}", .{dbg_stmt.line + 1}); | |
| 4069 | //try f.newline(); | |
| 4070 | try w.print("/* file:{d}:{d} */", .{ dbg_stmt.line + 1, dbg_stmt.column + 1 }); | |
| 4143 | try w.print("/* {d}:{d} */", .{ dbg_stmt.line + 1, dbg_stmt.column + 1 }); | |
| 4071 | 4144 | try f.newline(); |
| 4072 | 4145 | return .none; |
| 4073 | 4146 | } |
| ... | ... | @@ -4433,12 +4506,12 @@ fn airBitCast(f: *Function, inst: Air.Inst.Index) Error!CValue { |
| 4433 | 4506 | const operand_scalar_ty = operand_ty.scalarType(zcu); |
| 4434 | 4507 | const dest_scalar_ty = dest_ty.scalarType(zcu); |
| 4435 | 4508 | |
| 4436 | // Some cases are handled with a simple cast: | |
| 4437 | // * float -> float | |
| 4438 | // * bool -> int | |
| 4439 | 4509 | if ((operand_scalar_ty.isRuntimeFloat() and dest_scalar_ty.isRuntimeFloat()) or |
| 4440 | 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 | 4515 | try f.writeCValue(w, dest_local, .other); |
| 4443 | 4516 | try v.elem(f, w); |
| 4444 | 4517 | try w.writeAll(" = ("); |
| ... | ... | @@ -4458,85 +4531,44 @@ fn airBitCast(f: *Function, inst: Air.Inst.Index) Error!CValue { |
| 4458 | 4531 | try v.elem(f, w); |
| 4459 | 4532 | try w.writeAll(" != 0;"); |
| 4460 | 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 | 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 | 4535 | assert(operand_scalar_ty.isRuntimeFloat() or operand_scalar_ty.isAbiInt(zcu)); |
| 4536 | assert(dest_scalar_ty.isRuntimeFloat() or dest_scalar_ty.isAbiInt(zcu)); | |
| 4480 | 4537 | |
| 4481 | // memcpy the value... | |
| 4482 | try w.writeAll("memcpy(&"); | |
| 4483 | try f.writeCValue(w, dest_local, .other); | |
| 4484 | try v.elem(f, w); | |
| 4485 | try w.writeAll(", &"); | |
| 4486 | switch (operand) { | |
| 4487 | .constant => |val| try f.dg.renderValueAsLvalue(w, val), | |
| 4488 | else => try f.writeCValue(w, operand, .other), | |
| 4538 | const ref_ret = lowersToBigInt(dest_scalar_ty, zcu); | |
| 4539 | const ref_arg = lowersToBigInt(operand_scalar_ty, zcu); | |
| 4540 | ||
| 4541 | if (!ref_ret) { | |
| 4542 | try f.writeCValue(w, dest_local, .other); | |
| 4543 | try v.elem(f, w); | |
| 4544 | try w.writeAll(" = "); | |
| 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 | 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 | 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 | } |
| 4541 | 4573 | |
| 4542 | 4574 | try v.end(f, inst, w); |
| ... | ... | @@ -4906,11 +4938,9 @@ fn lowerSwitchCmp( |
| 4906 | 4938 | |
| 4907 | 4939 | fn asmInputNeedsLocal(f: *Function, constraint: []const u8, value: CValue) bool { |
| 4908 | 4940 | const dg = f.dg; |
| 4909 | const target = &dg.mod.resolved_target.result; | |
| 4910 | 4941 | return switch (constraint[0]) { |
| 4911 | 4942 | '{' => true, |
| 4912 | 'i', 'r' => false, | |
| 4913 | 'I' => !target.cpu.arch.isArm(), | |
| 4943 | 'r', 'i', 'n', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P' => false, | |
| 4914 | 4944 | else => switch (value) { |
| 4915 | 4945 | .constant => |val| switch (dg.pt.zcu.intern_pool.indexToKey(val.toIntern())) { |
| 4916 | 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 | 4967 | const w = &f.code.writer; |
| 4938 | 4968 | const inst_ty = f.typeOfIndex(inst); |
| 4939 | 4969 | const inst_local = if (inst_ty.hasRuntimeBits(zcu)) local: { |
| 4940 | const inst_local = try f.allocLocalValue(.{ | |
| 4941 | .type = inst_ty, | |
| 4942 | .alignment = .none, | |
| 4943 | }); | |
| 4970 | const inst_local = try f.allocLocalValue(.{ .type = inst_ty }); | |
| 4944 | 4971 | if (f.wantSafety()) { |
| 4945 | 4972 | try f.writeCValue(w, inst_local, .other); |
| 4946 | 4973 | try w.writeAll(" = "); |
| ... | ... | @@ -4967,10 +4994,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4967 | 4994 | if (is_reg) { |
| 4968 | 4995 | const output_ty = if (output.operand == .none) inst_ty else f.typeOf(output.operand).childType(zcu); |
| 4969 | 4996 | try w.writeAll("register "); |
| 4970 | const output_local = try f.allocLocalValue(.{ | |
| 4971 | .type = output_ty, | |
| 4972 | .alignment = .none, | |
| 4973 | }); | |
| 4997 | const output_local = try f.allocLocalValue(.{ .type = output_ty }); | |
| 4974 | 4998 | try f.allocs.put(gpa, output_local.new_local, false); |
| 4975 | 4999 | try f.dg.renderTypeAndName(w, output_ty, output_local, .{}, .none); |
| 4976 | 5000 | try w.writeAll(" __asm(\""); |
| ... | ... | @@ -4989,7 +5013,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 4989 | 5013 | while (it.next()) |input| { |
| 4990 | 5014 | const constraint = input.constraint; |
| 4991 | 5015 | |
| 4992 | if (constraint.len < 1 or mem.indexOfScalar(u8, "=+&%", constraint[0]) != null or | |
| 5016 | if (constraint.len < 1 or mem.findScalar(u8, "=+&%", constraint[0]) != null or | |
| 4993 | 5017 | (constraint[0] == '{' and constraint[constraint.len - 1] != '}')) |
| 4994 | 5018 | { |
| 4995 | 5019 | return f.fail("CBE: constraint not supported: '{s}'", .{constraint}); |
| ... | ... | @@ -5000,10 +5024,7 @@ fn airAsm(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5000 | 5024 | if (asmInputNeedsLocal(f, constraint, input_val)) { |
| 5001 | 5025 | const input_ty = f.typeOf(input.operand); |
| 5002 | 5026 | if (is_reg) try w.writeAll("register "); |
| 5003 | const input_local = try f.allocLocalValue(.{ | |
| 5004 | .type = input_ty, | |
| 5005 | .alignment = .none, | |
| 5006 | }); | |
| 5027 | const input_local = try f.allocLocalValue(.{ .type = input_ty }); | |
| 5007 | 5028 | try f.allocs.put(gpa, input_local.new_local, false); |
| 5008 | 5029 | // Do not render the declaration as `const` qualified if we're generating an |
| 5009 | 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 | 5077 | } |
| 5057 | 5078 | |
| 5058 | 5079 | const desc = mem.sliceTo(asm_source[src_i..], ']'); |
| 5059 | if (mem.indexOfScalar(u8, desc, ':')) |colon| { | |
| 5080 | if (mem.findScalar(u8, desc, ':')) |colon| { | |
| 5060 | 5081 | const name = desc[0..colon]; |
| 5061 | 5082 | const modifier = desc[colon + 1 ..]; |
| 5062 | 5083 | |
| ... | ... | @@ -5853,28 +5874,124 @@ fn airFloatCast(f: *Function, inst: Air.Inst.Index) !CValue { |
| 5853 | 5874 | else |
| 5854 | 5875 | unreachable; |
| 5855 | 5876 | |
| 5877 | const ref_ret = lowersToBigInt(inst_scalar_ty, zcu); | |
| 5878 | const ref_operand = lowersToBigInt(scalar_ty, zcu); | |
| 5879 | ||
| 5856 | 5880 | const w = &f.code.writer; |
| 5857 | 5881 | const local = try f.allocLocal(inst, inst_ty); |
| 5858 | 5882 | const v = try Vectorize.start(f, inst, w, operand_ty); |
| 5859 | try f.writeCValue(w, local, .other); | |
| 5860 | try v.elem(f, w); | |
| 5861 | try w.writeAll(" = "); | |
| 5883 | if (ref_ret) { | |
| 5884 | const inst_int_info = inst_scalar_ty.intInfo(zcu); | |
| 5885 | if (inst_int_info.bits <= 128) { | |
| 5886 | try w.writeAll("zig_"); | |
| 5887 | try f.dg.renderTypeForBuiltinFnName(w, inst_scalar_ty); | |
| 5888 | try w.print("_intCast_{c}{d}", .{ | |
| 5889 | @as(u8, switch (inst_int_info.signedness) { | |
| 5890 | .signed => 'i', | |
| 5891 | .unsigned => 'u', | |
| 5892 | }), | |
| 5893 | std.math.ceilPowerOfTwoAssert(u16, @max(inst_int_info.bits, 32)), | |
| 5894 | }); | |
| 5895 | try w.writeAll("(&"); | |
| 5896 | try f.writeCValue(w, local, .other); | |
| 5897 | try v.elem(f, w); | |
| 5898 | try w.writeAll(", "); | |
| 5899 | } | |
| 5900 | } else { | |
| 5901 | try f.writeCValue(w, local, .other); | |
| 5902 | try v.elem(f, w); | |
| 5903 | try w.writeAll(" = "); | |
| 5904 | } | |
| 5862 | 5905 | if (inst_scalar_ty.isInt(zcu) and scalar_ty.isRuntimeFloat()) { |
| 5863 | try w.writeAll("zig_wrap_"); | |
| 5864 | try f.dg.renderTypeForBuiltinFnName(w, inst_scalar_ty); | |
| 5865 | try w.writeByte('('); | |
| 5906 | const inst_int_info = inst_scalar_ty.intInfo(zcu); | |
| 5907 | if (inst_int_info.bits <= 128) try w.print("zig_{c}{d}_truncate_{[0]c}{[1]d}(", .{ | |
| 5908 | @as(u8, switch (inst_int_info.signedness) { | |
| 5909 | .signed => 'i', | |
| 5910 | .unsigned => 'u', | |
| 5911 | }), | |
| 5912 | std.math.ceilPowerOfTwoAssert(u16, @max(inst_int_info.bits, 32)), | |
| 5913 | }); | |
| 5866 | 5914 | } |
| 5867 | 5915 | try w.writeAll("zig_"); |
| 5868 | 5916 | try w.writeAll(operation); |
| 5869 | 5917 | try w.writeAll(compilerRtAbbrev(scalar_ty, zcu, target)); |
| 5870 | 5918 | try w.writeAll(compilerRtAbbrev(inst_scalar_ty, zcu, target)); |
| 5871 | 5919 | try w.writeByte('('); |
| 5872 | try f.writeCValue(w, operand, .other); | |
| 5873 | try v.elem(f, w); | |
| 5920 | if (ref_ret) { | |
| 5921 | const inst_int_info = inst_scalar_ty.intInfo(zcu); | |
| 5922 | if (inst_int_info.bits > 128) { | |
| 5923 | try w.writeByte('&'); | |
| 5924 | try f.writeCValue(w, local, .other); | |
| 5925 | try v.elem(f, w); | |
| 5926 | try w.writeAll(", "); | |
| 5927 | } | |
| 5928 | } | |
| 5929 | if (ref_operand) { | |
| 5930 | const operand_int_info = scalar_ty.intInfo(zcu); | |
| 5931 | if (operand_int_info.bits <= 128) { | |
| 5932 | try w.print("zig_{c}{d}_intCast_", .{ | |
| 5933 | @as(u8, switch (operand_int_info.signedness) { | |
| 5934 | .signed => 'i', | |
| 5935 | .unsigned => 'u', | |
| 5936 | }), | |
| 5937 | std.math.ceilPowerOfTwoAssert(u16, @max(operand_int_info.bits, 32)), | |
| 5938 | }); | |
| 5939 | try f.dg.renderTypeForBuiltinFnName(w, scalar_ty); | |
| 5940 | try w.writeAll("(&"); | |
| 5941 | switch (operand) { | |
| 5942 | .constant => |val| try f.dg.renderValueAsLvalue(w, val), | |
| 5943 | else => try f.writeCValue(w, operand, .other), | |
| 5944 | } | |
| 5945 | try v.elem(f, w); | |
| 5946 | try f.dg.renderBuiltinInfo(w, scalar_ty, .none); | |
| 5947 | try w.writeByte(')'); | |
| 5948 | } else { | |
| 5949 | try w.writeByte('&'); | |
| 5950 | switch (operand) { | |
| 5951 | .constant => |val| try f.dg.renderValueAsLvalue(w, val), | |
| 5952 | else => try f.writeCValue(w, operand, .other), | |
| 5953 | } | |
| 5954 | try v.elem(f, w); | |
| 5955 | try w.print(", {f}", .{fmtUnsignedIntLiteralSmall( | |
| 5956 | target, | |
| 5957 | .uint16_t, | |
| 5958 | operand_int_info.bits, | |
| 5959 | false, | |
| 5960 | 10, | |
| 5961 | .lower, | |
| 5962 | )}); | |
| 5963 | } | |
| 5964 | } else { | |
| 5965 | try f.writeCValue(w, operand, .other); | |
| 5966 | try v.elem(f, w); | |
| 5967 | } | |
| 5968 | if (ref_ret) { | |
| 5969 | const inst_int_info = inst_scalar_ty.intInfo(zcu); | |
| 5970 | if (inst_int_info.bits > 128) try w.print(", {f}", .{fmtUnsignedIntLiteralSmall( | |
| 5971 | target, | |
| 5972 | .uint16_t, | |
| 5973 | inst_int_info.bits, | |
| 5974 | false, | |
| 5975 | 10, | |
| 5976 | .lower, | |
| 5977 | )}); | |
| 5978 | } | |
| 5874 | 5979 | try w.writeByte(')'); |
| 5875 | 5980 | if (inst_scalar_ty.isInt(zcu) and scalar_ty.isRuntimeFloat()) { |
| 5876 | try f.dg.renderBuiltinInfo(w, inst_scalar_ty, .bits); | |
| 5877 | try w.writeByte(')'); | |
| 5981 | const inst_int_info = inst_scalar_ty.intInfo(zcu); | |
| 5982 | if (inst_int_info.bits <= 128) { | |
| 5983 | try w.print(", {f}", .{ | |
| 5984 | try f.dg.fmtIntLiteralDec(try pt.intValue(.u8, inst_int_info.bits), .other), | |
| 5985 | }); | |
| 5986 | try w.writeByte(')'); | |
| 5987 | } | |
| 5988 | } | |
| 5989 | if (ref_ret) { | |
| 5990 | const inst_int_info = inst_scalar_ty.intInfo(zcu); | |
| 5991 | if (inst_int_info.bits <= 128) { | |
| 5992 | try f.dg.renderBuiltinInfo(w, inst_scalar_ty, .none); | |
| 5993 | try w.writeByte(')'); | |
| 5994 | } | |
| 5878 | 5995 | } |
| 5879 | 5996 | try w.writeByte(';'); |
| 5880 | 5997 | try f.newline(); |
| ... | ... | @@ -5893,18 +6010,21 @@ fn airUnBuiltinCall( |
| 5893 | 6010 | const pt = f.dg.pt; |
| 5894 | 6011 | const zcu = pt.zcu; |
| 5895 | 6012 | |
| 5896 | const operand = try f.resolveInst(operand_ref); | |
| 5897 | try reap(f, inst, &.{operand_ref}); | |
| 5898 | 6013 | const inst_ty = f.typeOfIndex(inst); |
| 5899 | 6014 | const inst_scalar_ty = inst_ty.scalarType(zcu); |
| 5900 | 6015 | const operand_ty = f.typeOf(operand_ref); |
| 5901 | 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}); | |
| 5902 | 6021 | |
| 5903 | 6022 | const ref_ret = lowersToBigInt(inst_scalar_ty, zcu); |
| 5904 | 6023 | const ref_arg = lowersToBigInt(scalar_ty, zcu); |
| 5905 | 6024 | |
| 5906 | 6025 | const w = &f.code.writer; |
| 5907 | 6026 | const local = try f.allocLocal(inst, inst_ty); |
| 6027 | if (is_big) try reap(f, inst, &.{operand_ref}); | |
| 5908 | 6028 | const v = try Vectorize.start(f, inst, w, operand_ty); |
| 5909 | 6029 | if (!ref_ret) { |
| 5910 | 6030 | try f.writeCValue(w, local, .other); |
| ... | ... | @@ -5920,8 +6040,13 @@ fn airUnBuiltinCall( |
| 5920 | 6040 | try v.elem(f, w); |
| 5921 | 6041 | try w.writeAll(", "); |
| 5922 | 6042 | } |
| 5923 | if (ref_arg) try w.writeByte('&'); | |
| 5924 | try f.writeCValue(w, operand, .other); | |
| 6043 | if (ref_arg) { | |
| 6044 | try w.writeByte('&'); | |
| 6045 | switch (operand) { | |
| 6046 | .constant => |val| try f.dg.renderValueAsLvalue(w, val), | |
| 6047 | else => try f.writeCValue(w, operand, .other), | |
| 6048 | } | |
| 6049 | } else try f.writeCValue(w, operand, .other); | |
| 5925 | 6050 | try v.elem(f, w); |
| 5926 | 6051 | try f.dg.renderBuiltinInfo(w, scalar_ty, info); |
| 5927 | 6052 | try w.writeAll(");"); |
| ... | ... | @@ -5941,8 +6066,9 @@ fn airBinBuiltinCall( |
| 5941 | 6066 | const zcu = pt.zcu; |
| 5942 | 6067 | const bin_op = f.air.instructions.items(.data)[@backingInt(inst)].bin_op; |
| 5943 | 6068 | |
| 5944 | const operand_ty = f.typeOf(bin_op.lhs); | |
| 5945 | const is_big = lowersToBigInt(operand_ty, zcu); | |
| 6069 | const lhs_ty = f.typeOf(bin_op.lhs); | |
| 6070 | const rhs_ty = f.typeOf(bin_op.rhs); | |
| 6071 | const is_big = lowersToBigInt(lhs_ty, zcu); | |
| 5946 | 6072 | |
| 5947 | 6073 | const lhs = try f.resolveInst(bin_op.lhs); |
| 5948 | 6074 | const rhs = try f.resolveInst(bin_op.rhs); |
| ... | ... | @@ -5950,22 +6076,31 @@ fn airBinBuiltinCall( |
| 5950 | 6076 | |
| 5951 | 6077 | const inst_ty = f.typeOfIndex(inst); |
| 5952 | 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); | |
| 5954 | 6081 | |
| 5955 | 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); | |
| 5957 | 6085 | |
| 5958 | 6086 | const w = &f.code.writer; |
| 5959 | 6087 | const local = try f.allocLocal(inst, inst_ty); |
| 5960 | 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 | 6090 | if (!ref_ret) { |
| 5963 | 6091 | try f.writeCValue(w, local, .other); |
| 5964 | 6092 | try v.elem(f, w); |
| 5965 | 6093 | try w.writeAll(" = "); |
| 5966 | 6094 | } |
| 5967 | 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 | 6104 | try w.writeByte('('); |
| 5970 | 6105 | if (ref_ret) { |
| 5971 | 6106 | try w.writeByte('&'); |
| ... | ... | @@ -5973,15 +6108,45 @@ fn airBinBuiltinCall( |
| 5973 | 6108 | try v.elem(f, w); |
| 5974 | 6109 | try w.writeAll(", "); |
| 5975 | 6110 | } |
| 5976 | if (ref_arg) try w.writeByte('&'); | |
| 5977 | try f.writeCValue(w, lhs, .other); | |
| 6111 | if (ref_lhs) { | |
| 6112 | try w.writeByte('&'); | |
| 6113 | switch (lhs) { | |
| 6114 | .constant => |lhs_val| try f.dg.renderValueAsLvalue(w, lhs_val), | |
| 6115 | else => try f.writeCValue(w, lhs, .other), | |
| 6116 | } | |
| 6117 | } else try f.writeCValue(w, lhs, .other); | |
| 5978 | 6118 | try v.elem(f, w); |
| 5979 | 6119 | try w.writeAll(", "); |
| 5980 | if (ref_arg) try w.writeByte('&'); | |
| 5981 | try f.writeCValue(w, rhs, .other); | |
| 5982 | if (f.typeOf(bin_op.rhs).isVector(zcu)) try v.elem(f, w); | |
| 5983 | try f.dg.renderBuiltinInfo(w, scalar_ty, info); | |
| 5984 | try w.writeAll(");\n"); | |
| 6120 | if (ref_rhs) { | |
| 6121 | try w.writeByte('&'); | |
| 6122 | switch (rhs) { | |
| 6123 | .constant => |rhs_val| try f.dg.renderValueAsLvalue(w, rhs_val), | |
| 6124 | else => try f.writeCValue(w, rhs, .other), | |
| 6125 | } | |
| 6126 | } else try f.writeCValue(w, rhs, .other); | |
| 6127 | try v.elem(f, w); | |
| 6128 | try f.dg.renderBuiltinInfo(w, lhs_scalar_ty, info: switch (info) { | |
| 6129 | .none => .none, | |
| 6130 | .bits, .bits_none => .bits, | |
| 6131 | .big_temp_bits => { | |
| 6132 | if (lowersToBigInt(lhs_scalar_ty, zcu)) { | |
| 6133 | const temp_local = try f.allocAlignedLocal(inst, .{ | |
| 6134 | .type = lhs_scalar_ty, | |
| 6135 | .array_len = 2, | |
| 6136 | }); | |
| 6137 | try w.writeAll(", &"); | |
| 6138 | try f.writeCValue(w, temp_local, .other); | |
| 6139 | try freeLocal(f, inst, temp_local.new_local, null); | |
| 6140 | } | |
| 6141 | break :info .none; | |
| 6142 | }, | |
| 6143 | }); | |
| 6144 | switch (info) { | |
| 6145 | .none, .bits, .big_temp_bits => {}, | |
| 6146 | .bits_none => try f.dg.renderBuiltinInfo(w, rhs_scalar_ty, .none), | |
| 6147 | } | |
| 6148 | try w.writeAll(");"); | |
| 6149 | try f.newline(); | |
| 5985 | 6150 | try v.end(f, inst, w); |
| 5986 | 6151 | |
| 5987 | 6152 | return local; |
| ... | ... | @@ -6029,12 +6194,22 @@ fn airCmpBuiltinCall( |
| 6029 | 6194 | try v.elem(f, w); |
| 6030 | 6195 | try w.writeAll(", "); |
| 6031 | 6196 | } |
| 6032 | if (ref_arg) try w.writeByte('&'); | |
| 6033 | try f.writeCValue(w, lhs, .other); | |
| 6197 | if (ref_arg) { | |
| 6198 | try w.writeByte('&'); | |
| 6199 | switch (lhs) { | |
| 6200 | .constant => |lhs_val| try f.dg.renderValueAsLvalue(w, lhs_val), | |
| 6201 | else => try f.writeCValue(w, lhs, .other), | |
| 6202 | } | |
| 6203 | } else try f.writeCValue(w, lhs, .other); | |
| 6034 | 6204 | try v.elem(f, w); |
| 6035 | 6205 | try w.writeAll(", "); |
| 6036 | if (ref_arg) try w.writeByte('&'); | |
| 6037 | try f.writeCValue(w, rhs, .other); | |
| 6206 | if (ref_arg) { | |
| 6207 | try w.writeByte('&'); | |
| 6208 | switch (rhs) { | |
| 6209 | .constant => |rhs_val| try f.dg.renderValueAsLvalue(w, rhs_val), | |
| 6210 | else => try f.writeCValue(w, rhs, .other), | |
| 6211 | } | |
| 6212 | } else try f.writeCValue(w, rhs, .other); | |
| 6038 | 6213 | try v.elem(f, w); |
| 6039 | 6214 | try f.dg.renderBuiltinInfo(w, scalar_ty, info); |
| 6040 | 6215 | try w.writeByte(')'); |
| ... | ... | @@ -6595,7 +6770,8 @@ fn airShuffleOne(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6595 | 6770 | }, |
| 6596 | 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 | } |
| 6600 | 6776 | |
| 6601 | 6777 | return local; |
| ... | ... | @@ -6653,7 +6829,14 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6653 | 6829 | const operand_ty = f.typeOf(reduce.operand); |
| 6654 | 6830 | const w = &f.code.writer; |
| 6655 | 6831 | |
| 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 | 6840 | const op: union(enum) { |
| 6658 | 6841 | const Func = struct { operation: []const u8, info: BuiltinInfo = .none }; |
| 6659 | 6842 | builtin: Func, |
| ... | ... | @@ -6742,25 +6925,57 @@ fn airReduce(f: *Function, inst: Air.Inst.Index) !CValue { |
| 6742 | 6925 | try f.newline(); |
| 6743 | 6926 | |
| 6744 | 6927 | const v = try Vectorize.start(f, inst, w, operand_ty); |
| 6745 | try f.writeCValue(w, accum, .other); | |
| 6746 | 6928 | switch (op) { |
| 6747 | 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 | 6944 | try f.dg.renderTypeForBuiltinFnName(w, scalar_ty); |
| 6750 | 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 | 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 | 6966 | try v.elem(f, w); |
| 6755 | 6967 | try f.dg.renderBuiltinInfo(w, scalar_ty, func.info); |
| 6756 | 6968 | try w.writeByte(')'); |
| 6969 | if (is_big) try freeLocal(f, inst, prev_accum.new_local, null); | |
| 6757 | 6970 | }, |
| 6758 | 6971 | .infix => |ass| { |
| 6972 | try f.writeCValue(w, accum, .other); | |
| 6759 | 6973 | try w.writeAll(ass); |
| 6760 | 6974 | try f.writeCValue(w, operand, .other); |
| 6761 | 6975 | try v.elem(f, w); |
| 6762 | 6976 | }, |
| 6763 | 6977 | .ternary => |cmp| { |
| 6978 | try f.writeCValue(w, accum, .other); | |
| 6764 | 6979 | try w.writeAll(" = "); |
| 6765 | 6980 | try f.writeCValue(w, accum, .other); |
| 6766 | 6981 | try w.writeAll(cmp); |
| ... | ... | @@ -7097,101 +7312,6 @@ fn writeMemoryOrder(w: *Writer, order: std.lang.AtomicOrder) !void { |
| 7097 | 7312 | return w.writeAll(toMemoryOrder(order)); |
| 7098 | 7313 | } |
| 7099 | 7314 | |
| 7100 | fn 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 | ||
| 7195 | 7315 | fn toAtomicRmwSuffix(order: std.lang.AtomicRmwOp) []const u8 { |
| 7196 | 7316 | return switch (order) { |
| 7197 | 7317 | .Xchg => "xchg", |
| ... | ... | @@ -7224,17 +7344,18 @@ fn signAbbrev(signedness: std.lang.Signedness) u8 { |
| 7224 | 7344 | |
| 7225 | 7345 | fn compilerRtAbbrev(ty: Type, zcu: *Zcu, target: *const std.Target) []const u8 { |
| 7226 | 7346 | return if (ty.isInt(zcu)) switch (ty.intInfo(zcu).bits) { |
| 7347 | 0 => unreachable, | |
| 7227 | 7348 | 1...32 => "si", |
| 7228 | 7349 | 33...64 => "di", |
| 7229 | 7350 | 65...128 => "ti", |
| 7230 | else => unreachable, | |
| 7351 | else => "ei", | |
| 7231 | 7352 | } else if (ty.isRuntimeFloat()) switch (ty.floatBits(target)) { |
| 7353 | else => unreachable, | |
| 7232 | 7354 | 16 => "hf", |
| 7233 | 7355 | 32 => "sf", |
| 7234 | 7356 | 64 => "df", |
| 7235 | 7357 | 80 => "xf", |
| 7236 | 128 => "tf", | |
| 7237 | else => unreachable, | |
| 7358 | 128 => if (target.cpu.arch.isPowerPC()) "kf" else "tf", | |
| 7238 | 7359 | } else unreachable; |
| 7239 | 7360 | } |
| 7240 | 7361 | |
| ... | ... | @@ -7390,10 +7511,8 @@ fn fmtStringLiteral(str: []const u8, sentinel: ?u8) std.fmt.Alt(FormatStringCont |
| 7390 | 7511 | return .{ .data = .{ .str = str, .sentinel = sentinel } }; |
| 7391 | 7512 | } |
| 7392 | 7513 | |
| 7393 | fn undefPattern(comptime IntType: type) IntType { | |
| 7394 | const int_info = @typeInfo(IntType).int; | |
| 7395 | const UnsignedType = @Int(.unsigned, int_info.bits); | |
| 7396 | return @bitCast(@as(UnsignedType, (1 << (int_info.bits | 1)) / 3)); | |
| 7514 | fn undefPattern(comptime Result: type) Result { | |
| 7515 | return @bitCast(@as(@Int(.unsigned, @bitSizeOf(Result)), (1 << (@bitSizeOf(Result) | 1)) / 3)); | |
| 7397 | 7516 | } |
| 7398 | 7517 | |
| 7399 | 7518 | const FormatIntLiteralContext = struct { |
| ... | ... | @@ -7580,11 +7699,9 @@ const FormatSignedIntLiteralSmall = struct { |
| 7580 | 7699 | case: std.fmt.Case, |
| 7581 | 7700 | pub fn format(data: FormatSignedIntLiteralSmall, w: *Writer) Writer.Error!void { |
| 7582 | 7701 | const bits = data.int_cty.bits(data.target); |
| 7583 | const max_int: i64 = @bitCast((@as(u64, 1) << @intCast(bits - 1)) - 1); | |
| 7584 | const min_int: i64 = @bitCast(@as(u64, 1) << @intCast(bits - 1)); | |
| 7585 | if (data.val == max_int) { | |
| 7702 | if (data.val == @as(i64, std.math.maxInt(i64)) >> @intCast(64 - bits)) { | |
| 7586 | 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 | 7705 | return w.print("{s}_MIN", .{minMaxMacroPrefix(data.int_cty)}); |
| 7589 | 7706 | } |
| 7590 | 7707 | if (data.val < 0) try w.writeByte('-'); |
| ... | ... | @@ -7596,7 +7713,7 @@ const FormatSignedIntLiteralSmall = struct { |
| 7596 | 7713 | 16 => try w.writeAll("0x"), |
| 7597 | 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 | 7717 | try w.printInt(@abs(data.val), data.base, data.case, .{}); |
| 7601 | 7718 | try w.writeAll(intLiteralSuffix(data.int_cty)); |
| 7602 | 7719 | } |
| ... | ... | @@ -7610,8 +7727,7 @@ const FormatUnsignedIntLiteralSmall = struct { |
| 7610 | 7727 | case: std.fmt.Case, |
| 7611 | 7728 | pub fn format(data: FormatUnsignedIntLiteralSmall, w: *Writer) Writer.Error!void { |
| 7612 | 7729 | const bits = data.int_cty.bits(data.target); |
| 7613 | const max_int: u64 = @as(u64, std.math.maxInt(u64)) >> @intCast(64 - bits); | |
| 7614 | if (data.val == max_int) { | |
| 7730 | if (data.val == @as(u64, std.math.maxInt(u64)) >> @intCast(64 - bits)) { | |
| 7615 | 7731 | return w.print("{s}_MAX", .{minMaxMacroPrefix(data.int_cty)}); |
| 7616 | 7732 | } |
| 7617 | 7733 | try w.writeAll(intLiteralPrefix(data.int_cty, data.is_global)); |
| ... | ... | @@ -7735,6 +7851,31 @@ fn intLiteralSuffix(cty: CType.Int) []const u8 { |
| 7735 | 7851 | }; |
| 7736 | 7852 | } |
| 7737 | 7853 | |
| 7854 | const 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 | }; | |
| 7866 | const 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 | ||
| 7738 | 7879 | const Materialize = struct { |
| 7739 | 7880 | local: CValue, |
| 7740 | 7881 |
src/codegen/c/type.zig+204-23| ... | ... | @@ -44,8 +44,181 @@ pub const CType = union(enum) { |
| 44 | 44 | param_tys: []const CType, |
| 45 | 45 | ret_ty: *const CType, |
| 46 | 46 | varargs: bool, |
| 47 | cc: CallingConvention, | |
| 47 | 48 | }, |
| 48 | 49 | |
| 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 | 222 | /// Returns `true` if this node has a postfix operator, meaning an `[...]` or `(...)` appears |
| 50 | 223 | /// after the identifier in a declarator with this type. In this case, if this node is wrapped |
| 51 | 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 | 303 | pub fn bits(int: Int, target: *const std.Target) u16 { |
| 131 | 304 | return switch (int) { |
| 132 | 305 | // zig fmt: off |
| 133 | .char => target.cTypeBitSize(.char), | |
| 134 | ||
| 135 | .@"unsigned short" => target.cTypeBitSize(.ushort), | |
| 136 | .@"unsigned int" => target.cTypeBitSize(.uint), | |
| 137 | .@"unsigned long" => target.cTypeBitSize(.ulong), | |
| 138 | .@"unsigned long long" => target.cTypeBitSize(.ulonglong), | |
| 139 | ||
| 140 | .@"signed short" => target.cTypeBitSize(.short), | |
| 141 | .@"signed int" => target.cTypeBitSize(.int), | |
| 142 | .@"signed long" => target.cTypeBitSize(.long), | |
| 143 | .@"signed long long" => target.cTypeBitSize(.longlong), | |
| 144 | ||
| 145 | .uintptr_t, .intptr_t => target.ptrBitWidth(), | |
| 146 | ||
| 147 | .uint8_t, .int8_t => 8, | |
| 148 | .uint16_t, .int16_t => 16, | |
| 149 | .uint24_t, .int24_t => 24, | |
| 150 | .uint32_t, .int32_t => 32, | |
| 151 | .uint48_t, .int48_t => 48, | |
| 152 | .uint64_t, .int64_t => 64, | |
| 153 | .zig_u128, .zig_i128 => 128, | |
| 154 | // zig fmt: on | |
| 306 | .char => target.cTypeBitSize(.char).?, | |
| 307 | ||
| 308 | .@"unsigned short" => target.cTypeBitSize(.ushort).?, | |
| 309 | .@"unsigned int" => target.cTypeBitSize(.uint).?, | |
| 310 | .@"unsigned long" => target.cTypeBitSize(.ulong).?, | |
| 311 | .@"unsigned long long" => target.cTypeBitSize(.ulonglong).?, | |
| 312 | ||
| 313 | .@"signed short" => target.cTypeBitSize(.short).?, | |
| 314 | .@"signed int" => target.cTypeBitSize(.int).?, | |
| 315 | .@"signed long" => target.cTypeBitSize(.long).?, | |
| 316 | .@"signed long long" => target.cTypeBitSize(.longlong).?, | |
| 317 | ||
| 318 | .uintptr_t, .intptr_t => target.ptrBitWidth(), | |
| 319 | ||
| 320 | .uint8_t, .int8_t => 8, | |
| 321 | .uint16_t, .int16_t => 16, | |
| 322 | .uint24_t, .int24_t => 24, | |
| 323 | .uint32_t, .int32_t => 32, | |
| 324 | .uint48_t, .int48_t => 48, | |
| 325 | .uint64_t, .int64_t => 64, | |
| 326 | .zig_u128, .zig_i128 => 128, | |
| 327 | // zig fmt: on | |
| 155 | 328 | }; |
| 156 | 329 | } |
| 157 | 330 | }; |
| ... | ... | @@ -376,6 +549,7 @@ pub const CType = union(enum) { |
| 376 | 549 | .ret_ty = ret_cty_buf, |
| 377 | 550 | .param_tys = param_cty_buf, |
| 378 | 551 | .varargs = func_type.is_var_args, |
| 552 | .cc = .fromLang(func_type.cc, zcu.getTarget()), | |
| 379 | 553 | } }; |
| 380 | 554 | } |
| 381 | 555 | try deps.addType(gpa, cur_ty, allow_incomplete); |
| ... | ... | @@ -763,6 +937,13 @@ pub const CType = union(enum) { |
| 763 | 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 | 947 | try w.writeByte('*'); |
| 767 | 948 | }, |
| 768 | 949 | |
| ... | ... | @@ -812,7 +993,7 @@ pub const CType = union(enum) { |
| 812 | 993 | => {}, |
| 813 | 994 | |
| 814 | 995 | .pointer => |ptr| { |
| 815 | // Match opening paren "(" write `writeTypePrefix`. | |
| 996 | // Match opening paren "(" in `writeTypePrefix`. | |
| 816 | 997 | switch (ptr.elem_ty.kind()) { |
| 817 | 998 | .specifier, .pointer => {}, |
| 818 | 999 | .postfix_op => try w.writeByte(')'), |
src/codegen/c/type/render_defs.zig+143-155| ... | ... | @@ -21,16 +21,21 @@ pub fn defineAligned( |
| 21 | 21 | if (complete and alignment.compareStrict(.lt, ty.abiAlignment(zcu))) { |
| 22 | 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 | 25 | cty.fmtDeclaratorPrefix(zcu), |
| 26 | 26 | name_cty.fmtTypeName(zcu), |
| 27 | 27 | cty.fmtDeclaratorSuffix(zcu), |
| 28 | }); | |
| 29 | if (!zcu.comp.config.root_strip) try w.print(" /* align({d}) {f} */", .{ | |
| 28 | 30 | alignment.toByteUnits().?, |
| 29 | 31 | ty.fmt(pt), |
| 30 | 32 | }); |
| 33 | try w.writeByte('\n'); | |
| 31 | 34 | } |
| 32 | 35 | /// Renders the definition of a big-int `struct`. |
| 33 | 36 | pub 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 | 39 | const name_cty: CType = .{ .bigint = .{ |
| 35 | 40 | .limb_size = big.limb_size, |
| 36 | 41 | .limbs_len = big.limbs_len, |
| ... | ... | @@ -41,12 +46,20 @@ pub fn defineBigInt(big: CType.BigInt, w: *Writer, zcu: *const Zcu) Writer.Error |
| 41 | 46 | .elem_ty = &limb_cty, |
| 42 | 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 | 50 | name_cty.fmtTypeName(zcu), |
| 46 | 51 | array_cty.fmtDeclaratorPrefix(zcu), |
| 47 | 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 | } |
| 51 | 64 | |
| 52 | 65 | /// Renders a forward declaration of the `struct` which represents an error union whose payload type |
| ... | ... | @@ -81,27 +94,28 @@ pub fn errunionDefineComplete( |
| 81 | 94 | if (payload_ty.hasRuntimeBits(zcu)) { |
| 82 | 95 | const payload_cty: CType = try .lower(payload_ty, deps, arena, zcu); |
| 83 | 96 | try w.print( |
| 84 | \\{f} {{ /* anyerror!{f} */ | |
| 97 | \\{f} {{ | |
| 85 | 98 | \\ {f}payload{f}; |
| 86 | 99 | \\ {f}error{f}; |
| 87 | 100 | \\}}; |
| 88 | \\ | |
| 89 | 101 | , .{ |
| 90 | 102 | name_cty.fmtTypeName(zcu), |
| 91 | payload_ty.fmt(pt), | |
| 92 | 103 | payload_cty.fmtDeclaratorPrefix(zcu), |
| 93 | 104 | payload_cty.fmtDeclaratorSuffix(zcu), |
| 94 | 105 | error_cty.fmtDeclaratorPrefix(zcu), |
| 95 | 106 | error_cty.fmtDeclaratorSuffix(zcu), |
| 96 | 107 | }); |
| 97 | 108 | } else { |
| 98 | try w.print("{f} {{ {f}error{f}; }}; /* anyerror!{f} */\n", .{ | |
| 109 | try w.print("{f} {{ {f}error{f}; }};", .{ | |
| 99 | 110 | name_cty.fmtTypeName(zcu), |
| 100 | 111 | error_cty.fmtDeclaratorPrefix(zcu), |
| 101 | 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 | } |
| 106 | 120 | |
| 107 | 121 | /// 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 | 155 | }, |
| 142 | 156 | else => return, |
| 143 | 157 | }; |
| 144 | try w.print("typedef void {f}; /* {f} */\n", .{ | |
| 158 | try w.print("typedef void {f};", .{ | |
| 145 | 159 | name_cty.fmtTypeName(zcu), |
| 160 | }); | |
| 161 | if (!zcu.comp.config.root_strip) try w.print(" /* {f} */", .{ | |
| 146 | 162 | ty.fmt(pt), |
| 147 | 163 | }); |
| 164 | try w.writeByte('\n'); | |
| 148 | 165 | } |
| 149 | 166 | |
| 150 | 167 | /// 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 | 180 | |
| 164 | 181 | ty.assertHasLayout(zcu); |
| 165 | 182 | |
| 166 | switch (ty.zigTypeTag(zcu)) { | |
| 183 | const check_cty = check_cty: switch (ty.zigTypeTag(zcu)) { | |
| 167 | 184 | .@"fn" => if (!ty.fnHasRuntimeBits(zcu)) { |
| 168 | 185 | const name_cty: CType = .{ .@"fn" = ty }; |
| 169 | try w.print("typedef void {f}; /* {f} */\n", .{ | |
| 186 | try w.print("typedef void {f};", .{ | |
| 170 | 187 | name_cty.fmtTypeName(zcu), |
| 171 | ty.fmt(pt), | |
| 172 | 188 | }); |
| 189 | break :check_cty null; | |
| 173 | 190 | } else { |
| 174 | 191 | const ip = &zcu.intern_pool; |
| 175 | 192 | const func_type = ip.indexToKey(ty.toIntern()).func_type; |
| ... | ... | @@ -186,10 +203,12 @@ pub fn defineComplete( |
| 186 | 203 | const name_cty: CType = .{ .@"fn" = ty }; |
| 187 | 204 | const ret_cty: CType = try .lower(effective_ret_ty, deps, arena, zcu); |
| 188 | 205 | |
| 189 | try w.print("typedef {f}{f}(", .{ | |
| 190 | ret_cty.fmtDeclaratorPrefix(zcu), | |
| 191 | name_cty.fmtTypeName(zcu), | |
| 192 | }); | |
| 206 | try w.print("typedef {f}", .{ret_cty.fmtDeclaratorPrefix(zcu)}); | |
| 207 | switch (CType.CallingConvention.fromLang(func_type.cc, zcu.getTarget())) { | |
| 208 | .c => {}, | |
| 209 | else => |cc| try w.print("zig_callconv({t}) ", .{cc}), | |
| 210 | } | |
| 211 | try w.print("{f}(", .{name_cty.fmtTypeName(zcu)}); | |
| 193 | 212 | var any_params = false; |
| 194 | 213 | for (func_type.param_types.get(ip)) |param_ty_ip| { |
| 195 | 214 | const param_ty: Type = .fromInterned(param_ty_ip); |
| ... | ... | @@ -205,88 +224,85 @@ pub fn defineComplete( |
| 205 | 224 | } else if (!any_params) { |
| 206 | 225 | try w.writeAll("void"); |
| 207 | 226 | } |
| 208 | try w.print("){f}; /* {f} */\n", .{ | |
| 209 | ret_cty.fmtDeclaratorSuffixIgnoreNonstring(zcu), | |
| 210 | ty.fmt(pt), | |
| 211 | }); | |
| 227 | try w.print("){f};", .{ret_cty.fmtDeclaratorSuffixIgnoreNonstring(zcu)}); | |
| 228 | break :check_cty null; | |
| 212 | 229 | }, |
| 213 | 230 | .@"enum" => { |
| 214 | 231 | const name_cty: CType = .{ .@"enum" = ty }; |
| 215 | 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 | 234 | cty.fmtDeclaratorPrefix(zcu), |
| 218 | 235 | name_cty.fmtTypeName(zcu), |
| 219 | 236 | cty.fmtDeclaratorSuffix(zcu), |
| 220 | ty.fmt(pt), | |
| 221 | 237 | }); |
| 238 | break :check_cty null; | |
| 222 | 239 | }, |
| 223 | .@"struct" => if (ty.isTuple(zcu)) { | |
| 224 | try defineTuple(ty, deps, arena, w, pt); | |
| 225 | } else switch (ty.containerLayout(zcu)) { | |
| 226 | .auto, .@"extern" => try defineStruct(ty, deps, arena, w, pt), | |
| 240 | .@"struct" => if (ty.isTuple(zcu)) | |
| 241 | if (ty.hasRuntimeBits(zcu)) try defineTuple(ty, deps, arena, w, pt) else return | |
| 242 | else switch (ty.containerLayout(zcu)) { | |
| 243 | .auto, .@"extern" => if (ty.hasRuntimeBits(zcu)) try defineStruct(ty, deps, arena, w, pt) else return, | |
| 227 | 244 | .@"packed" => try defineBitpack(ty, deps, arena, w, pt), |
| 228 | 245 | }, |
| 229 | 246 | .@"union" => switch (ty.containerLayout(zcu)) { |
| 230 | .auto => try defineUnionAuto(ty, deps, arena, w, pt), | |
| 231 | .@"extern" => try defineUnionExtern(ty, deps, arena, w, pt), | |
| 247 | .auto => if (ty.hasRuntimeBits(zcu)) try defineUnionAuto(ty, deps, arena, w, pt) else return, | |
| 248 | .@"extern" => if (ty.hasRuntimeBits(zcu)) try defineUnionExtern(ty, deps, arena, w, pt) else return, | |
| 232 | 249 | .@"packed" => try defineBitpack(ty, deps, arena, w, pt), |
| 233 | 250 | }, |
| 234 | 251 | .pointer => if (ty.isSlice(zcu)) { |
| 235 | 252 | const name_cty: CType = .{ .slice = ty }; |
| 236 | 253 | const ptr_cty: CType = try .lower(ty.slicePtrFieldType(zcu), deps, arena, zcu); |
| 237 | 254 | try w.print( |
| 238 | \\{f} {{ /* {f} */ | |
| 255 | \\{f} {{ | |
| 239 | 256 | \\ {f}ptr{f}; |
| 240 | \\ size_t len; | |
| 257 | \\ uintptr_t len; | |
| 241 | 258 | \\}}; |
| 242 | \\ | |
| 243 | 259 | , .{ |
| 244 | 260 | name_cty.fmtTypeName(zcu), |
| 245 | ty.fmt(pt), | |
| 246 | 261 | ptr_cty.fmtDeclaratorPrefix(zcu), |
| 247 | 262 | ptr_cty.fmtDeclaratorSuffix(zcu), |
| 248 | 263 | }); |
| 249 | // Don't bother with `writeStaticAssertLayout`---there's not really any way we could mess | |
| 250 | // slices up, and they're all obviously the same layout. | |
| 251 | }, | |
| 264 | break :check_cty switch (ty.toIntern()) { | |
| 265 | .slice_const_u8_sentinel_0_type => name_cty, | |
| 266 | else => null, | |
| 267 | }; | |
| 268 | } else return, | |
| 252 | 269 | .optional => switch (CType.classifyOptional(ty, zcu)) { |
| 253 | 270 | .error_set, |
| 254 | 271 | .ptr_like, |
| 255 | 272 | .slice_like, |
| 256 | 273 | .npv_payload, |
| 257 | => {}, | |
| 274 | => return, | |
| 258 | 275 | |
| 259 | 276 | .opv_payload => { |
| 260 | 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 | 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 | }, |
| 267 | 286 | |
| 268 | 287 | .@"struct" => { |
| 269 | 288 | const name_cty: CType = .{ .opt = ty }; |
| 270 | 289 | const payload_cty: CType = try .lower(ty.optionalChild(zcu), deps, arena, zcu); |
| 271 | 290 | try w.print( |
| 272 | \\{f} {{ /* {f} */ | |
| 291 | \\{f} {{ | |
| 273 | 292 | \\ {f}payload{f}; |
| 274 | 293 | \\ bool is_null; |
| 275 | 294 | \\}}; |
| 276 | \\ | |
| 277 | 295 | , .{ |
| 278 | 296 | name_cty.fmtTypeName(zcu), |
| 279 | ty.fmt(pt), | |
| 280 | 297 | payload_cty.fmtDeclaratorPrefix(zcu), |
| 281 | 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 | 303 | .array => if (ty.hasRuntimeBits(zcu)) { |
| 287 | const elem_ty = ty.childType(zcu); | |
| 288 | 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 | 306 | const array_cty: CType = .{ .array = .{ |
| 291 | 307 | .len = ty.arrayLenIncludingSentinel(zcu), |
| 292 | 308 | .elem_ty = &elem_cty, |
| ... | ... | @@ -296,43 +312,35 @@ pub fn defineComplete( |
| 296 | 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)) { | |
| 300 | try w.print("{f} {{ {f}array{f}; }}; /* {f} */\n", .{ | |
| 301 | name_cty.fmtTypeName(zcu), | |
| 302 | array_cty.fmtDeclaratorPrefix(zcu), | |
| 303 | array_cty.fmtDeclaratorSuffix(zcu), | |
| 304 | ty.fmt(pt), | |
| 305 | }); | |
| 306 | } else { | |
| 307 | try w.print("zig_packed({f} {{ zig_under_align({d}) {f}array{f}; }}); /* {f} */\n", .{ | |
| 308 | name_cty.fmtTypeName(zcu), | |
| 309 | elem_ty.abiAlignment(zcu).toByteUnits().?, | |
| 310 | array_cty.fmtDeclaratorPrefix(zcu), | |
| 311 | array_cty.fmtDeclaratorSuffix(zcu), | |
| 312 | ty.fmt(pt), | |
| 313 | }); | |
| 314 | } | |
| 315 | try writeStaticAssertLayout(ty, name_cty, w, zcu); | |
| 316 | }, | |
| 315 | try w.print("{f} {{ {f}array{f}; }};", .{ | |
| 316 | name_cty.fmtTypeName(zcu), | |
| 317 | array_cty.fmtDeclaratorPrefix(zcu), | |
| 318 | array_cty.fmtDeclaratorSuffix(zcu), | |
| 319 | }); | |
| 320 | break :check_cty name_cty; | |
| 321 | } else return, | |
| 317 | 322 | .vector => if (ty.hasRuntimeBits(zcu)) { |
| 318 | const elem_ty = ty.childType(zcu); | |
| 319 | 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 | 325 | const array_cty: CType = .{ .array = .{ |
| 322 | 326 | .len = ty.arrayLenIncludingSentinel(zcu), |
| 323 | 327 | .elem_ty = &elem_cty, |
| 324 | 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 | 331 | name_cty.fmtTypeName(zcu), |
| 328 | 332 | array_cty.fmtDeclaratorPrefix(zcu), |
| 329 | 333 | array_cty.fmtDeclaratorSuffix(zcu), |
| 330 | ty.fmt(pt), | |
| 331 | 334 | }); |
| 332 | try writeStaticAssertLayout(ty, name_cty, w, zcu); | |
| 333 | }, | |
| 334 | else => {}, | |
| 335 | } | |
| 335 | break :check_cty name_cty; | |
| 336 | } else return, | |
| 337 | else => return, | |
| 338 | }; | |
| 339 | if (!zcu.comp.config.root_strip) try w.print(" /* {f} */", .{ | |
| 340 | ty.fmt(pt), | |
| 341 | }); | |
| 342 | try w.writeByte('\n'); | |
| 343 | if (check_cty) |cty| try writeStaticAssertTypeLayout(ty, cty, w, zcu); | |
| 336 | 344 | } |
| 337 | 345 | fn defineBitpack( |
| 338 | 346 | ty: Type, |
| ... | ... | @@ -340,16 +348,16 @@ fn defineBitpack( |
| 340 | 348 | arena: Allocator, |
| 341 | 349 | w: *Writer, |
| 342 | 350 | pt: Zcu.PerThread, |
| 343 | ) (Allocator.Error || Writer.Error)!void { | |
| 351 | ) (Allocator.Error || Writer.Error)!?CType { | |
| 344 | 352 | const zcu = pt.zcu; |
| 345 | 353 | const name_cty: CType = .{ .bitpack = ty }; |
| 346 | 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 | 356 | cty.fmtDeclaratorPrefix(zcu), |
| 349 | 357 | name_cty.fmtTypeName(zcu), |
| 350 | 358 | cty.fmtDeclaratorSuffix(zcu), |
| 351 | ty.fmt(pt), | |
| 352 | 359 | }); |
| 360 | return null; | |
| 353 | 361 | } |
| 354 | 362 | fn defineTuple( |
| 355 | 363 | ty: Type, |
| ... | ... | @@ -357,72 +365,54 @@ fn defineTuple( |
| 357 | 365 | arena: Allocator, |
| 358 | 366 | w: *Writer, |
| 359 | 367 | pt: Zcu.PerThread, |
| 360 | ) (Allocator.Error || Writer.Error)!void { | |
| 368 | ) (Allocator.Error || Writer.Error)!CType { | |
| 361 | 369 | const zcu = pt.zcu; |
| 362 | if (!ty.hasRuntimeBits(zcu)) return; | |
| 363 | 370 | const ip = &zcu.intern_pool; |
| 364 | 371 | const tuple = ip.indexToKey(ty.toIntern()).tuple_type; |
| 365 | 372 | |
| 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. | |
| 367 | 375 | |
| 368 | // If there are any underaligned fields, we need to byte-pack the tuple. | |
| 369 | const pack: bool = pack: { | |
| 370 | var offset: u64 = 0; | |
| 371 | for (tuple.types.get(ip)) |field_ty_ip| { | |
| 372 | const field_ty: Type = .fromInterned(field_ty_ip); | |
| 373 | if (!field_ty.hasRuntimeBits(zcu)) continue; | |
| 374 | const natural_align = field_ty.defaultStructFieldAlignment(.auto, zcu); | |
| 375 | const natural_offset = natural_align.forward(offset); | |
| 376 | offset = field_ty.abiAlignment(zcu).forward(offset); | |
| 377 | if (offset < natural_offset) break :pack true; | |
| 378 | // Also pack if any field is more aligned than the tuple should be. | |
| 379 | if (natural_align.compareStrict(.gt, tuple_align)) break :pack true; | |
| 380 | offset += field_ty.abiSize(zcu); | |
| 381 | } | |
| 382 | break :pack false; | |
| 383 | }; | |
| 376 | const tuple_align = ty.abiAlignment(zcu); | |
| 384 | 377 | |
| 385 | 378 | // If the alignment of other fields would not give the tuple sufficient alignment, we |
| 386 | 379 | // need to align the first field (which does not affect its offset, because 0 is always |
| 387 | 380 | // well-aligned) to indirectly specify the tuple alignment. |
| 388 | const overalign: bool = switch (pack) { | |
| 389 | true => tuple_align.compareStrict(.gt, .@"1"), | |
| 390 | false => for (tuple.types.get(ip)) |field_ty_ip| { | |
| 391 | const field_ty: Type = .fromInterned(field_ty_ip); | |
| 392 | if (!field_ty.hasRuntimeBits(zcu)) continue; | |
| 393 | const natural_align = field_ty.defaultStructFieldAlignment(.auto, zcu); | |
| 394 | if (natural_align.compareStrict(.gte, tuple_align)) break false; | |
| 395 | } else true, | |
| 396 | }; | |
| 381 | const overalign: bool = for (tuple.types.get(ip)) |field_ty_ip| { | |
| 382 | const field_ty: Type = .fromInterned(field_ty_ip); | |
| 383 | if (!field_ty.hasRuntimeBits(zcu)) continue; | |
| 384 | const natural_align = field_ty.abiAlignment(zcu); | |
| 385 | if (natural_align.compareStrict(.gte, tuple_align)) break false; | |
| 386 | } else true; | |
| 397 | 387 | |
| 398 | if (pack) try w.writeAll("zig_packed("); | |
| 399 | 388 | const name_cty: CType = .{ .@"struct" = ty }; |
| 400 | try w.print("{f} {{ /* {f} */\n", .{ | |
| 389 | try w.print("{f} {{\n", .{ | |
| 401 | 390 | name_cty.fmtTypeName(zcu), |
| 402 | ty.fmt(pt), | |
| 403 | 391 | }); |
| 404 | 392 | var zig_offset: u64 = 0; |
| 405 | 393 | var c_offset: u64 = 0; |
| 406 | 394 | for (tuple.types.get(ip), tuple.values.get(ip), 0..) |field_ty_ip, field_val_ip, field_index| { |
| 407 | 395 | if (field_val_ip != .none) continue; // `comptime` field |
| 408 | 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 | 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 | 401 | try w.writeByte(' '); |
| 413 | 402 | if (zig_offset == 0 and overalign) { |
| 414 | 403 | // This is the first field; specify its alignment to align the tuple. |
| 415 | 404 | try writeFieldAlign(field_ty, tuple_align, w, zcu); |
| 416 | } else if (zig_offset > c_offset) { | |
| 417 | // This field needs to be underaligned or overaligned compared to what its | |
| 418 | // offset would otherwise be. | |
| 419 | const need_align: Alignment = .minStrict( | |
| 420 | tuple_align, // don't make the tuple more aligned than it should be | |
| 421 | .fromLog2Units(@ctz(zig_offset)), | |
| 422 | ); | |
| 423 | try writeFieldAlign(field_ty, need_align, w, zcu); | |
| 424 | c_offset = need_align.forward(c_offset); | |
| 405 | } else switch (zig_offset - c_offset) { | |
| 406 | 0 => {}, | |
| 407 | else => |need_bytes| { | |
| 408 | // This field needs to be overaligned compared to what its offset would otherwise be. | |
| 409 | const need_align: Alignment = .fromLog2Units(std.math.log2_int(u64, need_bytes) + 1); | |
| 410 | assert(need_align.compareStrict(.lte, tuple_align)); | |
| 411 | try writeFieldAlign(field_ty, need_align, w, zcu); | |
| 412 | c_offset = need_align.forward(c_offset); | |
| 413 | }, | |
| 425 | 414 | } |
| 415 | assert(c_offset == zig_offset); | |
| 426 | 416 | const field_cty: CType = try .lower(field_ty, deps, arena, zcu); |
| 427 | 417 | try w.print("{f}f{d}{f};\n", .{ |
| 428 | 418 | field_cty.fmtDeclaratorPrefix(zcu), |
| ... | ... | @@ -433,11 +423,8 @@ fn defineTuple( |
| 433 | 423 | zig_offset += field_size; |
| 434 | 424 | c_offset += field_size; |
| 435 | 425 | } |
| 436 | try w.writeByte('}'); | |
| 437 | if (pack) try w.writeByte(')'); | |
| 438 | try w.writeAll(";\n"); | |
| 439 | ||
| 440 | try writeStaticAssertLayout(ty, name_cty, w, zcu); | |
| 426 | try w.writeAll("};"); | |
| 427 | return name_cty; | |
| 441 | 428 | } |
| 442 | 429 | fn defineStruct( |
| 443 | 430 | ty: Type, |
| ... | ... | @@ -445,9 +432,8 @@ fn defineStruct( |
| 445 | 432 | arena: Allocator, |
| 446 | 433 | w: *Writer, |
| 447 | 434 | pt: Zcu.PerThread, |
| 448 | ) (Allocator.Error || Writer.Error)!void { | |
| 435 | ) (Allocator.Error || Writer.Error)!CType { | |
| 449 | 436 | const zcu = pt.zcu; |
| 450 | if (!ty.hasRuntimeBits(zcu)) return; | |
| 451 | 437 | const ip = &zcu.intern_pool; |
| 452 | 438 | |
| 453 | 439 | const struct_type = ip.loadStructType(ty.toIntern()); |
| ... | ... | @@ -459,7 +445,7 @@ fn defineStruct( |
| 459 | 445 | while (it.next()) |field_index| { |
| 460 | 446 | const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]); |
| 461 | 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 | 449 | const natural_offset = natural_align.forward(offset); |
| 464 | 450 | const actual_offset = struct_type.field_offsets.get(ip)[field_index]; |
| 465 | 451 | if (actual_offset < natural_offset) break :pack true; |
| ... | ... | @@ -480,7 +466,7 @@ fn defineStruct( |
| 480 | 466 | while (it.next()) |field_index| { |
| 481 | 467 | const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]); |
| 482 | 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 | 470 | if (natural_align.compareStrict(.gte, struct_type.alignment)) break :overalign false; |
| 485 | 471 | } |
| 486 | 472 | break :overalign true; |
| ... | ... | @@ -489,16 +475,15 @@ fn defineStruct( |
| 489 | 475 | |
| 490 | 476 | if (pack) try w.writeAll("zig_packed("); |
| 491 | 477 | const name_cty: CType = .{ .@"struct" = ty }; |
| 492 | try w.print("{f} {{ /* {f} */\n", .{ | |
| 478 | try w.print("{f} {{\n", .{ | |
| 493 | 479 | name_cty.fmtTypeName(zcu), |
| 494 | ty.fmt(pt), | |
| 495 | 480 | }); |
| 496 | 481 | var it = struct_type.iterateRuntimeOrder(ip); |
| 497 | 482 | var offset: u64 = 0; |
| 498 | 483 | while (it.next()) |field_index| { |
| 499 | 484 | const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]); |
| 500 | 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 | 487 | const natural_offset = switch (pack) { |
| 503 | 488 | true => offset, |
| 504 | 489 | false => natural_align.forward(offset), |
| ... | ... | @@ -529,9 +514,8 @@ fn defineStruct( |
| 529 | 514 | assert(struct_type.alignment.forward(offset) == struct_type.size); |
| 530 | 515 | try w.writeByte('}'); |
| 531 | 516 | if (pack) try w.writeByte(')'); |
| 532 | try w.writeAll(";\n"); | |
| 533 | ||
| 534 | try writeStaticAssertLayout(ty, name_cty, w, zcu); | |
| 517 | try w.writeByte(';'); | |
| 518 | return name_cty; | |
| 535 | 519 | } |
| 536 | 520 | fn defineUnionAuto( |
| 537 | 521 | ty: Type, |
| ... | ... | @@ -539,9 +523,8 @@ fn defineUnionAuto( |
| 539 | 523 | arena: Allocator, |
| 540 | 524 | w: *Writer, |
| 541 | 525 | pt: Zcu.PerThread, |
| 542 | ) (Allocator.Error || Writer.Error)!void { | |
| 526 | ) (Allocator.Error || Writer.Error)!CType { | |
| 543 | 527 | const zcu = pt.zcu; |
| 544 | if (!ty.hasRuntimeBits(zcu)) return; | |
| 545 | 528 | const ip = &zcu.intern_pool; |
| 546 | 529 | |
| 547 | 530 | const union_type = ip.loadUnionType(ty.toIntern()); |
| ... | ... | @@ -553,7 +536,7 @@ fn defineUnionAuto( |
| 553 | 536 | const pack: bool = for (union_type.field_types.get(ip)) |field_ty_ip| { |
| 554 | 537 | const field_ty: Type = .fromInterned(field_ty_ip); |
| 555 | 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 | 540 | if (natural_align.compareStrict(.gt, union_type.alignment)) break true; |
| 558 | 541 | // The tag will immediately follow the payload. This layout may put the tag in what would |
| 559 | 542 | // otherwise be padding on the payload union, because if the most-aligned union field is not |
| ... | ... | @@ -571,7 +554,7 @@ fn defineUnionAuto( |
| 571 | 554 | false => for (union_type.field_types.get(ip)) |field_ty_ip| { |
| 572 | 555 | const field_ty: Type = .fromInterned(field_ty_ip); |
| 573 | 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 | 558 | if (natural_align.compareStrict(.gte, union_type.alignment)) break false; |
| 576 | 559 | } else overalign: { |
| 577 | 560 | if (union_type.has_runtime_tag) { |
| ... | ... | @@ -585,9 +568,8 @@ fn defineUnionAuto( |
| 585 | 568 | const payload_has_bits = !union_type.has_runtime_tag or union_type.size > enum_tag_ty.abiSize(zcu); |
| 586 | 569 | |
| 587 | 570 | const name_cty: CType = .{ .union_auto = ty }; |
| 588 | try w.print("{f} {{ /* {f} */\n", .{ | |
| 571 | try w.print("{f} {{\n", .{ | |
| 589 | 572 | name_cty.fmtTypeName(zcu), |
| 590 | ty.fmt(pt), | |
| 591 | 573 | }); |
| 592 | 574 | if (payload_has_bits) { |
| 593 | 575 | try w.writeByte(' '); |
| ... | ... | @@ -619,9 +601,8 @@ fn defineUnionAuto( |
| 619 | 601 | tag_cty.fmtDeclaratorSuffix(zcu), |
| 620 | 602 | }); |
| 621 | 603 | } |
| 622 | try w.writeAll("};\n"); | |
| 623 | ||
| 624 | try writeStaticAssertLayout(ty, name_cty, w, zcu); | |
| 604 | try w.writeAll("};"); | |
| 605 | return name_cty; | |
| 625 | 606 | } |
| 626 | 607 | fn defineUnionExtern( |
| 627 | 608 | ty: Type, |
| ... | ... | @@ -629,9 +610,8 @@ fn defineUnionExtern( |
| 629 | 610 | arena: Allocator, |
| 630 | 611 | w: *Writer, |
| 631 | 612 | pt: Zcu.PerThread, |
| 632 | ) (Allocator.Error || Writer.Error)!void { | |
| 613 | ) (Allocator.Error || Writer.Error)!CType { | |
| 633 | 614 | const zcu = pt.zcu; |
| 634 | if (!ty.hasRuntimeBits(zcu)) return; | |
| 635 | 615 | const ip = &zcu.intern_pool; |
| 636 | 616 | |
| 637 | 617 | const union_type = ip.loadUnionType(ty.toIntern()); |
| ... | ... | @@ -642,7 +622,7 @@ fn defineUnionExtern( |
| 642 | 622 | const pack: bool = for (union_type.field_types.get(ip)) |field_ty_ip| { |
| 643 | 623 | const field_ty: Type = .fromInterned(field_ty_ip); |
| 644 | 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 | 626 | if (natural_align.compareStrict(.gt, union_type.alignment)) break true; |
| 647 | 627 | } else false; |
| 648 | 628 | |
| ... | ... | @@ -654,7 +634,7 @@ fn defineUnionExtern( |
| 654 | 634 | false => for (union_type.field_types.get(ip)) |field_ty_ip| { |
| 655 | 635 | const field_ty: Type = .fromInterned(field_ty_ip); |
| 656 | 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 | 638 | if (natural_align.compareStrict(.gte, union_type.alignment)) break false; |
| 659 | 639 | } else overalign: { |
| 660 | 640 | if (union_type.has_runtime_tag) { |
| ... | ... | @@ -668,9 +648,8 @@ fn defineUnionExtern( |
| 668 | 648 | if (pack) try w.writeAll("zig_packed("); |
| 669 | 649 | |
| 670 | 650 | const name_cty: CType = .{ .union_extern = ty }; |
| 671 | try w.print("{f} {{ /* {f} */\n", .{ | |
| 651 | try w.print("{f} {{\n", .{ | |
| 672 | 652 | name_cty.fmtTypeName(zcu), |
| 673 | ty.fmt(pt), | |
| 674 | 653 | }); |
| 675 | 654 | |
| 676 | 655 | for (0..enum_tag_ty.enumFieldCount(zcu)) |field_index| { |
| ... | ... | @@ -691,9 +670,8 @@ fn defineUnionExtern( |
| 691 | 670 | } |
| 692 | 671 | try w.writeByte('}'); |
| 693 | 672 | if (pack) try w.writeByte(')'); |
| 694 | try w.writeAll(";\n"); | |
| 695 | ||
| 696 | try writeStaticAssertLayout(ty, name_cty, w, zcu); | |
| 673 | try w.writeByte(';'); | |
| 674 | return name_cty; | |
| 697 | 675 | } |
| 698 | 676 | |
| 699 | 677 | /// Writes an annotation which, placed before a struct/union field declaration with field type `ty`, |
| ... | ... | @@ -704,7 +682,7 @@ fn writeFieldAlign( |
| 704 | 682 | w: *Writer, |
| 705 | 683 | zcu: *const Zcu, |
| 706 | 684 | ) Writer.Error!void { |
| 707 | if (alignment.compareStrict(.lt, ty.defaultStructFieldAlignment(.auto, zcu))) { | |
| 685 | if (alignment.compareStrict(.lt, ty.abiAlignment(zcu))) { | |
| 708 | 686 | try w.print("zig_under_align({d}) ", .{alignment.toByteUnits().?}); |
| 709 | 687 | } else { |
| 710 | 688 | try w.print("zig_align({d}) ", .{alignment.toByteUnits().?}); |
| ... | ... | @@ -712,19 +690,29 @@ fn writeFieldAlign( |
| 712 | 690 | } |
| 713 | 691 | |
| 714 | 692 | /// Emits static assertions that the size and alignment of `cty` match those of the Zig type `ty`. |
| 715 | fn writeStaticAssertLayout( | |
| 693 | pub fn writeStaticAssertTypeLayout( | |
| 716 | 694 | ty: Type, |
| 717 | 695 | cty: CType, |
| 718 | 696 | w: *Writer, |
| 719 | 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. | |
| 703 | pub fn writeStaticAssertCTypeLayout( | |
| 704 | cty: CType, | |
| 705 | expected_size: u64, | |
| 706 | expected_alignment: Alignment, | |
| 707 | w: *Writer, | |
| 708 | zcu: *const Zcu, | |
| 720 | 709 | ) Writer.Error!void { |
| 721 | 710 | try w.print( |
| 722 | \\zig_static_assert(sizeof ({f}) == {d}, "incorrect size"); | |
| 723 | \\zig_static_assert(_Alignof ({f}) == {d}, "incorrect alignment"); | |
| 711 | \\zig_static_assert(sizeof({f}) == {d} && zig_alignOf({f}) == {d}, "abi mismatch"); | |
| 724 | 712 | \\ |
| 725 | 713 | , .{ |
| 726 | cty.fmtTypeName(zcu), ty.abiSize(zcu), | |
| 727 | cty.fmtTypeName(zcu), ty.abiAlignment(zcu).toByteUnits().?, | |
| 714 | cty.fmtTypeName(zcu), expected_size, | |
| 715 | cty.fmtTypeName(zcu), expected_alignment.toByteUnits().?, | |
| 728 | 716 | }); |
| 729 | 717 | } |
| 730 | 718 |
src/codegen/llvm.zig+722-544| ... | ... | @@ -263,7 +263,7 @@ pub fn targetTriple(allocator: Allocator, target: *const std.Target) ![]const u8 |
| 263 | 263 | => {}, |
| 264 | 264 | .semver => |ver| if (target.os.tag == .wasi and ver.min.major == 0) { |
| 265 | 265 | try llvm_triple.print("p{d}", .{ver.min.minor}); |
| 266 | } else { | |
| 266 | } else if (target.os.tag != .amdhsa) { | |
| 267 | 267 | try llvm_triple.print("{d}.{d}.{d}", .{ |
| 268 | 268 | ver.min.major, |
| 269 | 269 | ver.min.minor, |
| ... | ... | @@ -345,160 +345,6 @@ pub fn supportsTailCall(target: *const std.Target) bool { |
| 345 | 345 | }; |
| 346 | 346 | } |
| 347 | 347 | |
| 348 | pub 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 | 348 | // Avoid depending on `bindings.CodeModel` in the bitcode-only case. |
| 503 | 349 | const CodeModel = enum { |
| 504 | 350 | default, |
| ... | ... | @@ -573,6 +419,8 @@ pub const Object = struct { |
| 573 | 419 | val: InternPool.Index, |
| 574 | 420 | @"addrspace": std.lang.AddressSpace, |
| 575 | 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 | 424 | /// Maps enum types to their corresponding LLVM functions for implementing the `tag_name` instruction. |
| 577 | 425 | enum_tag_name_map: std.AutoHashMapUnmanaged(InternPool.Index, Builder.Function.Index), |
| 578 | 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 | 464 | }); |
| 617 | 465 | errdefer builder.deinit(); |
| 618 | 466 | |
| 619 | builder.data_layout = try builder.string(dataLayout(target)); | |
| 620 | ||
| 621 | 467 | const debug_compile_unit, const debug_enums_fwd_ref, const debug_globals_fwd_ref = |
| 622 | 468 | if (!builder.strip) debug_info: { |
| 623 | 469 | // We fully resolve all paths at this point to avoid lack of |
| ... | ... | @@ -653,7 +499,7 @@ pub const Object = struct { |
| 653 | 499 | }), |
| 654 | 500 | debug_enums_fwd_ref, |
| 655 | 501 | debug_globals_fwd_ref, |
| 656 | .{ .optimized = comp.root_mod.optimize_mode != .Debug }, | |
| 502 | .{ .optimized = comp.root_mod.optimize_mode != .debug }, | |
| 657 | 503 | ); |
| 658 | 504 | |
| 659 | 505 | try builder.addNamedMetadata(try builder.string("llvm.dbg.cu"), &.{debug_compile_unit}); |
| ... | ... | @@ -693,6 +539,7 @@ pub const Object = struct { |
| 693 | 539 | .zcu = zcu, |
| 694 | 540 | .nav_map = .empty, |
| 695 | 541 | .uav_map = .empty, |
| 542 | .const_map = .empty, | |
| 696 | 543 | .enum_tag_name_map = .empty, |
| 697 | 544 | .named_enum_map = .empty, |
| 698 | 545 | .type_map = .empty, |
| ... | ... | @@ -703,21 +550,22 @@ pub const Object = struct { |
| 703 | 550 | return obj; |
| 704 | 551 | } |
| 705 | 552 | |
| 706 | pub fn deinit(self: *Object) void { | |
| 707 | const gpa = self.gpa; | |
| 708 | self.type_pool.deinit(gpa); | |
| 709 | self.lazy_abi_aligns.deinit(gpa); | |
| 710 | self.debug_enums.deinit(gpa); | |
| 711 | self.debug_globals.deinit(gpa); | |
| 712 | self.debug_file_map.deinit(gpa); | |
| 713 | self.debug_types.deinit(gpa); | |
| 714 | self.nav_map.deinit(gpa); | |
| 715 | self.uav_map.deinit(gpa); | |
| 716 | self.enum_tag_name_map.deinit(gpa); | |
| 717 | self.named_enum_map.deinit(gpa); | |
| 718 | self.type_map.deinit(gpa); | |
| 719 | self.builder.deinit(); | |
| 720 | self.* = undefined; | |
| 553 | pub fn deinit(o: *Object) void { | |
| 554 | const gpa = o.gpa; | |
| 555 | o.type_pool.deinit(gpa); | |
| 556 | o.lazy_abi_aligns.deinit(gpa); | |
| 557 | o.debug_enums.deinit(gpa); | |
| 558 | o.debug_globals.deinit(gpa); | |
| 559 | o.debug_file_map.deinit(gpa); | |
| 560 | o.debug_types.deinit(gpa); | |
| 561 | o.nav_map.deinit(gpa); | |
| 562 | o.uav_map.deinit(gpa); | |
| 563 | o.const_map.deinit(gpa); | |
| 564 | o.enum_tag_name_map.deinit(gpa); | |
| 565 | o.named_enum_map.deinit(gpa); | |
| 566 | o.type_map.deinit(gpa); | |
| 567 | o.builder.deinit(); | |
| 568 | o.* = undefined; | |
| 721 | 569 | } |
| 722 | 570 | |
| 723 | 571 | fn genErrorNameTable(o: *Object) Allocator.Error!void { |
| ... | ... | @@ -741,16 +589,16 @@ pub const Object = struct { |
| 741 | 589 | for (llvm_errors[1..], error_name_list) |*llvm_error, name| { |
| 742 | 590 | const name_string = try o.builder.stringNull(name.toSlice(ip)); |
| 743 | 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); | |
| 745 | try name_variable_index.setInitializer(name_init, &o.builder); | |
| 746 | name_variable_index.setMutability(.constant, &o.builder); | |
| 747 | name_variable_index.setAlignment(comptime .fromByteUnits(1), &o.builder); | |
| 748 | const global_index = name_variable_index.ptrConst(&o.builder).global; | |
| 749 | global_index.setLinkage(.private, &o.builder); | |
| 750 | global_index.setUnnamedAddr(.unnamed_addr, &o.builder); | |
| 592 | const name_llvm_variable = try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default); | |
| 593 | try name_llvm_variable.setInitializer(name_init, &o.builder); | |
| 594 | name_llvm_variable.setMutability(.constant, &o.builder); | |
| 595 | name_llvm_variable.setAlignment(comptime .fromByteUnits(1), &o.builder); | |
| 596 | const llvm_global = name_llvm_variable.ptrConst(&o.builder).global; | |
| 597 | llvm_global.setLinkage(.private, &o.builder); | |
| 598 | llvm_global.setUnnamedAddr(.unnamed_addr, &o.builder); | |
| 751 | 599 | |
| 752 | 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 | 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 | 618 | b.module_asm.appendSliceAssumeCapacity(assembly); |
| 771 | 619 | b.module_asm.appendAssumeCapacity('\n'); |
| 772 | 620 | } |
| 773 | if (b.module_asm.getLast()) |last| { | |
| 621 | if (b.module_asm.last()) |last| { | |
| 774 | 622 | if (last != '\n') try b.module_asm.append(gpa, '\n'); |
| 775 | 623 | } |
| 776 | 624 | } |
| ... | ... | @@ -1028,7 +876,7 @@ pub const Object = struct { |
| 1028 | 876 | |
| 1029 | 877 | const optimize_mode = comp.root_mod.optimize_mode; |
| 1030 | 878 | |
| 1031 | const opt_level: bindings.CodeGenOptLevel = if (optimize_mode == .Debug) | |
| 879 | const opt_level: bindings.CodeGenOptLevel = if (optimize_mode == .debug) | |
| 1032 | 880 | .None |
| 1033 | 881 | else |
| 1034 | 882 | .Aggressive; |
| ... | ... | @@ -1199,19 +1047,33 @@ pub const Object = struct { |
| 1199 | 1047 | global.dll_storage_class = .default; |
| 1200 | 1048 | global.unnamed_addr = .unnamed_addr; |
| 1201 | 1049 | } |
| 1202 | llvm_function.setAlignment(switch (nav.resolved.?.@"align") { | |
| 1203 | .none => fn_ty.abiAlignment(zcu).toLlvm(), | |
| 1204 | else => |a| a.toLlvm(), | |
| 1205 | }, &o.builder); | |
| 1050 | llvm_function.setAlignment(nav.resolved.?.@"align".toLlvm(), &o.builder); | |
| 1206 | 1051 | llvm_function.setSection(s: { |
| 1207 | 1052 | const section = nav.resolved.?.@"linksection".toSlice(ip) orelse break :s .none; |
| 1208 | 1053 | break :s try o.builder.string(section); |
| 1209 | 1054 | }, &o.builder); |
| 1210 | try o.addLlvmFunctionAttributes(pt, func.owner_nav, llvm_function); | |
| 1211 | 1055 | |
| 1212 | var attributes = try llvm_function.ptrConst(&o.builder).attributes.toWip(&o.builder); | |
| 1056 | var attributes: Builder.FunctionAttributes.Wip = .{}; | |
| 1213 | 1057 | defer attributes.deinit(&o.builder); |
| 1214 | 1058 | |
| 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 | 1077 | const func_analysis = func.analysisUnordered(ip); |
| 1216 | 1078 | if (func_analysis.is_noinline) { |
| 1217 | 1079 | try attributes.addFnAttr(.@"noinline", &o.builder); |
| ... | ... | @@ -1299,7 +1161,7 @@ pub const Object = struct { |
| 1299 | 1161 | .NoReturn = fn_info.return_type == .noreturn_type, |
| 1300 | 1162 | }, |
| 1301 | 1163 | .sp_flags = .{ |
| 1302 | .Optimized = owner_mod.optimize_mode != .Debug, | |
| 1164 | .Optimized = owner_mod.optimize_mode != .debug, | |
| 1303 | 1165 | .Definition = true, |
| 1304 | 1166 | .LocalToUnit = is_internal_linkage, |
| 1305 | 1167 | }, |
| ... | ... | @@ -1324,7 +1186,7 @@ pub const Object = struct { |
| 1324 | 1186 | const counters_variable = try o.builder.addVariable(anon_name, .void, .default); |
| 1325 | 1187 | try o.used.append(gpa, counters_variable.toConst(&o.builder)); |
| 1326 | 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); | |
| 1328 | 1190 | |
| 1329 | 1191 | if (target.ofmt == .macho) { |
| 1330 | 1192 | counters_variable.setSection(try o.builder.string("__DATA,__sancov_cntrs"), &o.builder); |
| ... | ... | @@ -1507,10 +1369,6 @@ pub const Object = struct { |
| 1507 | 1369 | llvm_global.ptr(&o.builder).unnamed_addr = .unnamed_addr; |
| 1508 | 1370 | } |
| 1509 | 1371 | |
| 1510 | const llvm_align = switch (resolved.@"align") { | |
| 1511 | .none => nav_ty.abiAlignment(zcu).toLlvm(), | |
| 1512 | else => |a| a.toLlvm(), | |
| 1513 | }; | |
| 1514 | 1372 | const llvm_section: Builder.String = if (resolved.@"linksection".toSlice(ip)) |section| s: { |
| 1515 | 1373 | break :s try o.builder.string(section); |
| 1516 | 1374 | } else .none; |
| ... | ... | @@ -1519,13 +1377,20 @@ pub const Object = struct { |
| 1519 | 1377 | // can see are extern functions or other comptime function body values (e.g. undefined). Of |
| 1520 | 1378 | // these, only extern functions need to be lowered to LLVM functions. |
| 1521 | 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 | 1381 | const llvm_function: Builder.Function.Index = switch (llvm_global.ptrConst(&o.builder).kind) { |
| 1523 | 1382 | .function => |function| function, // re-use existing `Builder.Function` |
| 1524 | 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 | 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 | 1394 | } else { |
| 1530 | 1395 | const file_scope = nav.srcInst(ip).resolveFile(ip); |
| 1531 | 1396 | const mod = zcu.fileByIndex(file_scope).mod.?; |
| ... | ... | @@ -1534,7 +1399,10 @@ pub const Object = struct { |
| 1534 | 1399 | .variable => |variable| variable, // re-use existing `Builder.Variable` |
| 1535 | 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 | 1406 | llvm_variable.setSection(llvm_section, &o.builder); |
| 1539 | 1407 | llvm_variable.setMutability(if (resolved.@"const") .constant else .global, &o.builder); |
| 1540 | 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 | 1453 | const uav_ty = Value.fromInterned(uav).typeOf(zcu); |
| 1586 | 1454 | const uav_ref = try o.lowerUavRef( |
| 1587 | 1455 | uav, |
| 1588 | uav_ty.abiAlignment(zcu), | |
| 1456 | uav_ty.abiAlignment(zcu).toLlvm(), | |
| 1589 | 1457 | target_util.defaultAddressSpace(zcu.getTarget(), .global_constant), |
| 1590 | 1458 | ); |
| 1591 | 1459 | break :exp .{ uav_ty, uav_ref }; |
| ... | ... | @@ -1599,7 +1467,7 @@ pub const Object = struct { |
| 1599 | 1467 | |
| 1600 | 1468 | fn updateExportedGlobal( |
| 1601 | 1469 | o: *Object, |
| 1602 | global_index: Builder.Global.Index, | |
| 1470 | llvm_global: Builder.Global.Index, | |
| 1603 | 1471 | ty: Type, |
| 1604 | 1472 | export_indices: []const Zcu.Export.Index, |
| 1605 | 1473 | ) link.Error!void { |
| ... | ... | @@ -1634,18 +1502,21 @@ pub const Object = struct { |
| 1634 | 1502 | // make much sense: the linksection should be associated with the declaration itself rather |
| 1635 | 1503 | // than some particular symbol it is exported as! |
| 1636 | 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 | 1506 | variable.setSection(try o.builder.string(section_slice), &o.builder); |
| 1639 | 1507 | } |
| 1640 | 1508 | |
| 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); | |
| 1642 | 1513 | |
| 1643 | 1514 | // All exports are represented as aliases to the original global. |
| 1644 | 1515 | |
| 1645 | 1516 | // TODO: we currently do not delete old exports. To do that we'll need to track which |
| 1646 | 1517 | // globals actually *are* exports. |
| 1647 | 1518 | |
| 1648 | for (export_indices) |export_idx| { | |
| 1519 | for (export_indices, 0..) |export_idx, export_i| { | |
| 1649 | 1520 | const exp = export_idx.ptr(zcu); |
| 1650 | 1521 | const exp_name = try o.builder.strtabString(exp.opts.name.toSlice(ip)); |
| 1651 | 1522 | |
| ... | ... | @@ -1656,13 +1527,23 @@ pub const Object = struct { |
| 1656 | 1527 | // The name, aliasee, and type will be set within this block. Other properties of the |
| 1657 | 1528 | // alias will be set below. |
| 1658 | 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 | 1540 | const existing_global = o.builder.getGlobal(exp_name) orelse { |
| 1660 | 1541 | // There is no existing global with this name, so make a new alias. |
| 1661 | 1542 | const alias = try o.builder.addAlias( |
| 1662 | 1543 | exp_name, |
| 1663 | 1544 | llvm_global_ty, |
| 1664 | .default, | |
| 1665 | global_index.toConst(), | |
| 1545 | llvm_global.ptrConst(&o.builder).addr_space, | |
| 1546 | llvm_global.toConst(), | |
| 1666 | 1547 | ); |
| 1667 | 1548 | break :global alias.ptrConst(&o.builder).global; |
| 1668 | 1549 | }; |
| ... | ... | @@ -1671,8 +1552,9 @@ pub const Object = struct { |
| 1671 | 1552 | switch (existing_global.ptrConst(&o.builder).kind) { |
| 1672 | 1553 | .alias => |alias| { |
| 1673 | 1554 | // We can just repurpose the existing alias. |
| 1674 | alias.setAliasee(global_index.toConst(), &o.builder); | |
| 1675 | alias.ptrConst(&o.builder).global.ptr(&o.builder).type = global_index.typeOf(&o.builder); | |
| 1555 | alias.setAliasee(llvm_global.toConst(), &o.builder); | |
| 1556 | alias.ptrConst(&o.builder).global.ptr(&o.builder).type = llvm_global.typeOf(&o.builder); | |
| 1557 | alias.ptrConst(&o.builder).global.ptr(&o.builder).addr_space = llvm_global.ptrConst(&o.builder).addr_space; | |
| 1676 | 1558 | break :global existing_global; |
| 1677 | 1559 | }, |
| 1678 | 1560 | .variable, .function => { |
| ... | ... | @@ -1682,13 +1564,13 @@ pub const Object = struct { |
| 1682 | 1564 | // We need to make a new global which is an alias. Replace this existing one |
| 1683 | 1565 | // with the target global, making the name available and fixing references |
| 1684 | 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 | 1568 | // The name is now free, so create an alias. |
| 1687 | 1569 | const alias = try o.builder.addAlias( |
| 1688 | 1570 | exp_name, |
| 1689 | 1571 | llvm_global_ty, |
| 1690 | .default, | |
| 1691 | global_index.toConst(), | |
| 1572 | llvm_global.ptrConst(&o.builder).addr_space, | |
| 1573 | llvm_global.toConst(), | |
| 1692 | 1574 | ); |
| 1693 | 1575 | break :global alias.ptrConst(&o.builder).global; |
| 1694 | 1576 | }, |
| ... | ... | @@ -1721,11 +1603,11 @@ pub const Object = struct { |
| 1721 | 1603 | pub fn updateContainerType(o: *Object, pt: Zcu.PerThread, ty: InternPool.Index, success: bool) Allocator.Error!void { |
| 1722 | 1604 | _ = o.type_map.remove(ty); |
| 1723 | 1605 | try o.type_pool.updateContainerType(pt, .{ .llvm = o }, ty, success); |
| 1724 | if (o.named_enum_map.get(ty)) |function_index| { | |
| 1725 | try o.updateIsNamedEnumValueFunction(.fromInterned(ty), function_index); | |
| 1606 | if (o.named_enum_map.get(ty)) |llvm_function| { | |
| 1607 | try o.updateIsNamedEnumValueFunction(.fromInterned(ty), llvm_function); | |
| 1726 | 1608 | } |
| 1727 | if (o.enum_tag_name_map.get(ty)) |function_index| { | |
| 1728 | try o.updateEnumTagNameFunction(.fromInterned(ty), function_index); | |
| 1609 | if (o.enum_tag_name_map.get(ty)) |llvm_function| { | |
| 1610 | try o.updateEnumTagNameFunction(.fromInterned(ty), llvm_function); | |
| 1729 | 1611 | } |
| 1730 | 1612 | } |
| 1731 | 1613 | |
| ... | ... | @@ -2098,7 +1980,7 @@ pub const Object = struct { |
| 2098 | 1980 | payload_offset * 8, |
| 2099 | 1981 | ); |
| 2100 | 1982 | |
| 2101 | return try o.builder.debugStructType( | |
| 1983 | return o.builder.debugStructType( | |
| 2102 | 1984 | name, |
| 2103 | 1985 | null, // File |
| 2104 | 1986 | o.debug_compile_unit.unwrap().?, // Scope |
| ... | ... | @@ -2136,7 +2018,7 @@ pub const Object = struct { |
| 2136 | 2018 | defer debug_param_types.deinit(gpa); |
| 2137 | 2019 | |
| 2138 | 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 | 2022 | // Actual return type is void, then first arg is the sret pointer. |
| 2141 | 2023 | const ptr_ty = try pt.singleMutPtrType(.fromInterned(fn_info.return_type)); |
| 2142 | 2024 | debug_param_types.appendAssumeCapacity(try o.getDebugType(pt, .void)); |
| ... | ... | @@ -2571,53 +2453,117 @@ pub const Object = struct { |
| 2571 | 2453 | fn namespaceToDebugScope(o: *Object, pt: Zcu.PerThread, namespace_index: InternPool.NamespaceIndex) !Builder.Metadata { |
| 2572 | 2454 | const zcu = o.zcu; |
| 2573 | 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 | 2457 | return o.getDebugType(pt, .fromInterned(namespace.owner_type)); |
| 2576 | 2458 | } |
| 2577 | 2459 | |
| 2578 | /// Sets the attributes and callconv of the given `Builder.Function`, which corresponds to the | |
| 2579 | /// given `Nav` (which is a function). | |
| 2580 | fn addLlvmFunctionAttributes( | |
| 2460 | fn addCommonFnAttributes( | |
| 2461 | o: *Object, | |
| 2462 | attributes: *Builder.FunctionAttributes.Wip, | |
| 2463 | owner_mod: *Module, | |
| 2464 | omit_frame_pointer: bool, | |
| 2465 | ) Allocator.Error!void { | |
| 2466 | if (!owner_mod.red_zone) { | |
| 2467 | try attributes.addFnAttr(.noredzone, &o.builder); | |
| 2468 | } | |
| 2469 | if (omit_frame_pointer) { | |
| 2470 | try attributes.addFnAttr(.{ .string = .{ | |
| 2471 | .kind = try o.builder.string("frame-pointer"), | |
| 2472 | .value = try o.builder.string("none"), | |
| 2473 | } }, &o.builder); | |
| 2474 | } else { | |
| 2475 | try attributes.addFnAttr(.{ .string = .{ | |
| 2476 | .kind = try o.builder.string("frame-pointer"), | |
| 2477 | .value = try o.builder.string("all"), | |
| 2478 | } }, &o.builder); | |
| 2479 | } | |
| 2480 | try attributes.addFnAttr(.nounwind, &o.builder); | |
| 2481 | if (owner_mod.unwind_tables != .none) { | |
| 2482 | try attributes.addFnAttr( | |
| 2483 | .{ .uwtable = if (owner_mod.unwind_tables == .async) .async else .sync }, | |
| 2484 | &o.builder, | |
| 2485 | ); | |
| 2486 | } | |
| 2487 | if (owner_mod.optimize_mode == .small) { | |
| 2488 | try attributes.addFnAttr(.minsize, &o.builder); | |
| 2489 | try attributes.addFnAttr(.optsize, &o.builder); | |
| 2490 | } | |
| 2491 | const target = &owner_mod.resolved_target.result; | |
| 2492 | if (target.cpu.model.llvm_name) |s| { | |
| 2493 | try attributes.addFnAttr(.{ .string = .{ | |
| 2494 | .kind = try o.builder.string("target-cpu"), | |
| 2495 | .value = try o.builder.string(s), | |
| 2496 | } }, &o.builder); | |
| 2497 | } | |
| 2498 | if (owner_mod.resolved_target.llvm_cpu_features) |s| { | |
| 2499 | try attributes.addFnAttr(.{ .string = .{ | |
| 2500 | .kind = try o.builder.string("target-features"), | |
| 2501 | .value = try o.builder.string(std.mem.span(s)), | |
| 2502 | } }, &o.builder); | |
| 2503 | } | |
| 2504 | if (target.abi.float() == .soft) { | |
| 2505 | // `use-soft-float` means "use software routines for floating point computations". In | |
| 2506 | // other words, it configures how LLVM lowers basic float instructions like `fcmp`, | |
| 2507 | // `fadd`, etc. The float calling convention is configured on `TargetMachine` and is | |
| 2508 | // mostly an orthogonal concept, although obviously we do need hardware float operations | |
| 2509 | // to actually be able to pass float values in float registers. | |
| 2510 | // | |
| 2511 | // Ideally, we would support something akin to the `-mfloat-abi=softfp` option that GCC | |
| 2512 | // and Clang support for Arm32 and CSKY. We don't currently expose such an option in | |
| 2513 | // Zig, and using CPU features as the source of truth for this makes for a miserable | |
| 2514 | // user experience since people expect e.g. `arm-linux-gnueabi` to mean full soft float | |
| 2515 | // unless the compiler has explicitly been told otherwise. (And note that our baseline | |
| 2516 | // CPU models almost all include FPU features!) | |
| 2517 | // | |
| 2518 | // Revisit this at some point. | |
| 2519 | try attributes.addFnAttr(.{ .string = .{ | |
| 2520 | .kind = try o.builder.string("use-soft-float"), | |
| 2521 | .value = try o.builder.string("true"), | |
| 2522 | } }, &o.builder); | |
| 2523 | ||
| 2524 | // This prevents LLVM from using FPU/SIMD code for things like `memcpy`. As for the | |
| 2525 | // above, this should be revisited if `softfp` support is added. | |
| 2526 | try attributes.addFnAttr(.noimplicitfloat, &o.builder); | |
| 2527 | } | |
| 2528 | } | |
| 2529 | ||
| 2530 | pub fn addCallingConventionFnAttributes( | |
| 2581 | 2531 | o: *Object, |
| 2582 | 2532 | pt: Zcu.PerThread, |
| 2583 | nav_id: InternPool.Nav.Index, | |
| 2584 | function_index: Builder.Function.Index, | |
| 2533 | llvm_function: Builder.Function.Index, | |
| 2534 | attributes: *Builder.FunctionAttributes.Wip, | |
| 2535 | opt_extern: ?struct { | |
| 2536 | name: []const u8, | |
| 2537 | lib_name: ?[]const u8 = null, | |
| 2538 | }, | |
| 2539 | fn_info: FuncInfo, | |
| 2585 | 2540 | ) Allocator.Error!void { |
| 2586 | 2541 | const zcu = o.zcu; |
| 2587 | const ip = &zcu.intern_pool; | |
| 2588 | const nav = ip.getNav(nav_id); | |
| 2589 | const owner_mod = zcu.navFileScope(nav_id).mod.?; | |
| 2590 | const ty: Type = .fromInterned(nav.resolved.?.type); | |
| 2591 | ||
| 2592 | const fn_info = zcu.typeToFunc(ty).?; | |
| 2593 | const target = &owner_mod.resolved_target.result; | |
| 2542 | const target = zcu.getTarget(); | |
| 2594 | 2543 | |
| 2595 | var attributes: Builder.FunctionAttributes.Wip = .{}; | |
| 2596 | defer attributes.deinit(&o.builder); | |
| 2544 | if (fn_info.cc == .async) { | |
| 2545 | @panic("TODO: LLVM backend lower async function"); | |
| 2546 | } | |
| 2597 | 2547 | |
| 2598 | if (target.cpu.arch.isWasm()) if (nav.getExtern(ip)) |@"extern"| { | |
| 2548 | if (target.cpu.arch.isWasm()) if (opt_extern) |@"extern"| { | |
| 2599 | 2549 | try attributes.addFnAttr(.{ .string = .{ |
| 2600 | 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 | 2552 | } }, &o.builder); |
| 2603 | if (@"extern".lib_name.toSlice(ip)) |lib_name_slice| { | |
| 2604 | if (!std.mem.eql(u8, lib_name_slice, "c")) try attributes.addFnAttr(.{ .string = .{ | |
| 2553 | if (@"extern".lib_name) |lib_name| { | |
| 2554 | if (!std.mem.eql(u8, lib_name, "c")) try attributes.addFnAttr(.{ .string = .{ | |
| 2605 | 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 | 2557 | } }, &o.builder); |
| 2608 | 2558 | } |
| 2609 | 2559 | }; |
| 2610 | 2560 | |
| 2611 | if (fn_info.cc == .async) { | |
| 2612 | @panic("TODO: LLVM backend lower async function"); | |
| 2613 | } | |
| 2614 | ||
| 2615 | 2561 | const cc_info = toLlvmCallConv(fn_info.cc, target).?; |
| 2616 | 2562 | |
| 2617 | function_index.setCallConv(cc_info.llvm_cc, &o.builder); | |
| 2563 | llvm_function.setCallConv(cc_info.llvm_cc, &o.builder); | |
| 2618 | 2564 | |
| 2619 | 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 | } |
| 2622 | 2568 | |
| 2623 | 2569 | if (cc_info.naked) { |
| ... | ... | @@ -2668,29 +2614,16 @@ pub const Object = struct { |
| 2668 | 2614 | else => {}, |
| 2669 | 2615 | } |
| 2670 | 2616 | |
| 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 | 2617 | if (fn_info.return_type == .noreturn_type) try attributes.addFnAttr(.noreturn, &o.builder); |
| 2685 | 2618 | |
| 2686 | var it = iterateParamTypes(o, fn_info); | |
| 2687 | if (try fnReturnStrat(o, fn_info) == .sret) { | |
| 2688 | // Sret pointers must not be address 0 | |
| 2689 | try attributes.addParamAttr(it.llvm_index, .nonnull, &o.builder); | |
| 2690 | try attributes.addParamAttr(it.llvm_index, .@"noalias", &o.builder); | |
| 2691 | ||
| 2692 | const raw_llvm_ret_ty = try o.lowerType(.fromInterned(fn_info.return_type), .in_memory); | |
| 2693 | try attributes.addParamAttr(it.llvm_index, .{ .sret = raw_llvm_ret_ty }, &o.builder); | |
| 2619 | var it = iterateParamTypes(o, fn_info.cc, fn_info.param_types); | |
| 2620 | if (try fnReturnStrat(o, fn_info.cc, .fromInterned(fn_info.return_type)) == .sret) { | |
| 2621 | try o.addSRetFnAttributes( | |
| 2622 | attributes, | |
| 2623 | try o.lowerType(.fromInterned(fn_info.return_type), .in_memory), | |
| 2624 | Type.fromInterned(fn_info.return_type).abiAlignment(zcu).toLlvm(), | |
| 2625 | .declaration, | |
| 2626 | ); | |
| 2694 | 2627 | it.llvm_index += 1; |
| 2695 | 2628 | } else if (ccAbiPromoteInt(fn_info.cc, zcu, Type.fromInterned(fn_info.return_type))) |s| switch (s) { |
| 2696 | 2629 | .signed => try attributes.addRetAttr(.signext, &o.builder), |
| ... | ... | @@ -2709,9 +2642,9 @@ pub const Object = struct { |
| 2709 | 2642 | while (try it.next()) |lowering| switch (lowering) { |
| 2710 | 2643 | .byval => { |
| 2711 | 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 | 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 | } |
| 2716 | 2649 | |
| 2717 | 2650 | if (remaining_inreg_int > 0 and |
| ... | ... | @@ -2730,12 +2663,12 @@ pub const Object = struct { |
| 2730 | 2663 | } |
| 2731 | 2664 | }, |
| 2732 | 2665 | .byref => { |
| 2733 | const param_ty: Type = .fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); | |
| 2734 | try o.addByRefParamAttrs(&attributes, it.llvm_index - 1, it.byval_attr, param_ty); | |
| 2666 | const param_ty: Type = .fromInterned(fn_info.param_types[it.zig_index - 1]); | |
| 2667 | try o.addByRefParamAttrs(attributes, it.llvm_index - 1, it.byval_attr, param_ty); | |
| 2735 | 2668 | }, |
| 2736 | 2669 | .byref_mut => try attributes.addParamAttr(it.llvm_index - 1, .noundef, &o.builder), |
| 2737 | 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 | 2672 | const ptr_info = param_ty.ptrInfo(zcu); |
| 2740 | 2673 | const llvm_ptr_index = it.llvm_index - 2; |
| 2741 | 2674 | if (std.math.cast(u5, it.zig_index - 1)) |i| { |
| ... | ... | @@ -2767,94 +2700,205 @@ pub const Object = struct { |
| 2767 | 2700 | .i64_array, |
| 2768 | 2701 | => continue, |
| 2769 | 2702 | }; |
| 2770 | ||
| 2771 | function_index.setAttributes(try attributes.finish(&o.builder), &o.builder); | |
| 2772 | 2703 | } |
| 2773 | 2704 | |
| 2774 | fn addCommonFnAttributes( | |
| 2705 | pub fn addSRetFnAttributes( | |
| 2775 | 2706 | o: *Object, |
| 2776 | 2707 | attributes: *Builder.FunctionAttributes.Wip, |
| 2777 | owner_mod: *Module, | |
| 2778 | omit_frame_pointer: bool, | |
| 2708 | ret_ty: Builder.Type, | |
| 2709 | ret_align: Builder.Alignment, | |
| 2710 | location: enum { declaration, callsite }, | |
| 2779 | 2711 | ) Allocator.Error!void { |
| 2780 | if (!owner_mod.red_zone) { | |
| 2781 | try attributes.addFnAttr(.noredzone, &o.builder); | |
| 2782 | } | |
| 2783 | if (omit_frame_pointer) { | |
| 2784 | try attributes.addFnAttr(.{ .string = .{ | |
| 2785 | .kind = try o.builder.string("frame-pointer"), | |
| 2786 | .value = try o.builder.string("none"), | |
| 2787 | } }, &o.builder); | |
| 2788 | } else { | |
| 2789 | try attributes.addFnAttr(.{ .string = .{ | |
| 2790 | .kind = try o.builder.string("frame-pointer"), | |
| 2791 | .value = try o.builder.string("all"), | |
| 2792 | } }, &o.builder); | |
| 2793 | } | |
| 2794 | try attributes.addFnAttr(.nounwind, &o.builder); | |
| 2795 | if (owner_mod.unwind_tables != .none) { | |
| 2796 | try attributes.addFnAttr( | |
| 2797 | .{ .uwtable = if (owner_mod.unwind_tables == .async) .async else .sync }, | |
| 2798 | &o.builder, | |
| 2799 | ); | |
| 2800 | } | |
| 2801 | if (owner_mod.optimize_mode == .ReleaseSmall) { | |
| 2802 | try attributes.addFnAttr(.minsize, &o.builder); | |
| 2803 | try attributes.addFnAttr(.optsize, &o.builder); | |
| 2804 | } | |
| 2805 | const target = &owner_mod.resolved_target.result; | |
| 2806 | if (target.cpu.model.llvm_name) |s| { | |
| 2807 | try attributes.addFnAttr(.{ .string = .{ | |
| 2808 | .kind = try o.builder.string("target-cpu"), | |
| 2809 | .value = try o.builder.string(s), | |
| 2810 | } }, &o.builder); | |
| 2811 | } | |
| 2812 | if (owner_mod.resolved_target.llvm_cpu_features) |s| { | |
| 2813 | try attributes.addFnAttr(.{ .string = .{ | |
| 2814 | .kind = try o.builder.string("target-features"), | |
| 2815 | .value = try o.builder.string(std.mem.span(s)), | |
| 2816 | } }, &o.builder); | |
| 2817 | } | |
| 2818 | if (target.abi.float() == .soft) { | |
| 2819 | // `use-soft-float` means "use software routines for floating point computations". In | |
| 2820 | // other words, it configures how LLVM lowers basic float instructions like `fcmp`, | |
| 2821 | // `fadd`, etc. The float calling convention is configured on `TargetMachine` and is | |
| 2822 | // mostly an orthogonal concept, although obviously we do need hardware float operations | |
| 2823 | // to actually be able to pass float values in float registers. | |
| 2824 | // | |
| 2825 | // Ideally, we would support something akin to the `-mfloat-abi=softfp` option that GCC | |
| 2826 | // and Clang support for Arm32 and CSKY. We don't currently expose such an option in | |
| 2827 | // Zig, and using CPU features as the source of truth for this makes for a miserable | |
| 2828 | // user experience since people expect e.g. `arm-linux-gnueabi` to mean full soft float | |
| 2829 | // unless the compiler has explicitly been told otherwise. (And note that our baseline | |
| 2830 | // CPU models almost all include FPU features!) | |
| 2831 | // | |
| 2832 | // Revisit this at some point. | |
| 2833 | try attributes.addFnAttr(.{ .string = .{ | |
| 2834 | .kind = try o.builder.string("use-soft-float"), | |
| 2835 | .value = try o.builder.string("true"), | |
| 2836 | } }, &o.builder); | |
| 2837 | ||
| 2838 | // This prevents LLVM from using FPU/SIMD code for things like `memcpy`. As for the | |
| 2839 | // above, this should be revisited if `softfp` support is added. | |
| 2840 | try attributes.addFnAttr(.noimplicitfloat, &o.builder); | |
| 2712 | try attributes.addParamAttr(0, .dead_on_unwind, &o.builder); | |
| 2713 | switch (location) { | |
| 2714 | .declaration => try attributes.addParamAttr(0, .@"noalias", &o.builder), | |
| 2715 | .callsite => {}, | |
| 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 | } |
| 2843 | 2722 | |
| 2844 | 2723 | pub const TypeRepr = enum { |
| 2845 | 2724 | /// The representation of the type when it is being manipulated as a value in a function. |
| 2846 | /// e.g. Zig `u5` -> LLVM `i5` | |
| 2847 | by_value, | |
| 2848 | /// The representation of the type when it is stored in memory. | |
| 2849 | /// e.g. Zig `u5` -> LLVM `i8` | |
| 2725 | /// e.g. Zig `u90` -> LLVM `i90` | |
| 2726 | as_value, | |
| 2727 | /// The representation of the type when it is loaded from or stored to memory. | |
| 2728 | /// e.g. Zig `u90` -> LLVM `i96` | |
| 2729 | memory_access, | |
| 2730 | /// The representation of the type when it is in memory. | |
| 2731 | /// e.g. Zig `u90` -> LLVM `[12 x i8]` | |
| 2850 | 2732 | in_memory, |
| 2851 | 2733 | }; |
| 2852 | 2734 | |
| 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 | 2755 | pub fn errorIntType(o: *Object, repr: TypeRepr) Allocator.Error!Builder.Type { |
| 2854 | return o.builder.intType(switch (repr) { | |
| 2855 | .by_value => o.zcu.errorSetBits(), | |
| 2856 | .in_memory => @intCast(Type.anyerror.abiSize(o.zcu) * 8), | |
| 2857 | }); | |
| 2756 | return o.intType(o.zcu.errorSetBits(), repr); | |
| 2757 | } | |
| 2758 | ||
| 2759 | pub const SoftF80Layout = struct { | |
| 2760 | alignment: InternPool.Alignment, | |
| 2761 | /// byte offset of u64 field | |
| 2762 | mantissa_offset: u64, | |
| 2763 | /// byte offset of u16 field | |
| 2764 | exponent_offset: u64, | |
| 2765 | llvm_fields_len: u32, | |
| 2766 | ||
| 2767 | pub const LlvmFieldTag = enum { mantissa, exponent, padding }; | |
| 2768 | }; | |
| 2769 | pub fn softF80Layout(o: *Object, opts: struct { | |
| 2770 | llvm_field_tags_buf: []SoftF80Layout.LlvmFieldTag = &.{}, | |
| 2771 | llvm_field_types_buf: []Builder.Type = &.{}, | |
| 2772 | }) Allocator.Error!SoftF80Layout { | |
| 2773 | const zcu = o.zcu; | |
| 2774 | const target = zcu.getTarget(); | |
| 2775 | assert(std.zig.target.compilerRtFloatAbi(target, 80) == .soft); | |
| 2776 | // Current compiler rt soft abi, which is not yet affected by endianness for simplicity: | |
| 2777 | // | |
| 2778 | // typedef struct { uint64_t mantissa; uint16_t exponent; } f80; | |
| 2779 | // | |
| 2780 | var layout: SoftF80Layout = .{ | |
| 2781 | .alignment = Type.f80.abiAlignment(zcu), | |
| 2782 | .mantissa_offset = undefined, | |
| 2783 | .exponent_offset = undefined, | |
| 2784 | .llvm_fields_len = 0, | |
| 2785 | }; | |
| 2786 | var offset: u64 = 0; | |
| 2787 | for ([2]SoftF80Layout.LlvmFieldTag{ .mantissa, .exponent }, [2]Type{ .u64, .u16 }) |field_tag, field_type| { | |
| 2788 | const field_align = field_type.abiAlignment(zcu); | |
| 2789 | assert(field_align.compareStrict(.lte, layout.alignment)); | |
| 2790 | const field_offset = field_align.forward(offset); | |
| 2791 | switch (field_offset - offset) { | |
| 2792 | 0 => {}, | |
| 2793 | else => |padding| { | |
| 2794 | if (layout.llvm_fields_len < opts.llvm_field_tags_buf.len) | |
| 2795 | opts.llvm_field_tags_buf[layout.llvm_fields_len] = .padding; | |
| 2796 | if (layout.llvm_fields_len < opts.llvm_field_types_buf.len) | |
| 2797 | opts.llvm_field_types_buf[layout.llvm_fields_len] = try o.builder.arrayType(padding, .i8); | |
| 2798 | layout.llvm_fields_len += 1; | |
| 2799 | }, | |
| 2800 | } | |
| 2801 | switch (field_tag) { | |
| 2802 | .mantissa => layout.mantissa_offset = field_offset, | |
| 2803 | .exponent => layout.exponent_offset = field_offset, | |
| 2804 | .padding => unreachable, | |
| 2805 | } | |
| 2806 | if (layout.llvm_fields_len < opts.llvm_field_tags_buf.len) | |
| 2807 | opts.llvm_field_tags_buf[layout.llvm_fields_len] = field_tag; | |
| 2808 | if (layout.llvm_fields_len < opts.llvm_field_types_buf.len) | |
| 2809 | opts.llvm_field_types_buf[layout.llvm_fields_len] = try o.lowerType(field_type, .in_memory); | |
| 2810 | layout.llvm_fields_len += 1; | |
| 2811 | offset = field_offset + field_type.abiSize(zcu); | |
| 2812 | } | |
| 2813 | const end = layout.alignment.forward(offset); | |
| 2814 | assert(end == Type.f80.abiSize(zcu)); | |
| 2815 | switch (end - offset) { | |
| 2816 | 0 => {}, | |
| 2817 | else => |padding| { | |
| 2818 | if (layout.llvm_fields_len < opts.llvm_field_tags_buf.len) | |
| 2819 | opts.llvm_field_tags_buf[layout.llvm_fields_len] = .padding; | |
| 2820 | if (layout.llvm_fields_len < opts.llvm_field_types_buf.len) | |
| 2821 | opts.llvm_field_types_buf[layout.llvm_fields_len] = try o.builder.arrayType(padding, .i8); | |
| 2822 | layout.llvm_fields_len += 1; | |
| 2823 | }, | |
| 2824 | } | |
| 2825 | return layout; | |
| 2826 | } | |
| 2827 | ||
| 2828 | pub const SoftF128Layout = struct { | |
| 2829 | alignment: InternPool.Alignment, | |
| 2830 | /// byte offset of u64 field | |
| 2831 | lo_offset: u64, | |
| 2832 | /// byte offset of u64 field | |
| 2833 | hi_offset: u64, | |
| 2834 | llvm_fields_len: u32, | |
| 2835 | ||
| 2836 | pub const LlvmFieldTag = enum { lo, hi, padding }; | |
| 2837 | }; | |
| 2838 | pub fn softF128Layout(o: *Object, opts: struct { | |
| 2839 | llvm_field_tags_buf: []SoftF128Layout.LlvmFieldTag = &.{}, | |
| 2840 | llvm_field_types_buf: []Builder.Type = &.{}, | |
| 2841 | }) Allocator.Error!SoftF128Layout { | |
| 2842 | const zcu = o.zcu; | |
| 2843 | const target = zcu.getTarget(); | |
| 2844 | assert(std.zig.target.compilerRtFloatAbi(target, 128) == .soft); | |
| 2845 | // Current compiler rt soft abi: | |
| 2846 | // | |
| 2847 | // #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ | |
| 2848 | // typedef struct { uint64_t hi, lo; } f128; | |
| 2849 | // #else | |
| 2850 | // typedef struct { uint64_t lo, hi; } f128; | |
| 2851 | // #endif | |
| 2852 | // | |
| 2853 | var layout: SoftF128Layout = .{ | |
| 2854 | .alignment = Type.f128.abiAlignment(zcu), | |
| 2855 | .lo_offset = undefined, | |
| 2856 | .hi_offset = undefined, | |
| 2857 | .llvm_fields_len = 0, | |
| 2858 | }; | |
| 2859 | var offset: u64 = 0; | |
| 2860 | for (@as([2]SoftF128Layout.LlvmFieldTag, switch (target.cpu.arch.endian()) { | |
| 2861 | .big => .{ .hi, .lo }, | |
| 2862 | .little => .{ .lo, .hi }, | |
| 2863 | }), [2]Type{ .u64, .u64 }) |field_tag, field_type| { | |
| 2864 | const field_align = field_type.abiAlignment(zcu); | |
| 2865 | assert(field_align.compareStrict(.lte, layout.alignment)); | |
| 2866 | const field_offset = field_align.forward(offset); | |
| 2867 | switch (field_offset - offset) { | |
| 2868 | 0 => {}, | |
| 2869 | else => |padding| { | |
| 2870 | if (layout.llvm_fields_len < opts.llvm_field_tags_buf.len) | |
| 2871 | opts.llvm_field_tags_buf[layout.llvm_fields_len] = .padding; | |
| 2872 | if (layout.llvm_fields_len < opts.llvm_field_types_buf.len) | |
| 2873 | opts.llvm_field_types_buf[layout.llvm_fields_len] = try o.builder.arrayType(padding, .i8); | |
| 2874 | layout.llvm_fields_len += 1; | |
| 2875 | }, | |
| 2876 | } | |
| 2877 | switch (field_tag) { | |
| 2878 | .lo => layout.lo_offset = field_offset, | |
| 2879 | .hi => layout.hi_offset = field_offset, | |
| 2880 | .padding => unreachable, | |
| 2881 | } | |
| 2882 | if (layout.llvm_fields_len < opts.llvm_field_tags_buf.len) | |
| 2883 | opts.llvm_field_tags_buf[layout.llvm_fields_len] = field_tag; | |
| 2884 | if (layout.llvm_fields_len < opts.llvm_field_types_buf.len) | |
| 2885 | opts.llvm_field_types_buf[layout.llvm_fields_len] = try o.lowerType(field_type, .in_memory); | |
| 2886 | layout.llvm_fields_len += 1; | |
| 2887 | offset = field_offset + field_type.abiSize(zcu); | |
| 2888 | } | |
| 2889 | const end = layout.alignment.forward(offset); | |
| 2890 | assert(end == Type.f128.abiSize(zcu)); | |
| 2891 | switch (end - offset) { | |
| 2892 | 0 => {}, | |
| 2893 | else => |padding| { | |
| 2894 | if (layout.llvm_fields_len < opts.llvm_field_tags_buf.len) | |
| 2895 | opts.llvm_field_tags_buf[layout.llvm_fields_len] = .padding; | |
| 2896 | if (layout.llvm_fields_len < opts.llvm_field_types_buf.len) | |
| 2897 | opts.llvm_field_types_buf[layout.llvm_fields_len] = try o.builder.arrayType(padding, .i8); | |
| 2898 | layout.llvm_fields_len += 1; | |
| 2899 | }, | |
| 2900 | } | |
| 2901 | return layout; | |
| 2858 | 2902 | } |
| 2859 | 2903 | |
| 2860 | 2904 | pub fn lowerType(o: *Object, t: Type, repr: TypeRepr) Allocator.Error!Builder.Type { |
| ... | ... | @@ -2862,42 +2906,31 @@ pub const Object = struct { |
| 2862 | 2906 | const target = zcu.getTarget(); |
| 2863 | 2907 | const ip = &zcu.intern_pool; |
| 2864 | 2908 | |
| 2865 | if (repr == .by_value) { | |
| 2866 | assert(!isByRef(t, zcu)); // by-ref types must only be manipulated in memory | |
| 2909 | switch (repr) { | |
| 2910 | .as_value => assert(!isByRef(t, zcu)), // by-ref types must only be manipulated in memory | |
| 2911 | .memory_access, .in_memory => {}, | |
| 2867 | 2912 | } |
| 2868 | 2913 | |
| 2869 | 2914 | return switch (t.toIntern()) { |
| 2870 | 2915 | .u0_type => unreachable, // no runtime bits |
| 2871 | inline .u1_type, | |
| 2872 | .u8_type, | |
| 2873 | .i8_type, | |
| 2874 | .u16_type, | |
| 2875 | .i16_type, | |
| 2876 | .u29_type, | |
| 2877 | .u32_type, | |
| 2878 | .i32_type, | |
| 2879 | .u64_type, | |
| 2880 | .i64_type, | |
| 2881 | .u80_type, | |
| 2882 | .u128_type, | |
| 2883 | .i128_type, | |
| 2884 | => |tag| switch (repr) { | |
| 2885 | .by_value => @field(Builder.Type, "i" ++ @tagName(tag)[1 .. @tagName(tag).len - "_type".len]), | |
| 2886 | .in_memory => try o.builder.intType(@intCast(t.abiSize(zcu) * 8)), | |
| 2887 | }, | |
| 2888 | .usize_type, .isize_type => try o.builder.intType(target.ptrBitWidth()), | |
| 2889 | inline .c_char_type, | |
| 2890 | .c_short_type, | |
| 2891 | .c_ushort_type, | |
| 2892 | .c_int_type, | |
| 2893 | .c_uint_type, | |
| 2894 | .c_long_type, | |
| 2895 | .c_ulong_type, | |
| 2896 | .c_longlong_type, | |
| 2897 | .c_ulonglong_type, | |
| 2898 | => |tag| try o.builder.intType(target.cTypeBitSize( | |
| 2899 | @field(std.Target.CType, @tagName(tag)["c_".len .. @tagName(tag).len - "_type".len]), | |
| 2900 | )), | |
| 2916 | .u1_type, .bool_type => try o.intType(1, repr), | |
| 2917 | .u8_type, .i8_type => try o.intType(8, repr), | |
| 2918 | .u16_type, .i16_type => try o.intType(16, repr), | |
| 2919 | .u29_type => try o.intType(29, repr), | |
| 2920 | .u32_type, .i32_type => try o.intType(32, repr), | |
| 2921 | .u64_type, .i64_type => try o.intType(64, repr), | |
| 2922 | .u80_type => try o.intType(80, repr), | |
| 2923 | .u128_type, .i128_type => try o.intType(128, repr), | |
| 2924 | .usize_type, .isize_type => try o.intType(target.ptrBitWidth(), repr), | |
| 2925 | .c_char_type => try o.intType(target.cTypeBitSize(.char).?, repr), | |
| 2926 | .c_short_type => try o.intType(target.cTypeBitSize(.short).?, repr), | |
| 2927 | .c_ushort_type => try o.intType(target.cTypeBitSize(.ushort).?, repr), | |
| 2928 | .c_int_type => try o.intType(target.cTypeBitSize(.int).?, repr), | |
| 2929 | .c_uint_type => try o.intType(target.cTypeBitSize(.uint).?, repr), | |
| 2930 | .c_long_type => try o.intType(target.cTypeBitSize(.long).?, repr), | |
| 2931 | .c_ulong_type => try o.intType(target.cTypeBitSize(.ulong).?, repr), | |
| 2932 | .c_longlong_type => try o.intType(target.cTypeBitSize(.longlong).?, repr), | |
| 2933 | .c_ulonglong_type => try o.intType(target.cTypeBitSize(.ulonglong).?, repr), | |
| 2901 | 2934 | .c_longdouble_type, |
| 2902 | 2935 | .f16_type, |
| 2903 | 2936 | .f32_type, |
| ... | ... | @@ -2905,11 +2938,44 @@ pub const Object = struct { |
| 2905 | 2938 | .f80_type, |
| 2906 | 2939 | .f128_type, |
| 2907 | 2940 | => switch (t.floatBits(target)) { |
| 2908 | 16 => if (backendSupportsF16(target)) .half else .i16, | |
| 2909 | 32 => .float, | |
| 2910 | 64 => .double, | |
| 2911 | 80 => if (backendSupportsF80(target)) .x86_fp80 else .i80, | |
| 2912 | 128 => .fp128, | |
| 2941 | 16 => |bits| switch (std.zig.target.compilerRtFloatAbi(target, bits)) { | |
| 2942 | .hard => .half, | |
| 2943 | .soft => .i16, | |
| 2944 | }, | |
| 2945 | 32 => |bits| switch (std.zig.target.compilerRtFloatAbi(target, bits)) { | |
| 2946 | .hard => .float, | |
| 2947 | .soft => .i32, | |
| 2948 | }, | |
| 2949 | 64 => |bits| switch (std.zig.target.compilerRtFloatAbi(target, bits)) { | |
| 2950 | .hard => .double, | |
| 2951 | .soft => .i64, | |
| 2952 | }, | |
| 2953 | 80 => |bits| switch (std.zig.target.compilerRtFloatAbi(target, bits)) { | |
| 2954 | .hard => .x86_fp80, | |
| 2955 | .soft => { | |
| 2956 | var llvm_field_types_buf: [5]Builder.Type = undefined; | |
| 2957 | const f80_layout = try o.softF80Layout(.{ | |
| 2958 | .llvm_field_types_buf = &llvm_field_types_buf, | |
| 2959 | }); | |
| 2960 | return o.builder.structType( | |
| 2961 | .normal, | |
| 2962 | llvm_field_types_buf[0..f80_layout.llvm_fields_len], | |
| 2963 | ); | |
| 2964 | }, | |
| 2965 | }, | |
| 2966 | 128 => |bits| switch (std.zig.target.compilerRtFloatAbi(target, bits)) { | |
| 2967 | .hard => .fp128, | |
| 2968 | .soft => { | |
| 2969 | var llvm_field_types_buf: [5]Builder.Type = undefined; | |
| 2970 | const f128_layout = try o.softF128Layout(.{ | |
| 2971 | .llvm_field_types_buf = &llvm_field_types_buf, | |
| 2972 | }); | |
| 2973 | return o.builder.structType( | |
| 2974 | .normal, | |
| 2975 | llvm_field_types_buf[0..f128_layout.llvm_fields_len], | |
| 2976 | ); | |
| 2977 | }, | |
| 2978 | }, | |
| 2913 | 2979 | else => unreachable, |
| 2914 | 2980 | }, |
| 2915 | 2981 | .anyopaque_type => { |
| ... | ... | @@ -2918,7 +2984,6 @@ pub const Object = struct { |
| 2918 | 2984 | // @foo = external global i8 |
| 2919 | 2985 | return .i8; |
| 2920 | 2986 | }, |
| 2921 | .bool_type => .i1, | |
| 2922 | 2987 | .anyerror_type => try o.errorIntType(repr), |
| 2923 | 2988 | .void_type => unreachable, // no runtime bits |
| 2924 | 2989 | .type_type => unreachable, // no runtime bits |
| ... | ... | @@ -2968,10 +3033,7 @@ pub const Object = struct { |
| 2968 | 3033 | .none, |
| 2969 | 3034 | => unreachable, |
| 2970 | 3035 | else => switch (ip.indexToKey(t.toIntern())) { |
| 2971 | .int_type => |int_type| switch (repr) { | |
| 2972 | .by_value => try o.builder.intType(int_type.bits), | |
| 2973 | .in_memory => try o.builder.intType(@intCast(t.abiSize(zcu) * 8)), | |
| 2974 | }, | |
| 3036 | .int_type => |int_type| o.intType(int_type.bits, repr), | |
| 2975 | 3037 | .ptr_type => |ptr_type| type: { |
| 2976 | 3038 | const ptr_ty = try o.builder.ptrType( |
| 2977 | 3039 | toLlvmAddressSpace(ptr_type.flags.address_space, target), |
| ... | ... | @@ -2988,11 +3050,13 @@ pub const Object = struct { |
| 2988 | 3050 | array_type.lenIncludingSentinel(), |
| 2989 | 3051 | try o.lowerType(.fromInterned(array_type.child), repr), |
| 2990 | 3052 | ), |
| 2991 | .vector_type => |vector_type| o.builder.vectorType( | |
| 2992 | .normal, | |
| 2993 | vector_type.len, | |
| 2994 | try o.lowerType(.fromInterned(vector_type.child), .by_value), | |
| 2995 | ), | |
| 3053 | .vector_type => |vector_type| if (isByRef(t, zcu)) { | |
| 3054 | const child_llvm_ty = try o.lowerType(.fromInterned(vector_type.child), repr); | |
| 3055 | return o.builder.arrayType(vector_type.len, child_llvm_ty); | |
| 3056 | } else { | |
| 3057 | const child_llvm_ty = try o.lowerType(.fromInterned(vector_type.child), .as_value); | |
| 3058 | return o.builder.vectorType(.normal, vector_type.len, child_llvm_ty); | |
| 3059 | }, | |
| 2996 | 3060 | .opt_type => |child_ty| { |
| 2997 | 3061 | // Must stay in sync with `opt_payload` logic in `lowerPtr`. |
| 2998 | 3062 | switch (Type.fromInterned(child_ty).classify(zcu)) { |
| ... | ... | @@ -3252,8 +3316,11 @@ pub const Object = struct { |
| 3252 | 3316 | return ty; |
| 3253 | 3317 | }, |
| 3254 | 3318 | .opaque_type, .spirv_type => unreachable, // no runtime bits |
| 3255 | .enum_type => try o.lowerType(t.backingIntType(zcu), repr), | |
| 3256 | .func_type => |func_type| try o.lowerFnType(t, func_type), | |
| 3319 | .enum_type => try o.intType(t.backingIntType(zcu).intInfo(zcu).bits, repr), | |
| 3320 | .func_type => |func_type| { | |
| 3321 | assert(t.fnHasRuntimeBits(zcu)); | |
| 3322 | return o.lowerFnType(.fromIntern(func_type, ip)); | |
| 3323 | }, | |
| 3257 | 3324 | .error_set_type, .inferred_error_set_type => try o.errorIntType(repr), |
| 3258 | 3325 | // values, not types |
| 3259 | 3326 | .undef, |
| ... | ... | @@ -3279,14 +3346,28 @@ pub const Object = struct { |
| 3279 | 3346 | }; |
| 3280 | 3347 | } |
| 3281 | 3348 | |
| 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 | 3367 | const zcu = o.zcu; |
| 3284 | const ip = &zcu.intern_pool; | |
| 3285 | 3368 | const target = zcu.getTarget(); |
| 3286 | 3369 | |
| 3287 | assert(fn_ty.fnHasRuntimeBits(zcu)); | |
| 3288 | ||
| 3289 | const ret_strat = try fnReturnStrat(o, fn_info); | |
| 3370 | const ret_strat = try fnReturnStrat(o, fn_info.cc, .fromInterned(fn_info.return_type)); | |
| 3290 | 3371 | |
| 3291 | 3372 | var llvm_params: std.ArrayList(Builder.Type) = .empty; |
| 3292 | 3373 | defer llvm_params.deinit(o.gpa); |
| ... | ... | @@ -3301,35 +3382,35 @@ pub const Object = struct { |
| 3301 | 3382 | try llvm_params.append(o.gpa, llvm_ptr_ty); |
| 3302 | 3383 | } |
| 3303 | 3384 | |
| 3304 | var it = iterateParamTypes(o, fn_info); | |
| 3385 | var it = iterateParamTypes(o, fn_info.cc, fn_info.param_types); | |
| 3305 | 3386 | while (try it.next()) |lowering| switch (lowering) { |
| 3306 | 3387 | .no_bits => continue, |
| 3307 | 3388 | .byval => { |
| 3308 | const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); | |
| 3309 | try llvm_params.append(o.gpa, try o.lowerType(param_ty, if (isByRef(param_ty, zcu)) .in_memory else .by_value)); | |
| 3389 | const param_ty = Type.fromInterned(fn_info.param_types[it.zig_index - 1]); | |
| 3390 | try llvm_params.append(o.gpa, try o.lowerType(param_ty, if (isByRef(param_ty, zcu)) .memory_access else .as_value)); | |
| 3310 | 3391 | }, |
| 3311 | 3392 | .byref, .byref_mut => { |
| 3312 | 3393 | try llvm_params.append(o.gpa, .ptr); |
| 3313 | 3394 | }, |
| 3314 | 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 | 3397 | try llvm_params.append(o.gpa, try o.builder.intType( |
| 3317 | 3398 | @intCast(param_ty.abiSize(zcu) * 8), |
| 3318 | 3399 | )); |
| 3319 | 3400 | }, |
| 3320 | 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 | 3403 | try llvm_params.appendSlice(o.gpa, &.{ |
| 3323 | 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 | 3408 | .multiple_llvm_types => { |
| 3328 | 3409 | try llvm_params.appendSlice(o.gpa, it.types_buffer[0..it.types_len]); |
| 3329 | 3410 | }, |
| 3330 | 3411 | .float_array => |count| { |
| 3331 | const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); | |
| 3332 | const float_ty = try o.lowerType(aarch64_c_abi.getFloatArrayType(param_ty, zcu).?, .in_memory); | |
| 3412 | const param_ty = Type.fromInterned(fn_info.param_types[it.zig_index - 1]); | |
| 3413 | const float_ty = try o.lowerType(aarch64_c_abi.getFloatArrayType(param_ty, zcu).?, .memory_access); | |
| 3333 | 3414 | try llvm_params.append(o.gpa, try o.builder.arrayType(count, float_ty)); |
| 3334 | 3415 | }, |
| 3335 | 3416 | .i32_array, .i64_array => |arr_len| { |
| ... | ... | @@ -3343,7 +3424,7 @@ pub const Object = struct { |
| 3343 | 3424 | |
| 3344 | 3425 | const llvm_ret_ty: Builder.Type = switch (ret_strat) { |
| 3345 | 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 | 3428 | .mem_cast => |llvm_ret_ty| llvm_ret_ty, |
| 3348 | 3429 | }; |
| 3349 | 3430 | const llvm_fn_kind: Builder.Type.Function.Kind = switch (fn_info.is_var_args) { |
| ... | ... | @@ -3391,8 +3472,14 @@ pub const Object = struct { |
| 3391 | 3472 | .null => unreachable, // non-runtime value |
| 3392 | 3473 | .@"unreachable" => unreachable, // non-runtime value |
| 3393 | 3474 | |
| 3394 | .false => .false, | |
| 3395 | .true => .true, | |
| 3475 | .false => switch (repr) { | |
| 3476 | .as_value => .false, | |
| 3477 | .in_memory, .memory_access => try o.builder.intConst(.i8, 0), | |
| 3478 | }, | |
| 3479 | .true => switch (repr) { | |
| 3480 | .as_value => .true, | |
| 3481 | .in_memory, .memory_access => try o.builder.intConst(.i8, 1), | |
| 3482 | }, | |
| 3396 | 3483 | }, |
| 3397 | 3484 | .enum_literal => unreachable, // non-runtime value |
| 3398 | 3485 | .@"extern" => unreachable, // non-runtime value |
| ... | ... | @@ -3401,7 +3488,12 @@ pub const Object = struct { |
| 3401 | 3488 | var bigint_space: Value.BigIntSpace = undefined; |
| 3402 | 3489 | const bigint = val.toBigInt(&bigint_space, zcu); |
| 3403 | 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 | 3498 | .err => |err| { |
| 3407 | 3499 | const int = zcu.intern_pool.getErrorValueIfExists(err.name).?; |
| ... | ... | @@ -3456,18 +3548,12 @@ pub const Object = struct { |
| 3456 | 3548 | }, |
| 3457 | 3549 | .enum_tag => |enum_tag| o.lowerValue(enum_tag.int, repr), |
| 3458 | 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 | 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 | 3558 | .ptr => try o.lowerPtr(arg_val, 0), |
| 3473 | 3559 | .slice => |slice| return o.builder.structConst(try o.lowerType(ty, repr), &.{ |
| ... | ... | @@ -3586,12 +3672,13 @@ pub const Object = struct { |
| 3586 | 3672 | }, |
| 3587 | 3673 | .vector_type => |vector_type| { |
| 3588 | 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 | 3680 | switch (aggregate.storage) { |
| 3590 | 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 | 3682 | const vals = try allocator.alloc(Builder.Constant, vector_type.len); |
| 3596 | 3683 | defer allocator.free(vals); |
| 3597 | 3684 | |
| ... | ... | @@ -3600,16 +3687,21 @@ pub const Object = struct { |
| 3600 | 3687 | result_val.* = try o.builder.intConst(.i8, byte); |
| 3601 | 3688 | }, |
| 3602 | 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 | 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( | |
| 3610 | vector_ty, | |
| 3611 | try o.lowerValue(elem, .by_value), | |
| 3612 | ), | |
| 3699 | .repeated_elem => |elem| if (is_by_ref) { | |
| 3700 | const vals = try allocator.alloc(Builder.Constant, vector_type.len); | |
| 3701 | defer allocator.free(vals); | |
| 3702 | @memset(vals, try o.lowerValue(elem, repr)); | |
| 3703 | return o.builder.arrayConst(vector_ty, vals); | |
| 3704 | } else return o.builder.splatConst(vector_ty, try o.lowerValue(elem, .as_value)), | |
| 3613 | 3705 | } |
| 3614 | 3706 | }, |
| 3615 | 3707 | .tuple_type => |tuple| { |
| ... | ... | @@ -3837,6 +3929,117 @@ pub const Object = struct { |
| 3837 | 3929 | }; |
| 3838 | 3930 | } |
| 3839 | 3931 | |
| 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 | 4043 | fn lowerPtr( |
| 3841 | 4044 | o: *Object, |
| 3842 | 4045 | ptr_val: InternPool.Index, |
| ... | ... | @@ -3856,7 +4059,7 @@ pub const Object = struct { |
| 3856 | 4059 | const orig_ptr_ty: Type = .fromInterned(uav.orig_ty); |
| 3857 | 4060 | const base_ptr = try o.lowerUavRef( |
| 3858 | 4061 | uav.val, |
| 3859 | orig_ptr_ty.ptrAlignment(zcu), | |
| 4062 | orig_ptr_ty.ptrAlignment(zcu).toLlvm(), | |
| 3860 | 4063 | orig_ptr_ty.ptrAddressSpace(zcu), |
| 3861 | 4064 | ); |
| 3862 | 4065 | return o.builder.gepConst(.inbounds, .i8, base_ptr, null, &.{ |
| ... | ... | @@ -3865,8 +4068,8 @@ pub const Object = struct { |
| 3865 | 4068 | }, |
| 3866 | 4069 | .int => try o.builder.castConst( |
| 3867 | 4070 | .inttoptr, |
| 3868 | try o.builder.intConst(try o.lowerType(.usize, .by_value), offset), | |
| 3869 | try o.lowerType(.fromInterned(ptr.ty), .by_value), | |
| 4071 | try o.builder.intConst(try o.lowerType(.usize, .as_value), offset), | |
| 4072 | try o.lowerType(.fromInterned(ptr.ty), .as_value), | |
| 3870 | 4073 | ), |
| 3871 | 4074 | .eu_payload => |eu_ptr| try o.lowerPtr( |
| 3872 | 4075 | eu_ptr, |
| ... | ... | @@ -3908,12 +4111,12 @@ pub const Object = struct { |
| 3908 | 4111 | |
| 3909 | 4112 | pub fn lowerPtrToVoid( |
| 3910 | 4113 | o: *Object, |
| 3911 | /// Must not be `.none`. | |
| 3912 | @"align": InternPool.Alignment, | |
| 4114 | /// Must not be `.default`. | |
| 4115 | @"align": Builder.Alignment, | |
| 3913 | 4116 | @"addrspace": std.lang.AddressSpace, |
| 3914 | 4117 | ) Allocator.Error!Builder.Constant { |
| 3915 | 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 | 4120 | const llvm_addr = try o.builder.intConst(llvm_usize, addr); |
| 3918 | 4121 | const llvm_ptr_ty = try o.builder.ptrType(toLlvmAddressSpace(@"addrspace", o.zcu.getTarget())); |
| 3919 | 4122 | return o.builder.castConst(.inttoptr, llvm_addr, llvm_ptr_ty); |
| ... | ... | @@ -3922,11 +4125,11 @@ pub const Object = struct { |
| 3922 | 4125 | pub fn lowerUavRef( |
| 3923 | 4126 | o: *Object, |
| 3924 | 4127 | uav_val: InternPool.Index, |
| 3925 | /// Must not be `.none`. | |
| 3926 | @"align": InternPool.Alignment, | |
| 4128 | /// Must not be `.default`. | |
| 4129 | @"align": Builder.Alignment, | |
| 3927 | 4130 | @"addrspace": std.lang.AddressSpace, |
| 3928 | 4131 | ) Allocator.Error!Builder.Constant { |
| 3929 | assert(@"align" != .none); | |
| 4132 | assert(@"align" != .default); | |
| 3930 | 4133 | |
| 3931 | 4134 | const zcu = o.zcu; |
| 3932 | 4135 | const ip = &zcu.intern_pool; |
| ... | ... | @@ -3951,19 +4154,18 @@ pub const Object = struct { |
| 3951 | 4154 | // Keep the greater of the two alignments. |
| 3952 | 4155 | const llvm_variable = gop.value_ptr.*; |
| 3953 | 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 | 4158 | llvm_variable.setAlignment(llvm_new_align, &o.builder); |
| 3956 | 4159 | return llvm_variable.ptrConst(&o.builder).global.toConst(); |
| 3957 | 4160 | } |
| 3958 | 4161 | errdefer assert(o.uav_map.remove(.{ .val = uav_val, .@"addrspace" = @"addrspace" })); |
| 3959 | 4162 | |
| 3960 | const llvm_ty = try o.lowerType(uav_ty, .in_memory); | |
| 3961 | 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 | 4165 | gop.value_ptr.* = llvm_variable; |
| 3964 | 4166 | try llvm_variable.setInitializer(try o.lowerValue(uav_val, .in_memory), &o.builder); |
| 3965 | 4167 | llvm_variable.setMutability(.constant, &o.builder); |
| 3966 | llvm_variable.setAlignment(@"align".toLlvm(), &o.builder); | |
| 4168 | llvm_variable.setAlignment(@"align", &o.builder); | |
| 3967 | 4169 | const llvm_global = llvm_variable.ptrConst(&o.builder).global; |
| 3968 | 4170 | llvm_global.setLinkage(if (o.builder.strip) .private else .internal, &o.builder); |
| 3969 | 4171 | llvm_global.setUnnamedAddr(.unnamed_addr, &o.builder); |
| ... | ... | @@ -3982,7 +4184,7 @@ pub const Object = struct { |
| 3982 | 4184 | .none => nav_ty.abiAlignment(zcu), |
| 3983 | 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 | } |
| 3987 | 4189 | |
| 3988 | 4190 | const gop = try o.nav_map.getOrPut(gpa, nav_id); |
| ... | ... | @@ -4011,7 +4213,7 @@ pub const Object = struct { |
| 4011 | 4213 | attributes: *Builder.FunctionAttributes.Wip, |
| 4012 | 4214 | param_ty: Type, |
| 4013 | 4215 | param_index: u32, |
| 4014 | fn_info: InternPool.Key.FuncType, | |
| 4216 | fn_info: FuncInfo, | |
| 4015 | 4217 | llvm_arg_i: u32, |
| 4016 | 4218 | ) Allocator.Error!void { |
| 4017 | 4219 | const zcu = o.zcu; |
| ... | ... | @@ -4051,19 +4253,26 @@ pub const Object = struct { |
| 4051 | 4253 | }; |
| 4052 | 4254 | } |
| 4053 | 4255 | |
| 4256 | pub const Byval = struct { alignment: InternPool.Alignment = .none }; | |
| 4054 | 4257 | pub fn addByRefParamAttrs( |
| 4055 | 4258 | o: *Object, |
| 4056 | 4259 | attributes: *Builder.FunctionAttributes.Wip, |
| 4057 | 4260 | llvm_arg_i: u32, |
| 4058 | byval: bool, | |
| 4261 | maybe_byval: ?Byval, | |
| 4059 | 4262 | param_ty: Type, |
| 4060 | 4263 | ) Allocator.Error!void { |
| 4061 | 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 | 4265 | try attributes.addParamAttr(llvm_arg_i, .readonly, &o.builder); |
| 4065 | try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = .wrap(alignment) }, &o.builder); | |
| 4066 | if (byval) try attributes.addParamAttr(llvm_arg_i, .{ .byval = llvm_param_ty }, &o.builder); | |
| 4266 | try attributes.addParamAttr(llvm_arg_i, .nonnull, &o.builder); | |
| 4267 | try attributes.addParamAttr(llvm_arg_i, .noundef, &o.builder); | |
| 4268 | const alignment = if (maybe_byval) |byval| alignment: { | |
| 4269 | try attributes.addParamAttr(llvm_arg_i, .{ .byval = llvm_param_ty }, &o.builder); | |
| 4270 | break :alignment byval.alignment; | |
| 4271 | } else .none; | |
| 4272 | try attributes.addParamAttr(llvm_arg_i, .{ .@"align" = .wrap(switch (alignment) { | |
| 4273 | .none => param_ty.abiAlignment(o.zcu), | |
| 4274 | else => alignment, | |
| 4275 | }.toLlvm()) }, &o.builder); | |
| 4067 | 4276 | } |
| 4068 | 4277 | |
| 4069 | 4278 | pub fn getErrorNameTable(o: *Object) Allocator.Error!Builder.Variable.Index { |
| ... | ... | @@ -4071,18 +4280,18 @@ pub const Object = struct { |
| 4071 | 4280 | |
| 4072 | 4281 | const name = try o.builder.strtabString("__zig_error_name_table"); |
| 4073 | 4282 | // TODO: Address space |
| 4074 | const variable_index = try o.builder.addVariable(name, .ptr, .default); | |
| 4075 | variable_index.setMutability(.constant, &o.builder); | |
| 4076 | variable_index.setAlignment( | |
| 4283 | const llvm_variable = try o.builder.addVariable(name, .ptr, .default); | |
| 4284 | llvm_variable.setMutability(.constant, &o.builder); | |
| 4285 | llvm_variable.setAlignment( | |
| 4077 | 4286 | Type.slice_const_u8_sentinel_0.abiAlignment(o.zcu).toLlvm(), |
| 4078 | 4287 | &o.builder, |
| 4079 | 4288 | ); |
| 4080 | const global_index = variable_index.ptrConst(&o.builder).global; | |
| 4081 | global_index.setLinkage(.private, &o.builder); | |
| 4082 | global_index.setUnnamedAddr(.unnamed_addr, &o.builder); | |
| 4289 | const llvm_global = llvm_variable.ptrConst(&o.builder).global; | |
| 4290 | llvm_global.setLinkage(.private, &o.builder); | |
| 4291 | llvm_global.setUnnamedAddr(.unnamed_addr, &o.builder); | |
| 4083 | 4292 | |
| 4084 | o.error_name_table = variable_index; | |
| 4085 | return variable_index; | |
| 4293 | o.error_name_table = llvm_variable; | |
| 4294 | return llvm_variable; | |
| 4086 | 4295 | } |
| 4087 | 4296 | |
| 4088 | 4297 | pub fn getErrorsLen(o: *Object) Allocator.Error!Builder.Variable.Index { |
| ... | ... | @@ -4090,13 +4299,13 @@ pub const Object = struct { |
| 4090 | 4299 | if (o.errors_len_variable == .none) { |
| 4091 | 4300 | const llvm_err_int_ty = try o.errorIntType(.in_memory); |
| 4092 | 4301 | const name = try builder.strtabString("__zig_errors_len"); |
| 4093 | const variable_index = try builder.addVariable(name, llvm_err_int_ty, .default); | |
| 4094 | variable_index.setMutability(.constant, builder); | |
| 4095 | variable_index.setAlignment(Type.errorAbiAlignment(o.zcu).toLlvm(), builder); | |
| 4096 | const global_index = variable_index.ptrConst(&o.builder).global; | |
| 4097 | global_index.setLinkage(.private, builder); | |
| 4098 | global_index.setUnnamedAddr(.unnamed_addr, builder); | |
| 4099 | o.errors_len_variable = variable_index; | |
| 4302 | const llvm_variable = try builder.addVariable(name, llvm_err_int_ty, .default); | |
| 4303 | llvm_variable.setMutability(.constant, builder); | |
| 4304 | llvm_variable.setAlignment(Type.errorAbiAlignment(o.zcu).toLlvm(), builder); | |
| 4305 | const llvm_global = llvm_variable.ptrConst(&o.builder).global; | |
| 4306 | llvm_global.setLinkage(.private, builder); | |
| 4307 | llvm_global.setUnnamedAddr(.unnamed_addr, builder); | |
| 4308 | o.errors_len_variable = llvm_variable; | |
| 4100 | 4309 | } |
| 4101 | 4310 | return o.errors_len_variable; |
| 4102 | 4311 | } |
| ... | ... | @@ -4108,43 +4317,43 @@ pub const Object = struct { |
| 4108 | 4317 | const gop = try o.enum_tag_name_map.getOrPut(o.gpa, enum_ty.toIntern()); |
| 4109 | 4318 | if (gop.found_existing) return gop.value_ptr.*; |
| 4110 | 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 | 4321 | // Dummy function type; `updateEnumTagNameFunction` will replace it with the correct type. |
| 4113 | 4322 | // TODO: change the builder API so we don't need to do this. |
| 4114 | 4323 | try o.builder.fnType(.void, &.{}, .normal), |
| 4115 | 4324 | try o.builder.strtabStringFmt("__zig_tag_name_{f}", .{enum_ty.containerTypeName(ip).fmt(ip)}), |
| 4116 | 4325 | toLlvmAddressSpace(.generic, zcu.getTarget()), |
| 4117 | 4326 | ); |
| 4118 | gop.value_ptr.* = function_index; | |
| 4119 | try o.updateEnumTagNameFunction(enum_ty, function_index); | |
| 4120 | return function_index; | |
| 4327 | gop.value_ptr.* = llvm_function; | |
| 4328 | try o.updateEnumTagNameFunction(enum_ty, llvm_function); | |
| 4329 | return llvm_function; | |
| 4121 | 4330 | } |
| 4122 | 4331 | fn updateEnumTagNameFunction( |
| 4123 | 4332 | o: *Object, |
| 4124 | 4333 | enum_ty: Type, |
| 4125 | function_index: Builder.Function.Index, | |
| 4334 | llvm_function: Builder.Function.Index, | |
| 4126 | 4335 | ) Allocator.Error!void { |
| 4127 | 4336 | const zcu = o.zcu; |
| 4128 | 4337 | const ip = &zcu.intern_pool; |
| 4129 | 4338 | const loaded_enum = ip.loadEnumType(enum_ty.toIntern()); |
| 4130 | 4339 | |
| 4131 | const llvm_usize_ty = try o.lowerType(.usize, .by_value); | |
| 4132 | const llvm_ret_ty = try o.lowerType(.slice_const_u8_sentinel_0, .by_value); | |
| 4133 | const llvm_int_ty = try o.lowerType(.fromInterned(loaded_enum.int_tag_type), .by_value); | |
| 4340 | const llvm_usize_ty = try o.lowerType(.usize, .as_value); | |
| 4341 | const llvm_ret_ty = try o.lowerType(.slice_const_u8_sentinel_0, .as_value); | |
| 4342 | const llvm_int_ty = try o.lowerType(.fromInterned(loaded_enum.int_tag_type), .as_value); | |
| 4134 | 4343 | |
| 4135 | function_index.ptrConst(&o.builder).global.ptr(&o.builder).type = | |
| 4344 | llvm_function.ptrConst(&o.builder).global.ptr(&o.builder).type = | |
| 4136 | 4345 | try o.builder.fnType(llvm_ret_ty, &.{llvm_int_ty}, .normal); |
| 4137 | 4346 | |
| 4138 | 4347 | var attributes: Builder.FunctionAttributes.Wip = .{}; |
| 4139 | 4348 | defer attributes.deinit(&o.builder); |
| 4140 | 4349 | try o.addCommonFnAttributes(&attributes, zcu.root_mod, zcu.root_mod.omit_frame_pointer); |
| 4141 | 4350 | |
| 4142 | function_index.setLinkage(if (o.builder.strip) .private else .internal, &o.builder); | |
| 4143 | function_index.setCallConv(.fastcc, &o.builder); | |
| 4144 | function_index.setAttributes(try attributes.finish(&o.builder), &o.builder); | |
| 4351 | llvm_function.setLinkage(if (o.builder.strip) .private else .internal, &o.builder); | |
| 4352 | llvm_function.setCallConv(.fastcc, &o.builder); | |
| 4353 | llvm_function.setAttributes(try attributes.finish(&o.builder), &o.builder); | |
| 4145 | 4354 | |
| 4146 | 4355 | var wip = try Builder.WipFunction.init(&o.builder, .{ |
| 4147 | .function = function_index, | |
| 4356 | .function = llvm_function, | |
| 4148 | 4357 | .strip = true, |
| 4149 | 4358 | }); |
| 4150 | 4359 | defer wip.deinit(); |
| ... | ... | @@ -4163,23 +4372,23 @@ pub const Object = struct { |
| 4163 | 4372 | for (0..loaded_enum.field_names.len) |field_index| { |
| 4164 | 4373 | const name = try o.builder.stringNull(loaded_enum.field_names.get(ip)[field_index].toSlice(ip)); |
| 4165 | 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); | |
| 4167 | try name_variable_index.setInitializer(name_init, &o.builder); | |
| 4168 | name_variable_index.setMutability(.constant, &o.builder); | |
| 4169 | name_variable_index.setAlignment(comptime Builder.Alignment.fromByteUnits(1), &o.builder); | |
| 4170 | const name_global_index = name_variable_index.ptrConst(&o.builder).global; | |
| 4171 | name_global_index.setLinkage(.private, &o.builder); | |
| 4172 | name_global_index.setUnnamedAddr(.unnamed_addr, &o.builder); | |
| 4375 | const name_llvm_variable = try o.builder.addVariable(.empty, name_init.typeOf(&o.builder), .default); | |
| 4376 | try name_llvm_variable.setInitializer(name_init, &o.builder); | |
| 4377 | name_llvm_variable.setMutability(.constant, &o.builder); | |
| 4378 | name_llvm_variable.setAlignment(comptime .fromByteUnits(1), &o.builder); | |
| 4379 | const name_llvm_global = name_llvm_variable.ptrConst(&o.builder).global; | |
| 4380 | name_llvm_global.setLinkage(.private, &o.builder); | |
| 4381 | name_llvm_global.setUnnamedAddr(.unnamed_addr, &o.builder); | |
| 4173 | 4382 | |
| 4174 | 4383 | const name_val = try o.builder.structValue(llvm_ret_ty, &.{ |
| 4175 | name_global_index.toConst(), | |
| 4384 | name_llvm_global.toConst(), | |
| 4176 | 4385 | try o.builder.intConst(llvm_usize_ty, name.slice(&o.builder).?.len - 1), |
| 4177 | 4386 | }); |
| 4178 | 4387 | |
| 4179 | 4388 | const return_block = try wip.block(1, "Name"); |
| 4180 | 4389 | const llvm_tag_val = switch (loaded_enum.field_values.getOrNone(ip, field_index)) { |
| 4181 | 4390 | .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 | 4393 | try wip_switch.addCase(llvm_tag_val, return_block, &wip); |
| 4185 | 4394 | |
| ... | ... | @@ -4205,40 +4414,40 @@ pub const Object = struct { |
| 4205 | 4414 | const gop = try o.named_enum_map.getOrPut(o.gpa, enum_ty.toIntern()); |
| 4206 | 4415 | if (gop.found_existing) return gop.value_ptr.*; |
| 4207 | 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 | 4418 | // Dummy function type; `updateIsNamedEnumValue` will replace it with the correct type. |
| 4210 | 4419 | // TODO: change the builder API so we don't need to do this. |
| 4211 | 4420 | try o.builder.fnType(.void, &.{}, .normal), |
| 4212 | 4421 | try o.builder.strtabStringFmt("__zig_is_named_enum_value_{f}", .{enum_ty.containerTypeName(ip).fmt(ip)}), |
| 4213 | 4422 | toLlvmAddressSpace(.generic, zcu.getTarget()), |
| 4214 | 4423 | ); |
| 4215 | gop.value_ptr.* = function_index; | |
| 4216 | try o.updateIsNamedEnumValueFunction(enum_ty, function_index); | |
| 4217 | return function_index; | |
| 4424 | gop.value_ptr.* = llvm_function; | |
| 4425 | try o.updateIsNamedEnumValueFunction(enum_ty, llvm_function); | |
| 4426 | return llvm_function; | |
| 4218 | 4427 | } |
| 4219 | 4428 | fn updateIsNamedEnumValueFunction( |
| 4220 | 4429 | o: *Object, |
| 4221 | 4430 | enum_ty: Type, |
| 4222 | function_index: Builder.Function.Index, | |
| 4431 | llvm_function: Builder.Function.Index, | |
| 4223 | 4432 | ) Allocator.Error!void { |
| 4224 | 4433 | const zcu = o.zcu; |
| 4225 | 4434 | const ip = &zcu.intern_pool; |
| 4226 | 4435 | const loaded_enum = ip.loadEnumType(enum_ty.toIntern()); |
| 4227 | 4436 | |
| 4228 | const llvm_int_ty = try o.lowerType(.fromInterned(loaded_enum.int_tag_type), .by_value); | |
| 4229 | function_index.ptrConst(&o.builder).global.ptr(&o.builder).type = | |
| 4437 | const llvm_int_ty = try o.lowerType(.fromInterned(loaded_enum.int_tag_type), .as_value); | |
| 4438 | llvm_function.ptrConst(&o.builder).global.ptr(&o.builder).type = | |
| 4230 | 4439 | try o.builder.fnType(.i1, &.{llvm_int_ty}, .normal); |
| 4231 | 4440 | |
| 4232 | 4441 | var attributes: Builder.FunctionAttributes.Wip = .{}; |
| 4233 | 4442 | defer attributes.deinit(&o.builder); |
| 4234 | 4443 | try o.addCommonFnAttributes(&attributes, zcu.root_mod, zcu.root_mod.omit_frame_pointer); |
| 4235 | 4444 | |
| 4236 | function_index.setLinkage(if (o.builder.strip) .private else .internal, &o.builder); | |
| 4237 | function_index.setCallConv(.fastcc, &o.builder); | |
| 4238 | function_index.setAttributes(try attributes.finish(&o.builder), &o.builder); | |
| 4445 | llvm_function.setLinkage(if (o.builder.strip) .private else .internal, &o.builder); | |
| 4446 | llvm_function.setCallConv(.fastcc, &o.builder); | |
| 4447 | llvm_function.setAttributes(try attributes.finish(&o.builder), &o.builder); | |
| 4239 | 4448 | |
| 4240 | 4449 | var wip: Builder.WipFunction = try .init(&o.builder, .{ |
| 4241 | .function = function_index, | |
| 4450 | .function = llvm_function, | |
| 4242 | 4451 | .strip = true, |
| 4243 | 4452 | }); |
| 4244 | 4453 | defer wip.deinit(); |
| ... | ... | @@ -4252,7 +4461,7 @@ pub const Object = struct { |
| 4252 | 4461 | |
| 4253 | 4462 | if (loaded_enum.field_values.len > 0) { |
| 4254 | 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 | 4465 | try wip_switch.addCase(llvm_tag_val, named_block, &wip); |
| 4257 | 4466 | } |
| 4258 | 4467 | } else { |
| ... | ... | @@ -4274,20 +4483,27 @@ pub const Object = struct { |
| 4274 | 4483 | |
| 4275 | 4484 | pub fn getLibcFunction( |
| 4276 | 4485 | o: *Object, |
| 4486 | pt: Zcu.PerThread, | |
| 4277 | 4487 | fn_name: Builder.StrtabString, |
| 4278 | param_types: []const Builder.Type, | |
| 4279 | return_type: Builder.Type, | |
| 4488 | fn_info: FuncInfo, | |
| 4280 | 4489 | ) Allocator.Error!Builder.Function.Index { |
| 4281 | 4490 | if (o.builder.getGlobal(fn_name)) |global| return switch (global.ptrConst(&o.builder).kind) { |
| 4282 | 4491 | .alias => |alias| alias.getAliasee(&o.builder).ptrConst(&o.builder).kind.function, |
| 4283 | 4492 | .function => |function| function, |
| 4284 | 4493 | .variable, .replaced => unreachable, |
| 4285 | 4494 | }; |
| 4286 | return o.builder.addFunction( | |
| 4287 | try o.builder.fnType(return_type, param_types, .normal), | |
| 4495 | const llvm_function = try o.builder.addFunction( | |
| 4496 | try o.lowerFnType(fn_info), | |
| 4288 | 4497 | fn_name, |
| 4289 | 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 | }; |
| 4293 | 4509 | |
| ... | ... | @@ -4324,7 +4540,7 @@ pub fn toLlvmCallConv(cc: std.lang.CallingConvention, target: *const std.Target) |
| 4324 | 4540 | std.lang.CallingConvention.SpirvFragmentOptions, |
| 4325 | 4541 | std.lang.CallingConvention.SpirvMeshOptions, |
| 4326 | 4542 | => .{ null, 0, 0 }, |
| 4327 | else => @compileError("TODO: toLlvmCallConv" ++ @tagName(pl)), | |
| 4543 | else => @compileError("TODO: toLlvmCallConv(." ++ @tagName(pl) ++ ")"), | |
| 4328 | 4544 | }, |
| 4329 | 4545 | }; |
| 4330 | 4546 | return .{ |
| ... | ... | @@ -4360,6 +4576,7 @@ pub fn toLlvmCallConvTag(cc_tag: std.lang.CallingConvention.Tag, target: *const |
| 4360 | 4576 | null, |
| 4361 | 4577 | .x86_64_vectorcall => .x86_vectorcallcc, |
| 4362 | 4578 | .x86_64_interrupt => .x86_intrcc, |
| 4579 | .x86_64_preserve_none => .preserve_nonecc, | |
| 4363 | 4580 | .x86_stdcall => .x86_stdcallcc, |
| 4364 | 4581 | .x86_fastcall => .x86_fastcallcc, |
| 4365 | 4582 | .x86_thiscall => .x86_thiscallcc, |
| ... | ... | @@ -4375,6 +4592,7 @@ pub fn toLlvmCallConvTag(cc_tag: std.lang.CallingConvention.Tag, target: *const |
| 4375 | 4592 | .x86_interrupt => .x86_intrcc, |
| 4376 | 4593 | .aarch64_vfabi => .aarch64_vector_pcs, |
| 4377 | 4594 | .aarch64_vfabi_sve => .aarch64_sve_vector_pcs, |
| 4595 | .aarch64_preserve_none => .preserve_nonecc, | |
| 4378 | 4596 | .arm_aapcs => .arm_aapcscc, |
| 4379 | 4597 | .arm_aapcs_vfp => .arm_aapcs_vfpcc, |
| 4380 | 4598 | .riscv64_lp64_v => .riscv_vectorcallcc, |
| ... | ... | @@ -4407,6 +4625,7 @@ pub fn toLlvmCallConvTag(cc_tag: std.lang.CallingConvention.Tag, target: *const |
| 4407 | 4625 | .x86_16_interrupt, |
| 4408 | 4626 | .x86_sysv, |
| 4409 | 4627 | .x86_win, |
| 4628 | .x86_mingw, | |
| 4410 | 4629 | .x86_thiscall_mingw, |
| 4411 | 4630 | .x86_64_x32, |
| 4412 | 4631 | .aarch64_aapcs, |
| ... | ... | @@ -4581,47 +4800,6 @@ fn toLlvmGlobalAddressSpace(wanted_address_space: std.lang.AddressSpace, target: |
| 4581 | 4800 | }; |
| 4582 | 4801 | } |
| 4583 | 4802 | |
| 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. | |
| 4587 | pub 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. | |
| 4601 | pub 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. | |
| 4611 | pub 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 | 4803 | /// We need to insert extra padding if LLVM's isn't enough. |
| 4626 | 4804 | /// However we don't want to ever call LLVMABIAlignmentOfType or |
| 4627 | 4805 | /// 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 | 164 | const zcu = o.zcu; |
| 165 | 165 | const ty = val.typeOf(zcu); |
| 166 | 166 | if (!isByRef(ty, zcu)) { |
| 167 | return o.lowerValue(val.toIntern(), .by_value); | |
| 167 | return o.lowerValue(val.toIntern(), .as_value); | |
| 168 | 168 | } else { |
| 169 | 169 | // We need a pointer to a global constant, i.e. a UAV. |
| 170 | 170 | return o.lowerUavRef( |
| 171 | 171 | val.toIntern(), |
| 172 | ty.abiAlignment(zcu), | |
| 172 | ty.abiAlignment(zcu).toLlvm(), | |
| 173 | 173 | target_util.defaultAddressSpace(zcu.getTarget(), .global_constant), |
| 174 | 174 | ); |
| 175 | 175 | } |
| ... | ... | @@ -190,10 +190,10 @@ pub fn genMainBody(fg: *FuncGen) TodoError!void { |
| 190 | 190 | const fn_info = zcu.typeToFunc(fn_ty).?; |
| 191 | 191 | const param_types = fn_info.param_types.get(ip); |
| 192 | 192 | |
| 193 | var it = iterateParamTypes(o, fn_info); | |
| 193 | var it = iterateParamTypes(o, fn_info.cc, fn_info.param_types.get(ip)); | |
| 194 | 194 | |
| 195 | 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 | 197 | .sret => rp: { |
| 198 | 198 | defer it.llvm_index += 1; |
| 199 | 199 | break :rp fg.wip.arg(it.llvm_index); |
| ... | ... | @@ -218,7 +218,7 @@ pub fn genMainBody(fg: *FuncGen) TodoError!void { |
| 218 | 218 | switch (lowering) { |
| 219 | 219 | .no_bits => continue, |
| 220 | 220 | .byval => { |
| 221 | assert(!it.byval_attr); | |
| 221 | assert(it.byval_attr == null); | |
| 222 | 222 | const param_index = it.zig_index - 1; |
| 223 | 223 | const param_ty: Type = .fromInterned(param_types[param_index]); |
| 224 | 224 | const param = fg.wip.arg(it.llvm_index - 1); |
| ... | ... | @@ -237,15 +237,16 @@ pub fn genMainBody(fg: *FuncGen) TodoError!void { |
| 237 | 237 | .byref, .byref_mut => { |
| 238 | 238 | const param_ty: Type = .fromInterned(param_types[it.zig_index - 1]); |
| 239 | 239 | const param = fg.wip.arg(it.llvm_index - 1); |
| 240 | const alignment = if (it.byval_attr) |byval_attr| byval_attr.alignment else .none; | |
| 240 | 241 | |
| 241 | if (isByRef(param_ty, zcu)) { | |
| 242 | if (alignment == .none and isByRef(param_ty, zcu)) { | |
| 242 | 243 | args.appendAssumeCapacity(param); |
| 243 | 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 | 248 | .abi_sized_int => { |
| 248 | assert(!it.byval_attr); | |
| 249 | assert(it.byval_attr == null); | |
| 249 | 250 | const param_ty: Type = .fromInterned(param_types[it.zig_index - 1]); |
| 250 | 251 | const param = fg.wip.arg(it.llvm_index - 1); |
| 251 | 252 | |
| ... | ... | @@ -260,18 +261,18 @@ pub fn genMainBody(fg: *FuncGen) TodoError!void { |
| 260 | 261 | } |
| 261 | 262 | }, |
| 262 | 263 | .slice => { |
| 263 | assert(!it.byval_attr); | |
| 264 | assert(it.byval_attr == null); | |
| 264 | 265 | const param_ty: Type = .fromInterned(param_types[it.zig_index - 1]); |
| 265 | 266 | assert(!isByRef(param_ty, zcu)); |
| 266 | 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 | 269 | &.{ fg.wip.arg(it.llvm_index - 2), fg.wip.arg(it.llvm_index - 1) }, |
| 269 | 270 | "", |
| 270 | 271 | ); |
| 271 | 272 | args.appendAssumeCapacity(slice_val); |
| 272 | 273 | }, |
| 273 | 274 | .multiple_llvm_types => { |
| 274 | assert(!it.byval_attr); | |
| 275 | assert(it.byval_attr == null); | |
| 275 | 276 | const param_ty: Type = .fromInterned(param_types[it.zig_index - 1]); |
| 276 | 277 | const param_alignment = param_ty.abiAlignment(zcu); |
| 277 | 278 | const llvm_ty = try o.builder.arrayType(it.offsets_buffer[it.types_len], .i8); |
| ... | ... | @@ -696,7 +697,7 @@ fn genBodyDebugScope( |
| 696 | 697 | .{ |
| 697 | 698 | .di_flags = .{ .StaticMember = true }, |
| 698 | 699 | .sp_flags = .{ |
| 699 | .Optimized = mod.optimize_mode != .Debug, | |
| 700 | .Optimized = mod.optimize_mode != .debug, | |
| 700 | 701 | .Definition = true, |
| 701 | 702 | .LocalToUnit = true, // inline functions cannot be exported |
| 702 | 703 | }, |
| ... | ... | @@ -721,29 +722,19 @@ fn genBodyDebugScope( |
| 721 | 722 | try self.genBody(body, coverage_point); |
| 722 | 723 | } |
| 723 | 724 | |
| 724 | const CallAttr = enum { | |
| 725 | Auto, | |
| 726 | NeverTail, | |
| 727 | NeverInline, | |
| 728 | AlwaysTail, | |
| 729 | AlwaysInline, | |
| 730 | }; | |
| 731 | ||
| 732 | fn 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; | |
| 725 | fn airCall(fg: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier) Allocator.Error!Builder.Value { | |
| 726 | const o = fg.object; | |
| 737 | 727 | const zcu = o.zcu; |
| 728 | const air_call = fg.air.unwrapCall(inst); | |
| 729 | const args = air_call.args; | |
| 738 | 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 | 732 | const zig_fn_ty = switch (callee_ty.zigTypeTag(zcu)) { |
| 741 | 733 | .@"fn" => callee_ty, |
| 742 | 734 | .pointer => callee_ty.childType(zcu), |
| 743 | 735 | else => unreachable, |
| 744 | 736 | }; |
| 745 | 737 | const fn_info = zcu.typeToFunc(zig_fn_ty).?; |
| 746 | const return_type: Type = .fromInterned(fn_info.return_type); | |
| 747 | 738 | const llvm_fn = llvm_fn: { |
| 748 | 739 | // If the callee is a function *body*, we need to use a pointer to the global. |
| 749 | 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 | 743 | else => {}, |
| 753 | 744 | }; |
| 754 | 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 | ||
| 764 | fn 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 | 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)); | |
| 759 | 782 | |
| 760 | var llvm_args = std.array_list.Managed(Builder.Value).init(self.gpa); | |
| 761 | defer llvm_args.deinit(); | |
| 783 | var llvm_args: std.ArrayList(Builder.Value) = .empty; | |
| 784 | defer llvm_args.deinit(fg.gpa); | |
| 762 | 785 | |
| 763 | 786 | var attributes: Builder.FunctionAttributes.Wip = .{}; |
| 764 | 787 | defer attributes.deinit(&o.builder); |
| 765 | 788 | |
| 766 | if (self.disable_intrinsics) { | |
| 789 | if (fg.disable_intrinsics) { | |
| 767 | 790 | try attributes.addFnAttr(.nobuiltin, &o.builder); |
| 768 | 791 | } |
| 769 | 792 | |
| 770 | switch (modifier) { | |
| 793 | switch (opts.modifier) { | |
| 771 | 794 | .auto, .always_tail => {}, |
| 772 | 795 | .never_tail, .never_inline => try attributes.addFnAttr(.@"noinline", &o.builder), |
| 773 | 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 | 798 | |
| 776 | 799 | const sret_alloc: ?Builder.Value = switch (ret_strat) { |
| 777 | 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); | |
| 779 | 803 | |
| 780 | const ptr = try self.buildZigAlloca(return_type, .none); | |
| 781 | try llvm_args.append(ptr); | |
| 804 | const ptr = try fg.buildZigAlloca(return_type, .none); | |
| 805 | try llvm_args.append(fg.gpa, ptr); | |
| 782 | 806 | break :sret_alloc ptr; |
| 783 | 807 | }, |
| 784 | 808 | else => sret_alloc: { |
| ... | ... | @@ -792,132 +816,111 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier |
| 792 | 816 | |
| 793 | 817 | const err_return_tracing = fn_info.cc == .auto and zcu.comp.config.any_error_tracing; |
| 794 | 818 | if (err_return_tracing) { |
| 795 | assert(self.err_ret_trace != .none); | |
| 796 | try llvm_args.append(self.err_ret_trace); | |
| 797 | } | |
| 798 | ||
| 799 | var it = iterateParamTypes(o, fn_info); | |
| 800 | while (try it.nextCall(self, args)) |lowering| switch (lowering) { | |
| 801 | .no_bits => continue, | |
| 802 | .byval => { | |
| 803 | const arg = args[it.zig_index - 1]; | |
| 804 | const param_ty = self.typeOf(arg); | |
| 805 | const llvm_arg = try self.resolveInst(arg); | |
| 806 | if (isByRef(param_ty, zcu)) { | |
| 807 | const alignment = param_ty.abiAlignment(zcu).toLlvm(); | |
| 808 | // We don't need to handle non-ABI-sized integer types in memory here since they are | |
| 809 | // never by-ref. | |
| 810 | const llvm_param_ty = try o.lowerType(param_ty, .in_memory); | |
| 811 | const loaded = try self.wip.load(.normal, llvm_param_ty, llvm_arg, alignment, ""); | |
| 812 | try llvm_args.append(loaded); | |
| 813 | } else { | |
| 814 | try llvm_args.append(llvm_arg); | |
| 815 | } | |
| 816 | }, | |
| 817 | .byref => { | |
| 818 | const arg = args[it.zig_index - 1]; | |
| 819 | const param_ty = self.typeOf(arg); | |
| 820 | const llvm_arg = try self.resolveInst(arg); | |
| 821 | if (isByRef(param_ty, zcu)) { | |
| 822 | try llvm_args.append(llvm_arg); | |
| 823 | } else { | |
| 824 | const arg_ptr = try self.buildZigAlloca(param_ty, .none); | |
| 825 | try self.store(arg_ptr, .none, llvm_arg, param_ty, .normal); | |
| 826 | try llvm_args.append(arg_ptr); | |
| 827 | } | |
| 828 | }, | |
| 829 | .byref_mut => { | |
| 830 | const arg = args[it.zig_index - 1]; | |
| 831 | const param_ty = self.typeOf(arg); | |
| 832 | const llvm_arg = try self.resolveInst(arg); | |
| 833 | ||
| 834 | const arg_ptr = try self.buildZigAlloca(param_ty, .none); | |
| 835 | try self.store(arg_ptr, .none, llvm_arg, param_ty, .normal); | |
| 836 | try llvm_args.append(arg_ptr); | |
| 837 | }, | |
| 838 | .abi_sized_int => { | |
| 839 | const arg = args[it.zig_index - 1]; | |
| 840 | const param_ty = self.typeOf(arg); | |
| 841 | const llvm_arg = try self.resolveInst(arg); | |
| 842 | const int_llvm_ty = try o.builder.intType(@intCast(param_ty.abiSize(zcu) * 8)); | |
| 843 | ||
| 844 | if (isByRef(param_ty, zcu)) { | |
| 845 | const alignment = param_ty.abiAlignment(zcu).toLlvm(); | |
| 846 | const loaded = try self.wip.load(.normal, int_llvm_ty, llvm_arg, alignment, ""); | |
| 847 | try llvm_args.append(loaded); | |
| 848 | } else { | |
| 849 | // LLVM does not allow bitcasting structs so we must allocate | |
| 850 | // a local, store as one type, and then load as another type. | |
| 851 | const alignment = param_ty.abiAlignment(zcu).toLlvm(); | |
| 852 | const ptr = try self.buildAlloca(int_llvm_ty, alignment); | |
| 853 | try self.store(ptr, .none, llvm_arg, param_ty, .normal); | |
| 854 | const loaded = try self.wip.load(.normal, int_llvm_ty, ptr, alignment, ""); | |
| 855 | try llvm_args.append(loaded); | |
| 856 | } | |
| 857 | }, | |
| 858 | .slice => { | |
| 859 | const arg = args[it.zig_index - 1]; | |
| 860 | const llvm_arg = try self.resolveInst(arg); | |
| 861 | const ptr = try self.wip.extractValue(llvm_arg, &.{0}, ""); | |
| 862 | const len = try self.wip.extractValue(llvm_arg, &.{1}, ""); | |
| 863 | try llvm_args.appendSlice(&.{ ptr, len }); | |
| 864 | }, | |
| 865 | .multiple_llvm_types => { | |
| 866 | const arg = args[it.zig_index - 1]; | |
| 867 | const param_ty = self.typeOf(arg); | |
| 868 | const llvm_arg = try self.resolveInst(arg); | |
| 869 | const param_alignment = param_ty.abiAlignment(zcu); | |
| 870 | const llvm_ty = try o.builder.arrayType(it.offsets_buffer[it.types_len], .i8); | |
| 871 | const arg_ptr = try self.buildAlloca(llvm_ty, param_alignment.toLlvm()); | |
| 872 | try self.store(arg_ptr, .none, llvm_arg, param_ty, .normal); | |
| 873 | ||
| 874 | try llvm_args.ensureUnusedCapacity(it.types_len); | |
| 875 | for (it.types_buffer[0..it.types_len], it.offsets_buffer[0..it.types_len]) |field_ty, offset| { | |
| 876 | const field_ptr = try self.ptraddConst(arg_ptr, offset); | |
| 877 | const loaded = try self.wip.load(.normal, field_ty, field_ptr, param_alignment.offset(offset).toLlvm(), ""); | |
| 878 | llvm_args.appendAssumeCapacity(loaded); | |
| 879 | } | |
| 880 | }, | |
| 881 | .float_array => |count| { | |
| 882 | const arg = args[it.zig_index - 1]; | |
| 883 | const arg_ty = self.typeOf(arg); | |
| 884 | const arg_val = try self.resolveInst(arg); | |
| 885 | ||
| 886 | const arg_ptr: Builder.Value = if (!isByRef(arg_ty, zcu)) ptr: { | |
| 887 | const ptr = try self.buildZigAlloca(arg_ty, .none); | |
| 888 | try self.store(ptr, .none, arg_val, arg_ty, .normal); | |
| 889 | break :ptr ptr; | |
| 890 | } else arg_val; | |
| 891 | ||
| 892 | const float_ty = try o.lowerType(aarch64_c_abi.getFloatArrayType(arg_ty, zcu).?, .in_memory); | |
| 893 | const array_ty = try o.builder.arrayType(count, float_ty); | |
| 819 | assert(fg.err_ret_trace != .none); | |
| 820 | try llvm_args.append(fg.gpa, fg.err_ret_trace); | |
| 821 | } | |
| 894 | 822 | |
| 895 | const loaded = try self.wip.load(.normal, array_ty, arg_ptr, arg_ty.abiAlignment(zcu).toLlvm(), ""); | |
| 896 | try llvm_args.append(loaded); | |
| 897 | }, | |
| 898 | .i32_array, .i64_array => |arr_len| { | |
| 899 | const elem_size: u8 = if (lowering == .i32_array) 32 else 64; | |
| 900 | const arg = args[it.zig_index - 1]; | |
| 901 | const arg_ty = self.typeOf(arg); | |
| 902 | const arg_val = try self.resolveInst(arg); | |
| 903 | ||
| 904 | const arg_ptr: Builder.Value = if (!isByRef(arg_ty, zcu)) ptr: { | |
| 905 | const ptr = try self.buildZigAlloca(arg_ty, .none); | |
| 906 | try self.store(ptr, .none, arg_val, arg_ty, .normal); | |
| 907 | break :ptr ptr; | |
| 908 | } else arg_val; | |
| 823 | var it = iterateParamTypes(o, fn_info.cc, fn_info.param_types); | |
| 824 | while (try it.nextCall(arg_types)) |lowering| { | |
| 825 | const arg_ty: Type = .fromInterned(arg_types[it.zig_index - 1]); | |
| 826 | const arg_val = arg_values[it.zig_index - 1]; | |
| 827 | switch (lowering) { | |
| 828 | .no_bits => continue, | |
| 829 | .byval => { | |
| 830 | if (isByRef(arg_ty, zcu)) { | |
| 831 | const alignment = arg_ty.abiAlignment(zcu).toLlvm(); | |
| 832 | // We don't need to handle non-ABI-sized integer types in memory here since they are | |
| 833 | // never by-ref. | |
| 834 | const llvm_arg_ty = try o.lowerType(arg_ty, .memory_access); | |
| 835 | const loaded = try fg.wip.load(.normal, llvm_arg_ty, arg_val, alignment, ""); | |
| 836 | try llvm_args.append(fg.gpa, loaded); | |
| 837 | } else { | |
| 838 | try llvm_args.append(fg.gpa, arg_val); | |
| 839 | } | |
| 840 | }, | |
| 841 | .byref => { | |
| 842 | if (isByRef(arg_ty, zcu)) { | |
| 843 | try llvm_args.append(fg.gpa, arg_val); | |
| 844 | } else { | |
| 845 | const arg_ptr = try fg.buildZigAlloca(arg_ty, .none); | |
| 846 | try fg.store(arg_ptr, .none, arg_val, arg_ty, .normal); | |
| 847 | try llvm_args.append(fg.gpa, arg_ptr); | |
| 848 | } | |
| 849 | }, | |
| 850 | .byref_mut => { | |
| 851 | const arg_ptr = try fg.buildZigAlloca(arg_ty, .none); | |
| 852 | try fg.store(arg_ptr, .none, arg_val, arg_ty, .normal); | |
| 853 | try llvm_args.append(fg.gpa, arg_ptr); | |
| 854 | }, | |
| 855 | .abi_sized_int => { | |
| 856 | const int_llvm_ty = try o.builder.intType(@intCast(arg_ty.abiSize(zcu) * 8)); | |
| 909 | 857 | |
| 910 | const array_ty = try o.builder.arrayType(arr_len, try o.builder.intType(@intCast(elem_size))); | |
| 911 | const loaded = try self.wip.load(.normal, array_ty, arg_ptr, arg_ty.abiAlignment(zcu).toLlvm(), ""); | |
| 912 | try llvm_args.append(loaded); | |
| 913 | }, | |
| 914 | }; | |
| 858 | if (isByRef(arg_ty, zcu)) { | |
| 859 | const alignment = arg_ty.abiAlignment(zcu).toLlvm(); | |
| 860 | const loaded = try fg.wip.load(.normal, int_llvm_ty, arg_val, alignment, ""); | |
| 861 | try llvm_args.append(fg.gpa, loaded); | |
| 862 | } else { | |
| 863 | // LLVM does not allow bitcasting structs so we must allocate | |
| 864 | // a local, store as one type, and then load as another type. | |
| 865 | const alignment = arg_ty.abiAlignment(zcu).toLlvm(); | |
| 866 | const ptr = try fg.buildAlloca(int_llvm_ty, alignment); | |
| 867 | try fg.store(ptr, .none, arg_val, arg_ty, .normal); | |
| 868 | const loaded = try fg.wip.load(.normal, int_llvm_ty, ptr, alignment, ""); | |
| 869 | try llvm_args.append(fg.gpa, loaded); | |
| 870 | } | |
| 871 | }, | |
| 872 | .slice => { | |
| 873 | const ptr = try fg.wip.extractValue(arg_val, &.{0}, ""); | |
| 874 | const len = try fg.wip.extractValue(arg_val, &.{1}, ""); | |
| 875 | try llvm_args.appendSlice(fg.gpa, &.{ ptr, len }); | |
| 876 | }, | |
| 877 | .multiple_llvm_types => { | |
| 878 | const arg_alignment = arg_ty.abiAlignment(zcu); | |
| 879 | const llvm_ty = try o.builder.arrayType(it.offsets_buffer[it.types_len], .i8); | |
| 880 | const arg_ptr = try fg.buildAlloca(llvm_ty, arg_alignment.toLlvm()); | |
| 881 | try fg.store(arg_ptr, .none, arg_val, arg_ty, .normal); | |
| 882 | ||
| 883 | try llvm_args.ensureUnusedCapacity(fg.gpa, it.types_len); | |
| 884 | for (it.types_buffer[0..it.types_len], it.offsets_buffer[0..it.types_len]) |field_ty, offset| { | |
| 885 | const field_ptr = try fg.ptraddConst(arg_ptr, offset); | |
| 886 | const loaded = try fg.wip.load(.normal, field_ty, field_ptr, arg_alignment.offset(offset).toLlvm(), ""); | |
| 887 | llvm_args.appendAssumeCapacity(loaded); | |
| 888 | } | |
| 889 | }, | |
| 890 | .float_array => |count| { | |
| 891 | const arg_ptr: Builder.Value = if (!isByRef(arg_ty, zcu)) ptr: { | |
| 892 | const ptr = try fg.buildZigAlloca(arg_ty, .none); | |
| 893 | try fg.store(ptr, .none, arg_val, arg_ty, .normal); | |
| 894 | break :ptr ptr; | |
| 895 | } else arg_val; | |
| 896 | ||
| 897 | const float_ty = try o.lowerType(aarch64_c_abi.getFloatArrayType(arg_ty, zcu).?, .memory_access); | |
| 898 | const array_ty = try o.builder.arrayType(count, float_ty); | |
| 899 | ||
| 900 | const loaded = try fg.wip.load(.normal, array_ty, arg_ptr, arg_ty.abiAlignment(zcu).toLlvm(), ""); | |
| 901 | try llvm_args.append(fg.gpa, loaded); | |
| 902 | }, | |
| 903 | .i32_array, .i64_array => |arr_len| { | |
| 904 | const elem_size: u8 = if (lowering == .i32_array) 32 else 64; | |
| 905 | ||
| 906 | const arg_ptr: Builder.Value = if (!isByRef(arg_ty, zcu)) ptr: { | |
| 907 | const ptr = try fg.buildZigAlloca(arg_ty, .none); | |
| 908 | try fg.store(ptr, .none, arg_val, arg_ty, .normal); | |
| 909 | break :ptr ptr; | |
| 910 | } else arg_val; | |
| 911 | ||
| 912 | const array_ty = try o.builder.arrayType(arr_len, try o.builder.intType(@intCast(elem_size))); | |
| 913 | const loaded = try fg.wip.load(.normal, array_ty, arg_ptr, arg_ty.abiAlignment(zcu).toLlvm(), ""); | |
| 914 | try llvm_args.append(fg.gpa, loaded); | |
| 915 | }, | |
| 916 | } | |
| 917 | } | |
| 915 | 918 | |
| 916 | 919 | const cc_info = llvm.toLlvmCallConv(fn_info.cc, target).?; |
| 917 | 920 | |
| 918 | 921 | { |
| 919 | 922 | // Add argument attributes. |
| 920 | it = iterateParamTypes(o, fn_info); | |
| 923 | it = iterateParamTypes(o, fn_info.cc, fn_info.param_types); | |
| 921 | 924 | it.llvm_index += @intFromBool(ret_strat == .sret); |
| 922 | 925 | it.llvm_index += @intFromBool(err_return_tracing); |
| 923 | 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 | 928 | while (try it.next()) |lowering| switch (lowering) { |
| 926 | 929 | .byval => { |
| 927 | 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 | 932 | if (!isByRef(param_ty, zcu)) { |
| 930 | 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 | 950 | }, |
| 948 | 951 | .byref => { |
| 949 | 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 | 954 | try o.addByRefParamAttrs(&attributes, it.llvm_index - 1, it.byval_attr, param_ty); |
| 952 | 955 | }, |
| 953 | 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 | 964 | => continue, |
| 962 | 965 | |
| 963 | 966 | .slice => { |
| 964 | assert(!it.byval_attr); | |
| 965 | const param_ty = Type.fromInterned(fn_info.param_types.get(ip)[it.zig_index - 1]); | |
| 967 | assert(it.byval_attr == null); | |
| 968 | const param_ty = Type.fromInterned(fn_info.param_types[it.zig_index - 1]); | |
| 966 | 969 | const ptr_info = param_ty.ptrInfo(zcu); |
| 967 | 970 | const llvm_arg_i = it.llvm_index - 2; |
| 968 | 971 | |
| ... | ... | @@ -989,8 +992,8 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier |
| 989 | 992 | }; |
| 990 | 993 | } |
| 991 | 994 | |
| 992 | const call = try self.wip.call( | |
| 993 | switch (modifier) { | |
| 995 | const call = try fg.wip.call( | |
| 996 | switch (opts.modifier) { | |
| 994 | 997 | .auto, .never_inline => .normal, |
| 995 | 998 | .never_tail => .notail, |
| 996 | 999 | .always_tail => .musttail, |
| ... | ... | @@ -998,19 +1001,14 @@ fn airCall(self: *FuncGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier |
| 998 | 1001 | }, |
| 999 | 1002 | cc_info.llvm_cc, |
| 1000 | 1003 | try attributes.finish(&o.builder), |
| 1001 | try o.lowerType(zig_fn_ty, .by_value), | |
| 1004 | llvm_fn_ty, | |
| 1002 | 1005 | llvm_fn, |
| 1003 | 1006 | llvm_args.items, |
| 1004 | 1007 | "", |
| 1005 | 1008 | ); |
| 1006 | 1009 | |
| 1007 | if (fn_info.return_type == .noreturn_type and modifier != .always_tail) { | |
| 1008 | return .none; | |
| 1009 | } | |
| 1010 | ||
| 1011 | if (self.liveness.isUnused(inst)) { | |
| 1012 | return .none; | |
| 1013 | } | |
| 1010 | if (opts.is_unused) return .none; | |
| 1011 | if (fn_info.return_type == .noreturn_type and opts.modifier != .always_tail) return .none; | |
| 1014 | 1012 | |
| 1015 | 1013 | // We exit this `switch` if we have a pointer to the return value. |
| 1016 | 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 | 1018 | .sret => sret_alloc.?, |
| 1021 | 1019 | .mem_cast => |llvm_ret_ty| ret_val_ptr: { |
| 1022 | 1020 | const alignment = return_type.abiAlignment(zcu).toLlvm(); |
| 1023 | const ptr = try self.buildAlloca(llvm_ret_ty, alignment); | |
| 1024 | _ = try self.wip.store(.normal, call, ptr, alignment); | |
| 1021 | const ptr = try fg.buildAlloca(llvm_ret_ty, alignment); | |
| 1022 | _ = try fg.wip.store(.normal, call, ptr, alignment); | |
| 1025 | 1023 | break :ret_val_ptr ptr; |
| 1026 | 1024 | }, |
| 1027 | 1025 | }; |
| 1028 | 1026 | if (isByRef(return_type, zcu)) { |
| 1029 | 1027 | return ret_val_ptr; |
| 1030 | 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 | } |
| 1034 | 1032 | |
| ... | ... | @@ -1038,7 +1036,7 @@ fn buildSimplePanic(fg: *FuncGen, panic_id: Zcu.SimplePanicId) Allocator.Error!v |
| 1038 | 1036 | const target = zcu.getTarget(); |
| 1039 | 1037 | const panic_func = zcu.funcInfo(zcu.std_lang_decl_values.get(panic_id.toStdLangDecl())); |
| 1040 | 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); | |
| 1042 | 1040 | |
| 1043 | 1041 | const llvm_panic_fn_ref = try o.lowerNavRef(panic_func.owner_nav); |
| 1044 | 1042 | |
| ... | ... | @@ -1067,7 +1065,7 @@ fn airRet(self: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!vo |
| 1067 | 1065 | |
| 1068 | 1066 | const fn_info = zcu.typeToFunc(Type.fromInterned(ip.getNav(self.nav_index).resolved.?.type)).?; |
| 1069 | 1067 | |
| 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 | 1069 | const val_is_undef = if (un_op.toInterned()) |i| Value.fromInterned(i).isUndef(zcu) else false; |
| 1072 | 1070 | const ret_ty_align = ret_ty.abiAlignment(zcu); |
| 1073 | 1071 | |
| ... | ... | @@ -1076,7 +1074,7 @@ fn airRet(self: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!vo |
| 1076 | 1074 | .none => try self.buildZigAlloca(ret_ty, .none), |
| 1077 | 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 | 1078 | _ = try self.wip.callMemSet( |
| 1081 | 1079 | rp, |
| 1082 | 1080 | ret_ty_align.toLlvm(), |
| ... | ... | @@ -1141,7 +1139,7 @@ fn airRetLoad(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!void { |
| 1141 | 1139 | const ret_ty = ptr_ty.childType(zcu); |
| 1142 | 1140 | const fn_info = zcu.typeToFunc(.fromInterned(ip.getNav(self.nav_index).resolved.?.type)).?; |
| 1143 | 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 | 1143 | .void => _ = try self.wip.retVoid(), |
| 1146 | 1144 | .sret => { |
| 1147 | 1145 | assert(self.ret_ptr != .none); |
| ... | ... | @@ -1165,7 +1163,7 @@ fn airCVaArg(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value |
| 1165 | 1163 | const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op; |
| 1166 | 1164 | const list = try self.resolveInst(ty_op.operand); |
| 1167 | 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); | |
| 1169 | 1167 | |
| 1170 | 1168 | return self.wip.vaArg(list, llvm_arg_ty, ""); |
| 1171 | 1169 | } |
| ... | ... | @@ -1378,7 +1376,7 @@ fn lowerBlock( |
| 1378 | 1376 | if (have_block_result) { |
| 1379 | 1377 | const llvm_ty: Builder.Type = switch (isByRef(inst_ty, zcu)) { |
| 1380 | 1378 | true => .ptr, |
| 1381 | false => try o.lowerType(inst_ty, .by_value), | |
| 1379 | false => try o.lowerType(inst_ty, .as_value), | |
| 1382 | 1380 | }; |
| 1383 | 1381 | parent_bb.ptr(&self.wip).incoming = @intCast(breaks.list.len); |
| 1384 | 1382 | const phi = try self.wip.phi(llvm_ty, ""); |
| ... | ... | @@ -1485,7 +1483,7 @@ fn lowerSwitchDispatch( |
| 1485 | 1483 | const table_index = try self.wip.conv( |
| 1486 | 1484 | .unsigned, |
| 1487 | 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 | 1489 | const target_ptr_ptr = try self.ptraddScaled( |
| ... | ... | @@ -1510,7 +1508,7 @@ fn lowerSwitchDispatch( |
| 1510 | 1508 | // The switch prongs will correspond to our scalar cases. Ranges will |
| 1511 | 1509 | // be handled by conditional branches in the `else` prong. |
| 1512 | 1510 | |
| 1513 | const llvm_usize = try o.lowerType(.usize, .by_value); | |
| 1511 | const llvm_usize = try o.lowerType(.usize, .as_value); | |
| 1514 | 1512 | const cond_int = if (cond_ty.zigTypeTag(zcu) == .pointer) |
| 1515 | 1513 | try self.wip.cast(.ptrtoint, cond, llvm_usize, "") |
| 1516 | 1514 | else |
| ... | ... | @@ -1725,7 +1723,7 @@ fn lowerTry( |
| 1725 | 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 | 1727 | const is_err = try fg.wip.icmp(.ne, loaded, zero, ""); |
| 1730 | 1728 | |
| 1731 | 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 | 1860 | const table_includes_else = item_count != table_len; |
| 1863 | 1861 | |
| 1864 | 1862 | break :jmp_table .{ |
| 1865 | .min = try o.lowerValue(min.toIntern(), .by_value), | |
| 1866 | .max = try o.lowerValue(max.toIntern(), .by_value), | |
| 1863 | .min = try o.lowerValue(min.toIntern(), .as_value), | |
| 1864 | .max = try o.lowerValue(max.toIntern(), .as_value), | |
| 1867 | 1865 | .in_bounds_hint = if (table_includes_else) .none else switch (switch_br.getElseHint()) { |
| 1868 | 1866 | .none, .cold => .none, |
| 1869 | 1867 | .unpredictable => .unpredictable, |
| ... | ... | @@ -2021,142 +2019,102 @@ fn airArrayToSlice(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder |
| 2021 | 2019 | const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op; |
| 2022 | 2020 | const operand_ty = self.typeOf(ty_op.operand); |
| 2023 | 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 | 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 | 2025 | const operand = try self.resolveInst(ty_op.operand); |
| 2028 | 2026 | return self.wip.buildAggregate(slice_llvm_ty, &.{ operand, len }, ""); |
| 2029 | 2027 | } |
| 2030 | 2028 | |
| 2031 | fn airFloatFromInt(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value { | |
| 2032 | const o = self.object; | |
| 2029 | fn airFloatFromInt(fg: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value { | |
| 2030 | const o = fg.object; | |
| 2033 | 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; | |
| 2035 | 2033 | |
| 2036 | const operand = try self.resolveInst(ty_op.operand); | |
| 2037 | const operand_ty = self.typeOf(ty_op.operand); | |
| 2034 | const operand = try fg.resolveInst(ty_op.operand); | |
| 2035 | const operand_ty = fg.typeOf(ty_op.operand); | |
| 2038 | 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); | |
| 2040 | 2038 | |
| 2041 | const dest_ty = self.typeOfIndex(inst); | |
| 2039 | const dest_ty = fg.typeOfIndex(inst); | |
| 2042 | 2040 | const dest_scalar_ty = dest_ty.scalarType(zcu); |
| 2043 | const dest_llvm_ty = try o.lowerType(dest_ty, .by_value); | |
| 2044 | 2041 | const target = zcu.getTarget(); |
| 2045 | 2042 | |
| 2046 | if (intrinsicsAllowed(dest_scalar_ty, target)) return self.wip.conv( | |
| 2047 | if (is_signed_int) .signed else .unsigned, | |
| 2048 | operand, | |
| 2049 | dest_llvm_ty, | |
| 2050 | "", | |
| 2051 | ); | |
| 2043 | if (intrinsicsAllowed(.compiler_rt, dest_scalar_ty, target)) | |
| 2044 | return fg.wip.conv(.fromStdLang(operand_scalar_info.signedness), operand, try o.lowerType(dest_ty, .as_value), ""); | |
| 2052 | 2045 | |
| 2053 | const rt_int_bits = compilerRtIntBits(@intCast(operand_scalar_ty.bitSize(zcu))) orelse { | |
| 2054 | return self.todo("float_from_int on {d} bit integer", .{operand_scalar_ty.bitSize(zcu)}); | |
| 2046 | const rt_int_ty = compilerRtPromoteInt(operand_scalar_info) orelse { | |
| 2047 | return fg.todo("float_from_int on {d} bit integer", .{operand_scalar_info.bits}); | |
| 2055 | 2048 | }; |
| 2056 | const rt_int_ty = try o.builder.intType(rt_int_bits); | |
| 2057 | var extended = try self.wip.conv( | |
| 2058 | if (is_signed_int) .signed else .unsigned, | |
| 2049 | const vector_len = if (operand_ty.isVector(zcu)) operand_ty.vectorLen(zcu) else null; | |
| 2050 | const rt_llvm_int_ty = try o.lowerType(rt_int_ty, .as_value); | |
| 2051 | const extended = try fg.wip.conv( | |
| 2052 | .fromStdLang(operand_scalar_info.signedness), | |
| 2059 | 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 | 2060 | const fn_name = try o.builder.strtabStringFmt("__float{s}{s}i{s}f", .{ |
| 2068 | sign_prefix, | |
| 2069 | compiler_rt_operand_abbrev, | |
| 2070 | compiler_rt_dest_abbrev, | |
| 2061 | switch (operand_scalar_info.signedness) { | |
| 2062 | .signed => "", | |
| 2063 | .unsigned => "un", | |
| 2064 | }, | |
| 2065 | compilerRtIntAbbrev(rt_int_ty.intInfo(zcu).bits), | |
| 2066 | compilerRtFloatAbbrev(target, dest_scalar_ty.floatBits(target)), | |
| 2071 | 2067 | }); |
| 2072 | ||
| 2073 | var param_type = rt_int_ty; | |
| 2074 | if (rt_int_bits == 128 and (target.os.tag == .windows and target.cpu.arch == .x86_64)) { | |
| 2075 | // On Windows x86-64, "ti" functions must use Vector(2, u64) instead of the standard | |
| 2076 | // i128 calling convention to adhere to the ABI that LLVM expects compiler-rt to have. | |
| 2077 | param_type = try o.builder.vectorType(.normal, 2, .i64); | |
| 2078 | extended = try self.wip.cast(.bitcast, extended, param_type, ""); | |
| 2079 | } | |
| 2080 | ||
| 2081 | const libc_fn = try o.getLibcFunction(fn_name, &.{param_type}, dest_llvm_ty); | |
| 2082 | return self.wip.call( | |
| 2083 | .normal, | |
| 2084 | .ccc, | |
| 2085 | .none, | |
| 2086 | libc_fn.typeOf(&o.builder), | |
| 2087 | libc_fn.toValue(&o.builder), | |
| 2088 | &.{extended}, | |
| 2089 | "", | |
| 2090 | ); | |
| 2068 | return fg.buildElementwiseCall(fn_name, .{ | |
| 2069 | .cc = target.cCallingConvention().?, | |
| 2070 | .param_types = &.{rt_int_ty.toIntern()}, | |
| 2071 | .return_type = dest_scalar_ty.toIntern(), | |
| 2072 | }, &.{extended}, vector_len); | |
| 2091 | 2073 | } |
| 2092 | 2074 | |
| 2093 | 2075 | fn airIntFromFloat( |
| 2094 | self: *FuncGen, | |
| 2076 | fg: *FuncGen, | |
| 2095 | 2077 | inst: Air.Inst.Index, |
| 2096 | 2078 | fast: Builder.FastMathKind, |
| 2097 | 2079 | ) TodoError!Builder.Value { |
| 2098 | 2080 | _ = fast; |
| 2099 | 2081 | |
| 2100 | const o = self.object; | |
| 2082 | const o = fg.object; | |
| 2101 | 2083 | const zcu = o.zcu; |
| 2102 | 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; | |
| 2104 | 2086 | |
| 2105 | const operand = try self.resolveInst(ty_op.operand); | |
| 2106 | const operand_ty = self.typeOf(ty_op.operand); | |
| 2087 | const operand = try fg.resolveInst(ty_op.operand); | |
| 2088 | const operand_ty = fg.typeOf(ty_op.operand); | |
| 2107 | 2089 | const operand_scalar_ty = operand_ty.scalarType(zcu); |
| 2108 | 2090 | |
| 2109 | const dest_ty = self.typeOfIndex(inst); | |
| 2091 | const dest_ty = fg.typeOfIndex(inst); | |
| 2110 | 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); | |
| 2112 | 2095 | |
| 2113 | if (intrinsicsAllowed(operand_scalar_ty, target)) { | |
| 2096 | if (intrinsicsAllowed(.compiler_rt, operand_scalar_ty, target)) { | |
| 2114 | 2097 | // TODO set fast math flag |
| 2115 | return self.wip.conv( | |
| 2116 | if (dest_scalar_ty.isSignedInt(zcu)) .signed else .unsigned, | |
| 2117 | operand, | |
| 2118 | dest_llvm_ty, | |
| 2119 | "", | |
| 2120 | ); | |
| 2098 | return fg.wip.conv(.fromStdLang(dest_scalar_info.signedness), operand, dest_llvm_ty, ""); | |
| 2121 | 2099 | } |
| 2122 | 2100 | |
| 2123 | const rt_int_bits = compilerRtIntBits(@intCast(dest_scalar_ty.bitSize(zcu))) orelse { | |
| 2124 | return self.todo("int_from_float to {d} bit integer", .{dest_scalar_ty.bitSize(zcu)}); | |
| 2101 | const rt_int_ty = compilerRtPromoteInt(dest_scalar_info) orelse { | |
| 2102 | return fg.todo("int_from_float to {d} bit integer", .{dest_scalar_info.bits}); | |
| 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 | 2104 | const fn_name = try o.builder.strtabStringFmt("__fix{s}{s}f{s}i", .{ |
| 2140 | sign_prefix, | |
| 2141 | compiler_rt_operand_abbrev, | |
| 2142 | compiler_rt_dest_abbrev, | |
| 2105 | switch (dest_scalar_info.signedness) { | |
| 2106 | .signed => "", | |
| 2107 | .unsigned => "uns", | |
| 2108 | }, | |
| 2109 | compilerRtFloatAbbrev(target, operand_scalar_ty.floatBits(target)), | |
| 2110 | compilerRtIntAbbrev(rt_int_ty.intInfo(zcu).bits), | |
| 2143 | 2111 | }); |
| 2144 | ||
| 2145 | const operand_llvm_ty = try o.lowerType(operand_ty, .by_value); | |
| 2146 | const libc_fn = try o.getLibcFunction(fn_name, &.{operand_llvm_ty}, libc_ret_ty); | |
| 2147 | var result = try self.wip.call( | |
| 2148 | .normal, | |
| 2149 | .ccc, | |
| 2150 | .none, | |
| 2151 | libc_fn.typeOf(&o.builder), | |
| 2152 | libc_fn.toValue(&o.builder), | |
| 2153 | &.{operand}, | |
| 2154 | "", | |
| 2155 | ); | |
| 2156 | ||
| 2157 | if (libc_ret_ty != ret_ty) result = try self.wip.cast(.bitcast, result, ret_ty, ""); | |
| 2158 | if (ret_ty != dest_llvm_ty) result = try self.wip.cast(.trunc, result, dest_llvm_ty, ""); | |
| 2159 | return result; | |
| 2112 | const result = try fg.buildElementwiseCall(fn_name, .{ | |
| 2113 | .cc = target.cCallingConvention().?, | |
| 2114 | .param_types = &.{operand_scalar_ty.toIntern()}, | |
| 2115 | .return_type = rt_int_ty.toIntern(), | |
| 2116 | }, &.{operand}, if (operand_ty.isVector(zcu)) operand_ty.vectorLen(zcu) else null); | |
| 2117 | return fg.wip.cast(.trunc, result, try o.lowerType(dest_ty, .as_value), ""); | |
| 2160 | 2118 | } |
| 2161 | 2119 | |
| 2162 | 2120 | fn 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 | 2125 | fn sliceOrArrayLenInBytes(fg: *FuncGen, ptr: Builder.Value, ty: Type) Allocator.Error!Builder.Value { |
| 2168 | 2126 | const o = fg.object; |
| 2169 | 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 | 2129 | switch (ty.ptrSize(zcu)) { |
| 2172 | 2130 | .slice => { |
| 2173 | 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 | 2323 | }, |
| 2366 | 2324 | .float => { |
| 2367 | 2325 | // 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 | 2353 | const field_offset = parent_ty.structFieldOffset(extra.field_index, zcu); |
| 2396 | 2354 | if (field_offset == 0) return field_ptr; |
| 2397 | 2355 | |
| 2398 | const res_ty = try o.lowerType(ty_pl.ty.toType(), .by_value); | |
| 2399 | const llvm_usize = try o.lowerType(.usize, .by_value); | |
| 2356 | const res_ty = try o.lowerType(ty_pl.ty.toType(), .as_value); | |
| 2357 | const llvm_usize = try o.lowerType(.usize, .as_value); | |
| 2400 | 2358 | |
| 2401 | 2359 | const field_ptr_int = try self.wip.cast(.ptrtoint, field_ptr, llvm_usize, ""); |
| 2402 | 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 | 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 | 2478 | // We avoid taking this path for naked functions because there's no guarantee that such |
| 2521 | 2479 | // functions even have a valid stack pointer, making the `alloca` + `store` unsafe. |
| 2522 | 2480 | |
| ... | ... | @@ -2612,7 +2570,7 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value { |
| 2612 | 2570 | const output_inst = try self.resolveInst(output.operand); |
| 2613 | 2571 | const output_ty = self.typeOf(output.operand); |
| 2614 | 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); | |
| 2616 | 2574 | |
| 2617 | 2575 | switch (constraint[0]) { |
| 2618 | 2576 | '=' => {}, |
| ... | ... | @@ -2650,7 +2608,7 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value { |
| 2650 | 2608 | llvm_ret_indirect[output.index] = false; |
| 2651 | 2609 | |
| 2652 | 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 | 2612 | llvm_ret_i += 1; |
| 2655 | 2613 | } |
| 2656 | 2614 | |
| ... | ... | @@ -2689,7 +2647,7 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value { |
| 2689 | 2647 | llvm_param_types[llvm_param_i] = arg_llvm_value.typeOfWip(&self.wip); |
| 2690 | 2648 | } else { |
| 2691 | 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 | 2651 | const load_inst = try self.wip.load(.normal, arg_llvm_ty, arg_llvm_value, alignment, ""); |
| 2694 | 2652 | llvm_param_values[llvm_param_i] = load_inst; |
| 2695 | 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 | 2687 | llvm_param_attrs[llvm_param_i] = if (constraint[0] == '*') blk: { |
| 2730 | 2688 | if (!is_by_ref) self.maybeMarkAllowZeroAccess(arg_ty.ptrInfo(zcu)); |
| 2731 | 2689 | |
| 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 | 2691 | } else .none; |
| 2734 | 2692 | |
| 2735 | 2693 | llvm_param_i += 1; |
| ... | ... | @@ -2743,7 +2701,7 @@ fn airAssembly(self: *FuncGen, inst: Air.Inst.Index) TodoError!Builder.Value { |
| 2743 | 2701 | if (constraint[0] != '+') continue; |
| 2744 | 2702 | |
| 2745 | 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 | 2705 | if (llvm_ret_indirect[output.index]) { |
| 2748 | 2706 | llvm_param_values[llvm_param_i] = llvm_rw_vals[output.index]; |
| 2749 | 2707 | llvm_param_types[llvm_param_i] = llvm_rw_vals[output.index].typeOfWip(&self.wip); |
| ... | ... | @@ -2957,7 +2915,7 @@ fn airIsNonNull( |
| 2957 | 2915 | )); |
| 2958 | 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 | } |
| 2962 | 2920 | |
| 2963 | 2921 | comptime assert(optional_layout_version == 3); |
| ... | ... | @@ -2986,18 +2944,17 @@ fn airIsErr( |
| 2986 | 2944 | const operand_ty = self.typeOf(un_op); |
| 2987 | 2945 | const err_union_ty = if (operand_is_ptr) operand_ty.childType(zcu) else operand_ty; |
| 2988 | 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); | |
| 2990 | 2948 | |
| 2991 | 2949 | const access_kind: Builder.MemoryAccessKind = |
| 2992 | 2950 | if (operand_is_ptr and operand_ty.isVolatilePtr(zcu)) .@"volatile" else .normal; |
| 2993 | 2951 | |
| 2994 | 2952 | if (err_union_ty.errorUnionSet(zcu).errorSetIsEmpty(zcu)) { |
| 2995 | const val: Builder.Constant = switch (cond) { | |
| 2953 | return switch (cond) { | |
| 2996 | 2954 | .eq => .true, // 0 == 0 |
| 2997 | 2955 | .ne => .false, // 0 != 0 |
| 2998 | 2956 | else => unreachable, |
| 2999 | 2957 | }; |
| 3000 | return val.toValue(); | |
| 3001 | 2958 | } |
| 3002 | 2959 | |
| 3003 | 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 | 3113 | const err_union_ptr_align = err_union_ptr_ty.ptrAlignment(zcu); |
| 3157 | 3114 | |
| 3158 | 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); | |
| 3160 | 3117 | |
| 3161 | 3118 | const access_kind: Builder.MemoryAccessKind = |
| 3162 | 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 | 3191 | const payload_ty = self.typeOf(ty_op.operand); |
| 3235 | 3192 | assert(payload_ty.hasRuntimeBits(zcu)); |
| 3236 | 3193 | 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); | |
| 3238 | 3195 | |
| 3239 | 3196 | const result_ptr = try self.buildZigAlloca(err_un_ty, .none); |
| 3240 | 3197 | |
| ... | ... | @@ -3273,7 +3230,7 @@ fn airWasmMemorySize(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Build |
| 3273 | 3230 | const o = self.object; |
| 3274 | 3231 | const pl_op = self.air.instructions.items(.data)[@backingInt(inst)].pl_op; |
| 3275 | 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 | 3234 | return self.wip.callIntrinsic(.normal, .none, .@"wasm.memory.size", &.{llvm_usize}, &.{ |
| 3278 | 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 | 3240 | const o = self.object; |
| 3284 | 3241 | const pl_op = self.air.instructions.items(.data)[@backingInt(inst)].pl_op; |
| 3285 | 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 | 3244 | return self.wip.callIntrinsic(.normal, .none, .@"wasm.memory.grow", &.{llvm_isize}, &.{ |
| 3288 | 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 | 3267 | .normal, |
| 3311 | 3268 | .none, |
| 3312 | 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 | 3271 | &.{ lhs, rhs }, |
| 3315 | 3272 | "", |
| 3316 | 3273 | ); |
| ... | ... | @@ -3330,7 +3287,7 @@ fn airMax(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { |
| 3330 | 3287 | .normal, |
| 3331 | 3288 | .none, |
| 3332 | 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 | 3291 | &.{ lhs, rhs }, |
| 3335 | 3292 | "", |
| 3336 | 3293 | ); |
| ... | ... | @@ -3342,7 +3299,7 @@ fn airSlice(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value |
| 3342 | 3299 | const ptr = try self.resolveInst(bin_op.lhs); |
| 3343 | 3300 | const len = try self.resolveInst(bin_op.rhs); |
| 3344 | 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 | } |
| 3347 | 3304 | |
| 3348 | 3305 | fn airAdd(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allocator.Error!Builder.Value { |
| ... | ... | @@ -3373,7 +3330,7 @@ fn airSafeArithmetic( |
| 3373 | 3330 | const scalar_ty = inst_ty.scalarType(zcu); |
| 3374 | 3331 | |
| 3375 | 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 | 3334 | const results = |
| 3378 | 3335 | try fg.wip.callIntrinsic(.normal, .none, intrinsic, &.{llvm_inst_ty}, &.{ lhs, rhs }, ""); |
| 3379 | 3336 | |
| ... | ... | @@ -3423,7 +3380,7 @@ fn airAddSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value |
| 3423 | 3380 | .normal, |
| 3424 | 3381 | .none, |
| 3425 | 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 | 3384 | &.{ lhs, rhs }, |
| 3428 | 3385 | "", |
| 3429 | 3386 | ); |
| ... | ... | @@ -3462,7 +3419,7 @@ fn airSubSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value |
| 3462 | 3419 | .normal, |
| 3463 | 3420 | .none, |
| 3464 | 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 | 3423 | &.{ lhs, rhs }, |
| 3467 | 3424 | "", |
| 3468 | 3425 | ); |
| ... | ... | @@ -3501,7 +3458,7 @@ fn airMulSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value |
| 3501 | 3458 | .normal, |
| 3502 | 3459 | .none, |
| 3503 | 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 | 3462 | &.{ lhs, rhs, .@"0" }, |
| 3506 | 3463 | "", |
| 3507 | 3464 | ); |
| ... | ... | @@ -3545,8 +3502,8 @@ fn airDivFloor(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) |
| 3545 | 3502 | return self.buildFloatOp(.floor, fast, inst_ty, 1, .{result}); |
| 3546 | 3503 | } |
| 3547 | 3504 | if (scalar_ty.isSignedInt(zcu)) { |
| 3548 | const scalar_llvm_ty = try o.lowerType(scalar_ty, .by_value); | |
| 3549 | const inst_llvm_ty = try o.lowerType(inst_ty, .by_value); | |
| 3505 | const scalar_llvm_ty = try o.lowerType(scalar_ty, .as_value); | |
| 3506 | const inst_llvm_ty = try o.lowerType(inst_ty, .as_value); | |
| 3550 | 3507 | |
| 3551 | 3508 | const ExpectedContents = [std.math.big.int.calcTwosCompLimbCount(256)]std.math.big.Limb; |
| 3552 | 3509 | var bfa_buf: ExpectedContents = undefined; |
| ... | ... | @@ -3594,8 +3551,8 @@ fn airDivCeil(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) |
| 3594 | 3551 | return self.buildFloatOp(.ceil, fast, inst_ty, 1, .{result}); |
| 3595 | 3552 | } |
| 3596 | 3553 | if (scalar_ty.isSignedInt(zcu)) { |
| 3597 | const scalar_llvm_ty = try o.lowerType(scalar_ty, .by_value); | |
| 3598 | const inst_llvm_ty = try o.lowerType(inst_ty, .by_value); | |
| 3554 | const scalar_llvm_ty = try o.lowerType(scalar_ty, .as_value); | |
| 3555 | const inst_llvm_ty = try o.lowerType(inst_ty, .as_value); | |
| 3599 | 3556 | |
| 3600 | 3557 | const ExpectedContents = [std.math.big.int.calcTwosCompLimbCount(256)]std.math.big.Limb; |
| 3601 | 3558 | var bfa_buf: ExpectedContents = undefined; |
| ... | ... | @@ -3634,8 +3591,8 @@ fn airDivCeil(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) |
| 3634 | 3591 | const correction = try self.wip.cast(.zext, need_correction, inst_llvm_ty, "divCeil.correction"); |
| 3635 | 3592 | return self.wip.bin(.@"add nsw", div, correction, "divCeil"); |
| 3636 | 3593 | } else { |
| 3637 | const scalar_llvm_ty = try o.lowerType(scalar_ty, .by_value); | |
| 3638 | const inst_llvm_ty = try o.lowerType(inst_ty, .by_value); | |
| 3594 | const scalar_llvm_ty = try o.lowerType(scalar_ty, .as_value); | |
| 3595 | const inst_llvm_ty = try o.lowerType(inst_ty, .as_value); | |
| 3639 | 3596 | |
| 3640 | 3597 | const zero = try o.builder.splatValue( |
| 3641 | 3598 | inst_llvm_ty, |
| ... | ... | @@ -3692,15 +3649,17 @@ fn airMod(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allo |
| 3692 | 3649 | const lhs = try self.resolveInst(bin_op.lhs); |
| 3693 | 3650 | const rhs = try self.resolveInst(bin_op.rhs); |
| 3694 | 3651 | const inst_ty = self.typeOfIndex(inst); |
| 3695 | const inst_llvm_ty = try o.lowerType(inst_ty, .by_value); | |
| 3696 | 3652 | const scalar_ty = inst_ty.scalarType(zcu); |
| 3697 | 3653 | |
| 3698 | 3654 | if (scalar_ty.isRuntimeFloat()) { |
| 3699 | 3655 | const a = try self.buildFloatOp(.fmod, fast, inst_ty, 2, .{ lhs, rhs }); |
| 3700 | 3656 | const b = try self.buildFloatOp(.add, fast, inst_ty, 2, .{ a, rhs }); |
| 3701 | 3657 | const c = try self.buildFloatOp(.fmod, fast, inst_ty, 2, .{ b, rhs }); |
| 3702 | const zero = try o.builder.zeroInitValue(inst_llvm_ty); | |
| 3703 | const ltz = try self.buildFloatCmp(fast, .lt, inst_ty, .{ lhs, zero }); | |
| 3658 | const zero = if (isByRef(inst_ty, zcu)) zero: { | |
| 3659 | const zero = try o.builder.zeroInitConst(try o.lowerType(inst_ty, .in_memory)); | |
| 3660 | break :zero try o.lowerConstRef(zero, inst_ty.abiAlignment(zcu).toLlvm()); | |
| 3661 | } else try o.builder.zeroInitConst(try o.lowerType(inst_ty, .as_value)); | |
| 3662 | const ltz = try self.buildFloatCmp(fast, .lt, inst_ty, .{ lhs, zero.toValue() }); | |
| 3704 | 3663 | return self.wip.select(fast, ltz, c, a, ""); |
| 3705 | 3664 | } |
| 3706 | 3665 | if (scalar_ty.isSignedInt(zcu)) { |
| ... | ... | @@ -3709,6 +3668,7 @@ fn airMod(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allo |
| 3709 | 3668 | var bfa: std.heap.BufferFirstAllocator = .init(@ptrCast(&bfa_buf), self.gpa); |
| 3710 | 3669 | const allocator = bfa.allocator(); |
| 3711 | 3670 | |
| 3671 | const inst_llvm_ty = try o.lowerType(inst_ty, .as_value); | |
| 3712 | 3672 | const scalar_bits = scalar_ty.intInfo(zcu).bits; |
| 3713 | 3673 | var smin_big_int: std.math.big.int.Mutable = .{ |
| 3714 | 3674 | .limbs = try allocator.alloc( |
| ... | ... | @@ -3721,7 +3681,7 @@ fn airMod(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allo |
| 3721 | 3681 | defer allocator.free(smin_big_int.limbs); |
| 3722 | 3682 | smin_big_int.setTwosCompIntLimit(.min, .signed, scalar_bits); |
| 3723 | 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 | 3685 | smin_big_int.toConst(), |
| 3726 | 3686 | )); |
| 3727 | 3687 | |
| ... | ... | @@ -3757,7 +3717,7 @@ fn airPtrSub(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value |
| 3757 | 3717 | const ty_pl = self.air.instructions.items(.data)[@backingInt(inst)].ty_pl; |
| 3758 | 3718 | const bin_op = self.air.extraData(Air.Bin, ty_pl.payload).data; |
| 3759 | 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 | 3721 | const ptr_ty = self.typeOf(bin_op.lhs); |
| 3762 | 3722 | const elem_ty = ptr_ty.indexableElem(zcu); |
| 3763 | 3723 | const ptr = switch (ptr_ty.ptrSize(zcu)) { |
| ... | ... | @@ -3790,7 +3750,7 @@ fn airOverflow( |
| 3790 | 3750 | assert(isByRef(inst_ty, zcu)); // auto structs are by-ref |
| 3791 | 3751 | |
| 3792 | 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 | 3754 | const results = |
| 3795 | 3755 | try self.wip.callIntrinsic(.normal, .none, intrinsic, &.{llvm_lhs_ty}, &.{ lhs, rhs }, ""); |
| 3796 | 3756 | |
| ... | ... | @@ -3818,34 +3778,97 @@ fn airOverflow( |
| 3818 | 3778 | } |
| 3819 | 3779 | |
| 3820 | 3780 | fn buildElementwiseCall( |
| 3821 | self: *FuncGen, | |
| 3822 | llvm_fn: Builder.Function.Index, | |
| 3823 | args_vectors: []const Builder.Value, | |
| 3824 | result_vector: Builder.Value, | |
| 3825 | vector_len: usize, | |
| 3781 | fg: *FuncGen, | |
| 3782 | fn_name: Builder.StrtabString, | |
| 3783 | fn_info: Object.FuncInfo, | |
| 3784 | arg_values: []const Builder.Value, | |
| 3785 | vector_len: ?u32, | |
| 3826 | 3786 | ) Allocator.Error!Builder.Value { |
| 3827 | const o = self.object; | |
| 3828 | assert(args_vectors.len <= 3); | |
| 3787 | const o = fg.object; | |
| 3788 | const zcu = o.zcu; | |
| 3789 | const llvm_fn = try fg.object.getLibcFunction(fg.pt, fn_name, fn_info); | |
| 3790 | ||
| 3791 | const iterations = vector_len orelse 1; | |
| 3792 | const ret_ty: Type = .fromInterned(fn_info.return_type); | |
| 3793 | const ret_is_by_ref = isByRef(ret_ty, zcu); | |
| 3794 | if (iterations > 1 and (fn_info.return_type == .void_type or ret_is_by_ref) and | |
| 3795 | for (fn_info.param_types) |param_type| { | |
| 3796 | if (!isByRef(.fromInterned(param_type), zcu)) break false; | |
| 3797 | } else true) | |
| 3798 | { | |
| 3799 | const entry_block = fg.wip.cursor.block; | |
| 3800 | const loop_block = try fg.wip.block(2, "elementwise.loop"); | |
| 3801 | const done_block = try fg.wip.block(1, "elementwise.done"); | |
| 3802 | ||
| 3803 | const result_ptr = if (fn_info.return_type == .void_type) .none else result_ptr: { | |
| 3804 | const ret_llvm_ty = try o.lowerType(ret_ty, .in_memory); | |
| 3805 | break :result_ptr try fg.buildAlloca( | |
| 3806 | if (vector_len) |len| try o.builder.arrayType(len, ret_llvm_ty) else ret_llvm_ty, | |
| 3807 | ret_ty.abiAlignment(zcu).toLlvm(), | |
| 3808 | ); | |
| 3809 | }; | |
| 3810 | _ = try fg.wip.br(loop_block); | |
| 3829 | 3811 | |
| 3830 | var i: usize = 0; | |
| 3831 | var result = result_vector; | |
| 3832 | while (i < vector_len) : (i += 1) { | |
| 3833 | const index_i32 = try o.builder.intValue(.i32, i); | |
| 3812 | fg.wip.cursor = .{ .block = loop_block }; | |
| 3813 | const index = try fg.wip.phi(.i32, "elementwise.index"); | |
| 3834 | 3814 | |
| 3835 | var args: [3]Builder.Value = undefined; | |
| 3836 | for (args[0..args_vectors.len], args_vectors) |*arg_elem, arg_vector| { | |
| 3837 | arg_elem.* = try self.wip.extractElement(arg_vector, index_i32, ""); | |
| 3815 | var arg_elems_buf: [3]Builder.Value = undefined; | |
| 3816 | const arg_elems = arg_elems_buf[0..arg_values.len]; | |
| 3817 | for (arg_elems, fn_info.param_types, arg_values) |*arg_elem, param_type, arg_value| { | |
| 3818 | const arg_elem_ptr = try fg.ptraddScaled(arg_value, index.toValue(), Type.fromInterned(param_type).abiSize(zcu)); | |
| 3819 | arg_elem.* = try fg.load(arg_elem_ptr, .none, .fromInterned(param_type), .normal); | |
| 3838 | 3820 | } |
| 3839 | const result_elem = try self.wip.call( | |
| 3840 | .normal, | |
| 3841 | .ccc, | |
| 3842 | .none, | |
| 3843 | llvm_fn.typeOf(&o.builder), | |
| 3844 | llvm_fn.toValue(&o.builder), | |
| 3845 | args[0..args_vectors.len], | |
| 3846 | "", | |
| 3821 | const result_elem = try fg.buildCall(.{}, llvm_fn.typeOf(&o.builder), llvm_fn.toValue(&o.builder), fn_info, fn_info.param_types, arg_elems); | |
| 3822 | if (fn_info.return_type == .void_type) { | |
| 3823 | assert(result_elem == .none); | |
| 3824 | } else if (result_elem != .none) { | |
| 3825 | const result_elem_ptr = try fg.ptraddScaled(result_ptr, index.toValue(), ret_ty.abiSize(zcu)); | |
| 3826 | try fg.store(result_elem_ptr, .none, result_elem, ret_ty, .normal); | |
| 3827 | } | |
| 3828 | ||
| 3829 | const next_index = try fg.wip.bin(.@"add nuw", index.toValue(), try o.builder.intValue(.i32, 1), "elementwise.next_index"); | |
| 3830 | index.finish(&.{ try o.builder.intValue(.i32, 0), next_index }, &.{ entry_block, loop_block }, &fg.wip); | |
| 3831 | const is_done = try fg.wip.icmp(.eq, next_index, try o.builder.intValue(.i32, iterations), "elementwise.is_done"); | |
| 3832 | _ = try fg.wip.brCond(is_done, done_block, loop_block, .none); | |
| 3833 | ||
| 3834 | fg.wip.cursor = .{ .block = done_block }; | |
| 3835 | return result_ptr; | |
| 3836 | } | |
| 3837 | ||
| 3838 | var result = if (fn_info.return_type == .void_type) .none else if (ret_is_by_ref) result: { | |
| 3839 | const ret_llvm_ty = try o.lowerType(ret_ty, .in_memory); | |
| 3840 | break :result try fg.buildAlloca( | |
| 3841 | if (vector_len) |len| try o.builder.arrayType(len, ret_llvm_ty) else ret_llvm_ty, | |
| 3842 | ret_ty.abiAlignment(zcu).toLlvm(), | |
| 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 | 3873 | return result; |
| 3851 | 3874 | } |
| ... | ... | @@ -3853,19 +3876,18 @@ fn buildElementwiseCall( |
| 3853 | 3876 | /// Creates a floating point comparison by lowering to the appropriate |
| 3854 | 3877 | /// hardware instruction or softfloat routine for the target |
| 3855 | 3878 | fn buildFloatCmp( |
| 3856 | self: *FuncGen, | |
| 3879 | fg: *FuncGen, | |
| 3857 | 3880 | fast: Builder.FastMathKind, |
| 3858 | 3881 | pred: math.CompareOperator, |
| 3859 | 3882 | ty: Type, |
| 3860 | 3883 | params: [2]Builder.Value, |
| 3861 | 3884 | ) Allocator.Error!Builder.Value { |
| 3862 | const o = self.object; | |
| 3885 | const o = fg.object; | |
| 3863 | 3886 | const zcu = o.zcu; |
| 3864 | 3887 | const target = zcu.getTarget(); |
| 3865 | 3888 | const scalar_ty = ty.scalarType(zcu); |
| 3866 | const scalar_llvm_ty = try o.lowerType(scalar_ty, .by_value); | |
| 3867 | 3889 | |
| 3868 | if (intrinsicsAllowed(scalar_ty, target)) { | |
| 3890 | if (intrinsicsAllowed(.compiler_rt, scalar_ty, target)) { | |
| 3869 | 3891 | const cond: Builder.FloatCondition = switch (pred) { |
| 3870 | 3892 | .eq => .oeq, |
| 3871 | 3893 | .neq => .une, |
| ... | ... | @@ -3874,53 +3896,33 @@ fn buildFloatCmp( |
| 3874 | 3896 | .gt => .ogt, |
| 3875 | 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 | } |
| 3879 | 3901 | |
| 3880 | const float_bits = scalar_ty.floatBits(target); | |
| 3881 | const compiler_rt_float_abbrev = compilerRtFloatAbbrev(float_bits); | |
| 3882 | const fn_base_name = switch (pred) { | |
| 3883 | .neq => "ne", | |
| 3884 | .eq => "eq", | |
| 3885 | .lt => "lt", | |
| 3886 | .lte => "le", | |
| 3887 | .gt => "gt", | |
| 3888 | .gte => "ge", | |
| 3889 | }; | |
| 3890 | const fn_name = try o.builder.strtabStringFmt("__{s}{s}f2", .{ fn_base_name, compiler_rt_float_abbrev }); | |
| 3891 | ||
| 3892 | const libc_fn = try o.getLibcFunction(fn_name, &.{ scalar_llvm_ty, scalar_llvm_ty }, .i32); | |
| 3893 | ||
| 3894 | const int_cond: Builder.IntegerCondition = switch (pred) { | |
| 3902 | const fn_name = try o.builder.strtabStringFmt("__{s}{s}f2", .{ | |
| 3903 | switch (pred) { | |
| 3904 | .neq => "ne", | |
| 3905 | .eq => "eq", | |
| 3906 | .lt => "lt", | |
| 3907 | .lte => "le", | |
| 3908 | .gt => "gt", | |
| 3909 | .gte => "ge", | |
| 3910 | }, | |
| 3911 | compilerRtFloatAbbrev(target, scalar_ty.floatBits(target)), | |
| 3912 | }); | |
| 3913 | const result = try fg.buildElementwiseCall(fn_name, .{ | |
| 3914 | .cc = target.cCallingConvention().?, | |
| 3915 | .param_types = &.{ scalar_ty.toIntern(), scalar_ty.toIntern() }, | |
| 3916 | .return_type = .i32_type, | |
| 3917 | }, &params, if (ty.isVector(zcu)) ty.vectorLen(zcu) else null); | |
| 3918 | return fg.wip.icmp(switch (pred) { | |
| 3895 | 3919 | .eq => .eq, |
| 3896 | 3920 | .neq => .ne, |
| 3897 | 3921 | .lt => .slt, |
| 3898 | 3922 | .lte => .sle, |
| 3899 | 3923 | .gt => .sgt, |
| 3900 | 3924 | .gte => .sge, |
| 3901 | }; | |
| 3902 | ||
| 3903 | if (ty.zigTypeTag(zcu) == .vector) { | |
| 3904 | const vec_len = ty.vectorLen(zcu); | |
| 3905 | const vector_result_ty = try o.builder.vectorType(.normal, vec_len, .i32); | |
| 3906 | ||
| 3907 | const init = try o.builder.poisonValue(vector_result_ty); | |
| 3908 | const result = try self.buildElementwiseCall(libc_fn, &params, init, vec_len); | |
| 3909 | ||
| 3910 | const zero_vector = try o.builder.splatValue(vector_result_ty, .@"0"); | |
| 3911 | return self.wip.icmp(int_cond, result, zero_vector, ""); | |
| 3912 | } | |
| 3913 | ||
| 3914 | const result = try self.wip.call( | |
| 3915 | .normal, | |
| 3916 | .ccc, | |
| 3917 | .none, | |
| 3918 | libc_fn.typeOf(&o.builder), | |
| 3919 | libc_fn.toValue(&o.builder), | |
| 3920 | &params, | |
| 3921 | "", | |
| 3922 | ); | |
| 3923 | return self.wip.icmp(int_cond, result, .@"0", ""); | |
| 3925 | }, result, try o.builder.splatValue(result.typeOfWip(&fg.wip), .@"0"), ""); | |
| 3924 | 3926 | } |
| 3925 | 3927 | |
| 3926 | 3928 | const FloatOp = enum { |
| ... | ... | @@ -3949,32 +3951,30 @@ const FloatOp = enum { |
| 3949 | 3951 | trunc, |
| 3950 | 3952 | }; |
| 3951 | 3953 | |
| 3952 | const FloatOpStrat = union(enum) { | |
| 3953 | intrinsic: []const u8, | |
| 3954 | libc: Builder.String, | |
| 3955 | }; | |
| 3956 | ||
| 3957 | 3954 | /// Creates a floating point operation (add, sub, fma, sqrt, exp, etc.) |
| 3958 | 3955 | /// by lowering to the appropriate hardware instruction or softfloat |
| 3959 | 3956 | /// routine for the target |
| 3960 | 3957 | fn buildFloatOp( |
| 3961 | self: *FuncGen, | |
| 3958 | fg: *FuncGen, | |
| 3962 | 3959 | comptime op: FloatOp, |
| 3963 | 3960 | fast: Builder.FastMathKind, |
| 3964 | 3961 | ty: Type, |
| 3965 | 3962 | comptime params_len: usize, |
| 3966 | 3963 | params: [params_len]Builder.Value, |
| 3967 | 3964 | ) Allocator.Error!Builder.Value { |
| 3968 | const o = self.object; | |
| 3965 | const o = fg.object; | |
| 3969 | 3966 | const zcu = o.zcu; |
| 3970 | 3967 | const target = zcu.getTarget(); |
| 3971 | 3968 | const scalar_ty = ty.scalarType(zcu); |
| 3972 | const llvm_ty = try o.lowerType(ty, .by_value); | |
| 3973 | 3969 | |
| 3974 | if (op != .tan and intrinsicsAllowed(scalar_ty, target)) switch (op) { | |
| 3970 | switch (op) { | |
| 3975 | 3971 | // Some operations are dedicated LLVM instructions, not available as intrinsics |
| 3976 | .neg => return self.wip.un(.fneg, params[0], ""), | |
| 3977 | .add, .sub, .mul, .div, .fmod => return self.wip.bin(switch (fast) { | |
| 3972 | .neg => if (intrinsicsAllowed(.compiler_rt, scalar_ty, target)) return fg.wip.un(.fneg, params[0], ""), | |
| 3973 | .add, .sub, .mul, .div, .fmod => if (intrinsicsAllowed(switch (op) { | |
| 3974 | else => unreachable, | |
| 3975 | .add, .sub, .mul, .div => .compiler_rt, | |
| 3976 | .fmod => .libc, | |
| 3977 | }, scalar_ty, target)) return fg.wip.bin(switch (fast) { | |
| 3978 | 3978 | .normal => switch (op) { |
| 3979 | 3979 | .add => .fadd, |
| 3980 | 3980 | .sub => .fsub, |
| ... | ... | @@ -3992,6 +3992,7 @@ fn buildFloatOp( |
| 3992 | 3992 | else => unreachable, |
| 3993 | 3993 | }, |
| 3994 | 3994 | }, params[0], params[1], ""), |
| 3995 | .fma, | |
| 3995 | 3996 | .fmax, |
| 3996 | 3997 | .fmin, |
| 3997 | 3998 | .ceil, |
| ... | ... | @@ -4006,9 +4007,10 @@ fn buildFloatOp( |
| 4006 | 4007 | .round, |
| 4007 | 4008 | .sin, |
| 4008 | 4009 | .sqrt, |
| 4010 | .tan, | |
| 4009 | 4011 | .trunc, |
| 4010 | .fma, | |
| 4011 | => return self.wip.callIntrinsic(fast, .none, switch (op) { | |
| 4012 | => if (intrinsicsAllowed(.libc, scalar_ty, target)) return fg.wip.callIntrinsic(fast, .none, switch (op) { | |
| 4013 | .fma => .fma, | |
| 4012 | 4014 | .fmax => .maxnum, |
| 4013 | 4015 | .fmin => .minnum, |
| 4014 | 4016 | .ceil => .ceil, |
| ... | ... | @@ -4023,39 +4025,154 @@ fn buildFloatOp( |
| 4023 | 4025 | .round => .round, |
| 4024 | 4026 | .sin => .sin, |
| 4025 | 4027 | .sqrt => .sqrt, |
| 4028 | .tan => .tan, | |
| 4026 | 4029 | .trunc => .trunc, |
| 4027 | .fma => .fma, | |
| 4028 | 4030 | else => unreachable, |
| 4029 | }, &.{llvm_ty}, &params, ""), | |
| 4030 | .tan => unreachable, | |
| 4031 | }; | |
| 4031 | }, &.{try o.lowerType(ty, .as_value)}, &params, ""), | |
| 4032 | } | |
| 4032 | 4033 | |
| 4033 | 4034 | const float_bits = scalar_ty.floatBits(target); |
| 4034 | 4035 | const fn_name = switch (op) { |
| 4035 | .neg => { | |
| 4036 | // In this case we can generate a softfloat negation by XORing the | |
| 4037 | // bits with a constant. | |
| 4036 | // In these cases we can generate a softfloat operation by modifying the sign bit using a bitwise operation. | |
| 4037 | .neg, .fabs => if (isByRef(scalar_ty, zcu)) { | |
| 4038 | const is_vector = ty.toIntern() != scalar_ty.toIntern(); | |
| 4039 | const result_ptr = try fg.buildZigAlloca(ty, .none); | |
| 4040 | const entry_block = fg.wip.cursor.block; | |
| 4041 | const loop_block, const done_block, const llvm_usize_ty, const offset, const elem, const result_elem = if (is_vector) loop: { | |
| 4042 | const loop_block = try fg.wip.block(2, "neg_fabs.loop"); | |
| 4043 | const done_block = try fg.wip.block(1, "neg_fabs.done"); | |
| 4044 | _ = try fg.wip.br(loop_block); | |
| 4045 | ||
| 4046 | fg.wip.cursor = .{ .block = loop_block }; | |
| 4047 | const llvm_usize_ty = try o.lowerType(.usize, .as_value); | |
| 4048 | const offset = try fg.wip.phi(llvm_usize_ty, "neg_fabs.offset"); | |
| 4049 | break :loop .{ | |
| 4050 | loop_block, | |
| 4051 | done_block, | |
| 4052 | llvm_usize_ty, | |
| 4053 | offset, | |
| 4054 | try fg.ptraddScaled(params[0], offset.toValue(), 1), | |
| 4055 | try fg.ptraddScaled(result_ptr, offset.toValue(), 1), | |
| 4056 | }; | |
| 4057 | } else .{ undefined, undefined, undefined, undefined, params[0], result_ptr }; | |
| 4058 | switch (scalar_ty.floatBits(target)) { | |
| 4059 | else => unreachable, | |
| 4060 | 80 => { | |
| 4061 | const f80_layout = o.softF80Layout(.{}) catch unreachable; | |
| 4062 | const mantissa = try fg.load( | |
| 4063 | try fg.ptraddConst(elem, f80_layout.mantissa_offset), | |
| 4064 | f80_layout.alignment.offset(f80_layout.mantissa_offset), | |
| 4065 | .u64, | |
| 4066 | .normal, | |
| 4067 | ); | |
| 4068 | const exponent = try fg.load( | |
| 4069 | try fg.ptraddConst(elem, f80_layout.exponent_offset), | |
| 4070 | f80_layout.alignment.offset(f80_layout.exponent_offset), | |
| 4071 | .u16, | |
| 4072 | .normal, | |
| 4073 | ); | |
| 4074 | const exponent_sign_bit: u16 = 1 << (16 - 1); | |
| 4075 | const updated_exponent = try fg.wip.bin(switch (op) { | |
| 4076 | else => unreachable, | |
| 4077 | .neg => .xor, | |
| 4078 | .fabs => .@"and", | |
| 4079 | }, exponent, try o.builder.intValue(.i16, switch (op) { | |
| 4080 | else => unreachable, | |
| 4081 | .neg => exponent_sign_bit, | |
| 4082 | .fabs => exponent_sign_bit - 1, | |
| 4083 | }), "neg_fabs.updated_exponent"); | |
| 4084 | try fg.store( | |
| 4085 | try fg.ptraddConst(result_elem, f80_layout.mantissa_offset), | |
| 4086 | f80_layout.alignment.offset(f80_layout.mantissa_offset), | |
| 4087 | mantissa, | |
| 4088 | .u64, | |
| 4089 | .normal, | |
| 4090 | ); | |
| 4091 | try fg.store( | |
| 4092 | try fg.ptraddConst(result_elem, f80_layout.exponent_offset), | |
| 4093 | f80_layout.alignment.offset(f80_layout.exponent_offset), | |
| 4094 | updated_exponent, | |
| 4095 | .u16, | |
| 4096 | .normal, | |
| 4097 | ); | |
| 4098 | }, | |
| 4099 | 128 => { | |
| 4100 | const f128_layout = o.softF128Layout(.{}) catch unreachable; | |
| 4101 | const lo = try fg.load( | |
| 4102 | try fg.ptraddConst(elem, f128_layout.lo_offset), | |
| 4103 | f128_layout.alignment.offset(f128_layout.lo_offset), | |
| 4104 | .u64, | |
| 4105 | .normal, | |
| 4106 | ); | |
| 4107 | const hi = try fg.load( | |
| 4108 | try fg.ptraddConst(elem, f128_layout.hi_offset), | |
| 4109 | f128_layout.alignment.offset(f128_layout.hi_offset), | |
| 4110 | .u64, | |
| 4111 | .normal, | |
| 4112 | ); | |
| 4113 | const hi_sign_bit: u64 = 1 << (64 - 1); | |
| 4114 | const updated_hi = try fg.wip.bin(switch (op) { | |
| 4115 | else => unreachable, | |
| 4116 | .neg => .xor, | |
| 4117 | .fabs => .@"and", | |
| 4118 | }, hi, try o.builder.intValue(.i64, switch (op) { | |
| 4119 | else => unreachable, | |
| 4120 | .neg => hi_sign_bit, | |
| 4121 | .fabs => hi_sign_bit - 1, | |
| 4122 | }), "neg_fabs.updated_hi"); | |
| 4123 | try fg.store( | |
| 4124 | try fg.ptraddConst(result_elem, f128_layout.lo_offset), | |
| 4125 | f128_layout.alignment.offset(f128_layout.lo_offset), | |
| 4126 | lo, | |
| 4127 | .u64, | |
| 4128 | .normal, | |
| 4129 | ); | |
| 4130 | try fg.store( | |
| 4131 | try fg.ptraddConst(result_elem, f128_layout.hi_offset), | |
| 4132 | f128_layout.alignment.offset(f128_layout.hi_offset), | |
| 4133 | updated_hi, | |
| 4134 | .u64, | |
| 4135 | .normal, | |
| 4136 | ); | |
| 4137 | }, | |
| 4138 | } | |
| 4139 | if (is_vector) { | |
| 4140 | const next_offset = try fg.wip.bin(.@"add nuw", offset.toValue(), try o.builder.intValue(llvm_usize_ty, scalar_ty.abiSize(zcu)), "neg_fabs.next_offset"); | |
| 4141 | offset.finish(&.{ try o.builder.intValue(llvm_usize_ty, 0), next_offset }, &.{ entry_block, loop_block }, &fg.wip); | |
| 4142 | const is_done = try fg.wip.icmp(.eq, next_offset, try o.builder.intValue(llvm_usize_ty, ty.abiSize(zcu)), "neg_fabs.is_done"); | |
| 4143 | _ = try fg.wip.brCond(is_done, done_block, loop_block, .none); | |
| 4144 | ||
| 4145 | fg.wip.cursor = .{ .block = done_block }; | |
| 4146 | } | |
| 4147 | return result_ptr; | |
| 4148 | } else { | |
| 4038 | 4149 | const int_ty = try o.builder.intType(@intCast(float_bits)); |
| 4039 | 4150 | const cast_ty = switch (ty.zigTypeTag(zcu)) { |
| 4040 | 4151 | .vector => try o.builder.vectorType(.normal, ty.vectorLen(zcu), int_ty), |
| 4041 | 4152 | else => int_ty, |
| 4042 | 4153 | }; |
| 4043 | const sign_mask = try o.builder.splatValue( | |
| 4044 | cast_ty, | |
| 4045 | try o.builder.intConst(int_ty, @as(u128, 1) << @intCast(float_bits - 1)), | |
| 4046 | ); | |
| 4047 | const bitcasted_operand = try self.wip.cast(.bitcast, params[0], cast_ty, ""); | |
| 4048 | const result = try self.wip.bin(.xor, bitcasted_operand, sign_mask, ""); | |
| 4049 | return self.wip.cast(.bitcast, result, llvm_ty, ""); | |
| 4154 | const sign_bit = @as(u128, 1) << @intCast(float_bits - 1); | |
| 4155 | const bitwise_rhs = try o.builder.splatValue(cast_ty, try o.builder.intConst(int_ty, switch (op) { | |
| 4156 | else => unreachable, | |
| 4157 | .neg => sign_bit, | |
| 4158 | .fabs => sign_bit - 1, | |
| 4159 | })); | |
| 4160 | const bitcasted_operand = try fg.wip.cast(.bitcast, params[0], cast_ty, ""); | |
| 4161 | const result = try fg.wip.bin(switch (op) { | |
| 4162 | else => unreachable, | |
| 4163 | .neg => .xor, | |
| 4164 | .fabs => .@"and", | |
| 4165 | }, bitcasted_operand, bitwise_rhs, ""); | |
| 4166 | const llvm_ty = try o.lowerType(ty, .as_value); | |
| 4167 | return fg.wip.cast(.bitcast, result, llvm_ty, ""); | |
| 4050 | 4168 | }, |
| 4051 | 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 | 4172 | .ceil, |
| 4055 | 4173 | .cos, |
| 4056 | 4174 | .exp, |
| 4057 | 4175 | .exp2, |
| 4058 | .fabs, | |
| 4059 | 4176 | .floor, |
| 4060 | 4177 | .fma, |
| 4061 | 4178 | .fmax, |
| ... | ... | @@ -4073,27 +4190,27 @@ fn buildFloatOp( |
| 4073 | 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 | } | |
| 4076 | 4199 | |
| 4077 | const scalar_llvm_ty = try o.lowerType(scalar_ty, .by_value); | |
| 4078 | const libc_fn = try o.getLibcFunction( | |
| 4079 | fn_name, | |
| 4080 | @as([3]Builder.Type, @splat(scalar_llvm_ty))[0..params.len], | |
| 4081 | scalar_llvm_ty, | |
| 4082 | ); | |
| 4083 | if (ty.zigTypeTag(zcu) == .vector) { | |
| 4084 | const result = try o.builder.poisonValue(llvm_ty); | |
| 4085 | return self.buildElementwiseCall(libc_fn, &params, result, ty.vectorLen(zcu)); | |
| 4086 | } | |
| 4087 | ||
| 4088 | return self.wip.call( | |
| 4089 | fast.toCallKind(), | |
| 4090 | .ccc, | |
| 4091 | .none, | |
| 4092 | libc_fn.typeOf(&o.builder), | |
| 4093 | libc_fn.toValue(&o.builder), | |
| 4094 | &params, | |
| 4095 | "", | |
| 4096 | ); | |
| 4200 | /// Creates a floating point cast operation by lowering to the specified softfloat routine. | |
| 4201 | fn buildFloatCastCall( | |
| 4202 | fg: *FuncGen, | |
| 4203 | dest_ty: Type, | |
| 4204 | fn_name: Builder.StrtabString, | |
| 4205 | operand_ty: Type, | |
| 4206 | operand: Builder.Value, | |
| 4207 | ) Allocator.Error!Builder.Value { | |
| 4208 | const zcu = fg.object.zcu; | |
| 4209 | return fg.buildElementwiseCall(fn_name, .{ | |
| 4210 | .cc = zcu.getTarget().cCallingConvention().?, | |
| 4211 | .param_types = &.{operand_ty.scalarType(zcu).toIntern()}, | |
| 4212 | .return_type = dest_ty.scalarType(zcu).toIntern(), | |
| 4213 | }, &.{operand}, if (operand_ty.isVector(zcu)) operand_ty.vectorLen(zcu) else null); | |
| 4097 | 4214 | } |
| 4098 | 4215 | |
| 4099 | 4216 | fn 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 | 4246 | const dest_ty = self.typeOfIndex(inst); |
| 4130 | 4247 | assert(isByRef(dest_ty, zcu)); // auto structs are by-ref |
| 4131 | 4248 | |
| 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), ""); | |
| 4133 | 4250 | |
| 4134 | 4251 | const result = try self.wip.bin(.shl, lhs, casted_rhs, ""); |
| 4135 | 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 | 4313 | } |
| 4197 | 4314 | const lhs_scalar_ty = lhs_ty.scalarType(zcu); |
| 4198 | 4315 | |
| 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 | 4317 | return self.wip.bin(if (lhs_scalar_ty.isSignedInt(zcu)) |
| 4201 | 4318 | .@"shl nsw" |
| 4202 | 4319 | else |
| ... | ... | @@ -4217,7 +4334,7 @@ fn airShl(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { |
| 4217 | 4334 | // features which we do not use. Therefore this branch is currently impossible. |
| 4218 | 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 | 4338 | return self.wip.bin(.shl, lhs, casted_rhs, ""); |
| 4222 | 4339 | } |
| 4223 | 4340 | |
| ... | ... | @@ -4231,8 +4348,8 @@ fn airShlSat(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value |
| 4231 | 4348 | |
| 4232 | 4349 | const lhs_ty = self.typeOf(bin_op.lhs); |
| 4233 | 4350 | const lhs_info = lhs_ty.intInfo(zcu); |
| 4234 | const llvm_lhs_ty = try o.lowerType(lhs_ty, .by_value); | |
| 4235 | const llvm_lhs_scalar_ty = try o.lowerType(lhs_ty.scalarType(zcu), .by_value); | |
| 4351 | const llvm_lhs_ty = try o.lowerType(lhs_ty, .as_value); | |
| 4352 | const llvm_lhs_scalar_ty = try o.lowerType(lhs_ty.scalarType(zcu), .as_value); | |
| 4236 | 4353 | |
| 4237 | 4354 | const rhs_ty = self.typeOf(bin_op.rhs); |
| 4238 | 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 | 4359 | } |
| 4243 | 4360 | const rhs_info = rhs_ty.intInfo(zcu); |
| 4244 | 4361 | assert(rhs_info.signedness == .unsigned); |
| 4245 | const llvm_rhs_ty = try o.lowerType(rhs_ty, .by_value); | |
| 4246 | const llvm_rhs_scalar_ty = try o.lowerType(rhs_ty.scalarType(zcu), .by_value); | |
| 4362 | const llvm_rhs_ty = try o.lowerType(rhs_ty, .as_value); | |
| 4363 | const llvm_rhs_scalar_ty = try o.lowerType(rhs_ty.scalarType(zcu), .as_value); | |
| 4247 | 4364 | |
| 4248 | 4365 | const result = try self.wip.callIntrinsic( |
| 4249 | 4366 | .normal, |
| ... | ... | @@ -4319,7 +4436,7 @@ fn airShr(self: *FuncGen, inst: Air.Inst.Index, is_exact: bool) Allocator.Error! |
| 4319 | 4436 | } |
| 4320 | 4437 | const lhs_scalar_ty = lhs_ty.scalarType(zcu); |
| 4321 | 4438 | |
| 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 | 4440 | const is_signed_int = lhs_scalar_ty.isSignedInt(zcu); |
| 4324 | 4441 | |
| 4325 | 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 | 4457 | .normal, |
| 4341 | 4458 | .none, |
| 4342 | 4459 | .abs, |
| 4343 | &.{try o.lowerType(operand_ty, .by_value)}, | |
| 4460 | &.{try o.lowerType(operand_ty, .as_value)}, | |
| 4344 | 4461 | &.{ operand, .false }, |
| 4345 | 4462 | "", |
| 4346 | 4463 | ), |
| ... | ... | @@ -4354,7 +4471,7 @@ fn airIntCast(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error! |
| 4354 | 4471 | const zcu = o.zcu; |
| 4355 | 4472 | const ty_op = fg.air.instructions.items(.data)[@backingInt(inst)].ty_op; |
| 4356 | 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 | 4475 | const operand = try fg.resolveInst(ty_op.operand); |
| 4359 | 4476 | const operand_ty = fg.typeOf(ty_op.operand); |
| 4360 | 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 | 4499 | |
| 4383 | 4500 | if (!have_min_check and !have_max_check) break :bounds_check; |
| 4384 | 4501 | |
| 4385 | const operand_llvm_ty = try o.lowerType(operand_ty, .by_value); | |
| 4386 | const operand_scalar_llvm_ty = try o.lowerType(operand_scalar, .by_value); | |
| 4502 | const operand_llvm_ty = try o.lowerType(operand_ty, .as_value); | |
| 4503 | const operand_scalar_llvm_ty = try o.lowerType(operand_scalar, .as_value); | |
| 4387 | 4504 | |
| 4388 | 4505 | const is_vector = operand_ty.zigTypeTag(zcu) == .vector; |
| 4389 | 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 | 4578 | fn airTrunc(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { |
| 4462 | 4579 | const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op; |
| 4463 | 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 | 4582 | return self.wip.cast(.trunc, operand, dest_llvm_ty, ""); |
| 4466 | 4583 | } |
| 4467 | 4584 | |
| ... | ... | @@ -4471,32 +4588,20 @@ fn airFptrunc(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Valu |
| 4471 | 4588 | const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op; |
| 4472 | 4589 | const operand = try self.resolveInst(ty_op.operand); |
| 4473 | 4590 | const operand_ty = self.typeOf(ty_op.operand); |
| 4591 | const operand_scalar_ty = operand_ty.scalarType(zcu); | |
| 4474 | 4592 | const dest_ty = self.typeOfIndex(inst); |
| 4593 | const dest_scalar_ty = dest_ty.scalarType(zcu); | |
| 4475 | 4594 | const target = zcu.getTarget(); |
| 4476 | 4595 | |
| 4477 | if (intrinsicsAllowed(dest_ty, target) and intrinsicsAllowed(operand_ty, target)) { | |
| 4478 | return self.wip.cast(.fptrunc, operand, try o.lowerType(dest_ty, .by_value), ""); | |
| 4479 | } else { | |
| 4480 | const operand_llvm_ty = try o.lowerType(operand_ty, .by_value); | |
| 4481 | const dest_llvm_ty = try o.lowerType(dest_ty, .by_value); | |
| 4482 | ||
| 4483 | const dest_bits = dest_ty.floatBits(target); | |
| 4484 | const src_bits = operand_ty.floatBits(target); | |
| 4485 | const fn_name = try o.builder.strtabStringFmt("__trunc{s}f{s}f2", .{ | |
| 4486 | compilerRtFloatAbbrev(src_bits), compilerRtFloatAbbrev(dest_bits), | |
| 4487 | }); | |
| 4488 | ||
| 4489 | const libc_fn = try o.getLibcFunction(fn_name, &.{operand_llvm_ty}, dest_llvm_ty); | |
| 4490 | return self.wip.call( | |
| 4491 | .normal, | |
| 4492 | .ccc, | |
| 4493 | .none, | |
| 4494 | libc_fn.typeOf(&o.builder), | |
| 4495 | libc_fn.toValue(&o.builder), | |
| 4496 | &.{operand}, | |
| 4497 | "", | |
| 4498 | ); | |
| 4499 | } | |
| 4596 | if (intrinsicsAllowed(.compiler_rt, dest_scalar_ty, target) and | |
| 4597 | intrinsicsAllowed(.compiler_rt, operand_scalar_ty, target)) | |
| 4598 | return self.wip.cast(.fptrunc, operand, try o.lowerType(dest_ty, .as_value), ""); | |
| 4599 | const dest_bits = dest_scalar_ty.floatBits(target); | |
| 4600 | const src_bits = operand_scalar_ty.floatBits(target); | |
| 4601 | const fn_name = try o.builder.strtabStringFmt("__trunc{s}f{s}f2", .{ | |
| 4602 | compilerRtFloatAbbrev(target, src_bits), compilerRtFloatAbbrev(target, dest_bits), | |
| 4603 | }); | |
| 4604 | return self.buildFloatCastCall(dest_ty, fn_name, operand_ty, operand); | |
| 4500 | 4605 | } |
| 4501 | 4606 | |
| 4502 | 4607 | 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 | 4610 | const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op; |
| 4506 | 4611 | const operand = try self.resolveInst(ty_op.operand); |
| 4507 | 4612 | const operand_ty = self.typeOf(ty_op.operand); |
| 4613 | const operand_scalar_ty = operand_ty.scalarType(zcu); | |
| 4508 | 4614 | const dest_ty = self.typeOfIndex(inst); |
| 4615 | const dest_scalar_ty = dest_ty.scalarType(zcu); | |
| 4509 | 4616 | const target = zcu.getTarget(); |
| 4510 | 4617 | |
| 4511 | if (intrinsicsAllowed(dest_ty, target) and intrinsicsAllowed(operand_ty, target)) { | |
| 4512 | return self.wip.cast(.fpext, operand, try o.lowerType(dest_ty, .by_value), ""); | |
| 4513 | } else { | |
| 4514 | const operand_llvm_ty = try o.lowerType(operand_ty, .by_value); | |
| 4515 | const dest_llvm_ty = try o.lowerType(dest_ty, .by_value); | |
| 4516 | ||
| 4517 | const dest_bits = dest_ty.scalarType(zcu).floatBits(target); | |
| 4518 | const src_bits = operand_ty.scalarType(zcu).floatBits(target); | |
| 4519 | const fn_name = try o.builder.strtabStringFmt("__extend{s}f{s}f2", .{ | |
| 4520 | compilerRtFloatAbbrev(src_bits), compilerRtFloatAbbrev(dest_bits), | |
| 4521 | }); | |
| 4522 | ||
| 4523 | const libc_fn = try o.getLibcFunction(fn_name, &.{operand_llvm_ty}, dest_llvm_ty); | |
| 4524 | if (dest_ty.isVector(zcu)) return self.buildElementwiseCall( | |
| 4525 | libc_fn, | |
| 4526 | &.{operand}, | |
| 4527 | try o.builder.poisonValue(dest_llvm_ty), | |
| 4528 | dest_ty.vectorLen(zcu), | |
| 4529 | ); | |
| 4530 | return self.wip.call( | |
| 4531 | .normal, | |
| 4532 | .ccc, | |
| 4533 | .none, | |
| 4534 | libc_fn.typeOf(&o.builder), | |
| 4535 | libc_fn.toValue(&o.builder), | |
| 4536 | &.{operand}, | |
| 4537 | "", | |
| 4538 | ); | |
| 4539 | } | |
| 4618 | if (intrinsicsAllowed(.compiler_rt, dest_scalar_ty, target) and | |
| 4619 | intrinsicsAllowed(.compiler_rt, operand_scalar_ty, target)) | |
| 4620 | return self.wip.cast(.fpext, operand, try o.lowerType(dest_ty, .as_value), ""); | |
| 4621 | const dest_bits = dest_scalar_ty.floatBits(target); | |
| 4622 | const src_bits = operand_scalar_ty.floatBits(target); | |
| 4623 | const fn_name = try o.builder.strtabStringFmt("__extend{s}f{s}f2", .{ | |
| 4624 | compilerRtFloatAbbrev(target, src_bits), compilerRtFloatAbbrev(target, dest_bits), | |
| 4625 | }); | |
| 4626 | return self.buildFloatCastCall(dest_ty, fn_name, operand_ty, operand); | |
| 4540 | 4627 | } |
| 4541 | 4628 | |
| 4542 | 4629 | fn 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 | 4645 | // * bool/int/float <-> bool/int/float |
| 4559 | 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. | |
| 4562 | 4650 | |
| 4563 | assert(!isByRef(operand_ty, zcu)); | |
| 4564 | assert(!isByRef(dest_ty, zcu)); | |
| 4651 | if (isByRef(operand_ty, zcu)) { | |
| 4652 | const operand_scalar_ty = operand_ty.scalarType(zcu); | |
| 4653 | const target = zcu.getTarget(); | |
| 4654 | const bits = operand_scalar_ty.floatBits(target); | |
| 4655 | const dest_scalar_ty = dest_ty.scalarType(zcu); | |
| 4656 | if (isByRef(dest_ty, zcu)) { | |
| 4657 | assert(dest_scalar_ty.floatBits(target) == bits); | |
| 4658 | return operand; | |
| 4659 | } | |
| 4660 | assert(dest_scalar_ty.intInfo(zcu).bits == bits); | |
| 4565 | 4661 | |
| 4566 | const llvm_dest_ty = try o.lowerType(dest_ty, .by_value); | |
| 4567 | const result = try fg.wip.cast(.bitcast, operand, llvm_dest_ty, ""); | |
| 4568 | if (safety and dest_ty.zigTypeTag(zcu) == .@"enum" and !dest_ty.isNonexhaustiveEnum(zcu)) { | |
| 4569 | const llvm_fn = try o.getIsNamedEnumValueFunction(dest_ty); | |
| 4570 | const is_valid_enum_val = try fg.wip.call( | |
| 4571 | .normal, | |
| 4572 | .fastcc, | |
| 4573 | .none, | |
| 4574 | llvm_fn.typeOf(&o.builder), | |
| 4575 | llvm_fn.toValue(&o.builder), | |
| 4576 | &.{result}, | |
| 4577 | "", | |
| 4578 | ); | |
| 4579 | const fail_block = try fg.wip.block(1, "ValidEnumFail"); | |
| 4580 | const ok_block = try fg.wip.block(1, "ValidEnumOk"); | |
| 4581 | _ = try fg.wip.brCond(is_valid_enum_val, ok_block, fail_block, .none); | |
| 4582 | fg.wip.cursor = .{ .block = fail_block }; | |
| 4662 | const len = if (operand_ty.toIntern() != operand_scalar_ty.toIntern()) | |
| 4663 | operand_ty.vectorLen(zcu) | |
| 4664 | else | |
| 4665 | null; | |
| 4666 | const operand_scalar_size = operand_scalar_ty.abiSize(zcu); | |
| 4667 | var result = if (len) |_| | |
| 4668 | try o.builder.poisonValue(try o.lowerType(dest_ty, .as_value)) | |
| 4669 | else | |
| 4670 | undefined; | |
| 4671 | for (0..len orelse 1) |index| { | |
| 4672 | const result_elem = result_elem: switch (bits) { | |
| 4673 | else => unreachable, | |
| 4674 | 80 => { | |
| 4675 | const f80_layout = o.softF80Layout(.{}) catch unreachable; | |
| 4676 | const mantissa = try fg.load( | |
| 4677 | try fg.ptraddConst(operand, operand_scalar_size * index + f80_layout.mantissa_offset), | |
| 4678 | f80_layout.alignment.offset(f80_layout.mantissa_offset), | |
| 4679 | .u64, | |
| 4680 | .normal, | |
| 4681 | ); | |
| 4682 | const exponent = try fg.load( | |
| 4683 | try fg.ptraddConst(operand, operand_scalar_size * index + f80_layout.exponent_offset), | |
| 4684 | f80_layout.alignment.offset(f80_layout.exponent_offset), | |
| 4685 | .u16, | |
| 4686 | .normal, | |
| 4687 | ); | |
| 4688 | const casted_mantissa = try fg.wip.cast(.zext, mantissa, .i80, "bitCast.casted_mantissa"); | |
| 4689 | const casted_exponent = try fg.wip.cast(.zext, exponent, .i80, "bitCast.casted_exponent"); | |
| 4690 | const shifted_exponent = try fg.wip.bin(.@"shl nuw", casted_exponent, try o.builder.intValue(.i80, 64), "bitCast.shifted_exponent"); | |
| 4691 | break :result_elem try fg.wip.bin(.@"or", casted_mantissa, shifted_exponent, "bitCast.result_elem"); | |
| 4692 | }, | |
| 4693 | 128 => { | |
| 4694 | const f128_layout = o.softF128Layout(.{}) catch unreachable; | |
| 4695 | const lo = try fg.load( | |
| 4696 | try fg.ptraddConst(operand, operand_scalar_size * index + f128_layout.lo_offset), | |
| 4697 | f128_layout.alignment.offset(f128_layout.lo_offset), | |
| 4698 | .u64, | |
| 4699 | .normal, | |
| 4700 | ); | |
| 4701 | const hi = try fg.load( | |
| 4702 | try fg.ptraddConst(operand, operand_scalar_size * index + f128_layout.hi_offset), | |
| 4703 | f128_layout.alignment.offset(f128_layout.hi_offset), | |
| 4704 | .u64, | |
| 4705 | .normal, | |
| 4706 | ); | |
| 4707 | const casted_lo = try fg.wip.cast(.zext, lo, .i128, "bitCast.casted_lo"); | |
| 4708 | const casted_hi = try fg.wip.cast(.zext, hi, .i128, "bitCast.casted_hi"); | |
| 4709 | const shifted_hi = try fg.wip.bin(.@"shl nuw", casted_hi, try o.builder.intValue(.i128, 64), "bitCast.shifted_hi"); | |
| 4710 | break :result_elem try fg.wip.bin(.@"or", casted_lo, shifted_hi, "bitCast.result_elem"); | |
| 4711 | }, | |
| 4712 | }; | |
| 4713 | result = if (len) |_| | |
| 4714 | try fg.wip.insertElement(result, result_elem, try o.builder.intValue(.i32, index), "elementwise.result") | |
| 4715 | else | |
| 4716 | result_elem; | |
| 4717 | } | |
| 4718 | return result; | |
| 4719 | } | |
| 4720 | ||
| 4721 | if (isByRef(dest_ty, zcu)) { | |
| 4722 | const dest_scalar_ty = dest_ty.scalarType(zcu); | |
| 4723 | const bits = dest_scalar_ty.floatBits(zcu.getTarget()); | |
| 4724 | assert(dest_scalar_ty.isRuntimeFloat()); | |
| 4725 | const operand_scalar_ty = operand_ty.scalarType(zcu); | |
| 4726 | assert(operand_scalar_ty.intInfo(zcu).bits == bits); | |
| 4727 | ||
| 4728 | const len = if (operand_ty.toIntern() != operand_scalar_ty.toIntern()) | |
| 4729 | operand_ty.vectorLen(zcu) | |
| 4730 | else | |
| 4731 | null; | |
| 4732 | const operand_scalar_size = operand_scalar_ty.abiSize(zcu); | |
| 4733 | const result_ptr = try fg.buildZigAlloca(dest_ty, .none); | |
| 4734 | for (0..len orelse 1) |index| { | |
| 4735 | const operand_elem = if (len) |_| | |
| 4736 | try fg.wip.extractElement(operand, try o.builder.intValue(.i32, index), "elementwise.operand_elem") | |
| 4737 | else | |
| 4738 | operand; | |
| 4739 | switch (bits) { | |
| 4740 | else => unreachable, | |
| 4741 | 80 => { | |
| 4742 | const f80_layout = o.softF80Layout(.{}) catch unreachable; | |
| 4743 | const mantissa = try fg.wip.cast(.trunc, operand_elem, .i64, "bitCast.mantissa"); | |
| 4744 | const shifted_exponent = try fg.wip.bin(.lshr, operand_elem, try o.builder.intValue(.i80, 64), "bitCast.shifted_exponent"); | |
| 4745 | const exponent = try fg.wip.cast(.@"trunc nuw", shifted_exponent, .i16, "bitCast.exponent"); | |
| 4746 | try fg.store( | |
| 4747 | try fg.ptraddConst(result_ptr, operand_scalar_size * index + f80_layout.mantissa_offset), | |
| 4748 | f80_layout.alignment.offset(f80_layout.mantissa_offset), | |
| 4749 | mantissa, | |
| 4750 | .u64, | |
| 4751 | .normal, | |
| 4752 | ); | |
| 4753 | try fg.store( | |
| 4754 | try fg.ptraddConst(result_ptr, operand_scalar_size * index + f80_layout.exponent_offset), | |
| 4755 | f80_layout.alignment.offset(f80_layout.exponent_offset), | |
| 4756 | exponent, | |
| 4757 | .u16, | |
| 4758 | .normal, | |
| 4759 | ); | |
| 4760 | }, | |
| 4761 | 128 => { | |
| 4762 | const f128_layout = o.softF128Layout(.{}) catch unreachable; | |
| 4763 | const lo = try fg.wip.cast(.trunc, operand_elem, .i64, "bitCast.lo"); | |
| 4764 | const shifted_hi = try fg.wip.bin(.lshr, operand_elem, try o.builder.intValue(.i128, 64), "bitCast.shifted_hi"); | |
| 4765 | const hi = try fg.wip.cast(.@"trunc nuw", shifted_hi, .i64, "bitCast.hi"); | |
| 4766 | try fg.store( | |
| 4767 | try fg.ptraddConst(result_ptr, operand_scalar_size * index + f128_layout.lo_offset), | |
| 4768 | f128_layout.alignment.offset(f128_layout.lo_offset), | |
| 4769 | lo, | |
| 4770 | .u64, | |
| 4771 | .normal, | |
| 4772 | ); | |
| 4773 | try fg.store( | |
| 4774 | try fg.ptraddConst(result_ptr, operand_scalar_size * index + f128_layout.hi_offset), | |
| 4775 | f128_layout.alignment.offset(f128_layout.hi_offset), | |
| 4776 | hi, | |
| 4777 | .u64, | |
| 4778 | .normal, | |
| 4779 | ); | |
| 4780 | }, | |
| 4781 | } | |
| 4782 | } | |
| 4783 | return result_ptr; | |
| 4784 | } | |
| 4785 | ||
| 4786 | const llvm_dest_ty = try o.lowerType(dest_ty, .as_value); | |
| 4787 | const result = try fg.wip.cast(.bitcast, operand, llvm_dest_ty, ""); | |
| 4788 | if (safety and dest_ty.zigTypeTag(zcu) == .@"enum" and !dest_ty.isNonexhaustiveEnum(zcu)) { | |
| 4789 | const llvm_fn = try o.getIsNamedEnumValueFunction(dest_ty); | |
| 4790 | const is_valid_enum_val = try fg.wip.call( | |
| 4791 | .normal, | |
| 4792 | .fastcc, | |
| 4793 | .none, | |
| 4794 | llvm_fn.typeOf(&o.builder), | |
| 4795 | llvm_fn.toValue(&o.builder), | |
| 4796 | &.{result}, | |
| 4797 | "", | |
| 4798 | ); | |
| 4799 | const fail_block = try fg.wip.block(1, "ValidEnumFail"); | |
| 4800 | const ok_block = try fg.wip.block(1, "ValidEnumOk"); | |
| 4801 | _ = try fg.wip.brCond(is_valid_enum_val, ok_block, fail_block, .none); | |
| 4802 | fg.wip.cursor = .{ .block = fail_block }; | |
| 4583 | 4803 | try fg.buildSimplePanic(.invalid_enum_value); |
| 4584 | 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 | 4826 | assert(dest_ty.scalarType(zcu).isPtrAtRuntime(zcu)); |
| 4607 | 4827 | |
| 4608 | 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 | 4830 | return fg.wip.cast(.inttoptr, operand, llvm_dest_ty, ""); |
| 4611 | 4831 | } |
| 4612 | 4832 | |
| ... | ... | @@ -4620,7 +4840,7 @@ fn airIntFromPtr(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val |
| 4620 | 4840 | assert(dest_ty.scalarType(zcu).toIntern() == .usize_type); |
| 4621 | 4841 | |
| 4622 | 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 | 4844 | return fg.wip.cast(.ptrtoint, operand, llvm_dest_ty, ""); |
| 4625 | 4845 | } |
| 4626 | 4846 | |
| ... | ... | @@ -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 | 4913 | const alloca = try self.buildZigAlloca(inst_ty, .none); |
| 4694 | 4914 | try self.store(alloca, .none, arg_val, inst_ty, .normal); |
| 4695 | 4915 | _ = try self.wip.callIntrinsic( |
| ... | ... | @@ -4730,7 +4950,7 @@ fn airAlloc(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value |
| 4730 | 4950 | const ptr_align = ptr_ty.ptrAlignment(zcu); |
| 4731 | 4951 | const elem_ty = ptr_ty.childType(zcu); |
| 4732 | 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 | 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 | 4963 | const ptr_align = ptr_ty.ptrAlignment(zcu); |
| 4744 | 4964 | const elem_ty = ptr_ty.childType(zcu); |
| 4745 | 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 | 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 | 4974 | .none => ty.abiAlignment(o.zcu), |
| 4755 | 4975 | else => |a| a, |
| 4756 | 4976 | }; |
| 4757 | return fg.buildAlloca( | |
| 4758 | try o.lowerType(ty, .in_memory), | |
| 4759 | resolved_align.toLlvm(), | |
| 4760 | ); | |
| 4977 | return fg.buildAlloca(try o.lowerType(ty, .in_memory), resolved_align.toLlvm()); | |
| 4761 | 4978 | } |
| 4762 | 4979 | |
| 4763 | 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 | 5037 | // unexpected call in the user's code. This is problematic if the code in question is |
| 4821 | 5038 | // not ready to correctly make calls yet, such as in our early PIE startup code, or in |
| 4822 | 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 | 5041 | return .none; |
| 4825 | 5042 | } |
| 4826 | 5043 | |
| ... | ... | @@ -4832,7 +5049,7 @@ fn airStore(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!Bu |
| 4832 | 5049 | return .none; |
| 4833 | 5050 | } |
| 4834 | 5051 | |
| 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 | 5053 | _ = try fg.wip.callMemSet( |
| 4837 | 5054 | ptr, |
| 4838 | 5055 | ptr_alignment.toLlvm(), |
| ... | ... | @@ -4850,24 +5067,31 @@ fn airStore(fg: *FuncGen, inst: Air.Inst.Index, safety: bool) Allocator.Error!Bu |
| 4850 | 5067 | const elem = try fg.resolveInst(bin_op.rhs); |
| 4851 | 5068 | |
| 4852 | 5069 | if (ptr_info.flags.vector_index != .none) { |
| 4853 | // Accepted proposal https://github.com/ziglang/zig/issues/24061 will eliminate this usage of `pt`. | |
| 4854 | const vec_ty = try fg.pt.vectorType(.{ | |
| 4855 | .len = ptr_info.packed_offset.host_size, | |
| 4856 | .child = elem_ty.toIntern(), | |
| 4857 | }); | |
| 5070 | if (isByRef(elem_ty, zcu)) { | |
| 5071 | const offset = @backingInt(ptr_info.flags.vector_index) * elem_ty.abiSize(zcu); | |
| 5072 | const elem_ptr = try fg.ptraddConst(ptr, offset); | |
| 5073 | try fg.store(elem_ptr, ptr_alignment.offset(offset), elem, elem_ty, access_kind); | |
| 5074 | } else { | |
| 5075 | // Accepted proposal https://github.com/ziglang/zig/issues/24061 will eliminate this usage of `pt`. | |
| 5076 | const vec_ty = try fg.pt.vectorType(.{ | |
| 5077 | .len = ptr_info.packed_offset.host_size, | |
| 5078 | .child = elem_ty.toIntern(), | |
| 5079 | }); | |
| 5080 | ||
| 5081 | const loaded_vector = try fg.load(ptr, ptr_alignment, vec_ty, access_kind); | |
| 5082 | const index_val = try o.builder.intValue(.i32, ptr_info.flags.vector_index); | |
| 5083 | const modified_vector = try fg.wip.insertElement(loaded_vector, elem, index_val, ""); | |
| 4858 | 5084 | |
| 4859 | const loaded_vector = try fg.load(ptr, ptr_alignment, vec_ty, access_kind); | |
| 4860 | const index_val = try o.builder.intValue(.i32, ptr_info.flags.vector_index); | |
| 4861 | const modified_vector = try fg.wip.insertElement(loaded_vector, elem, index_val, ""); | |
| 5085 | try fg.store(ptr, ptr_alignment, modified_vector, vec_ty, access_kind); | |
| 5086 | } | |
| 4862 | 5087 | |
| 4863 | try fg.store(ptr, ptr_alignment, modified_vector, vec_ty, access_kind); | |
| 4864 | 5088 | return .none; |
| 4865 | 5089 | } |
| 4866 | 5090 | |
| 4867 | 5091 | if (ptr_info.packed_offset.host_size != 0) { |
| 4868 | 5092 | // Accepted proposal https://github.com/ziglang/zig/issues/24061 will eliminate this usage of `pt`. |
| 4869 | 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); | |
| 4871 | 5095 | |
| 4872 | 5096 | const backing_int_val = try fg.load(ptr, ptr_alignment, backing_int_ty, access_kind); |
| 4873 | 5097 | |
| ... | ... | @@ -4927,32 +5151,98 @@ fn airLoad(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { |
| 4927 | 5151 | if (ptr_info.flags.is_volatile) .@"volatile" else .normal; |
| 4928 | 5152 | |
| 4929 | 5153 | if (ptr_info.flags.vector_index != .none) { |
| 4930 | // Accepted proposal https://github.com/ziglang/zig/issues/24061 will eliminate this usage of `pt`. | |
| 4931 | const vec_ty = try fg.pt.vectorType(.{ | |
| 4932 | .len = ptr_info.packed_offset.host_size, | |
| 4933 | .child = elem_ty.toIntern(), | |
| 4934 | }); | |
| 4935 | const vector_val = try fg.load(ptr, ptr_align, vec_ty, access_kind); | |
| 4936 | const index_val = try o.builder.intValue(.i32, ptr_info.flags.vector_index); | |
| 4937 | return fg.wip.extractElement(vector_val, index_val, ""); | |
| 5154 | if (isByRef(elem_ty, zcu)) { | |
| 5155 | const elem_size = elem_ty.abiSize(zcu); | |
| 5156 | const offset = @backingInt(ptr_info.flags.vector_index) * elem_size; | |
| 5157 | const elem_ptr = try fg.ptraddConst(ptr, offset); | |
| 5158 | return fg.load(elem_ptr, ptr_align.offset(offset), elem_ty, access_kind); | |
| 5159 | } else { | |
| 5160 | // Accepted proposal https://github.com/ziglang/zig/issues/24061 will eliminate this usage of `pt`. | |
| 5161 | const vec_ty = try fg.pt.vectorType(.{ | |
| 5162 | .len = ptr_info.packed_offset.host_size, | |
| 5163 | .child = elem_ty.toIntern(), | |
| 5164 | }); | |
| 5165 | const vector_val = try fg.load(ptr, ptr_align, vec_ty, access_kind); | |
| 5166 | const index_val = try o.builder.intValue(.i32, ptr_info.flags.vector_index); | |
| 5167 | return fg.wip.extractElement(vector_val, index_val, ""); | |
| 5168 | } | |
| 4938 | 5169 | } |
| 4939 | 5170 | |
| 4940 | 5171 | if (ptr_info.packed_offset.host_size == 0) { |
| 4941 | 5172 | return fg.load(ptr, ptr_align, elem_ty, access_kind); |
| 4942 | 5173 | } |
| 4943 | 5174 | |
| 4944 | assert(!isByRef(elem_ty, zcu)); // all packable types are by-val | |
| 4945 | ||
| 4946 | 5175 | // Accepted proposal https://github.com/ziglang/zig/issues/24061 will eliminate this usage of `pt`. |
| 4947 | 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); | |
| 4949 | 5178 | |
| 4950 | 5179 | const backing_int_val = try fg.load(ptr, ptr_align, backing_int_ty, .normal); |
| 4951 | 5180 | |
| 4952 | 5181 | const elem_bits = ptr_ty.childType(zcu).bitSize(zcu); |
| 4953 | 5182 | const shift_amt = try o.builder.intValue(llvm_backing_int_ty, ptr_info.packed_offset.bit_offset); |
| 4954 | 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); | |
| 4956 | 5246 | |
| 4957 | 5247 | if (elem_ty.zigTypeTag(zcu) == .float or elem_ty.zigTypeTag(zcu) == .vector) { |
| 4958 | 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 | 5292 | fn airRetAddr(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { |
| 5003 | 5293 | _ = inst; |
| 5004 | 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 | 5296 | if (!target_util.supportsReturnAddress(self.object.zcu.getTarget(), self.ownerModule().optimize_mode)) { |
| 5007 | 5297 | // https://github.com/ziglang/zig/issues/11946 |
| 5008 | 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 | 5304 | fn airFrameAddress(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { |
| 5015 | 5305 | _ = inst; |
| 5016 | 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 | } |
| 5019 | 5309 | |
| 5020 | 5310 | fn airCmpxchg( |
| ... | ... | @@ -5031,7 +5321,7 @@ fn airCmpxchg( |
| 5031 | 5321 | var expected_value = try self.resolveInst(extra.expected_value); |
| 5032 | 5322 | var new_value = try self.resolveInst(extra.new_value); |
| 5033 | 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 | 5325 | const llvm_abi_ty = try self.getAtomicAbiType(operand_ty, false); |
| 5036 | 5326 | if (llvm_abi_ty != .none) { |
| 5037 | 5327 | // operand needs widening and truncating |
| ... | ... | @@ -5101,7 +5391,7 @@ fn airAtomicRmw(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Va |
| 5101 | 5391 | const op = toLlvmAtomicRmwBinOp(extra.op(), is_signed_int, is_float); |
| 5102 | 5392 | const ordering = toLlvmAtomicOrdering(extra.ordering()); |
| 5103 | 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); | |
| 5105 | 5395 | |
| 5106 | 5396 | const access_kind: Builder.MemoryAccessKind = |
| 5107 | 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 | 5420 | |
| 5131 | 5421 | // If we are storing a pointer we need to convert to and from a plain old integer. |
| 5132 | 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 | 5424 | else => operand, |
| 5135 | 5425 | }; |
| 5136 | 5426 | |
| ... | ... | @@ -5169,7 +5459,7 @@ fn airAtomicLoad(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.V |
| 5169 | 5459 | Type.fromInterned(info.child).abiAlignment(zcu)).toLlvm(); |
| 5170 | 5460 | const access_kind: Builder.MemoryAccessKind = |
| 5171 | 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); | |
| 5173 | 5463 | |
| 5174 | 5464 | self.maybeMarkAllowZeroAccess(info); |
| 5175 | 5465 | |
| ... | ... | @@ -5503,11 +5793,11 @@ fn airClzCtz(self: *FuncGen, inst: Air.Inst.Index, intrinsic: Builder.Intrinsic) |
| 5503 | 5793 | .normal, |
| 5504 | 5794 | .none, |
| 5505 | 5795 | intrinsic, |
| 5506 | &.{try o.lowerType(operand_ty, .by_value)}, | |
| 5796 | &.{try o.lowerType(operand_ty, .as_value)}, | |
| 5507 | 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 | } |
| 5512 | 5802 | |
| 5513 | 5803 | fn 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 | 5811 | .normal, |
| 5522 | 5812 | .none, |
| 5523 | 5813 | intrinsic, |
| 5524 | &.{try o.lowerType(operand_ty, .by_value)}, | |
| 5814 | &.{try o.lowerType(operand_ty, .as_value)}, | |
| 5525 | 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 | } |
| 5530 | 5820 | |
| 5531 | 5821 | fn 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 | 5828 | |
| 5539 | 5829 | const inst_ty = self.typeOfIndex(inst); |
| 5540 | 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); | |
| 5542 | 5832 | |
| 5543 | 5833 | if (bits % 16 == 8) { |
| 5544 | 5834 | // 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 | 5849 | |
| 5560 | 5850 | const result = |
| 5561 | 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 | } |
| 5564 | 5854 | |
| 5565 | 5855 | fn 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 | 5869 | |
| 5580 | 5870 | for (0..names.len) |name_index| { |
| 5581 | 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 | 5873 | try wip_switch.addCase(this_tag_int_value, valid_block, &self.wip); |
| 5584 | 5874 | } |
| 5585 | 5875 | self.wip.cursor = .{ .block = valid_block }; |
| ... | ... | @@ -5638,7 +5928,7 @@ fn airErrorName(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Va |
| 5638 | 5928 | const slice_ty = self.typeOfIndex(inst); |
| 5639 | 5929 | |
| 5640 | 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), ""); | |
| 5642 | 5932 | |
| 5643 | 5933 | const error_name_table_ptr = try o.getErrorNameTable(); |
| 5644 | 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 | 5939 | const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op; |
| 5650 | 5940 | const scalar = try self.resolveInst(ty_op.operand); |
| 5651 | 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 | } |
| 5654 | 5944 | |
| 5655 | 5945 | fn 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 | 5962 | const operand = try fg.resolveInst(unwrapped.operand); |
| 5673 | 5963 | const mask = unwrapped.mask; |
| 5674 | 5964 | const operand_ty = fg.typeOf(unwrapped.operand); |
| 5675 | const llvm_operand_ty = try o.lowerType(operand_ty, .by_value); | |
| 5676 | const llvm_result_ty = try o.lowerType(unwrapped.result_ty, .by_value); | |
| 5677 | const llvm_elem_ty = try o.lowerType(unwrapped.result_ty.childType(zcu), .by_value); | |
| 5965 | const llvm_operand_ty = try o.lowerType(operand_ty, .as_value); | |
| 5966 | const llvm_result_ty = try o.lowerType(unwrapped.result_ty, .as_value); | |
| 5967 | const llvm_elem_ty = try o.lowerType(unwrapped.result_ty.childType(zcu), .as_value); | |
| 5678 | 5968 | const llvm_poison_elem = try o.builder.poisonConst(llvm_elem_ty); |
| 5679 | 5969 | const llvm_poison_mask_elem = try o.builder.poisonConst(.i32); |
| 5680 | 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 | 5994 | .elem => llvm_poison_elem, |
| 5705 | 5995 | .value => |val| if (!Value.fromInterned(val).isUndef(zcu)) elem: { |
| 5706 | 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 | 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 | 6066 | const unwrapped = fg.air.unwrapShuffleTwo(zcu, inst); |
| 5777 | 6067 | |
| 5778 | 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 | 6070 | const llvm_mask_ty = try o.builder.vectorType(.normal, @intCast(mask.len), .i32); |
| 5781 | 6071 | const llvm_poison_mask_elem = try o.builder.poisonConst(.i32); |
| 5782 | 6072 | |
| ... | ... | @@ -5848,95 +6138,25 @@ fn airShuffleTwo(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Val |
| 5848 | 6138 | ); |
| 5849 | 6139 | } |
| 5850 | 6140 | |
| 5851 | /// Reduce a vector by repeatedly applying `llvm_fn` to produce an accumulated result. | |
| 5852 | /// | |
| 5853 | /// Equivalent to: | |
| 5854 | /// ``` | |
| 5855 | /// var accum: T = init; | |
| 5856 | /// for (0..i) |i| { | |
| 5857 | /// accum = llvm_fn(accum, vec[i]); | |
| 5858 | /// } | |
| 5859 | /// // result is 'accum' | |
| 5860 | /// ``` | |
| 5861 | fn 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 | ||
| 5919 | fn airReduce(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allocator.Error!Builder.Value { | |
| 5920 | const o = self.object; | |
| 6141 | fn airReduce(fg: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) Allocator.Error!Builder.Value { | |
| 6142 | const o = fg.object; | |
| 5921 | 6143 | const zcu = o.zcu; |
| 5922 | 6144 | const target = zcu.getTarget(); |
| 5923 | 6145 | |
| 5924 | const reduce = self.air.instructions.items(.data)[@backingInt(inst)].reduce; | |
| 5925 | const operand = try self.resolveInst(reduce.operand); | |
| 5926 | const operand_ty = self.typeOf(reduce.operand); | |
| 5927 | const llvm_operand_ty = try o.lowerType(operand_ty, .by_value); | |
| 5928 | const scalar_ty = self.typeOfIndex(inst); | |
| 5929 | const llvm_scalar_ty = try o.lowerType(scalar_ty, .by_value); | |
| 6146 | const reduce = fg.air.instructions.items(.data)[@backingInt(inst)].reduce; | |
| 6147 | const operand = try fg.resolveInst(reduce.operand); | |
| 6148 | const operand_ty = fg.typeOf(reduce.operand); | |
| 6149 | const scalar_ty = fg.typeOfIndex(inst); | |
| 5930 | 6150 | |
| 5931 | 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 | 6153 | .And => .@"vector.reduce.and", |
| 5934 | 6154 | .Or => .@"vector.reduce.or", |
| 5935 | 6155 | .Xor => .@"vector.reduce.xor", |
| 5936 | 6156 | else => unreachable, |
| 5937 | }, &.{llvm_operand_ty}, &.{operand}, ""), | |
| 6157 | }, &.{try o.lowerType(operand_ty, .as_value)}, &.{operand}, ""), | |
| 5938 | 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 | 6160 | .Min => if (scalar_ty.isSignedInt(zcu)) |
| 5941 | 6161 | .@"vector.reduce.smin" |
| 5942 | 6162 | else |
| ... | ... | @@ -5946,29 +6166,29 @@ fn airReduce(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) A |
| 5946 | 6166 | else |
| 5947 | 6167 | .@"vector.reduce.umax", |
| 5948 | 6168 | else => unreachable, |
| 5949 | }, &.{llvm_operand_ty}, &.{operand}, ""), | |
| 5950 | .float => if (intrinsicsAllowed(scalar_ty, target)) | |
| 5951 | return self.wip.callIntrinsic(fast, .none, switch (reduce.operation) { | |
| 6169 | }, &.{try o.lowerType(operand_ty, .as_value)}, &.{operand}, ""), | |
| 6170 | .float => if (intrinsicsAllowed(.libc, scalar_ty, target)) | |
| 6171 | return fg.wip.callIntrinsic(fast, .none, switch (reduce.operation) { | |
| 5952 | 6172 | .Min => .@"vector.reduce.fmin", |
| 5953 | 6173 | .Max => .@"vector.reduce.fmax", |
| 5954 | 6174 | else => unreachable, |
| 5955 | }, &.{llvm_operand_ty}, &.{operand}, ""), | |
| 6175 | }, &.{try o.lowerType(operand_ty, .as_value)}, &.{operand}, ""), | |
| 5956 | 6176 | else => unreachable, |
| 5957 | 6177 | }, |
| 5958 | 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 | 6180 | .Add => .@"vector.reduce.add", |
| 5961 | 6181 | .Mul => .@"vector.reduce.mul", |
| 5962 | 6182 | else => unreachable, |
| 5963 | }, &.{llvm_operand_ty}, &.{operand}, ""), | |
| 5964 | .float => if (intrinsicsAllowed(scalar_ty, target)) | |
| 5965 | return self.wip.callIntrinsic(fast, .none, switch (reduce.operation) { | |
| 6183 | }, &.{try o.lowerType(operand_ty, .as_value)}, &.{operand}, ""), | |
| 6184 | .float => if (intrinsicsAllowed(.compiler_rt, scalar_ty, target)) | |
| 6185 | return fg.wip.callIntrinsic(fast, .none, switch (reduce.operation) { | |
| 5966 | 6186 | .Add => .@"vector.reduce.fadd", |
| 5967 | 6187 | .Mul => .@"vector.reduce.fmul", |
| 5968 | 6188 | else => unreachable, |
| 5969 | }, &.{llvm_operand_ty}, &.{ switch (reduce.operation) { | |
| 5970 | .Add => try o.builder.fpValue(llvm_scalar_ty, -0.0), | |
| 5971 | .Mul => try o.builder.fpValue(llvm_scalar_ty, 1.0), | |
| 6189 | }, &.{try o.lowerType(operand_ty, .as_value)}, &.{ switch (reduce.operation) { | |
| 6190 | .Add => try o.builder.fpValue(try o.lowerType(scalar_ty, .as_value), -0.0), | |
| 6191 | .Mul => try o.builder.fpValue(try o.lowerType(scalar_ty, .as_value), 1.0), | |
| 5972 | 6192 | else => unreachable, |
| 5973 | 6193 | }, operand }, ""), |
| 5974 | 6194 | else => unreachable, |
| ... | ... | @@ -5986,62 +6206,119 @@ fn airReduce(self: *FuncGen, inst: Air.Inst.Index, fast: Builder.FastMathKind) A |
| 5986 | 6206 | libcFloatPrefix(float_bits), libcFloatSuffix(float_bits), |
| 5987 | 6207 | }), |
| 5988 | 6208 | .Add => try o.builder.strtabStringFmt("__add{s}f3", .{ |
| 5989 | compilerRtFloatAbbrev(float_bits), | |
| 6209 | compilerRtFloatAbbrev(target, float_bits), | |
| 5990 | 6210 | }), |
| 5991 | 6211 | .Mul => try o.builder.strtabStringFmt("__mul{s}f3", .{ |
| 5992 | compilerRtFloatAbbrev(float_bits), | |
| 6212 | compilerRtFloatAbbrev(target, float_bits), | |
| 5993 | 6213 | }), |
| 5994 | 6214 | else => unreachable, |
| 5995 | 6215 | }; |
| 5996 | ||
| 5997 | const libc_fn = try o.getLibcFunction(fn_name, &.{ llvm_scalar_ty, llvm_scalar_ty }, llvm_scalar_ty); | |
| 5998 | const init_val = switch (llvm_scalar_ty) { | |
| 5999 | .i16 => try o.builder.intValue(.i16, @as(i16, @bitCast( | |
| 6000 | @as(f16, switch (reduce.operation) { | |
| 6001 | .Min, .Max => std.math.nan(f16), | |
| 6002 | .Add => -0.0, | |
| 6003 | .Mul => 1.0, | |
| 6004 | else => unreachable, | |
| 6005 | }), | |
| 6006 | ))), | |
| 6007 | .i80 => try o.builder.intValue(.i80, @as(i80, @bitCast( | |
| 6008 | @as(f80, switch (reduce.operation) { | |
| 6009 | .Min, .Max => std.math.nan(f80), | |
| 6010 | .Add => -0.0, | |
| 6011 | .Mul => 1.0, | |
| 6012 | else => unreachable, | |
| 6013 | }), | |
| 6014 | ))), | |
| 6015 | .i128 => try o.builder.intValue(.i128, @as(i128, @bitCast( | |
| 6016 | @as(f128, switch (reduce.operation) { | |
| 6017 | .Min, .Max => std.math.nan(f128), | |
| 6018 | .Add => -0.0, | |
| 6019 | .Mul => 1.0, | |
| 6020 | else => unreachable, | |
| 6021 | }), | |
| 6022 | ))), | |
| 6216 | const fn_info: Object.FuncInfo = .{ | |
| 6217 | .cc = target.cCallingConvention().?, | |
| 6218 | .param_types = &.{ scalar_ty.toIntern(), scalar_ty.toIntern() }, | |
| 6219 | .return_type = scalar_ty.toIntern(), | |
| 6220 | }; | |
| 6221 | const llvm_fn = try fg.object.getLibcFunction(fg.pt, fn_name, fn_info); | |
| 6222 | const init = switch (float_bits) { | |
| 6023 | 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 | } |
| 6027 | 6294 | |
| 6028 | fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { | |
| 6029 | const o = self.object; | |
| 6295 | fn airAggregateInit(fg: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Value { | |
| 6296 | const o = fg.object; | |
| 6030 | 6297 | const zcu = o.zcu; |
| 6031 | 6298 | const ip = &zcu.intern_pool; |
| 6032 | const ty_pl = self.air.instructions.items(.data)[@backingInt(inst)].ty_pl; | |
| 6033 | const result_ty = self.typeOfIndex(inst); | |
| 6299 | const ty_pl = fg.air.instructions.items(.data)[@backingInt(inst)].ty_pl; | |
| 6300 | const result_ty = fg.typeOfIndex(inst); | |
| 6034 | 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]); | |
| 6036 | 6303 | |
| 6037 | 6304 | switch (result_ty.zigTypeTag(zcu)) { |
| 6038 | .vector => { | |
| 6039 | const llvm_result_ty = try o.lowerType(result_ty, .by_value); | |
| 6305 | .vector => if (isByRef(result_ty, zcu)) { | |
| 6306 | const elem_ty = result_ty.childType(zcu); | |
| 6307 | const elem_size = elem_ty.abiSize(zcu); | |
| 6308 | const result_ptr = try fg.buildZigAlloca(result_ty, .none); | |
| 6309 | for (elements, 0..) |elem, elem_index| { | |
| 6310 | const elem_ptr = try fg.ptraddConst(result_ptr, elem_index * elem_size); | |
| 6311 | const llvm_elem = try fg.resolveInst(elem); | |
| 6312 | try fg.store(elem_ptr, .none, llvm_elem, elem_ty, .normal); | |
| 6313 | } | |
| 6314 | return result_ptr; | |
| 6315 | } else { | |
| 6316 | const llvm_result_ty = try o.lowerType(result_ty, .as_value); | |
| 6040 | 6317 | var vector = try o.builder.poisonValue(llvm_result_ty); |
| 6041 | for (elements, 0..) |elem, i| { | |
| 6042 | const index_u32 = try o.builder.intValue(.i32, i); | |
| 6043 | const llvm_elem = try self.resolveInst(elem); | |
| 6044 | vector = try self.wip.insertElement(vector, llvm_elem, index_u32, ""); | |
| 6318 | for (elements, 0..) |elem, elem_index| { | |
| 6319 | const elem_index_val = try o.builder.intValue(.i32, elem_index); | |
| 6320 | const llvm_elem = try fg.resolveInst(elem); | |
| 6321 | vector = try fg.wip.insertElement(vector, llvm_elem, elem_index_val, ""); | |
| 6045 | 6322 | } |
| 6046 | 6323 | return vector; |
| 6047 | 6324 | }, |
| ... | ... | @@ -6057,18 +6334,18 @@ fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builde |
| 6057 | 6334 | for (elements, struct_type.field_types.get(ip)) |elem, field_ty| { |
| 6058 | 6335 | if (!Type.fromInterned(field_ty).hasRuntimeBits(zcu)) continue; |
| 6059 | 6336 | |
| 6060 | const non_int_val = try self.resolveInst(elem); | |
| 6337 | const non_int_val = try fg.resolveInst(elem); | |
| 6061 | 6338 | const ty_bit_size: u16 = @intCast(Type.fromInterned(field_ty).bitSize(zcu)); |
| 6062 | 6339 | const small_int_ty = try o.builder.intType(ty_bit_size); |
| 6063 | 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 | 6342 | 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 | 6344 | const shift_rhs = try o.builder.intValue(int_ty, running_bits); |
| 6068 | 6345 | const extended_int_val = |
| 6069 | try self.wip.conv(.unsigned, small_int_val, int_ty, ""); | |
| 6070 | const shifted = try self.wip.bin(.shl, extended_int_val, shift_rhs, ""); | |
| 6071 | running_int = try self.wip.bin(.@"or", running_int, shifted, ""); | |
| 6346 | try fg.wip.conv(.unsigned, small_int_val, int_ty, ""); | |
| 6347 | const shifted = try fg.wip.bin(.shl, extended_int_val, shift_rhs, ""); | |
| 6348 | running_int = try fg.wip.bin(.@"or", running_int, shifted, ""); | |
| 6072 | 6349 | running_bits += ty_bit_size; |
| 6073 | 6350 | } |
| 6074 | 6351 | return running_int; |
| ... | ... | @@ -6078,19 +6355,19 @@ fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builde |
| 6078 | 6355 | // TODO in debug builds init to undef so that the padding will be 0xaa |
| 6079 | 6356 | // even if we fully populate the fields. |
| 6080 | 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); | |
| 6082 | 6359 | |
| 6083 | 6360 | for (elements, 0..) |elem, field_index| { |
| 6084 | 6361 | if (result_ty.structFieldIsComptime(field_index, zcu)) continue; |
| 6085 | 6362 | const field_ty = result_ty.fieldType(field_index, zcu); |
| 6086 | 6363 | if (!field_ty.hasRuntimeBits(zcu)) continue; |
| 6087 | 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 | 6366 | const field_ptr_align = struct_align.offset(offset); |
| 6090 | 6367 | |
| 6091 | const llvm_field_val = try self.resolveInst(elem); | |
| 6368 | const llvm_field_val = try fg.resolveInst(elem); | |
| 6092 | 6369 | |
| 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 | } |
| 6095 | 6372 | |
| 6096 | 6373 | return alloca_inst; |
| ... | ... | @@ -6099,21 +6376,21 @@ fn airAggregateInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builde |
| 6099 | 6376 | .array => { |
| 6100 | 6377 | assert(isByRef(result_ty, zcu)); |
| 6101 | 6378 | |
| 6102 | const alloca_inst = try self.buildZigAlloca(result_ty, .none); | |
| 6379 | const alloca_inst = try fg.buildZigAlloca(result_ty, .none); | |
| 6103 | 6380 | |
| 6104 | 6381 | const array_info = result_ty.arrayInfo(zcu); |
| 6105 | 6382 | |
| 6106 | 6383 | const elem_size = array_info.elem_type.abiSize(zcu); |
| 6107 | 6384 | |
| 6108 | 6385 | for (elements, 0..) |elem, i| { |
| 6109 | const elem_ptr = try self.ptraddConst(alloca_inst, elem_size * i); | |
| 6110 | const llvm_elem = try self.resolveInst(elem); | |
| 6111 | try self.store(elem_ptr, .none, llvm_elem, array_info.elem_type, .normal); | |
| 6386 | const elem_ptr = try fg.ptraddConst(alloca_inst, elem_size * i); | |
| 6387 | const llvm_elem = try fg.resolveInst(elem); | |
| 6388 | try fg.store(elem_ptr, .none, llvm_elem, array_info.elem_type, .normal); | |
| 6112 | 6389 | } |
| 6113 | 6390 | if (array_info.sentinel) |sent_val| { |
| 6114 | const elem_ptr = try self.ptraddConst(alloca_inst, elem_size * array_info.len); | |
| 6115 | const llvm_elem = try self.resolveValue(sent_val); | |
| 6116 | try self.store(elem_ptr, .none, llvm_elem.toValue(), array_info.elem_type, .normal); | |
| 6391 | const elem_ptr = try fg.ptraddConst(alloca_inst, elem_size * array_info.len); | |
| 6392 | const llvm_elem = try fg.resolveValue(sent_val); | |
| 6393 | try fg.store(elem_ptr, .none, llvm_elem.toValue(), array_info.elem_type, .normal); | |
| 6117 | 6394 | } |
| 6118 | 6395 | |
| 6119 | 6396 | return alloca_inst; |
| ... | ... | @@ -6153,10 +6430,10 @@ fn airUnionInit(self: *FuncGen, inst: Air.Inst.Index) Allocator.Error!Builder.Va |
| 6153 | 6430 | const loaded_enum = ip.loadEnumType(tag_ty.toIntern()); |
| 6154 | 6431 | const llvm_tag_val = switch (loaded_enum.field_values.getOrNone(ip, extra.field_index)) { |
| 6155 | 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 | 6434 | 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 | 6438 | const tag_ptr = try self.ptraddConst(result_ptr, layout.tagOffset()); |
| 6162 | 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 | 6495 | const ty_op = self.air.instructions.items(.data)[@backingInt(inst)].ty_op; |
| 6219 | 6496 | const inst_ty = self.typeOfIndex(inst); |
| 6220 | 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 | } |
| 6223 | 6500 | |
| 6224 | 6501 | fn workIntrinsic( |
| ... | ... | @@ -6370,7 +6647,7 @@ fn load( |
| 6370 | 6647 | }; |
| 6371 | 6648 | |
| 6372 | 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 | 6651 | const result_ptr = try fg.buildZigAlloca(load_ty, .none); |
| 6375 | 6652 | _ = try fg.wip.callMemCpy( |
| 6376 | 6653 | result_ptr, |
| ... | ... | @@ -6384,11 +6661,14 @@ fn load( |
| 6384 | 6661 | return result_ptr; |
| 6385 | 6662 | } |
| 6386 | 6663 | |
| 6387 | const llvm_memory_ty = try o.lowerType(load_ty, .in_memory); | |
| 6388 | const llvm_value_ty = try o.lowerType(load_ty, .by_value); | |
| 6664 | const llvm_access_ty = try o.lowerType(load_ty, .memory_access); | |
| 6665 | const llvm_value_ty = try o.lowerType(load_ty, .as_value); | |
| 6389 | 6666 | |
| 6390 | if (llvm_memory_ty != llvm_value_ty) { | |
| 6391 | assert(load_ty.isAbiInt(zcu)); | |
| 6667 | if (llvm_access_ty != llvm_value_ty) { | |
| 6668 | const signedness: std.lang.Signedness = switch (load_ty.toIntern()) { | |
| 6669 | .bool_type => .unsigned, | |
| 6670 | else => load_ty.intInfo(zcu).signedness, | |
| 6671 | }; | |
| 6392 | 6672 | // `load_ty` is an integer type with padding bits. In theory, we shouldn't need any special |
| 6393 | 6673 | // handling for these, as LLVM's documented semantics are a valid implementation of Zig's |
| 6394 | 6674 | // semantics. However: |
| ... | ... | @@ -6401,13 +6681,13 @@ fn load( |
| 6401 | 6681 | // |
| 6402 | 6682 | // Therefore, we handle these memory accesses specially: in this case we will actually load |
| 6403 | 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 | 6685 | // For packed structs, current Zig semantics don't really allow us to make the padding bits |
| 6406 | 6686 | // well-defined. This should be solved once https://github.com/ziglang/zig/issues/24061 is |
| 6407 | 6687 | // implemented, but until then, do a normal trunc for packed types. |
| 6408 | 6688 | return fg.wip.cast(switch (load_ty.zigTypeTag(zcu)) { |
| 6409 | 6689 | .@"struct", .@"union" => .trunc, |
| 6410 | else => switch (load_ty.intInfo(zcu).signedness) { | |
| 6690 | else => switch (signedness) { | |
| 6411 | 6691 | .unsigned => .@"trunc nuw", |
| 6412 | 6692 | .signed => .@"trunc nsw", |
| 6413 | 6693 | }, |
| ... | ... | @@ -6443,7 +6723,7 @@ fn store( |
| 6443 | 6723 | }; |
| 6444 | 6724 | |
| 6445 | 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 | 6727 | _ = try fg.wip.callMemCpy( |
| 6448 | 6728 | ptr, |
| 6449 | 6729 | llvm_ptr_align, |
| ... | ... | @@ -6456,45 +6736,34 @@ fn store( |
| 6456 | 6736 | return; |
| 6457 | 6737 | } |
| 6458 | 6738 | |
| 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)); | |
| 6460 | 6740 | |
| 6461 | const llvm_memory_ty = try o.lowerType(elem_ty, .in_memory); | |
| 6462 | const llvm_value_ty = try o.lowerType(elem_ty, .by_value); | |
| 6741 | const llvm_access_ty = try o.lowerType(elem_ty, .memory_access); | |
| 6742 | const llvm_value_ty = try o.lowerType(elem_ty, .as_value); | |
| 6463 | 6743 | |
| 6464 | if (llvm_memory_ty != llvm_value_ty) { | |
| 6465 | assert(elem_ty.isAbiInt(zcu)); | |
| 6744 | if (llvm_access_ty != llvm_value_ty) { | |
| 6745 | const signedness: std.lang.Signedness = switch (elem_ty.toIntern()) { | |
| 6746 | .bool_type => .unsigned, | |
| 6747 | else => elem_ty.intInfo(zcu).signedness, | |
| 6748 | }; | |
| 6466 | 6749 | // `elem_ty` is an integer type with padding bits, so we need to handle it specially---see |
| 6467 | 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 | 6752 | .unsigned => .zext, |
| 6470 | 6753 | .signed => .sext, |
| 6471 | }, elem, llvm_memory_ty, ""); | |
| 6472 | _ = try fg.wip.storeAtomic( | |
| 6473 | access_kind, | |
| 6474 | extended, | |
| 6475 | ptr, | |
| 6476 | fg.sync_scope, | |
| 6477 | .none, | |
| 6478 | llvm_ptr_align, | |
| 6479 | ); | |
| 6754 | }, elem, llvm_access_ty, ""); | |
| 6755 | _ = try fg.wip.store(access_kind, extended, ptr, llvm_ptr_align); | |
| 6480 | 6756 | return; |
| 6481 | 6757 | } |
| 6482 | 6758 | |
| 6483 | 6759 | // `elem_ty` is a simple by-val type which requires no special handling. |
| 6484 | _ = try fg.wip.storeAtomic( | |
| 6485 | access_kind, | |
| 6486 | elem, | |
| 6487 | ptr, | |
| 6488 | fg.sync_scope, | |
| 6489 | .none, | |
| 6490 | llvm_ptr_align, | |
| 6491 | ); | |
| 6760 | _ = try fg.wip.store(access_kind, elem, ptr, llvm_ptr_align); | |
| 6492 | 6761 | } |
| 6493 | 6762 | |
| 6494 | 6763 | fn valgrindMarkUndef(fg: *FuncGen, ptr: Builder.Value, len: Builder.Value) Allocator.Error!void { |
| 6495 | 6764 | const VG_USERREQ__MAKE_MEM_UNDEFINED = 1296236545; |
| 6496 | 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 | 6767 | const zero = try o.builder.intValue(usize_ty, 0); |
| 6499 | 6768 | const req = try o.builder.intValue(usize_ty, VG_USERREQ__MAKE_MEM_UNDEFINED); |
| 6500 | 6769 | const ptr_as_usize = try fg.wip.cast(.ptrtoint, ptr, usize_ty, ""); |
| ... | ... | @@ -6516,7 +6785,7 @@ fn valgrindClientRequest( |
| 6516 | 6785 | const target = zcu.getTarget(); |
| 6517 | 6786 | if (!target_util.hasValgrindSupport(target, .stage2_llvm)) return default_value; |
| 6518 | 6787 | |
| 6519 | const llvm_usize = try o.lowerType(.usize, .by_value); | |
| 6788 | const llvm_usize = try o.lowerType(.usize, .as_value); | |
| 6520 | 6789 | const usize_align = Type.usize.abiAlignment(zcu).toLlvm(); |
| 6521 | 6790 | |
| 6522 | 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 | 6919 | |
| 6651 | 6920 | const ParamTypeIterator = struct { |
| 6652 | 6921 | object: *Object, |
| 6653 | fn_info: InternPool.Key.FuncType, | |
| 6922 | cc: std.lang.CallingConvention, | |
| 6923 | param_types: []const InternPool.Index, | |
| 6654 | 6924 | zig_index: u32, |
| 6655 | 6925 | llvm_index: u32, |
| 6656 | 6926 | types_len: u32, |
| 6657 | 6927 | types_buffer: [8]Builder.Type, |
| 6658 | 6928 | offsets_buffer: [9]u64, |
| 6659 | byval_attr: bool, | |
| 6929 | byval_attr: ?Object.Byval, | |
| 6660 | 6930 | |
| 6661 | 6931 | const Lowering = union(enum) { |
| 6662 | 6932 | no_bits, |
| ... | ... | @@ -6672,88 +6942,78 @@ const ParamTypeIterator = struct { |
| 6672 | 6942 | }; |
| 6673 | 6943 | |
| 6674 | 6944 | pub fn next(it: *ParamTypeIterator) Allocator.Error!?Lowering { |
| 6675 | if (it.zig_index >= it.fn_info.param_types.len) return null; | |
| 6676 | const ip = &it.object.zcu.intern_pool; | |
| 6677 | const ty = it.fn_info.param_types.get(ip)[it.zig_index]; | |
| 6678 | it.byval_attr = false; | |
| 6945 | if (it.zig_index >= it.param_types.len) return null; | |
| 6946 | const ty = it.param_types[it.zig_index]; | |
| 6947 | it.byval_attr = null; | |
| 6679 | 6948 | return nextInner(it, Type.fromInterned(ty)); |
| 6680 | 6949 | } |
| 6681 | 6950 | |
| 6682 | 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 { | |
| 6684 | const ip = &it.object.zcu.intern_pool; | |
| 6685 | if (it.zig_index >= it.fn_info.param_types.len) { | |
| 6686 | if (it.zig_index >= args.len) { | |
| 6952 | fn nextCall(it: *ParamTypeIterator, arg_types: []const InternPool.Index) Allocator.Error!?Lowering { | |
| 6953 | if (it.zig_index >= it.param_types.len) { | |
| 6954 | if (it.zig_index >= arg_types.len) { | |
| 6687 | 6955 | return null; |
| 6688 | 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 | 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 | } |
| 6695 | 6963 | |
| 6696 | 6964 | fn nextInner(it: *ParamTypeIterator, ty: Type) Allocator.Error!?Lowering { |
| 6697 | 6965 | const zcu = it.object.zcu; |
| 6698 | const target = zcu.getTarget(); | |
| 6699 | ||
| 6966 | ty.assertHasLayout(zcu); | |
| 6700 | 6967 | if (!ty.hasRuntimeBits(zcu)) { |
| 6701 | 6968 | it.zig_index += 1; |
| 6702 | 6969 | return .no_bits; |
| 6703 | 6970 | } |
| 6704 | switch (it.fn_info.cc) { | |
| 6971 | switch (it.cc) { | |
| 6705 | 6972 | .@"inline" => unreachable, |
| 6706 | 6973 | .auto => { |
| 6707 | 6974 | it.zig_index += 1; |
| 6708 | 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 | 6991 | if (ty.isSlice(zcu) or |
| 6710 | 6992 | (ty.zigTypeTag(zcu) == .optional and ty.optionalChild(zcu).isSlice(zcu) and !ty.ptrAllowsZero(zcu))) |
| 6711 | 6993 | { |
| 6712 | 6994 | it.llvm_index += 1; |
| 6713 | 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 | 7000 | .async => { |
| 6728 | 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 | 7003 | .aarch64_aapcs, .aarch64_aapcs_darwin, .aarch64_aapcs_win => { |
| 6744 | 7004 | it.zig_index += 1; |
| 6745 | 7005 | it.llvm_index += 1; |
| 6746 | 7006 | switch (aarch64_c_abi.classifyType(ty, zcu)) { |
| 6747 | 7007 | .memory => return .byref_mut, |
| 6748 | .float_array => |len| return Lowering{ .float_array = len }, | |
| 7008 | .float_array => |len| return .{ .float_array = len }, | |
| 6749 | 7009 | .byval => return .byval, |
| 6750 | 7010 | .integer => { |
| 6751 | it.types_len = 1; | |
| 6752 | 7011 | it.types_buffer[0..1].* = .{.i64}; |
| 6753 | 7012 | it.offsets_buffer[0..2].* = .{ 0, 8 }; |
| 7013 | it.types_len = 1; | |
| 6754 | 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 | 7019 | .arm_aapcs, .arm_aapcs_vfp => { |
| ... | ... | @@ -6761,26 +7021,101 @@ const ParamTypeIterator = struct { |
| 6761 | 7021 | it.llvm_index += 1; |
| 6762 | 7022 | switch (arm_c_abi.classifyType(ty, zcu, .arg)) { |
| 6763 | 7023 | .memory => { |
| 6764 | it.byval_attr = true; | |
| 7024 | it.byval_attr = .{}; | |
| 6765 | 7025 | return .byref; |
| 6766 | 7026 | }, |
| 6767 | 7027 | .byval => return .byval, |
| 6768 | .i32_array => |size| return Lowering{ .i32_array = size }, | |
| 6769 | .i64_array => |size| return Lowering{ .i64_array = size }, | |
| 7028 | .i32_array => |size| return .{ .i32_array = size }, | |
| 7029 | .i64_array => |size| return .{ .i64_array = size }, | |
| 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 | 7097 | .mips_o32 => { |
| 6773 | 7098 | it.zig_index += 1; |
| 6774 | 7099 | it.llvm_index += 1; |
| 6775 | 7100 | switch (mips_c_abi.classifyType(ty, zcu, .arg)) { |
| 6776 | 7101 | .memory => { |
| 6777 | it.byval_attr = true; | |
| 7102 | it.byval_attr = .{}; | |
| 6778 | 7103 | return .byref; |
| 6779 | 7104 | }, |
| 6780 | 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 | 7119 | .riscv64_lp64, .riscv32_ilp32 => { |
| 6785 | 7120 | it.zig_index += 1; |
| 6786 | 7121 | it.llvm_index += 1; |
| ... | ... | @@ -6788,7 +7123,7 @@ const ParamTypeIterator = struct { |
| 6788 | 7123 | .memory => return .byref_mut, |
| 6789 | 7124 | .byval => return .byval, |
| 6790 | 7125 | .integer => return .abi_sized_int, |
| 6791 | .double_integer => return Lowering{ .i64_array = 2 }, | |
| 7126 | .double_integer => return .{ .i64_array = 2 }, | |
| 6792 | 7127 | .fields => { |
| 6793 | 7128 | it.types_len = 0; |
| 6794 | 7129 | var field_it: InternPool.LoadedStructType.RuntimeOrderIterator = if (zcu.typeToStruct(ty)) |loaded_struct| |
| ... | ... | @@ -6798,7 +7133,7 @@ const ParamTypeIterator = struct { |
| 6798 | 7133 | while (field_it.next()) |field_index| { |
| 6799 | 7134 | const field_ty = ty.fieldType(field_index, zcu); |
| 6800 | 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 | 7137 | it.offsets_buffer[it.types_len] = ty.structFieldOffset(field_index, zcu); |
| 6803 | 7138 | it.types_len += 1; |
| 6804 | 7139 | } |
| ... | ... | @@ -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 | 7165 | .direct => |scalar_ty| { |
| 6813 | 7166 | if (isScalar(zcu, ty)) { |
| 6814 | 7167 | it.zig_index += 1; |
| 6815 | 7168 | it.llvm_index += 1; |
| 6816 | 7169 | return .byval; |
| 6817 | 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 | 7172 | it.offsets_buffer[0..2].* = .{ 0, scalar_ty.abiSize(zcu) }; |
| 6820 | 7173 | it.types_len = 1; |
| 6821 | it.llvm_index += 1; | |
| 6822 | 7174 | it.zig_index += 1; |
| 7175 | it.llvm_index += 1; | |
| 6823 | 7176 | return .multiple_llvm_types; |
| 6824 | 7177 | } |
| 6825 | 7178 | }, |
| 6826 | 7179 | .indirect => { |
| 6827 | 7180 | it.zig_index += 1; |
| 6828 | 7181 | it.llvm_index += 1; |
| 6829 | it.byval_attr = true; | |
| 7182 | it.byval_attr = .{}; | |
| 6830 | 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 | 7245 | // TODO investigate other callconvs |
| 6834 | 7246 | else => { |
| 6835 | 7247 | it.zig_index += 1; |
| ... | ... | @@ -6839,7 +7251,7 @@ const ParamTypeIterator = struct { |
| 6839 | 7251 | } |
| 6840 | 7252 | } |
| 6841 | 7253 | |
| 6842 | fn nextWin64(it: *ParamTypeIterator, ty: Type) ?Lowering { | |
| 7254 | fn next_x86_64_win(it: *ParamTypeIterator, ty: Type) Lowering { | |
| 6843 | 7255 | const zcu = it.object.zcu; |
| 6844 | 7256 | switch (x86_64_abi.classifyWindows(ty, zcu, zcu.getTarget(), .arg)) { |
| 6845 | 7257 | .integer => { |
| ... | ... | @@ -6880,119 +7292,114 @@ const ParamTypeIterator = struct { |
| 6880 | 7292 | } |
| 6881 | 7293 | } |
| 6882 | 7294 | |
| 6883 | fn nextSystemV(it: *ParamTypeIterator, ty: Type) Allocator.Error!?Lowering { | |
| 6884 | const zcu = it.object.zcu; | |
| 6885 | const ip = &zcu.intern_pool; | |
| 6886 | ty.assertHasLayout(zcu); | |
| 6887 | const classes = x86_64_abi.classifySystemV(ty, zcu, zcu.getTarget(), .arg); | |
| 6888 | if (classes[0] == .memory) { | |
| 6889 | it.zig_index += 1; | |
| 6890 | it.llvm_index += 1; | |
| 6891 | it.byval_attr = true; | |
| 6892 | return .byref; | |
| 6893 | } | |
| 6894 | if (isScalar(zcu, ty)) { | |
| 6895 | it.zig_index += 1; | |
| 6896 | it.llvm_index += 1; | |
| 6897 | return .byval; | |
| 6898 | } | |
| 6899 | var types_index: u32 = 0; | |
| 6900 | var offset: u64 = 0; | |
| 6901 | for (classes) |class| { | |
| 6902 | switch (class) { | |
| 6903 | .integer => { | |
| 6904 | it.types_buffer[types_index] = .i64; | |
| 6905 | it.offsets_buffer[types_index] = offset; | |
| 6906 | types_index += 1; | |
| 6907 | }, | |
| 6908 | .sse => { | |
| 6909 | it.types_buffer[types_index] = .double; | |
| 6910 | it.offsets_buffer[types_index] = offset; | |
| 6911 | types_index += 1; | |
| 6912 | }, | |
| 6913 | .sseup => { | |
| 6914 | if (it.types_buffer[types_index - 1] == .double) { | |
| 6915 | it.types_buffer[types_index - 1] = .fp128; | |
| 6916 | } else { | |
| 6917 | it.types_buffer[types_index] = .double; | |
| 6918 | it.offsets_buffer[types_index] = offset; | |
| 6919 | types_index += 1; | |
| 7295 | fn next_x86_64_sysv(it: *ParamTypeIterator, ty: Type) Allocator.Error!Lowering { | |
| 7296 | const o = it.object; | |
| 7297 | const zcu = o.zcu; | |
| 7298 | const target = zcu.getTarget(); | |
| 7299 | const classes = x86_64_abi.classifySystemV(ty, zcu, target, .arg); | |
| 7300 | var types_len: u32 = 0; | |
| 7301 | const classes_len = for (classes, 0..) |class, class_index| switch (class) { | |
| 7302 | .integer => { | |
| 7303 | it.types_buffer[types_len] = try o.builder.intType(@min(8 * ty.abiSize(zcu) - 64 * class_index, 64)); | |
| 7304 | it.offsets_buffer[types_len] = 8 * class_index; | |
| 7305 | types_len += 1; | |
| 7306 | }, | |
| 7307 | .sse => { | |
| 7308 | it.types_buffer[types_len] = .double; | |
| 7309 | it.offsets_buffer[types_len] = 8 * class_index; | |
| 7310 | types_len += 1; | |
| 7311 | }, | |
| 7312 | .sseup => { | |
| 7313 | if (it.types_buffer[types_len - 1] == .double) { | |
| 7314 | if (ty.isVector(zcu)) { | |
| 7315 | it.zig_index += 1; | |
| 7316 | it.llvm_index += 1; | |
| 7317 | return .byval; | |
| 6920 | 7318 | } |
| 6921 | }, | |
| 6922 | .float => { | |
| 6923 | it.types_buffer[types_index] = .float; | |
| 6924 | it.offsets_buffer[types_index] = offset; | |
| 6925 | types_index += 1; | |
| 6926 | }, | |
| 6927 | .float_combine => { | |
| 6928 | it.types_buffer[types_index] = try it.object.builder.vectorType(.normal, 2, .float); | |
| 6929 | it.offsets_buffer[types_index] = offset; | |
| 6930 | types_index += 1; | |
| 6931 | }, | |
| 6932 | .x87 => { | |
| 6933 | it.zig_index += 1; | |
| 6934 | it.llvm_index += 1; | |
| 6935 | it.byval_attr = true; | |
| 6936 | return .byref; | |
| 6937 | }, | |
| 6938 | .x87up => unreachable, | |
| 6939 | .none => break, | |
| 6940 | .memory => unreachable, // handled above | |
| 6941 | .win_i128 => unreachable, // windows only | |
| 6942 | .bool_vector_mask, | |
| 6943 | .integer_per_element, | |
| 6944 | .sse_per_element, | |
| 6945 | .sse_sse_x87_per_qword, | |
| 6946 | .sse_per_xword, | |
| 6947 | .sse_per_yword, | |
| 6948 | .sse_per_zword, | |
| 6949 | => unreachable, // vectors already handled by `isScalar` above | |
| 6950 | } | |
| 6951 | offset += 8; | |
| 6952 | } | |
| 6953 | const first_non_integer = std.mem.indexOfNone(x86_64_abi.Class, &classes, &.{.integer}); | |
| 6954 | if (first_non_integer == null or classes[first_non_integer.?] == .none) { | |
| 6955 | assert(first_non_integer orelse classes.len == types_index); | |
| 6956 | if (types_index == 1) { | |
| 7319 | it.types_buffer[types_len - 1] = .fp128; | |
| 7320 | } else { | |
| 7321 | it.types_buffer[types_len] = .double; | |
| 7322 | it.offsets_buffer[types_len] = 8 * class_index; | |
| 7323 | types_len += 1; | |
| 7324 | } | |
| 7325 | }, | |
| 7326 | .float => { | |
| 7327 | it.types_buffer[types_len] = .float; | |
| 7328 | it.offsets_buffer[types_len] = 8 * class_index; | |
| 7329 | types_len += 1; | |
| 7330 | }, | |
| 7331 | .float_combine => { | |
| 7332 | it.types_buffer[types_len] = try it.object.builder.vectorType(.normal, 2, .float); | |
| 7333 | it.offsets_buffer[types_len] = 8 * class_index; | |
| 7334 | types_len += 1; | |
| 7335 | }, | |
| 7336 | .x87 => { | |
| 6957 | 7337 | it.zig_index += 1; |
| 6958 | 7338 | it.llvm_index += 1; |
| 6959 | return .abi_sized_int; | |
| 6960 | } | |
| 6961 | if (it.llvm_index + types_index > 6) { | |
| 7339 | it.byval_attr = .{}; | |
| 7340 | return .byref; | |
| 7341 | }, | |
| 7342 | .x87up => unreachable, | |
| 7343 | .none => break class_index, | |
| 7344 | .memory => { | |
| 7345 | it.zig_index += 1; | |
| 7346 | it.llvm_index += 1; | |
| 7347 | it.byval_attr = .{}; | |
| 7348 | return .byref; | |
| 7349 | }, | |
| 7350 | .win_i128 => unreachable, // windows only | |
| 7351 | .bool_vector_mask, | |
| 7352 | .integer_per_element, | |
| 7353 | .sse_per_element, | |
| 7354 | .sse_sse_x87_per_qword, | |
| 7355 | .sse_per_xword, | |
| 7356 | .sse_per_yword, | |
| 7357 | .sse_per_zword, | |
| 7358 | => { | |
| 7359 | it.zig_index += 1; | |
| 7360 | it.llvm_index += 1; | |
| 7361 | return .byval; | |
| 7362 | }, | |
| 7363 | } else classes.len; | |
| 7364 | if (types_len > 1) { | |
| 7365 | if (it.llvm_index + classes_len > 6) { | |
| 6962 | 7366 | it.zig_index += 1; |
| 6963 | 7367 | it.llvm_index += 1; |
| 6964 | it.byval_attr = true; | |
| 7368 | it.byval_attr = .{}; | |
| 6965 | 7369 | return .byref; |
| 6966 | 7370 | } |
| 6967 | switch (ip.indexToKey(ty.toIntern())) { | |
| 6968 | .struct_type => { | |
| 6969 | const size = ty.abiSize(zcu); | |
| 6970 | assert(@divCeil(size, 8) == types_index); | |
| 6971 | if (size % 8 > 0) { | |
| 6972 | it.types_buffer[types_index - 1] = | |
| 6973 | try it.object.builder.intType(@intCast(size % 8 * 8)); | |
| 6974 | } | |
| 6975 | }, | |
| 6976 | else => {}, | |
| 7371 | } else if (!isByRef(ty, zcu)) { | |
| 7372 | const llvm_ty = try o.lowerType(ty, .as_value); | |
| 7373 | if (it.types_buffer[0] == llvm_ty or | |
| 7374 | (it.types_buffer[0] == .i64 and llvm_ty.isPointer(&o.builder))) | |
| 7375 | { | |
| 7376 | it.zig_index += 1; | |
| 7377 | it.llvm_index += 1; | |
| 7378 | return .byval; | |
| 6977 | 7379 | } |
| 6978 | 7380 | } |
| 6979 | it.offsets_buffer[types_index] = offset; | |
| 6980 | it.types_len = types_index; | |
| 6981 | it.llvm_index += types_index; | |
| 7381 | it.offsets_buffer[types_len] = 8 * classes_len; | |
| 7382 | it.types_len = types_len; | |
| 7383 | it.llvm_index += types_len; | |
| 6982 | 7384 | it.zig_index += 1; |
| 6983 | 7385 | return .multiple_llvm_types; |
| 6984 | 7386 | } |
| 6985 | 7387 | }; |
| 6986 | pub fn iterateParamTypes(object: *Object, fn_info: InternPool.Key.FuncType) ParamTypeIterator { | |
| 7388 | pub fn iterateParamTypes( | |
| 7389 | object: *Object, | |
| 7390 | cc: std.lang.CallingConvention, | |
| 7391 | param_types: []const InternPool.Index, | |
| 7392 | ) ParamTypeIterator { | |
| 6987 | 7393 | return .{ |
| 6988 | 7394 | .object = object, |
| 6989 | .fn_info = fn_info, | |
| 7395 | .cc = cc, | |
| 7396 | .param_types = param_types, | |
| 6990 | 7397 | .zig_index = 0, |
| 6991 | 7398 | .llvm_index = 0, |
| 6992 | 7399 | .types_len = undefined, |
| 6993 | 7400 | .types_buffer = undefined, |
| 6994 | 7401 | .offsets_buffer = undefined, |
| 6995 | .byval_attr = false, | |
| 7402 | .byval_attr = null, | |
| 6996 | 7403 | }; |
| 6997 | 7404 | } |
| 6998 | 7405 | |
| ... | ... | @@ -7017,54 +7424,68 @@ pub const FnReturnStrat = union(enum) { |
| 7017 | 7424 | /// In order to support the C calling convention, some return types need to be lowered |
| 7018 | 7425 | /// completely differently in the function prototype to honor the C ABI, and then |
| 7019 | 7426 | /// be effectively bitcasted to the actual return type. |
| 7020 | pub fn fnReturnStrat(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Error!FnReturnStrat { | |
| 7427 | pub fn fnReturnStrat(o: *Object, cc: std.lang.CallingConvention, ret_ty: Type) Allocator.Error!FnReturnStrat { | |
| 7021 | 7428 | const zcu = o.zcu; |
| 7022 | const ret_ty: Type = .fromInterned(fn_info.return_type); | |
| 7023 | 7429 | ret_ty.assertHasLayout(zcu); |
| 7024 | 7430 | if (!ret_ty.hasRuntimeBits(zcu)) return .void; |
| 7025 | switch (fn_info.cc) { | |
| 7431 | return switch (cc) { | |
| 7026 | 7432 | .@"inline" => unreachable, |
| 7027 | 7433 | .auto => { |
| 7028 | if (isByRef(ret_ty, zcu)) return .sret; | |
| 7029 | ||
| 7434 | // Match the c calling convention in some cases to avoid llvm bugs. | |
| 7030 | 7435 | const target = zcu.getTarget(); |
| 7031 | if (target.cpu.arch.isX86() and | |
| 7032 | !target.cpu.has(.x86, .avx512f) and | |
| 7033 | ret_ty.totalVectorBits(zcu) >= 512) | |
| 7034 | { | |
| 7035 | // As of LLVM 18, passing a vector byval with fastcc that is 512 bits or more returns | |
| 7036 | // "512-bit vector arguments require 'avx512f' for AVX512" | |
| 7037 | return .sret; | |
| 7038 | } | |
| 7039 | ||
| 7040 | return .by_val; | |
| 7436 | if (target.cpu.arch == .x86_64 and ret_ty.isVector(zcu) and ret_ty.childType(zcu).toIntern() == .bool_type) return switch (ret_ty.vectorLen(zcu)) { | |
| 7437 | 0 => .void, | |
| 7438 | 1...8 => .{ .mem_cast = .i8 }, | |
| 7439 | 9...16 => .{ .mem_cast = .i16 }, | |
| 7440 | 17...32 => .{ .mem_cast = .i32 }, | |
| 7441 | 33...64 => .{ .mem_cast = .double }, | |
| 7442 | else => .by_val, | |
| 7443 | }; | |
| 7444 | return if (isByRef(ret_ty, zcu)) .sret else .by_val; | |
| 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 | 7446 | .aarch64_aapcs, .aarch64_aapcs_darwin, .aarch64_aapcs_win => switch (aarch64_c_abi.classifyType(ret_ty, zcu)) { |
| 7051 | .memory => return .sret, | |
| 7052 | .float_array, .byval => return .forceByVal(o, ret_ty), | |
| 7053 | .integer => return .{ .mem_cast = .i64 }, | |
| 7054 | .double_integer => return .{ .mem_cast = try o.builder.arrayType(2, .i64) }, | |
| 7447 | .memory => .sret, | |
| 7448 | .float_array, .byval => .forceByVal(o, ret_ty), | |
| 7449 | .integer => .{ .mem_cast = .i64 }, | |
| 7450 | .double_integer => .{ .mem_cast = try o.builder.arrayType(2, .i64) }, | |
| 7055 | 7451 | }, |
| 7056 | 7452 | .arm_aapcs, .arm_aapcs_vfp => switch (arm_c_abi.classifyType(ret_ty, zcu, .ret)) { |
| 7057 | .memory, .i64_array => return .sret, | |
| 7058 | .i32_array => |len| return if (len == 1) .{ .mem_cast = .i32 } else .sret, | |
| 7059 | .byval => return .forceByVal(o, ret_ty), | |
| 7453 | .memory, .i64_array => .sret, | |
| 7454 | .i32_array => |len| if (len == 1) .{ .mem_cast = .i32 } else .sret, | |
| 7455 | .byval => .forceByVal(o, ret_ty), | |
| 7456 | }, | |
| 7457 | .loongarch32_ilp32, .loongarch64_lp64 => switch (loongarch_c_abi.classifyType(ret_ty, zcu)) { | |
| 7458 | .ignored => .void, | |
| 7459 | .gar, .far => .by_val, | |
| 7460 | .member => |member_ty| .{ .mem_cast = try o.lowerType(member_ty, .as_value) }, | |
| 7461 | .member_pair => |member_tys| .{ .mem_cast = try o.builder.structType(.normal, &.{ | |
| 7462 | try o.lowerType(member_tys[0], .as_value), | |
| 7463 | try o.lowerType(member_tys[1], .as_value), | |
| 7464 | }) }, | |
| 7465 | .memory_gar => .{ .mem_cast = switch (cc) { | |
| 7466 | else => unreachable, | |
| 7467 | .loongarch32_ilp32 => .i32, | |
| 7468 | .loongarch64_lp64 => .i64, | |
| 7469 | } }, | |
| 7470 | .memory_gar_pair => .{ .mem_cast = try o.builder.arrayType(2, switch (cc) { | |
| 7471 | else => unreachable, | |
| 7472 | .loongarch32_ilp32 => .i32, | |
| 7473 | .loongarch64_lp64 => .i64, | |
| 7474 | }) }, | |
| 7475 | .address => .sret, | |
| 7060 | 7476 | }, |
| 7061 | 7477 | .mips_o32 => switch (mips_c_abi.classifyType(ret_ty, zcu, .ret)) { |
| 7062 | .memory, .i32_array => return .sret, | |
| 7063 | .byval => return .forceByVal(o, ret_ty), | |
| 7478 | .memory, .i32_array => .sret, | |
| 7479 | .byval => .forceByVal(o, ret_ty), | |
| 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 | 7486 | .riscv64_lp64, .riscv32_ilp32 => switch (riscv_c_abi.classifyType(ret_ty, zcu)) { |
| 7066 | .memory => return .sret, | |
| 7067 | .integer => return .{ .mem_cast = try o.builder.intType(@intCast(ret_ty.abiSize(zcu) * 8)) }, | |
| 7487 | .memory => .sret, | |
| 7488 | .integer => .{ .mem_cast = try o.builder.intType(@intCast(ret_ty.abiSize(zcu) * 8)) }, | |
| 7068 | 7489 | .double_integer => { |
| 7069 | 7490 | const integer: Builder.Type = switch (zcu.getTarget().cpu.arch) { |
| 7070 | 7491 | .riscv64, .riscv64be => .i64, |
| ... | ... | @@ -7073,34 +7494,78 @@ pub fn fnReturnStrat(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Err |
| 7073 | 7494 | }; |
| 7074 | 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 | 7498 | .fields => { |
| 7078 | 7499 | var types_len: usize = 0; |
| 7079 | 7500 | var types: [8]Builder.Type = undefined; |
| 7080 | 7501 | for (0..ret_ty.structFieldCount(zcu)) |field_index| { |
| 7081 | 7502 | const field_ty = ret_ty.fieldType(field_index, zcu); |
| 7082 | 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 | 7505 | types_len += 1; |
| 7085 | 7506 | } |
| 7086 | 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 | 7517 | .direct => |scalar_ty| if (scalar_ty.toIntern() == ret_ty.toIntern()) { |
| 7091 | 7518 | assert(!isByRef(ret_ty, zcu)); |
| 7092 | 7519 | return .by_val; |
| 7093 | } else { | |
| 7094 | return .{ .mem_cast = try o.lowerType(scalar_ty, .by_value) }; | |
| 7095 | }, | |
| 7096 | .indirect => return .sret, | |
| 7520 | } else .{ .mem_cast = try o.lowerType(scalar_ty, .as_value) }, | |
| 7521 | .indirect => .sret, | |
| 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 | 7563 | // TODO investigate other callconvs |
| 7099 | else => return .forceByVal(o, ret_ty), | |
| 7100 | } | |
| 7564 | else => .forceByVal(o, ret_ty), | |
| 7565 | }; | |
| 7101 | 7566 | } |
| 7102 | 7567 | |
| 7103 | fn lowerX86FastcallFnRetTy(o: *Object, zcu: *Zcu, ty: Type) Allocator.Error!FnReturnStrat { | |
| 7568 | fn fnReturnStrat_x86_fastcall(o: *Object, zcu: *Zcu, ty: Type) Allocator.Error!FnReturnStrat { | |
| 7104 | 7569 | if (isScalar(zcu, ty)) { |
| 7105 | 7570 | assert(!isByRef(ty, zcu)); |
| 7106 | 7571 | return .by_val; |
| ... | ... | @@ -7115,9 +7580,8 @@ fn lowerX86FastcallFnRetTy(o: *Object, zcu: *Zcu, ty: Type) Allocator.Error!FnRe |
| 7115 | 7580 | return .sret; |
| 7116 | 7581 | } |
| 7117 | 7582 | |
| 7118 | fn lowerWin64FnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Error!FnReturnStrat { | |
| 7583 | fn fnReturnStrat_x86_64_win(o: *Object, ret_ty: Type) Allocator.Error!FnReturnStrat { | |
| 7119 | 7584 | const zcu = o.zcu; |
| 7120 | const ret_ty = Type.fromInterned(fn_info.return_type); | |
| 7121 | 7585 | switch (x86_64_abi.classifyWindows(ret_ty, zcu, zcu.getTarget(), .ret)) { |
| 7122 | 7586 | .integer => if (isScalar(zcu, ret_ty)) { |
| 7123 | 7587 | assert(!isByRef(ret_ty, zcu)); |
| ... | ... | @@ -7150,78 +7614,65 @@ fn lowerWin64FnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Err |
| 7150 | 7614 | } |
| 7151 | 7615 | } |
| 7152 | 7616 | |
| 7153 | fn lowerSystemVFnRetTy(o: *Object, fn_info: InternPool.Key.FuncType) Allocator.Error!FnReturnStrat { | |
| 7617 | fn fnReturnStrat_x86_64_sysv(o: *Object, ret_ty: Type) Allocator.Error!FnReturnStrat { | |
| 7154 | 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 | 7619 | const classes = x86_64_abi.classifySystemV(ret_ty, zcu, zcu.getTarget(), .ret); |
| 7162 | var types_index: u32 = 0; | |
| 7163 | 7620 | var types_buffer: [8]Builder.Type = undefined; |
| 7164 | for (classes) |class| { | |
| 7165 | switch (class) { | |
| 7166 | .integer => { | |
| 7167 | types_buffer[types_index] = .i64; | |
| 7168 | types_index += 1; | |
| 7169 | }, | |
| 7170 | .sse => { | |
| 7171 | types_buffer[types_index] = .double; | |
| 7172 | types_index += 1; | |
| 7173 | }, | |
| 7174 | .sseup => { | |
| 7175 | if (types_buffer[types_index - 1] == .double) { | |
| 7176 | types_buffer[types_index - 1] = .fp128; | |
| 7177 | } else { | |
| 7178 | types_buffer[types_index] = .double; | |
| 7179 | types_index += 1; | |
| 7180 | } | |
| 7181 | }, | |
| 7182 | .float => { | |
| 7183 | types_buffer[types_index] = .float; | |
| 7184 | types_index += 1; | |
| 7185 | }, | |
| 7186 | .float_combine => { | |
| 7187 | types_buffer[types_index] = try o.builder.vectorType(.normal, 2, .float); | |
| 7188 | types_index += 1; | |
| 7189 | }, | |
| 7190 | .x87 => { | |
| 7191 | if (types_index != 0 or classes[2] != .none) return .sret; | |
| 7192 | types_buffer[types_index] = .x86_fp80; | |
| 7193 | types_index += 1; | |
| 7194 | }, | |
| 7195 | .x87up => continue, | |
| 7196 | .none => break, | |
| 7197 | .memory => return .sret, | |
| 7198 | .win_i128 => unreachable, // windows only | |
| 7199 | .bool_vector_mask, | |
| 7200 | .integer_per_element, | |
| 7201 | .sse_per_element, | |
| 7202 | .sse_sse_x87_per_qword, | |
| 7203 | .sse_per_xword, | |
| 7204 | .sse_per_yword, | |
| 7205 | .sse_per_zword, | |
| 7206 | => unreachable, // vectors already handled by `isScalar` above | |
| 7207 | } | |
| 7208 | } | |
| 7209 | const first_non_integer = std.mem.indexOfNone(x86_64_abi.Class, &classes, &.{.integer}); | |
| 7210 | if (first_non_integer == null or classes[first_non_integer.?] == .none) { | |
| 7211 | assert(first_non_integer orelse classes.len == types_index); | |
| 7212 | switch (ip.indexToKey(ret_ty.toIntern())) { | |
| 7213 | .struct_type => { | |
| 7214 | const size = ret_ty.abiSize(zcu); | |
| 7215 | assert(@divCeil(size, 8) == types_index); | |
| 7216 | if (size % 8 > 0) { | |
| 7217 | types_buffer[types_index - 1] = try o.builder.intType(@intCast(size % 8 * 8)); | |
| 7218 | } | |
| 7219 | }, | |
| 7220 | else => {}, | |
| 7221 | } | |
| 7222 | if (types_index == 1) return .{ .mem_cast = types_buffer[0] }; | |
| 7621 | var types_len: u32 = 0; | |
| 7622 | for (classes, 0..) |class, class_index| switch (class) { | |
| 7623 | .integer => { | |
| 7624 | types_buffer[types_len] = try o.builder.intType(@min(8 * ret_ty.abiSize(zcu) - 64 * class_index, 64)); | |
| 7625 | types_len += 1; | |
| 7626 | }, | |
| 7627 | .sse => { | |
| 7628 | types_buffer[types_len] = .double; | |
| 7629 | types_len += 1; | |
| 7630 | }, | |
| 7631 | .sseup => { | |
| 7632 | if (types_buffer[types_len - 1] == .double) { | |
| 7633 | if (ret_ty.isVector(zcu)) return .by_val; | |
| 7634 | types_buffer[types_len - 1] = .fp128; | |
| 7635 | } else { | |
| 7636 | types_buffer[types_len] = .double; | |
| 7637 | types_len += 1; | |
| 7638 | } | |
| 7639 | }, | |
| 7640 | .float => { | |
| 7641 | types_buffer[types_len] = .float; | |
| 7642 | types_len += 1; | |
| 7643 | }, | |
| 7644 | .float_combine => { | |
| 7645 | types_buffer[types_len] = try o.builder.vectorType(.normal, 2, .float); | |
| 7646 | types_len += 1; | |
| 7647 | }, | |
| 7648 | .x87 => { | |
| 7649 | if (types_len > 0 or classes[2] != .none) return .sret; | |
| 7650 | types_buffer[types_len] = .x86_fp80; | |
| 7651 | types_len += 1; | |
| 7652 | }, | |
| 7653 | .x87up => continue, | |
| 7654 | .none => break, | |
| 7655 | .memory => return if (ret_ty.isVector(zcu)) .by_val else .sret, | |
| 7656 | .win_i128 => unreachable, // windows only | |
| 7657 | .bool_vector_mask, | |
| 7658 | .integer_per_element, | |
| 7659 | .sse_per_element, | |
| 7660 | .sse_sse_x87_per_qword, | |
| 7661 | .sse_per_xword, | |
| 7662 | .sse_per_yword, | |
| 7663 | .sse_per_zword, | |
| 7664 | => return .by_val, | |
| 7665 | }; | |
| 7666 | if (types_len > 1) return .{ .mem_cast = try o.builder.structType(.normal, types_buffer[0..types_len]) }; | |
| 7667 | if (!isByRef(ret_ty, zcu)) { | |
| 7668 | const llvm_ty = try o.lowerType(ret_ty, .as_value); | |
| 7669 | if (types_buffer[0] == llvm_ty) return .by_val; | |
| 7670 | if (types_buffer[0] == .i64 and llvm_ty.isPointer(&o.builder)) return .by_val; | |
| 7671 | if (types_buffer[0] == .double and llvm_ty.isVector(&o.builder) and | |
| 7672 | llvm_ty.vectorLen(&o.builder) == 1 and | |
| 7673 | llvm_ty.scalarType(&o.builder) == .double) return .by_val; | |
| 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 | } |
| 7226 | 7677 | |
| 7227 | 7678 | /// 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 | 7685 | else => {}, |
| 7235 | 7686 | } |
| 7236 | 7687 | |
| 7237 | const ty_tag = ty.zigTypeTag(zcu); | |
| 7238 | const int_info = switch (ty_tag) { | |
| 7239 | .bool => Type.u1.intInfo(zcu), | |
| 7240 | else => if (ty.isAbiInt(zcu)) ty.intInfo(zcu) else return null, | |
| 7241 | }; | |
| 7688 | const target = zcu.getTarget(); | |
| 7689 | const int_info: std.lang.Type.Int = if (ty.toIntern() == .bool_type) | |
| 7690 | .{ .signedness = .unsigned, .bits = 1 } | |
| 7691 | else if (ty.isAbiInt(zcu)) | |
| 7692 | ty.intInfo(zcu) | |
| 7693 | else if (ty.isRuntimeFloat()) switch (ty.floatBits(target)) { | |
| 7694 | else => unreachable, | |
| 7695 | 16, 32, 64 => |bits| switch (std.zig.target.compilerRtFloatAbi(target, bits)) { | |
| 7696 | .hard => return null, | |
| 7697 | .soft => .{ .signedness = .unsigned, .bits = bits }, | |
| 7698 | }, | |
| 7699 | 80, 128 => return null, | |
| 7700 | } else return null; | |
| 7242 | 7701 | |
| 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)); | |
| 7244 | 7703 | |
| 7245 | const target = zcu.getTarget(); | |
| 7246 | 7704 | return switch (target.cpu.arch) { |
| 7247 | 7705 | .aarch64, |
| 7248 | 7706 | .aarch64_be, |
| ... | ... | @@ -7338,15 +7796,26 @@ pub fn isByRef(ty: Type, zcu: *const Zcu) bool { |
| 7338 | 7796 | .void, |
| 7339 | 7797 | .bool, |
| 7340 | 7798 | .int, |
| 7341 | .float, | |
| 7342 | 7799 | .pointer, |
| 7343 | 7800 | .error_set, |
| 7344 | 7801 | .@"fn", |
| 7345 | 7802 | .@"enum", |
| 7346 | .vector, | |
| 7347 | 7803 | .@"anyframe", |
| 7348 | 7804 | => false, |
| 7349 | 7805 | |
| 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 | 7819 | .array, |
| 7351 | 7820 | .frame, |
| 7352 | 7821 | => ty.hasRuntimeBits(zcu), |
| ... | ... | @@ -7392,7 +7861,7 @@ fn getAtomicAbiType(fg: *const FuncGen, ty: Type, is_rmw_xchg: bool) Allocator.E |
| 7392 | 7861 | fn ptraddConst(fg: *FuncGen, ptr: Builder.Value, offset: u64) Allocator.Error!Builder.Value { |
| 7393 | 7862 | if (offset == 0) return ptr; |
| 7394 | 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 | 7865 | const offset_val = try o.builder.intValue(llvm_usize_ty, offset); |
| 7397 | 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 | 7876 | return fg.wip.gep(.inbounds, llvm_scale_ty, ptr, &.{index}, ""); |
| 7408 | 7877 | } |
| 7409 | 7878 | |
| 7410 | fn compilerRtIntBits(bits: u16) ?u16 { | |
| 7411 | inline for (.{ 32, 64, 128 }) |b| { | |
| 7412 | if (bits <= b) { | |
| 7413 | return b; | |
| 7414 | } | |
| 7415 | } | |
| 7879 | fn compilerRtPromoteInt(int_info: InternPool.Key.IntType) ?Type { | |
| 7880 | if (int_info.bits <= 32) return switch (int_info.signedness) { | |
| 7881 | .signed => .i32, | |
| 7882 | .unsigned => .u32, | |
| 7883 | }; | |
| 7884 | if (int_info.bits <= 64) return switch (int_info.signedness) { | |
| 7885 | .signed => .i64, | |
| 7886 | .unsigned => .u64, | |
| 7887 | }; | |
| 7888 | if (int_info.bits <= 128) return switch (int_info.signedness) { | |
| 7889 | .signed => .i128, | |
| 7890 | .unsigned => .u128, | |
| 7891 | }; | |
| 7416 | 7892 | return null; |
| 7417 | 7893 | } |
| 7418 | 7894 | |
| ... | ... | @@ -7471,13 +7947,21 @@ fn appendConstraints( |
| 7471 | 7947 | } |
| 7472 | 7948 | |
| 7473 | 7949 | /// LLVM does not support all relevant intrinsics for all targets, so we |
| 7474 | /// may need to manually generate a compiler-rt call. | |
| 7475 | fn intrinsicsAllowed(scalar_ty: Type, target: *const std.Target) bool { | |
| 7476 | return switch (scalar_ty.toIntern()) { | |
| 7477 | .f16_type => llvm.backendSupportsF16(target), | |
| 7478 | .f80_type => (target.cTypeBitSize(.longdouble) == 80) and llvm.backendSupportsF80(target), | |
| 7479 | .f128_type => (target.cTypeBitSize(.longdouble) == 128) and llvm.backendSupportsF128(target), | |
| 7480 | else => true, | |
| 7950 | /// may need to manually generate a compiler-rt call using a soft type. | |
| 7951 | fn intrinsicsAllowed(kind: enum { compiler_rt, libc }, scalar_ty: Type, target: *const std.Target) bool { | |
| 7952 | if (!scalar_ty.isRuntimeFloat()) return true; | |
| 7953 | const bits = scalar_ty.floatBits(target); | |
| 7954 | // Since upstream musl/msvc do not actually define the *f128 functions, llvm decides | |
| 7955 | // that it is a much better idea to just emit a call to the entirely wrong function as | |
| 7956 | // a fallback. We wouldn't want any linker errors when trying to perform an operation | |
| 7957 | // that isn't actually implemented anywhere, now would we! | |
| 7958 | if (bits == 128 and target.cpu.arch.isX86() and !target.abi.isGnu()) return switch (kind) { | |
| 7959 | .compiler_rt => true, | |
| 7960 | .libc => false, | |
| 7961 | }; | |
| 7962 | return switch (std.zig.target.compilerRtFloatAbi(target, bits)) { | |
| 7963 | .hard => true, | |
| 7964 | .soft => false, | |
| 7481 | 7965 | }; |
| 7482 | 7966 | } |
| 7483 | 7967 | |
| ... | ... | @@ -7823,12 +8307,14 @@ const Builder = std.zig.llvm.Builder; |
| 7823 | 8307 | const assert = std.debug.assert; |
| 7824 | 8308 | const math = std.math; |
| 7825 | 8309 | |
| 7826 | const x86_64_abi = @import("../x86_64/abi.zig"); | |
| 7827 | const wasm_c_abi = @import("../wasm/abi.zig"); | |
| 7828 | 8310 | const aarch64_c_abi = @import("../aarch64/abi.zig"); |
| 7829 | 8311 | const arm_c_abi = @import("../arm/abi.zig"); |
| 7830 | const riscv_c_abi = @import("../riscv64/abi.zig"); | |
| 8312 | const loongarch_c_abi = @import("../loongarch/abi.zig"); | |
| 7831 | 8313 | const mips_c_abi = @import("../mips/abi.zig"); |
| 8314 | const riscv_c_abi = @import("../riscv64/abi.zig"); | |
| 8315 | const s390x_c_abi = @import("../s390x/abi.zig"); | |
| 8316 | const wasm_c_abi = @import("../wasm/abi.zig"); | |
| 8317 | const x86_64_abi = @import("../x86_64/abi.zig"); | |
| 7832 | 8318 | |
| 7833 | 8319 | const Zcu = @import("../../Zcu.zig"); |
| 7834 | 8320 | const Air = @import("../../Air.zig"); |
src/codegen/llvm/bindings.zig+2| ... | ... | @@ -331,6 +331,8 @@ extern fn ZigLLVMWriteArchive( |
| 331 | 331 | file_names_ptr: [*]const [*:0]const u8, |
| 332 | 332 | file_names_len: usize, |
| 333 | 333 | archive_kind: ArchiveKind, |
| 334 | err_file_index_out: *usize, | |
| 335 | err_msg_out: *[*:0]u8, | |
| 334 | 336 | ) bool; |
| 335 | 337 | |
| 336 | 338 | pub const ParseCommandLineOptions = ZigLLVMParseCommandLineOptions; |
src/codegen/loongarch/abi.zig created+133| ... | ... | @@ -0,0 +1,133 @@ |
| 1 | const std = @import("std"); | |
| 2 | const InternPool = @import("../../InternPool.zig"); | |
| 3 | const Type = @import("../../Type.zig"); | |
| 4 | const Zcu = @import("../../Zcu.zig"); | |
| 5 | ||
| 6 | pub 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 | ||
| 32 | pub fn classifyType(ty: Type, zcu: *Zcu) Class { | |
| 33 | return Classifier.init(zcu).classifyType(ty); | |
| 34 | } | |
| 35 | ||
| 36 | const 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 | 38 | return .byval; |
| 39 | 39 | }, |
| 40 | 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 | 49 | .int, .@"enum", .error_set => { |
| 43 | 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 | 5036 | .register_pair, |
| 5037 | 5037 | => { |
| 5038 | 5038 | if (ret_ty.isVector(zcu)) { |
| 5039 | const bit_size = ret_ty.totalVectorBits(zcu); | |
| 5039 | const bit_size = ret_ty.bitSize(zcu); | |
| 5040 | 5040 | |
| 5041 | 5041 | // set the vtype to hold the entire vector's contents in a single element |
| 5042 | 5042 | try func.setVl(.zero, 0, .{ |
| ... | ... | @@ -6235,8 +6235,8 @@ fn airAsm(func: *Func, inst: Air.Inst.Index) !void { |
| 6235 | 6235 | next_op: for (&ops) |*op| { |
| 6236 | 6236 | const op_str = while (!last_op) { |
| 6237 | 6237 | const full_str = op_it.next() orelse break :next_op; |
| 6238 | const code_str = if (mem.indexOfScalar(u8, full_str, '#') orelse | |
| 6239 | mem.indexOf(u8, full_str, "//")) |comment| | |
| 6238 | const code_str = if (mem.findScalar(u8, full_str, '#') orelse | |
| 6239 | mem.find(u8, full_str, "//")) |comment| | |
| 6240 | 6240 | code: { |
| 6241 | 6241 | last_op = true; |
| 6242 | 6242 | break :code full_str[0..comment]; |
| ... | ... | @@ -6250,7 +6250,7 @@ fn airAsm(func: *Func, inst: Air.Inst.Index) !void { |
| 6250 | 6250 | } else if (std.fmt.parseInt(i12, op_str, 10)) |int| { |
| 6251 | 6251 | op.* = .{ .imm = Immediate.s(int) }; |
| 6252 | 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 | 6254 | const modifier = if (mod_index) |index| |
| 6255 | 6255 | op_str[index + "]@".len ..] |
| 6256 | 6256 | else |
| ... | ... | @@ -6871,7 +6871,7 @@ fn genSetReg(func: *Func, ty: Type, reg: Register, src_mcv: MCValue) InnerError! |
| 6871 | 6871 | // size to the total size of the vector, and vmv.x.s will work then |
| 6872 | 6872 | if (src_reg.class() == .vector) { |
| 6873 | 6873 | try func.setVl(.zero, 0, .{ |
| 6874 | .vsew = switch (ty.totalVectorBits(zcu)) { | |
| 6874 | .vsew = switch (ty.bitSize(zcu)) { | |
| 6875 | 6875 | 8 => .@"8", |
| 6876 | 6876 | 16 => .@"16", |
| 6877 | 6877 | 32 => .@"32", |
| ... | ... | @@ -8339,9 +8339,9 @@ fn resolveCallingConventionValues( |
| 8339 | 8339 | fn wantSafety(func: *Func) bool { |
| 8340 | 8340 | return switch (func.mod.optimize_mode) { |
| 8341 | 8341 | .Debug => true, |
| 8342 | .ReleaseSafe => true, | |
| 8343 | .ReleaseFast => false, | |
| 8344 | .ReleaseSmall => false, | |
| 8342 | .safe => true, | |
| 8343 | .fast => false, | |
| 8344 | .small => false, | |
| 8345 | 8345 | }; |
| 8346 | 8346 | } |
| 8347 | 8347 |
src/codegen/riscv64/abi.zig+10-2| ... | ... | @@ -56,12 +56,20 @@ pub fn classifyType(ty: Type, zcu: *Zcu) Class { |
| 56 | 56 | return .integer; |
| 57 | 57 | }, |
| 58 | 58 | .bool => return .integer, |
| 59 | .float => return .byval, | |
| 60 | 59 | .int, .@"enum", .error_set => { |
| 61 | 60 | const bit_size = ty.bitSize(zcu); |
| 62 | 61 | if (bit_size > max_byval_size) return .memory; |
| 63 | 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 | 73 | .vector => { |
| 66 | 74 | const bit_size = ty.bitSize(zcu); |
| 67 | 75 | if (bit_size > max_byval_size) return .memory; |
| ... | ... | @@ -190,7 +198,7 @@ pub fn classifySystem(ty: Type, zcu: *Zcu) [8]SystemClass { |
| 190 | 198 | }, |
| 191 | 199 | .vector => { |
| 192 | 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 | 202 | if (vec_bits <= 64) { |
| 195 | 203 | result[0] = .integer; |
| 196 | 204 | return result; |
src/codegen/riscv64/encoding.zig+1-1| ... | ... | @@ -498,7 +498,7 @@ pub const Instruction = union(Lir.Format) { |
| 498 | 498 | extra: u32, |
| 499 | 499 | |
| 500 | 500 | comptime { |
| 501 | for (std.meta.fieldTypes(Instruction)) |field_type| { | |
| 501 | for (@typeInfo(Instruction).@"union".field_types) |field_type| { | |
| 502 | 502 | assert(@bitSizeOf(field_type) == 32); |
| 503 | 503 | } |
| 504 | 504 | } |
src/codegen/s390x/abi.zig created+85| ... | ... | @@ -0,0 +1,85 @@ |
| 1 | const assert = std.debug.assert; | |
| 2 | const std = @import("std"); | |
| 3 | const InternPool = @import("../../InternPool.zig"); | |
| 4 | const Type = @import("../../Type.zig"); | |
| 5 | const Zcu = @import("../../Zcu.zig"); | |
| 6 | ||
| 7 | pub const Context = enum { ret, arg }; | |
| 8 | ||
| 9 | pub const Class = enum { | |
| 10 | none, | |
| 11 | double_or_float, | |
| 12 | vector, | |
| 13 | simple, | |
| 14 | simple_aggregate, | |
| 15 | pointer, | |
| 16 | }; | |
| 17 | ||
| 18 | pub 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 | 4764 | fn wantSafety(self: *Self) bool { |
| 4765 | 4765 | return switch (self.bin_file.comp.root_mod.optimize_mode) { |
| 4766 | 4766 | .Debug => true, |
| 4767 | .ReleaseSafe => true, | |
| 4768 | .ReleaseFast => false, | |
| 4769 | .ReleaseSmall => false, | |
| 4767 | .safe => true, | |
| 4768 | .fast => false, | |
| 4769 | .small => false, | |
| 4770 | 4770 | }; |
| 4771 | 4771 | } |
| 4772 | 4772 |
src/codegen/spirv/Assembler.zig+39-38| ... | ... | @@ -24,8 +24,9 @@ inst: struct { |
| 24 | 24 | opcode: Opcode = undefined, |
| 25 | 25 | operands: std.ArrayList(Operand) = .empty, |
| 26 | 26 | string_bytes: std.ArrayList(u8) = .empty, |
| 27 | inst_offset: u32 = 0, | |
| 27 | 28 | |
| 28 | fn result(ass: @This()) ?AsmValue.Ref { | |
| 29 | fn result(ass: *const @This()) ?AsmValue.Ref { | |
| 29 | 30 | for (ass.operands.items[0..@min(ass.operands.items.len, 2)]) |op| { |
| 30 | 31 | switch (op) { |
| 31 | 32 | .result_id => |index| return index, |
| ... | ... | @@ -35,7 +36,7 @@ inst: struct { |
| 35 | 36 | return null; |
| 36 | 37 | } |
| 37 | 38 | } = .{}, |
| 38 | value_map: std.array_hash_map.String(AsmValue) = .{}, | |
| 39 | value_map: std.array_hash_map.String(AsmValue) = .empty, | |
| 39 | 40 | inst_map: std.array_hash_map.String(void) = .empty, |
| 40 | 41 | |
| 41 | 42 | const Operand = union(enum) { |
| ... | ... | @@ -82,7 +83,7 @@ pub fn assemble(ass: *Assembler, src: []const u8) Error!void { |
| 82 | 83 | if (ass.inst_map.count() == 0) { |
| 83 | 84 | const instructions = spec.InstructionSet.core.instructions(); |
| 84 | 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 | 87 | const entry = try ass.inst_map.getOrPut(gpa, inst.name); |
| 87 | 88 | assert(entry.index == i); |
| 88 | 89 | } |
| ... | ... | @@ -114,12 +115,13 @@ fn addError(ass: *Assembler, offset: u32, comptime fmt: []const u8, args: anytyp |
| 114 | 115 | } |
| 115 | 116 | |
| 116 | 117 | fn fail(ass: *Assembler, offset: u32, comptime fmt: []const u8, args: anytype) Error { |
| 118 | @branchHint(.cold); | |
| 117 | 119 | try ass.addError(offset, fmt, args); |
| 118 | 120 | return error.AssembleFail; |
| 119 | 121 | } |
| 120 | 122 | |
| 121 | 123 | fn 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 | } |
| 124 | 126 | |
| 125 | 127 | const AsmValue = union(enum) { |
| ... | ... | @@ -177,19 +179,19 @@ fn processInstruction(ass: *Assembler) !void { |
| 177 | 179 | const cg = ass.cg; |
| 178 | 180 | const result: AsmValue = switch (ass.inst.opcode) { |
| 179 | 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 | 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 | 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 | 190 | .OpExtInstImport => blk: { |
| 189 | 191 | const set_name_offset = ass.inst.operands.items[1].string; |
| 190 | 192 | const set_name = std.mem.sliceTo(ass.inst.string_bytes.items[set_name_offset..], 0); |
| 191 | 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 | 196 | break :blk .{ .value = try cg.importInstructionSet(set_tag) }; |
| 195 | 197 | }, |
| ... | ... | @@ -209,9 +211,8 @@ fn processInstruction(ass: *Assembler) !void { |
| 209 | 211 | switch (ass.value_map.values()[result_ref]) { |
| 210 | 212 | .just_declared => ass.value_map.values()[result_ref] = result, |
| 211 | 213 | else => { |
| 212 | // TODO: Improve source location. | |
| 213 | 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 | 230 | 0 => .unsigned, |
| 230 | 231 | 1 => .signed, |
| 231 | 232 | else => { |
| 232 | // TODO: Improve source location. | |
| 233 | return ass.fail(0, "{} is not a valid signedness (expected 0 or 1)", .{operands[2].literal32}); | |
| 233 | return ass.fail(ass.inst.inst_offset, "{} is not a valid signedness (expected 0 or 1)", .{operands[2].literal32}); | |
| 234 | 234 | }, |
| 235 | 235 | }; |
| 236 | 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 | 239 | break :blk try cg.intType(signedness, width); |
| 240 | 240 | }, |
| ... | ... | @@ -243,7 +243,7 @@ fn processTypeInstruction(ass: *Assembler) !AsmValue { |
| 243 | 243 | switch (bits) { |
| 244 | 244 | 16, 32, 64 => {}, |
| 245 | 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 | 249 | break :blk try cg.floatType(@intCast(bits)); |
| ... | ... | @@ -366,38 +366,40 @@ fn processGenericInstruction(ass: *Assembler) !?AsmValue { |
| 366 | 366 | |
| 367 | 367 | var maybe_result_id: ?Id = null; |
| 368 | 368 | const first_word = section.instructions.items.len; |
| 369 | // At this point we're not quite sure how many operands this instruction is | |
| 370 | // going to have, so insert 0 and patch up the actual opcode word later. | |
| 371 | try section.ensureUnusedCapacity(cg.gpa, 1); | |
| 369 | ||
| 370 | // Pre-calculate exact instruction size to avoid per-operand capacity checks. | |
| 371 | var total_words: usize = 1; // 1 word for the opcode itself | |
| 372 | for (operands) |operand| { | |
| 373 | total_words += switch (operand) { | |
| 374 | .value, .literal32, .result_id, .ref_id => 1, | |
| 375 | .literal64 => 2, | |
| 376 | .string => |offset| blk: { | |
| 377 | const text = std.mem.sliceTo(ass.inst.string_bytes.items[offset..], 0); | |
| 378 | break :blk @divCeil(text.len + 1, @sizeOf(Word)); | |
| 379 | }, | |
| 380 | }; | |
| 381 | } | |
| 382 | ||
| 383 | try section.ensureUnusedCapacity(cg.gpa, total_words); | |
| 372 | 384 | section.writeWord(0); |
| 373 | 385 | |
| 374 | 386 | for (operands) |operand| { |
| 375 | 387 | switch (operand) { |
| 376 | .value, .literal32 => |word| { | |
| 377 | try section.ensureUnusedCapacity(cg.gpa, 1); | |
| 378 | section.writeWord(word); | |
| 379 | }, | |
| 380 | .literal64 => |dword| { | |
| 381 | try section.ensureUnusedCapacity(cg.gpa, 2); | |
| 382 | section.writeDoubleWord(dword); | |
| 383 | }, | |
| 388 | .value, .literal32 => |word| section.writeWord(word), | |
| 389 | .literal64 => |dword| section.writeDoubleWord(dword), | |
| 384 | 390 | .result_id => { |
| 385 | 391 | maybe_result_id = if (maybe_spv_decl_index) |spv_decl_index| |
| 386 | 392 | cg.declPtr(spv_decl_index).result_id |
| 387 | 393 | else |
| 388 | 394 | cg.allocId(); |
| 389 | try section.ensureUnusedCapacity(cg.gpa, 1); | |
| 390 | 395 | section.writeOperand(Id, maybe_result_id.?); |
| 391 | 396 | }, |
| 392 | 397 | .ref_id => |index| { |
| 393 | 398 | const result = try ass.resolveRef(index); |
| 394 | try section.ensureUnusedCapacity(cg.gpa, 1); | |
| 395 | 399 | section.writeOperand(spec.Id, result.resultId()); |
| 396 | 400 | }, |
| 397 | 401 | .string => |offset| { |
| 398 | 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 | 403 | section.writeOperand(spec.LiteralString, text); |
| 402 | 404 | }, |
| 403 | 405 | } |
| ... | ... | @@ -445,11 +447,11 @@ fn processSpecConstVector(ass: *Assembler) !?AsmValue { |
| 445 | 447 | const gpa = cg.gpa; |
| 446 | 448 | const ty_ref = switch (ass.inst.operands.items[0]) { |
| 447 | 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 | 452 | const composite_ty_id = switch (try ass.resolveRef(ty_ref)) { |
| 451 | 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 | }; |
| 454 | 456 | |
| 455 | 457 | const globals = &cg.sections.globals; |
| ... | ... | @@ -483,7 +485,7 @@ fn processSpecConstVector(ass: *Assembler) !?AsmValue { |
| 483 | 485 | } |
| 484 | 486 | |
| 485 | 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 | 490 | try annotations.emitRaw(gpa, .OpDecorate, 3); |
| 489 | 491 | annotations.writeOperand(Id, elem_id); |
| ... | ... | @@ -505,8 +507,7 @@ fn resolveMaybeForwardRef(ass: *Assembler, ref: AsmValue.Ref) !AsmValue { |
| 505 | 507 | switch (value) { |
| 506 | 508 | .just_declared => { |
| 507 | 509 | const name = ass.value_map.keys()[ref]; |
| 508 | // TODO: Improve source location. | |
| 509 | return ass.fail(0, "ass-referential parameter %{s}", .{name}); | |
| 510 | return ass.fail(ass.inst.inst_offset, "self-referential parameter %{s}", .{name}); | |
| 510 | 511 | }, |
| 511 | 512 | else => return value, |
| 512 | 513 | } |
| ... | ... | @@ -518,8 +519,7 @@ fn resolveRef(ass: *Assembler, ref: AsmValue.Ref) !AsmValue { |
| 518 | 519 | .just_declared => unreachable, |
| 519 | 520 | .unresolved_forward_reference => { |
| 520 | 521 | const name = ass.value_map.keys()[ref]; |
| 521 | // TODO: Improve source location. | |
| 522 | return ass.fail(0, "reference to undeclared result-id %{s}", .{name}); | |
| 522 | return ass.fail(ass.inst.inst_offset, "reference to undeclared result-id %{s}", .{name}); | |
| 523 | 523 | }, |
| 524 | 524 | else => return value, |
| 525 | 525 | } |
| ... | ... | @@ -536,6 +536,7 @@ fn parseInstruction(ass: *Assembler) !void { |
| 536 | 536 | ass.inst.opcode = undefined; |
| 537 | 537 | ass.inst.operands.clearRetainingCapacity(); |
| 538 | 538 | ass.inst.string_bytes.clearRetainingCapacity(); |
| 539 | ass.inst.inst_offset = ass.currentToken().start; | |
| 539 | 540 | |
| 540 | 541 | const lhs_result_tok = ass.currentToken(); |
| 541 | 542 | const maybe_lhs_result: ?AsmValue.Ref = if (ass.eatToken(.result_id_assign)) blk: { |
| ... | ... | @@ -589,8 +590,8 @@ fn parseInstruction(ass: *Assembler) !void { |
| 589 | 590 | .required => if (ass.isAtInstructionBoundary()) { |
| 590 | 591 | return ass.fail( |
| 591 | 592 | ass.currentToken().start, |
| 592 | "missing required operand", // TODO: Operand name? | |
| 593 | .{}, | |
| 593 | "missing required operand '{s}'", | |
| 594 | .{@tagName(operand.kind)}, | |
| 594 | 595 | ); |
| 595 | 596 | } else { |
| 596 | 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 | 7280 | if (cg.block_terminated) return; |
| 7281 | 7281 | |
| 7282 | 7282 | const gpa = cg.gpa; |
| 7283 | const sblock = cg.block_stack.getLast().?; | |
| 7283 | const sblock = cg.block_stack.last().?; | |
| 7284 | 7284 | const merge_block = switch (sblock.*) { |
| 7285 | 7285 | .selection => |*merge| blk: { |
| 7286 | 7286 | const merge_label = cg.allocId(); |
| ... | ... | @@ -7447,7 +7447,7 @@ fn lowerBlock(cg: *CodeGen, inst: Air.Inst.Index, body: []const Air.Inst.Index) |
| 7447 | 7447 | .operand_2 = this_block, |
| 7448 | 7448 | }); |
| 7449 | 7449 | |
| 7450 | const sblock = cg.block_stack.getLast().?; | |
| 7450 | const sblock = cg.block_stack.last().?; | |
| 7451 | 7451 | |
| 7452 | 7452 | if (ty.isNoReturn(zcu)) { |
| 7453 | 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 | 49 | operand_words: usize, |
| 50 | 50 | ) !void { |
| 51 | 51 | const word_count = 1 + operand_words; |
| 52 | if (word_count > std.math.maxInt(u16)) return error.OutOfMemory; | |
| 52 | 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 | } |
| 55 | 56 | |
| 56 | 57 | /// Write an entire instruction, including all operands |
| ... | ... | @@ -70,7 +71,8 @@ pub fn emitAssumeCapacity( |
| 70 | 71 | operands: opcode.Operands(), |
| 71 | 72 | ) !void { |
| 72 | 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 | 76 | section.writeOperands(opcode.Operands(), operands); |
| 75 | 77 | } |
| 76 | 78 | |
| ... | ... | @@ -81,8 +83,9 @@ pub fn emit( |
| 81 | 83 | operands: opcode.Operands(), |
| 82 | 84 | ) !void { |
| 83 | 85 | const word_count = instructionSize(opcode, operands); |
| 86 | if (word_count > std.math.maxInt(u16)) return error.OutOfMemory; | |
| 84 | 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 | 89 | section.writeOperands(opcode.Operands(), operands); |
| 87 | 90 | } |
| 88 | 91 |
src/codegen/wasm/CodeGen.zig+111-65| ... | ... | @@ -24,12 +24,6 @@ const Alignment = InternPool.Alignment; |
| 24 | 24 | const errUnionPayloadOffset = codegen.errUnionPayloadOffset; |
| 25 | 25 | const errUnionErrorOffset = codegen.errUnionErrorOffset; |
| 26 | 26 | |
| 27 | const target_util = @import("../../target.zig"); | |
| 28 | const libcFloatPrefix = target_util.libcFloatPrefix; | |
| 29 | const libcFloatSuffix = target_util.libcFloatSuffix; | |
| 30 | const compilerRtFloatAbbrev = target_util.compilerRtFloatAbbrev; | |
| 31 | const compilerRtIntAbbrev = target_util.compilerRtIntAbbrev; | |
| 32 | ||
| 33 | 27 | pub fn legalizeFeatures(_: *const std.Target) *const Air.Legalize.Features { |
| 34 | 28 | return comptime &.initMany(&.{ |
| 35 | 29 | .expand_bit_cast_safe, |
| ... | ... | @@ -573,7 +567,7 @@ fn addCallIntrinsic(cg: *CodeGen, intrinsic: Mir.Intrinsic) error{OutOfMemory}!v |
| 573 | 567 | /// Appends entries to `mir_extra` based on the type of `extra`. |
| 574 | 568 | /// Returns the index into `mir_extra` |
| 575 | 569 | fn 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 | 571 | try cg.mir_extra.ensureUnusedCapacity(cg.gpa, field_count); |
| 578 | 572 | return cg.addExtraAssumeCapacity(extra); |
| 579 | 573 | } |
| ... | ... | @@ -933,21 +927,26 @@ fn resolveCallingConventionValues( |
| 933 | 927 | }, |
| 934 | 928 | .wasm_mvp => { |
| 935 | 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 | 932 | continue; |
| 938 | 933 | } |
| 939 | switch (abi.classifyType(.fromInterned(ty), zcu)) { | |
| 940 | .direct => |scalar_ty| if (!abi.lowerAsDoubleI64(scalar_ty, zcu)) { | |
| 934 | ||
| 935 | switch (abi.classifyType(param_ty, zcu, target)) { | |
| 936 | .direct, .indirect => { | |
| 941 | 937 | try args.append(.{ .local = .{ .value = result.local_index, .references = 1 } }); |
| 942 | 938 | result.local_index += 1; |
| 943 | } else { | |
| 939 | }, | |
| 940 | .double_i64 => { | |
| 944 | 941 | try args.append(.{ .local = .{ .value = result.local_index, .references = 1 } }); |
| 945 | 942 | try args.append(.{ .local = .{ .value = result.local_index + 1, .references = 1 } }); |
| 946 | 943 | result.local_index += 2; |
| 947 | 944 | }, |
| 948 | .indirect => { | |
| 949 | try args.append(.{ .local = .{ .value = result.local_index, .references = 1 } }); | |
| 950 | result.local_index += 1; | |
| 945 | .unrolled => |vector| { | |
| 946 | for (0..vector.len) |_| { | |
| 947 | try args.append(.{ .local = .{ .value = result.local_index, .references = 1 } }); | |
| 948 | result.local_index += 1; | |
| 949 | } | |
| 951 | 950 | }, |
| 952 | 951 | } |
| 953 | 952 | } |
| ... | ... | @@ -974,9 +973,10 @@ pub fn firstParamSRet( |
| 974 | 973 | switch (cc) { |
| 975 | 974 | .@"inline" => unreachable, |
| 976 | 975 | .auto => return isByRef(return_type, zcu, target), |
| 977 | .wasm_mvp => switch (abi.classifyType(return_type, zcu)) { | |
| 978 | .direct => |scalar_ty| return abi.lowerAsDoubleI64(scalar_ty, zcu), | |
| 979 | .indirect => return true, | |
| 976 | .wasm_mvp => switch (abi.classifyType(return_type, zcu, target)) { | |
| 977 | .direct => return false, | |
| 978 | .double_i64, .indirect => return true, | |
| 979 | .unrolled => |vector| return vector.len > 1, | |
| 980 | 980 | }, |
| 981 | 981 | else => return false, |
| 982 | 982 | } |
| ... | ... | @@ -991,18 +991,15 @@ fn lowerArg(cg: *CodeGen, cc: std.lang.CallingConvention, ty: Type, value: WValu |
| 991 | 991 | |
| 992 | 992 | const zcu = cg.pt.zcu; |
| 993 | 993 | |
| 994 | switch (abi.classifyType(ty, zcu)) { | |
| 995 | .direct => |scalar_type| if (!abi.lowerAsDoubleI64(scalar_type, zcu)) { | |
| 994 | switch (abi.classifyType(ty, zcu, cg.target)) { | |
| 995 | .direct => |scalar_ty| { | |
| 996 | 996 | if (!isByRef(ty, zcu, cg.target)) { |
| 997 | 997 | return cg.lowerToStack(value); |
| 998 | 998 | } else { |
| 999 | switch (value) { | |
| 1000 | .nav_ref, .stack_offset => _ = try cg.load(value, scalar_type, 0), | |
| 1001 | .dead => unreachable, | |
| 1002 | else => try cg.emitWValue(value), | |
| 1003 | } | |
| 999 | _ = try cg.load(value, scalar_ty, 0); | |
| 1004 | 1000 | } |
| 1005 | } else { | |
| 1001 | }, | |
| 1002 | .double_i64 => { | |
| 1006 | 1003 | assert(ty.abiSize(zcu) == 16); |
| 1007 | 1004 | // in this case we have an integer or float that must be lowered as 2 i64's. |
| 1008 | 1005 | try cg.emitWValue(value); |
| ... | ... | @@ -1010,7 +1007,17 @@ fn lowerArg(cg: *CodeGen, cc: std.lang.CallingConvention, ty: Type, value: WValu |
| 1010 | 1007 | try cg.emitWValue(value); |
| 1011 | 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 | } |
| 1016 | 1023 | |
| ... | ... | @@ -1953,16 +1960,19 @@ fn airRet(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 1953 | 1960 | if (cg.return_value != .none) { |
| 1954 | 1961 | try cg.store(cg.return_value, operand, ret_ty, 0); |
| 1955 | 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 | 1964 | .direct => |scalar_type| { |
| 1958 | assert(!abi.lowerAsDoubleI64(scalar_type, zcu)); | |
| 1959 | 1965 | if (!isByRef(ret_ty, zcu, cg.target)) { |
| 1960 | 1966 | try cg.emitWValue(operand); |
| 1961 | 1967 | } else { |
| 1962 | 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 | 1977 | } else { |
| 1968 | 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 | 2019 | try cg.addImm32(0); |
| 2010 | 2020 | } |
| 2011 | 2021 | } else if (!firstParamSRet(fn_info.cc, Type.fromInterned(fn_info.return_type), zcu, cg.target)) { |
| 2012 | // leave on the stack | |
| 2013 | _ = try cg.load(operand, ret_ty, 0); | |
| 2022 | if (fn_info.cc == .wasm_mvp) { | |
| 2023 | switch (abi.classifyType(ret_ty, zcu, cg.target)) { | |
| 2024 | .direct => |scalar_type| _ = try cg.load(operand, scalar_type, 0), | |
| 2025 | .double_i64, .indirect => unreachable, | |
| 2026 | .unrolled => |vector| { | |
| 2027 | assert(vector.len == 1); | |
| 2028 | _ = try cg.load(operand, vector.elem_type, 0); | |
| 2029 | }, | |
| 2030 | } | |
| 2031 | } else { | |
| 2032 | _ = try cg.load(operand, ret_ty, 0); | |
| 2033 | } | |
| 2014 | 2034 | } |
| 2015 | 2035 | |
| 2016 | 2036 | try cg.restoreStackPointer(); |
| ... | ... | @@ -2138,22 +2158,30 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier) |
| 2138 | 2158 | } else if (first_param_sret) { |
| 2139 | 2159 | break :result_value sret; |
| 2140 | 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 | 2162 | .direct => |scalar_type| { |
| 2143 | assert(!abi.lowerAsDoubleI64(scalar_type, zcu)); | |
| 2144 | 2163 | if (!isByRef(ret_ty, zcu, cg.target)) { |
| 2145 | 2164 | const result_local = try cg.allocLocal(ret_ty); |
| 2146 | 2165 | try cg.addLocal(.local_set, result_local.local.value); |
| 2147 | 2166 | break :result_value result_local; |
| 2148 | 2167 | } else { |
| 2149 | const result_local = try cg.allocLocal(ret_ty); | |
| 2168 | const result_local = try cg.allocLocal(scalar_type); | |
| 2150 | 2169 | try cg.addLocal(.local_set, result_local.local.value); |
| 2151 | 2170 | const result = try cg.allocStack(ret_ty); |
| 2152 | 2171 | try cg.store(result, result_local, scalar_type, 0); |
| 2153 | 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 | 2186 | } else { |
| 2159 | 2187 | const result_local = try cg.allocLocal(ret_ty); |
| ... | ... | @@ -2456,17 +2484,32 @@ fn airArg(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 2456 | 2484 | const cc = zcu.typeToFunc(zcu.navValue(cg.owner_nav).typeOf(zcu)).?.cc; |
| 2457 | 2485 | const arg_ty = cg.typeOfIndex(inst); |
| 2458 | 2486 | if (cc == .wasm_mvp) { |
| 2459 | switch (abi.classifyType(arg_ty, zcu)) { | |
| 2460 | .direct => |scalar_ty| if (!abi.lowerAsDoubleI64(scalar_ty, zcu)) { | |
| 2487 | switch (abi.classifyType(arg_ty, zcu, cg.target)) { | |
| 2488 | .direct => |scalar_type| { | |
| 2461 | 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 | 2498 | cg.arg_index += 2; |
| 2464 | 2499 | const result = try cg.allocStack(arg_ty); |
| 2465 | 2500 | try cg.store(result, arg, Type.u64, 0); |
| 2466 | 2501 | try cg.store(result, cg.args[arg_index + 1], Type.u64, 8); |
| 2467 | 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 | 2514 | } else { |
| 2472 | 2515 | cg.arg_index += 1; |
| ... | ... | @@ -2515,15 +2558,15 @@ const IntType = struct { |
| 2515 | 2558 | .anyerror, .adhoc_inferred_error_set => .{ .is_signed = false, .bits = zcu.errorSetBits() }, |
| 2516 | 2559 | .isize => .{ .is_signed = true, .bits = cg.target.ptrBitWidth() }, |
| 2517 | 2560 | .usize => .{ .is_signed = false, .bits = cg.target.ptrBitWidth() }, |
| 2518 | .c_char => .{ .is_signed = cg.target.cCharSignedness() == .signed, .bits = cg.target.cTypeBitSize(.char) }, | |
| 2519 | .c_short => .{ .is_signed = true, .bits = cg.target.cTypeBitSize(.short) }, | |
| 2520 | .c_ushort => .{ .is_signed = false, .bits = cg.target.cTypeBitSize(.short) }, | |
| 2521 | .c_int => .{ .is_signed = true, .bits = cg.target.cTypeBitSize(.int) }, | |
| 2522 | .c_uint => .{ .is_signed = false, .bits = cg.target.cTypeBitSize(.int) }, | |
| 2523 | .c_long => .{ .is_signed = true, .bits = cg.target.cTypeBitSize(.long) }, | |
| 2524 | .c_ulong => .{ .is_signed = false, .bits = cg.target.cTypeBitSize(.long) }, | |
| 2525 | .c_longlong => .{ .is_signed = true, .bits = cg.target.cTypeBitSize(.longlong) }, | |
| 2526 | .c_ulonglong => .{ .is_signed = false, .bits = cg.target.cTypeBitSize(.longlong) }, | |
| 2561 | .c_char => .{ .is_signed = cg.target.cCharSignedness().? == .signed, .bits = cg.target.cTypeBitSize(.char).? }, | |
| 2562 | .c_short => .{ .is_signed = true, .bits = cg.target.cTypeBitSize(.short).? }, | |
| 2563 | .c_ushort => .{ .is_signed = false, .bits = cg.target.cTypeBitSize(.short).? }, | |
| 2564 | .c_int => .{ .is_signed = true, .bits = cg.target.cTypeBitSize(.int).? }, | |
| 2565 | .c_uint => .{ .is_signed = false, .bits = cg.target.cTypeBitSize(.int).? }, | |
| 2566 | .c_long => .{ .is_signed = true, .bits = cg.target.cTypeBitSize(.long).? }, | |
| 2567 | .c_ulong => .{ .is_signed = false, .bits = cg.target.cTypeBitSize(.long).? }, | |
| 2568 | .c_longlong => .{ .is_signed = true, .bits = cg.target.cTypeBitSize(.longlong).? }, | |
| 2569 | .c_ulonglong => .{ .is_signed = false, .bits = cg.target.cTypeBitSize(.longlong).? }, | |
| 2527 | 2570 | .f16, .f32, .f64, .f80, .f128, .c_longdouble => unreachable, |
| 2528 | 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 | 4383 | .f32 => return cg.callIntrinsic(.fmodf, &.{ .f32_type, .f32_type }, Type.f32, &.{ lhs, rhs }), |
| 4341 | 4384 | .f64 => return cg.callIntrinsic(.fmod, &.{ .f64_type, .f64_type }, Type.f64, &.{ lhs, rhs }), |
| 4342 | 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 | } |
| 4346 | 4389 | |
| ... | ... | @@ -4376,7 +4419,7 @@ fn floatMax(cg: *CodeGen, ty: FloatType, lhs: WValue, rhs: WValue) InnerError!WV |
| 4376 | 4419 | .f32 => return cg.callIntrinsic(.fmaxf, &.{ .f32_type, .f32_type }, Type.f32, &.{ lhs, rhs }), |
| 4377 | 4420 | .f64 => return cg.callIntrinsic(.fmax, &.{ .f64_type, .f64_type }, Type.f64, &.{ lhs, rhs }), |
| 4378 | 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 | } |
| 4382 | 4425 | |
| ... | ... | @@ -4387,7 +4430,7 @@ fn floatMin(cg: *CodeGen, ty: FloatType, lhs: WValue, rhs: WValue) InnerError!WV |
| 4387 | 4430 | .f32 => return cg.callIntrinsic(.fminf, &.{ .f32_type, .f32_type }, Type.f32, &.{ lhs, rhs }), |
| 4388 | 4431 | .f64 => return cg.callIntrinsic(.fmin, &.{ .f64_type, .f64_type }, Type.f64, &.{ lhs, rhs }), |
| 4389 | 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 | } |
| 4393 | 4436 | |
| ... | ... | @@ -4405,7 +4448,7 @@ fn floatSqrt(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue { |
| 4405 | 4448 | return .stack; |
| 4406 | 4449 | }, |
| 4407 | 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 | } |
| 4411 | 4454 | |
| ... | ... | @@ -4415,7 +4458,7 @@ fn floatSin(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue { |
| 4415 | 4458 | .f32 => return cg.callIntrinsic(.sinf, &.{.f32_type}, Type.f32, &.{arg}), |
| 4416 | 4459 | .f64 => return cg.callIntrinsic(.sin, &.{.f64_type}, Type.f64, &.{arg}), |
| 4417 | 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 | } |
| 4421 | 4464 | |
| ... | ... | @@ -4425,7 +4468,7 @@ fn floatCos(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue { |
| 4425 | 4468 | .f32 => return cg.callIntrinsic(.cosf, &.{.f32_type}, Type.f32, &.{arg}), |
| 4426 | 4469 | .f64 => return cg.callIntrinsic(.cos, &.{.f64_type}, Type.f64, &.{arg}), |
| 4427 | 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 | } |
| 4431 | 4474 | |
| ... | ... | @@ -4435,7 +4478,7 @@ fn floatTan(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue { |
| 4435 | 4478 | .f32 => return cg.callIntrinsic(.tanf, &.{.f32_type}, Type.f32, &.{arg}), |
| 4436 | 4479 | .f64 => return cg.callIntrinsic(.tan, &.{.f64_type}, Type.f64, &.{arg}), |
| 4437 | 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 | } |
| 4441 | 4484 | |
| ... | ... | @@ -4445,7 +4488,7 @@ fn floatExp(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue { |
| 4445 | 4488 | .f32 => return cg.callIntrinsic(.expf, &.{.f32_type}, Type.f32, &.{arg}), |
| 4446 | 4489 | .f64 => return cg.callIntrinsic(.exp, &.{.f64_type}, Type.f64, &.{arg}), |
| 4447 | 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 | } |
| 4451 | 4494 | |
| ... | ... | @@ -4455,7 +4498,7 @@ fn floatExp2(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue { |
| 4455 | 4498 | .f32 => return cg.callIntrinsic(.exp2f, &.{.f32_type}, Type.f32, &.{arg}), |
| 4456 | 4499 | .f64 => return cg.callIntrinsic(.exp2, &.{.f64_type}, Type.f64, &.{arg}), |
| 4457 | 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 | } |
| 4461 | 4504 | |
| ... | ... | @@ -4465,7 +4508,7 @@ fn floatLog(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue { |
| 4465 | 4508 | .f32 => return cg.callIntrinsic(.logf, &.{.f32_type}, Type.f32, &.{arg}), |
| 4466 | 4509 | .f64 => return cg.callIntrinsic(.log, &.{.f64_type}, Type.f64, &.{arg}), |
| 4467 | 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 | } |
| 4471 | 4514 | |
| ... | ... | @@ -4475,7 +4518,7 @@ fn floatLog2(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue { |
| 4475 | 4518 | .f32 => return cg.callIntrinsic(.log2f, &.{.f32_type}, Type.f32, &.{arg}), |
| 4476 | 4519 | .f64 => return cg.callIntrinsic(.log2, &.{.f64_type}, Type.f64, &.{arg}), |
| 4477 | 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 | } |
| 4481 | 4524 | |
| ... | ... | @@ -4485,7 +4528,7 @@ fn floatLog10(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue { |
| 4485 | 4528 | .f32 => return cg.callIntrinsic(.log10f, &.{.f32_type}, Type.f32, &.{arg}), |
| 4486 | 4529 | .f64 => return cg.callIntrinsic(.log10, &.{.f64_type}, Type.f64, &.{arg}), |
| 4487 | 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 | } |
| 4491 | 4534 | |
| ... | ... | @@ -4503,7 +4546,7 @@ fn floatFloor(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue { |
| 4503 | 4546 | return .stack; |
| 4504 | 4547 | }, |
| 4505 | 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 | } |
| 4509 | 4552 | |
| ... | ... | @@ -4521,7 +4564,7 @@ fn floatCeil(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue { |
| 4521 | 4564 | return .stack; |
| 4522 | 4565 | }, |
| 4523 | 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 | } |
| 4527 | 4570 | |
| ... | ... | @@ -4539,7 +4582,7 @@ fn floatRound(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue { |
| 4539 | 4582 | return .stack; |
| 4540 | 4583 | }, |
| 4541 | 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 | } |
| 4545 | 4588 | |
| ... | ... | @@ -4557,7 +4600,7 @@ fn floatTrunc(cg: *CodeGen, ty: FloatType, arg: WValue) InnerError!WValue { |
| 4557 | 4600 | return .stack; |
| 4558 | 4601 | }, |
| 4559 | 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 | } |
| 4563 | 4606 | |
| ... | ... | @@ -4929,7 +4972,8 @@ fn lowerPtr(cg: *CodeGen, ptr_val: InternPool.Index, prev_offset: u64) InnerErro |
| 4929 | 4972 | const ptr = zcu.intern_pool.indexToKey(ptr_val).ptr; |
| 4930 | 4973 | const offset: u64 = prev_offset + ptr.byte_offset; |
| 4931 | 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 | 4977 | .{ .nav_ref = .{ .nav_index = nav, .offset = @intCast(offset) } } |
| 4934 | 4978 | else |
| 4935 | 4979 | .{ .imm32 = @intCast(zcu.navAlignment(nav).forward(@as(u32, 0xaaaaaaaa))) }, |
| ... | ... | @@ -5613,6 +5657,8 @@ fn bitcastClass(cg: *CodeGen, ty: Type) BitcastClass { |
| 5613 | 5657 | } |
| 5614 | 5658 | |
| 5615 | 5659 | fn bitcast(cg: *CodeGen, dest_ty: Type, src_ty: Type, operand: WValue) InnerError!?WValue { |
| 5660 | if (dest_ty.eql(src_ty)) return null; | |
| 5661 | ||
| 5616 | 5662 | const zcu = cg.pt.zcu; |
| 5617 | 5663 | const src_class = cg.bitcastClass(src_ty); |
| 5618 | 5664 | const dest_class = cg.bitcastClass(dest_ty); |
src/codegen/wasm/Emit.zig+125-49| ... | ... | @@ -21,7 +21,7 @@ pub const Error = error{ |
| 21 | 21 | OutOfMemory, |
| 22 | 22 | }; |
| 23 | 23 | |
| 24 | pub fn lowerToCode(emit: *Emit) Error!void { | |
| 24 | pub fn lower(emit: *Emit) Error!void { | |
| 25 | 25 | const mir = &emit.mir; |
| 26 | 26 | const code = emit.code; |
| 27 | 27 | const wasm = emit.wasm; |
| ... | ... | @@ -31,6 +31,47 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 31 | 31 | const target = &comp.root_mod.resolved_target.result; |
| 32 | 32 | const is_wasm32 = target.cpu.arch == .wasm32; |
| 33 | 33 | |
| 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 | 75 | const tags = mir.instructions.items(.tag); |
| 35 | 76 | const datas = mir.instructions.items(.data); |
| 36 | 77 | var inst: u32 = 0; |
| ... | ... | @@ -78,14 +119,21 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 78 | 119 | continue :loop tags[inst]; |
| 79 | 120 | }, |
| 80 | 121 | .func_ref => { |
| 81 | const indirect_func_idx: Wasm.ZcuIndirectFunctionSetIndex = @fromBackingInt(@intCast( | |
| 82 | wasm.zcu_indirect_function_set.getIndex(datas[inst].nav_index).?, | |
| 83 | )); | |
| 84 | code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.i32_const)); | |
| 122 | try code.ensureUnusedCapacity(gpa, 11); | |
| 123 | const opcode: std.wasm.Opcode = if (is_wasm32) .i32_const else .i64_const; | |
| 124 | code.appendAssumeCapacity(@backingInt(opcode)); | |
| 85 | 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 | 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 | 138 | inst += 1; |
| 91 | 139 | continue :loop tags[inst]; |
| ... | ... | @@ -105,18 +153,17 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 105 | 153 | continue :loop tags[inst]; |
| 106 | 154 | }, |
| 107 | 155 | .error_name_table_ref => { |
| 108 | wasm.error_name_table_ref_count += 1; | |
| 109 | 156 | try code.ensureUnusedCapacity(gpa, 11); |
| 110 | 157 | const opcode: std.wasm.Opcode = if (is_wasm32) .i32_const else .i64_const; |
| 111 | 158 | code.appendAssumeCapacity(@backingInt(opcode)); |
| 112 | 159 | if (is_obj) { |
| 113 | try wasm.out_relocs.append(gpa, .{ | |
| 160 | try wasm.zcu_relocations.append(gpa, .{ | |
| 114 | 161 | .offset = @intCast(code.items.len), |
| 115 | .pointee = .{ .symbol_index = try wasm.errorNameTableSymbolIndex() }, | |
| 116 | .tag = if (is_wasm32) .memory_addr_leb else .memory_addr_leb64, | |
| 162 | .pointee = .{ .data_resolution = .__zig_error_name_table }, | |
| 163 | .tag = if (is_wasm32) .memory_addr_sleb else .memory_addr_sleb64, | |
| 117 | 164 | .addend = 0, |
| 118 | 165 | }); |
| 119 | code.appendNTimesAssumeCapacity(0, if (is_wasm32) 5 else 10); | |
| 166 | appendSlebRelocPlaceholder(code, is_wasm32); | |
| 120 | 167 | |
| 121 | 168 | inst += 1; |
| 122 | 169 | continue :loop tags[inst]; |
| ... | ... | @@ -164,13 +211,13 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 164 | 211 | try code.ensureUnusedCapacity(gpa, 6); |
| 165 | 212 | code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.call)); |
| 166 | 213 | if (is_obj) { |
| 167 | try wasm.out_relocs.append(gpa, .{ | |
| 214 | try wasm.zcu_relocations.append(gpa, .{ | |
| 168 | 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 | 217 | .tag = .function_index_leb, |
| 171 | 218 | .addend = 0, |
| 172 | 219 | }); |
| 173 | code.appendNTimesAssumeCapacity(0, 5); | |
| 220 | appendUlebRelocPlaceholder(code); | |
| 174 | 221 | } else { |
| 175 | 222 | appendOutputFunctionIndex(code, .fromIpNav(wasm, datas[inst].nav_index)); |
| 176 | 223 | } |
| ... | ... | @@ -191,13 +238,13 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 191 | 238 | ).?; |
| 192 | 239 | if (is_obj) { |
| 193 | 240 | code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.call_indirect)); |
| 194 | try wasm.out_relocs.append(gpa, .{ | |
| 241 | try wasm.zcu_relocations.append(gpa, .{ | |
| 195 | 242 | .offset = @intCast(code.items.len), |
| 196 | 243 | .pointee = .{ .type_index = func_ty_index }, |
| 197 | 244 | .tag = .type_index_leb, |
| 198 | 245 | .addend = 0, |
| 199 | 246 | }); |
| 200 | code.appendNTimesAssumeCapacity(0, 5); | |
| 247 | appendUlebRelocPlaceholder(code); | |
| 201 | 248 | } else { |
| 202 | 249 | const index: Wasm.Flush.FuncTypeIndex = @fromBackingInt(@intCast(wasm.flush_buffer.func_types.getIndex(func_ty_index) orelse { |
| 203 | 250 | // In this case we tried to call a function pointer for |
| ... | ... | @@ -224,13 +271,13 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 224 | 271 | try code.ensureUnusedCapacity(gpa, 6); |
| 225 | 272 | code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.call)); |
| 226 | 273 | if (is_obj) { |
| 227 | try wasm.out_relocs.append(gpa, .{ | |
| 274 | try wasm.zcu_relocations.append(gpa, .{ | |
| 228 | 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 | 277 | .tag = .function_index_leb, |
| 231 | 278 | .addend = 0, |
| 232 | 279 | }); |
| 233 | code.appendNTimesAssumeCapacity(0, 5); | |
| 280 | appendUlebRelocPlaceholder(code); | |
| 234 | 281 | } else { |
| 235 | 282 | appendOutputFunctionIndex(code, .fromTagIndexType(wasm, datas[inst].ip_index)); |
| 236 | 283 | } |
| ... | ... | @@ -244,14 +291,20 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 244 | 291 | const opcode: std.wasm.Opcode = if (is_wasm32) .i32_const else .i64_const; |
| 245 | 292 | code.appendAssumeCapacity(@backingInt(opcode)); |
| 246 | 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 | 301 | } else { |
| 249 | 302 | const addr: u32 = wasm.tagIndexTableAddr(datas[inst].ip_index); |
| 250 | 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 | }, |
| 256 | 309 | |
| 257 | 310 | .call_intrinsic => { |
| ... | ... | @@ -263,13 +316,13 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 263 | 316 | try code.ensureUnusedCapacity(gpa, 6); |
| 264 | 317 | code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.call)); |
| 265 | 318 | if (is_obj) { |
| 266 | try wasm.out_relocs.append(gpa, .{ | |
| 319 | try wasm.zcu_relocations.append(gpa, .{ | |
| 267 | 320 | .offset = @intCast(code.items.len), |
| 268 | .pointee = .{ .symbol_index = try wasm.symbolNameIndex(symbol_name) }, | |
| 321 | .pointee = .{ .function_name = symbol_name }, | |
| 269 | 322 | .tag = .function_index_leb, |
| 270 | 323 | .addend = 0, |
| 271 | 324 | }); |
| 272 | code.appendNTimesAssumeCapacity(0, 5); | |
| 325 | appendUlebRelocPlaceholder(code); | |
| 273 | 326 | } else { |
| 274 | 327 | appendOutputFunctionIndex(code, .fromSymbolName(wasm, symbol_name)); |
| 275 | 328 | } |
| ... | ... | @@ -281,18 +334,7 @@ pub fn lowerToCode(emit: *Emit) Error!void { |
| 281 | 334 | .global_set_sp => { |
| 282 | 335 | try code.ensureUnusedCapacity(gpa, 6); |
| 283 | 336 | code.appendAssumeCapacity(@backingInt(std.wasm.Opcode.global_set)); |
| 284 | if (is_obj) { | |
| 285 | try wasm.out_relocs.append(gpa, .{ | |
| 286 | .offset = @intCast(code.items.len), | |
| 287 | .pointee = .{ .symbol_index = try wasm.stackPointerSymbolIndex() }, | |
| 288 | .tag = .global_index_leb, | |
| 289 | .addend = 0, | |
| 290 | }); | |
| 291 | code.appendNTimesAssumeCapacity(0, 5); | |
| 292 | } else { | |
| 293 | const sp_global: Wasm.GlobalIndex = .stack_pointer; | |
| 294 | writeUleb128(code, @backingInt(sp_global)); | |
| 295 | } | |
| 337 | try appendStackPointerGlobalIndex(wasm, code, is_obj); | |
| 296 | 338 | |
| 297 | 339 | inst += 1; |
| 298 | 340 | continue :loop tags[inst]; |
| ... | ... | @@ -960,13 +1002,13 @@ fn uavRefObj(wasm: *Wasm, code: *ArrayList(u8), value: InternPool.Index, offset: |
| 960 | 1002 | try code.ensureUnusedCapacity(gpa, 11); |
| 961 | 1003 | code.appendAssumeCapacity(@backingInt(opcode)); |
| 962 | 1004 | |
| 963 | try wasm.out_relocs.append(gpa, .{ | |
| 1005 | try wasm.zcu_relocations.append(gpa, .{ | |
| 964 | 1006 | .offset = @intCast(code.items.len), |
| 965 | .pointee = .{ .symbol_index = try wasm.uavSymbolIndex(value) }, | |
| 966 | .tag = if (is_wasm32) .memory_addr_leb else .memory_addr_leb64, | |
| 1007 | .pointee = .{ .data_uav = value }, | |
| 1008 | .tag = if (is_wasm32) .memory_addr_sleb else .memory_addr_sleb64, | |
| 967 | 1009 | .addend = offset, |
| 968 | 1010 | }); |
| 969 | code.appendNTimesAssumeCapacity(0, if (is_wasm32) 5 else 10); | |
| 1011 | appendSlebRelocPlaceholder(code, is_wasm32); | |
| 970 | 1012 | } |
| 971 | 1013 | |
| 972 | 1014 | fn 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 | 1020 | code.appendAssumeCapacity(@backingInt(opcode)); |
| 979 | 1021 | |
| 980 | 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 | } |
| 983 | 1025 | |
| 984 | 1026 | fn 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 | 1037 | const opcode: std.wasm.Opcode = if (is_wasm32) .i32_const else .i64_const; |
| 996 | 1038 | code.appendAssumeCapacity(@backingInt(opcode)); |
| 997 | 1039 | if (is_obj) { |
| 998 | try wasm.out_relocs.append(gpa, .{ | |
| 1040 | try wasm.zcu_relocations.append(gpa, .{ | |
| 999 | 1041 | .offset = @intCast(code.items.len), |
| 1000 | .pointee = .{ .symbol_index = try wasm.navSymbolIndex(data.nav_index) }, | |
| 1001 | .tag = if (is_wasm32) .memory_addr_leb else .memory_addr_leb64, | |
| 1042 | .pointee = .{ .data_nav = data.nav_index }, | |
| 1043 | .tag = if (is_wasm32) .memory_addr_sleb else .memory_addr_sleb64, | |
| 1002 | 1044 | .addend = data.offset, |
| 1003 | 1045 | }); |
| 1004 | code.appendNTimesAssumeCapacity(0, if (is_wasm32) 5 else 10); | |
| 1046 | appendSlebRelocPlaceholder(code, is_wasm32); | |
| 1005 | 1047 | } else { |
| 1006 | 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 | } |
| 1010 | 1052 | |
| ... | ... | @@ -1012,6 +1054,40 @@ fn appendOutputFunctionIndex(code: *ArrayList(u8), i: Wasm.OutputFunctionIndex) |
| 1012 | 1054 | writeUleb128(code, @backingInt(i)); |
| 1013 | 1055 | } |
| 1014 | 1056 | |
| 1057 | fn 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 | ||
| 1076 | fn appendUlebRelocPlaceholder(code: *ArrayList(u8)) void { | |
| 1077 | code.appendSliceAssumeCapacity(&.{ 0x80, 0x80, 0x80, 0x80, 0x00 }); | |
| 1078 | } | |
| 1079 | ||
| 1080 | fn 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 | ||
| 1015 | 1091 | fn writeUleb128(code: *ArrayList(u8), arg: anytype) void { |
| 1016 | 1092 | var w: std.Io.Writer = .fixed(code.unusedCapacitySlice()); |
| 1017 | 1093 | w.writeUleb128(arg) catch unreachable; |
src/codegen/wasm/Mir.zig+22-70| ... | ... | @@ -114,7 +114,7 @@ pub const Inst = struct { |
| 114 | 114 | /// |
| 115 | 115 | /// Uses `payload` pointing to a `NavRefOff`. |
| 116 | 116 | nav_ref_off, |
| 117 | /// Lowers to an i32_const which is the index of the function in the | |
| 117 | /// Lowers to an iNN_const which is the index of the function in the | |
| 118 | 118 | /// table section. |
| 119 | 119 | /// |
| 120 | 120 | /// Uses `nav_index`. |
| ... | ... | @@ -661,8 +661,8 @@ pub const Inst = struct { |
| 661 | 661 | |
| 662 | 662 | comptime { |
| 663 | 663 | switch (builtin.mode) { |
| 664 | .Debug, .ReleaseSafe => {}, | |
| 665 | .ReleaseFast, .ReleaseSmall => assert(@sizeOf(Data) == 4), | |
| 664 | .debug, .safe => {}, | |
| 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 | 679 | } |
| 680 | 680 | |
| 681 | 681 | pub 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 | 682 | var emit: Emit = .{ |
| 731 | 683 | .mir = mir.*, |
| 732 | 684 | .wasm = wasm, |
| 733 | 685 | .code = code, |
| 734 | 686 | }; |
| 735 | try emit.lowerToCode(); | |
| 687 | try emit.lower(); | |
| 736 | 688 | } |
| 737 | 689 | |
| 738 | 690 | pub 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 | 943 | __udivti3, |
| 992 | 944 | __umodei5, |
| 993 | 945 | __umodti3, |
| 994 | ceilq, | |
| 946 | ceilf128, | |
| 995 | 947 | cos, |
| 996 | 948 | cosf, |
| 997 | cosq, | |
| 949 | cosf128, | |
| 998 | 950 | exp, |
| 999 | 951 | exp2, |
| 1000 | 952 | exp2f, |
| 1001 | exp2q, | |
| 953 | exp2f128, | |
| 1002 | 954 | expf, |
| 1003 | expq, | |
| 1004 | fabsq, | |
| 1005 | floorq, | |
| 955 | expf128, | |
| 956 | fabsf128, | |
| 957 | floorf128, | |
| 1006 | 958 | fma, |
| 1007 | 959 | fmaf, |
| 1008 | fmaq, | |
| 960 | fmaf128, | |
| 1009 | 961 | fmax, |
| 1010 | 962 | fmaxf, |
| 1011 | fmaxq, | |
| 963 | fmaxf128, | |
| 1012 | 964 | fmin, |
| 1013 | 965 | fminf, |
| 1014 | fminq, | |
| 966 | fminf128, | |
| 1015 | 967 | fmod, |
| 1016 | 968 | fmodf, |
| 1017 | fmodq, | |
| 969 | fmodf128, | |
| 1018 | 970 | log, |
| 1019 | 971 | log10, |
| 1020 | 972 | log10f, |
| 1021 | log10q, | |
| 973 | log10f128, | |
| 1022 | 974 | log2, |
| 1023 | 975 | log2f, |
| 1024 | log2q, | |
| 976 | log2f128, | |
| 1025 | 977 | logf, |
| 1026 | logq, | |
| 1027 | roundq, | |
| 978 | logf128, | |
| 979 | roundf128, | |
| 1028 | 980 | sin, |
| 1029 | 981 | sinf, |
| 1030 | sinq, | |
| 1031 | sqrtq, | |
| 982 | sinf128, | |
| 983 | sqrtf128, | |
| 1032 | 984 | tan, |
| 1033 | 985 | tanf, |
| 1034 | tanq, | |
| 1035 | truncq, | |
| 986 | tanf128, | |
| 987 | truncf128, | |
| 1036 | 988 | memcpy, |
| 1037 | 989 | memmove, |
| 1038 | 990 | memset, |
src/codegen/wasm/abi.zig+72-22| ... | ... | @@ -11,21 +11,53 @@ const assert = std.debug.assert; |
| 11 | 11 | const Type = @import("../../Type.zig"); |
| 12 | 12 | const Zcu = @import("../../Zcu.zig"); |
| 13 | 13 | |
| 14 | /// Defines how to pass a type as part of a function signature, | |
| 15 | /// both for parameters as well as return values. | |
| 14 | /// Describes how the Wasm backend represents a C ABI value. | |
| 16 | 15 | pub const Class = union(enum) { |
| 17 | 16 | direct: Type, |
| 17 | double_i64, | |
| 18 | 18 | indirect, |
| 19 | unrolled: struct { | |
| 20 | elem_type: Type, | |
| 21 | len: u32, | |
| 22 | }, | |
| 19 | 23 | }; |
| 20 | 24 | |
| 21 | /// Classifies a given Zig type to determine how they must be passed | |
| 22 | /// or returned as value within a wasm function. | |
| 23 | pub fn classifyType(ty: Type, zcu: *const Zcu) Class { | |
| 25 | pub const LlvmClass = union(enum) { | |
| 26 | direct: Type, | |
| 27 | indirect, | |
| 28 | }; | |
| 29 | ||
| 30 | pub 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 | ||
| 51 | pub fn classifyTypeForLlvm(ty: Type, zcu: *const Zcu) LlvmClass { | |
| 24 | 52 | const ip = &zcu.intern_pool; |
| 25 | 53 | assert(ty.hasRuntimeBits(zcu)); |
| 26 | 54 | switch (ty.zigTypeTag(zcu)) { |
| 27 | 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 | 61 | .bool => return .{ .direct = ty }, |
| 30 | 62 | .vector => return .{ .direct = ty }, |
| 31 | 63 | .array => return .indirect, |
| ... | ... | @@ -39,20 +71,35 @@ pub fn classifyType(ty: Type, zcu: *const Zcu) Class { |
| 39 | 71 | }, |
| 40 | 72 | .@"struct" => { |
| 41 | 73 | const struct_type = zcu.typeToStruct(ty).?; |
| 42 | if (struct_type.layout == .@"packed") { | |
| 43 | return .{ .direct = ty }; | |
| 44 | } | |
| 45 | if (struct_type.field_types.len > 1) { | |
| 46 | // The struct type is non-scalar. | |
| 47 | return .indirect; | |
| 74 | switch (struct_type.layout) { | |
| 75 | .auto => unreachable, | |
| 76 | .@"packed" => return .{ .direct = ty }, | |
| 77 | .@"extern" => {}, | |
| 48 | 78 | } |
| 49 | const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[0]); | |
| 50 | const explicit_align = struct_type.field_aligns.getOrNone(ip, 0); | |
| 51 | if (explicit_align != .none) { | |
| 52 | if (explicit_align.compareStrict(.gt, field_ty.abiAlignment(zcu))) | |
| 79 | var opt_single_field_ty: ?Type = null; | |
| 80 | for (struct_type.field_types.get(ip), 0..) |field_ty_index, field_index| { | |
| 81 | const field_ty: Type = .fromInterned(field_ty_index); | |
| 82 | if (!field_ty.hasRuntimeBits(zcu)) continue; | |
| 83 | ||
| 84 | if (opt_single_field_ty != null) { | |
| 85 | return .indirect; | |
| 86 | } | |
| 87 | ||
| 88 | const field_align = struct_type.field_aligns.getOrNone(ip, field_index); | |
| 89 | if (field_align != .none and field_align.compareStrict(.gt, field_ty.abiAlignment(zcu))) { | |
| 53 | 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 | 104 | .@"union" => { |
| 58 | 105 | const union_obj = zcu.typeToUnion(ty).?; |
| ... | ... | @@ -63,7 +110,14 @@ pub fn classifyType(ty: Type, zcu: *const Zcu) Class { |
| 63 | 110 | assert(layout.tag_size == 0); |
| 64 | 111 | if (union_obj.field_types.len > 1) return .indirect; |
| 65 | 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 | 122 | .error_union, |
| 69 | 123 | .frame, |
| ... | ... | @@ -82,7 +136,3 @@ pub fn classifyType(ty: Type, zcu: *const Zcu) Class { |
| 82 | 136 | => unreachable, |
| 83 | 137 | } |
| 84 | 138 | } |
| 85 | ||
| 86 | pub 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 | 1301 | } |
| 1302 | 1302 | |
| 1303 | 1303 | fn 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 | 1305 | try self.mir_extra.ensureUnusedCapacity(self.gpa, field_count); |
| 1306 | 1306 | return self.addExtraAssumeCapacity(extra); |
| 1307 | 1307 | } |
| ... | ... | @@ -2152,7 +2152,7 @@ fn gen( |
| 2152 | 2152 | |
| 2153 | 2153 | const epilogue = if (self.epilogue_relocs.items.len > 0) epilogue: { |
| 2154 | 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 | 2156 | self.epilogue_relocs.items.len -= 1; |
| 2157 | 2157 | self.mir_instructions.set(last_inst, .{ |
| 2158 | 2158 | .tag = .pseudo, |
| ... | ... | @@ -34436,7 +34436,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 34436 | 34436 | .call_frame = .{ .alignment = .@"16" }, |
| 34437 | 34437 | .extra_temps = .{ |
| 34438 | 34438 | .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, |
| 34439 | .{ .type = .usize, .kind = .{ .extern_func = "truncq" } }, | |
| 34439 | .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } }, | |
| 34440 | 34440 | .unused, |
| 34441 | 34441 | .unused, |
| 34442 | 34442 | .unused, |
| ... | ... | @@ -34470,7 +34470,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 34470 | 34470 | .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, |
| 34471 | 34471 | .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, |
| 34472 | 34472 | .{ .type = .f128, .kind = .mem }, |
| 34473 | .{ .type = .usize, .kind = .{ .extern_func = "truncq" } }, | |
| 34473 | .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } }, | |
| 34474 | 34474 | .unused, |
| 34475 | 34475 | .unused, |
| 34476 | 34476 | .unused, |
| ... | ... | @@ -34505,7 +34505,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 34505 | 34505 | .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, |
| 34506 | 34506 | .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, |
| 34507 | 34507 | .{ .type = .f128, .kind = .mem }, |
| 34508 | .{ .type = .usize, .kind = .{ .extern_func = "truncq" } }, | |
| 34508 | .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } }, | |
| 34509 | 34509 | .unused, |
| 34510 | 34510 | .unused, |
| 34511 | 34511 | .unused, |
| ... | ... | @@ -34540,7 +34540,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 34540 | 34540 | .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, |
| 34541 | 34541 | .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, |
| 34542 | 34542 | .{ .type = .f128, .kind = .mem }, |
| 34543 | .{ .type = .usize, .kind = .{ .extern_func = "truncq" } }, | |
| 34543 | .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } }, | |
| 34544 | 34544 | .unused, |
| 34545 | 34545 | .unused, |
| 34546 | 34546 | .unused, |
| ... | ... | @@ -34575,7 +34575,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 34575 | 34575 | .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 34576 | 34576 | .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, |
| 34577 | 34577 | .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, |
| 34578 | .{ .type = .usize, .kind = .{ .extern_func = "truncq" } }, | |
| 34578 | .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } }, | |
| 34579 | 34579 | .unused, |
| 34580 | 34580 | .unused, |
| 34581 | 34581 | .unused, |
| ... | ... | @@ -34612,7 +34612,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 34612 | 34612 | .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 34613 | 34613 | .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, |
| 34614 | 34614 | .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, |
| 34615 | .{ .type = .usize, .kind = .{ .extern_func = "truncq" } }, | |
| 34615 | .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } }, | |
| 34616 | 34616 | .unused, |
| 34617 | 34617 | .unused, |
| 34618 | 34618 | .unused, |
| ... | ... | @@ -34649,7 +34649,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 34649 | 34649 | .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 34650 | 34650 | .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, |
| 34651 | 34651 | .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, |
| 34652 | .{ .type = .usize, .kind = .{ .extern_func = "truncq" } }, | |
| 34652 | .{ .type = .usize, .kind = .{ .extern_func = "truncf128" } }, | |
| 34653 | 34653 | .unused, |
| 34654 | 34654 | .unused, |
| 34655 | 34655 | .unused, |
| ... | ... | @@ -34688,7 +34688,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 34688 | 34688 | .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, |
| 34689 | 34689 | .{ .type = .f128, .kind = .mem }, |
| 34690 | 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 | 34692 | .unused, |
| 34693 | 34693 | .unused, |
| 34694 | 34694 | .unused, |
| ... | ... | @@ -34727,7 +34727,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 34727 | 34727 | .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, |
| 34728 | 34728 | .{ .type = .f128, .kind = .mem }, |
| 34729 | 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 | 34731 | .unused, |
| 34732 | 34732 | .unused, |
| 34733 | 34733 | .unused, |
| ... | ... | @@ -34766,7 +34766,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 34766 | 34766 | .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, |
| 34767 | 34767 | .{ .type = .f128, .kind = .mem }, |
| 34768 | 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 | 34770 | .unused, |
| 34771 | 34771 | .unused, |
| 34772 | 34772 | .unused, |
| ... | ... | @@ -35960,8 +35960,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 35960 | 35960 | .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, |
| 35961 | 35961 | .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { |
| 35962 | 35962 | else => unreachable, |
| 35963 | .zero => "truncq", | |
| 35964 | .down => "floorq", | |
| 35963 | .zero => "truncf128", | |
| 35964 | .down => "floorf128", | |
| 35965 | 35965 | } } }, |
| 35966 | 35966 | .unused, |
| 35967 | 35967 | .unused, |
| ... | ... | @@ -35998,8 +35998,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 35998 | 35998 | .{ .type = .f128, .kind = .mem }, |
| 35999 | 35999 | .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { |
| 36000 | 36000 | else => unreachable, |
| 36001 | .zero => "truncq", | |
| 36002 | .down => "floorq", | |
| 36001 | .zero => "truncf128", | |
| 36002 | .down => "floorf128", | |
| 36003 | 36003 | } } }, |
| 36004 | 36004 | .unused, |
| 36005 | 36005 | .unused, |
| ... | ... | @@ -36037,8 +36037,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 36037 | 36037 | .{ .type = .f128, .kind = .mem }, |
| 36038 | 36038 | .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { |
| 36039 | 36039 | else => unreachable, |
| 36040 | .zero => "truncq", | |
| 36041 | .down => "floorq", | |
| 36040 | .zero => "truncf128", | |
| 36041 | .down => "floorf128", | |
| 36042 | 36042 | } } }, |
| 36043 | 36043 | .unused, |
| 36044 | 36044 | .unused, |
| ... | ... | @@ -36076,8 +36076,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 36076 | 36076 | .{ .type = .f128, .kind = .mem }, |
| 36077 | 36077 | .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { |
| 36078 | 36078 | else => unreachable, |
| 36079 | .zero => "truncq", | |
| 36080 | .down => "floorq", | |
| 36079 | .zero => "truncf128", | |
| 36080 | .down => "floorf128", | |
| 36081 | 36081 | } } }, |
| 36082 | 36082 | .unused, |
| 36083 | 36083 | .unused, |
| ... | ... | @@ -36115,8 +36115,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 36115 | 36115 | .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, |
| 36116 | 36116 | .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { |
| 36117 | 36117 | else => unreachable, |
| 36118 | .zero => "truncq", | |
| 36119 | .down => "floorq", | |
| 36118 | .zero => "truncf128", | |
| 36119 | .down => "floorf128", | |
| 36120 | 36120 | } } }, |
| 36121 | 36121 | .unused, |
| 36122 | 36122 | .unused, |
| ... | ... | @@ -36156,8 +36156,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 36156 | 36156 | .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, |
| 36157 | 36157 | .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { |
| 36158 | 36158 | else => unreachable, |
| 36159 | .zero => "truncq", | |
| 36160 | .down => "floorq", | |
| 36159 | .zero => "truncf128", | |
| 36160 | .down => "floorf128", | |
| 36161 | 36161 | } } }, |
| 36162 | 36162 | .unused, |
| 36163 | 36163 | .unused, |
| ... | ... | @@ -36197,8 +36197,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 36197 | 36197 | .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, |
| 36198 | 36198 | .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { |
| 36199 | 36199 | else => unreachable, |
| 36200 | .zero => "truncq", | |
| 36201 | .down => "floorq", | |
| 36200 | .zero => "truncf128", | |
| 36201 | .down => "floorf128", | |
| 36202 | 36202 | } } }, |
| 36203 | 36203 | .unused, |
| 36204 | 36204 | .unused, |
| ... | ... | @@ -36240,8 +36240,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 36240 | 36240 | .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 36241 | 36241 | .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { |
| 36242 | 36242 | else => unreachable, |
| 36243 | .zero => "truncq", | |
| 36244 | .down => "floorq", | |
| 36243 | .zero => "truncf128", | |
| 36244 | .down => "floorf128", | |
| 36245 | 36245 | } } }, |
| 36246 | 36246 | .unused, |
| 36247 | 36247 | .unused, |
| ... | ... | @@ -36283,8 +36283,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 36283 | 36283 | .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 36284 | 36284 | .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { |
| 36285 | 36285 | else => unreachable, |
| 36286 | .zero => "truncq", | |
| 36287 | .down => "floorq", | |
| 36286 | .zero => "truncf128", | |
| 36287 | .down => "floorf128", | |
| 36288 | 36288 | } } }, |
| 36289 | 36289 | .unused, |
| 36290 | 36290 | .unused, |
| ... | ... | @@ -36326,8 +36326,8 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 36326 | 36326 | .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 36327 | 36327 | .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { |
| 36328 | 36328 | else => unreachable, |
| 36329 | .zero => "truncq", | |
| 36330 | .down => "floorq", | |
| 36329 | .zero => "truncf128", | |
| 36330 | .down => "floorf128", | |
| 36331 | 36331 | } } }, |
| 36332 | 36332 | .unused, |
| 36333 | 36333 | .unused, |
| ... | ... | @@ -37691,7 +37691,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 37691 | 37691 | .call_frame = .{ .alignment = .@"16" }, |
| 37692 | 37692 | .extra_temps = .{ |
| 37693 | 37693 | .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, |
| 37694 | .{ .type = .usize, .kind = .{ .extern_func = "floorq" } }, | |
| 37694 | .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } }, | |
| 37695 | 37695 | .unused, |
| 37696 | 37696 | .unused, |
| 37697 | 37697 | .unused, |
| ... | ... | @@ -37725,7 +37725,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 37725 | 37725 | .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, |
| 37726 | 37726 | .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, |
| 37727 | 37727 | .{ .type = .f128, .kind = .mem }, |
| 37728 | .{ .type = .usize, .kind = .{ .extern_func = "floorq" } }, | |
| 37728 | .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } }, | |
| 37729 | 37729 | .unused, |
| 37730 | 37730 | .unused, |
| 37731 | 37731 | .unused, |
| ... | ... | @@ -37760,7 +37760,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 37760 | 37760 | .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, |
| 37761 | 37761 | .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, |
| 37762 | 37762 | .{ .type = .f128, .kind = .mem }, |
| 37763 | .{ .type = .usize, .kind = .{ .extern_func = "floorq" } }, | |
| 37763 | .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } }, | |
| 37764 | 37764 | .unused, |
| 37765 | 37765 | .unused, |
| 37766 | 37766 | .unused, |
| ... | ... | @@ -37795,7 +37795,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 37795 | 37795 | .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, |
| 37796 | 37796 | .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, |
| 37797 | 37797 | .{ .type = .f128, .kind = .mem }, |
| 37798 | .{ .type = .usize, .kind = .{ .extern_func = "floorq" } }, | |
| 37798 | .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } }, | |
| 37799 | 37799 | .unused, |
| 37800 | 37800 | .unused, |
| 37801 | 37801 | .unused, |
| ... | ... | @@ -37830,7 +37830,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 37830 | 37830 | .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 37831 | 37831 | .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, |
| 37832 | 37832 | .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, |
| 37833 | .{ .type = .usize, .kind = .{ .extern_func = "floorq" } }, | |
| 37833 | .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } }, | |
| 37834 | 37834 | .unused, |
| 37835 | 37835 | .unused, |
| 37836 | 37836 | .unused, |
| ... | ... | @@ -37867,7 +37867,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 37867 | 37867 | .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 37868 | 37868 | .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, |
| 37869 | 37869 | .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, |
| 37870 | .{ .type = .usize, .kind = .{ .extern_func = "floorq" } }, | |
| 37870 | .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } }, | |
| 37871 | 37871 | .unused, |
| 37872 | 37872 | .unused, |
| 37873 | 37873 | .unused, |
| ... | ... | @@ -37904,7 +37904,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 37904 | 37904 | .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 37905 | 37905 | .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, |
| 37906 | 37906 | .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, |
| 37907 | .{ .type = .usize, .kind = .{ .extern_func = "floorq" } }, | |
| 37907 | .{ .type = .usize, .kind = .{ .extern_func = "floorf128" } }, | |
| 37908 | 37908 | .unused, |
| 37909 | 37909 | .unused, |
| 37910 | 37910 | .unused, |
| ... | ... | @@ -37943,7 +37943,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 37943 | 37943 | .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, |
| 37944 | 37944 | .{ .type = .f128, .kind = .mem }, |
| 37945 | 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 | 37947 | .unused, |
| 37948 | 37948 | .unused, |
| 37949 | 37949 | .unused, |
| ... | ... | @@ -37982,7 +37982,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 37982 | 37982 | .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, |
| 37983 | 37983 | .{ .type = .f128, .kind = .mem }, |
| 37984 | 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 | 37986 | .unused, |
| 37987 | 37987 | .unused, |
| 37988 | 37988 | .unused, |
| ... | ... | @@ -38021,7 +38021,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 38021 | 38021 | .{ .type = .usize, .kind = .{ .extern_func = "__divtf3" } }, |
| 38022 | 38022 | .{ .type = .f128, .kind = .mem }, |
| 38023 | 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 | 38025 | .unused, |
| 38026 | 38026 | .unused, |
| 38027 | 38027 | .unused, |
| ... | ... | @@ -39558,7 +39558,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 39558 | 39558 | }, |
| 39559 | 39559 | .call_frame = .{ .alignment = .@"16" }, |
| 39560 | 39560 | .extra_temps = .{ |
| 39561 | .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } }, | |
| 39561 | .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } }, | |
| 39562 | 39562 | .unused, |
| 39563 | 39563 | .unused, |
| 39564 | 39564 | .unused, |
| ... | ... | @@ -39590,7 +39590,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 39590 | 39590 | .extra_temps = .{ |
| 39591 | 39591 | .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 39592 | 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 | 39594 | .unused, |
| 39595 | 39595 | .unused, |
| 39596 | 39596 | .unused, |
| ... | ... | @@ -39623,7 +39623,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 39623 | 39623 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 39624 | 39624 | .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 39625 | 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 | 39627 | .unused, |
| 39628 | 39628 | .unused, |
| 39629 | 39629 | .unused, |
| ... | ... | @@ -39659,7 +39659,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 39659 | 39659 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 39660 | 39660 | .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 39661 | 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 | 39663 | .unused, |
| 39664 | 39664 | .unused, |
| 39665 | 39665 | .unused, |
| ... | ... | @@ -39695,7 +39695,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 39695 | 39695 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 39696 | 39696 | .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 39697 | 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 | 39699 | .unused, |
| 39700 | 39700 | .unused, |
| 39701 | 39701 | .unused, |
| ... | ... | @@ -39731,7 +39731,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 39731 | 39731 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 39732 | 39732 | .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 39733 | 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 | 39735 | .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 39736 | 39736 | .unused, |
| 39737 | 39737 | .unused, |
| ... | ... | @@ -39767,7 +39767,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 39767 | 39767 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 39768 | 39768 | .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 39769 | 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 | 39771 | .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 39772 | 39772 | .unused, |
| 39773 | 39773 | .unused, |
| ... | ... | @@ -39803,7 +39803,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 39803 | 39803 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 39804 | 39804 | .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 39805 | 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 | 39807 | .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 39808 | 39808 | .unused, |
| 39809 | 39809 | .unused, |
| ... | ... | @@ -42803,7 +42803,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 42803 | 42803 | .call_frame = .{ .alignment = .@"16" }, |
| 42804 | 42804 | .extra_temps = .{ |
| 42805 | 42805 | .{ .type = .f128, .kind = .mem }, |
| 42806 | .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } }, | |
| 42806 | .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } }, | |
| 42807 | 42807 | .{ .type = .u64, .kind = .{ .reg = .rcx } }, |
| 42808 | 42808 | .{ .type = .u64, .kind = .{ .reg = .rdx } }, |
| 42809 | 42809 | .{ .type = .u64, .kind = .{ .reg = .rax } }, |
| ... | ... | @@ -42849,7 +42849,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 42849 | 42849 | .call_frame = .{ .alignment = .@"16" }, |
| 42850 | 42850 | .extra_temps = .{ |
| 42851 | 42851 | .{ .type = .f128, .kind = .mem }, |
| 42852 | .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } }, | |
| 42852 | .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } }, | |
| 42853 | 42853 | .{ .type = .u64, .kind = .{ .reg = .rcx } }, |
| 42854 | 42854 | .{ .type = .u64, .kind = .{ .reg = .rdx } }, |
| 42855 | 42855 | .{ .type = .u64, .kind = .{ .reg = .rax } }, |
| ... | ... | @@ -42895,7 +42895,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 42895 | 42895 | .call_frame = .{ .alignment = .@"16" }, |
| 42896 | 42896 | .extra_temps = .{ |
| 42897 | 42897 | .{ .type = .f128, .kind = .mem }, |
| 42898 | .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } }, | |
| 42898 | .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } }, | |
| 42899 | 42899 | .{ .type = .u64, .kind = .{ .reg = .rcx } }, |
| 42900 | 42900 | .{ .type = .u64, .kind = .{ .reg = .rdx } }, |
| 42901 | 42901 | .{ .type = .u64, .kind = .{ .reg = .rax } }, |
| ... | ... | @@ -42942,7 +42942,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 42942 | 42942 | .call_frame = .{ .alignment = .@"16" }, |
| 42943 | 42943 | .extra_temps = .{ |
| 42944 | 42944 | .{ .type = .f128, .kind = .mem }, |
| 42945 | .{ .type = .usize, .kind = .{ .extern_func = "fmodq" } }, | |
| 42945 | .{ .type = .usize, .kind = .{ .extern_func = "fmodf128" } }, | |
| 42946 | 42946 | .{ .type = .u64, .kind = .{ .reg = .rdx } }, |
| 42947 | 42947 | .{ .type = .f128, .kind = .mem }, |
| 42948 | 42948 | .{ .type = .u64, .kind = .{ .reg = .rax } }, |
| ... | ... | @@ -42984,7 +42984,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 42984 | 42984 | .extra_temps = .{ |
| 42985 | 42985 | .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 42986 | 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 | 42988 | .{ .type = .f128, .kind = .mem }, |
| 42989 | 42989 | .{ .type = .f128, .kind = .{ .reg = .xmm1 } }, |
| 42990 | 42990 | .{ .type = .u64, .kind = .{ .reg = .rax } }, |
| ... | ... | @@ -43029,7 +43029,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 43029 | 43029 | .extra_temps = .{ |
| 43030 | 43030 | .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 43031 | 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 | 43033 | .{ .type = .f128, .kind = .mem }, |
| 43034 | 43034 | .{ .type = .f128, .kind = .{ .reg = .xmm1 } }, |
| 43035 | 43035 | .{ .type = .u64, .kind = .{ .reg = .rax } }, |
| ... | ... | @@ -43074,7 +43074,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 43074 | 43074 | .extra_temps = .{ |
| 43075 | 43075 | .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 43076 | 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 | 43078 | .{ .type = .f128, .kind = .mem }, |
| 43079 | 43079 | .{ .type = .f128, .kind = .{ .reg = .xmm1 } }, |
| 43080 | 43080 | .{ .type = .u64, .kind = .{ .reg = .rax } }, |
| ... | ... | @@ -43120,7 +43120,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 43120 | 43120 | .extra_temps = .{ |
| 43121 | 43121 | .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 43122 | 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 | 43124 | .{ .type = .f128, .kind = .mem }, |
| 43125 | 43125 | .{ .type = .usize, .kind = .{ .reg = .rax } }, |
| 43126 | 43126 | .{ .type = .usize, .kind = .{ .extern_func = "__addtf3" } }, |
| ... | ... | @@ -43164,7 +43164,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 43164 | 43164 | .{ .type = .isize, .kind = .{ .rc = .general_purpose } }, |
| 43165 | 43165 | .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 43166 | 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 | 43168 | .{ .type = .f128, .kind = .{ .reg = .rcx } }, |
| 43169 | 43169 | .{ .type = .f128, .kind = .{ .reg = .rdx } }, |
| 43170 | 43170 | .{ .type = .f128, .kind = .{ .reg = .rax } }, |
| ... | ... | @@ -43211,7 +43211,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 43211 | 43211 | .{ .type = .isize, .kind = .{ .rc = .general_purpose } }, |
| 43212 | 43212 | .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 43213 | 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 | 43215 | .{ .type = .f128, .kind = .{ .reg = .rcx } }, |
| 43216 | 43216 | .{ .type = .f128, .kind = .{ .reg = .rdx } }, |
| 43217 | 43217 | .{ .type = .f128, .kind = .{ .reg = .rax } }, |
| ... | ... | @@ -43258,7 +43258,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 43258 | 43258 | .{ .type = .isize, .kind = .{ .rc = .general_purpose } }, |
| 43259 | 43259 | .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 43260 | 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 | 43262 | .{ .type = .f128, .kind = .{ .reg = .rcx } }, |
| 43263 | 43263 | .{ .type = .f128, .kind = .{ .reg = .rdx } }, |
| 43264 | 43264 | .{ .type = .f128, .kind = .{ .reg = .rax } }, |
| ... | ... | @@ -43306,7 +43306,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 43306 | 43306 | .{ .type = .isize, .kind = .{ .rc = .general_purpose } }, |
| 43307 | 43307 | .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 43308 | 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 | 43310 | .{ .type = .f128, .kind = .{ .reg = .rdx } }, |
| 43311 | 43311 | .{ .type = .f128, .kind = .mem }, |
| 43312 | 43312 | .{ .type = .f128, .kind = .{ .reg = .rax } }, |
| ... | ... | @@ -47623,7 +47623,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 47623 | 47623 | }, |
| 47624 | 47624 | .call_frame = .{ .alignment = .@"16" }, |
| 47625 | 47625 | .extra_temps = .{ |
| 47626 | .{ .type = .usize, .kind = .{ .extern_func = "fmaxq" } }, | |
| 47626 | .{ .type = .usize, .kind = .{ .extern_func = "fmaxf128" } }, | |
| 47627 | 47627 | .unused, |
| 47628 | 47628 | .unused, |
| 47629 | 47629 | .unused, |
| ... | ... | @@ -47655,7 +47655,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 47655 | 47655 | .extra_temps = .{ |
| 47656 | 47656 | .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 47657 | 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 | 47659 | .unused, |
| 47660 | 47660 | .unused, |
| 47661 | 47661 | .unused, |
| ... | ... | @@ -47688,7 +47688,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 47688 | 47688 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 47689 | 47689 | .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 47690 | 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 | 47692 | .unused, |
| 47693 | 47693 | .unused, |
| 47694 | 47694 | .unused, |
| ... | ... | @@ -47724,7 +47724,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 47724 | 47724 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 47725 | 47725 | .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 47726 | 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 | 47728 | .unused, |
| 47729 | 47729 | .unused, |
| 47730 | 47730 | .unused, |
| ... | ... | @@ -47760,7 +47760,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 47760 | 47760 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 47761 | 47761 | .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 47762 | 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 | 47764 | .unused, |
| 47765 | 47765 | .unused, |
| 47766 | 47766 | .unused, |
| ... | ... | @@ -47796,7 +47796,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 47796 | 47796 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 47797 | 47797 | .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 47798 | 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 | 47800 | .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 47801 | 47801 | .unused, |
| 47802 | 47802 | .unused, |
| ... | ... | @@ -47832,7 +47832,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 47832 | 47832 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 47833 | 47833 | .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 47834 | 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 | 47836 | .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 47837 | 47837 | .unused, |
| 47838 | 47838 | .unused, |
| ... | ... | @@ -47868,7 +47868,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 47868 | 47868 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 47869 | 47869 | .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 47870 | 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 | 47872 | .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 47873 | 47873 | .unused, |
| 47874 | 47874 | .unused, |
| ... | ... | @@ -51926,7 +51926,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 51926 | 51926 | }, |
| 51927 | 51927 | .call_frame = .{ .alignment = .@"16" }, |
| 51928 | 51928 | .extra_temps = .{ |
| 51929 | .{ .type = .usize, .kind = .{ .extern_func = "fminq" } }, | |
| 51929 | .{ .type = .usize, .kind = .{ .extern_func = "fminf128" } }, | |
| 51930 | 51930 | .unused, |
| 51931 | 51931 | .unused, |
| 51932 | 51932 | .unused, |
| ... | ... | @@ -51958,7 +51958,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 51958 | 51958 | .extra_temps = .{ |
| 51959 | 51959 | .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 51960 | 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 | 51962 | .unused, |
| 51963 | 51963 | .unused, |
| 51964 | 51964 | .unused, |
| ... | ... | @@ -51991,7 +51991,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 51991 | 51991 | .{ .type = .isize, .kind = .{ .rc = .general_purpose } }, |
| 51992 | 51992 | .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 51993 | 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 | 51995 | .unused, |
| 51996 | 51996 | .unused, |
| 51997 | 51997 | .unused, |
| ... | ... | @@ -52027,7 +52027,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 52027 | 52027 | .{ .type = .isize, .kind = .{ .rc = .general_purpose } }, |
| 52028 | 52028 | .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 52029 | 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 | 52031 | .unused, |
| 52032 | 52032 | .unused, |
| 52033 | 52033 | .unused, |
| ... | ... | @@ -52063,7 +52063,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 52063 | 52063 | .{ .type = .isize, .kind = .{ .rc = .general_purpose } }, |
| 52064 | 52064 | .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 52065 | 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 | 52067 | .unused, |
| 52068 | 52068 | .unused, |
| 52069 | 52069 | .unused, |
| ... | ... | @@ -52099,7 +52099,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 52099 | 52099 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 52100 | 52100 | .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 52101 | 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 | 52103 | .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 52104 | 52104 | .unused, |
| 52105 | 52105 | .unused, |
| ... | ... | @@ -52135,7 +52135,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 52135 | 52135 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 52136 | 52136 | .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 52137 | 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 | 52139 | .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 52140 | 52140 | .unused, |
| 52141 | 52141 | .unused, |
| ... | ... | @@ -52171,7 +52171,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 52171 | 52171 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 52172 | 52172 | .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 52173 | 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 | 52175 | .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 52176 | 52176 | .unused, |
| 52177 | 52177 | .unused, |
| ... | ... | @@ -76457,7 +76457,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 76457 | 76457 | }, |
| 76458 | 76458 | .call_frame = .{ .alignment = .@"16" }, |
| 76459 | 76459 | .extra_temps = .{ |
| 76460 | .{ .type = .usize, .kind = .{ .extern_func = "sqrtq" } }, | |
| 76460 | .{ .type = .usize, .kind = .{ .extern_func = "sqrtf128" } }, | |
| 76461 | 76461 | .unused, |
| 76462 | 76462 | .unused, |
| 76463 | 76463 | .unused, |
| ... | ... | @@ -76484,7 +76484,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 76484 | 76484 | .call_frame = .{ .alignment = .@"16" }, |
| 76485 | 76485 | .extra_temps = .{ |
| 76486 | 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 | 76488 | .unused, |
| 76489 | 76489 | .unused, |
| 76490 | 76490 | .unused, |
| ... | ... | @@ -76512,7 +76512,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 76512 | 76512 | .extra_temps = .{ |
| 76513 | 76513 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 76514 | 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 | 76516 | .unused, |
| 76517 | 76517 | .unused, |
| 76518 | 76518 | .unused, |
| ... | ... | @@ -76543,7 +76543,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 76543 | 76543 | .extra_temps = .{ |
| 76544 | 76544 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 76545 | 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 | 76547 | .unused, |
| 76548 | 76548 | .unused, |
| 76549 | 76549 | .unused, |
| ... | ... | @@ -76574,7 +76574,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 76574 | 76574 | .extra_temps = .{ |
| 76575 | 76575 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 76576 | 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 | 76578 | .unused, |
| 76579 | 76579 | .unused, |
| 76580 | 76580 | .unused, |
| ... | ... | @@ -76605,7 +76605,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 76605 | 76605 | .extra_temps = .{ |
| 76606 | 76606 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 76607 | 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 | 76609 | .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 76610 | 76610 | .unused, |
| 76611 | 76611 | .unused, |
| ... | ... | @@ -76636,7 +76636,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 76636 | 76636 | .extra_temps = .{ |
| 76637 | 76637 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 76638 | 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 | 76640 | .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 76641 | 76641 | .unused, |
| 76642 | 76642 | .unused, |
| ... | ... | @@ -76667,7 +76667,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 76667 | 76667 | .extra_temps = .{ |
| 76668 | 76668 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 76669 | 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 | 76671 | .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 76672 | 76672 | .unused, |
| 76673 | 76673 | .unused, |
| ... | ... | @@ -77306,7 +77306,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 77306 | 77306 | }, |
| 77307 | 77307 | .call_frame = .{ .alignment = .@"16" }, |
| 77308 | 77308 | .extra_temps = .{ |
| 77309 | .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "q" } }, | |
| 77309 | .{ .type = .usize, .kind = .{ .extern_func = @tagName(name) ++ "f128" } }, | |
| 77310 | 77310 | .unused, |
| 77311 | 77311 | .unused, |
| 77312 | 77312 | .unused, |
| ... | ... | @@ -77333,7 +77333,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 77333 | 77333 | .call_frame = .{ .alignment = .@"16" }, |
| 77334 | 77334 | .extra_temps = .{ |
| 77335 | 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 | 77337 | .unused, |
| 77338 | 77338 | .unused, |
| 77339 | 77339 | .unused, |
| ... | ... | @@ -77361,7 +77361,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 77361 | 77361 | .extra_temps = .{ |
| 77362 | 77362 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 77363 | 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 | 77365 | .unused, |
| 77366 | 77366 | .unused, |
| 77367 | 77367 | .unused, |
| ... | ... | @@ -77392,7 +77392,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 77392 | 77392 | .extra_temps = .{ |
| 77393 | 77393 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 77394 | 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 | 77396 | .unused, |
| 77397 | 77397 | .unused, |
| 77398 | 77398 | .unused, |
| ... | ... | @@ -77423,7 +77423,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 77423 | 77423 | .extra_temps = .{ |
| 77424 | 77424 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 77425 | 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 | 77427 | .unused, |
| 77428 | 77428 | .unused, |
| 77429 | 77429 | .unused, |
| ... | ... | @@ -77454,7 +77454,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 77454 | 77454 | .extra_temps = .{ |
| 77455 | 77455 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 77456 | 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 | 77458 | .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 77459 | 77459 | .unused, |
| 77460 | 77460 | .unused, |
| ... | ... | @@ -77485,7 +77485,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 77485 | 77485 | .extra_temps = .{ |
| 77486 | 77486 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 77487 | 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 | 77489 | .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 77490 | 77490 | .unused, |
| 77491 | 77491 | .unused, |
| ... | ... | @@ -77516,7 +77516,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 77516 | 77516 | .extra_temps = .{ |
| 77517 | 77517 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 77518 | 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 | 77520 | .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 77521 | 77521 | .unused, |
| 77522 | 77522 | .unused, |
| ... | ... | @@ -80155,9 +80155,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 80155 | 80155 | .extra_temps = .{ |
| 80156 | 80156 | .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { |
| 80157 | 80157 | else => unreachable, |
| 80158 | .down => "floorq", | |
| 80159 | .up => "ceilq", | |
| 80160 | .zero => "truncq", | |
| 80158 | .down => "floorf128", | |
| 80159 | .up => "ceilf128", | |
| 80160 | .zero => "truncf128", | |
| 80161 | 80161 | } } }, |
| 80162 | 80162 | .unused, |
| 80163 | 80163 | .unused, |
| ... | ... | @@ -80187,9 +80187,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 80187 | 80187 | .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 80188 | 80188 | .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { |
| 80189 | 80189 | else => unreachable, |
| 80190 | .down => "floorq", | |
| 80191 | .up => "ceilq", | |
| 80192 | .zero => "truncq", | |
| 80190 | .down => "floorf128", | |
| 80191 | .up => "ceilf128", | |
| 80192 | .zero => "truncf128", | |
| 80193 | 80193 | } } }, |
| 80194 | 80194 | .unused, |
| 80195 | 80195 | .unused, |
| ... | ... | @@ -80220,9 +80220,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 80220 | 80220 | .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 80221 | 80221 | .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { |
| 80222 | 80222 | else => unreachable, |
| 80223 | .down => "floorq", | |
| 80224 | .up => "ceilq", | |
| 80225 | .zero => "truncq", | |
| 80223 | .down => "floorf128", | |
| 80224 | .up => "ceilf128", | |
| 80225 | .zero => "truncf128", | |
| 80226 | 80226 | } } }, |
| 80227 | 80227 | .unused, |
| 80228 | 80228 | .unused, |
| ... | ... | @@ -80256,9 +80256,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 80256 | 80256 | .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 80257 | 80257 | .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { |
| 80258 | 80258 | else => unreachable, |
| 80259 | .down => "floorq", | |
| 80260 | .up => "ceilq", | |
| 80261 | .zero => "truncq", | |
| 80259 | .down => "floorf128", | |
| 80260 | .up => "ceilf128", | |
| 80261 | .zero => "truncf128", | |
| 80262 | 80262 | } } }, |
| 80263 | 80263 | .unused, |
| 80264 | 80264 | .unused, |
| ... | ... | @@ -80292,9 +80292,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 80292 | 80292 | .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 80293 | 80293 | .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { |
| 80294 | 80294 | else => unreachable, |
| 80295 | .down => "floorq", | |
| 80296 | .up => "ceilq", | |
| 80297 | .zero => "truncq", | |
| 80295 | .down => "floorf128", | |
| 80296 | .up => "ceilf128", | |
| 80297 | .zero => "truncf128", | |
| 80298 | 80298 | } } }, |
| 80299 | 80299 | .unused, |
| 80300 | 80300 | .unused, |
| ... | ... | @@ -80328,9 +80328,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 80328 | 80328 | .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 80329 | 80329 | .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { |
| 80330 | 80330 | else => unreachable, |
| 80331 | .down => "floorq", | |
| 80332 | .up => "ceilq", | |
| 80333 | .zero => "truncq", | |
| 80331 | .down => "floorf128", | |
| 80332 | .up => "ceilf128", | |
| 80333 | .zero => "truncf128", | |
| 80334 | 80334 | } } }, |
| 80335 | 80335 | .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 80336 | 80336 | .unused, |
| ... | ... | @@ -80364,9 +80364,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 80364 | 80364 | .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 80365 | 80365 | .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { |
| 80366 | 80366 | else => unreachable, |
| 80367 | .down => "floorq", | |
| 80368 | .up => "ceilq", | |
| 80369 | .zero => "truncq", | |
| 80367 | .down => "floorf128", | |
| 80368 | .up => "ceilf128", | |
| 80369 | .zero => "truncf128", | |
| 80370 | 80370 | } } }, |
| 80371 | 80371 | .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 80372 | 80372 | .unused, |
| ... | ... | @@ -80400,9 +80400,9 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 80400 | 80400 | .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 80401 | 80401 | .{ .type = .usize, .kind = .{ .extern_func = switch (direction) { |
| 80402 | 80402 | else => unreachable, |
| 80403 | .down => "floorq", | |
| 80404 | .up => "ceilq", | |
| 80405 | .zero => "truncq", | |
| 80403 | .down => "floorf128", | |
| 80404 | .up => "ceilf128", | |
| 80405 | .zero => "truncf128", | |
| 80406 | 80406 | } } }, |
| 80407 | 80407 | .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 80408 | 80408 | .unused, |
| ... | ... | @@ -125531,7 +125531,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 125531 | 125531 | .{ ._, ._, .call, .tmp1d, ._, ._, ._ }, |
| 125532 | 125532 | } }, |
| 125533 | 125533 | }, .{ |
| 125534 | .required_cc_abi = .sysv64, | |
| 125535 | 125534 | .required_features = .{ .sse, null, null, null }, |
| 125536 | 125535 | .src_constraints = .{ .{ .unsigned_int = .xword }, .any, .any }, |
| 125537 | 125536 | .dst_constraints = .{ .{ .float = .xword }, .any }, |
| ... | ... | @@ -125557,34 +125556,6 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 125557 | 125556 | .each = .{ .once = &.{ |
| 125558 | 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 | 125560 | .required_features = .{ .@"64bit", .sse, null, null }, |
| 125590 | 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 | 126762 | .{ ._, ._ae, .j, .@"0b", ._, ._, ._ }, |
| 126792 | 126763 | } }, |
| 126793 | 126764 | }, .{ |
| 126794 | .required_cc_abi = .sysv64, | |
| 126795 | 126765 | .required_features = .{ .avx, null, null, null }, |
| 126796 | 126766 | .src_constraints = .{ .{ .multiple_scalar_unsigned_int = .{ .of = .xword, .is = .xword } }, .any, .any }, |
| 126797 | 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 | 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 | 126797 | .required_features = .{ .sse2, null, null, null }, |
| 126861 | 126798 | .src_constraints = .{ .{ .multiple_scalar_unsigned_int = .{ .of = .xword, .is = .xword } }, .any, .any }, |
| 126862 | 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 | 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 | 126829 | .required_features = .{ .sse, null, null, null }, |
| 126926 | 126830 | .src_constraints = .{ .{ .multiple_scalar_unsigned_int = .{ .of = .xword, .is = .xword } }, .any, .any }, |
| 126927 | 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 | 126857 | .{ ._, ._, .sub, .tmp0d, .si(16), ._, ._ }, |
| 126954 | 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 | 126861 | .required_features = .{ .@"64bit", .avx, null, null }, |
| 126990 | 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 | 142424 | .extra_temps = .{ |
| 142553 | 142425 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 142554 | 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 | 142428 | .unused, |
| 142557 | 142429 | .unused, |
| 142558 | 142430 | .unused, |
| ... | ... | @@ -142584,7 +142456,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 142584 | 142456 | .extra_temps = .{ |
| 142585 | 142457 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 142586 | 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 | 142460 | .unused, |
| 142589 | 142461 | .unused, |
| 142590 | 142462 | .unused, |
| ... | ... | @@ -142616,7 +142488,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 142616 | 142488 | .extra_temps = .{ |
| 142617 | 142489 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 142618 | 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 | 142492 | .unused, |
| 142621 | 142493 | .unused, |
| 142622 | 142494 | .unused, |
| ... | ... | @@ -142649,7 +142521,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 142649 | 142521 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 142650 | 142522 | .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 142651 | 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 | 142525 | .{ .type = .f128, .kind = .mem }, |
| 142654 | 142526 | .unused, |
| 142655 | 142527 | .unused, |
| ... | ... | @@ -142683,7 +142555,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 142683 | 142555 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 142684 | 142556 | .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 142685 | 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 | 142559 | .{ .type = .f128, .kind = .mem }, |
| 142688 | 142560 | .unused, |
| 142689 | 142561 | .unused, |
| ... | ... | @@ -142717,7 +142589,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 142717 | 142589 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 142718 | 142590 | .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 142719 | 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 | 142593 | .{ .type = .f128, .kind = .mem }, |
| 142722 | 142594 | .unused, |
| 142723 | 142595 | .unused, |
| ... | ... | @@ -152785,7 +152657,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 152785 | 152657 | .extra_temps = .{ |
| 152786 | 152658 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 152787 | 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 | 152661 | .unused, |
| 152790 | 152662 | .unused, |
| 152791 | 152663 | .unused, |
| ... | ... | @@ -152817,7 +152689,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 152817 | 152689 | .extra_temps = .{ |
| 152818 | 152690 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 152819 | 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 | 152693 | .unused, |
| 152822 | 152694 | .unused, |
| 152823 | 152695 | .unused, |
| ... | ... | @@ -152849,7 +152721,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 152849 | 152721 | .extra_temps = .{ |
| 152850 | 152722 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 152851 | 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 | 152725 | .unused, |
| 152854 | 152726 | .unused, |
| 152855 | 152727 | .unused, |
| ... | ... | @@ -152882,7 +152754,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 152882 | 152754 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 152883 | 152755 | .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 152884 | 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 | 152758 | .{ .type = .f128, .kind = .mem }, |
| 152887 | 152759 | .unused, |
| 152888 | 152760 | .unused, |
| ... | ... | @@ -152916,7 +152788,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 152916 | 152788 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 152917 | 152789 | .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 152918 | 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 | 152792 | .{ .type = .f128, .kind = .mem }, |
| 152921 | 152793 | .unused, |
| 152922 | 152794 | .unused, |
| ... | ... | @@ -152950,7 +152822,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 152950 | 152822 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 152951 | 152823 | .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 152952 | 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 | 152826 | .{ .type = .f128, .kind = .mem }, |
| 152955 | 152827 | .unused, |
| 152956 | 152828 | .unused, |
| ... | ... | @@ -163019,7 +162891,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 163019 | 162891 | .extra_temps = .{ |
| 163020 | 162892 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 163021 | 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 | 162895 | .unused, |
| 163024 | 162896 | .unused, |
| 163025 | 162897 | .unused, |
| ... | ... | @@ -163051,7 +162923,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 163051 | 162923 | .extra_temps = .{ |
| 163052 | 162924 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 163053 | 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 | 162927 | .unused, |
| 163056 | 162928 | .unused, |
| 163057 | 162929 | .unused, |
| ... | ... | @@ -163083,7 +162955,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 163083 | 162955 | .extra_temps = .{ |
| 163084 | 162956 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 163085 | 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 | 162959 | .unused, |
| 163088 | 162960 | .unused, |
| 163089 | 162961 | .unused, |
| ... | ... | @@ -163116,7 +162988,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 163116 | 162988 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 163117 | 162989 | .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 163118 | 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 | 162992 | .{ .type = .f128, .kind = .mem }, |
| 163121 | 162993 | .unused, |
| 163122 | 162994 | .unused, |
| ... | ... | @@ -163150,7 +163022,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 163150 | 163022 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 163151 | 163023 | .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 163152 | 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 | 163026 | .{ .type = .f128, .kind = .mem }, |
| 163155 | 163027 | .unused, |
| 163156 | 163028 | .unused, |
| ... | ... | @@ -163184,7 +163056,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 163184 | 163056 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 163185 | 163057 | .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 163186 | 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 | 163060 | .{ .type = .f128, .kind = .mem }, |
| 163189 | 163061 | .unused, |
| 163190 | 163062 | .unused, |
| ... | ... | @@ -164816,7 +164688,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 164816 | 164688 | .extra_temps = .{ |
| 164817 | 164689 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 164818 | 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 | 164692 | .unused, |
| 164821 | 164693 | .unused, |
| 164822 | 164694 | .unused, |
| ... | ... | @@ -164848,7 +164720,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 164848 | 164720 | .extra_temps = .{ |
| 164849 | 164721 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 164850 | 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 | 164724 | .unused, |
| 164853 | 164725 | .unused, |
| 164854 | 164726 | .unused, |
| ... | ... | @@ -164880,7 +164752,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 164880 | 164752 | .extra_temps = .{ |
| 164881 | 164753 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 164882 | 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 | 164756 | .unused, |
| 164885 | 164757 | .unused, |
| 164886 | 164758 | .unused, |
| ... | ... | @@ -164913,7 +164785,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 164913 | 164785 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 164914 | 164786 | .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 164915 | 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 | 164789 | .{ .type = .f128, .kind = .mem }, |
| 164918 | 164790 | .unused, |
| 164919 | 164791 | .unused, |
| ... | ... | @@ -164947,7 +164819,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 164947 | 164819 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 164948 | 164820 | .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 164949 | 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 | 164823 | .{ .type = .f128, .kind = .mem }, |
| 164952 | 164824 | .unused, |
| 164953 | 164825 | .unused, |
| ... | ... | @@ -164981,7 +164853,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 164981 | 164853 | .{ .type = .u32, .kind = .{ .rc = .general_purpose } }, |
| 164982 | 164854 | .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 164983 | 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 | 164857 | .{ .type = .f128, .kind = .mem }, |
| 164986 | 164858 | .unused, |
| 164987 | 164859 | .unused, |
| ... | ... | @@ -172785,7 +172657,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 172785 | 172657 | }, |
| 172786 | 172658 | .call_frame = .{ .alignment = .@"16" }, |
| 172787 | 172659 | .extra_temps = .{ |
| 172788 | .{ .type = .usize, .kind = .{ .extern_func = "fmaq" } }, | |
| 172660 | .{ .type = .usize, .kind = .{ .extern_func = "fmaf128" } }, | |
| 172789 | 172661 | .unused, |
| 172790 | 172662 | .unused, |
| 172791 | 172663 | .unused, |
| ... | ... | @@ -172818,7 +172690,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 172818 | 172690 | .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 172819 | 172691 | .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, |
| 172820 | 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 | 172694 | .unused, |
| 172823 | 172695 | .unused, |
| 172824 | 172696 | .unused, |
| ... | ... | @@ -172852,7 +172724,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 172852 | 172724 | .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 172853 | 172725 | .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, |
| 172854 | 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 | 172728 | .unused, |
| 172857 | 172729 | .unused, |
| 172858 | 172730 | .unused, |
| ... | ... | @@ -172889,7 +172761,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 172889 | 172761 | .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 172890 | 172762 | .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, |
| 172891 | 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 | 172765 | .unused, |
| 172894 | 172766 | .unused, |
| 172895 | 172767 | .unused, |
| ... | ... | @@ -172926,7 +172798,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 172926 | 172798 | .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 172927 | 172799 | .{ .type = .f128, .kind = .{ .param_sse = .{ .cc = .ccc, .after = 1, .at = 1 } } }, |
| 172928 | 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 | 172802 | .unused, |
| 172931 | 172803 | .unused, |
| 172932 | 172804 | .unused, |
| ... | ... | @@ -172963,7 +172835,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 172963 | 172835 | .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 172964 | 172836 | .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, |
| 172965 | 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 | 172839 | .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 172968 | 172840 | .unused, |
| 172969 | 172841 | .unused, |
| ... | ... | @@ -173000,7 +172872,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 173000 | 172872 | .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 173001 | 172873 | .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, |
| 173002 | 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 | 172876 | .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 173005 | 172877 | .unused, |
| 173006 | 172878 | .unused, |
| ... | ... | @@ -173037,7 +172909,7 @@ fn genBody(cg: *CodeGen, body: []const Air.Inst.Index) InnerError!void { |
| 173037 | 172909 | .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 173038 | 172910 | .{ .type = .usize, .kind = .{ .param_gpr = .{ .cc = .ccc, .after = 1, .at = 1 } } }, |
| 173039 | 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 | 172913 | .{ .type = .f128, .kind = .{ .ret_sse = .{ .cc = .ccc, .after = 0, .at = 0 } } }, |
| 173042 | 172914 | .unused, |
| 173043 | 172915 | .unused, |
| ... | ... | @@ -176621,10 +176493,20 @@ fn genCall(cg: *CodeGen, info: union(enum) { |
| 176621 | 176493 | |
| 176622 | 176494 | for (call_info.args, arg_types, args, frame_indices) |dst_arg, arg_ty, src_arg, frame_index| switch (dst_arg) { |
| 176623 | 176495 | .none, .load_frame, .indirect_load_frame => {}, |
| 176624 | .register => |dst_reg| try cg.genSetReg(registerAlias( | |
| 176625 | dst_reg, | |
| 176626 | @intCast(cg.unalignedSize(arg_ty)), | |
| 176627 | ), arg_ty, src_arg, opts), | |
| 176496 | .register => |dst_reg| switch (fn_info.cc) { | |
| 176497 | else => try cg.genSetReg(registerAlias( | |
| 176498 | dst_reg, | |
| 176499 | @intCast(cg.unalignedSize(arg_ty)), | |
| 176500 | ), arg_ty, src_arg, opts), | |
| 176501 | .x86_64_sysv, .x86_64_win => { | |
| 176502 | const promoted_ty = cg.promoteInt(arg_ty); | |
| 176503 | const promoted_unaligned_size: u32 = @intCast(cg.unalignedSize(promoted_ty)); | |
| 176504 | const dst_alias = registerAlias(dst_reg, promoted_unaligned_size); | |
| 176505 | try cg.genSetReg(dst_alias, promoted_ty, src_arg, opts); | |
| 176506 | if (promoted_ty.toIntern() != arg_ty.toIntern()) | |
| 176507 | try cg.truncateRegister(arg_ty, dst_alias); | |
| 176508 | }, | |
| 176509 | }, | |
| 176628 | 176510 | .register_pair, |
| 176629 | 176511 | .register_triple, |
| 176630 | 176512 | .register_quadruple, |
| ... | ... | @@ -177096,7 +176978,7 @@ fn lowerBlock(self: *CodeGen, inst: Air.Inst.Index, body: []const Air.Inst.Index |
| 177096 | 176978 | defer block_data.value.deinit(self.gpa); |
| 177097 | 176979 | if (block_data.value.relocs.items.len > 0) { |
| 177098 | 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 | 176982 | block_data.value.relocs.items.len -= 1; |
| 177101 | 176983 | self.mir_instructions.set(last_inst, .{ |
| 177102 | 176984 | .tag = .pseudo, |
| ... | ... | @@ -178017,7 +177899,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 178017 | 177899 | else if (std.mem.endsWith(u8, mnem_str, "l")) |
| 178018 | 177900 | .dword |
| 178019 | 177901 | else if (std.mem.endsWith(u8, mnem_str, "q") and |
| 178020 | (std.mem.indexOfScalar(u8, "vp", mnem_str[0]) == null or | |
| 177902 | (std.mem.findScalar(u8, "vp", mnem_str[0]) == null or | |
| 178021 | 177903 | !std.mem.endsWith(u8, mnem_str, "dq"))) |
| 178022 | 177904 | .qword |
| 178023 | 177905 | else if (std.mem.endsWith(u8, mnem_str, "t")) |
| ... | ... | @@ -178084,8 +177966,8 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 178084 | 177966 | }) + 1, |
| 178085 | 177967 | } |
| 178086 | 177968 | }; |
| 178087 | const untrimmed_op_str = if (std.mem.indexOfScalar(u8, full_op_str, '#') orelse | |
| 178088 | std.mem.indexOf(u8, full_op_str, "//")) |comment| | |
| 177969 | const untrimmed_op_str = if (std.mem.findScalar(u8, full_op_str, '#') orelse | |
| 177970 | std.mem.find(u8, full_op_str, "//")) |comment| | |
| 178089 | 177971 | untrimmed_op_str: { |
| 178090 | 177972 | ops_index = ops_str.len; |
| 178091 | 177973 | break :untrimmed_op_str full_op_str[0..comment]; |
| ... | ... | @@ -178094,7 +177976,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 178094 | 177976 | if (trimmed_op_str.len > 0) break trimmed_op_str; |
| 178095 | 177977 | }; |
| 178096 | 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 | 177980 | const reg = parseRegName(op_str["%%".len .. colon orelse op_str.len]) orelse |
| 178099 | 177981 | return self.fail("invalid register: '{s}'", .{op_str}); |
| 178100 | 177982 | if (colon) |colon_pos| { |
| ... | ... | @@ -178115,7 +177997,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 178115 | 177997 | op.* = .{ .reg = reg }; |
| 178116 | 177998 | } |
| 178117 | 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 | 178001 | const modifier = if (colon) |colon_pos| |
| 178120 | 178002 | op_str[colon_pos + ":".len .. op_str.len - "]".len] |
| 178121 | 178003 | else |
| ... | ... | @@ -178198,7 +178080,7 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 178198 | 178080 | else |_| |
| 178199 | 178081 | return self.fail("invalid immediate: '{s}'", .{op_str}); |
| 178200 | 178082 | } else if (std.mem.endsWith(u8, op_str, ")")) { |
| 178201 | const open = std.mem.indexOfScalar(u8, op_str, '(') orelse | |
| 178083 | const open = std.mem.findScalar(u8, op_str, '(') orelse | |
| 178202 | 178084 | return self.fail("invalid operand: '{s}'", .{op_str}); |
| 178203 | 178085 | var sib_it = |
| 178204 | 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 | 178141 | .disp = if (std.mem.startsWith(u8, op_str[0..open], "%[") and |
| 178260 | 178142 | std.mem.endsWith(u8, op_str[0..open], "]")) |
| 178261 | 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 | 178145 | const modifier = if (colon) |colon_pos| |
| 178264 | 178146 | op_str[colon_pos + ":".len .. open - "]".len] |
| 178265 | 178147 | else |
| ... | ... | @@ -178328,14 +178210,14 @@ fn airAsm(self: *CodeGen, inst: Air.Inst.Index) !void { |
| 178328 | 178210 | .{ ._, .pseudo } |
| 178329 | 178211 | else for (std.enums.values(Mir.Inst.Fixes)) |fixes| { |
| 178330 | 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 | 178214 | const fixes_prefix = if (space_index) |index| |
| 178333 | 178215 | std.meta.stringToEnum(encoder.Instruction.Prefix, fixes_name[0..index]).? |
| 178334 | 178216 | else |
| 178335 | 178217 | .none; |
| 178336 | 178218 | if (fixes_prefix != prefix) continue; |
| 178337 | 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 | 178221 | const mnem_prefix = pattern[0..wildcard_index]; |
| 178340 | 178222 | const mnem_suffix = pattern[wildcard_index + "_".len ..]; |
| 178341 | 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 | 178463 | .sse => switch (ty.zigTypeTag(zcu)) { |
| 178582 | 178464 | else => { |
| 178583 | 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 | 178467 | .integer, .sse, .sseup, .memory, .float, .float_combine, |
| 178586 | 178468 | }) == null); |
| 178587 | 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 | 178471 | 1 => return if (cg.hasFeature(.avx)) .{ .vex_insert_extract = .{ |
| 178590 | 178472 | .insert = .{ .vp_b, .insr }, |
| 178591 | 178473 | .extract = .{ .vp_b, .extr }, |
| ... | ... | @@ -181994,7 +181876,7 @@ fn resolveCallingConventionValues( |
| 181994 | 181876 | } |
| 181995 | 181877 | |
| 181996 | 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; | |
| 181998 | 181880 | |
| 181999 | 181881 | var arg_mcv: [4]MCValue = undefined; |
| 182000 | 181882 | var arg_mcv_len: u32 = 0; |
| ... | ... | @@ -182502,8 +182384,8 @@ fn hasFeature(cg: *CodeGen, feature: std.Target.x86.Feature) bool { |
| 182502 | 182384 | .slow_unaligned_mem_16, |
| 182503 | 182385 | .slow_unaligned_mem_32, |
| 182504 | 182386 | => switch (cg.mod.optimize_mode) { |
| 182505 | .Debug, .ReleaseSafe, .ReleaseFast => null, | |
| 182506 | .ReleaseSmall => false, | |
| 182387 | .debug, .safe, .fast => null, | |
| 182388 | .small => false, | |
| 182507 | 182389 | }, |
| 182508 | 182390 | .fast_11bytenop, |
| 182509 | 182391 | .fast_15bytenop, |
| ... | ... | @@ -182523,8 +182405,8 @@ fn hasFeature(cg: *CodeGen, feature: std.Target.x86.Feature) bool { |
| 182523 | 182405 | .fast_vector_fsqrt, |
| 182524 | 182406 | .fast_vector_shift_masks, |
| 182525 | 182407 | => switch (cg.mod.optimize_mode) { |
| 182526 | .Debug, .ReleaseSafe, .ReleaseFast => null, | |
| 182527 | .ReleaseSmall => true, | |
| 182408 | .debug, .safe, .fast => null, | |
| 182409 | .small => true, | |
| 182528 | 182410 | }, |
| 182529 | 182411 | .mmx => false, |
| 182530 | 182412 | .sahf => switch (cg.target.cpu.arch) { |
| ... | ... | @@ -182626,15 +182508,15 @@ fn intInfo(cg: *CodeGen, ty: Type) ?std.lang.Type.Int { |
| 182626 | 182508 | .anyerror => .{ .signedness = .unsigned, .bits = zcu.errorSetBits() }, |
| 182627 | 182509 | .isize => .{ .signedness = .signed, .bits = cg.target.ptrBitWidth() }, |
| 182628 | 182510 | .usize => .{ .signedness = .unsigned, .bits = cg.target.ptrBitWidth() }, |
| 182629 | .c_char => .{ .signedness = cg.target.cCharSignedness(), .bits = cg.target.cTypeBitSize(.char) }, | |
| 182630 | .c_short => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.short) }, | |
| 182631 | .c_ushort => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.short) }, | |
| 182632 | .c_int => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.int) }, | |
| 182633 | .c_uint => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.int) }, | |
| 182634 | .c_long => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.long) }, | |
| 182635 | .c_ulong => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.long) }, | |
| 182636 | .c_longlong => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.longlong) }, | |
| 182637 | .c_ulonglong => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.longlong) }, | |
| 182511 | .c_char => .{ .signedness = cg.target.cCharSignedness().?, .bits = cg.target.cTypeBitSize(.char).? }, | |
| 182512 | .c_short => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.short).? }, | |
| 182513 | .c_ushort => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.short).? }, | |
| 182514 | .c_int => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.int).? }, | |
| 182515 | .c_uint => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.int).? }, | |
| 182516 | .c_long => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.long).? }, | |
| 182517 | .c_ulong => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.long).? }, | |
| 182518 | .c_longlong => .{ .signedness = .signed, .bits = cg.target.cTypeBitSize(.longlong).? }, | |
| 182519 | .c_ulonglong => .{ .signedness = .unsigned, .bits = cg.target.cTypeBitSize(.longlong).? }, | |
| 182638 | 182520 | .f16, .f32, .f64, .f80, .f128, .c_longdouble => null, |
| 182639 | 182521 | .anyopaque, |
| 182640 | 182522 | .void, |
| ... | ... | @@ -183696,8 +183578,8 @@ const Temp = struct { |
| 183696 | 183578 | const class = classes[class_index]; |
| 183697 | 183579 | next_class_index = @intCast(switch (class) { |
| 183698 | 183580 | .integer, .memory, .float, .float_combine => class_index + 1, |
| 183699 | .sse => std.mem.indexOfNonePos(abi.Class, classes, class_index + 1, &.{.sseup}) orelse classes.len, | |
| 183700 | .x87 => std.mem.indexOfNonePos(abi.Class, classes, class_index + 1, &.{.x87up}) orelse classes.len, | |
| 183581 | .sse => std.mem.findNonePos(abi.Class, classes, class_index + 1, &.{.sseup}) orelse classes.len, | |
| 183582 | .x87 => std.mem.findNonePos(abi.Class, classes, class_index + 1, &.{.x87up}) orelse classes.len, | |
| 183701 | 183583 | .sseup, |
| 183702 | 183584 | .x87up, |
| 183703 | 183585 | .none, |
| ... | ... | @@ -189943,7 +189825,7 @@ const Select = struct { |
| 189943 | 189825 | s.cg.asmOps(mir_tag, mir_ops) catch |err| switch (err) { |
| 189944 | 189826 | error.InvalidInstruction => { |
| 189945 | 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 | 189829 | return s.cg.fail("invalid instruction: '{s}{s}{s} {s} {s} {s} {s}'", .{ |
| 189948 | 189830 | fixes[0..fixes_blank], |
| 189949 | 189831 | @tagName(mir_tag[1]), |
| ... | ... | @@ -190023,7 +189905,7 @@ const Select = struct { |
| 190023 | 189905 | .add, .com, .comi, .div, .divr, .mul, .st, .sub, .subr, .ucom, .ucomi => s.top +%= 1, |
| 190024 | 189906 | else => { |
| 190025 | 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 | 189909 | std.debug.panic("{s}: {s}{s}{s}\n", .{ |
| 190028 | 189910 | @src().fn_name, |
| 190029 | 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 | 435 | for (0..inst_fixes_len) |fixes_i| { |
| 436 | 436 | const fixes: Mir.Inst.Fixes = @fromBackingInt(@intCast(fixes_i)); |
| 437 | 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 | 439 | @tagName(fixes)[i + 1 ..] |
| 440 | 440 | else |
| 441 | 441 | @tagName(fixes); |
| 442 | const wildcard_idx = std.mem.indexOfScalar(u8, pattern, '_').?; | |
| 442 | const wildcard_idx = std.mem.findScalar(u8, pattern, '_').?; | |
| 443 | 443 | break :affix .{ pattern[0..wildcard_idx], pattern[wildcard_idx + 1 ..] }; |
| 444 | 444 | }; |
| 445 | 445 | for (0..inst_tags_len) |inst_tag_i| { |
| ... | ... | @@ -477,7 +477,7 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void { |
| 477 | 477 | else => return lower.fail("TODO lower .{s}", .{@tagName(inst.ops)}), |
| 478 | 478 | }; |
| 479 | 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 | 481 | @field(Prefix, @tagName(tag)[0..space]) |
| 482 | 482 | else |
| 483 | 483 | .none, |
| ... | ... | @@ -487,8 +487,8 @@ fn generic(lower: *Lower, inst: Mir.Inst) Error!void { |
| 487 | 487 | } |
| 488 | 488 | // This combination is invalid; make the theoretical mnemonic name and emit an error with it. |
| 489 | 489 | const fixes_name = @tagName(fixes); |
| 490 | const pattern = fixes_name[if (std.mem.indexOfScalar(u8, fixes_name, ' ')) |i| i + " ".len else 0..]; | |
| 491 | const wildcard_index = std.mem.indexOfScalar(u8, pattern, '_').?; | |
| 490 | const pattern = fixes_name[if (std.mem.findScalar(u8, fixes_name, ' ')) |i| i + " ".len else 0..]; | |
| 491 | const wildcard_index = std.mem.findScalar(u8, pattern, '_').?; | |
| 492 | 492 | return lower.fail("unsupported mnemonic: '{s}{s}{s}'", .{ |
| 493 | 493 | pattern[0..wildcard_index], |
| 494 | 494 | @tagName(inst.tag), |
src/codegen/x86_64/Mir.zig+3-3| ... | ... | @@ -1745,8 +1745,8 @@ pub const Inst = struct { |
| 1745 | 1745 | for (@typeInfo(Mnemonic).@"enum".field_names) |mnemonic_name| { |
| 1746 | 1746 | if (mnemonic_name[0] == '.') continue; |
| 1747 | 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..]; | |
| 1749 | const wildcard_index = std.mem.indexOfScalar(u8, pattern, '_').?; | |
| 1748 | const pattern = fixes_name[if (std.mem.findScalar(u8, fixes_name, ' ')) |index| index + " ".len else 0..]; | |
| 1749 | const wildcard_index = std.mem.findScalar(u8, pattern, '_').?; | |
| 1750 | 1750 | const mnem_prefix = pattern[0..wildcard_index]; |
| 1751 | 1751 | const mnem_suffix = pattern[wildcard_index + "_".len ..]; |
| 1752 | 1752 | if (!std.mem.startsWith(u8, mnemonic_name, mnem_prefix)) continue; |
| ... | ... | @@ -1823,7 +1823,7 @@ pub const NullTerminatedString = enum(u32) { |
| 1823 | 1823 | pub fn toSlice(nts: NullTerminatedString, mir: *const Mir) ?[:0]const u8 { |
| 1824 | 1824 | if (nts == .none) return null; |
| 1825 | 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 | }; |
| 1829 | 1829 |
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 | 133 | .float => switch (ty.floatBits(target)) { |
| 134 | 134 | 16, 32, 64 => .sse, |
| 135 | 135 | 80 => .memory, |
| 136 | 128 => if (ctx == .arg) .memory else .sse, | |
| 136 | 128 => .win_i128, | |
| 137 | 137 | else => unreachable, |
| 138 | 138 | }, |
| 139 | 139 | .vector => { |
| ... | ... | @@ -238,16 +238,18 @@ pub fn classifySystemV(ty: Type, zcu: *Zcu, target: *const std.Target, ctx: Cont |
| 238 | 238 | }; |
| 239 | 239 | const unaligned_size = elem_ty.abiSize(zcu) * len; |
| 240 | 240 | if (unaligned_size <= 4) return Class.one_integer; |
| 241 | if (ctx == .arg and unaligned_size == 8 * 1 * 1 and len == 1 and | |
| 242 | elem_ty.isRuntimeFloat()) return Class.stack; // what | |
| 241 | if (unaligned_size == 8 * 1 * 1 and len == 1) { | |
| 242 | if (ctx == .arg and elem_ty.isRuntimeFloat()) return Class.stack; // what? | |
| 243 | if (ctx != .other and !elem_ty.isRuntimeFloat() and target.os.tag == .freebsd) return Class.one_integer; // who? | |
| 244 | } | |
| 243 | 245 | if (unaligned_size <= 8 * 1) return .{ .sse, .none, .none, .none, .none, .none, .none, .none }; |
| 244 | 246 | if (unaligned_size <= 8 * 2) return .{ .sse, .sseup, .none, .none, .none, .none, .none, .none }; |
| 245 | 247 | if (!target.cpu.has(.x86, .avx)) { |
| 246 | 248 | if (ctx == .ret) switch (unaligned_size) { |
| 247 | 249 | else => {}, |
| 248 | 250 | 8 * 3 => if (len == 3) return if (elem_ty.isRuntimeFloat()) .{ |
| 249 | .sse_sse_x87_per_qword, .none, .none, .none, .none, .none, .none, .none, // how | |
| 250 | } else Class.len_integers, // why | |
| 251 | .sse_sse_x87_per_qword, .none, .none, .none, .none, .none, .none, .none, // how? | |
| 252 | } else Class.len_integers, // why? | |
| 251 | 253 | 8 * 2 * 2, 8 * 2 * 4 => return .{ .sse_per_xword, .none, .none, .none, .none, .none, .none, .none }, |
| 252 | 254 | }; |
| 253 | 255 | return Class.stack; |
| ... | ... | @@ -316,7 +318,7 @@ pub fn classifySystemV(ty: Type, zcu: *Zcu, target: *const std.Target, ctx: Cont |
| 316 | 318 | // byte isn't SSE or any other eightbyte isn't SSEUP, the whole argument |
| 317 | 319 | // is passed in memory." |
| 318 | 320 | 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; | |
| 320 | 322 | |
| 321 | 323 | // "If SSEUP is not preceded by SSE or SSEUP, it is converted to SSE." |
| 322 | 324 | for (&result, 0..) |*class, i| switch (class.*) { |
| ... | ... | @@ -356,11 +358,10 @@ fn classifySystemVStruct( |
| 356 | 358 | while (field_it.next()) |field_index| { |
| 357 | 359 | const field_ty = Type.fromInterned(loaded_struct.field_types.get(ip)[field_index]); |
| 358 | 360 | const field_align = loaded_struct.field_aligns.getOrNone(ip, field_index); |
| 359 | byte_offset = std.mem.alignForward( | |
| 360 | u64, | |
| 361 | byte_offset, | |
| 362 | field_align.toByteUnits() orelse field_ty.abiAlignment(zcu).toByteUnits().?, | |
| 363 | ); | |
| 361 | byte_offset = switch (field_align) { | |
| 362 | .none => field_ty.abiAlignment(zcu), | |
| 363 | else => field_align, | |
| 364 | }.forward(byte_offset); | |
| 364 | 365 | if (zcu.typeToStruct(field_ty)) |field_loaded_struct| { |
| 365 | 366 | switch (field_loaded_struct.layout) { |
| 366 | 367 | .auto => unreachable, |
| ... | ... | @@ -379,6 +380,9 @@ fn classifySystemVStruct( |
| 379 | 380 | }, |
| 380 | 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 | 387 | const field_classes = std.mem.sliceTo(&classifySystemV(field_ty, zcu, target, .other), .none); |
| 384 | 388 | for (result[@intCast(byte_offset / 8)..][0..field_classes.len], field_classes) |*result_class, field_class| |
| ... | ... | @@ -386,11 +390,7 @@ fn classifySystemVStruct( |
| 386 | 390 | byte_offset += field_ty.abiSize(zcu); |
| 387 | 391 | } |
| 388 | 392 | const final_byte_offset = starting_byte_offset + loaded_struct.size; |
| 389 | std.debug.assert(final_byte_offset == std.mem.alignForward( | |
| 390 | u64, | |
| 391 | byte_offset, | |
| 392 | loaded_struct.alignment.toByteUnits().?, | |
| 393 | )); | |
| 393 | std.debug.assert(final_byte_offset == loaded_struct.alignment.forward(byte_offset)); | |
| 394 | 394 | return final_byte_offset; |
| 395 | 395 | } |
| 396 | 396 | |
| ... | ... | @@ -422,6 +422,9 @@ fn classifySystemVUnion( |
| 422 | 422 | }, |
| 423 | 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 | 429 | const field_classes = std.mem.sliceTo(&classifySystemV(field_ty, zcu, target, .other), .none); |
| 427 | 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 | 433 | return starting_byte_offset + loaded_union.size; |
| 431 | 434 | } |
| 432 | 435 | |
| 436 | fn 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 | ||
| 433 | 456 | pub const zigcc = struct { |
| 434 | 457 | pub const stack_align: ?InternPool.Alignment = null; |
| 435 | 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 | 1171 | defer testing.allocator.free(expected_fmt); |
| 1172 | 1172 | const given_fmt = try std.fmt.allocPrint(testing.allocator, "{x}", .{given}); |
| 1173 | 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 | 1175 | const padding = try testing.allocator.alloc(u8, idx + 5); |
| 1176 | 1176 | defer testing.allocator.free(padding); |
| 1177 | 1177 | @memset(padding, ' '); |
src/libs/freebsd.zig-1| ... | ... | @@ -1077,7 +1077,6 @@ fn buildSharedLib( |
| 1077 | 1077 | .omit_frame_pointer = comp.root_mod.omit_frame_pointer, |
| 1078 | 1078 | .valgrind = false, |
| 1079 | 1079 | .optimize_mode = optimize_mode, |
| 1080 | .structured_cfg = comp.root_mod.structured_cfg, | |
| 1081 | 1080 | }, |
| 1082 | 1081 | .global = config, |
| 1083 | 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 | 398 | try result.appendSlice("powerpc" ++ s ++ "powerpc32"); |
| 399 | 399 | } |
| 400 | 400 | } else if (arch == .s390x) { |
| 401 | try result.appendSlice("s390" ++ s ++ "s390-64"); | |
| 401 | try result.appendSlice("s390"); | |
| 402 | 402 | } else if (arch.isLoongArch()) { |
| 403 | 403 | try result.appendSlice("loongarch"); |
| 404 | 404 | } else if (arch == .m68k) { |
| ... | ... | @@ -607,8 +607,6 @@ fn add_include_dirs_arch( |
| 607 | 607 | try args.append("-I"); |
| 608 | 608 | try args.append(try path.join(arena, &[_][]const u8{ dir, "s390", nptl })); |
| 609 | 609 | } else { |
| 610 | try args.append("-I"); | |
| 611 | try args.append(try path.join(arena, &[_][]const u8{ dir, "s390" ++ s ++ "s390-64" })); | |
| 612 | 610 | try args.append("-I"); |
| 613 | 611 | try args.append(try path.join(arena, &[_][]const u8{ dir, "s390" })); |
| 614 | 612 | } |
| ... | ... | @@ -1223,7 +1221,6 @@ fn buildSharedLib( |
| 1223 | 1221 | .omit_frame_pointer = comp.root_mod.omit_frame_pointer, |
| 1224 | 1222 | .valgrind = false, |
| 1225 | 1223 | .optimize_mode = optimize_mode, |
| 1226 | .structured_cfg = comp.root_mod.structured_cfg, | |
| 1227 | 1224 | }, |
| 1228 | 1225 | .global = config, |
| 1229 | 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 | 172 | .omit_frame_pointer = comp.root_mod.omit_frame_pointer, |
| 173 | 173 | .valgrind = false, |
| 174 | 174 | .optimize_mode = optimize_mode, |
| 175 | .structured_cfg = comp.root_mod.structured_cfg, | |
| 176 | 175 | .pic = if (target_util.supports_fpic(target)) true else null, |
| 177 | 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 | 365 | .omit_frame_pointer = comp.root_mod.omit_frame_pointer, |
| 367 | 366 | .valgrind = false, |
| 368 | 367 | .optimize_mode = optimize_mode, |
| 369 | .structured_cfg = comp.root_mod.structured_cfg, | |
| 370 | 368 | .unwind_tables = unwind_tables, |
| 371 | 369 | .pic = if (target_util.supports_fpic(target)) true else null, |
| 372 | 370 | .code_model = comp.root_mod.code_model, |
| ... | ... | @@ -539,15 +537,15 @@ pub fn addCxxArgs( |
| 539 | 537 | // is simple and works everywhere. |
| 540 | 538 | try cflags.append("-D_LIBCPP_PSTL_BACKEND_SERIAL"); |
| 541 | 539 | switch (optimize_mode) { |
| 542 | .Debug => { | |
| 540 | .debug => { | |
| 543 | 541 | try cflags.append("-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_DEBUG"); |
| 544 | 542 | try cflags.append("-D_LIBCPP_ASSERTION_SEMANTIC_DEFAULT=_LIBCPP_ASSERTION_SEMANTIC_ENFORCE"); |
| 545 | 543 | }, |
| 546 | .ReleaseFast, .ReleaseSmall => { | |
| 544 | .fast, .small => { | |
| 547 | 545 | try cflags.append("-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_NONE"); |
| 548 | 546 | try cflags.append("-D_LIBCPP_ASSERTION_SEMANTIC_DEFAULT=_LIBCPP_ASSERTION_SEMANTIC_IGNORE"); |
| 549 | 547 | }, |
| 550 | .ReleaseSafe => { | |
| 548 | .safe => { | |
| 551 | 549 | try cflags.append("-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_FAST"); |
| 552 | 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 | 100 | .valgrind = false, |
| 101 | 101 | .unwind_tables = unwind_tables, |
| 102 | 102 | .optimize_mode = optimize_mode, |
| 103 | .structured_cfg = comp.root_mod.structured_cfg, | |
| 104 | 103 | .pic = true, |
| 105 | 104 | .no_builtin = true, |
| 106 | 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 | 118 | // defines will be correct. |
| 119 | 119 | try cflags.append("-D_LIBUNWIND_IS_NATIVE_ONLY"); |
| 120 | 120 | |
| 121 | if (comp.root_mod.optimize_mode == .Debug) { | |
| 121 | if (comp.root_mod.optimize_mode == .debug) { | |
| 122 | 122 | try cflags.append("-D_DEBUG"); |
| 123 | 123 | } |
| 124 | 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 | 135 | }); |
| 136 | 136 | |
| 137 | 137 | switch (comp.compilerRtOptMode()) { |
| 138 | .Debug, .ReleaseSafe => try winpthreads_args.append("-DWINPTHREAD_DBG"), | |
| 139 | .ReleaseFast, .ReleaseSmall => {}, | |
| 138 | .debug, .safe => try winpthreads_args.append("-DWINPTHREAD_DBG"), | |
| 139 | .fast, .small => {}, | |
| 140 | 140 | } |
| 141 | 141 | |
| 142 | 142 | for (mingw32_winpthreads_src) |dep| { |
src/libs/mingw/Preprocessor.zig+4-4| ... | ... | @@ -15,7 +15,7 @@ const RawTokenList = std.ArrayList(Token); |
| 15 | 15 | const ExpandBuf = std.ArrayList(Token); |
| 16 | 16 | |
| 17 | 17 | const Preprocessor = @This(); |
| 18 | const DefineMap = std.StringArrayHashMapUnmanaged(Macro); | |
| 18 | const DefineMap = std.array_hash_map.String(Macro); | |
| 19 | 19 | |
| 20 | 20 | const GeneratedTokens = std.ArrayList(u8); |
| 21 | 21 | |
| ... | ... | @@ -29,7 +29,7 @@ pub const Source = struct { |
| 29 | 29 | buf: []const u8, |
| 30 | 30 | }; |
| 31 | 31 | |
| 32 | sources: std.StringArrayHashMapUnmanaged(Source) = .empty, | |
| 32 | sources: std.array_hash_map.String(Source) = .empty, | |
| 33 | 33 | |
| 34 | 34 | arena: Allocator, |
| 35 | 35 | io: std.Io, |
| ... | ... | @@ -91,9 +91,9 @@ fn addTokenAssumeCapacity(pp: *Preprocessor, tok: Token) void { |
| 91 | 91 | |
| 92 | 92 | fn defineBuiltins(pp: *Preprocessor) !void { |
| 93 | 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 | 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 | 97 | try pp.defineBuiltinValue("__SIZEOF_DOUBLE__", val, .pp_num); |
| 98 | 98 | |
| 99 | 99 | if (pp.target.abi.isGnu()) { |
src/libs/mingw/def.zig+4-4| ... | ... | @@ -61,7 +61,7 @@ pub const ModuleDefinition = struct { |
| 61 | 61 | // or ? for C++ functions). Vectorcall functions won't have any |
| 62 | 62 | // fixed prefix, but the function base name will still be at least |
| 63 | 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 | 65 | e.name = e.name[0..name_len_without_at_suffix]; |
| 66 | 66 | } |
| 67 | 67 | } |
| ... | ... | @@ -452,7 +452,7 @@ pub const Parser = struct { |
| 452 | 452 | var ext_name_needs_underscore = false; |
| 453 | 453 | if (self.machine_type == .I386) { |
| 454 | 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 | 456 | name_needs_underscore = !is_decorated and !is_forward_target; |
| 457 | 457 | |
| 458 | 458 | if (ext_name_tok) |ext_name| { |
| ... | ... | @@ -578,9 +578,9 @@ pub const Parser = struct { |
| 578 | 578 | // themselves can start with an underscore, while a second one still needs |
| 579 | 579 | // to be added. |
| 580 | 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 | 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 | 584 | return false; |
| 585 | 585 | } |
| 586 | 586 |
src/libs/mingw/implib.zig+1-1| ... | ... | @@ -351,7 +351,7 @@ fn getNameType( |
| 351 | 351 | // the leading underscore. In MinGW on the other hand, a decorated |
| 352 | 352 | // stdcall function still omits the underscore (IMPORT_NAME_NOPREFIX). |
| 353 | 353 | if (std.mem.startsWith(u8, ext_name, "_") and |
| 354 | std.mem.indexOfScalar(u8, ext_name, '@') != null and | |
| 354 | std.mem.findScalar(u8, ext_name, '@') != null and | |
| 355 | 355 | module_definition_type != .mingw) |
| 356 | 356 | return .NAME; |
| 357 | 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 | 225 | .omit_frame_pointer = comp.root_mod.omit_frame_pointer, |
| 226 | 226 | .valgrind = false, |
| 227 | 227 | .optimize_mode = optimize_mode, |
| 228 | .structured_cfg = comp.root_mod.structured_cfg, | |
| 229 | 228 | }, |
| 230 | 229 | .global = config, |
| 231 | 230 | .cc_argv = cc_argv, |
src/libs/netbsd.zig-1| ... | ... | @@ -727,7 +727,6 @@ fn buildSharedLib( |
| 727 | 727 | .omit_frame_pointer = comp.root_mod.omit_frame_pointer, |
| 728 | 728 | .valgrind = false, |
| 729 | 729 | .optimize_mode = optimize_mode, |
| 730 | .structured_cfg = comp.root_mod.structured_cfg, | |
| 731 | 730 | }, |
| 732 | 731 | .global = config, |
| 733 | 732 | .cc_argv = &.{}, |
src/libs/openbsd.zig-1| ... | ... | @@ -647,7 +647,6 @@ fn buildSharedLib( |
| 647 | 647 | .omit_frame_pointer = comp.root_mod.omit_frame_pointer, |
| 648 | 648 | .valgrind = false, |
| 649 | 649 | .optimize_mode = optimize_mode, |
| 650 | .structured_cfg = comp.root_mod.structured_cfg, | |
| 651 | 650 | }, |
| 652 | 651 | .global = config, |
| 653 | 652 | .cc_argv = &.{}, |
src/link.zig+57-3| ... | ... | @@ -1238,11 +1238,11 @@ pub const File = struct { |
| 1238 | 1238 | } |
| 1239 | 1239 | |
| 1240 | 1240 | switch (base.tag) { |
| 1241 | inline .elf2, .coff2, .wasm => |tag| { | |
| 1241 | inline .elf2, .coff2, .wasm, .c => |tag| { | |
| 1242 | 1242 | dev.check(tag.devFeature()); |
| 1243 | 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 | } |
| 1247 | 1247 | |
| 1248 | 1248 | base.post_prelink = true; |
| ... | ... | @@ -2127,7 +2127,7 @@ pub fn resolveInputs( |
| 2127 | 2127 | continue; |
| 2128 | 2128 | }, |
| 2129 | 2129 | } |
| 2130 | @compileError("unreachable"); | |
| 2130 | comptime unreachable; | |
| 2131 | 2131 | } |
| 2132 | 2132 | |
| 2133 | 2133 | if (failed_libs.items.len > 0) { |
| ... | ... | @@ -2239,6 +2239,60 @@ fn resolveLibInput( |
| 2239 | 2239 | return finishResolveLibInput(io, resolved_inputs, archive_dedup, test_path, file, link_mode, name_query.query); |
| 2240 | 2240 | } |
| 2241 | 2241 | |
| 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 | 2296 | return .no_match; |
| 2243 | 2297 | } |
| 2244 | 2298 |
src/link/C.zig+26-25| ... | ... | @@ -43,6 +43,8 @@ type_dependencies: std.ArrayList(link.ConstPool.Index), |
| 43 | 43 | /// one array. |
| 44 | 44 | align_dependency_masks: std.ArrayList(u64), |
| 45 | 45 | |
| 46 | /// Emitted at the top of the file. This can be cached since it only depends on the target. | |
| 47 | header: String, | |
| 46 | 48 | /// All NAVs, regardless of whether they are functions or simple constants, are put in this map. |
| 47 | 49 | navs: std.array_hash_map.Auto(InternPool.Nav.Index, RenderedDecl), |
| 48 | 50 | /// 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 | 406 | emit: Path, |
| 405 | 407 | options: link.File.OpenOptions, |
| 406 | 408 | ) !*C { |
| 409 | assert(comp.root_mod.resolved_target.result.ofmt == .c); | |
| 407 | 410 | const io = comp.io; |
| 408 | const target = &comp.root_mod.resolved_target.result; | |
| 409 | assert(target.ofmt == .c); | |
| 410 | 411 | const optimize_mode = comp.root_mod.optimize_mode; |
| 411 | 412 | const use_lld = build_options.have_llvm and comp.config.use_lld; |
| 412 | 413 | const use_llvm = comp.config.use_llvm; |
| ... | ... | @@ -422,14 +423,13 @@ pub fn createEmpty( |
| 422 | 423 | }); |
| 423 | 424 | errdefer file.close(io); |
| 424 | 425 | |
| 425 | const c_file = try arena.create(C); | |
| 426 | ||
| 427 | c_file.* = .{ | |
| 426 | const c = try arena.create(C); | |
| 427 | c.* = .{ | |
| 428 | 428 | .base = .{ |
| 429 | 429 | .tag = .c, |
| 430 | 430 | .comp = comp, |
| 431 | 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 | 433 | .print_gc_sections = options.print_gc_sections, |
| 434 | 434 | .stack_size = options.stack_size orelse 16777216, |
| 435 | 435 | .allow_shlib_undefined = options.allow_shlib_undefined orelse false, |
| ... | ... | @@ -439,6 +439,7 @@ pub fn createEmpty( |
| 439 | 439 | .string_bytes = .empty, |
| 440 | 440 | .type_dependencies = .empty, |
| 441 | 441 | .align_dependency_masks = .empty, |
| 442 | .header = .empty, | |
| 442 | 443 | .navs = .empty, |
| 443 | 444 | .uavs = .empty, |
| 444 | 445 | .type_pool = .empty, |
| ... | ... | @@ -447,8 +448,7 @@ pub fn createEmpty( |
| 447 | 448 | .exported_navs = .empty, |
| 448 | 449 | .exported_uavs = .empty, |
| 449 | 450 | }; |
| 450 | ||
| 451 | return c_file; | |
| 451 | return c; | |
| 452 | 452 | } |
| 453 | 453 | |
| 454 | 454 | pub fn deinit(c: *C) void { |
| ... | ... | @@ -469,6 +469,21 @@ pub fn deinit(c: *C) void { |
| 469 | 469 | c.exported_uavs.deinit(gpa); |
| 470 | 470 | } |
| 471 | 471 | |
| 472 | pub 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 | ||
| 472 | 487 | pub fn updateContainerType( |
| 473 | 488 | c: *C, |
| 474 | 489 | pt: Zcu.PerThread, |
| ... | ... | @@ -727,7 +742,6 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog |
| 727 | 742 | const io = comp.io; |
| 728 | 743 | const zcu = c.base.comp.zcu.?; |
| 729 | 744 | const ip = &zcu.intern_pool; |
| 730 | const target = zcu.getTarget(); | |
| 731 | 745 | const active = zcu.activate(tid); |
| 732 | 746 | defer active.deactivate(); |
| 733 | 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 | 957 | // We have discovered the full set of NAVs, UAVs, and types we need to emit, and will now begin |
| 944 | 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 | 961 | // * Big-int type definitions |
| 948 | 962 | // * Other CType definitions (traversing the dependency graph to sort topologically) |
| 949 | 963 | // * Global assembly |
| ... | ... | @@ -968,7 +982,7 @@ pub fn flush(c: *C, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: std.Prog |
| 968 | 982 | |
| 969 | 983 | // We know exactly what we'll be emitting, so can reserve capacity for all of our buffers! |
| 970 | 984 | |
| 971 | try f.all_buffers.ensureUnusedCapacity(gpa, 3 + // ABI defines and `#include "zig.h"` | |
| 985 | try f.all_buffers.ensureUnusedCapacity(gpa, 1 + // Header | |
| 972 | 986 | 1 + // Big-int type definitions |
| 973 | 987 | need_types.count() + // `RenderedType.fwd_decl` (worst-case) |
| 974 | 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 | 998 | need_uavs.count() * 3 + // UAV definitions ("static ", "zig_align(4)", "<definition body>") |
| 985 | 999 | need_navs.count() * 2); // NAV definitions ("static ", "<definition body>") |
| 986 | 1000 | |
| 987 | // ABI defines and `#include "zig.h"` | |
| 988 | switch (target.abi) { | |
| 989 | .msvc, .itanium => f.appendBufAssumeCapacity("#define ZIG_TARGET_ABI_MSVC\n"), | |
| 990 | else => {}, | |
| 991 | } | |
| 992 | f.appendBufAssumeCapacity(try std.fmt.allocPrint( | |
| 993 | arena, | |
| 994 | "#define ZIG_TARGET_MAX_INT_ALIGNMENT {d}\n", | |
| 995 | .{target.cMaxIntAlignment()}, | |
| 996 | )); | |
| 997 | f.appendBufAssumeCapacity( | |
| 998 | \\#include "zig.h" | |
| 999 | \\ | |
| 1000 | ); | |
| 1001 | f.appendBufAssumeCapacity(c.header.get(c)); | |
| 1001 | 1002 | |
| 1002 | 1003 | // Big-int type definitions |
| 1003 | 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 | 621 | } |
| 622 | 622 | |
| 623 | 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 | 625 | return std.array_hash_map.hashString(key); |
| 626 | 626 | } |
| 627 | 627 | }; |
| ... | ... | @@ -711,7 +711,7 @@ pub const ExportTable = struct { |
| 711 | 711 | } |
| 712 | 712 | |
| 713 | 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 | 715 | return std.array_hash_map.hashString(key); |
| 716 | 716 | } |
| 717 | 717 | }; |
| ... | ... | @@ -759,7 +759,7 @@ pub const ImportTable = struct { |
| 759 | 759 | } |
| 760 | 760 | |
| 761 | 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 | 763 | return std.array_hash_map.hashString(key); |
| 764 | 764 | } |
| 765 | 765 | }; |
| ... | ... | @@ -822,7 +822,7 @@ pub const String = enum(u32) { |
| 822 | 822 | |
| 823 | 823 | pub fn toSlice(s: String, coff: *Coff) [:0]const u8 { |
| 824 | 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 | } |
| 827 | 827 | |
| 828 | 828 | pub fn toOptional(s: String) String.Optional { |
| ... | ... | @@ -3535,7 +3535,7 @@ fn objectSectionParentName(coff: *Coff, name: []const u8) []const u8 { |
| 3535 | 3535 | // Otherwise, we want to keep the full name so that this sort can occur correctly when |
| 3536 | 3536 | // the object is finally linked into an image. |
| 3537 | 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 | 3539 | else |
| 3540 | 3540 | name; |
| 3541 | 3541 | } |
| ... | ... | @@ -3654,7 +3654,7 @@ fn verifyParentSectionAttributes( |
| 3654 | 3654 | parent.name(coff).toSlice(coff), |
| 3655 | 3655 | }); |
| 3656 | 3656 | |
| 3657 | inline for (comptime std.meta.fieldNames(ObjectSectionAttributes)) |field| { | |
| 3657 | inline for (@typeInfo(ObjectSectionAttributes).@"struct".field_names) |field| { | |
| 3658 | 3658 | if (@field(child_attrs, field) != @field(parent_attrs, field)) { |
| 3659 | 3659 | err.addNote("flags.{s} was {d} in {s}, but {d} in {s}", .{ |
| 3660 | 3660 | field, |
| ... | ... | @@ -5370,7 +5370,9 @@ fn loadDll(coff: *Coff, path: std.Build.Cache.Path, fr: *Io.File.Reader) LoadInp |
| 5370 | 5370 | } |
| 5371 | 5371 | |
| 5372 | 5372 | pub 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 | 5376 | const base = coff.base; |
| 5375 | 5377 | const comp = base.comp; |
| 5376 | 5378 | |
| ... | ... | @@ -5598,11 +5600,11 @@ fn updateFuncInner( |
| 5598 | 5600 | const ni = try coff.mf.addLastChildNode(gpa, sec_si.node(coff), .{ |
| 5599 | 5601 | .alignment = switch (nav.resolved.?.@"align") { |
| 5600 | 5602 | .none => switch (mod.optimize_mode) { |
| 5601 | .Debug, | |
| 5602 | .ReleaseSafe, | |
| 5603 | .ReleaseFast, | |
| 5603 | .debug, | |
| 5604 | .safe, | |
| 5605 | .fast, | |
| 5604 | 5606 | => target_util.defaultFunctionAlignment(target), |
| 5605 | .ReleaseSmall => target_util.minFunctionAlignment(target), | |
| 5607 | .small => target_util.minFunctionAlignment(target), | |
| 5606 | 5608 | }, |
| 5607 | 5609 | else => |a| a.maxStrict(target_util.minFunctionAlignment(target)), |
| 5608 | 5610 | }.toStdMem(), |
| ... | ... | @@ -5735,7 +5737,7 @@ fn reportUndefs(coff: *Coff, tid: Zcu.PerThread.Id) !void { |
| 5735 | 5737 | const gpa = comp.gpa; |
| 5736 | 5738 | const max_notes = 4; |
| 5737 | 5739 | |
| 5738 | var undef_indices: std.ArrayListUnmanaged(u32) = .empty; | |
| 5740 | var undef_indices: std.ArrayList(u32) = .empty; | |
| 5739 | 5741 | for (coff.relocs.items, 0..) |reloc, reloc_i| { |
| 5740 | 5742 | if (reloc.flags.free) continue; |
| 5741 | 5743 | const target_sym = reloc.target.get(coff); |
| ... | ... | @@ -5886,7 +5888,9 @@ pub fn flush( |
| 5886 | 5888 | prog_node: std.Progress.Node, |
| 5887 | 5889 | ) link.Error!void { |
| 5888 | 5890 | _ = arena; |
| 5889 | _ = prog_node; | |
| 5891 | const sub_prog_node = prog_node.start("COFF Flush", 0); | |
| 5892 | defer sub_prog_node.end(); | |
| 5893 | ||
| 5890 | 5894 | const comp = coff.base.comp; |
| 5891 | 5895 | |
| 5892 | 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 | 6653 | |
| 6650 | 6654 | const target = &comp.root_mod.resolved_target.result; |
| 6651 | 6655 | const alignment = switch (comp.root_mod.optimize_mode) { |
| 6652 | .Debug, | |
| 6653 | .ReleaseSafe, | |
| 6654 | .ReleaseFast, | |
| 6656 | .debug, | |
| 6657 | .safe, | |
| 6658 | .fast, | |
| 6655 | 6659 | => target_util.defaultFunctionAlignment(target), |
| 6656 | .ReleaseSmall => target_util.minFunctionAlignment(target), | |
| 6660 | .small => target_util.minFunctionAlignment(target), | |
| 6657 | 6661 | }.toStdMem(); |
| 6658 | 6662 | const parent_si = (try coff.pseudoSectionMapIndex( |
| 6659 | 6663 | .@".thunks", |
| ... | ... | @@ -6983,7 +6987,7 @@ fn flushMoved(coff: *Coff, ni: MappedFile.Node.Index) !void { |
| 6983 | 6987 | continue; |
| 6984 | 6988 | |
| 6985 | 6989 | import_hint_name_index = @intCast(import_hint_name_align.forward( |
| 6986 | std.mem.indexOfScalarPos( | |
| 6990 | std.mem.findScalarPos( | |
| 6987 | 6991 | u8, |
| 6988 | 6992 | import_hint_name_slice, |
| 6989 | 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 | 4151 | .x86_64_regcall_v3_sysv => .LLVM_X86RegCall, |
| 4152 | 4152 | .x86_64_regcall_v4_win => .LLVM_X86RegCall, |
| 4153 | 4153 | .x86_64_vectorcall => .LLVM_vectorcall, |
| 4154 | .x86_sysv => .normal, | |
| 4155 | .x86_win => .normal, | |
| 4154 | .x86_sysv, .x86_win, .x86_mingw => .normal, | |
| 4155 | .x86_64_preserve_none => .LLVM_PreserveNone, | |
| 4156 | 4156 | .x86_stdcall => .BORLAND_stdcall, |
| 4157 | 4157 | .x86_fastcall => .BORLAND_msfastcall, |
| 4158 | 4158 | .x86_thiscall => .BORLAND_thiscall, |
| ... | ... | @@ -4166,6 +4166,7 @@ fn updateConstInner(dwarf: *Dwarf, pt: Zcu.PerThread, debug_const_index: link.Co |
| 4166 | 4166 | .aarch64_aapcs_win => .normal, |
| 4167 | 4167 | .aarch64_vfabi => .LLVM_AAPCS, |
| 4168 | 4168 | .aarch64_vfabi_sve => .LLVM_AAPCS, |
| 4169 | .aarch64_preserve_none => .LLVM_PreserveNone, | |
| 4169 | 4170 | |
| 4170 | 4171 | .arm_aapcs => .LLVM_AAPCS, |
| 4171 | 4172 | .arm_aapcs_vfp => .LLVM_AAPCS_VFP, |
src/link/Elf.zig+136-137| ... | ... | @@ -127,7 +127,7 @@ const SectionIndexes = struct { |
| 127 | 127 | symtab: ?u32 = null, |
| 128 | 128 | }; |
| 129 | 129 | |
| 130 | const ProgramHeaderList = std.ArrayList(elf.Elf64_Phdr); | |
| 130 | const ProgramHeaderList = std.ArrayList(elf.Elf64.Phdr); | |
| 131 | 131 | |
| 132 | 132 | const OptionalProgramHeaderIndex = enum(u16) { |
| 133 | 133 | none = std.math.maxInt(u16), |
| ... | ... | @@ -159,21 +159,21 @@ const ProgramHeaderIndex = enum(u16) { |
| 159 | 159 | }; |
| 160 | 160 | |
| 161 | 161 | const ProgramHeaderIndexes = struct { |
| 162 | /// PT_PHDR | |
| 162 | /// PT.PHDR | |
| 163 | 163 | table: OptionalProgramHeaderIndex = .none, |
| 164 | /// PT_LOAD for PHDR table | |
| 164 | /// PT.LOAD for PHDR table | |
| 165 | 165 | /// We add this special load segment to ensure the EHDR and PHDR table are always |
| 166 | 166 | /// loaded into memory. |
| 167 | 167 | table_load: OptionalProgramHeaderIndex = .none, |
| 168 | /// PT_INTERP | |
| 168 | /// PT.INTERP | |
| 169 | 169 | interp: OptionalProgramHeaderIndex = .none, |
| 170 | /// PT_DYNAMIC | |
| 170 | /// PT.DYNAMIC | |
| 171 | 171 | dynamic: OptionalProgramHeaderIndex = .none, |
| 172 | /// PT_GNU_EH_FRAME | |
| 172 | /// PT.GNU_EH_FRAME | |
| 173 | 173 | gnu_eh_frame: OptionalProgramHeaderIndex = .none, |
| 174 | /// PT_GNU_STACK | |
| 174 | /// PT.GNU_STACK | |
| 175 | 175 | gnu_stack: OptionalProgramHeaderIndex = .none, |
| 176 | /// PT_TLS | |
| 176 | /// PT.TLS | |
| 177 | 177 | /// TODO I think ELF permits multiple TLS segments but for now, assume one per file. |
| 178 | 178 | tls: OptionalProgramHeaderIndex = .none, |
| 179 | 179 | }; |
| ... | ... | @@ -260,7 +260,7 @@ pub fn createEmpty( |
| 260 | 260 | .tag = .elf, |
| 261 | 261 | .comp = comp, |
| 262 | 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 | 264 | .print_gc_sections = options.print_gc_sections, |
| 265 | 265 | .stack_size = options.stack_size orelse 16777216, |
| 266 | 266 | .allow_shlib_undefined = options.allow_shlib_undefined orelse !is_native_os, |
| ... | ... | @@ -334,23 +334,23 @@ pub fn createEmpty( |
| 334 | 334 | if (!is_obj_or_ar) { |
| 335 | 335 | try self.dynstrtab.append(gpa, 0); |
| 336 | 336 | |
| 337 | // Initialize PT_PHDR program header | |
| 337 | // Initialize PT.PHDR program header | |
| 338 | 338 | const p_align: u16 = switch (self.ptr_width) { |
| 339 | .p32 => @alignOf(elf.Elf32_Phdr), | |
| 340 | .p64 => @alignOf(elf.Elf64_Phdr), | |
| 339 | .p32 => @alignOf(elf.Elf32.Phdr), | |
| 340 | .p64 => @alignOf(elf.Elf64.Phdr), | |
| 341 | 341 | }; |
| 342 | 342 | const ehsize: u64 = switch (self.ptr_width) { |
| 343 | 343 | .p32 => @sizeOf(elf.Elf32_Ehdr), |
| 344 | 344 | .p64 => @sizeOf(elf.Elf64_Ehdr), |
| 345 | 345 | }; |
| 346 | 346 | const phsize: u64 = switch (self.ptr_width) { |
| 347 | .p32 => @sizeOf(elf.Elf32_Phdr), | |
| 348 | .p64 => @sizeOf(elf.Elf64_Phdr), | |
| 347 | .p32 => @sizeOf(elf.Elf32.Phdr), | |
| 348 | .p64 => @sizeOf(elf.Elf64.Phdr), | |
| 349 | 349 | }; |
| 350 | 350 | const max_nphdrs = comptime getMaxNumberOfPhdrs(); |
| 351 | 351 | const reserved: u64 = mem.alignForward(u64, padToIdeal(max_nphdrs * phsize), self.page_size); |
| 352 | 352 | self.phdr_indexes.table = (try self.addPhdr(.{ |
| 353 | .type = elf.PT_PHDR, | |
| 353 | .type = @backingInt(elf.PT.PHDR), | |
| 354 | 354 | .flags = elf.PF_R, |
| 355 | 355 | .@"align" = p_align, |
| 356 | 356 | .addr = self.image_base + ehsize, |
| ... | ... | @@ -359,7 +359,7 @@ pub fn createEmpty( |
| 359 | 359 | .memsz = reserved, |
| 360 | 360 | })).toOptional(); |
| 361 | 361 | self.phdr_indexes.table_load = (try self.addPhdr(.{ |
| 362 | .type = elf.PT_LOAD, | |
| 362 | .type = @backingInt(elf.PT.LOAD), | |
| 363 | 363 | .flags = elf.PF_R, |
| 364 | 364 | .@"align" = self.page_size, |
| 365 | 365 | .addr = self.image_base, |
| ... | ... | @@ -514,11 +514,11 @@ fn detectAllocCollision(self: *Elf, start: u64, size: u64) !?u64 { |
| 514 | 514 | } |
| 515 | 515 | |
| 516 | 516 | for (self.phdrs.items) |phdr| { |
| 517 | if (phdr.p_type != elf.PT_LOAD) continue; | |
| 518 | const increased_size = padToIdeal(phdr.p_filesz); | |
| 519 | const test_end = phdr.p_offset +| increased_size; | |
| 517 | if (phdr.type != .LOAD) continue; | |
| 518 | const increased_size = padToIdeal(phdr.filesz); | |
| 519 | const test_end = phdr.offset +| increased_size; | |
| 520 | 520 | if (start < test_end) { |
| 521 | if (end > phdr.p_offset) return test_end; | |
| 521 | if (end > phdr.offset) return test_end; | |
| 522 | 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 | 538 | if (section.sh_offset < min_pos) min_pos = section.sh_offset; |
| 539 | 539 | } |
| 540 | 540 | for (self.phdrs.items) |phdr| { |
| 541 | if (phdr.p_offset <= start) continue; | |
| 542 | if (phdr.p_offset < min_pos) min_pos = phdr.p_offset; | |
| 541 | if (phdr.offset <= start) continue; | |
| 542 | if (phdr.offset < min_pos) min_pos = phdr.offset; | |
| 543 | 543 | } |
| 544 | 544 | return min_pos - start; |
| 545 | 545 | } |
| ... | ... | @@ -714,7 +714,6 @@ pub fn loadInput(self: *Elf, input: link.Input) !void { |
| 714 | 714 | const target = self.getTarget(); |
| 715 | 715 | const debug_fmt_strip = comp.config.debug_format == .strip; |
| 716 | 716 | const default_sym_version = self.default_sym_version; |
| 717 | const is_static_lib = self.base.isStaticLib(); | |
| 718 | 717 | |
| 719 | 718 | if (comp.verbose_link) { |
| 720 | 719 | comp.mutex.lockUncancelable(io); // protect comp.arena |
| ... | ... | @@ -733,7 +732,11 @@ pub fn loadInput(self: *Elf, input: link.Input) !void { |
| 733 | 732 | .res => unreachable, |
| 734 | 733 | .dso_exact => @panic("TODO"), |
| 735 | 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 | 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 | 1086 | default_sym_version: elf.Versym, |
| 1084 | 1087 | objects: *std.ArrayList(File.Index), |
| 1085 | 1088 | obj: link.Input.Object, |
| 1086 | is_static_lib: bool, | |
| 1087 | 1089 | ) !void { |
| 1088 | 1090 | const tracy = trace(@src()); |
| 1089 | 1091 | defer tracy.end(); |
| ... | ... | @@ -1092,17 +1094,14 @@ fn parseArchive( |
| 1092 | 1094 | var archive = try Archive.parse(gpa, io, diags, file_handles, obj.path, fh); |
| 1093 | 1095 | defer archive.deinit(gpa); |
| 1094 | 1096 | |
| 1095 | const init_alive = if (is_static_lib) true else obj.must_link; | |
| 1096 | ||
| 1097 | 1097 | for (archive.objects) |extracted| { |
| 1098 | 1098 | const index: File.Index = @intCast(try files.addOne(gpa)); |
| 1099 | 1099 | files.set(index, .{ .object = extracted }); |
| 1100 | 1100 | const object = &files.items(.data)[index].object; |
| 1101 | 1101 | object.index = index; |
| 1102 | object.alive = init_alive; | |
| 1102 | object.alive = obj.must_link; | |
| 1103 | 1103 | try object.parseCommon(gpa, io, diags, obj.path, obj.file, target); |
| 1104 | if (!is_static_lib) | |
| 1105 | try object.parse(gpa, io, diags, obj.path, obj.file, target, debug_fmt_strip, default_sym_version); | |
| 1104 | try object.parse(gpa, io, diags, obj.path, obj.file, target, debug_fmt_strip, default_sym_version); | |
| 1106 | 1105 | try objects.append(gpa, index); |
| 1107 | 1106 | } |
| 1108 | 1107 | } |
| ... | ... | @@ -1471,34 +1470,34 @@ fn writePhdrTable(self: *Elf) !void { |
| 1471 | 1470 | const phdr_table = &self.phdrs.items[self.phdr_indexes.table.int().?]; |
| 1472 | 1471 | |
| 1473 | 1472 | log.debug("writing program headers from 0x{x} to 0x{x}", .{ |
| 1474 | phdr_table.p_offset, | |
| 1475 | phdr_table.p_offset + phdr_table.p_filesz, | |
| 1473 | phdr_table.offset, | |
| 1474 | phdr_table.offset + phdr_table.filesz, | |
| 1476 | 1475 | }); |
| 1477 | 1476 | |
| 1478 | 1477 | switch (self.ptr_width) { |
| 1479 | 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 | 1480 | defer gpa.free(buf); |
| 1482 | 1481 | |
| 1483 | 1482 | for (buf, 0..) |*phdr, i| { |
| 1484 | 1483 | phdr.* = phdrTo32(self.phdrs.items[i]); |
| 1485 | 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 | 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 | 1492 | defer gpa.free(buf); |
| 1494 | 1493 | |
| 1495 | 1494 | for (buf, 0..) |*phdr, i| { |
| 1496 | 1495 | phdr.* = self.phdrs.items[i]; |
| 1497 | 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 | 1580 | const entry_sym = obj.entrySymbol(self) orelse break :blk 0; |
| 1582 | 1581 | break :blk @intCast(entry_sym.address(.{}, self)); |
| 1583 | 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 | 1584 | switch (self.ptr_width) { |
| 1586 | 1585 | .p32 => { |
| 1587 | 1586 | mem.writeInt(u32, hdr_buf[index..][0..4], @intCast(e_entry), endian); |
| ... | ... | @@ -1622,8 +1621,8 @@ pub fn writeElfHeader(self: *Elf) !void { |
| 1622 | 1621 | index += 2; |
| 1623 | 1622 | |
| 1624 | 1623 | const e_phentsize: u16 = switch (self.ptr_width) { |
| 1625 | .p32 => @sizeOf(elf.Elf32_Phdr), | |
| 1626 | .p64 => @sizeOf(elf.Elf64_Phdr), | |
| 1624 | .p32 => @sizeOf(elf.Elf32.Phdr), | |
| 1625 | .p64 => @sizeOf(elf.Elf64.Phdr), | |
| 1627 | 1626 | }; |
| 1628 | 1627 | mem.writeInt(u16, hdr_buf[index..][0..2], e_phentsize, endian); |
| 1629 | 1628 | index += 2; |
| ... | ... | @@ -2091,26 +2090,26 @@ fn initSpecialPhdrs(self: *Elf) !void { |
| 2091 | 2090 | |
| 2092 | 2091 | if (self.section_indexes.interp != null and self.phdr_indexes.interp == .none) { |
| 2093 | 2092 | self.phdr_indexes.interp = (try self.addPhdr(.{ |
| 2094 | .type = elf.PT_INTERP, | |
| 2093 | .type = @backingInt(elf.PT.INTERP), | |
| 2095 | 2094 | .flags = elf.PF_R, |
| 2096 | 2095 | .@"align" = 1, |
| 2097 | 2096 | })).toOptional(); |
| 2098 | 2097 | } |
| 2099 | 2098 | if (self.section_indexes.dynamic != null and self.phdr_indexes.dynamic == .none) { |
| 2100 | 2099 | self.phdr_indexes.dynamic = (try self.addPhdr(.{ |
| 2101 | .type = elf.PT_DYNAMIC, | |
| 2100 | .type = @backingInt(elf.PT.DYNAMIC), | |
| 2102 | 2101 | .flags = elf.PF_R | elf.PF_W, |
| 2103 | 2102 | })).toOptional(); |
| 2104 | 2103 | } |
| 2105 | 2104 | if (self.section_indexes.eh_frame_hdr != null and self.phdr_indexes.gnu_eh_frame == .none) { |
| 2106 | 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 | 2107 | .flags = elf.PF_R, |
| 2109 | 2108 | })).toOptional(); |
| 2110 | 2109 | } |
| 2111 | 2110 | if (self.phdr_indexes.gnu_stack == .none) { |
| 2112 | 2111 | self.phdr_indexes.gnu_stack = (try self.addPhdr(.{ |
| 2113 | .type = elf.PT_GNU_STACK, | |
| 2112 | .type = @backingInt(elf.PT.GNU_STACK), | |
| 2114 | 2113 | .flags = elf.PF_W | elf.PF_R, |
| 2115 | 2114 | .memsz = self.base.stack_size, |
| 2116 | 2115 | .@"align" = 1, |
| ... | ... | @@ -2122,7 +2121,7 @@ fn initSpecialPhdrs(self: *Elf) !void { |
| 2122 | 2121 | } else false; |
| 2123 | 2122 | if (has_tls and self.phdr_indexes.tls == .none) { |
| 2124 | 2123 | self.phdr_indexes.tls = (try self.addPhdr(.{ |
| 2125 | .type = elf.PT_TLS, | |
| 2124 | .type = @backingInt(elf.PT.TLS), | |
| 2126 | 2125 | .flags = elf.PF_R, |
| 2127 | 2126 | .@"align" = 1, |
| 2128 | 2127 | })).toOptional(); |
| ... | ... | @@ -2173,7 +2172,7 @@ fn sortInitFini(self: *Elf) !void { |
| 2173 | 2172 | => is_init_fini = true, |
| 2174 | 2173 | else => { |
| 2175 | 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 | 2178 | if (!is_init_fini and !is_ctor_dtor) continue; |
| ... | ... | @@ -2260,15 +2259,15 @@ fn setHashSections(self: *Elf) !void { |
| 2260 | 2259 | } |
| 2261 | 2260 | } |
| 2262 | 2261 | |
| 2263 | fn phdrRank(phdr: elf.Elf64_Phdr) u8 { | |
| 2264 | return switch (phdr.p_type) { | |
| 2265 | elf.PT_NULL => 0, | |
| 2266 | elf.PT_PHDR => 1, | |
| 2267 | elf.PT_INTERP => 2, | |
| 2268 | elf.PT_LOAD => 3, | |
| 2269 | elf.PT_DYNAMIC, elf.PT_TLS => 4, | |
| 2270 | elf.PT_GNU_EH_FRAME => 5, | |
| 2271 | elf.PT_GNU_STACK => 6, | |
| 2262 | fn phdrRank(phdr: elf.Elf64.Phdr) u8 { | |
| 2263 | return switch (phdr.type) { | |
| 2264 | .NULL => 0, | |
| 2265 | .PHDR => 1, | |
| 2266 | .INTERP => 2, | |
| 2267 | .LOAD => 3, | |
| 2268 | .DYNAMIC, .TLS => 4, | |
| 2269 | .GNU_EH_FRAME => 5, | |
| 2270 | .GNU_STACK => 6, | |
| 2272 | 2271 | else => 7, |
| 2273 | 2272 | }; |
| 2274 | 2273 | } |
| ... | ... | @@ -2282,12 +2281,12 @@ fn sortPhdrs( |
| 2282 | 2281 | const Entry = struct { |
| 2283 | 2282 | phndx: u16, |
| 2284 | 2283 | |
| 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 | 2285 | const lhs_phdr = program_headers[lhs.phndx]; |
| 2287 | 2286 | const rhs_phdr = program_headers[rhs.phndx]; |
| 2288 | 2287 | const lhs_rank = phdrRank(lhs_phdr); |
| 2289 | 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 | 2290 | return lhs_rank < rhs_rank; |
| 2292 | 2291 | } |
| 2293 | 2292 | }; |
| ... | ... | @@ -2299,7 +2298,7 @@ fn sortPhdrs( |
| 2299 | 2298 | } |
| 2300 | 2299 | |
| 2301 | 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); | |
| 2303 | 2302 | |
| 2304 | 2303 | const backlinks = try gpa.alloc(u16, entries.len); |
| 2305 | 2304 | defer gpa.free(backlinks); |
| ... | ... | @@ -2655,8 +2654,8 @@ fn addLoadPhdrs(self: *Elf) error{OutOfMemory}!void { |
| 2655 | 2654 | if (shdr.sh_type == elf.SHT_NULL) continue; |
| 2656 | 2655 | if (shdr.sh_flags & elf.SHF_ALLOC == 0) continue; |
| 2657 | 2656 | const flags = shdrToPhdrFlags(shdr.sh_flags); |
| 2658 | if (self.getPhdr(.{ .flags = flags, .type = elf.PT_LOAD }) == .none) { | |
| 2659 | _ = try self.addPhdr(.{ .flags = flags, .type = elf.PT_LOAD }); | |
| 2657 | if (self.getPhdr(.{ .flags = flags, .type = @backingInt(elf.PT.LOAD) }) == .none) { | |
| 2658 | _ = try self.addPhdr(.{ .flags = flags, .type = @backingInt(elf.PT.LOAD) }); | |
| 2660 | 2659 | } |
| 2661 | 2660 | } |
| 2662 | 2661 | } |
| ... | ... | @@ -2672,11 +2671,11 @@ fn allocatePhdrTable(self: *Elf) error{OutOfMemory}!void { |
| 2672 | 2671 | .p64 => @sizeOf(elf.Elf64_Ehdr), |
| 2673 | 2672 | }; |
| 2674 | 2673 | const phsize: u64 = switch (self.ptr_width) { |
| 2675 | .p32 => @sizeOf(elf.Elf32_Phdr), | |
| 2676 | .p64 => @sizeOf(elf.Elf64_Phdr), | |
| 2674 | .p32 => @sizeOf(elf.Elf32.Phdr), | |
| 2675 | .p64 => @sizeOf(elf.Elf64.Phdr), | |
| 2677 | 2676 | }; |
| 2678 | 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); | |
| 2680 | 2679 | |
| 2681 | 2680 | if (needed_size > available_space) { |
| 2682 | 2681 | // In this case, we have two options: |
| ... | ... | @@ -2689,10 +2688,10 @@ fn allocatePhdrTable(self: *Elf) error{OutOfMemory}!void { |
| 2689 | 2688 | err.addNote("required 0x{x}, available 0x{x}", .{ needed_size, available_space }); |
| 2690 | 2689 | } |
| 2691 | 2690 | |
| 2692 | phdr_table_load.p_filesz = needed_size + ehsize; | |
| 2693 | phdr_table_load.p_memsz = needed_size + ehsize; | |
| 2694 | phdr_table.p_filesz = needed_size; | |
| 2695 | phdr_table.p_memsz = needed_size; | |
| 2691 | phdr_table_load.filesz = needed_size + ehsize; | |
| 2692 | phdr_table_load.memsz = needed_size + ehsize; | |
| 2693 | phdr_table.filesz = needed_size; | |
| 2694 | phdr_table.memsz = needed_size; | |
| 2696 | 2695 | } |
| 2697 | 2696 | |
| 2698 | 2697 | /// Allocates alloc sections and creates load segments for sections |
| ... | ... | @@ -2758,7 +2757,7 @@ pub fn allocateAllocSections(self: *Elf) !void { |
| 2758 | 2757 | // of any section that is contained in a cover and use it to align |
| 2759 | 2758 | // the start address of the segement (and first section). |
| 2760 | 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; | |
| 2762 | 2761 | |
| 2763 | 2762 | for (covers) |cover| { |
| 2764 | 2763 | if (cover.items.len == 0) continue; |
| ... | ... | @@ -2817,14 +2816,14 @@ pub fn allocateAllocSections(self: *Elf) !void { |
| 2817 | 2816 | } |
| 2818 | 2817 | |
| 2819 | 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 | 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 | 2822 | if (filesz > allocated_size) { |
| 2824 | const old_offset = phdr.p_offset; | |
| 2825 | phdr.p_offset = 0; | |
| 2823 | const old_offset = phdr.offset; | |
| 2824 | phdr.offset = 0; | |
| 2826 | 2825 | var new_offset = try self.findFreeSpace(filesz, @"align"); |
| 2827 | phdr.p_offset = new_offset; | |
| 2826 | phdr.offset = new_offset; | |
| 2828 | 2827 | |
| 2829 | 2828 | log.debug("moving phdr({d}) from 0x{x} to 0x{x}", .{ phndx, old_offset, new_offset }); |
| 2830 | 2829 | |
| ... | ... | @@ -2854,11 +2853,11 @@ pub fn allocateAllocSections(self: *Elf) !void { |
| 2854 | 2853 | } |
| 2855 | 2854 | } |
| 2856 | 2855 | |
| 2857 | phdr.p_vaddr = first.sh_addr; | |
| 2858 | phdr.p_paddr = first.sh_addr; | |
| 2859 | phdr.p_memsz = memsz; | |
| 2860 | phdr.p_filesz = filesz; | |
| 2861 | phdr.p_align = @"align"; | |
| 2856 | phdr.vaddr = first.sh_addr; | |
| 2857 | phdr.paddr = first.sh_addr; | |
| 2858 | phdr.memsz = memsz; | |
| 2859 | phdr.filesz = filesz; | |
| 2860 | phdr.@"align" = @"align"; | |
| 2862 | 2861 | |
| 2863 | 2862 | addr = mem.alignForward(u64, addr, self.page_size); |
| 2864 | 2863 | } |
| ... | ... | @@ -2902,12 +2901,12 @@ fn allocateSpecialPhdrs(self: *Elf) void { |
| 2902 | 2901 | if (pair[0].int()) |index| { |
| 2903 | 2902 | const shdr = slice.items(.shdr)[pair[1].?]; |
| 2904 | 2903 | const phdr = &self.phdrs.items[index]; |
| 2905 | phdr.p_align = shdr.sh_addralign; | |
| 2906 | phdr.p_offset = shdr.sh_offset; | |
| 2907 | phdr.p_vaddr = shdr.sh_addr; | |
| 2908 | phdr.p_paddr = shdr.sh_addr; | |
| 2909 | phdr.p_filesz = shdr.sh_size; | |
| 2910 | phdr.p_memsz = shdr.sh_size; | |
| 2904 | phdr.@"align" = shdr.sh_addralign; | |
| 2905 | phdr.offset = shdr.sh_offset; | |
| 2906 | phdr.vaddr = shdr.sh_addr; | |
| 2907 | phdr.paddr = shdr.sh_addr; | |
| 2908 | phdr.filesz = shdr.sh_size; | |
| 2909 | phdr.memsz = shdr.sh_size; | |
| 2911 | 2910 | } |
| 2912 | 2911 | } |
| 2913 | 2912 | |
| ... | ... | @@ -2924,25 +2923,25 @@ fn allocateSpecialPhdrs(self: *Elf) void { |
| 2924 | 2923 | shndx += 1; |
| 2925 | 2924 | continue; |
| 2926 | 2925 | } |
| 2927 | phdr.p_offset = shdr.sh_offset; | |
| 2928 | phdr.p_vaddr = shdr.sh_addr; | |
| 2929 | phdr.p_paddr = shdr.sh_addr; | |
| 2930 | phdr.p_align = shdr.sh_addralign; | |
| 2926 | phdr.offset = shdr.sh_offset; | |
| 2927 | phdr.vaddr = shdr.sh_addr; | |
| 2928 | phdr.paddr = shdr.sh_addr; | |
| 2929 | phdr.@"align" = shdr.sh_addralign; | |
| 2931 | 2930 | shndx += 1; |
| 2932 | phdr.p_align = @max(phdr.p_align, shdr.sh_addralign); | |
| 2931 | phdr.@"align" = @max(phdr.@"align", shdr.sh_addralign); | |
| 2933 | 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; | |
| 2937 | 2936 | |
| 2938 | 2937 | while (shndx < shdrs.len) : (shndx += 1) { |
| 2939 | 2938 | const next = shdrs[shndx]; |
| 2940 | 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 | 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 | 3346 | return @intCast(@divExact(self.getTarget().ptrBitWidth(), 8)); |
| 3348 | 3347 | } |
| 3349 | 3348 | |
| 3350 | fn phdrTo32(phdr: elf.Elf64_Phdr) elf.Elf32_Phdr { | |
| 3349 | fn phdrTo32(phdr: elf.Elf64.Phdr) elf.Elf32.Phdr { | |
| 3351 | 3350 | return .{ |
| 3352 | .p_type = phdr.p_type, | |
| 3353 | .p_flags = phdr.p_flags, | |
| 3354 | .p_offset = @as(u32, @intCast(phdr.p_offset)), | |
| 3355 | .p_vaddr = @as(u32, @intCast(phdr.p_vaddr)), | |
| 3356 | .p_paddr = @as(u32, @intCast(phdr.p_paddr)), | |
| 3357 | .p_filesz = @as(u32, @intCast(phdr.p_filesz)), | |
| 3358 | .p_memsz = @as(u32, @intCast(phdr.p_memsz)), | |
| 3359 | .p_align = @as(u32, @intCast(phdr.p_align)), | |
| 3351 | .type = phdr.type, | |
| 3352 | .flags = phdr.flags, | |
| 3353 | .offset = @intCast(phdr.offset), | |
| 3354 | .vaddr = @intCast(phdr.vaddr), | |
| 3355 | .paddr = @intCast(phdr.paddr), | |
| 3356 | .filesz = @intCast(phdr.filesz), | |
| 3357 | .memsz = @intCast(phdr.memsz), | |
| 3358 | .@"align" = @intCast(phdr.@"align"), | |
| 3360 | 3359 | }; |
| 3361 | 3360 | } |
| 3362 | 3361 | |
| ... | ... | @@ -3397,7 +3396,7 @@ fn getPhdr(self: *Elf, opts: struct { |
| 3397 | 3396 | if (self.phdr_indexes.table_load.int()) |index| { |
| 3398 | 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 | 3400 | return @fromBackingInt(@intCast(phndx)); |
| 3402 | 3401 | } |
| 3403 | 3402 | return .none; |
| ... | ... | @@ -3415,14 +3414,14 @@ fn addPhdr(self: *Elf, opts: struct { |
| 3415 | 3414 | const gpa = self.base.comp.gpa; |
| 3416 | 3415 | const index: ProgramHeaderIndex = @fromBackingInt(@intCast(self.phdrs.items.len)); |
| 3417 | 3416 | try self.phdrs.append(gpa, .{ |
| 3418 | .p_type = opts.type, | |
| 3419 | .p_flags = opts.flags, | |
| 3420 | .p_offset = opts.offset, | |
| 3421 | .p_vaddr = opts.addr, | |
| 3422 | .p_paddr = opts.addr, | |
| 3423 | .p_filesz = opts.filesz, | |
| 3424 | .p_memsz = opts.memsz, | |
| 3425 | .p_align = opts.@"align", | |
| 3417 | .type = @fromBackingInt(opts.type), | |
| 3418 | .flags = @fromBackingInt(opts.flags), | |
| 3419 | .offset = opts.offset, | |
| 3420 | .vaddr = opts.addr, | |
| 3421 | .paddr = opts.addr, | |
| 3422 | .filesz = opts.filesz, | |
| 3423 | .memsz = opts.memsz, | |
| 3424 | .@"align" = opts.@"align", | |
| 3426 | 3425 | }); |
| 3427 | 3426 | return index; |
| 3428 | 3427 | } |
| ... | ... | @@ -3673,9 +3672,9 @@ pub fn tpAddress(self: *Elf) i64 { |
| 3673 | 3672 | const index = self.phdr_indexes.tls.int() orelse return 0; |
| 3674 | 3673 | const phdr = self.phdrs.items[index]; |
| 3675 | 3674 | const addr = switch (self.getTarget().cpu.arch) { |
| 3676 | .x86_64 => mem.alignForward(u64, phdr.p_vaddr + phdr.p_memsz, phdr.p_align), | |
| 3677 | .aarch64, .aarch64_be => mem.alignBackward(u64, phdr.p_vaddr - 16, phdr.p_align), | |
| 3678 | .riscv64, .riscv64be => phdr.p_vaddr, | |
| 3675 | .x86_64 => mem.alignForward(u64, phdr.vaddr + phdr.memsz, phdr.@"align"), | |
| 3676 | .aarch64, .aarch64_be => mem.alignBackward(u64, phdr.vaddr - 16, phdr.@"align"), | |
| 3677 | .riscv64, .riscv64be => phdr.vaddr, | |
| 3679 | 3678 | else => |arch| std.debug.panic("TODO implement getTpAddress for {s}", .{@tagName(arch)}), |
| 3680 | 3679 | }; |
| 3681 | 3680 | return @intCast(addr); |
| ... | ... | @@ -3684,13 +3683,13 @@ pub fn tpAddress(self: *Elf) i64 { |
| 3684 | 3683 | pub fn dtpAddress(self: *Elf) i64 { |
| 3685 | 3684 | const index = self.phdr_indexes.tls.int() orelse return 0; |
| 3686 | 3685 | const phdr = self.phdrs.items[index]; |
| 3687 | return @intCast(phdr.p_vaddr); | |
| 3686 | return @intCast(phdr.vaddr); | |
| 3688 | 3687 | } |
| 3689 | 3688 | |
| 3690 | 3689 | pub fn tlsAddress(self: *Elf) i64 { |
| 3691 | 3690 | const index = self.phdr_indexes.tls.int() orelse return 0; |
| 3692 | 3691 | const phdr = self.phdrs.items[index]; |
| 3693 | return @intCast(phdr.p_vaddr); | |
| 3692 | return @intCast(phdr.vaddr); | |
| 3694 | 3693 | } |
| 3695 | 3694 | |
| 3696 | 3695 | pub fn getShString(self: Elf, off: u32) [:0]const u8 { |
| ... | ... | @@ -3702,7 +3701,7 @@ fn shString( |
| 3702 | 3701 | off: u32, |
| 3703 | 3702 | ) [:0]const u8 { |
| 3704 | 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 | } |
| 3707 | 3706 | |
| 3708 | 3707 | pub 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 | 3885 | |
| 3887 | 3886 | const FormatPhdr = struct { |
| 3888 | 3887 | elf_file: *Elf, |
| 3889 | phdr: elf.Elf64_Phdr, | |
| 3888 | phdr: elf.Elf64.Phdr, | |
| 3890 | 3889 | }; |
| 3891 | 3890 | |
| 3892 | fn fmtPhdr(self: *Elf, phdr: elf.Elf64_Phdr) std.fmt.Alt(FormatPhdr, formatPhdr) { | |
| 3891 | fn fmtPhdr(self: *Elf, phdr: elf.Elf64.Phdr) std.fmt.Alt(FormatPhdr, formatPhdr) { | |
| 3893 | 3892 | return .{ .data = .{ |
| 3894 | 3893 | .phdr = phdr, |
| 3895 | 3894 | .elf_file = self, |
| ... | ... | @@ -3898,28 +3897,28 @@ fn fmtPhdr(self: *Elf, phdr: elf.Elf64_Phdr) std.fmt.Alt(FormatPhdr, formatPhdr) |
| 3898 | 3897 | |
| 3899 | 3898 | fn formatPhdr(ctx: FormatPhdr, writer: *std.Io.Writer) std.Io.Writer.Error!void { |
| 3900 | 3899 | const phdr = ctx.phdr; |
| 3901 | const write = phdr.p_flags & elf.PF_W != 0; | |
| 3902 | const read = phdr.p_flags & elf.PF_R != 0; | |
| 3903 | const exec = phdr.p_flags & elf.PF_X != 0; | |
| 3900 | const write = phdr.flags.W; | |
| 3901 | const read = phdr.flags.R; | |
| 3902 | const exec = phdr.flags.X; | |
| 3904 | 3903 | var flags: [3]u8 = @splat('_'); |
| 3905 | 3904 | if (exec) flags[0] = 'X'; |
| 3906 | 3905 | if (write) flags[1] = 'W'; |
| 3907 | 3906 | if (read) flags[2] = 'R'; |
| 3908 | const p_type = switch (phdr.p_type) { | |
| 3909 | elf.PT_LOAD => "LOAD", | |
| 3910 | elf.PT_TLS => "TLS", | |
| 3911 | elf.PT_GNU_EH_FRAME => "GNU_EH_FRAME", | |
| 3912 | elf.PT_GNU_STACK => "GNU_STACK", | |
| 3913 | elf.PT_DYNAMIC => "DYNAMIC", | |
| 3914 | elf.PT_INTERP => "INTERP", | |
| 3915 | elf.PT_NULL => "NULL", | |
| 3916 | elf.PT_PHDR => "PHDR", | |
| 3917 | elf.PT_NOTE => "NOTE", | |
| 3907 | const p_type = switch (phdr.type) { | |
| 3908 | .LOAD => "LOAD", | |
| 3909 | .TLS => "TLS", | |
| 3910 | .GNU_EH_FRAME => "GNU_EH_FRAME", | |
| 3911 | .GNU_STACK => "GNU_STACK", | |
| 3912 | .DYNAMIC => "DYNAMIC", | |
| 3913 | .INTERP => "INTERP", | |
| 3914 | .NULL => "NULL", | |
| 3915 | .PHDR => "PHDR", | |
| 3916 | .NOTE => "NOTE", | |
| 3918 | 3917 | else => "UNKNOWN", |
| 3919 | 3918 | }; |
| 3920 | 3919 | try writer.print("{s} : {s} : @{x} ({x}) : align({x}) : filesz({x}) : memsz({x})", .{ |
| 3921 | p_type, flags, phdr.p_offset, phdr.p_vaddr, | |
| 3922 | phdr.p_align, phdr.p_filesz, phdr.p_memsz, | |
| 3920 | p_type, flags, phdr.offset, phdr.vaddr, | |
| 3921 | phdr.@"align", phdr.filesz, phdr.memsz, | |
| 3923 | 3922 | }); |
| 3924 | 3923 | } |
| 3925 | 3924 | |
| ... | ... | @@ -4376,7 +4375,7 @@ fn createThunks(elf_file: *Elf, atom_list: *AtomList) !void { |
| 4376 | 4375 | |
| 4377 | 4376 | pub fn stringTableLookup(strtab: []const u8, off: u32) [:0]const u8 { |
| 4378 | 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 | } |
| 4381 | 4380 | |
| 4382 | 4381 | pub 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 | 118 | |
| 119 | 119 | pub fn stringTableLookup(strtab: []const u8, off: u32) [:'\n']const u8 { |
| 120 | 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 | } |
| 123 | 123 | |
| 124 | 124 | pub fn setArHdr(opts: struct { |
src/link/Elf/ZigObject.zig+4-4| ... | ... | @@ -1299,7 +1299,7 @@ fn getNavShdrIndex( |
| 1299 | 1299 | } |
| 1300 | 1300 | if (nav_val.isUndef(zcu)) |
| 1301 | 1301 | return switch (zcu.navFileScope(nav_index).mod.?.optimize_mode) { |
| 1302 | .Debug, .ReleaseSafe => { | |
| 1302 | .debug, .safe => { | |
| 1303 | 1303 | if (self.data_index) |symbol_index| |
| 1304 | 1304 | return self.symbol(symbol_index).outputShndx(elf_file).?; |
| 1305 | 1305 | const osec = try elf_file.addSection(.{ |
| ... | ... | @@ -1311,7 +1311,7 @@ fn getNavShdrIndex( |
| 1311 | 1311 | self.data_index = try self.addSectionSymbol(gpa, try self.addString(gpa, ".data"), osec); |
| 1312 | 1312 | return osec; |
| 1313 | 1313 | }, |
| 1314 | .ReleaseFast, .ReleaseSmall => { | |
| 1314 | .fast, .small => { | |
| 1315 | 1315 | if (self.bss_index) |symbol_index| |
| 1316 | 1316 | return self.symbol(symbol_index).outputShndx(elf_file).?; |
| 1317 | 1317 | const osec = try elf_file.addSection(.{ |
| ... | ... | @@ -1374,8 +1374,8 @@ fn updateNavCode( |
| 1374 | 1374 | const target = &mod.resolved_target.result; |
| 1375 | 1375 | const required_alignment = switch (nav.resolved.?.@"align") { |
| 1376 | 1376 | .none => switch (mod.optimize_mode) { |
| 1377 | .Debug, .ReleaseSafe, .ReleaseFast => target_util.defaultFunctionAlignment(target), | |
| 1378 | .ReleaseSmall => target_util.minFunctionAlignment(target), | |
| 1377 | .debug, .safe, .fast => target_util.defaultFunctionAlignment(target), | |
| 1378 | .small => target_util.minFunctionAlignment(target), | |
| 1379 | 1379 | }.maxStrict(Type.fromInterned(nav.resolved.?.type).abiAlignment(zcu)), |
| 1380 | 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 | 126 | inputs: std.ArrayList(struct { |
| 127 | 127 | path: std.Build.Cache.Path, |
| 128 | 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 | }), |
| 136 | input_pending_index: u32, | |
| 131 | 137 | input_sections: std.ArrayList(InputSection), |
| 132 | 138 | input_section_pending_index: u32, |
| 133 | 139 | navs: std.array_hash_map.Auto(InternPool.Nav.Index, struct { |
| ... | ... | @@ -181,7 +187,10 @@ input_prog_node: std.Progress.Node, |
| 181 | 187 | const Error = link.Error || error{MappedFileIo}; |
| 182 | 188 | |
| 183 | 189 | const Node = union(enum) { |
| 184 | file, | |
| 190 | archive, | |
| 191 | /// This includes the archive magic and long file member. | |
| 192 | archive_header, | |
| 193 | elf, | |
| 185 | 194 | ehdr, |
| 186 | 195 | shdr, |
| 187 | 196 | segment: u32, |
| ... | ... | @@ -189,6 +198,8 @@ const Node = union(enum) { |
| 189 | 198 | /// |
| 190 | 199 | /// The section '.dynamic' may contain relocations via `elf.dynamic_first_symbol_reloc`. |
| 191 | 200 | section: Section.Index, |
| 201 | /// Only valid for static libraries, represents one non-zcu archive member. | |
| 202 | input_member: InputIndex, | |
| 192 | 203 | /// May contain relocations. |
| 193 | 204 | input_section: InputSection.Index, |
| 194 | 205 | /// 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 | 230 | return elf.inputs.items[@backingInt(ii)].member; |
| 220 | 231 | } |
| 221 | 232 | |
| 233 | pub fn node(ii: InputIndex, elf: *const Elf) MappedFile.Node.Index { | |
| 234 | return elf.inputs.items[@backingInt(ii)].extra.node; | |
| 235 | } | |
| 236 | ||
| 222 | 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 | } |
| 225 | 240 | |
| 226 | 241 | pub fn localSymbolRange(ii: InputIndex, elf: *Elf) [2]Symbol.LocalIndex { |
| 227 | 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 | 244 | return .{ ii.fileSymbol(elf), next_ii.fileSymbol(elf) }; |
| 230 | 245 | } else { |
| 231 | 246 | const local_symbols_len = switch (elf.shdrPtr(.symtab)) { |
| 232 | 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 | 330 | }; |
| 316 | 331 | |
| 317 | 332 | pub const Known = struct { |
| 318 | comptime file: MappedFile.Node.Index = .root, | |
| 319 | comptime ehdr: MappedFile.Node.Index = @fromBackingInt(@intCast(1)), | |
| 320 | comptime shdr: MappedFile.Node.Index = @fromBackingInt(@intCast(2)), | |
| 321 | comptime rodata: MappedFile.Node.Index = @fromBackingInt(@intCast(3)), | |
| 322 | comptime phdr: MappedFile.Node.Index = @fromBackingInt(@intCast(4)), | |
| 323 | comptime text: MappedFile.Node.Index = @fromBackingInt(@intCast(5)), | |
| 324 | comptime data: MappedFile.Node.Index = @fromBackingInt(@intCast(6)), | |
| 325 | comptime data_rel_ro: MappedFile.Node.Index = @fromBackingInt(@intCast(7)), | |
| 326 | ||
| 333 | archive: MappedFile.Node.Index, | |
| 334 | archive_header: MappedFile.Node.Index, | |
| 335 | elf: MappedFile.Node.Index, | |
| 336 | ehdr: MappedFile.Node.Index, | |
| 337 | shdr: MappedFile.Node.Index, | |
| 338 | rodata: MappedFile.Node.Index, | |
| 339 | phdr: MappedFile.Node.Index, | |
| 340 | text: MappedFile.Node.Index, | |
| 341 | data: MappedFile.Node.Index, | |
| 342 | data_rel_ro: MappedFile.Node.Index, | |
| 327 | 343 | tls: MappedFile.Node.Index, |
| 328 | 344 | }; |
| 329 | 345 | |
| ... | ... | @@ -333,11 +349,11 @@ const Node = union(enum) { |
| 333 | 349 | |
| 334 | 350 | /// In this linker implementation, `link.File.AtomId` is a type-erased `MappedFile.Node.Index`. |
| 335 | 351 | fn toAtom(ni: MappedFile.Node.Index) link.File.AtomId { |
| 336 | return @fromBackingInt(@intCast(@backingInt(ni))); | |
| 352 | return @fromBackingInt(@backingInt(ni)); | |
| 337 | 353 | } |
| 338 | 354 | /// In this linker implementation, `link.File.AtomId` is a type-erased `MappedFile.Node.Index`. |
| 339 | 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 | }; |
| 343 | 359 | |
| ... | ... | @@ -424,13 +440,13 @@ const Section = struct { |
| 424 | 440 | fn unwrap(opt: RelaIndex.Optional) ?RelaIndex { |
| 425 | 441 | return switch (opt) { |
| 426 | 442 | .none => null, |
| 427 | _ => @fromBackingInt(@intCast(@backingInt(opt))), | |
| 443 | _ => @fromBackingInt(@backingInt(opt)), | |
| 428 | 444 | }; |
| 429 | 445 | } |
| 430 | 446 | }; |
| 431 | 447 | |
| 432 | 448 | fn toOptional(i: RelaIndex) RelaIndex.Optional { |
| 433 | return @fromBackingInt(@intCast(@backingInt(i))); | |
| 449 | return @fromBackingInt(@backingInt(i)); | |
| 434 | 450 | } |
| 435 | 451 | }; |
| 436 | 452 | |
| ... | ... | @@ -465,8 +481,8 @@ const Section = struct { |
| 465 | 481 | |
| 466 | 482 | pub fn fromSection(sec: std.elf.Section) Index { |
| 467 | 483 | return switch (sec) { |
| 468 | std.elf.SHN_UNDEF...std.elf.SHN_LORESERVE - 1 => @fromBackingInt(@intCast(sec)), | |
| 469 | std.elf.SHN_LORESERVE...std.elf.SHN_HIRESERVE => @fromBackingInt(@intCast(reserve(sec))), | |
| 484 | std.elf.SHN_UNDEF...std.elf.SHN_LORESERVE - 1 => @fromBackingInt(sec), | |
| 485 | std.elf.SHN_LORESERVE...std.elf.SHN_HIRESERVE => @fromBackingInt(reserve(sec)), | |
| 470 | 486 | }; |
| 471 | 487 | } |
| 472 | 488 | pub fn toSection(s: Index) ?std.elf.Section { |
| ... | ... | @@ -485,7 +501,7 @@ const Section = struct { |
| 485 | 501 | |
| 486 | 502 | fn name(s: Index, elf: *Elf) String(.shstrtab) { |
| 487 | 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 | } |
| 491 | 507 | |
| ... | ... | @@ -928,21 +944,7 @@ const GotReloc = struct { |
| 928 | 944 | } |
| 929 | 945 | } |
| 930 | 946 | fn applyInner(reloc: *const GotReloc, elf: *Elf) error{ RelocationOverflow, RelocationMisaligned }!void { |
| 931 | const node_vaddr: u64 = switch (elf.getNode(reloc.node)) { | |
| 932 | .file => unreachable, | |
| 933 | .ehdr => unreachable, | |
| 934 | .shdr => unreachable, | |
| 935 | .segment => unreachable, | |
| 936 | .copied_global => unreachable, | |
| 937 | .section => |shndx| shndx.vaddr(elf), | |
| 938 | .input_section => |isi| isi.ptrConst(elf).vaddr, | |
| 939 | inline .nav, | |
| 940 | .uav, | |
| 941 | .lazy_code, | |
| 942 | .lazy_const_data, | |
| 943 | => |i| Symbol.Id.local(i.symbol(elf)).value(elf), | |
| 944 | }; | |
| 945 | const dest_vaddr = node_vaddr + reloc.offset; | |
| 947 | const dest_vaddr = elf.getNodeVAddr(reloc.node) + reloc.offset; | |
| 946 | 948 | const dest_slice = reloc.node.slice(&elf.mf)[@intCast(reloc.offset)..]; |
| 947 | 949 | |
| 948 | 950 | const got_vaddr = elf.shndx.got.vaddr(elf); |
| ... | ... | @@ -1131,12 +1133,12 @@ pub const MachineRelocType = union { |
| 1131 | 1133 | |
| 1132 | 1134 | pub fn wrap(int: u32, elf: *const Elf) MachineRelocType { |
| 1133 | 1135 | return switch (elf.ehdrMachine()) { |
| 1134 | .AARCH64 => .{ .AARCH64 = @fromBackingInt(@intCast(int)) }, | |
| 1135 | .LOONGARCH => .{ .LARCH = @fromBackingInt(@intCast(int)) }, | |
| 1136 | .PPC64 => .{ .PPC64 = @fromBackingInt(@intCast(int)) }, | |
| 1137 | .RISCV => .{ .RISCV = @fromBackingInt(@intCast(int)) }, | |
| 1138 | .SPARCV9 => .{ .SPARC = @fromBackingInt(@intCast(int)) }, | |
| 1139 | .X86_64 => .{ .X86_64 = @fromBackingInt(@intCast(int)) }, | |
| 1136 | .AARCH64 => .{ .AARCH64 = @fromBackingInt(int) }, | |
| 1137 | .LOONGARCH => .{ .LARCH = @fromBackingInt(int) }, | |
| 1138 | .PPC64 => .{ .PPC64 = @fromBackingInt(int) }, | |
| 1139 | .RISCV => .{ .RISCV = @fromBackingInt(int) }, | |
| 1140 | .SPARCV9 => .{ .SPARC = @fromBackingInt(int) }, | |
| 1141 | .X86_64 => .{ .X86_64 = @fromBackingInt(int) }, | |
| 1140 | 1142 | }; |
| 1141 | 1143 | } |
| 1142 | 1144 | pub fn unwrap(rt: MachineRelocType, elf: *const Elf) u32 { |
| ... | ... | @@ -1646,21 +1648,7 @@ const SymbolReloc = struct { |
| 1646 | 1648 | } |
| 1647 | 1649 | } |
| 1648 | 1650 | fn applyInner(reloc: *const SymbolReloc, elf: *Elf) error{ RelocationOverflow, RelocationMisaligned }!void { |
| 1649 | const node_vaddr: u64 = switch (elf.getNode(reloc.node)) { | |
| 1650 | .file => unreachable, | |
| 1651 | .ehdr => unreachable, | |
| 1652 | .shdr => unreachable, | |
| 1653 | .segment => unreachable, | |
| 1654 | .copied_global => unreachable, | |
| 1655 | .section => |shndx| shndx.vaddr(elf), | |
| 1656 | .input_section => |isi| isi.ptrConst(elf).vaddr, | |
| 1657 | inline .nav, | |
| 1658 | .uav, | |
| 1659 | .lazy_code, | |
| 1660 | .lazy_const_data, | |
| 1661 | => |i| Symbol.Id.local(i.symbol(elf)).value(elf), | |
| 1662 | }; | |
| 1663 | const dest_vaddr = node_vaddr + reloc.offset; | |
| 1651 | const dest_vaddr = elf.getNodeVAddr(reloc.node) + reloc.offset; | |
| 1664 | 1652 | const dest_slice = reloc.node.slice(&elf.mf)[@intCast(reloc.offset)..]; |
| 1665 | 1653 | |
| 1666 | 1654 | const addend: u64 = @bitCast(reloc.addend); |
| ... | ... | @@ -1875,7 +1863,7 @@ fn addLocalSymbolAssumeCapacity(elf: *Elf, opts: AddLocalSymbolOptions) Symbol.L |
| 1875 | 1863 | |
| 1876 | 1864 | // `shdr.info` stores the index of the first global symbol. We will replace it with our |
| 1877 | 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)); | |
| 1879 | 1867 | |
| 1880 | 1868 | const old_size = elf.targetLoad(&shdr.size); |
| 1881 | 1869 | const new_size = old_size + ent_size; |
| ... | ... | @@ -1897,7 +1885,7 @@ fn addLocalSymbolAssumeCapacity(elf: *Elf, opts: AddLocalSymbolOptions) Symbol.L |
| 1897 | 1885 | // ...then the `elf.symtab` metadata... |
| 1898 | 1886 | new_index.ptr(elf).* = target_index.ptr(elf).*; |
| 1899 | 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 | 1889 | elf.globalByName(global_name).?.symtab_index = new_index; |
| 1902 | 1890 | |
| 1903 | 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 | 1911 | std.mem.byteSwapAllFields(class.ElfN().Sym, target_sym); |
| 1924 | 1912 | } |
| 1925 | 1913 | |
| 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 | 2359 | inline else => |shdr, class| { |
| 2372 | 2360 | // `shdr.info` stores the index of the first global symbol. We are going to swap the |
| 2373 | 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 | 2363 | const src_index = global_ptr.symtab_index; |
| 2376 | 2364 | |
| 2377 | 2365 | // 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 | 2375 | const src_sym_ptr = @field(elf.symPtr(src_index), @tagName(class)); |
| 2388 | 2376 | const dest_sym_ptr = @field(elf.symPtr(dest_index), @tagName(class)); |
| 2389 | 2377 | |
| 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 | 2379 | assert(elf.globalByName(this_name).? == global_ptr); |
| 2392 | 2380 | |
| 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 | 2382 | const other_global_ptr = elf.globalByName(other_name).?; |
| 2395 | 2383 | assert(other_global_ptr.symtab_index == dest_index); |
| 2396 | 2384 | |
| ... | ... | @@ -2426,7 +2414,7 @@ fn moveDemotedGlobal(elf: *Elf, global_ptr: *Symbol.Global) void { |
| 2426 | 2414 | const src_dynsym_ptr = @field(elf.dynsymPtr(remove_dynsym_index), @tagName(class)); |
| 2427 | 2415 | const dest_dynsym_ptr = @field(elf.dynsymPtr(free_dynsym_index), @tagName(class)); |
| 2428 | 2416 | |
| 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 | 2418 | const moved_name = elf.stringExisting(.strtab, moved_name_dynstr.slice(elf)); |
| 2431 | 2419 | const moved_global_ptr = elf.globalByName(moved_name).?; |
| 2432 | 2420 | |
| ... | ... | @@ -2505,7 +2493,7 @@ const Symbol = struct { |
| 2505 | 2493 | _, |
| 2506 | 2494 | |
| 2507 | 2495 | fn index(li: LocalIndex) Index { |
| 2508 | return @fromBackingInt(@intCast(@backingInt(li))); | |
| 2496 | return @fromBackingInt(@backingInt(li)); | |
| 2509 | 2497 | } |
| 2510 | 2498 | }; |
| 2511 | 2499 | |
| ... | ... | @@ -2527,16 +2515,16 @@ const Symbol = struct { |
| 2527 | 2515 | global: String(.strtab), |
| 2528 | 2516 | } { |
| 2529 | 2517 | return switch (s.kind) { |
| 2530 | .local => .{ .local = @fromBackingInt(@intCast(s.raw)) }, | |
| 2531 | .global => .{ .global = @fromBackingInt(@intCast(s.raw)) }, | |
| 2518 | .local => .{ .local = @fromBackingInt(s.raw) }, | |
| 2519 | .global => .{ .global = @fromBackingInt(s.raw) }, | |
| 2532 | 2520 | }; |
| 2533 | 2521 | } |
| 2534 | 2522 | |
| 2535 | 2523 | fn toTypeErased(s: Symbol.Id) link.File.SymbolId { |
| 2536 | return @fromBackingInt(@intCast(@as(u32, @bitCast(s)))); | |
| 2524 | return @bitCast(s); | |
| 2537 | 2525 | } |
| 2538 | 2526 | fn fromTypeErased(s: link.File.SymbolId) Symbol.Id { |
| 2539 | return @bitCast(@backingInt(s)); | |
| 2527 | return @bitCast(s); | |
| 2540 | 2528 | } |
| 2541 | 2529 | |
| 2542 | 2530 | fn index(s: Symbol.Id, elf: *const Elf) Symbol.Index { |
| ... | ... | @@ -2648,24 +2636,10 @@ const Symbol = struct { |
| 2648 | 2636 | .yes_textrel => elf.textrel_count += 1, |
| 2649 | 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 | 2639 | // There is capacity for a relocation because we just deleted one earlier. |
| 2666 | 2640 | reloc.rela_index = elf.shndx.rela_dyn.relaAddOneAssumeCapacity(elf, .{ |
| 2667 | 2641 | .type = .relative(elf), |
| 2668 | .offset = node_vaddr + reloc.offset, | |
| 2642 | .offset = elf.getNodeVAddr(reloc.node) + reloc.offset, | |
| 2669 | 2643 | .raw_sym_index = 0, |
| 2670 | 2644 | .addend = 0, |
| 2671 | 2645 | }).toOptional(); |
| ... | ... | @@ -2771,11 +2745,14 @@ fn classifySymbolValue(elf: *Elf, sym: Symbol.Id) enum { |
| 2771 | 2745 | |
| 2772 | 2746 | pub fn symbolForAtom(elf: *Elf, atom: link.File.AtomId) link.File.SymbolId { |
| 2773 | 2747 | const lsi: Symbol.LocalIndex = switch (elf.getNode(Node.fromAtom(atom))) { |
| 2774 | .file, | |
| 2748 | .archive, | |
| 2749 | .archive_header, | |
| 2750 | .elf, | |
| 2775 | 2751 | .ehdr, |
| 2776 | 2752 | .shdr, |
| 2777 | 2753 | .segment, |
| 2778 | 2754 | .section, |
| 2755 | .input_member, | |
| 2779 | 2756 | .input_section, |
| 2780 | 2757 | .copied_global, |
| 2781 | 2758 | => unreachable, |
| ... | ... | @@ -3001,12 +2978,12 @@ fn String(section: StringSection) type { |
| 3001 | 2978 | } |
| 3002 | 2979 | fn string(elf: *Elf, comptime section: StringSection, key: []const u8) Error!String(section) { |
| 3003 | 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 | 2983 | /// Like `string`, but asserts that the string is already in `section`. |
| 3007 | 2984 | fn stringExisting(elf: *Elf, comptime section: StringSection, key: []const u8) String(section) { |
| 3008 | 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 | } |
| 3011 | 2988 | |
| 3012 | 2989 | const StringTable = struct { |
| ... | ... | @@ -3033,7 +3010,7 @@ const StringTable = struct { |
| 3033 | 3010 | } |
| 3034 | 3011 | |
| 3035 | 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 | 3014 | return std.hash_map.hashString(key); |
| 3038 | 3015 | } |
| 3039 | 3016 | }; |
| ... | ... | @@ -3172,6 +3149,16 @@ fn create( |
| 3172 | 3149 | .options = options, |
| 3173 | 3150 | .mf = try .init(file, comp.gpa, io), |
| 3174 | 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 | 3162 | .tls = .none, |
| 3176 | 3163 | }, |
| 3177 | 3164 | .nodes = .empty, |
| ... | ... | @@ -3218,6 +3205,7 @@ fn create( |
| 3218 | 3205 | .dynamic_first_symbol_reloc = .none, |
| 3219 | 3206 | .needed = .empty, |
| 3220 | 3207 | .inputs = .empty, |
| 3208 | .input_pending_index = 0, | |
| 3221 | 3209 | .input_sections = .empty, |
| 3222 | 3210 | .input_section_pending_index = 0, |
| 3223 | 3211 | .navs = .empty, |
| ... | ... | @@ -3293,6 +3281,7 @@ fn initHeaders( |
| 3293 | 3281 | const comp = elf.base.comp; |
| 3294 | 3282 | const gpa = comp.gpa; |
| 3295 | 3283 | |
| 3284 | const is_archive = comp.config.output_mode == .Lib and comp.config.link_mode == .static; | |
| 3296 | 3285 | const have_dynamic_section = switch (@"type") { |
| 3297 | 3286 | .REL => false, |
| 3298 | 3287 | .EXEC => comp.config.link_mode == .dynamic, |
| ... | ... | @@ -3389,7 +3378,8 @@ fn initHeaders( |
| 3389 | 3378 | }, phnum }; |
| 3390 | 3379 | }; |
| 3391 | 3380 | |
| 3392 | const expected_nodes_len = 3 + // `.file`, `.ehdr`, and `.shdr` nodes | |
| 3381 | const expected_nodes_len = @as(usize, if (is_archive) 2 else 0) + // .archive, .archive_header | |
| 3382 | 3 + // `.file`, `.ehdr`, and `.shdr` nodes | |
| 3393 | 3383 | (shnum - 1) + // -1 because the null shdr does not have a `.section` node |
| 3394 | 3384 | (phnum -| 1); // -1 because the GNU_STACK phdr does not have a `.segment` node |
| 3395 | 3385 | |
| ... | ... | @@ -3398,17 +3388,49 @@ fn initHeaders( |
| 3398 | 3388 | try elf.section_by_name.ensureUnusedCapacity(gpa, shnum); |
| 3399 | 3389 | try elf.phdrs.resize(gpa, phnum); |
| 3400 | 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); | |
| 3402 | 3424 | |
| 3403 | 3425 | const entsize: struct { ph: u32, sh: u32 } = switch (class) { |
| 3404 | 3426 | .NONE, _ => unreachable, |
| 3405 | 3427 | inline else => |ct_class| entsize: { |
| 3406 | 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 | 3430 | .size = @sizeOf(ElfN.Ehdr), |
| 3409 | 3431 | .alignment = addr_align, |
| 3410 | 3432 | .fixed = true, |
| 3411 | })); | |
| 3433 | }); | |
| 3412 | 3434 | elf.nodes.appendAssumeCapacity(.ehdr); |
| 3413 | 3435 | |
| 3414 | 3436 | const ehdr: *ElfN.Ehdr = @ptrCast(@alignCast(elf.ni.ehdr.slice(&elf.mf))); |
| ... | ... | @@ -3461,12 +3483,12 @@ fn initHeaders( |
| 3461 | 3483 | }, |
| 3462 | 3484 | }; |
| 3463 | 3485 | |
| 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 | 3487 | .size = 1 * entsize.sh, // as above, only the null shdr initially |
| 3466 | 3488 | .alignment = elf.mf.flags.block_size, |
| 3467 | 3489 | .moved = true, |
| 3468 | 3490 | .resized = true, |
| 3469 | })); | |
| 3491 | }); | |
| 3470 | 3492 | elf.nodes.appendAssumeCapacity(.shdr); |
| 3471 | 3493 | |
| 3472 | 3494 | const page_align: std.mem.Alignment = .fromByteUnits(switch (machine) { |
| ... | ... | @@ -3491,45 +3513,45 @@ fn initHeaders( |
| 3491 | 3513 | }); |
| 3492 | 3514 | |
| 3493 | 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 | 3517 | .alignment = elf.mf.flags.block_size, |
| 3496 | 3518 | .moved = true, |
| 3497 | 3519 | .bubbles_moved = false, |
| 3498 | })); | |
| 3520 | }); | |
| 3499 | 3521 | elf.nodes.appendAssumeCapacity(.{ .segment = phndx.rodata }); |
| 3500 | 3522 | elf.phdrs.items[phndx.rodata] = elf.ni.rodata; |
| 3501 | 3523 | |
| 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 | 3525 | .size = @as(u64, phnum) * entsize.ph, |
| 3504 | 3526 | .alignment = addr_align, |
| 3505 | 3527 | .moved = true, |
| 3506 | 3528 | .resized = true, |
| 3507 | 3529 | .bubbles_moved = false, |
| 3508 | })); | |
| 3530 | }); | |
| 3509 | 3531 | elf.nodes.appendAssumeCapacity(.{ .segment = phndx.phdr }); |
| 3510 | 3532 | elf.phdrs.items[phndx.phdr] = elf.ni.phdr; |
| 3511 | 3533 | |
| 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 | 3535 | .alignment = elf.mf.flags.block_size, |
| 3514 | 3536 | .moved = true, |
| 3515 | 3537 | .bubbles_moved = false, |
| 3516 | })); | |
| 3538 | }); | |
| 3517 | 3539 | elf.nodes.appendAssumeCapacity(.{ .segment = phndx.text }); |
| 3518 | 3540 | elf.phdrs.items[phndx.text] = elf.ni.text; |
| 3519 | 3541 | |
| 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 | 3543 | .alignment = elf.mf.flags.block_size, |
| 3522 | 3544 | .moved = true, |
| 3523 | 3545 | .bubbles_moved = false, |
| 3524 | })); | |
| 3546 | }); | |
| 3525 | 3547 | elf.nodes.appendAssumeCapacity(.{ .segment = phndx.data }); |
| 3526 | 3548 | elf.phdrs.items[phndx.data] = elf.ni.data; |
| 3527 | 3549 | |
| 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 | 3551 | .alignment = elf.mf.flags.block_size, |
| 3530 | 3552 | .moved = true, |
| 3531 | 3553 | .bubbles_moved = false, |
| 3532 | })); | |
| 3554 | }); | |
| 3533 | 3555 | elf.nodes.appendAssumeCapacity(.{ .segment = phndx.relro }); |
| 3534 | 3556 | elf.phdrs.items[phndx.relro] = elf.ni.data_rel_ro; |
| 3535 | 3557 | |
| ... | ... | @@ -3706,7 +3728,7 @@ fn initHeaders( |
| 3706 | 3728 | .node = .none, |
| 3707 | 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 | 3732 | .type = .SYMTAB, |
| 3711 | 3733 | .size = @sizeOf(ElfN.Sym) * 1, |
| 3712 | 3734 | .addralign = addr_align, |
| ... | ... | @@ -3729,7 +3751,7 @@ fn initHeaders( |
| 3729 | 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 | 3755 | .type = .STRTAB, |
| 3734 | 3756 | .size = 1, |
| 3735 | 3757 | .entsize = 1, |
| ... | ... | @@ -3740,7 +3762,7 @@ fn initHeaders( |
| 3740 | 3762 | try Section.Index.symtab.rename(elf, ".symtab"); |
| 3741 | 3763 | try Section.Index.shstrtab.rename(elf, ".shstrtab"); |
| 3742 | 3764 | |
| 3743 | assert(.strtab == try elf.addSection(elf.ni.file, .{ | |
| 3765 | assert(.strtab == try elf.addSection(elf.ni.elf, .{ | |
| 3744 | 3766 | .name = ".strtab", |
| 3745 | 3767 | .type = .STRTAB, |
| 3746 | 3768 | .size = 1, |
| ... | ... | @@ -4210,6 +4232,8 @@ fn initHeaders( |
| 4210 | 4232 | break :str try elf.string(.dynstr, slice); |
| 4211 | 4233 | }, |
| 4212 | 4234 | }; |
| 4235 | ||
| 4236 | try elf.ensureElfNodeSize(); | |
| 4213 | 4237 | } |
| 4214 | 4238 | |
| 4215 | 4239 | 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 | 4245 | break :count count; |
| 4222 | 4246 | }); |
| 4223 | 4247 | elf.mf.update_prog_node = prog_node.start("Relocations", elf.mf.updates.items.len); |
| 4224 | elf.input_prog_node = prog_node.start( | |
| 4225 | "Inputs", | |
| 4226 | elf.input_sections.items.len - elf.input_section_pending_index, | |
| 4227 | ); | |
| 4248 | elf.input_prog_node = prog_node.start("Inputs", (elf.inputs.items.len - elf.input_pending_index) + | |
| 4249 | (elf.input_sections.items.len - elf.input_section_pending_index)); | |
| 4228 | 4250 | } |
| 4229 | 4251 | |
| 4230 | 4252 | pub fn endProgress(elf: *Elf) void { |
| ... | ... | @@ -4244,13 +4266,15 @@ fn getNode(elf: *const Elf, ni: MappedFile.Node.Index) Node { |
| 4244 | 4266 | /// Asserts that `ni` is a section, input section, copied global, NAV, UAV, or lazy code/data. |
| 4245 | 4267 | fn getNodeShndx(elf: *const Elf, ni: MappedFile.Node.Index) Section.Index { |
| 4246 | 4268 | return switch (elf.getNode(ni)) { |
| 4247 | .file => unreachable, | |
| 4248 | .ehdr => unreachable, | |
| 4249 | .shdr => unreachable, | |
| 4250 | .segment => unreachable, | |
| 4251 | ||
| 4269 | .archive, | |
| 4270 | .archive_header, | |
| 4271 | .elf, | |
| 4272 | .ehdr, | |
| 4273 | .shdr, | |
| 4274 | .segment, | |
| 4275 | .input_member, | |
| 4276 | => unreachable, | |
| 4252 | 4277 | .section => |shndx| shndx, |
| 4253 | ||
| 4254 | 4278 | .input_section, |
| 4255 | 4279 | .copied_global, |
| 4256 | 4280 | .nav, |
| ... | ... | @@ -4260,21 +4284,44 @@ fn getNodeShndx(elf: *const Elf, ni: MappedFile.Node.Index) Section.Index { |
| 4260 | 4284 | => elf.getNode(ni.parent(&elf.mf)).section, |
| 4261 | 4285 | }; |
| 4262 | 4286 | } |
| 4287 | fn 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 | } | |
| 4263 | 4307 | fn computeNodeVAddr(elf: *Elf, ni: MappedFile.Node.Index) u64 { |
| 4264 | 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 | 4311 | .ehdr, .shdr => unreachable, |
| 4267 | 4312 | .segment => |phndx| switch (elf.phdrSlice()) { |
| 4268 | 4313 | inline else => |phdr| elf.targetLoad(&phdr[phndx].vaddr), |
| 4269 | 4314 | }, |
| 4270 | 4315 | .section => |shndx| if (shndx == elf.shndx.tdata) 0 else shndx.vaddr(elf), |
| 4271 | .input_section => unreachable, | |
| 4272 | .copied_global => unreachable, | |
| 4316 | .input_member, .input_section, .copied_global => unreachable, | |
| 4273 | 4317 | inline .nav, .uav, .lazy_code, .lazy_const_data => |i| Symbol.Id.local(i.symbol(elf)).value(elf), |
| 4274 | 4318 | }; |
| 4275 | 4319 | const offset, _ = ni.location(&elf.mf).resolve(&elf.mf); |
| 4276 | 4320 | return parent_vaddr + offset; |
| 4277 | 4321 | } |
| 4322 | fn 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 | } | |
| 4278 | 4325 | |
| 4279 | 4326 | /// Deletes any existing relocations in the given node, and marks the start of the node's contiguous |
| 4280 | 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 | 4330 | /// the special-case sections '.plt' and '.dynamic'. |
| 4284 | 4331 | fn resetNodeRelocs(elf: *Elf, ni: MappedFile.Node.Index) void { |
| 4285 | 4332 | const symbol_relocs: *SymbolReloc.Index, const got_relocs: ?*GotReloc.Index = switch (elf.getNode(ni)) { |
| 4286 | .file => unreachable, // cannot contain relocs | |
| 4287 | .ehdr => unreachable, // cannot contain relocs | |
| 4288 | .shdr => unreachable, // cannot contain relocs | |
| 4289 | .segment => unreachable, // cannot contain relocs | |
| 4333 | .archive, | |
| 4334 | .archive_header, | |
| 4335 | .elf, | |
| 4336 | .ehdr, | |
| 4337 | .shdr, | |
| 4338 | .segment, | |
| 4339 | .input_member, | |
| 4340 | .copied_global, | |
| 4341 | => unreachable, // cannot contain relocs | |
| 4290 | 4342 | .section => unreachable, // cannot contain relocs (.plt and .dynamic unsupported) |
| 4291 | .copied_global => unreachable, // cannot contain relocs | |
| 4292 | 4343 | .input_section => |isi| .{ |
| 4293 | 4344 | &elf.input_sections.items[@backingInt(isi)].first_symbol_reloc, |
| 4294 | 4345 | &elf.input_sections.items[@backingInt(isi)].first_got_reloc, |
| ... | ... | @@ -4359,7 +4410,7 @@ fn flushMovedNodeRelocs( |
| 4359 | 4410 | } |
| 4360 | 4411 | |
| 4361 | 4412 | fn 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 | } |
| 4364 | 4415 | |
| 4365 | 4416 | /// 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 | 4466 | return elf.identClass().size(); |
| 4416 | 4467 | } |
| 4417 | 4468 | fn 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 | 4470 | return ident_data.endian(); |
| 4420 | 4471 | } |
| 4421 | 4472 | fn targetTlsVariant(elf: *const Elf) union(enum) { |
| ... | ... | @@ -4487,7 +4538,7 @@ fn targetLoad(elf: *const Elf, ptr: anytype) @typeInfo(@TypeOf(ptr)).pointer.chi |
| 4487 | 4538 | return switch (@typeInfo(Child)) { |
| 4488 | 4539 | else => @compileError(@typeName(Child)), |
| 4489 | 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 | 4542 | .@"struct" => |@"struct"| @bitCast( |
| 4492 | 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 | 4614 | } |
| 4564 | 4615 | } |
| 4565 | 4616 | |
| 4617 | fn 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 | ||
| 4566 | 4627 | const SymPtr = union(std.elf.CLASS) { |
| 4567 | 4628 | NONE: noreturn, |
| 4568 | 4629 | @"32": *std.elf.Elf32.Sym, |
| ... | ... | @@ -4657,7 +4718,7 @@ fn mapInputSection(elf: *Elf, opts: struct { |
| 4657 | 4718 | } |
| 4658 | 4719 | errdefer assert(elf.section_by_name.pop().?.key == name_shstrtab); |
| 4659 | 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 | 4722 | if (opts.flags.EXECINSTR) break :parent elf.ni.text; |
| 4662 | 4723 | if (opts.flags.TLS) break :parent elf.ni.tls; |
| 4663 | 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 | 4843 | break :a switch (nav.resolved.?.@"align") { |
| 4783 | 4844 | else => |a| a.maxStrict(min), |
| 4784 | 4845 | .none => switch (mod.optimize_mode) { |
| 4785 | .Debug, | |
| 4786 | .ReleaseSafe, | |
| 4787 | .ReleaseFast, | |
| 4846 | .debug, | |
| 4847 | .safe, | |
| 4848 | .fast, | |
| 4788 | 4849 | => target_util.defaultFunctionAlignment(target), |
| 4789 | .ReleaseSmall => min, | |
| 4850 | .small => min, | |
| 4790 | 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 | 4939 | /// indicates to the frontend that the input could be a GNU ld script instead. |
| 4879 | 4940 | pub fn loadInput(elf: *Elf, input: link.Input) (link.Error || error{BadMagic})!void { |
| 4880 | 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 | 4943 | else => |e| return e, |
| 4883 | 4944 | error.MappedFileIo => return diags.fail( |
| 4884 | 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 | 5047 | const r = &fr.interface; |
| 4987 | 5048 | |
| 4988 | 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 | 5054 | const magic = r.take(std.elf.ARMAG.len) catch |err| switch (err) { |
| 4991 | 5055 | error.ReadFailed => |e| return e, |
| ... | ... | @@ -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 | 5163 | try elf.ensureUnusedSymbolCapacity(1, .all_local); |
| 5075 | try elf.inputs.ensureUnusedCapacity(gpa, 1); | |
| 5076 | const file_symbol = elf.addLocalSymbolAssumeCapacity(.{ | |
| 5164 | input.extra = .{ .file_symbol = elf.addLocalSymbolAssumeCapacity(.{ | |
| 5077 | 5165 | .node = .none, |
| 5078 | 5166 | .name = try elf.string(.strtab, std.fs.path.stem(member orelse path.sub_path)), |
| 5079 | 5167 | .value = 0, |
| 5080 | 5168 | .size = 0, |
| 5081 | 5169 | .type = .FILE, |
| 5082 | 5170 | .shndx = .ABS, |
| 5083 | }); | |
| 5084 | elf.inputs.addOneAssumeCapacity().* = .{ | |
| 5085 | .path = path, | |
| 5086 | .member = if (member) |m| try gpa.dupe(u8, m) else null, | |
| 5087 | .file_symbol = file_symbol, | |
| 5088 | }; | |
| 5171 | }) }; | |
| 5089 | 5172 | const target_endian = elf.targetEndian(); |
| 5090 | 5173 | switch (elf.identClass()) { |
| 5091 | 5174 | .NONE, _ => unreachable, |
| ... | ... | @@ -5267,7 +5350,7 @@ fn loadObject( |
| 5267 | 5350 | .first_symbol_reloc = .none, |
| 5268 | 5351 | .first_got_reloc = .none, |
| 5269 | 5352 | }; |
| 5270 | elf.synth_prog_node.increaseEstimatedTotalItems(1); | |
| 5353 | elf.input_prog_node.increaseEstimatedTotalItems(1); | |
| 5271 | 5354 | } |
| 5272 | 5355 | var symmap: std.ArrayList(Symbol.Id) = .empty; |
| 5273 | 5356 | defer symmap.deinit(gpa); |
| ... | ... | @@ -5479,6 +5562,9 @@ fn loadDso(elf: *Elf, path: std.Build.Cache.Path, fr: *Io.File.Reader) (LoadPars |
| 5479 | 5562 | |
| 5480 | 5563 | log.debug("loadDso({f})", .{path.fmtEscapeString()}); |
| 5481 | 5564 | try elf.checkInputIdent(path, r); |
| 5565 | ||
| 5566 | if (elf.ehdrType() == .REL) return; // this input does not affect the output artifact | |
| 5567 | ||
| 5482 | 5568 | const target_endian = elf.targetEndian(); |
| 5483 | 5569 | switch (elf.identClass()) { |
| 5484 | 5570 | .NONE, _ => unreachable, |
| ... | ... | @@ -5709,7 +5795,8 @@ fn checkInputIdent( |
| 5709 | 5795 | } |
| 5710 | 5796 | |
| 5711 | 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)]); | |
| 5713 | 5800 | |
| 5714 | 5801 | if (ident.class != target.class) return diags.failParse( |
| 5715 | 5802 | path, |
| ... | ... | @@ -5812,7 +5899,9 @@ fn updateInitFiniArraySectionSize( |
| 5812 | 5899 | } |
| 5813 | 5900 | |
| 5814 | 5901 | pub 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 | 5905 | const diags = &elf.base.comp.link_diags; |
| 5817 | 5906 | elf.prelinkInner() catch |err| switch (err) { |
| 5818 | 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 | 5912 | const comp = elf.base.comp; |
| 5824 | 5913 | const gpa = comp.gpa; |
| 5825 | 5914 | |
| 5826 | if (comp.zcu != null and !comp.config.use_llvm) { | |
| 5827 | // We're use self-hosted codegen---add an input representing the Zig "object". | |
| 5915 | if (comp.zcu != null and !comp.config.use_llvm and elf.ni.elf == MappedFile.Node.Index.root) { | |
| 5916 | // We're using self-hosted codegen---add an input representing the Zig "object". | |
| 5828 | 5917 | try elf.ensureUnusedSymbolCapacity(1, .all_local); |
| 5829 | 5918 | try elf.inputs.ensureUnusedCapacity(gpa, 1); |
| 5830 | const zcu_name = try std.fmt.allocPrint(gpa, "{s}_zcu", .{ | |
| 5831 | std.fs.path.stem(elf.base.emit.sub_path), | |
| 5832 | }); | |
| 5919 | const zcu_name = try std.fmt.allocPrint(gpa, "{s}_zcu", .{comp.root_name}); | |
| 5833 | 5920 | defer gpa.free(zcu_name); |
| 5834 | 5921 | const zcu_file_symbol = elf.addLocalSymbolAssumeCapacity(.{ |
| 5835 | 5922 | .node = .none, |
| ... | ... | @@ -5842,9 +5929,12 @@ fn prelinkInner(elf: *Elf) Error!void { |
| 5842 | 5929 | elf.inputs.addOneAssumeCapacity().* = .{ |
| 5843 | 5930 | .path = elf.base.emit, |
| 5844 | 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 | } |
| 5849 | 5939 | |
| 5850 | 5940 | fn prepareDynamic(elf: *Elf) Error!void { |
| ... | ... | @@ -6034,12 +6124,12 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct { |
| 6034 | 6124 | }, |
| 6035 | 6125 | }; |
| 6036 | 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 | 6130 | try elf.ensureNodeSize(elf.ni.shdr, new_shdr_size); |
| 6041 | 6131 | const ni = try elf.mf.addLastChildNode(gpa, switch (elf.ehdrType()) { |
| 6042 | .REL => elf.ni.file, | |
| 6132 | .REL => elf.ni.elf, | |
| 6043 | 6133 | .EXEC, .DYN => segment_ni, |
| 6044 | 6134 | }, .{ |
| 6045 | 6135 | .size = opts.size, |
| ... | ... | @@ -6062,7 +6152,6 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct { |
| 6062 | 6152 | else => .{ .shndx = .UNDEF }, |
| 6063 | 6153 | } }); |
| 6064 | 6154 | elf.nodes.appendAssumeCapacity(.{ .section = shndx }); |
| 6065 | const offset = ni.fileLocation(&elf.mf, false).offset; | |
| 6066 | 6155 | switch (elf.shdrPtr(shndx)) { |
| 6067 | 6156 | inline else => |shdr, class| { |
| 6068 | 6157 | shdr.* = .{ |
| ... | ... | @@ -6070,7 +6159,7 @@ fn addSection(elf: *Elf, segment_ni: MappedFile.Node.Index, opts: struct { |
| 6070 | 6159 | .type = opts.type, |
| 6071 | 6160 | .flags = .{ .shf = opts.flags }, |
| 6072 | 6161 | .addr = @intCast(addr), |
| 6073 | .offset = @intCast(offset), | |
| 6162 | .offset = @intCast(elf.getNodeElfOffset(ni)), | |
| 6074 | 6163 | .size = @intCast(opts.size), |
| 6075 | 6164 | .link = opts.link, |
| 6076 | 6165 | .info = opts.info, |
| ... | ... | @@ -6504,20 +6593,7 @@ fn addSymbolRelocAssumeCapacity( |
| 6504 | 6593 | |
| 6505 | 6594 | // If we emit a runtime relocation entry, its `offset` is a virtual address, so we need to |
| 6506 | 6595 | // determine the vaddr of `node`. |
| 6507 | const node_vaddr: u64 = switch (elf.getNode(node)) { | |
| 6508 | .file => unreachable, | |
| 6509 | .ehdr => unreachable, | |
| 6510 | .shdr => unreachable, | |
| 6511 | .segment => unreachable, | |
| 6512 | .copied_global => unreachable, | |
| 6513 | .section => |shndx| shndx.vaddr(elf), | |
| 6514 | .input_section => |isi| isi.ptrConst(elf).vaddr, | |
| 6515 | inline .nav, | |
| 6516 | .uav, | |
| 6517 | .lazy_code, | |
| 6518 | .lazy_const_data, | |
| 6519 | => |i| Symbol.Id.local(i.symbol(elf)).value(elf), | |
| 6520 | }; | |
| 6596 | const node_vaddr = elf.getNodeVAddr(node); | |
| 6521 | 6597 | |
| 6522 | 6598 | // If this is `true`, we will try to create a copy relocation for the target symbol if it is |
| 6523 | 6599 | // not locally defined. If the relocation value is always computed from the target symbol's |
| ... | ... | @@ -6656,20 +6732,23 @@ fn addGotRelocAssumeCapacity( |
| 6656 | 6732 | ) void { |
| 6657 | 6733 | assert(elf.ehdrType() != .REL); |
| 6658 | 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 | 6747 | .input_section, |
| 6660 | 6748 | .nav, |
| 6661 | 6749 | .lazy_code, |
| 6662 | 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 | } |
| 6674 | 6753 | |
| 6675 | 6754 | const gop = elf.got.getOrPutAssumeCapacity(target); |
| ... | ... | @@ -7053,11 +7132,24 @@ pub fn flush( |
| 7053 | 7132 | tid: Zcu.PerThread.Id, |
| 7054 | 7133 | prog_node: std.Progress.Node, |
| 7055 | 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 | } | |
| 7140 | fn flushInner( | |
| 7141 | elf: *Elf, | |
| 7142 | arena: std.mem.Allocator, | |
| 7143 | tid: Zcu.PerThread.Id, | |
| 7144 | prog_node: std.Progress.Node, | |
| 7145 | ) Error!void { | |
| 7056 | 7146 | const comp = elf.base.comp; |
| 7057 | 7147 | const diags = &comp.link_diags; |
| 7058 | _ = prog_node; | |
| 7059 | 7148 | _ = arena; |
| 7060 | 7149 | |
| 7150 | const sub_prog_node = prog_node.start("ELF Flush", 0); | |
| 7151 | defer sub_prog_node.end(); | |
| 7152 | ||
| 7061 | 7153 | if (comp.config.output_mode == .Exe) { |
| 7062 | 7154 | var any_undef = false; |
| 7063 | 7155 | for (elf.globals.strong_undef.keys()) |name| { |
| ... | ... | @@ -7068,11 +7160,9 @@ pub fn flush( |
| 7068 | 7160 | if (any_undef) return error.AlreadyReported; |
| 7069 | 7161 | } |
| 7070 | 7162 | |
| 7071 | elf.prepareDynamic() catch |err| switch (err) { | |
| 7072 | error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}), | |
| 7073 | else => |e| return e, | |
| 7074 | }; | |
| 7163 | try elf.prepareDynamic(); | |
| 7075 | 7164 | |
| 7165 | try elf.ensureElfNodeSize(); | |
| 7076 | 7166 | while (try elf.idle(tid)) {} |
| 7077 | 7167 | |
| 7078 | 7168 | // 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 | 7187 | .enabled => "_start", |
| 7098 | 7188 | .named => |named| named, |
| 7099 | 7189 | }; |
| 7100 | const sym_name_strtab = elf.string(.strtab, sym_name_slice) catch |err| switch (err) { | |
| 7101 | error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}), | |
| 7102 | else => |e| return e, | |
| 7103 | }; | |
| 7190 | const sym_name_strtab = try elf.string(.strtab, sym_name_slice); | |
| 7104 | 7191 | if (elf.globalByName(sym_name_strtab) == null) break :entry 0; |
| 7105 | 7192 | break :entry Symbol.Id.global(sym_name_strtab).value(elf); |
| 7106 | 7193 | }; |
| ... | ... | @@ -7108,10 +7195,11 @@ pub fn flush( |
| 7108 | 7195 | inline else => |ehdr| elf.targetStore(&ehdr.entry, @intCast(entry_addr)), |
| 7109 | 7196 | } |
| 7110 | 7197 | |
| 7111 | elf.mf.flush() catch |err| switch (err) { | |
| 7112 | error.MappedFileIo => return diags.fail("failed to write output file: {t}", .{elf.mf.io_err.?}), | |
| 7113 | else => |e| return e, | |
| 7114 | }; | |
| 7198 | try elf.mf.flush(); | |
| 7199 | ||
| 7200 | if (elf.options.enable_link_snapshots) | |
| 7201 | elf.dumpStderr(tid) catch |err| | |
| 7202 | return comp.link_diags.fail("dumping link snapshot failed: {t}", .{err}); | |
| 7115 | 7203 | } |
| 7116 | 7204 | |
| 7117 | 7205 | 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 | } |
| 7125 | 7213 | |
| 7126 | 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 | 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 | 7228 | elf.input_section_pending_index += 1; |
| 7130 | 7229 | const sub_prog_node = elf.idleProgNode(tid, elf.input_prog_node, elf.getNode(isi.node(elf))); |
| 7131 | 7230 | defer sub_prog_node.end(); |
| ... | ... | @@ -7213,11 +7312,13 @@ pub fn idle(elf: *Elf, tid: Zcu.PerThread.Id) link.Error!bool { |
| 7213 | 7312 | while (elf.mf.updates.pop()) |ni| { |
| 7214 | 7313 | const clean_moved = ni.cleanMoved(&elf.mf); |
| 7215 | 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 | 7317 | const sub_prog_node = elf.idleProgNode(tid, elf.mf.update_prog_node, elf.getNode(ni)); |
| 7218 | 7318 | defer sub_prog_node.end(); |
| 7219 | 7319 | if (clean_moved) try elf.flushMoved(ni); |
| 7220 | 7320 | if (clean_resized) try elf.flushResized(ni); |
| 7321 | if (clean_next_moved) try elf.flushNextMoved(ni); | |
| 7221 | 7322 | break :task; |
| 7222 | 7323 | } else elf.mf.update_prog_node.completeOne(); |
| 7223 | 7324 | } |
| ... | ... | @@ -7238,6 +7339,10 @@ fn idleProgNode( |
| 7238 | 7339 | return prog_node.start(name: switch (node) { |
| 7239 | 7340 | else => |tag| @tagName(tag), |
| 7240 | 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 | 7346 | .input_section => |isi| { |
| 7242 | 7347 | const ii = isi.input(elf); |
| 7243 | 7348 | break :name std.fmt.bufPrint(&name, "{f}{f} {s}", .{ |
| ... | ... | @@ -7290,6 +7395,8 @@ fn genPending(elf: *Elf, pt: Zcu.PerThread) Error!void { |
| 7290 | 7395 | }; |
| 7291 | 7396 | break; |
| 7292 | 7397 | } |
| 7398 | ||
| 7399 | try elf.ensureElfNodeSize(); | |
| 7293 | 7400 | } |
| 7294 | 7401 | |
| 7295 | 7402 | fn genUav( |
| ... | ... | @@ -7358,6 +7465,36 @@ fn genLazy(elf: *Elf, pt: Zcu.PerThread, lmr: Node.LazyMapRef) Error!void { |
| 7358 | 7465 | } |
| 7359 | 7466 | } |
| 7360 | 7467 | |
| 7468 | fn 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 | ||
| 7361 | 7498 | fn flushInputSection(elf: *Elf, isi: InputSection.Index) Error!void { |
| 7362 | 7499 | const file_loc = isi.fileLocation(elf); |
| 7363 | 7500 | if (file_loc.size == 0) return; |
| ... | ... | @@ -7404,33 +7541,29 @@ fn flushInputSection(elf: *Elf, isi: InputSection.Index) Error!void { |
| 7404 | 7541 | assert(isi.node(elf).hasMoved(&elf.mf)); |
| 7405 | 7542 | } |
| 7406 | 7543 | |
| 7407 | fn flushFileOffset(elf: *Elf, ni: MappedFile.Node.Index) void { | |
| 7544 | fn flushElfOffset(elf: *Elf, ni: MappedFile.Node.Index) void { | |
| 7545 | const elf_offset = elf.getNodeElfOffset(ni); | |
| 7408 | 7546 | switch (elf.getNode(ni)) { |
| 7409 | 7547 | else => unreachable, |
| 7410 | .ehdr => assert(ni.fileLocation(&elf.mf, false).offset == 0), | |
| 7548 | .ehdr => assert(elf_offset == 0), | |
| 7411 | 7549 | .shdr => switch (elf.ehdrPtr()) { |
| 7412 | inline else => |ehdr| elf.targetStore( | |
| 7413 | &ehdr.shoff, | |
| 7414 | @intCast(ni.fileLocation(&elf.mf, false).offset), | |
| 7415 | ), | |
| 7550 | inline else => |ehdr| elf.targetStore(&ehdr.shoff, @intCast(elf_offset)), | |
| 7416 | 7551 | }, |
| 7417 | 7552 | .segment => |phndx| { |
| 7418 | 7553 | switch (elf.phdrSlice()) { |
| 7419 | 7554 | inline else => |phdr, class| { |
| 7420 | 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 | 7557 | if (elf.targetLoad(&ph.type) == .PHDR) { |
| 7423 | 7558 | @field(elf.ehdrPtr(), @tagName(class)).phoff = ph.offset; |
| 7424 | 7559 | } |
| 7425 | 7560 | }, |
| 7426 | 7561 | } |
| 7427 | 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 | 7565 | .section => |shndx| switch (elf.shdrPtr(shndx)) { |
| 7431 | inline else => |shdr| elf.targetStore(&shdr.offset, @intCast( | |
| 7432 | ni.fileLocation(&elf.mf, false).offset, | |
| 7433 | )), | |
| 7566 | inline else => |shdr| elf.targetStore(&shdr.offset, @intCast(elf_offset)), | |
| 7434 | 7567 | }, |
| 7435 | 7568 | } |
| 7436 | 7569 | } |
| ... | ... | @@ -7443,10 +7576,11 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void |
| 7443 | 7576 | defer elf.mf.nodes_lock.unlock(); |
| 7444 | 7577 | |
| 7445 | 7578 | switch (elf.getNode(ni)) { |
| 7446 | .file => unreachable, | |
| 7447 | .ehdr, .shdr => elf.flushFileOffset(ni), | |
| 7579 | .archive, .archive_header => unreachable, | |
| 7580 | .elf => {}, | |
| 7581 | .ehdr, .shdr => elf.flushElfOffset(ni), | |
| 7448 | 7582 | .segment => |phndx| { |
| 7449 | elf.flushFileOffset(ni); | |
| 7583 | elf.flushElfOffset(ni); | |
| 7450 | 7584 | switch (elf.phdrSlice()) { |
| 7451 | 7585 | inline else => |phdr| { |
| 7452 | 7586 | const ph = &phdr[phndx]; |
| ... | ... | @@ -7467,7 +7601,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void |
| 7467 | 7601 | } |
| 7468 | 7602 | }, |
| 7469 | 7603 | .section => |shndx| { |
| 7470 | elf.flushFileOffset(ni); | |
| 7604 | elf.flushElfOffset(ni); | |
| 7471 | 7605 | const addr = elf.computeNodeVAddr(ni); |
| 7472 | 7606 | const old_addr: u64, const flags: std.elf.SHF = switch (elf.shdrPtr(shndx)) { |
| 7473 | 7607 | inline else => |shdr| .{ |
| ... | ... | @@ -7518,6 +7652,7 @@ fn flushMoved(elf: *Elf, ni: MappedFile.Node.Index) std.mem.Allocator.Error!void |
| 7518 | 7652 | elf.flushMovedNodeRelocs(ni, addr, elf.dynamic_first_symbol_reloc, .none); |
| 7519 | 7653 | } |
| 7520 | 7654 | }, |
| 7655 | .input_member => {}, | |
| 7521 | 7656 | .input_section => |isi| { |
| 7522 | 7657 | const old_section_addr = isi.ptr(elf).vaddr; |
| 7523 | 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 | 7661 | // Update local symbols |
| 7527 | 7662 | const ii = isi.input(elf); |
| 7528 | 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 | 7665 | if (lsi.index().ptr(elf).node != ni) continue; |
| 7531 | 7666 | const visibility: std.elf.STV = switch (elf.symPtr(lsi.index())) { |
| 7532 | 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 | 7748 | |
| 7614 | 7749 | _, const size = ni.location(&elf.mf).resolve(&elf.mf); |
| 7615 | 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 | 7762 | .ehdr => unreachable, |
| 7618 | 7763 | .shdr => {}, |
| 7619 | 7764 | .segment => |phndx| switch (elf.phdrSlice()) { |
| ... | ... | @@ -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 | ||
| 7865 | fn 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 | ||
| 7719 | 7943 | fn updateDynamicEntry(elf: *Elf, key: u32, new_val: u64) void { |
| 7720 | 7944 | switch (elf.shdrPtr(elf.shndx.dynamic)) { |
| 7721 | 7945 | inline else => |shdr, class| { |
| ... | ... | @@ -7756,7 +7980,7 @@ fn addPltEntry(elf: *Elf, global_name: String(.strtab), dynsym_index: u32) void |
| 7756 | 7980 | }; |
| 7757 | 7981 | |
| 7758 | 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); | |
| 7760 | 7984 | |
| 7761 | 7985 | if (plt_index < elf.plt.count()) { |
| 7762 | 7986 | // We reused a free entry, so we're already done! |
| ... | ... | @@ -8096,7 +8320,10 @@ fn updateExportsInner( |
| 8096 | 8320 | }, |
| 8097 | 8321 | .uav => |uav| .{ (try elf.uavMapIndex(uav, .none)).symbol(elf), .OBJECT }, |
| 8098 | 8322 | }; |
| 8323 | ||
| 8324 | try elf.ensureElfNodeSize(); | |
| 8099 | 8325 | while (try elf.idle(pt.tid)) {} |
| 8326 | ||
| 8100 | 8327 | const value: u64 = Symbol.Id.local(exported_lsi).value(elf); |
| 8101 | 8328 | const size: u64, const shndx: Section.Index = switch (elf.symPtr(exported_lsi.index())) { |
| 8102 | 8329 | inline else => |exported_sym| .{ |
| ... | ... | @@ -8150,6 +8377,16 @@ pub fn deleteExport(elf: *Elf, exported: Zcu.Exported, name: InternPool.NullTerm |
| 8150 | 8377 | _ = name; |
| 8151 | 8378 | } |
| 8152 | 8379 | |
| 8380 | fn 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 | ||
| 8153 | 8390 | pub fn dump(elf: *Elf, w: *Io.Writer, tid: Zcu.PerThread.Id) !link.File.DumpResult { |
| 8154 | 8391 | if (elf.options.enable_link_snapshots) { |
| 8155 | 8392 | try elf.printNode(tid, w, .root, 0); |
| ... | ... | @@ -8227,13 +8464,14 @@ pub fn printNode( |
| 8227 | 8464 | { |
| 8228 | 8465 | const mf_node = &elf.mf.nodes.items[@backingInt(ni)]; |
| 8229 | 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 | 8468 | @backingInt(ni), |
| 8232 | 8469 | off, |
| 8233 | 8470 | size, |
| 8234 | 8471 | mf_node.flags.alignment.toByteUnits(), |
| 8235 | 8472 | if (mf_node.flags.fixed) " fixed" else "", |
| 8236 | 8473 | if (mf_node.flags.moved) " moved" else "", |
| 8474 | if (mf_node.flags.next_moved) " next_moved" else "", | |
| 8237 | 8475 | if (mf_node.flags.resized) " resized" else "", |
| 8238 | 8476 | if (mf_node.flags.has_content) " has_content" else "", |
| 8239 | 8477 | }); |
| ... | ... | @@ -8269,11 +8507,19 @@ pub fn printNode( |
| 8269 | 8507 | } |
| 8270 | 8508 | } |
| 8271 | 8509 | |
| 8272 | fn ensureNodeSize( | |
| 8273 | elf: *Elf, | |
| 8274 | node: MappedFile.Node.Index, | |
| 8275 | need_size: u64, | |
| 8276 | ) Error!void { | |
| 8510 | /// Must be called deterministically after any call to `MappedFile.Node.Index.resize` | |
| 8511 | /// (of `elf.ni.elf` or one of its children) before any possible calls to `idle`. | |
| 8512 | fn ensureElfNodeSize(elf: *Elf) MappedFile.Error!void { | |
| 8513 | if (elf.ni.elf == MappedFile.Node.Index.root) return; | |
| 8514 | var child_it = elf.ni.elf.reverseChildren(&elf.mf); | |
| 8515 | const last_end = if (child_it.next()) |last_ni| last_end: { | |
| 8516 | const last_offset, const last_size = last_ni.location(&elf.mf).resolve(&elf.mf); | |
| 8517 | break :last_end last_offset + last_size; | |
| 8518 | } else 0; | |
| 8519 | try elf.ensureNodeSize(elf.ni.elf, last_end + @sizeOf(std.elf.ar_hdr)); | |
| 8520 | } | |
| 8521 | ||
| 8522 | fn ensureNodeSize(elf: *Elf, node: MappedFile.Node.Index, need_size: u64) MappedFile.Error!void { | |
| 8277 | 8523 | _, const node_size = node.location(&elf.mf).resolve(&elf.mf); |
| 8278 | 8524 | if (need_size <= node_size) return; |
| 8279 | 8525 | const gpa = elf.base.comp.gpa; |
src/link/Lld.zig+39-26| ... | ... | @@ -99,8 +99,6 @@ pub const Elf = struct { |
| 99 | 99 | bind_global_refs_locally: bool, |
| 100 | 100 | pub const HashStyle = enum { sysv, gnu, both }; |
| 101 | 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; | |
| 104 | 102 | |
| 105 | 103 | fn init(comp: *Compilation, options: link.File.OpenOptions) !Elf { |
| 106 | 104 | const PtrWidth = enum { p32, p64 }; |
| ... | ... | @@ -208,8 +206,8 @@ pub fn createEmpty( |
| 208 | 206 | const optimize_mode = comp.root_mod.optimize_mode; |
| 209 | 207 | |
| 210 | 208 | const gc_sections: bool = options.gc_sections orelse switch (target.ofmt) { |
| 211 | .coff => optimize_mode != .Debug, | |
| 212 | .elf => optimize_mode != .Debug and output_mode != .Obj, | |
| 209 | .coff => optimize_mode != .debug, | |
| 210 | .elf => optimize_mode != .debug and output_mode != .Obj, | |
| 213 | 211 | .wasm => output_mode != .Obj, |
| 214 | 212 | else => unreachable, |
| 215 | 213 | }; |
| ... | ... | @@ -271,12 +269,12 @@ pub fn flush( |
| 271 | 269 | .wasm => wasmLink(lld, arena), |
| 272 | 270 | }; |
| 273 | 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 | 273 | else => |e| return lld.base.comp.link_diags.fail("failed to link with LLD: {t}", .{e}), |
| 276 | 274 | }; |
| 277 | 275 | } |
| 278 | 276 | |
| 279 | fn linkAsArchive(lld: *Lld, arena: Allocator) !void { | |
| 277 | fn linkAsArchive(lld: *Lld, arena: Allocator) link.Error!void { | |
| 280 | 278 | const base = &lld.base; |
| 281 | 279 | const comp = base.comp; |
| 282 | 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 | 306 | |
| 309 | 307 | try object_files.ensureUnusedCapacity(arena, comp.link_inputs.len); |
| 310 | 308 | for (comp.link_inputs) |input| switch (input) { |
| 311 | .res, .dso, .dso_exact => {}, // shared libraries should not be included in static archives | |
| 312 | .object, .archive => { | |
| 309 | .dso, .dso_exact, .archive => {}, // static archives should not contain shared libraries or other static archives | |
| 310 | .res, .object => { | |
| 313 | 311 | const path = try input.path().?.toStringZ(arena); |
| 314 | 312 | object_files.appendAssumeCapacity(path); |
| 315 | 313 | }, |
| ... | ... | @@ -340,7 +338,9 @@ fn linkAsArchive(lld: *Lld, arena: Allocator) !void { |
| 340 | 338 | const llvm = @import("../codegen/llvm.zig"); |
| 341 | 339 | const target = &comp.root_mod.resolved_target.result; |
| 342 | 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 | 344 | full_out_path_z, |
| 345 | 345 | object_files.items.ptr, |
| 346 | 346 | object_files.items.len, |
| ... | ... | @@ -348,8 +348,19 @@ fn linkAsArchive(lld: *Lld, arena: Allocator) !void { |
| 348 | 348 | .windows => .COFF, |
| 349 | 349 | else => if (target.os.tag.isDarwin()) .DARWIN else .GNU, |
| 350 | 350 | }, |
| 351 | ); | |
| 352 | if (bad) return error.UnableToWriteArchive; | |
| 351 | &err_file_index, | |
| 352 | &err_msg, | |
| 353 | )) { | |
| 354 | defer std.c.free(err_msg); | |
| 355 | if (err_file_index < object_files.items.len) { | |
| 356 | return comp.link_diags.fail("LLD failed to open input file '{s}': {s}", .{ | |
| 357 | object_files.items[err_file_index], | |
| 358 | err_msg, | |
| 359 | }); | |
| 360 | } else { | |
| 361 | return comp.link_diags.fail("LLD failed to write archive: {s}", .{err_msg}); | |
| 362 | } | |
| 363 | } | |
| 353 | 364 | } |
| 354 | 365 | |
| 355 | 366 | fn addCommonArgs(argv: *std.array_list.Managed([]const u8), coff: bool) !void { |
| ... | ... | @@ -383,7 +394,7 @@ fn coffLink(lld: *Lld, arena: Allocator) !void { |
| 383 | 394 | const target = &comp.root_mod.resolved_target.result; |
| 384 | 395 | const optimize_mode = comp.root_mod.optimize_mode; |
| 385 | 396 | const entry_name: ?[]const u8 = switch (coff.entry) { |
| 386 | // This logic isn't quite right for disabled or enabled. No point in fixing it | |
| 397 | // This logic isn't quite right for default or enabled. No point in fixing it | |
| 387 | 398 | // when the goal is to eliminate dependency on LLD anyway. |
| 388 | 399 | // https://github.com/ziglang/zig/issues/17751 |
| 389 | 400 | .disabled, .default, .enabled => null, |
| ... | ... | @@ -456,9 +467,9 @@ fn coffLink(lld: *Lld, arena: Allocator) !void { |
| 456 | 467 | |
| 457 | 468 | if (comp.config.lto != .none) { |
| 458 | 469 | switch (optimize_mode) { |
| 459 | .Debug => {}, | |
| 460 | .ReleaseSmall => try argv.append("-OPT:lldlto=2"), | |
| 461 | .ReleaseFast, .ReleaseSafe => try argv.append("-OPT:lldlto=3"), | |
| 470 | .debug => {}, | |
| 471 | .small => try argv.append("-OPT:lldlto=2"), | |
| 472 | .fast, .safe => try argv.append("-OPT:lldlto=3"), | |
| 462 | 473 | } |
| 463 | 474 | } |
| 464 | 475 | if (comp.config.output_mode == .Exe) { |
| ... | ... | @@ -492,6 +503,8 @@ fn coffLink(lld: *Lld, arena: Allocator) !void { |
| 492 | 503 | |
| 493 | 504 | if (entry_name) |name| { |
| 494 | 505 | try argv.append(try arena.print("-ENTRY:{s}", .{name})); |
| 506 | } else if (coff.entry == .disabled) { | |
| 507 | try argv.append("-NOENTRY"); | |
| 495 | 508 | } |
| 496 | 509 | |
| 497 | 510 | if (coff.repro) { |
| ... | ... | @@ -865,15 +878,15 @@ fn elfLink(lld: *Lld, arena: Allocator) !void { |
| 865 | 878 | |
| 866 | 879 | if (comp.config.lto != .none) { |
| 867 | 880 | switch (comp.root_mod.optimize_mode) { |
| 868 | .Debug => {}, | |
| 869 | .ReleaseSmall => try argv.append("--lto-O2"), | |
| 870 | .ReleaseFast, .ReleaseSafe => try argv.append("--lto-O3"), | |
| 881 | .debug => {}, | |
| 882 | .small => try argv.append("--lto-O2"), | |
| 883 | .fast, .safe => try argv.append("--lto-O3"), | |
| 871 | 884 | } |
| 872 | 885 | } |
| 873 | 886 | switch (comp.root_mod.optimize_mode) { |
| 874 | .Debug => {}, | |
| 875 | .ReleaseSmall => try argv.append("-O2"), | |
| 876 | .ReleaseFast, .ReleaseSafe => try argv.append("-O3"), | |
| 887 | .debug => {}, | |
| 888 | .small => try argv.append("-O2"), | |
| 889 | .fast, .safe => try argv.append("-O3"), | |
| 877 | 890 | } |
| 878 | 891 | |
| 879 | 892 | if (elf.entry_name) |name| { |
| ... | ... | @@ -1010,8 +1023,8 @@ fn elfLink(lld: *Lld, arena: Allocator) !void { |
| 1010 | 1023 | } |
| 1011 | 1024 | |
| 1012 | 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. | |
| 1014 | // NetBSD expects 2 PT_LOAD segments in a shared object, otherwise | |
| 1026 | // Add options to produce shared objects with only 2 PT.LOAD segments. | |
| 1027 | // NetBSD expects 2 PT.LOAD segments in a shared object, otherwise | |
| 1015 | 1028 | // ld.elf_so fails loading dynamic libraries with "not found" error. |
| 1016 | 1029 | // See https://github.com/ziglang/zig/issues/9109 . |
| 1017 | 1030 | try argv.append("--no-rosegment"); |
| ... | ... | @@ -1416,9 +1429,9 @@ fn wasmLink(lld: *Lld, arena: Allocator) !void { |
| 1416 | 1429 | |
| 1417 | 1430 | if (comp.config.lto != .none) { |
| 1418 | 1431 | switch (comp.root_mod.optimize_mode) { |
| 1419 | .Debug => {}, | |
| 1420 | .ReleaseSmall => try argv.append("-O2"), | |
| 1421 | .ReleaseFast, .ReleaseSafe => try argv.append("-O3"), | |
| 1432 | .debug => {}, | |
| 1433 | .small => try argv.append("-O2"), | |
| 1434 | .fast, .safe => try argv.append("-O3"), | |
| 1422 | 1435 | } |
| 1423 | 1436 | } |
| 1424 | 1437 |
src/link/MachO.zig+35-10| ... | ... | @@ -24,6 +24,8 @@ dylibs: std.ArrayList(File.Index) = .empty, |
| 24 | 24 | |
| 25 | 25 | segments: std.ArrayList(macho.segment_command_64) = .empty, |
| 26 | 26 | sections: std.MultiArrayList(Section) = .{}, |
| 27 | /// Populated by `allocateSections`. | |
| 28 | header_size: ?u32 = null, | |
| 27 | 29 | |
| 28 | 30 | resolver: SymbolResolver = .{}, |
| 29 | 31 | /// This table will be populated after `scanRelocs` has run. |
| ... | ... | @@ -181,7 +183,7 @@ pub fn createEmpty( |
| 181 | 183 | .tag = .macho, |
| 182 | 184 | .comp = comp, |
| 183 | 185 | .emit = emit, |
| 184 | .gc_sections = options.gc_sections orelse (optimize_mode != .Debug), | |
| 186 | .gc_sections = options.gc_sections orelse (optimize_mode != .debug), | |
| 185 | 187 | .print_gc_sections = options.print_gc_sections, |
| 186 | 188 | .stack_size = options.stack_size orelse 16777216, |
| 187 | 189 | .allow_shlib_undefined = allow_shlib_undefined, |
| ... | ... | @@ -990,6 +992,11 @@ fn addArchive(self: *MachO, lib: link.Input.Object, handle: File.HandleIndex, fa |
| 990 | 992 | const tracy = trace(@src()); |
| 991 | 993 | defer tracy.end(); |
| 992 | 994 | |
| 995 | if (self.base.isStaticLib()) { | |
| 996 | // Ignore static library inputs when generating a static library. | |
| 997 | return; | |
| 998 | } | |
| 999 | ||
| 993 | 1000 | const gpa = self.base.comp.gpa; |
| 994 | 1001 | |
| 995 | 1002 | var archive: Archive = .{}; |
| ... | ... | @@ -1068,7 +1075,7 @@ fn isHoisted(self: *MachO, install_name: []const u8) bool { |
| 1068 | 1075 | if (mem.startsWith(u8, dirname, "/usr/lib")) return true; |
| 1069 | 1076 | if (eatPrefix(dirname, "/System/Library/Frameworks/")) |path| { |
| 1070 | 1077 | const basename = fs.path.basename(install_name); |
| 1071 | if (mem.indexOfScalar(u8, path, '.')) |index| { | |
| 1078 | if (mem.findScalar(u8, path, '.')) |index| { | |
| 1072 | 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 | 1744 | }); |
| 1738 | 1745 | } |
| 1739 | 1746 | } else if (eatPrefix(name, "section$start$")) |actual_name| { |
| 1740 | const sep = mem.indexOfScalar(u8, actual_name, '$').?; // TODO error rather than a panic | |
| 1747 | const sep = mem.findScalar(u8, actual_name, '$').?; // TODO error rather than a panic | |
| 1741 | 1748 | const segname = actual_name[0..sep]; // TODO check segname is valid |
| 1742 | 1749 | const sectname = actual_name[sep + 1 ..]; // TODO check sectname is valid |
| 1743 | 1750 | if (self.getSectionByName(segname, sectname) == null) { |
| 1744 | 1751 | _ = try self.addSection(segname, sectname, .{}); |
| 1745 | 1752 | } |
| 1746 | 1753 | } else if (eatPrefix(name, "section$end$")) |actual_name| { |
| 1747 | const sep = mem.indexOfScalar(u8, actual_name, '$').?; // TODO error rather than a panic | |
| 1754 | const sep = mem.findScalar(u8, actual_name, '$').?; // TODO error rather than a panic | |
| 1748 | 1755 | const segname = actual_name[0..sep]; // TODO check segname is valid |
| 1749 | 1756 | const sectname = actual_name[sep + 1 ..]; // TODO check sectname is valid |
| 1750 | 1757 | if (self.getSectionByName(segname, sectname) == null) { |
| ... | ... | @@ -1765,7 +1772,7 @@ fn getSegmentProt(segname: []const u8) macho.vm_prot_t { |
| 1765 | 1772 | fn getSegmentRank(segname: []const u8) u8 { |
| 1766 | 1773 | if (mem.eql(u8, segname, "__PAGEZERO")) return 0x0; |
| 1767 | 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 | 1776 | if (mem.startsWith(u8, segname, "__TEXT")) return 0x1; |
| 1770 | 1777 | if (mem.startsWith(u8, segname, "__DATA_CONST")) return 0x2; |
| 1771 | 1778 | if (mem.startsWith(u8, segname, "__DATA")) return 0x3; |
| ... | ... | @@ -2209,13 +2216,14 @@ fn initSegments(self: *MachO) !void { |
| 2209 | 2216 | } |
| 2210 | 2217 | |
| 2211 | 2218 | fn 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 | 2221 | var vmaddr: u64 = if (self.pagezero_seg_index) |index| |
| 2214 | 2222 | self.segments.items[index].vmaddr + self.segments.items[index].vmsize |
| 2215 | 2223 | else |
| 2216 | 2224 | 0; |
| 2217 | vmaddr += headerpad; | |
| 2218 | var fileoff = headerpad; | |
| 2225 | vmaddr += header_size; | |
| 2226 | var fileoff = header_size; | |
| 2219 | 2227 | var prev_seg_id: u8 = if (self.pagezero_seg_index) |index| index + 1 else 0; |
| 2220 | 2228 | |
| 2221 | 2229 | const page_size = self.getPageSize(); |
| ... | ... | @@ -2339,7 +2347,7 @@ fn allocateSyntheticSymbols(self: *MachO) void { |
| 2339 | 2347 | } |
| 2340 | 2348 | } else if (mem.startsWith(u8, name, "section$start$")) { |
| 2341 | 2349 | const actual_name = name["section$start$".len..]; |
| 2342 | const sep = mem.indexOfScalar(u8, actual_name, '$').?; // TODO error rather than a panic | |
| 2350 | const sep = mem.findScalar(u8, actual_name, '$').?; // TODO error rather than a panic | |
| 2343 | 2351 | const segname = actual_name[0..sep]; |
| 2344 | 2352 | const sectname = actual_name[sep + 1 ..]; |
| 2345 | 2353 | if (self.getSectionByName(segname, sectname)) |sect_id| { |
| ... | ... | @@ -2349,7 +2357,7 @@ fn allocateSyntheticSymbols(self: *MachO) void { |
| 2349 | 2357 | } |
| 2350 | 2358 | } else if (mem.startsWith(u8, name, "section$end$")) { |
| 2351 | 2359 | const actual_name = name["section$end$".len..]; |
| 2352 | const sep = mem.indexOfScalar(u8, actual_name, '$').?; // TODO error rather than a panic | |
| 2360 | const sep = mem.findScalar(u8, actual_name, '$').?; // TODO error rather than a panic | |
| 2353 | 2361 | const segname = actual_name[0..sep]; |
| 2354 | 2362 | const sectname = actual_name[sep + 1 ..]; |
| 2355 | 2363 | if (self.getSectionByName(segname, sectname)) |sect_id| { |
| ... | ... | @@ -2895,6 +2903,11 @@ fn writeLoadCommands(self: *MachO) !struct { usize, usize, u64 } { |
| 2895 | 2903 | ncmds += 1; |
| 2896 | 2904 | } |
| 2897 | 2905 | |
| 2906 | if (self.needsEncryptionInfo()) { | |
| 2907 | try load_commands.writeEncryptionInfoLC(self, &writer); | |
| 2908 | ncmds += 1; | |
| 2909 | } | |
| 2910 | ||
| 2898 | 2911 | for (self.rpath_list) |rpath| { |
| 2899 | 2912 | try load_commands.writeRpathLC(rpath, &writer); |
| 2900 | 2913 | ncmds += 1; |
| ... | ... | @@ -5410,6 +5423,18 @@ pub fn alignPow(macho_file: *MachO, x: u32) error{AlreadyReported}!u32 { |
| 5410 | 5423 | return result; |
| 5411 | 5424 | } |
| 5412 | 5425 | |
| 5426 | pub 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 | 5438 | /// Branch instruction has 26 bits immediate but is 4 byte aligned. |
| 5414 | 5439 | const jump_bits = @bitSizeOf(i28); |
| 5415 | 5440 | const 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 | 45 | const amt = try handle.readPositionalAll(io, buf, pos); |
| 46 | 46 | if (amt != len) return error.InputOutput; |
| 47 | 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 | 49 | break :name buf[0..actual_len]; |
| 50 | 50 | } |
| 51 | 51 | unreachable; |
| ... | ... | @@ -161,7 +161,7 @@ pub const ar_hdr = extern struct { |
| 161 | 161 | fn name(self: *const ar_hdr) ?[]const u8 { |
| 162 | 162 | const value = &self.ar_name; |
| 163 | 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 | 165 | return value[0..sentinel]; |
| 166 | 166 | } |
| 167 | 167 |
src/link/MachO/Symbol.zig+1-1| ... | ... | @@ -43,7 +43,7 @@ pub fn isSymbolStab(symbol: Symbol, macho_file: *MachO) bool { |
| 43 | 43 | |
| 44 | 44 | pub fn isTlvInit(symbol: Symbol, macho_file: *MachO) bool { |
| 45 | 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 | } |
| 48 | 48 | |
| 49 | 49 | pub fn weakRef(symbol: Symbol, macho_file: *MachO) bool { |
src/link/MachO/ZigObject.zig+4-4| ... | ... | @@ -946,8 +946,8 @@ fn updateNavCode( |
| 946 | 946 | const target = &mod.resolved_target.result; |
| 947 | 947 | const required_alignment = switch (nav.resolved.?.@"align") { |
| 948 | 948 | .none => switch (mod.optimize_mode) { |
| 949 | .Debug, .ReleaseSafe, .ReleaseFast => target_util.defaultFunctionAlignment(target), | |
| 950 | .ReleaseSmall => target_util.minFunctionAlignment(target), | |
| 949 | .debug, .safe, .fast => target_util.defaultFunctionAlignment(target), | |
| 950 | .small => target_util.minFunctionAlignment(target), | |
| 951 | 951 | }, |
| 952 | 952 | else => |a| a.maxStrict(target_util.minFunctionAlignment(target)), |
| 953 | 953 | }; |
| ... | ... | @@ -1172,8 +1172,8 @@ fn getNavOutputSection( |
| 1172 | 1172 | if (nav.resolved.?.@"const") return macho_file.zig_const_sect_index.?; |
| 1173 | 1173 | if (nav_val.isUndef(zcu)) |
| 1174 | 1174 | return switch (zcu.navFileScope(nav_index).mod.?.optimize_mode) { |
| 1175 | .Debug, .ReleaseSafe => macho_file.zig_data_sect_index.?, | |
| 1176 | .ReleaseFast, .ReleaseSmall => macho_file.zig_bss_sect_index.?, | |
| 1175 | .debug, .safe => macho_file.zig_data_sect_index.?, | |
| 1176 | .fast, .small => macho_file.zig_bss_sect_index.?, | |
| 1177 | 1177 | }; |
| 1178 | 1178 | for (code) |byte| { |
| 1179 | 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 | 54 | // Check for match with edges from this node. |
| 55 | 55 | for (self.nodes.items(.edges)[node_index].items) |edge_index| { |
| 56 | 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 | 58 | if (match == 0) continue; |
| 59 | 59 | if (match == edge.label.len) return self.putNode(edge.node, allocator, label[match..]); |
| 60 | 60 | |
| ... | ... | @@ -351,7 +351,7 @@ fn expectEqualHexStrings(expected: []const u8, given: []const u8) !void { |
| 351 | 351 | defer testing.allocator.free(expected_fmt); |
| 352 | 352 | const given_fmt = try std.fmt.allocPrint(testing.allocator, "{x}", .{given}); |
| 353 | 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 | 355 | const padding = try testing.allocator.alloc(u8, idx + 5); |
| 356 | 356 | defer testing.allocator.free(padding); |
| 357 | 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 | 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 | 69 | // LC_RPATH |
| 66 | 70 | { |
| 67 | 71 | for (macho_file.rpath_list) |rpath| { |
| ... | ... | @@ -163,23 +167,29 @@ pub fn calcLoadCommandsSizeObject(macho_file: *MachO) u32 { |
| 163 | 167 | return @as(u32, @intCast(sizeofcmds)); |
| 164 | 168 | } |
| 165 | 169 | |
| 166 | pub fn calcMinHeaderPadSize(macho_file: *MachO) !u32 { | |
| 170 | pub fn calcMinHeaderSize(macho_file: *MachO) !u32 { | |
| 167 | 171 | var padding: u32 = (try calcLoadCommandsSize(macho_file, false)) + |
| 168 | 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)}); | |
| 170 | 174 | |
| 171 | 175 | if (macho_file.headerpad_max_install_names) { |
| 172 | 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 | 178 | min_headerpad_size + @sizeOf(macho.mach_header_64), |
| 175 | 179 | }); |
| 176 | 180 | padding = @max(padding, min_headerpad_size); |
| 177 | 181 | } |
| 178 | 182 | |
| 179 | 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}); | |
| 181 | 185 | |
| 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 | } |
| 184 | 194 | |
| 185 | 195 | pub fn writeDylinkerLC(writer: *Writer) !void { |
| ... | ... | @@ -260,6 +270,13 @@ pub fn writeDylibIdLC(macho_file: *MachO, writer: *Writer) !void { |
| 260 | 270 | }, writer); |
| 261 | 271 | } |
| 262 | 272 | |
| 273 | pub 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 | ||
| 263 | 280 | pub fn writeRpathLC(rpath: []const u8, writer: *Writer) !void { |
| 264 | 281 | const rpath_len = rpath.len + 1; |
| 265 | 282 | const cmdsize = @as(u32, @intCast(mem.alignForward( |
src/link/MappedFile.zig+93-41| ... | ... | @@ -23,6 +23,7 @@ nodes: std.ArrayList(Node), |
| 23 | 23 | free_ni: Node.Index, |
| 24 | 24 | large: std.ArrayList(u64), |
| 25 | 25 | updates: std.ArrayList(Node.Index), |
| 26 | /// This progress node's estimated total items is increased once for each node appended to `updates`. | |
| 26 | 27 | update_prog_node: std.Progress.Node, |
| 27 | 28 | writers: std.SinglyLinkedList, |
| 28 | 29 | io_err: ?IoError, |
| ... | ... | @@ -61,7 +62,7 @@ pub const Error = Allocator.Error || Io.Cancelable || error{ |
| 61 | 62 | MappedFileIo, |
| 62 | 63 | }; |
| 63 | 64 | |
| 64 | pub fn init(file: Io.File, gpa: std.mem.Allocator, io: Io) (Allocator.Error || Io.Cancelable || IoError)!MappedFile { | |
| 65 | pub fn init(file: Io.File, gpa: Allocator, io: Io) (Allocator.Error || Io.Cancelable || IoError)!MappedFile { | |
| 65 | 66 | var mf: MappedFile = .{ |
| 66 | 67 | .io = io, |
| 67 | 68 | .flags = undefined, |
| ... | ... | @@ -105,7 +106,7 @@ pub fn init(file: Io.File, gpa: std.mem.Allocator, io: Io) (Allocator.Error || I |
| 105 | 106 | return mf; |
| 106 | 107 | } |
| 107 | 108 | |
| 108 | pub fn deinit(mf: *MappedFile, gpa: std.mem.Allocator) void { | |
| 109 | pub fn deinit(mf: *MappedFile, gpa: Allocator) void { | |
| 109 | 110 | mf.unmap(); |
| 110 | 111 | mf.nodes.deinit(gpa); |
| 111 | 112 | mf.large.deinit(gpa); |
| ... | ... | @@ -133,11 +134,15 @@ pub const Node = extern struct { |
| 133 | 134 | moved: bool, |
| 134 | 135 | /// Whether this node has been resized. |
| 135 | 136 | resized: bool, |
| 137 | /// Whether the next sibling has moved or is a different node. | |
| 138 | next_moved: bool, | |
| 136 | 139 | /// Whether this node might contain non-zero bytes. |
| 137 | 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 | 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 | }; |
| 142 | 147 | |
| 143 | 148 | pub const Location = union(enum(u1)) { |
| ... | ... | @@ -191,6 +196,22 @@ pub const Node = extern struct { |
| 191 | 196 | pub fn next(ni: Node.Index, mf: *const MappedFile) Node.Index { |
| 192 | 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 | } | |
| 194 | 215 | |
| 195 | 216 | pub fn ChildIterator(comptime direction: enum { prev, next }) type { |
| 196 | 217 | return struct { |
| ... | ... | @@ -211,7 +232,7 @@ pub const Node = extern struct { |
| 211 | 232 | return .{ .mf = mf, .ni = ni.get(mf).last }; |
| 212 | 233 | } |
| 213 | 234 | |
| 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 | 236 | var child_ni = ni.get(mf).last; |
| 216 | 237 | while (child_ni != .none) { |
| 217 | 238 | try child_ni.moved(gpa, mf); |
| ... | ... | @@ -229,11 +250,11 @@ pub const Node = extern struct { |
| 229 | 250 | } |
| 230 | 251 | return false; |
| 231 | 252 | } |
| 232 | pub fn moved(ni: Node.Index, gpa: std.mem.Allocator, mf: *MappedFile) Allocator.Error!void { | |
| 233 | try mf.updates.ensureUnusedCapacity(gpa, 1); | |
| 253 | pub fn moved(ni: Node.Index, gpa: Allocator, mf: *MappedFile) Allocator.Error!void { | |
| 254 | try mf.updates.ensureUnusedCapacity(gpa, 2); | |
| 234 | 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 | 258 | const node_moved = &ni.get(mf).flags.moved; |
| 238 | 259 | defer node_moved.* = false; |
| 239 | 260 | return node_moved.*; |
| ... | ... | @@ -242,7 +263,11 @@ pub const Node = extern struct { |
| 242 | 263 | if (ni.hasMoved(mf)) return; |
| 243 | 264 | const node = ni.get(mf); |
| 244 | 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 | 271 | mf.updates.appendAssumeCapacity(ni); |
| 247 | 272 | mf.update_prog_node.increaseEstimatedTotalItems(1); |
| 248 | 273 | } |
| ... | ... | @@ -250,11 +275,11 @@ pub const Node = extern struct { |
| 250 | 275 | pub fn hasResized(ni: Node.Index, mf: *const MappedFile) bool { |
| 251 | 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 | 279 | try mf.updates.ensureUnusedCapacity(gpa, 1); |
| 255 | 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 | 283 | const node_resized = &ni.get(mf).flags.resized; |
| 259 | 284 | defer node_resized.* = false; |
| 260 | 285 | return node_resized.*; |
| ... | ... | @@ -263,7 +288,28 @@ pub const Node = extern struct { |
| 263 | 288 | const node = ni.get(mf); |
| 264 | 289 | if (node.flags.resized) return; |
| 265 | 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 | 313 | mf.updates.appendAssumeCapacity(ni); |
| 268 | 314 | mf.update_prog_node.increaseEstimatedTotalItems(1); |
| 269 | 315 | } |
| ... | ... | @@ -333,7 +379,7 @@ pub const Node = extern struct { |
| 333 | 379 | return mf.memory_map.memory[@intCast(file_loc.offset)..][0..@intCast(file_loc.size)]; |
| 334 | 380 | } |
| 335 | 381 | |
| 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 | 383 | mf.resizeNode(gpa, ni, size) catch |err| switch (err) { |
| 338 | 384 | error.OutOfMemory, |
| 339 | 385 | error.Canceled, |
| ... | ... | @@ -360,7 +406,7 @@ pub const Node = extern struct { |
| 360 | 406 | pub fn realign( |
| 361 | 407 | ni: Node.Index, |
| 362 | 408 | mf: *MappedFile, |
| 363 | gpa: std.mem.Allocator, | |
| 409 | gpa: Allocator, | |
| 364 | 410 | new_alignment: std.mem.Alignment, |
| 365 | 411 | opts: RealignNodeOptions, |
| 366 | 412 | ) Error!void { |
| ... | ... | @@ -384,7 +430,7 @@ pub const Node = extern struct { |
| 384 | 430 | pub fn shrink( |
| 385 | 431 | ni: Node.Index, |
| 386 | 432 | mf: *MappedFile, |
| 387 | gpa: std.mem.Allocator, | |
| 433 | gpa: Allocator, | |
| 388 | 434 | size: u64, |
| 389 | 435 | shift_next: bool, |
| 390 | 436 | ) Error!void { |
| ... | ... | @@ -392,7 +438,7 @@ pub const Node = extern struct { |
| 392 | 438 | mf.updateWriters(); |
| 393 | 439 | } |
| 394 | 440 | |
| 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 | 442 | w.* = .{ |
| 397 | 443 | .gpa = gpa, |
| 398 | 444 | .mf = mf, |
| ... | ... | @@ -419,7 +465,7 @@ pub const Node = extern struct { |
| 419 | 465 | } |
| 420 | 466 | |
| 421 | 467 | pub const Writer = struct { |
| 422 | gpa: std.mem.Allocator, | |
| 468 | gpa: Allocator, | |
| 423 | 469 | mf: *MappedFile, |
| 424 | 470 | writer_node: std.SinglyLinkedList.Node, |
| 425 | 471 | ni: Node.Index, |
| ... | ... | @@ -543,14 +589,13 @@ pub const Node = extern struct { |
| 543 | 589 | } |
| 544 | 590 | }; |
| 545 | 591 | |
| 546 | fn addNode(mf: *MappedFile, gpa: std.mem.Allocator, opts: struct { | |
| 592 | fn addNode(mf: *MappedFile, gpa: Allocator, opts: struct { | |
| 547 | 593 | parent: Node.Index = .none, |
| 548 | 594 | prev: Node.Index = .none, |
| 549 | 595 | next: Node.Index = .none, |
| 550 | 596 | offset: u64 = 0, |
| 551 | 597 | add_node: AddNodeOptions, |
| 552 | 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 | 599 | mf.nodes_lock.assertUnlocked(); |
| 555 | 600 | const location_tag: Node.Location.Tag, const location_payload: Node.Location.Payload = location: { |
| 556 | 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 | 615 | }; |
| 571 | 616 | switch (opts.prev) { |
| 572 | 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 | 620 | switch (opts.next) { |
| 576 | 621 | .none => opts.parent.get(mf).last = free_ni, |
| ... | ... | @@ -588,22 +633,27 @@ fn addNode(mf: *MappedFile, gpa: std.mem.Allocator, opts: struct { |
| 588 | 633 | .fixed = opts.add_node.fixed, |
| 589 | 634 | .moved = true, |
| 590 | 635 | .resized = true, |
| 636 | .next_moved = true, | |
| 591 | 637 | .has_content = false, |
| 592 | 638 | .bubbles_moved = opts.add_node.bubbles_moved, |
| 639 | .enable_next_moved = opts.add_node.enable_next_moved, | |
| 593 | 640 | }, |
| 594 | 641 | .location_payload = location_payload, |
| 595 | 642 | }; |
| 596 | 643 | |
| 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 | 650 | try mf.realignNode(gpa, free_ni, opts.add_node.alignment, .{}); |
| 599 | 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 | 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 | 657 | return free_ni; |
| 608 | 658 | } |
| 609 | 659 | |
| ... | ... | @@ -613,12 +663,14 @@ pub const AddNodeOptions = struct { |
| 613 | 663 | fixed: bool = false, |
| 614 | 664 | moved: bool = false, |
| 615 | 665 | resized: bool = false, |
| 666 | next_moved: bool = false, | |
| 616 | 667 | bubbles_moved: bool = true, |
| 668 | enable_next_moved: bool = false, | |
| 617 | 669 | }; |
| 618 | 670 | |
| 619 | 671 | pub fn addOnlyChildNode( |
| 620 | 672 | mf: *MappedFile, |
| 621 | gpa: std.mem.Allocator, | |
| 673 | gpa: Allocator, | |
| 622 | 674 | parent_ni: Node.Index, |
| 623 | 675 | opts: AddNodeOptions, |
| 624 | 676 | ) Error!Node.Index { |
| ... | ... | @@ -641,7 +693,7 @@ pub fn addOnlyChildNode( |
| 641 | 693 | |
| 642 | 694 | pub fn addFirstChildNode( |
| 643 | 695 | mf: *MappedFile, |
| 644 | gpa: std.mem.Allocator, | |
| 696 | gpa: Allocator, | |
| 645 | 697 | parent_ni: Node.Index, |
| 646 | 698 | opts: AddNodeOptions, |
| 647 | 699 | ) Error!Node.Index { |
| ... | ... | @@ -664,7 +716,7 @@ pub fn addFirstChildNode( |
| 664 | 716 | |
| 665 | 717 | pub fn addLastChildNode( |
| 666 | 718 | mf: *MappedFile, |
| 667 | gpa: std.mem.Allocator, | |
| 719 | gpa: Allocator, | |
| 668 | 720 | parent_ni: Node.Index, |
| 669 | 721 | opts: AddNodeOptions, |
| 670 | 722 | ) Error!Node.Index { |
| ... | ... | @@ -694,7 +746,7 @@ pub fn addLastChildNode( |
| 694 | 746 | |
| 695 | 747 | pub fn addNodeAfter( |
| 696 | 748 | mf: *MappedFile, |
| 697 | gpa: std.mem.Allocator, | |
| 749 | gpa: Allocator, | |
| 698 | 750 | prev_ni: Node.Index, |
| 699 | 751 | opts: AddNodeOptions, |
| 700 | 752 | ) Error!Node.Index { |
| ... | ... | @@ -721,7 +773,7 @@ pub fn addNodeAfter( |
| 721 | 773 | |
| 722 | 774 | fn shrinkNode( |
| 723 | 775 | mf: *MappedFile, |
| 724 | gpa: std.mem.Allocator, | |
| 776 | gpa: Allocator, | |
| 725 | 777 | ni: Node.Index, |
| 726 | 778 | size: u64, |
| 727 | 779 | shift_next: bool, |
| ... | ... | @@ -740,7 +792,7 @@ fn shrinkNode( |
| 740 | 792 | } |
| 741 | 793 | |
| 742 | 794 | try mf.large.ensureUnusedCapacity(gpa, 4); |
| 743 | try mf.updates.ensureUnusedCapacity(gpa, 2); | |
| 795 | try mf.updates.ensureUnusedCapacity(gpa, 4); | |
| 744 | 796 | |
| 745 | 797 | ni.setLocationAssumeCapacity(mf, old_offset, size); |
| 746 | 798 | if (!shift_next or node.next == .none) return; |
| ... | ... | @@ -765,7 +817,7 @@ fn shrinkNode( |
| 765 | 817 | |
| 766 | 818 | fn resizeNode( |
| 767 | 819 | mf: *MappedFile, |
| 768 | gpa: std.mem.Allocator, | |
| 820 | gpa: Allocator, | |
| 769 | 821 | ni: Node.Index, |
| 770 | 822 | requested_size: u64, |
| 771 | 823 | ) (Allocator.Error || Io.Cancelable || IoError)!void { |
| ... | ... | @@ -904,11 +956,11 @@ fn resizeNode( |
| 904 | 956 | next_ni.get(mf).prev = node.prev; |
| 905 | 957 | switch (node.prev) { |
| 906 | 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 | 962 | node.prev = parent.last; |
| 911 | node.next = .none; | |
| 963 | try ni.setNext(gpa, .none, mf); | |
| 912 | 964 | parent.last = ni; |
| 913 | 965 | if (node.flags.has_content) { |
| 914 | 966 | const parent_file_offset = node.parent.fileLocation(mf, false).offset; |
| ... | ... | @@ -972,13 +1024,13 @@ fn resizeNode( |
| 972 | 1024 | if (parent.last != first_floating_ni) { |
| 973 | 1025 | first_floating.prev = parent.last; |
| 974 | 1026 | parent.last = first_floating_ni; |
| 975 | last.next = first_floating_ni; | |
| 976 | last_fixed.next = first_floating.next; | |
| 1027 | try parent.last.setNext(gpa, first_floating_ni, mf); | |
| 1028 | try last_fixed_ni.setNext(gpa, first_floating.next, mf); | |
| 977 | 1029 | switch (first_floating.next) { |
| 978 | 1030 | .none => {}, |
| 979 | 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 | 1035 | if (first_floating.flags.has_content) { |
| 984 | 1036 | const parent_file_offset = |
| ... | ... | @@ -1040,7 +1092,7 @@ fn resizeNode( |
| 1040 | 1092 | |
| 1041 | 1093 | fn realignNode( |
| 1042 | 1094 | mf: *MappedFile, |
| 1043 | gpa: std.mem.Allocator, | |
| 1095 | gpa: Allocator, | |
| 1044 | 1096 | ni: Node.Index, |
| 1045 | 1097 | new_alignment: std.mem.Alignment, |
| 1046 | 1098 | opts: Node.Index.RealignNodeOptions, |
| ... | ... | @@ -1241,9 +1293,9 @@ fn copyFileRange( |
| 1241 | 1293 | return size - remaining_size; |
| 1242 | 1294 | } |
| 1243 | 1295 | |
| 1244 | fn ensureCapacityForSetLocation(mf: *MappedFile, gpa: std.mem.Allocator) Allocator.Error!void { | |
| 1296 | fn ensureCapacityForSetLocation(mf: *MappedFile, gpa: Allocator) Allocator.Error!void { | |
| 1245 | 1297 | try mf.large.ensureUnusedCapacity(gpa, 2); |
| 1246 | try mf.updates.ensureUnusedCapacity(gpa, 1); | |
| 1298 | try mf.updates.ensureUnusedCapacity(gpa, 2); | |
| 1247 | 1299 | } |
| 1248 | 1300 | |
| 1249 | 1301 | pub 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 | 25 | const Linker = @This(); |
| 26 | 26 | |
| 27 | 27 | base: link.File, |
| 28 | fragments: std.AutoArrayHashMapUnmanaged(InternPool.Nav.Index, Mir) = .empty, | |
| 29 | pending_navs: std.ArrayListUnmanaged(InternPool.Nav.Index) = .empty, | |
| 30 | entry_points: std.ArrayListUnmanaged(EntryPointDecl) = .empty, | |
| 31 | external_objects: std.ArrayListUnmanaged(ExternalObject) = .empty, | |
| 28 | fragments: std.array_hash_map.Auto(InternPool.Nav.Index, Mir) = .empty, | |
| 29 | pending_navs: std.ArrayList(InternPool.Nav.Index) = .empty, | |
| 30 | entry_points: std.ArrayList(EntryPointDecl) = .empty, | |
| 31 | external_objects: std.ArrayList(ExternalObject) = .empty, | |
| 32 | 32 | |
| 33 | 33 | const EntryPointDecl = struct { |
| 34 | 34 | nav: InternPool.Nav.Index, |
| ... | ... | @@ -363,16 +363,16 @@ fn mergeFragments(linker: *Linker, gpa: Allocator, arena: Allocator) error{OutOf |
| 363 | 363 | } |
| 364 | 364 | |
| 365 | 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 | 367 | defer ext_id_offsets.deinit(gpa); |
| 368 | 368 | try ext_id_offsets.ensureTotalCapacity(gpa, linker.external_objects.items.len); |
| 369 | 369 | |
| 370 | 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 | 372 | defer resolved_ids.deinit(gpa); |
| 373 | 373 | |
| 374 | 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 | 376 | defer extern_name_map.deinit(gpa); |
| 377 | 377 | |
| 378 | 378 | var nav_it = nav_final_ids.iterator(); |
| ... | ... | @@ -518,14 +518,14 @@ fn mergeZigFragments( |
| 518 | 518 | frag_infos: []const FragmentInfo, |
| 519 | 519 | nav_final_ids: *const std.AutoHashMapUnmanaged(InternPool.Nav.Index, Id), |
| 520 | 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 | 522 | maybe_ip: ?*InternPool, |
| 523 | 523 | ) error{OutOfMemory}!void { |
| 524 | 524 | for (linker.fragments.values(), frag_infos) |*mir, frag_info| { |
| 525 | 525 | var id_remap: std.AutoHashMapUnmanaged(Id, Id) = .empty; |
| 526 | 526 | defer id_remap.deinit(gpa); |
| 527 | 527 | |
| 528 | var resolved_local_ids: std.AutoArrayHashMapUnmanaged(Id, void) = .empty; | |
| 528 | var resolved_local_ids: std.array_hash_map.Auto(Id, void) = .empty; | |
| 529 | 529 | defer resolved_local_ids.deinit(gpa); |
| 530 | 530 | |
| 531 | 531 | for (mir.nav_refs) |ref| { |
| ... | ... | @@ -569,7 +569,7 @@ fn remapFilteredInsts( |
| 569 | 569 | id_offset: Word, |
| 570 | 570 | id_remap: *const std.AutoHashMapUnmanaged(Id, Id), |
| 571 | 571 | parser: *BinaryModule.Parser, |
| 572 | skip_ids: *const std.AutoArrayHashMapUnmanaged(Id, void), | |
| 572 | skip_ids: *const std.array_hash_map.Auto(Id, void), | |
| 573 | 573 | mode: FilterMode, |
| 574 | 574 | ) error{OutOfMemory}!void { |
| 575 | 575 | if (words.len == 0) return; |
| ... | ... | @@ -887,9 +887,9 @@ fn appendExternalObjects( |
| 887 | 887 | has_linkage: *bool, |
| 888 | 888 | keep_entry_points: bool, |
| 889 | 889 | is_obj: bool, |
| 890 | resolved_ids: *const std.AutoArrayHashMapUnmanaged(Id, void), | |
| 890 | resolved_ids: *const std.array_hash_map.Auto(Id, void), | |
| 891 | 891 | ) error{OutOfMemory}!void { |
| 892 | var export_map: std.StringArrayHashMapUnmanaged(Id) = .empty; | |
| 892 | var export_map: std.array_hash_map.String(Id) = .empty; | |
| 893 | 893 | defer export_map.deinit(gpa); |
| 894 | 894 | |
| 895 | 895 | for (linker.external_objects.items, ext_id_offsets) |ext_obj, id_offset| { |
| ... | ... | @@ -908,7 +908,7 @@ fn appendExternalObjects( |
| 908 | 908 | } |
| 909 | 909 | for (per_obj_remaps) |*m| m.* = .empty; |
| 910 | 910 | |
| 911 | var resolved_linkage_ids: std.AutoArrayHashMapUnmanaged(Id, void) = .empty; | |
| 911 | var resolved_linkage_ids: std.array_hash_map.Auto(Id, void) = .empty; | |
| 912 | 912 | defer resolved_linkage_ids.deinit(gpa); |
| 913 | 913 | |
| 914 | 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 | 85 | |
| 86 | 86 | for (inst.operands, 0..) |word, i| { |
| 87 | 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 | 89 | const canonical = id_remap.get(@fromBackingInt(@intCast(word))) orelse @as(Id, @fromBackingInt(@intCast(word))); |
| 90 | 90 | try key_words.append(gpa, @backingInt(canonical)); |
| 91 | 91 | } else { |
| ... | ... | @@ -182,7 +182,7 @@ pub fn run(parser: *BinaryModule.Parser, binary: *BinaryModule) !void { |
| 182 | 182 | } else null; |
| 183 | 183 | |
| 184 | 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 | 186 | max_id = @max(max_id, word.*); |
| 187 | 187 | if (maybe_result_id_index != null and i == maybe_result_id_index.?) continue; |
| 188 | 188 |
src/link/SpirV/prune_unused.zig+1-1| ... | ... | @@ -187,7 +187,7 @@ fn markAlive( |
| 187 | 187 | parser: *BinaryModule.Parser, |
| 188 | 188 | binary: BinaryModule, |
| 189 | 189 | inst: BinaryModule.Instruction, |
| 190 | alive: *std.DynamicBitSetUnmanaged, | |
| 190 | alive: *std.bit_set.Dynamic, | |
| 191 | 191 | id_to_index: *const std.AutoHashMapUnmanaged(ResultId, u32), |
| 192 | 192 | code_offsets: *const std.ArrayList(usize), |
| 193 | 193 | id_offset_buf: *std.ArrayList(u16), |
src/link/Wasm.zig+953-206| ... | ... | @@ -133,25 +133,21 @@ object_total_sections: u32 = 0, |
| 133 | 133 | /// All comdat symbols from all objects concatenated. |
| 134 | 134 | object_comdat_symbols: std.MultiArrayList(Comdat.Symbol) = .empty, |
| 135 | 135 | |
| 136 | /// Relocations to be emitted into an object file. Remains empty when not | |
| 137 | /// emitting an object file. | |
| 138 | out_relocs: std.MultiArrayList(OutReloc) = .empty, | |
| 136 | /// Relocations produced by Zig code and data lowering. These retain semantic | |
| 137 | /// targets until `flush`, where final output indexes are known. | |
| 138 | zcu_relocations: std.MultiArrayList(ZcuRelocation) = .empty, | |
| 139 | 139 | /// List of locations within `string_bytes` that must be patched with the virtual |
| 140 | 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. | |
| 142 | 142 | uav_fixups: std.ArrayList(UavFixup) = .empty, |
| 143 | 143 | /// List of locations within `string_bytes` that must be patched with the virtual |
| 144 | 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 | 146 | /// No functions here only global variables. |
| 147 | 147 | nav_fixups: std.ArrayList(NavFixup) = .empty, |
| 148 | 148 | /// When a nav reference is a function pointer, this tracks the required function |
| 149 | 149 | /// table entry index that needs to overwrite the code in the final output. |
| 150 | 150 | func_table_fixups: std.ArrayList(FuncTableFixup) = .empty, |
| 151 | /// Symbols to be emitted into an object file. Remains empty when not emitting | |
| 152 | /// an object file. | |
| 153 | symbol_table: std.array_hash_map.Auto(String, void) = .empty, | |
| 154 | ||
| 155 | 151 | /// When importing objects from the host environment, a name must be supplied. |
| 156 | 152 | /// LLVM uses "env" by default when none is given. |
| 157 | 153 | /// 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 | 240 | /// remove elements from the table, and the remainder are either undefined |
| 245 | 241 | /// symbol errors, or symbol table entries depending on the output mode. |
| 246 | 242 | data_imports: std.array_hash_map.Auto(String, DataImportId) = .empty, |
| 247 | /// Set of data symbols that will appear in the final binary. Used to populate | |
| 243 | /// Set of data symbols that will appear in the final binary when outputting an object file. | |
| 244 | datas: 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 | 246 | /// `Flush.data_segments` before sorting. |
| 249 | 247 | data_segments: std.array_hash_map.Auto(DataSegmentId, void) = .empty, |
| 250 | 248 | |
| ... | ... | @@ -302,11 +300,6 @@ pub const TagNameOff = extern struct { |
| 302 | 300 | len: u32, |
| 303 | 301 | }; |
| 304 | 302 | |
| 305 | /// Index into `Wasm.zcu_indirect_function_set`. | |
| 306 | pub const ZcuIndirectFunctionSetIndex = enum(u32) { | |
| 307 | _, | |
| 308 | }; | |
| 309 | ||
| 310 | 303 | pub const UavFixup = extern struct { |
| 311 | 304 | uavs_exe_index: UavsExeIndex, |
| 312 | 305 | /// Index into `string_bytes`. |
| ... | ... | @@ -315,14 +308,14 @@ pub const UavFixup = extern struct { |
| 315 | 308 | }; |
| 316 | 309 | |
| 317 | 310 | pub const NavFixup = extern struct { |
| 318 | navs_exe_index: NavsExeIndex, | |
| 311 | nav_index: InternPool.Nav.Index, | |
| 319 | 312 | /// Index into `string_bytes`. |
| 320 | 313 | offset: u32, |
| 321 | 314 | addend: u32, |
| 322 | 315 | }; |
| 323 | 316 | |
| 324 | 317 | pub const FuncTableFixup = extern struct { |
| 325 | table_index: ZcuIndirectFunctionSetIndex, | |
| 318 | nav_index: InternPool.Nav.Index, | |
| 326 | 319 | /// Index into `string_bytes`. |
| 327 | 320 | offset: u32, |
| 328 | 321 | }; |
| ... | ... | @@ -355,7 +348,9 @@ pub const FunctionIndex = enum(u32) { |
| 355 | 348 | |
| 356 | 349 | pub fn fromSymbolName(wasm: *const Wasm, name: String) ?FunctionIndex { |
| 357 | 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 | 355 | if (wasm.function_exports.get(name)) |index| return index; |
| 361 | 356 | if (wasm.hidden_function_exports.get(name)) |index| return index; |
| ... | ... | @@ -374,7 +369,8 @@ pub const GlobalExport = extern struct { |
| 374 | 369 | }; |
| 375 | 370 | |
| 376 | 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 | 375 | /// Note that function_imports indexes are subject to swap removals during |
| 380 | 376 | /// `flush`. |
| ... | ... | @@ -386,7 +382,11 @@ pub const OutputFunctionIndex = enum(u32) { |
| 386 | 382 | } |
| 387 | 383 | |
| 388 | 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 | } |
| 391 | 391 | |
| 392 | 392 | pub fn fromObjectFunction(wasm: *const Wasm, index: ObjectFunctionIndex) OutputFunctionIndex { |
| ... | ... | @@ -429,6 +429,9 @@ pub const OutputFunctionIndex = enum(u32) { |
| 429 | 429 | |
| 430 | 430 | pub fn fromSymbolName(wasm: *const Wasm, name: String) OutputFunctionIndex { |
| 431 | 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 | 435 | return fromFunctionIndex(wasm, FunctionIndex.fromSymbolName(wasm, name) orelse { |
| 433 | 436 | if (std.debug.runtime_safety) { |
| 434 | 437 | std.debug.panic("function index for symbol not found: {s}", .{name.slice(wasm)}); |
| ... | ... | @@ -437,6 +440,56 @@ pub const OutputFunctionIndex = enum(u32) { |
| 437 | 440 | } |
| 438 | 441 | }; |
| 439 | 442 | |
| 443 | // Order | |
| 444 | // 0. Flush.data_imports | |
| 445 | // 1. Wasm.datas | |
| 446 | pub 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 | 493 | /// Index into `Wasm.globals`. |
| 441 | 494 | pub const GlobalIndex = enum(u32) { |
| 442 | 495 | _, |
| ... | ... | @@ -452,17 +505,17 @@ pub const GlobalIndex = enum(u32) { |
| 452 | 505 | return .stack_pointer; |
| 453 | 506 | } |
| 454 | 507 | |
| 455 | pub fn ptr(index: GlobalIndex, f: *const Flush) *Wasm.GlobalImport.Resolution { | |
| 456 | return &f.globals.items[@backingInt(index)]; | |
| 508 | pub fn fromResolution(wasm: *const Wasm, resolution: GlobalImport.Resolution) ?GlobalIndex { | |
| 509 | const i = wasm.globals.getIndex(resolution) orelse return null; | |
| 510 | return @fromBackingInt(@intCast(wasm.flush_buffer.global_imports.entries.len + i)); | |
| 457 | 511 | } |
| 458 | 512 | |
| 459 | 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; | |
| 461 | return @fromBackingInt(@intCast(i)); | |
| 514 | return fromResolution(wasm, .fromIpNav(wasm, nav_index)); | |
| 462 | 515 | } |
| 463 | 516 | |
| 464 | 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 | } |
| 467 | 520 | |
| 468 | 521 | pub fn fromObjectGlobalHandlingWeak(wasm: *const Wasm, index: ObjectGlobalIndex) GlobalIndex { |
| ... | ... | @@ -474,8 +527,9 @@ pub const GlobalIndex = enum(u32) { |
| 474 | 527 | } |
| 475 | 528 | |
| 476 | 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 | 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 | }; |
| 481 | 535 | |
| ... | ... | @@ -483,10 +537,6 @@ pub const GlobalIndex = enum(u32) { |
| 483 | 537 | pub const TableIndex = enum(u32) { |
| 484 | 538 | _, |
| 485 | 539 | |
| 486 | pub fn ptr(index: TableIndex, f: *const Flush) *Wasm.TableImport.Resolution { | |
| 487 | return &f.tables.items[@backingInt(index)]; | |
| 488 | } | |
| 489 | ||
| 490 | 540 | pub fn fromObjectTable(wasm: *const Wasm, i: ObjectTableIndex) TableIndex { |
| 491 | 541 | return @fromBackingInt(@intCast(wasm.tables.getIndex(.fromObjectTable(i)).?)); |
| 492 | 542 | } |
| ... | ... | @@ -668,9 +718,10 @@ pub const SymbolFlags = packed struct(u32) { |
| 668 | 718 | flags.ref_type = .funcref; |
| 669 | 719 | } |
| 670 | 720 | |
| 671 | pub fn isIncluded(flags: SymbolFlags, is_dynamic: bool) bool { | |
| 721 | pub fn isIncluded(flags: SymbolFlags, is_dynamic: bool, is_obj: bool) bool { | |
| 672 | 722 | return flags.exported or |
| 673 | 723 | (is_dynamic and !flags.visibility_hidden) or |
| 724 | (is_obj and flags.binding != .local) or | |
| 674 | 725 | (flags.no_strip and flags.must_link); |
| 675 | 726 | } |
| 676 | 727 | |
| ... | ... | @@ -696,8 +747,8 @@ pub const SymbolFlags = packed struct(u32) { |
| 696 | 747 | /// Masks off the Zig-specific stuff. |
| 697 | 748 | pub fn toAbiInteger(flags: SymbolFlags) u32 { |
| 698 | 749 | var copy = flags; |
| 699 | copy.initZigSpecific(false, false); | |
| 700 | return @bitCast(copy); | |
| 750 | copy.initZigSpecific(false, flags.no_strip); | |
| 751 | return @backingInt(copy); | |
| 701 | 752 | } |
| 702 | 753 | }; |
| 703 | 754 | |
| ... | ... | @@ -812,7 +863,7 @@ pub const UavsExeIndex = enum(u32) { |
| 812 | 863 | /// Used when emitting a relocatable object. |
| 813 | 864 | pub const ZcuDataObj = extern struct { |
| 814 | 865 | code: DataPayload, |
| 815 | relocs: OutReloc.Slice, | |
| 866 | relocs: ZcuRelocation.Slice, | |
| 816 | 867 | }; |
| 817 | 868 | |
| 818 | 869 | /// Used when not emitting a relocatable object. |
| ... | ... | @@ -855,7 +906,9 @@ const ZcuDataStarts = struct { |
| 855 | 906 | var uavs_i = zds.uavs_i; |
| 856 | 907 | while (uavs_i < wasm.uavs_obj.entries.len) : (uavs_i += 1) { |
| 857 | 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 | } |
| 861 | 914 | |
| ... | ... | @@ -906,6 +959,51 @@ pub const ZcuFunc = union { |
| 906 | 959 | return &wasm.zcu_funcs.values()[@backingInt(i)]; |
| 907 | 960 | } |
| 908 | 961 | |
| 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 | 1007 | pub fn name(i: @This(), wasm: *const Wasm) [:0]const u8 { |
| 910 | 1008 | const zcu = wasm.base.comp.zcu.?; |
| 911 | 1009 | const ip = &zcu.intern_pool; |
| ... | ... | @@ -1034,6 +1132,15 @@ pub const FunctionImport = extern struct { |
| 1034 | 1132 | return pack(wasm, .{ .object_function = object_function }); |
| 1035 | 1133 | } |
| 1036 | 1134 | |
| 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 | 1144 | pub fn isNavOrUnresolved(r: Resolution, wasm: *const Wasm) bool { |
| 1038 | 1145 | return switch (r.unpack(wasm)) { |
| 1039 | 1146 | .unresolved, .zcu_func => true, |
| ... | ... | @@ -1136,6 +1243,7 @@ pub const GlobalImport = extern struct { |
| 1136 | 1243 | __tls_base, |
| 1137 | 1244 | __tls_size, |
| 1138 | 1245 | // Next, index into `object_globals`. |
| 1246 | // Next, index into `uavs_obj` or `uavs_exe` depending on whether emitting an object. | |
| 1139 | 1247 | // Next, index into `navs_obj` or `navs_exe` depending on whether emitting an object. |
| 1140 | 1248 | _, |
| 1141 | 1249 | |
| ... | ... | @@ -1150,6 +1258,8 @@ pub const GlobalImport = extern struct { |
| 1150 | 1258 | __tls_base, |
| 1151 | 1259 | __tls_size, |
| 1152 | 1260 | object_global: ObjectGlobalIndex, |
| 1261 | uav_exe: UavsExeIndex, | |
| 1262 | uav_obj: UavsObjIndex, | |
| 1153 | 1263 | nav_exe: NavsExeIndex, |
| 1154 | 1264 | nav_obj: NavsObjIndex, |
| 1155 | 1265 | }; |
| ... | ... | @@ -1170,12 +1280,22 @@ pub const GlobalImport = extern struct { |
| 1170 | 1280 | return .{ .object_global = @fromBackingInt(@intCast(object_global_index)) }; |
| 1171 | 1281 | const comp = wasm.base.comp; |
| 1172 | 1282 | const is_obj = comp.config.output_mode == .Obj; |
| 1173 | const nav_index = object_global_index - wasm.object_globals.items.len; | |
| 1174 | return if (is_obj) .{ | |
| 1175 | .nav_obj = @fromBackingInt(@intCast(nav_index)), | |
| 1176 | } else .{ | |
| 1177 | .nav_exe = @fromBackingInt(@intCast(nav_index)), | |
| 1178 | }; | |
| 1283 | const uav_index = object_global_index - wasm.object_globals.items.len; | |
| 1284 | if (is_obj) { | |
| 1285 | if (uav_index < wasm.uavs_obj.entries.len) { | |
| 1286 | return .{ .uav_obj = @fromBackingInt(@intCast(uav_index)) }; | |
| 1287 | } | |
| 1288 | return .{ .nav_obj = @fromBackingInt( | |
| 1289 | @intCast(uav_index - wasm.uavs_obj.entries.len), | |
| 1290 | ) }; | |
| 1291 | } else { | |
| 1292 | if (uav_index < wasm.uavs_exe.entries.len) { | |
| 1293 | return .{ .uav_exe = @fromBackingInt(@intCast(uav_index)) }; | |
| 1294 | } | |
| 1295 | return .{ .nav_exe = @fromBackingInt( | |
| 1296 | @intCast(uav_index - wasm.uavs_exe.entries.len), | |
| 1297 | ) }; | |
| 1298 | } | |
| 1179 | 1299 | }, |
| 1180 | 1300 | }; |
| 1181 | 1301 | } |
| ... | ... | @@ -1190,11 +1310,29 @@ pub const GlobalImport = extern struct { |
| 1190 | 1310 | .__tls_base => .__tls_base, |
| 1191 | 1311 | .__tls_size => .__tls_size, |
| 1192 | 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))), | |
| 1194 | .nav_exe => |i| @fromBackingInt(@intCast(first_object_global + wasm.object_globals.items.len + @backingInt(i))), | |
| 1313 | inline .uav_obj, .uav_exe => |i| @fromBackingInt(@intCast( | |
| 1314 | first_object_global + wasm.object_globals.items.len + @backingInt(i), | |
| 1315 | )), | |
| 1316 | .nav_obj => |i| @fromBackingInt(@intCast( | |
| 1317 | first_object_global + wasm.object_globals.items.len + | |
| 1318 | wasm.uavs_obj.entries.len + @backingInt(i), | |
| 1319 | )), | |
| 1320 | .nav_exe => |i| @fromBackingInt(@intCast( | |
| 1321 | first_object_global + wasm.object_globals.items.len + | |
| 1322 | wasm.uavs_exe.entries.len + @backingInt(i), | |
| 1323 | )), | |
| 1195 | 1324 | }; |
| 1196 | 1325 | } |
| 1197 | 1326 | |
| 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 | 1336 | pub fn fromIpNav(wasm: *const Wasm, ip_nav: InternPool.Nav.Index) Resolution { |
| 1199 | 1337 | const comp = wasm.base.comp; |
| 1200 | 1338 | const is_obj = comp.config.output_mode == .Obj; |
| ... | ... | @@ -1209,7 +1347,22 @@ pub const GlobalImport = extern struct { |
| 1209 | 1347 | return pack(wasm, .{ .object_global = object_global }); |
| 1210 | 1348 | } |
| 1211 | 1349 | |
| 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 | 1366 | return switch (unpack(r, wasm)) { |
| 1214 | 1367 | .unresolved => unreachable, |
| 1215 | 1368 | .__heap_base => @tagName(Unpacked.__heap_base), |
| ... | ... | @@ -1219,6 +1372,11 @@ pub const GlobalImport = extern struct { |
| 1219 | 1372 | .__tls_base => @tagName(Unpacked.__tls_base), |
| 1220 | 1373 | .__tls_size => @tagName(Unpacked.__tls_size), |
| 1221 | 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 | 1380 | .nav_obj => |i| i.name(wasm), |
| 1223 | 1381 | .nav_exe => |i| i.name(wasm), |
| 1224 | 1382 | }; |
| ... | ... | @@ -1349,6 +1507,22 @@ pub const TableImport = extern struct { |
| 1349 | 1507 | return pack(.{ .object_table = object_table }); |
| 1350 | 1508 | } |
| 1351 | 1509 | |
| 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 | 1526 | pub fn refType(r: Resolution, wasm: *const Wasm) std.wasm.RefType { |
| 1353 | 1527 | return switch (unpack(r)) { |
| 1354 | 1528 | .unresolved => unreachable, |
| ... | ... | @@ -1602,6 +1776,8 @@ pub const ObjectDataImport = extern struct { |
| 1602 | 1776 | unresolved, |
| 1603 | 1777 | __zig_error_names, |
| 1604 | 1778 | __zig_error_name_table, |
| 1779 | __zig_tag_names, | |
| 1780 | __zig_tag_name_table, | |
| 1605 | 1781 | __heap_base, |
| 1606 | 1782 | __heap_end, |
| 1607 | 1783 | /// Next, an `ObjectData.Index`. |
| ... | ... | @@ -1615,6 +1791,8 @@ pub const ObjectDataImport = extern struct { |
| 1615 | 1791 | unresolved, |
| 1616 | 1792 | __zig_error_names, |
| 1617 | 1793 | __zig_error_name_table, |
| 1794 | __zig_tag_names, | |
| 1795 | __zig_tag_name_table, | |
| 1618 | 1796 | __heap_base, |
| 1619 | 1797 | __heap_end, |
| 1620 | 1798 | object: ObjectData.Index, |
| ... | ... | @@ -1629,6 +1807,8 @@ pub const ObjectDataImport = extern struct { |
| 1629 | 1807 | .unresolved => .unresolved, |
| 1630 | 1808 | .__zig_error_names => .__zig_error_names, |
| 1631 | 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 | 1812 | .__heap_base => .__heap_base, |
| 1633 | 1813 | .__heap_end => .__heap_end, |
| 1634 | 1814 | _ => { |
| ... | ... | @@ -1665,6 +1845,8 @@ pub const ObjectDataImport = extern struct { |
| 1665 | 1845 | .unresolved => .unresolved, |
| 1666 | 1846 | .__zig_error_names => .__zig_error_names, |
| 1667 | 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 | 1850 | .__heap_base => .__heap_base, |
| 1669 | 1851 | .__heap_end => .__heap_end, |
| 1670 | 1852 | .object => |i| @fromBackingInt(@intCast(first_object + @backingInt(i))), |
| ... | ... | @@ -1678,12 +1860,32 @@ pub const ObjectDataImport = extern struct { |
| 1678 | 1860 | return pack(wasm, .{ .object = object_data_index }); |
| 1679 | 1861 | } |
| 1680 | 1862 | |
| 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 | 1881 | pub fn objectDataSegment(r: Resolution, wasm: *const Wasm) ?ObjectDataSegment.Index { |
| 1682 | 1882 | return switch (unpack(r, wasm)) { |
| 1683 | 1883 | .unresolved => unreachable, |
| 1684 | 1884 | .object => |i| i.ptr(wasm).segment, |
| 1685 | 1885 | .__zig_error_names, |
| 1686 | 1886 | .__zig_error_name_table, |
| 1887 | .__zig_tag_names, | |
| 1888 | .__zig_tag_name_table, | |
| 1687 | 1889 | .__heap_base, |
| 1688 | 1890 | .__heap_end, |
| 1689 | 1891 | .uav_exe, |
| ... | ... | @@ -1706,12 +1908,107 @@ pub const ObjectDataImport = extern struct { |
| 1706 | 1908 | }, |
| 1707 | 1909 | .__zig_error_names => .{ .segment = .__zig_error_names, .offset = 0 }, |
| 1708 | 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 | 1913 | .__heap_base => .{ .segment = .__heap_base, .offset = 0 }, |
| 1710 | 1914 | .__heap_end => .{ .segment = .__heap_end, .offset = 0 }, |
| 1711 | .uav_exe => @panic("TODO"), | |
| 1712 | .uav_obj => @panic("TODO"), | |
| 1713 | .nav_exe => @panic("TODO"), | |
| 1714 | .nav_obj => @panic("TODO"), | |
| 1915 | .uav_exe => |i| .{ .segment = .pack(wasm, .{ .uav_exe = i }), .offset = 0 }, | |
| 1916 | .uav_obj => |i| .{ .segment = .pack(wasm, .{ .uav_obj = i }), .offset = 0 }, | |
| 1917 | .nav_exe => |i| .{ .segment = .pack(wasm, .{ .nav_exe = i }), .offset = 0 }, | |
| 1918 | .nav_obj => |i| .{ .segment = .pack(wasm, .{ .nav_obj = i }), .offset = 0 }, | |
| 1919 | }; | |
| 1920 | } | |
| 1921 | ||
| 1922 | pub fn flags(r: Resolution, wasm: *const Wasm) SymbolFlags { | |
| 1923 | return switch (unpack(r, wasm)) { | |
| 1924 | .unresolved => unreachable, | |
| 1925 | .__zig_error_names, | |
| 1926 | .__zig_error_name_table, | |
| 1927 | .__zig_tag_names, | |
| 1928 | .__zig_tag_name_table, | |
| 1929 | => .{ .binding = .local }, | |
| 1930 | .__heap_base, | |
| 1931 | .__heap_end, | |
| 1932 | => unreachable, | |
| 1933 | .object => |i| i.ptr(wasm).flags, | |
| 1934 | inline .nav_exe, .nav_obj => |i| { | |
| 1935 | const zcu = wasm.base.comp.zcu.?; | |
| 1936 | const ip = &zcu.intern_pool; | |
| 1937 | const nav = ip.getNav(i.key(wasm).*); | |
| 1938 | if (nav.getExtern(ip)) |ext| { | |
| 1939 | const name_slice = ext.name.toSlice(ip); | |
| 1940 | const name_string = wasm.getExistingString(name_slice).?; | |
| 1941 | return .{ | |
| 1942 | .binding = switch (ext.linkage) { | |
| 1943 | .internal => .local, | |
| 1944 | .strong => .strong, | |
| 1945 | .weak => .weak, | |
| 1946 | .link_once => @panic("TODO: COMDAT"), | |
| 1947 | }, | |
| 1948 | .visibility_hidden = switch (ext.visibility) { | |
| 1949 | .default => false, | |
| 1950 | .hidden => true, | |
| 1951 | .protected => false, | |
| 1952 | }, | |
| 1953 | .undefined = false, | |
| 1954 | .exported = wasm.missing_exports.contains(name_string), | |
| 1955 | .explicit_name = false, | |
| 1956 | .no_strip = false, | |
| 1957 | .tls = ext.is_threadlocal, | |
| 1958 | .absolute = false, | |
| 1959 | }; | |
| 1960 | } else { | |
| 1961 | return .{ | |
| 1962 | .binding = .local, | |
| 1963 | .tls = nav.resolved.?.@"threadlocal", | |
| 1964 | }; | |
| 1965 | } | |
| 1966 | }, | |
| 1967 | .uav_exe, .uav_obj => .{ .binding = .local }, | |
| 1968 | }; | |
| 1969 | } | |
| 1970 | ||
| 1971 | pub fn name(r: Resolution, wasm: *const Wasm, buf: []u8) []const u8 { | |
| 1972 | return switch (unpack(r, wasm)) { | |
| 1973 | .unresolved => unreachable, | |
| 1974 | .object => |i| i.ptr(wasm).name.slice(wasm), | |
| 1975 | .__zig_error_names => @tagName(.__zig_error_names), | |
| 1976 | .__zig_error_name_table => @tagName(.__zig_error_name_table), | |
| 1977 | .__zig_tag_names => @tagName(.__zig_tag_names), | |
| 1978 | .__zig_tag_name_table => @tagName(.__zig_tag_name_table), | |
| 1979 | .__heap_base => @tagName(.__heap_base), | |
| 1980 | .__heap_end => @tagName(.__heap_end), | |
| 1981 | inline .uav_exe, .uav_obj => |i| std.fmt.bufPrint( | |
| 1982 | buf, | |
| 1983 | "__anon_{d}", | |
| 1984 | .{@backingInt(i.key(wasm).*)}, | |
| 1985 | ) catch unreachable, | |
| 1986 | inline .nav_exe, .nav_obj => |i| i.name(wasm), | |
| 1987 | }; | |
| 1988 | } | |
| 1989 | ||
| 1990 | pub fn size(r: Resolution, wasm: *const Wasm) u32 { | |
| 1991 | return switch (unpack(r, wasm)) { | |
| 1992 | .unresolved => unreachable, | |
| 1993 | .__zig_error_names => @intCast(wasm.error_name_bytes.items.len), | |
| 1994 | .__zig_error_name_table => { | |
| 1995 | const comp = wasm.base.comp; | |
| 1996 | const zcu = comp.zcu.?; | |
| 1997 | const errors_len = wasm.error_name_offs.items.len; | |
| 1998 | const elem_size = Zcu.Type.slice_const_u8_sentinel_0.abiSize(zcu); | |
| 1999 | return @intCast(errors_len * elem_size); | |
| 2000 | }, | |
| 2001 | .__zig_tag_names => @intCast(wasm.tag_name_bytes.items.len), | |
| 2002 | .__zig_tag_name_table => { | |
| 2003 | const comp = wasm.base.comp; | |
| 2004 | const zcu = comp.zcu.?; | |
| 2005 | const table_len = wasm.tag_name_offs.items.len; | |
| 2006 | const elem_size = Zcu.Type.slice_const_u8_sentinel_0.abiSize(zcu); | |
| 2007 | return @intCast(table_len * elem_size); | |
| 2008 | }, | |
| 2009 | .__heap_base, .__heap_end => wasm.pointerSize(), | |
| 2010 | .object => |i| i.ptr(wasm).size, | |
| 2011 | inline .uav_exe, .uav_obj, .nav_exe, .nav_obj => |i| i.value(wasm).code.len, | |
| 1715 | 2012 | }; |
| 1716 | 2013 | } |
| 1717 | 2014 | }; |
| ... | ... | @@ -1910,6 +2207,38 @@ pub const DataSegmentId = enum(u32) { |
| 1910 | 2207 | }; |
| 1911 | 2208 | } |
| 1912 | 2209 | |
| 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 | 2242 | pub fn isBss(id: DataSegmentId, wasm: *const Wasm) bool { |
| 1914 | 2243 | return id.category(wasm) == .zero; |
| 1915 | 2244 | } |
| ... | ... | @@ -2181,6 +2510,7 @@ const PreloadedStrings = struct { |
| 2181 | 2510 | _initialize: String, |
| 2182 | 2511 | _start: String, |
| 2183 | 2512 | memory: String, |
| 2513 | env: String, | |
| 2184 | 2514 | }; |
| 2185 | 2515 | |
| 2186 | 2516 | /// Index into string_bytes |
| ... | ... | @@ -2209,14 +2539,14 @@ pub const String = enum(u32) { |
| 2209 | 2539 | } |
| 2210 | 2540 | |
| 2211 | 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 | 2543 | return std.hash_map.hashString(adapted_key); |
| 2214 | 2544 | } |
| 2215 | 2545 | }; |
| 2216 | 2546 | |
| 2217 | 2547 | pub fn slice(index: String, wasm: *const Wasm) [:0]const u8 { |
| 2218 | 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 | } |
| 2221 | 2551 | |
| 2222 | 2552 | pub fn toOptional(i: String) OptionalString { |
| ... | ... | @@ -2262,6 +2592,34 @@ pub const ZcuImportIndex = enum(u32) { |
| 2262 | 2592 | return &wasm.imports.keys()[@backingInt(index)]; |
| 2263 | 2593 | } |
| 2264 | 2594 | |
| 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 | 2623 | pub fn importName(index: ZcuImportIndex, wasm: *const Wasm) String { |
| 2266 | 2624 | const zcu = wasm.base.comp.zcu.?; |
| 2267 | 2625 | const ip = &zcu.intern_pool; |
| ... | ... | @@ -2348,6 +2706,13 @@ pub const FunctionImportId = enum(u32) { |
| 2348 | 2706 | } |
| 2349 | 2707 | } |
| 2350 | 2708 | |
| 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 | 2716 | pub fn importName(id: FunctionImportId, wasm: *const Wasm) String { |
| 2352 | 2717 | return switch (unpack(id, wasm)) { |
| 2353 | 2718 | inline .object_function_import, .zcu_import => |i| i.importName(wasm), |
| ... | ... | @@ -2385,38 +2750,61 @@ pub const FunctionImportId = enum(u32) { |
| 2385 | 2750 | } |
| 2386 | 2751 | }; |
| 2387 | 2752 | |
| 2388 | /// 0. Index into `object_global_imports`. | |
| 2389 | /// 1. Index into `imports`. | |
| 2753 | /// 0. `__stack_pointer`. | |
| 2754 | /// 1. Index into `object_global_imports`. | |
| 2755 | /// 2. Index into `imports`. | |
| 2390 | 2756 | pub const GlobalImportId = enum(u32) { |
| 2757 | __stack_pointer, | |
| 2391 | 2758 | _, |
| 2392 | 2759 | |
| 2393 | 2760 | pub const Unpacked = union(enum) { |
| 2761 | __stack_pointer, | |
| 2394 | 2762 | object_global_import: GlobalImport.Index, |
| 2395 | 2763 | zcu_import: ZcuImportIndex, |
| 2396 | 2764 | }; |
| 2397 | 2765 | |
| 2398 | 2766 | pub fn pack(unpacked: Unpacked, wasm: *const Wasm) GlobalImportId { |
| 2399 | 2767 | return switch (unpacked) { |
| 2400 | .object_global_import => |i| @fromBackingInt(@intCast(@backingInt(i))), | |
| 2401 | .zcu_import => |i| @fromBackingInt(@intCast(@backingInt(i) + wasm.object_global_imports.entries.len)), | |
| 2768 | .__stack_pointer => .__stack_pointer, | |
| 2769 | .object_global_import => |i| @fromBackingInt(@intCast(@backingInt(i) + 1)), | |
| 2770 | .zcu_import => |i| @fromBackingInt(@intCast(@backingInt(i) + wasm.object_global_imports.entries.len + 1)), | |
| 2402 | 2771 | }; |
| 2403 | 2772 | } |
| 2404 | 2773 | |
| 2405 | 2774 | pub fn unpack(id: GlobalImportId, wasm: *const Wasm) Unpacked { |
| 2406 | const i = @backingInt(id); | |
| 2407 | if (i < wasm.object_global_imports.entries.len) return .{ .object_global_import = @fromBackingInt(@intCast(i)) }; | |
| 2408 | const zcu_import_i = i - wasm.object_global_imports.entries.len; | |
| 2409 | return .{ .zcu_import = @fromBackingInt(@intCast(zcu_import_i)) }; | |
| 2775 | return switch (id) { | |
| 2776 | .__stack_pointer => .__stack_pointer, | |
| 2777 | _ => { | |
| 2778 | const i = @backingInt(id) - 1; | |
| 2779 | if (i < wasm.object_global_imports.entries.len) { | |
| 2780 | return .{ .object_global_import = @fromBackingInt(@intCast(i)) }; | |
| 2781 | } | |
| 2782 | const zcu_import_i = i - wasm.object_global_imports.entries.len; | |
| 2783 | return .{ .zcu_import = @fromBackingInt(@intCast(zcu_import_i)) }; | |
| 2784 | }, | |
| 2785 | }; | |
| 2410 | 2786 | } |
| 2411 | 2787 | |
| 2412 | 2788 | pub fn fromObject(object_global_import: GlobalImport.Index, wasm: *const Wasm) GlobalImportId { |
| 2413 | 2789 | return pack(.{ .object_global_import = object_global_import }, wasm); |
| 2414 | 2790 | } |
| 2415 | 2791 | |
| 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 | 2803 | /// This function is allowed O(N) lookup because it is only called during |
| 2417 | 2804 | /// diagnostic generation. |
| 2418 | 2805 | pub fn sourceLocation(id: GlobalImportId, wasm: *const Wasm) SourceLocation { |
| 2419 | 2806 | switch (id.unpack(wasm)) { |
| 2807 | .__stack_pointer => return .zig_object_nofile, | |
| 2420 | 2808 | .object_global_import => |obj_global_index| { |
| 2421 | 2809 | // TODO binary search |
| 2422 | 2810 | for (wasm.objects.items, 0..) |o, i| { |
| ... | ... | @@ -2433,18 +2821,28 @@ pub const GlobalImportId = enum(u32) { |
| 2433 | 2821 | |
| 2434 | 2822 | pub fn importName(id: GlobalImportId, wasm: *const Wasm) String { |
| 2435 | 2823 | return switch (unpack(id, wasm)) { |
| 2824 | .__stack_pointer => wasm.preloaded_strings.__stack_pointer, | |
| 2436 | 2825 | inline .object_global_import, .zcu_import => |i| i.importName(wasm), |
| 2437 | 2826 | }; |
| 2438 | 2827 | } |
| 2439 | 2828 | |
| 2440 | 2829 | pub fn moduleName(id: GlobalImportId, wasm: *const Wasm) OptionalString { |
| 2441 | 2830 | return switch (unpack(id, wasm)) { |
| 2831 | .__stack_pointer => wasm.preloaded_strings.env.toOptional(), | |
| 2442 | 2832 | inline .object_global_import, .zcu_import => |i| i.moduleName(wasm), |
| 2443 | 2833 | }; |
| 2444 | 2834 | } |
| 2445 | 2835 | |
| 2446 | 2836 | pub fn globalType(id: GlobalImportId, wasm: *Wasm) ObjectGlobal.Type { |
| 2447 | 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 | 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 | 2880 | return pack(.{ .object_data_import = object_data_import }, wasm); |
| 2483 | 2881 | } |
| 2484 | 2882 | |
| 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 | 2890 | pub fn sourceLocation(id: DataImportId, wasm: *const Wasm) SourceLocation { |
| 2486 | 2891 | switch (id.unpack(wasm)) { |
| 2487 | 2892 | .object_data_import => |obj_data_index| { |
| ... | ... | @@ -2499,33 +2904,42 @@ pub const DataImportId = enum(u32) { |
| 2499 | 2904 | } |
| 2500 | 2905 | }; |
| 2501 | 2906 | |
| 2502 | /// Index into `Wasm.symbol_table`. | |
| 2503 | pub 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 | ||
| 2511 | pub const OutReloc = struct { | |
| 2907 | pub const ZcuRelocation = struct { | |
| 2512 | 2908 | tag: Object.RelocationType, |
| 2513 | 2909 | offset: u32, |
| 2514 | 2910 | pointee: Pointee, |
| 2515 | 2911 | addend: i32, |
| 2516 | 2912 | |
| 2517 | pub const Pointee = union { | |
| 2518 | symbol_index: SymbolTableIndex, | |
| 2913 | pub const Pointee = union(enum) { | |
| 2914 | function_nav: InternPool.Nav.Index, | |
| 2915 | function_name: String, | |
| 2916 | tag_function: InternPool.Index, | |
| 2917 | data_uav: InternPool.Index, | |
| 2918 | data_nav: InternPool.Nav.Index, | |
| 2919 | data_resolution: ObjectDataImport.Resolution, | |
| 2920 | stack_pointer, | |
| 2519 | 2921 | type_index: FunctionType.Index, |
| 2520 | 2922 | }; |
| 2521 | 2923 | |
| 2522 | 2924 | pub const Slice = extern struct { |
| 2523 | /// Index into `out_relocs`. | |
| 2925 | /// Index into `zcu_relocations`. | |
| 2524 | 2926 | off: u32, |
| 2525 | 2927 | len: u32, |
| 2526 | 2928 | |
| 2527 | pub fn slice(s: Slice, wasm: *const Wasm) []OutReloc { | |
| 2528 | return wasm.relocations.items[s.off..][0..s.len]; | |
| 2929 | pub fn tags(s: Slice, wasm: *const Wasm) []const Object.RelocationType { | |
| 2930 | return wasm.zcu_relocations.items(.tag)[s.off..][0..s.len]; | |
| 2931 | } | |
| 2932 | ||
| 2933 | pub fn offsets(s: Slice, wasm: *const Wasm) []const u32 { | |
| 2934 | return wasm.zcu_relocations.items(.offset)[s.off..][0..s.len]; | |
| 2935 | } | |
| 2936 | ||
| 2937 | pub fn pointees(s: Slice, wasm: *const Wasm) []const Pointee { | |
| 2938 | return wasm.zcu_relocations.items(.pointee)[s.off..][0..s.len]; | |
| 2939 | } | |
| 2940 | ||
| 2941 | pub fn addends(s: Slice, wasm: *const Wasm) []const i32 { | |
| 2942 | return wasm.zcu_relocations.items(.addend)[s.off..][0..s.len]; | |
| 2529 | 2943 | } |
| 2530 | 2944 | }; |
| 2531 | 2945 | }; |
| ... | ... | @@ -3137,9 +3551,9 @@ pub fn deinit(wasm: *Wasm) void { |
| 3137 | 3551 | wasm.table_imports.deinit(gpa); |
| 3138 | 3552 | wasm.tables.deinit(gpa); |
| 3139 | 3553 | wasm.data_imports.deinit(gpa); |
| 3554 | wasm.datas.deinit(gpa); | |
| 3140 | 3555 | wasm.data_segments.deinit(gpa); |
| 3141 | wasm.symbol_table.deinit(gpa); | |
| 3142 | wasm.out_relocs.deinit(gpa); | |
| 3556 | wasm.zcu_relocations.deinit(gpa); | |
| 3143 | 3557 | wasm.uav_fixups.deinit(gpa); |
| 3144 | 3558 | wasm.nav_fixups.deinit(gpa); |
| 3145 | 3559 | wasm.func_table_fixups.deinit(gpa); |
| ... | ... | @@ -3351,6 +3765,25 @@ pub fn updateExports( |
| 3351 | 3765 | const zcu = pt.zcu; |
| 3352 | 3766 | const gpa = zcu.gpa; |
| 3353 | 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 | 3787 | for (export_indices) |export_idx| { |
| 3355 | 3788 | const exp = export_idx.ptr(zcu); |
| 3356 | 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 | 3876 | // Zig always depends on a stack pointer global. |
| 3444 | 3877 | // If emitting an object, it's an import. Otherwise, the linker synthesizes it. |
| 3445 | 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 | 3884 | } else { |
| 3448 | 3885 | try wasm.globals.put(gpa, .__stack_pointer, {}); |
| 3449 | 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 | 3890 | // These loops do both recursive marking of alive symbols well as checking for undefined symbols. |
| 3454 | 3891 | // At the end, output functions and globals will be populated. |
| 3455 | 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 | 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 | 3904 | wasm.functions_end_prelink = @intCast(wasm.functions.entries.len); |
| 3468 | 3905 | |
| 3469 | 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 | 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 | 3912 | wasm.global_exports_len = @intCast(wasm.global_exports.items.len); |
| 3476 | 3913 | |
| 3477 | 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 | 3916 | try markTableImport(wasm, name, import, @fromBackingInt(@intCast(i))); |
| 3480 | 3917 | } |
| 3481 | 3918 | } |
| 3482 | 3919 | |
| 3483 | 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 | 3922 | try markDataImport(wasm, name, import, @fromBackingInt(@intCast(i))); |
| 3486 | 3923 | } |
| 3487 | 3924 | } |
| ... | ... | @@ -3512,18 +3949,23 @@ pub fn markFunctionImport( |
| 3512 | 3949 | |
| 3513 | 3950 | const comp = wasm.base.comp; |
| 3514 | 3951 | const gpa = comp.gpa; |
| 3952 | const is_obj = comp.config.output_mode == .Obj; | |
| 3515 | 3953 | |
| 3516 | 3954 | try wasm.functions.ensureUnusedCapacity(gpa, 1); |
| 3517 | 3955 | |
| 3518 | 3956 | if (import.resolution == .unresolved) { |
| 3519 | if (name == wasm.preloaded_strings.__wasm_init_memory) { | |
| 3520 | try wasm.resolveFunctionSynthetic(import, .__wasm_init_memory, &.{}, &.{}); | |
| 3521 | } else if (name == wasm.preloaded_strings.__wasm_apply_global_tls_relocs) { | |
| 3522 | try wasm.resolveFunctionSynthetic(import, .__wasm_apply_global_tls_relocs, &.{}, &.{}); | |
| 3523 | } else if (name == wasm.preloaded_strings.__wasm_call_ctors) { | |
| 3524 | try wasm.resolveFunctionSynthetic(import, .__wasm_call_ctors, &.{}, &.{}); | |
| 3525 | } else if (name == wasm.preloaded_strings.__wasm_init_tls) { | |
| 3526 | try wasm.resolveFunctionSynthetic(import, .__wasm_init_tls, &.{.i32}, &.{}); | |
| 3957 | if (!is_obj) { | |
| 3958 | if (name == wasm.preloaded_strings.__wasm_init_memory) { | |
| 3959 | try wasm.resolveFunctionSynthetic(import, .__wasm_init_memory, &.{}, &.{}); | |
| 3960 | } else if (name == wasm.preloaded_strings.__wasm_apply_global_tls_relocs) { | |
| 3961 | try wasm.resolveFunctionSynthetic(import, .__wasm_apply_global_tls_relocs, &.{}, &.{}); | |
| 3962 | } else if (name == wasm.preloaded_strings.__wasm_call_ctors) { | |
| 3963 | try wasm.resolveFunctionSynthetic(import, .__wasm_call_ctors, &.{}, &.{}); | |
| 3964 | } else if (name == wasm.preloaded_strings.__wasm_init_tls) { | |
| 3965 | try wasm.resolveFunctionSynthetic(import, .__wasm_init_tls, &.{.i32}, &.{}); | |
| 3966 | } else { | |
| 3967 | try wasm.function_imports.put(gpa, name, .fromObject(func_index, wasm)); | |
| 3968 | } | |
| 3527 | 3969 | } else { |
| 3528 | 3970 | try wasm.function_imports.put(gpa, name, .fromObject(func_index, wasm)); |
| 3529 | 3971 | } |
| ... | ... | @@ -3576,28 +4018,33 @@ fn markGlobalImport( |
| 3576 | 4018 | |
| 3577 | 4019 | const comp = wasm.base.comp; |
| 3578 | 4020 | const gpa = comp.gpa; |
| 4021 | const is_obj = comp.config.output_mode == .Obj; | |
| 3579 | 4022 | |
| 3580 | 4023 | try wasm.globals.ensureUnusedCapacity(gpa, 1); |
| 3581 | 4024 | |
| 3582 | 4025 | if (import.resolution == .unresolved) { |
| 3583 | if (name == wasm.preloaded_strings.__heap_base) { | |
| 3584 | import.resolution = .__heap_base; | |
| 3585 | wasm.globals.putAssumeCapacity(.__heap_base, {}); | |
| 3586 | } else if (name == wasm.preloaded_strings.__heap_end) { | |
| 3587 | import.resolution = .__heap_end; | |
| 3588 | wasm.globals.putAssumeCapacity(.__heap_end, {}); | |
| 3589 | } else if (name == wasm.preloaded_strings.__stack_pointer) { | |
| 3590 | import.resolution = .__stack_pointer; | |
| 3591 | wasm.globals.putAssumeCapacity(.__stack_pointer, {}); | |
| 3592 | } else if (name == wasm.preloaded_strings.__tls_align) { | |
| 3593 | import.resolution = .__tls_align; | |
| 3594 | wasm.globals.putAssumeCapacity(.__tls_align, {}); | |
| 3595 | } else if (name == wasm.preloaded_strings.__tls_base) { | |
| 3596 | import.resolution = .__tls_base; | |
| 3597 | wasm.globals.putAssumeCapacity(.__tls_base, {}); | |
| 3598 | } else if (name == wasm.preloaded_strings.__tls_size) { | |
| 3599 | import.resolution = .__tls_size; | |
| 3600 | wasm.globals.putAssumeCapacity(.__tls_size, {}); | |
| 4026 | if (!is_obj) { | |
| 4027 | if (name == wasm.preloaded_strings.__heap_base) { | |
| 4028 | import.resolution = .__heap_base; | |
| 4029 | wasm.globals.putAssumeCapacity(.__heap_base, {}); | |
| 4030 | } else if (name == wasm.preloaded_strings.__heap_end) { | |
| 4031 | import.resolution = .__heap_end; | |
| 4032 | wasm.globals.putAssumeCapacity(.__heap_end, {}); | |
| 4033 | } else if (name == wasm.preloaded_strings.__stack_pointer) { | |
| 4034 | import.resolution = .__stack_pointer; | |
| 4035 | wasm.globals.putAssumeCapacity(.__stack_pointer, {}); | |
| 4036 | } else if (name == wasm.preloaded_strings.__tls_align) { | |
| 4037 | import.resolution = .__tls_align; | |
| 4038 | wasm.globals.putAssumeCapacity(.__tls_align, {}); | |
| 4039 | } else if (name == wasm.preloaded_strings.__tls_base) { | |
| 4040 | import.resolution = .__tls_base; | |
| 4041 | wasm.globals.putAssumeCapacity(.__tls_base, {}); | |
| 4042 | } else if (name == wasm.preloaded_strings.__tls_size) { | |
| 4043 | import.resolution = .__tls_size; | |
| 4044 | wasm.globals.putAssumeCapacity(.__tls_size, {}); | |
| 4045 | } else { | |
| 4046 | try wasm.global_imports.put(gpa, name, .fromObject(global_index, wasm)); | |
| 4047 | } | |
| 3601 | 4048 | } else { |
| 3602 | 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 | 4072 | try wasm.markRelocations(global.relocations(wasm)); |
| 3626 | 4073 | } |
| 3627 | 4074 | |
| 3628 | fn markTableImport( | |
| 4075 | pub fn markTableImport( | |
| 3629 | 4076 | wasm: *Wasm, |
| 3630 | 4077 | name: String, |
| 3631 | 4078 | import: *TableImport, |
| ... | ... | @@ -3636,13 +4083,18 @@ fn markTableImport( |
| 3636 | 4083 | |
| 3637 | 4084 | const comp = wasm.base.comp; |
| 3638 | 4085 | const gpa = comp.gpa; |
| 4086 | const is_obj = comp.config.output_mode == .Obj; | |
| 3639 | 4087 | |
| 3640 | 4088 | try wasm.tables.ensureUnusedCapacity(gpa, 1); |
| 3641 | 4089 | |
| 3642 | 4090 | if (import.resolution == .unresolved) { |
| 3643 | if (name == wasm.preloaded_strings.__indirect_function_table) { | |
| 3644 | import.resolution = .__indirect_function_table; | |
| 3645 | wasm.tables.putAssumeCapacity(.__indirect_function_table, {}); | |
| 4091 | if (!is_obj) { | |
| 4092 | if (name == wasm.preloaded_strings.__indirect_function_table) { | |
| 4093 | import.resolution = .__indirect_function_table; | |
| 4094 | wasm.tables.putAssumeCapacity(.__indirect_function_table, {}); | |
| 4095 | } else { | |
| 4096 | try wasm.table_imports.put(gpa, name, table_index); | |
| 4097 | } | |
| 3646 | 4098 | } else { |
| 3647 | 4099 | try wasm.table_imports.put(gpa, name, table_index); |
| 3648 | 4100 | } |
| ... | ... | @@ -3676,22 +4128,38 @@ pub fn markDataImport( |
| 3676 | 4128 | |
| 3677 | 4129 | const comp = wasm.base.comp; |
| 3678 | 4130 | const gpa = comp.gpa; |
| 4131 | const is_obj = comp.config.output_mode == .Obj; | |
| 4132 | ||
| 4133 | try wasm.data_segments.ensureUnusedCapacity(gpa, 1); | |
| 3679 | 4134 | |
| 3680 | 4135 | if (import.resolution == .unresolved) { |
| 3681 | if (name == wasm.preloaded_strings.__heap_base) { | |
| 3682 | import.resolution = .__heap_base; | |
| 3683 | wasm.data_segments.putAssumeCapacity(.__heap_base, {}); | |
| 3684 | } else if (name == wasm.preloaded_strings.__heap_end) { | |
| 3685 | import.resolution = .__heap_end; | |
| 3686 | wasm.data_segments.putAssumeCapacity(.__heap_end, {}); | |
| 4136 | if (!is_obj) { | |
| 4137 | if (name == wasm.preloaded_strings.__heap_base) { | |
| 4138 | import.resolution = .__heap_base; | |
| 4139 | wasm.data_segments.putAssumeCapacity(.__heap_base, {}); | |
| 4140 | } else if (name == wasm.preloaded_strings.__heap_end) { | |
| 4141 | import.resolution = .__heap_end; | |
| 4142 | wasm.data_segments.putAssumeCapacity(.__heap_end, {}); | |
| 4143 | } else { | |
| 4144 | try wasm.data_imports.put(gpa, name, .fromObject(data_index, wasm)); | |
| 4145 | } | |
| 3687 | 4146 | } else { |
| 3688 | 4147 | try wasm.data_imports.put(gpa, name, .fromObject(data_index, wasm)); |
| 3689 | 4148 | } |
| 3690 | } else if (import.resolution.objectDataSegment(wasm)) |segment_index| { | |
| 3691 | try markDataSegment(wasm, segment_index); | |
| 4149 | } else switch (import.resolution.unpack(wasm)) { | |
| 4150 | .object => |object_data_index| try markData(wasm, object_data_index), | |
| 4151 | else => {}, | |
| 3692 | 4152 | } |
| 3693 | 4153 | } |
| 3694 | 4154 | |
| 4155 | fn 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 | ||
| 3695 | 4163 | fn markRelocations(wasm: *Wasm, relocs: ObjectRelocation.IterableSlice) link.Error!void { |
| 3696 | 4164 | const gpa = wasm.base.comp.gpa; |
| 3697 | 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 | 4250 | .memory_addr_tls_sleb, |
| 3783 | 4251 | .memory_addr_locrel_i32, |
| 3784 | 4252 | .memory_addr_tls_sleb64, |
| 3785 | => try markDataSegment(wasm, pointee.data.ptr(wasm).segment), | |
| 4253 | => try markData(wasm, pointee.data), | |
| 3786 | 4254 | |
| 3787 | 4255 | .type_index_leb => continue, |
| 3788 | 4256 | } |
| ... | ... | @@ -3829,7 +4297,13 @@ pub fn flush( |
| 3829 | 4297 | const hidden_function_exports_end_zcu: u32 = @intCast(wasm.hidden_function_exports.entries.len); |
| 3830 | 4298 | defer wasm.hidden_function_exports.shrinkRetainingCapacity(hidden_function_exports_end_zcu); |
| 3831 | 4299 | |
| 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 | 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 | 4307 | try wasm.flush_buffer.missing_exports.reinit(gpa, wasm.missing_exports.keys(), &.{}); |
| 3834 | 4308 | try wasm.flush_buffer.function_imports.reinit(gpa, wasm.function_imports.keys(), wasm.function_imports.values()); |
| 3835 | 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 | 4332 | } |
| 3859 | 4333 | |
| 3860 | 4334 | pub 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 | 4336 | wasm.string_bytes_lock.lock(); |
| 3863 | 4337 | defer wasm.string_bytes_lock.unlock(); |
| 3864 | 4338 | const gpa = wasm.base.comp.gpa; |
| ... | ... | @@ -3889,7 +4363,7 @@ pub fn internStringFmt(wasm: *Wasm, comptime format: []const u8, args: anytype) |
| 3889 | 4363 | } |
| 3890 | 4364 | |
| 3891 | 4365 | pub 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 | 4367 | return wasm.string_table.getKeyAdapted(bytes, @as(String.TableIndexAdapter, .{ |
| 3894 | 4368 | .bytes = wasm.string_bytes.items, |
| 3895 | 4369 | })); |
| ... | ... | @@ -3953,6 +4427,255 @@ pub fn getExistingFunctionType( |
| 3953 | 4427 | }); |
| 3954 | 4428 | } |
| 3955 | 4429 | |
| 4430 | fn 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 | ||
| 4439 | pub 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 | ||
| 3956 | 4679 | pub fn addExpr(wasm: *Wasm, bytes: []const u8) Allocator.Error!Expr { |
| 3957 | 4680 | const gpa = wasm.base.comp.gpa; |
| 3958 | 4681 | // 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 | 4695 | }; |
| 3973 | 4696 | } |
| 3974 | 4697 | |
| 3975 | pub fn uavSymbolIndex(wasm: *Wasm, ip_index: InternPool.Index) Allocator.Error!SymbolTableIndex { | |
| 3976 | const comp = wasm.base.comp; | |
| 3977 | assert(comp.config.output_mode == .Obj); | |
| 3978 | const gpa = comp.gpa; | |
| 3979 | const name = try wasm.internStringFmt("__anon_{d}", .{@backingInt(ip_index)}); | |
| 3980 | const gop = try wasm.symbol_table.getOrPut(gpa, name); | |
| 3981 | gop.value_ptr.* = {}; | |
| 3982 | return @fromBackingInt(@intCast(gop.index)); | |
| 3983 | } | |
| 3984 | ||
| 3985 | pub fn navSymbolIndex(wasm: *Wasm, nav_index: InternPool.Nav.Index) Allocator.Error!SymbolTableIndex { | |
| 4698 | pub fn addNavReloc( | |
| 4699 | wasm: *Wasm, | |
| 4700 | reloc_offset: usize, | |
| 4701 | nav_index: InternPool.Nav.Index, | |
| 4702 | nav_ty: Zcu.Type, | |
| 4703 | addend: u32, | |
| 4704 | ) !void { | |
| 3986 | 4705 | const comp = wasm.base.comp; |
| 3987 | assert(comp.config.output_mode == .Obj); | |
| 3988 | 4706 | const zcu = comp.zcu.?; |
| 3989 | 4707 | const ip = &zcu.intern_pool; |
| 3990 | 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 | ||
| 3998 | pub 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 | ||
| 4007 | pub 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 | } | |
| 4015 | 4709 | |
| 4016 | pub fn tagTableIndexSymbolIndex(wasm: *Wasm, ip_index: InternPool.Index) Allocator.Error!SymbolTableIndex { | |
| 4017 | const comp = wasm.base.comp; | |
| 4018 | assert(comp.config.output_mode == .Obj); | |
| 4019 | const gpa = comp.gpa; | |
| 4020 | const name = try wasm.internStringFmt("__zig_tag_name_{d}", .{ip_index}); | |
| 4021 | const gop = try wasm.symbol_table.getOrPut(gpa, name); | |
| 4022 | gop.value_ptr.* = {}; | |
| 4023 | return @fromBackingInt(@intCast(gop.index)); | |
| 4024 | } | |
| 4710 | const is_obj = comp.config.output_mode == .Obj; | |
| 4025 | 4711 | |
| 4026 | pub fn symbolNameIndex(wasm: *Wasm, name: String) Allocator.Error!SymbolTableIndex { | |
| 4027 | const comp = wasm.base.comp; | |
| 4028 | assert(comp.config.output_mode == .Obj); | |
| 4029 | const gpa = comp.gpa; | |
| 4030 | const gop = try wasm.symbol_table.getOrPut(gpa, name); | |
| 4031 | gop.value_ptr.* = {}; | |
| 4032 | return @fromBackingInt(@intCast(gop.index)); | |
| 4712 | if (nav_ty.zigTypeTag(zcu) == .@"fn") { | |
| 4713 | const gop = try wasm.zcu_indirect_function_set.getOrPut(gpa, nav_index); | |
| 4714 | if (!gop.found_existing) gop.value_ptr.* = {}; | |
| 4715 | if (is_obj) { | |
| 4716 | assert(addend == 0); | |
| 4717 | try wasm.zcu_relocations.append(gpa, .{ | |
| 4718 | .offset = @intCast(reloc_offset), | |
| 4719 | .pointee = .{ .function_nav = nav_index }, | |
| 4720 | .tag = switch (wasm.pointerSize()) { | |
| 4721 | 4 => .table_index_i32, | |
| 4722 | 8 => .table_index_i64, | |
| 4723 | else => unreachable, | |
| 4724 | }, | |
| 4725 | .addend = 0, | |
| 4726 | }); | |
| 4727 | } else { | |
| 4728 | try wasm.func_table_fixups.append(gpa, .{ | |
| 4729 | .nav_index = nav_index, | |
| 4730 | .offset = @intCast(reloc_offset), | |
| 4731 | }); | |
| 4732 | } | |
| 4733 | } else { | |
| 4734 | if (is_obj) { | |
| 4735 | if (ip.getNav(nav_index).getExtern(ip) == null) _ = try wasm.refNavObj(nav_index); | |
| 4736 | try wasm.zcu_relocations.append(gpa, .{ | |
| 4737 | .offset = @intCast(reloc_offset), | |
| 4738 | .pointee = .{ .data_nav = nav_index }, | |
| 4739 | .tag = switch (wasm.pointerSize()) { | |
| 4740 | 4 => .memory_addr_i32, | |
| 4741 | 8 => .memory_addr_i64, | |
| 4742 | else => unreachable, | |
| 4743 | }, | |
| 4744 | .addend = @intCast(addend), | |
| 4745 | }); | |
| 4746 | } else { | |
| 4747 | try wasm.nav_fixups.ensureUnusedCapacity(gpa, 1); | |
| 4748 | wasm.nav_fixups.appendAssumeCapacity(.{ | |
| 4749 | .nav_index = nav_index, | |
| 4750 | .offset = @intCast(reloc_offset), | |
| 4751 | .addend = addend, | |
| 4752 | }); | |
| 4753 | } | |
| 4754 | } | |
| 4033 | 4755 | } |
| 4034 | 4756 | |
| 4035 | 4757 | pub fn addUavReloc( |
| ... | ... | @@ -4057,12 +4779,12 @@ pub fn addUavReloc( |
| 4057 | 4779 | if (comp.config.output_mode == .Obj) { |
| 4058 | 4780 | const gop = try wasm.uavs_obj.getOrPut(gpa, uav_val); |
| 4059 | 4781 | 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 | 4783 | .offset = @intCast(reloc_offset), |
| 4062 | .pointee = .{ .symbol_index = try wasm.uavSymbolIndex(uav_val) }, | |
| 4784 | .pointee = .{ .data_uav = uav_val }, | |
| 4063 | 4785 | .tag = switch (wasm.pointerSize()) { |
| 4064 | 32 => .memory_addr_i32, | |
| 4065 | 64 => .memory_addr_i64, | |
| 4786 | 4 => .memory_addr_i32, | |
| 4787 | 8 => .memory_addr_i64, | |
| 4066 | 4788 | else => unreachable, |
| 4067 | 4789 | }, |
| 4068 | 4790 | .addend = @intCast(addend), |
| ... | ... | @@ -4085,7 +4807,7 @@ pub fn addUavReloc( |
| 4085 | 4807 | pub fn refNavObj(wasm: *Wasm, nav_index: InternPool.Nav.Index) !NavsObjIndex { |
| 4086 | 4808 | const comp = wasm.base.comp; |
| 4087 | 4809 | const gpa = comp.gpa; |
| 4088 | assert(comp.config.output_mode != .Obj); | |
| 4810 | assert(comp.config.output_mode == .Obj); | |
| 4089 | 4811 | const gop = try wasm.navs_obj.getOrPut(gpa, nav_index); |
| 4090 | 4812 | if (!gop.found_existing) gop.value_ptr.* = .{ |
| 4091 | 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 | 4835 | } |
| 4114 | 4836 | |
| 4115 | 4837 | /// Asserts it is called after `Flush.data_segments` is fully populated and sorted. |
| 4116 | pub fn uavAddr(wasm: *Wasm, ip_index: InternPool.Index) u32 { | |
| 4838 | pub fn uavAddr(wasm: *const Wasm, ip_index: InternPool.Index) u32 { | |
| 4117 | 4839 | assert(wasm.flush_buffer.memory_layout_finished); |
| 4118 | 4840 | const comp = wasm.base.comp; |
| 4119 | 4841 | assert(comp.config.output_mode != .Obj); |
| ... | ... | @@ -4123,7 +4845,7 @@ pub fn uavAddr(wasm: *Wasm, ip_index: InternPool.Index) u32 { |
| 4123 | 4845 | } |
| 4124 | 4846 | |
| 4125 | 4847 | /// Asserts it is called after `Flush.data_segments` is fully populated and sorted. |
| 4126 | pub fn navAddr(wasm: *Wasm, nav_index: InternPool.Nav.Index) u32 { | |
| 4848 | pub fn navAddr(wasm: *const Wasm, nav_index: InternPool.Nav.Index) u32 { | |
| 4127 | 4849 | assert(wasm.flush_buffer.memory_layout_finished); |
| 4128 | 4850 | const comp = wasm.base.comp; |
| 4129 | 4851 | assert(comp.config.output_mode != .Obj); |
| ... | ... | @@ -4139,23 +4861,34 @@ pub fn navAddr(wasm: *Wasm, nav_index: InternPool.Nav.Index) u32 { |
| 4139 | 4861 | .@"extern" => |ext| if (wasm.getExistingString(ext.name.toSlice(ip))) |symbol_name| { |
| 4140 | 4862 | if (wasm.object_data_imports.getPtr(symbol_name)) |import| { |
| 4141 | 4863 | switch (import.resolution.unpack(wasm)) { |
| 4142 | .unresolved => unreachable, | |
| 4864 | .unresolved => {}, | |
| 4143 | 4865 | .object => |object_data_index| { |
| 4144 | 4866 | const object_data = object_data_index.ptr(wasm); |
| 4145 | 4867 | const ds_id: DataSegmentId = .fromObjectDataSegment(wasm, object_data.segment); |
| 4146 | 4868 | const segment_base_addr = wasm.flush_buffer.data_segments.get(ds_id).?; |
| 4147 | 4869 | return segment_base_addr + object_data.offset; |
| 4148 | 4870 | }, |
| 4149 | .__zig_error_names => @panic("TODO"), | |
| 4150 | .__zig_error_name_table => @panic("TODO"), | |
| 4151 | .__heap_base => @panic("TODO"), | |
| 4152 | .__heap_end => @panic("TODO"), | |
| 4153 | .uav_exe => @panic("TODO"), | |
| 4154 | .uav_obj => @panic("TODO"), | |
| 4155 | .nav_exe => @panic("TODO"), | |
| 4156 | .nav_obj => @panic("TODO"), | |
| 4871 | .__heap_base, | |
| 4872 | .__heap_end, | |
| 4873 | .uav_exe, | |
| 4874 | .nav_exe, | |
| 4875 | => { | |
| 4876 | const data_loc = import.resolution.dataLoc(wasm); | |
| 4877 | return wasm.flush_buffer.data_segments.get(data_loc.segment).? + data_loc.offset; | |
| 4878 | }, | |
| 4879 | .__zig_error_names, | |
| 4880 | .__zig_error_name_table, | |
| 4881 | .__zig_tag_names, | |
| 4882 | .__zig_tag_name_table, | |
| 4883 | .uav_obj, | |
| 4884 | .nav_obj, | |
| 4885 | => unreachable, | |
| 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 | 4893 | else => {}, |
| 4161 | 4894 | } |
| ... | ... | @@ -4177,8 +4910,12 @@ pub fn tagIndexTableAddr(wasm: *Wasm, ip_index: InternPool.Index) u32 { |
| 4177 | 4910 | assert(comp.config.output_mode != .Obj); |
| 4178 | 4911 | const f = &wasm.flush_buffer; |
| 4179 | 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).?; | |
| 4181 | return table_base_addr + table_index * 8; | |
| 4913 | return table_base_addr + wasm.tagIndexTableOffset(ip_index); | |
| 4914 | } | |
| 4915 | ||
| 4916 | pub 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 | } |
| 4183 | 4920 | |
| 4184 | 4921 | fn convertZcuFnType( |
| ... | ... | @@ -4201,12 +4938,15 @@ fn convertZcuFnType( |
| 4201 | 4938 | try params_buffer.append(gpa, .i32); // memory address is always a 32-bit handle |
| 4202 | 4939 | } else if (return_type.hasRuntimeBits(zcu)) { |
| 4203 | 4940 | if (cc == .wasm_mvp) { |
| 4204 | switch (abi.classifyType(return_type, zcu)) { | |
| 4205 | .direct => |scalar_ty| { | |
| 4206 | assert(!abi.lowerAsDoubleI64(scalar_ty, zcu)); | |
| 4207 | try returns_buffer.append(gpa, CodeGen.typeToValtype(scalar_ty, zcu, target)); | |
| 4941 | switch (abi.classifyType(return_type, zcu, target)) { | |
| 4942 | .direct => |scalar_type| { | |
| 4943 | try returns_buffer.append(gpa, CodeGen.typeToValtype(scalar_type, zcu, target)); | |
| 4944 | }, | |
| 4945 | .double_i64, .indirect => unreachable, | |
| 4946 | .unrolled => |vector| { | |
| 4947 | assert(vector.len == 1); | |
| 4948 | try returns_buffer.append(gpa, CodeGen.typeToValtype(vector.elem_type, zcu, target)); | |
| 4208 | 4949 | }, |
| 4209 | .indirect => unreachable, | |
| 4210 | 4950 | } |
| 4211 | 4951 | } else { |
| 4212 | 4952 | try returns_buffer.append(gpa, CodeGen.typeToValtype(return_type, zcu, target)); |
| ... | ... | @@ -4222,16 +4962,22 @@ fn convertZcuFnType( |
| 4222 | 4962 | |
| 4223 | 4963 | switch (cc) { |
| 4224 | 4964 | .wasm_mvp => { |
| 4225 | switch (abi.classifyType(param_type, zcu)) { | |
| 4226 | .direct => |scalar_ty| { | |
| 4227 | if (!abi.lowerAsDoubleI64(scalar_ty, zcu)) { | |
| 4228 | try params_buffer.append(gpa, CodeGen.typeToValtype(scalar_ty, zcu, target)); | |
| 4229 | } else { | |
| 4230 | try params_buffer.append(gpa, .i64); | |
| 4231 | try params_buffer.append(gpa, .i64); | |
| 4965 | switch (abi.classifyType(param_type, zcu, target)) { | |
| 4966 | .direct => |scalar_type| { | |
| 4967 | try params_buffer.append(gpa, CodeGen.typeToValtype(scalar_type, zcu, target)); | |
| 4968 | }, | |
| 4969 | .double_i64 => { | |
| 4970 | try params_buffer.append(gpa, .i64); | |
| 4971 | try params_buffer.append(gpa, .i64); | |
| 4972 | }, | |
| 4973 | .indirect => { | |
| 4974 | try params_buffer.append(gpa, CodeGen.typeToValtype(param_type, zcu, target)); | |
| 4975 | }, | |
| 4976 | .unrolled => |vector| { | |
| 4977 | for (0..vector.len) |_| { | |
| 4978 | try params_buffer.append(gpa, CodeGen.typeToValtype(vector.elem_type, zcu, target)); | |
| 4232 | 4979 | } |
| 4233 | 4980 | }, |
| 4234 | .indirect => try params_buffer.append(gpa, CodeGen.typeToValtype(param_type, zcu, target)), | |
| 4235 | 4981 | } |
| 4236 | 4982 | }, |
| 4237 | 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 | 5001 | /// those entries. |
| 4256 | 5002 | fn lowerZcuData(wasm: *Wasm, pt: Zcu.PerThread, ip_index: InternPool.Index) !ZcuDataObj { |
| 4257 | 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 | 5005 | const uav_fixups_start: u32 = @intCast(wasm.uav_fixups.items.len); |
| 4260 | 5006 | const nav_fixups_start: u32 = @intCast(wasm.nav_fixups.items.len); |
| 4261 | 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 | 5017 | } |
| 4272 | 5018 | |
| 4273 | 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 | 5021 | const any_fixups = |
| 5022 | relocs_len != 0 or | |
| 4276 | 5023 | uav_fixups_start != wasm.uav_fixups.items.len or |
| 4277 | 5024 | nav_fixups_start != wasm.nav_fixups.items.len or |
| 4278 | 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 | 45 | |
| 46 | 46 | fn nameOrIndex(archive: Header) !NameOrIndex { |
| 47 | 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 | 49 | const len = value.len; |
| 50 | 50 | if (slash_index == len - 1) { |
| 51 | 51 | // Name stored directly |
src/link/Wasm/Flush.zig+1148-137| ... | ... | @@ -7,7 +7,6 @@ const Object = @import("Object.zig"); |
| 7 | 7 | const Zcu = @import("../../Zcu.zig"); |
| 8 | 8 | const Alignment = Wasm.Alignment; |
| 9 | 9 | const String = Wasm.String; |
| 10 | const Relocation = Wasm.Relocation; | |
| 11 | 10 | const InternPool = @import("../../InternPool.zig"); |
| 12 | 11 | const Mir = @import("../../codegen/wasm/Mir.zig"); |
| 13 | 12 | |
| ... | ... | @@ -33,8 +32,13 @@ data_segment_groups: ArrayList(DataSegmentGroup) = .empty, |
| 33 | 32 | binary_bytes: ArrayList(u8) = .empty, |
| 34 | 33 | missing_exports: std.array_hash_map.Auto(String, void) = .empty, |
| 35 | 34 | function_imports: std.array_hash_map.Auto(String, Wasm.FunctionImportId) = .empty, |
| 35 | intrinsic_function_imports: std.array_hash_map.Auto(String, Wasm.FunctionType.Index) = .empty, | |
| 36 | /// Function aliases emitted after function symbols. | |
| 37 | function_export_symbols: std.array_hash_map.Auto(String, FunctionExportSymbol) = .empty, | |
| 36 | 38 | global_imports: std.array_hash_map.Auto(String, Wasm.GlobalImportId) = .empty, |
| 37 | 39 | data_imports: std.array_hash_map.Auto(String, Wasm.DataImportId) = .empty, |
| 40 | /// Data aliases emitted after data symbols. | |
| 41 | data_exports: std.array_hash_map.Auto(String, DataExportSymbol) = .empty, | |
| 38 | 42 | |
| 39 | 43 | indirect_function_table: std.array_hash_map.Auto(Wasm.OutputFunctionIndex, void) = .empty, |
| 40 | 44 | |
| ... | ... | @@ -43,6 +47,9 @@ func_types: std.array_hash_map.Auto(Wasm.FunctionType.Index, void) = .empty, |
| 43 | 47 | |
| 44 | 48 | enum_tag_name_table: std.array_hash_map.Auto(InternPool.Index, u32) = .empty, |
| 45 | 49 | |
| 50 | code_relocs: std.ArrayList(Relocation) = .empty, | |
| 51 | data_relocs: std.ArrayList(Relocation) = .empty, | |
| 52 | ||
| 46 | 53 | /// For debug purposes only. |
| 47 | 54 | memory_layout_finished: bool = false, |
| 48 | 55 | |
| ... | ... | @@ -55,6 +62,74 @@ pub const FuncTypeIndex = enum(u32) { |
| 55 | 62 | } |
| 56 | 63 | }; |
| 57 | 64 | |
| 65 | /// Index into SYMTAB_FUNCTION. | |
| 66 | const 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. | |
| 100 | const 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 | 133 | /// Index into `indirect_function_table`. |
| 59 | 134 | const IndirectFunctionTableIndex = enum(u32) { |
| 60 | 135 | _, |
| ... | ... | @@ -71,9 +146,8 @@ const IndirectFunctionTableIndex = enum(u32) { |
| 71 | 146 | return @fromBackingInt(@intCast(f.indirect_function_table.getIndex(i).?)); |
| 72 | 147 | } |
| 73 | 148 | |
| 74 | fn fromZcuIndirectFunctionSetIndex(i: Wasm.ZcuIndirectFunctionSetIndex) IndirectFunctionTableIndex { | |
| 75 | // These are the same since those are added to the table first. | |
| 76 | return @fromBackingInt(@intCast(@backingInt(i))); | |
| 149 | fn fromIpNav(wasm: *const Wasm, nav_index: InternPool.Nav.Index) IndirectFunctionTableIndex { | |
| 150 | return fromOutputFunctionIndex(&wasm.flush_buffer, .fromIpNav(wasm, nav_index)); | |
| 77 | 151 | } |
| 78 | 152 | |
| 79 | 153 | fn toAbi(i: IndirectFunctionTableIndex) u32 { |
| ... | ... | @@ -81,6 +155,39 @@ const IndirectFunctionTableIndex = enum(u32) { |
| 81 | 155 | } |
| 82 | 156 | }; |
| 83 | 157 | |
| 158 | const SymbolTableOffsets = struct { | |
| 159 | function: u32, | |
| 160 | data: u32, | |
| 161 | global: u32, | |
| 162 | table: u32, | |
| 163 | }; | |
| 164 | ||
| 165 | const FunctionExportSymbol = struct { | |
| 166 | function_index: Wasm.FunctionIndex, | |
| 167 | flags: Wasm.SymbolFlags, | |
| 168 | }; | |
| 169 | ||
| 170 | const DataExportSymbol = struct { | |
| 171 | resolution: Wasm.ObjectDataImport.Resolution, | |
| 172 | flags: Wasm.SymbolFlags, | |
| 173 | }; | |
| 174 | ||
| 175 | const 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 | ||
| 84 | 191 | const DataSegmentGroup = struct { |
| 85 | 192 | first_segment: Wasm.DataSegmentId, |
| 86 | 193 | end_addr: u32, |
| ... | ... | @@ -90,9 +197,14 @@ pub fn clear(f: *Flush) void { |
| 90 | 197 | f.data_segments.clearRetainingCapacity(); |
| 91 | 198 | f.data_segment_groups.clearRetainingCapacity(); |
| 92 | 199 | f.binary_bytes.clearRetainingCapacity(); |
| 200 | f.intrinsic_function_imports.clearRetainingCapacity(); | |
| 201 | f.function_export_symbols.clearRetainingCapacity(); | |
| 202 | f.data_exports.clearRetainingCapacity(); | |
| 93 | 203 | f.indirect_function_table.clearRetainingCapacity(); |
| 94 | 204 | f.func_types.clearRetainingCapacity(); |
| 95 | 205 | f.enum_tag_name_table.clearRetainingCapacity(); |
| 206 | f.code_relocs.clearRetainingCapacity(); | |
| 207 | f.data_relocs.clearRetainingCapacity(); | |
| 96 | 208 | f.memory_layout_finished = false; |
| 97 | 209 | } |
| 98 | 210 | |
| ... | ... | @@ -102,11 +214,16 @@ pub fn deinit(f: *Flush, gpa: Allocator) void { |
| 102 | 214 | f.binary_bytes.deinit(gpa); |
| 103 | 215 | f.missing_exports.deinit(gpa); |
| 104 | 216 | f.function_imports.deinit(gpa); |
| 217 | f.intrinsic_function_imports.deinit(gpa); | |
| 218 | f.function_export_symbols.deinit(gpa); | |
| 105 | 219 | f.global_imports.deinit(gpa); |
| 106 | 220 | f.data_imports.deinit(gpa); |
| 221 | f.data_exports.deinit(gpa); | |
| 107 | 222 | f.indirect_function_table.deinit(gpa); |
| 108 | 223 | f.func_types.deinit(gpa); |
| 109 | 224 | f.enum_tag_name_table.deinit(gpa); |
| 225 | f.code_relocs.deinit(gpa); | |
| 226 | f.data_relocs.deinit(gpa); | |
| 110 | 227 | f.* = undefined; |
| 111 | 228 | } |
| 112 | 229 | |
| ... | ... | @@ -131,51 +248,12 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 131 | 248 | |
| 132 | 249 | if (comp.zcu) |zcu| { |
| 133 | 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; | |
| 134 | 254 | |
| 135 | 255 | log.debug("total MIR instructions: {d}", .{wasm.mir_instructions.len}); |
| 136 | 256 | |
| 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 | 258 | var i = wasm.function_imports_len_prelink; |
| 181 | 259 | while (i < f.function_imports.entries.len) { |
| ... | ... | @@ -225,10 +303,24 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 225 | 303 | log.debug("flush export '{s}' nav={d}", .{ nav_export.name.slice(wasm), nav_export.nav_index }); |
| 226 | 304 | const function_index = Wasm.FunctionIndex.fromIpNav(wasm, nav_export.nav_index).?; |
| 227 | 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 | 308 | .hidden => true, |
| 230 | 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 | 324 | if (is_hidden) { |
| 233 | 325 | try wasm.hidden_function_exports.put(gpa, nav_export.name, function_index); |
| 234 | 326 | } else { |
| ... | ... | @@ -239,17 +331,170 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 239 | 331 | if (nav_export.name.toOptional() == entry_name) |
| 240 | 332 | wasm.entry_resolution = .fromIpNav(wasm, nav_export.nav_index); |
| 241 | 333 | } else { |
| 242 | // This is a data export because Zcu currently has no way to | |
| 243 | // export wasm globals. | |
| 244 | _ = f.missing_exports.swapRemove(nav_export.name); | |
| 334 | // data exports are linker symbols | |
| 335 | // explicit exports become address globals | |
| 336 | const explicit = f.missing_exports.swapRemove(nav_export.name); | |
| 337 | const opts = export_index.ptr(zcu).opts; | |
| 338 | try f.data_exports.put(gpa, nav_export.name, .{ | |
| 339 | .resolution = .fromIpNav(wasm, nav_export.nav_index), | |
| 340 | .flags = if (is_obj) .{ | |
| 341 | .binding = switch (opts.linkage) { | |
| 342 | .internal => .local, | |
| 343 | .strong => .strong, | |
| 344 | .weak => .weak, | |
| 345 | .link_once => @panic("TODO: COMDAT"), | |
| 346 | }, | |
| 347 | .visibility_hidden = !explicit and switch (opts.visibility) { | |
| 348 | .default => false, | |
| 349 | .hidden => true, | |
| 350 | .protected => false, | |
| 351 | }, | |
| 352 | .exported = explicit, | |
| 353 | .tls = ip.getNav(nav_export.nav_index).resolved.?.@"threadlocal", | |
| 354 | } else .{}, | |
| 355 | }); | |
| 245 | 356 | _ = f.data_imports.swapRemove(nav_export.name); |
| 246 | if (!is_obj) { | |
| 247 | diags.addError("unable to export data symbol '{s}'; not emitting a relocatable", .{ | |
| 248 | nav_export.name.slice(wasm), | |
| 357 | if (explicit and !is_obj) { | |
| 358 | const global_resolution: Wasm.GlobalImport.Resolution = .fromIpNav( | |
| 359 | wasm, | |
| 360 | nav_export.nav_index, | |
| 361 | ); | |
| 362 | try wasm.globals.put(gpa, global_resolution, {}); | |
| 363 | try wasm.global_exports.append(gpa, .{ | |
| 364 | .name = nav_export.name, | |
| 365 | .global_index = Wasm.GlobalIndex.fromResolution(wasm, global_resolution).?, | |
| 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 | } | |
| 253 | 498 | |
| 254 | 499 | for (f.missing_exports.keys()) |exp_name| { |
| 255 | 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 | 545 | if (wasm.object_init_funcs.items.len > 0) { |
| 301 | 546 | // Zig has no constructors so these are only for object file inputs. |
| 302 | 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 | } |
| 305 | 570 | |
| 306 | 571 | // 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 | 606 | // dropped in __wasm_init_memory, which is registered as the start function |
| 342 | 607 | // We also initialize bss segments (using memory.fill) as part of this |
| 343 | 608 | // function. |
| 344 | if (wasm.any_passive_inits) { | |
| 609 | if (!is_obj and wasm.any_passive_inits) { | |
| 345 | 610 | try wasm.addFunction(.__wasm_init_memory, &.{}, &.{}); |
| 346 | 611 | } |
| 347 | 612 | |
| 348 | 613 | try wasm.tables.ensureUnusedCapacity(gpa, 1); |
| 349 | 614 | |
| 350 | 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 | } |
| 353 | 637 | |
| 354 | 638 | // Sort order: |
| ... | ... | @@ -449,7 +733,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 449 | 733 | const start_addr = alignment.forward(memory_ptr); |
| 450 | 734 | |
| 451 | 735 | const want_new_segment = b: { |
| 452 | if (is_obj) break :b false; | |
| 736 | if (is_obj) break :b i != 0; | |
| 453 | 737 | switch (seen_tls) { |
| 454 | 738 | .before => switch (category) { |
| 455 | 739 | .tls => { |
| ... | ... | @@ -489,7 +773,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 489 | 773 | log.debug("0x{x} {d} {s}", .{ start_addr, @backingInt(segment_id), segment_id.name(wasm) }); |
| 490 | 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 | 777 | .first_segment = first_segment, |
| 494 | 778 | .end_addr = @intCast(memory_ptr), |
| 495 | 779 | }); |
| ... | ... | @@ -555,7 +839,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 555 | 839 | |
| 556 | 840 | // When we have TLS GOT entries and shared memory is enabled, we must |
| 557 | 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 | 843 | // This logic that checks `any_tls_relocs` is missing the part where it |
| 560 | 844 | // also notices threadlocal globals from Zcu code. |
| 561 | 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 | 866 | for (f.function_imports.values()) |id| { |
| 583 | 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 | 872 | for (wasm.functions.keys()) |function| { |
| 586 | 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 | 904 | const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); |
| 618 | 905 | |
| 619 | 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 | 908 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(module_name.len))); |
| 622 | 909 | try binary_bytes.appendSlice(gpa, module_name); |
| 623 | 910 | |
| ... | ... | @@ -631,6 +918,20 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 631 | 918 | } |
| 632 | 919 | total_imports += f.function_imports.entries.len; |
| 633 | 920 | |
| 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 | 935 | for (wasm.table_imports.values()) |id| { |
| 635 | 936 | const table_import = id.value(wasm); |
| 636 | 937 | const module_name = table_import.module_name.slice(wasm); |
| ... | ... | @@ -662,7 +963,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 662 | 963 | } |
| 663 | 964 | |
| 664 | 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 | 967 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(module_name.len))); |
| 667 | 968 | try binary_bytes.appendSlice(gpa, module_name); |
| 668 | 969 | |
| ... | ... | @@ -726,12 +1027,12 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 726 | 1027 | for (wasm.globals.keys()) |global_resolution| { |
| 727 | 1028 | switch (global_resolution.unpack(wasm)) { |
| 728 | 1029 | .unresolved => unreachable, |
| 729 | .__heap_base => try appendGlobal(gpa, binary_bytes, 0, virtual_addrs.heap_base), | |
| 730 | .__heap_end => try appendGlobal(gpa, binary_bytes, 0, virtual_addrs.heap_end), | |
| 731 | .__stack_pointer => try appendGlobal(gpa, binary_bytes, 1, virtual_addrs.stack_pointer), | |
| 732 | .__tls_align => try appendGlobal(gpa, binary_bytes, 0, @intCast(virtual_addrs.tls_align.toByteUnits().?)), | |
| 733 | .__tls_base => try appendGlobal(gpa, binary_bytes, 1, virtual_addrs.tls_base.?), | |
| 734 | .__tls_size => try appendGlobal(gpa, binary_bytes, 0, virtual_addrs.tls_size.?), | |
| 1030 | .__heap_base => try appendGlobal(gpa, binary_bytes, 0, virtual_addrs.heap_base, is64), | |
| 1031 | .__heap_end => try appendGlobal(gpa, binary_bytes, 0, virtual_addrs.heap_end, is64), | |
| 1032 | .__stack_pointer => try appendGlobal(gpa, binary_bytes, 1, virtual_addrs.stack_pointer, is64), | |
| 1033 | .__tls_align => try appendGlobal(gpa, binary_bytes, 0, @intCast(virtual_addrs.tls_align.toByteUnits().?), is64), | |
| 1034 | .__tls_base => try appendGlobal(gpa, binary_bytes, 1, virtual_addrs.tls_base.?, is64), | |
| 1035 | .__tls_size => try appendGlobal(gpa, binary_bytes, 0, virtual_addrs.tls_size.?, is64), | |
| 735 | 1036 | .object_global => |i| { |
| 736 | 1037 | const global = i.ptr(wasm); |
| 737 | 1038 | try binary_bytes.appendSlice(gpa, &.{ |
| ... | ... | @@ -740,8 +1041,9 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 740 | 1041 | }); |
| 741 | 1042 | try emitExpr(wasm, binary_bytes, global.expr); |
| 742 | 1043 | }, |
| 743 | .nav_exe => unreachable, // Zig source code currently cannot represent this. | |
| 744 | .nav_obj => unreachable, // Zig source code currently cannot represent this. | |
| 1044 | .uav_exe => |i| try appendGlobal(gpa, binary_bytes, 0, wasm.uavAddr(i.key(wasm).*), is64), | |
| 1045 | .nav_exe => |i| try appendGlobal(gpa, binary_bytes, 0, wasm.navAddr(i.key(wasm).*), is64), | |
| 1046 | .uav_obj, .nav_obj => unreachable, | |
| 745 | 1047 | } |
| 746 | 1048 | } |
| 747 | 1049 | |
| ... | ... | @@ -766,7 +1068,8 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 766 | 1068 | |
| 767 | 1069 | if (wasm.export_table and f.indirect_function_table.entries.len > 0) { |
| 768 | 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 | 1073 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); |
| 771 | 1074 | try binary_bytes.appendSlice(gpa, name); |
| 772 | 1075 | try binary_bytes.append(gpa, @backingInt(std.wasm.ExternalKind.table)); |
| ... | ... | @@ -803,16 +1106,18 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 803 | 1106 | // start section |
| 804 | 1107 | if (wasm.functions.getIndex(.__wasm_init_memory)) |func_index| { |
| 805 | 1108 | try emitStartSection(gpa, binary_bytes, .fromFunctionIndex(wasm, @fromBackingInt(@intCast(func_index)))); |
| 806 | } else if (Wasm.OutputFunctionIndex.fromResolution(wasm, wasm.entry_resolution)) |func_index| { | |
| 807 | try emitStartSection(gpa, binary_bytes, func_index); | |
| 1109 | section_index += 1; | |
| 808 | 1110 | } |
| 809 | 1111 | |
| 810 | 1112 | // element section |
| 811 | if (f.indirect_function_table.entries.len > 0) { | |
| 1113 | if (!is_obj and f.indirect_function_table.entries.len > 0) { | |
| 812 | 1114 | const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); |
| 813 | 1115 | |
| 814 | 1116 | // 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 | 1121 | // passive with implicit 0-index table or set table index manually |
| 817 | 1122 | const flags: u32 = if (table_index == 0) 0x0 else 0x02; |
| 818 | 1123 | try appendLeb128(gpa, binary_bytes, flags); |
| ... | ... | @@ -841,11 +1146,13 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 841 | 1146 | if (f.data_segment_groups.items.len > 0) { |
| 842 | 1147 | const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); |
| 843 | 1148 | replaceVecSectionHeader(binary_bytes, header_offset, .data_count, @intCast(f.data_segment_groups.items.len)); |
| 1149 | section_index += 1; | |
| 844 | 1150 | } |
| 845 | 1151 | |
| 846 | 1152 | // Code section. |
| 847 | 1153 | if (wasm.functions.count() != 0) { |
| 848 | 1154 | const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); |
| 1155 | const section_offset = binary_bytes.items.len - uleb128size(@intCast(wasm.functions.count())); | |
| 849 | 1156 | |
| 850 | 1157 | for (wasm.functions.keys()) |resolution| switch (resolution.unpack(wasm)) { |
| 851 | 1158 | .unresolved => unreachable, |
| ... | ... | @@ -870,10 +1177,22 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 870 | 1177 | const code = ptr.code.slice(wasm); |
| 871 | 1178 | try appendLeb128(gpa, binary_bytes, code.len); |
| 872 | 1179 | const code_start = binary_bytes.items.len; |
| 1180 | const output_offset: u32 = @intCast(binary_bytes.items.len - section_offset); | |
| 873 | 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 | 1194 | .zcu_func => |i| { |
| 1195 | const function_offset: u32 = @intCast(binary_bytes.items.len - section_offset); | |
| 877 | 1196 | const code_start = try reserveSize(gpa, binary_bytes); |
| 878 | 1197 | defer replaceSize(binary_bytes, code_start); |
| 879 | 1198 | |
| ... | ... | @@ -899,7 +1218,22 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 899 | 1218 | .func_tys = undefined, |
| 900 | 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 | 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 | 1255 | } |
| 922 | 1256 | } |
| 923 | 1257 | for (wasm.nav_fixups.items) |nav_fixup| { |
| 924 | const ds_id: Wasm.DataSegmentId = .pack(wasm, .{ .nav_exe = nav_fixup.navs_exe_index }); | |
| 925 | const vaddr = f.data_segments.get(ds_id).? + nav_fixup.addend; | |
| 1258 | const vaddr = wasm.navAddr(nav_fixup.nav_index) + nav_fixup.addend; | |
| 926 | 1259 | if (!is64) { |
| 927 | 1260 | mem.writeInt(u32, wasm.string_bytes.items[nav_fixup.offset..][0..4], vaddr, .little); |
| 928 | 1261 | } else { |
| ... | ... | @@ -930,7 +1263,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 930 | 1263 | } |
| 931 | 1264 | } |
| 932 | 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 | 1267 | if (!is64) { |
| 935 | 1268 | mem.writeInt(u32, wasm.string_bytes.items[fixup.offset..][0..4], table_index.toAbi(), .little); |
| 936 | 1269 | } else { |
| ... | ... | @@ -942,6 +1275,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 942 | 1275 | // Data section. |
| 943 | 1276 | if (f.data_segment_groups.items.len != 0) { |
| 944 | 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)); | |
| 945 | 1279 | |
| 946 | 1280 | var group_index: u32 = 0; |
| 947 | 1281 | var segment_offset: u32 = 0; |
| ... | ... | @@ -976,7 +1310,11 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 976 | 1310 | try appendLeb128(gpa, binary_bytes, group_size); |
| 977 | 1311 | } |
| 978 | 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 | 1318 | continue; |
| 981 | 1319 | } |
| 982 | 1320 | |
| ... | ... | @@ -986,6 +1324,7 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 986 | 1324 | segment_offset = needed_offset; |
| 987 | 1325 | |
| 988 | 1326 | const code_start = binary_bytes.items.len; |
| 1327 | const output_offset: u32 = @intCast(binary_bytes.items.len - section_offset); | |
| 989 | 1328 | append: { |
| 990 | 1329 | const code = switch (segment_id.unpack(wasm)) { |
| 991 | 1330 | .__heap_base => { |
| ... | ... | @@ -1001,12 +1340,19 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 1001 | 1340 | break :append; |
| 1002 | 1341 | }, |
| 1003 | 1342 | .__zig_error_name_table => { |
| 1004 | if (is_obj) @panic("TODO error name table reloc"); | |
| 1005 | const base = f.data_segments.get(.__zig_error_names).?; | |
| 1006 | if (!is64) { | |
| 1007 | try emitTagNameTable(gpa, binary_bytes, wasm.error_name_offs.items, wasm.error_name_bytes.items, base, u32); | |
| 1343 | if (is_obj) { | |
| 1344 | try emitRelocatableNameTable( | |
| 1345 | wasm, | |
| 1346 | binary_bytes, | |
| 1347 | &f.data_relocs, | |
| 1348 | output_offset, | |
| 1349 | wasm.error_name_offs.items, | |
| 1350 | wasm.error_name_bytes.items, | |
| 1351 | .__zig_error_names, | |
| 1352 | ); | |
| 1008 | 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 | 1357 | break :append; |
| 1012 | 1358 | }, |
| ... | ... | @@ -1015,22 +1361,51 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 1015 | 1361 | break :append; |
| 1016 | 1362 | }, |
| 1017 | 1363 | .__zig_tag_name_table => { |
| 1018 | if (is_obj) @panic("TODO tag name table reloc"); | |
| 1019 | const base = f.data_segments.get(.__zig_tag_names).?; | |
| 1020 | if (!is64) { | |
| 1021 | try emitTagNameTable(gpa, binary_bytes, wasm.tag_name_offs.items, wasm.tag_name_bytes.items, base, u32); | |
| 1364 | if (is_obj) { | |
| 1365 | try emitRelocatableNameTable( | |
| 1366 | wasm, | |
| 1367 | binary_bytes, | |
| 1368 | &f.data_relocs, | |
| 1369 | output_offset, | |
| 1370 | wasm.tag_name_offs.items, | |
| 1371 | wasm.tag_name_bytes.items, | |
| 1372 | .__zig_tag_names, | |
| 1373 | ); | |
| 1022 | 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 | 1378 | break :append; |
| 1026 | 1379 | }, |
| 1027 | 1380 | .object => |i| { |
| 1028 | 1381 | const ptr = i.ptr(wasm); |
| 1029 | 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 | 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 | 1410 | try binary_bytes.appendSlice(gpa, code.slice(wasm)); |
| 1036 | 1411 | } |
| ... | ... | @@ -1043,7 +1418,274 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 1043 | 1418 | } |
| 1044 | 1419 | |
| 1045 | 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 | 1689 | } else if (comp.config.debug_format != .strip) { |
| 1048 | 1690 | try emitNameSection(wasm, f.data_segment_groups.items, binary_bytes); |
| 1049 | 1691 | } |
| ... | ... | @@ -1121,7 +1763,10 @@ fn emitNameSection( |
| 1121 | 1763 | const sub_offset = try reserveCustomSectionHeader(gpa, binary_bytes); |
| 1122 | 1764 | defer replaceHeader(binary_bytes, sub_offset, @backingInt(std.wasm.NameSubsection.function)); |
| 1123 | 1765 | |
| 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 | 1770 | try appendLeb128(gpa, binary_bytes, total_functions); |
| 1126 | 1771 | |
| 1127 | 1772 | for (f.function_imports.keys(), 0..) |name_index, function_index| { |
| ... | ... | @@ -1130,7 +1775,16 @@ fn emitNameSection( |
| 1130 | 1775 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); |
| 1131 | 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 | 1788 | const name = resolution.name(wasm).?; |
| 1135 | 1789 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(function_index))); |
| 1136 | 1790 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); |
| ... | ... | @@ -1152,7 +1806,8 @@ fn emitNameSection( |
| 1152 | 1806 | try binary_bytes.appendSlice(gpa, name); |
| 1153 | 1807 | } |
| 1154 | 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 | 1811 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(global_index))); |
| 1157 | 1812 | try appendLeb128(gpa, binary_bytes, @as(u32, @intCast(name.len))); |
| 1158 | 1813 | try binary_bytes.appendSlice(gpa, name); |
| ... | ... | @@ -1270,7 +1925,7 @@ fn emitProducerSection(gpa: Allocator, binary_bytes: *ArrayList(u8)) !void { |
| 1270 | 1925 | |
| 1271 | 1926 | fn splitSegmentName(name: []const u8) struct { []const u8, []const u8 } { |
| 1272 | 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 | 1929 | return .{ name[0..pivot], name[pivot..] }; |
| 1275 | 1930 | } |
| 1276 | 1931 | |
| ... | ... | @@ -1418,29 +2073,6 @@ pub fn emitExpr(wasm: *const Wasm, binary_bytes: *ArrayList(u8), expr: Wasm.Expr |
| 1418 | 2073 | try binary_bytes.appendSlice(gpa, slice[0 .. slice.len + 1]); // +1 to include end opcode |
| 1419 | 2074 | } |
| 1420 | 2075 | |
| 1421 | fn 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 | ||
| 1444 | 2076 | fn uleb128size(x: u32) u32 { |
| 1445 | 2077 | var value = x; |
| 1446 | 2078 | var size: u32 = 0; |
| ... | ... | @@ -1449,22 +2081,395 @@ fn uleb128size(x: u32) u32 { |
| 1449 | 2081 | } |
| 1450 | 2082 | |
| 1451 | 2083 | fn emitTagNameTable( |
| 1452 | gpa: Allocator, | |
| 2084 | wasm: *const Wasm, | |
| 1453 | 2085 | code: *ArrayList(u8), |
| 1454 | 2086 | tag_name_offs: []const u32, |
| 1455 | 2087 | tag_name_bytes: []const u8, |
| 1456 | 2088 | base: u32, |
| 1457 | comptime Int: type, | |
| 2089 | is64: bool, | |
| 1458 | 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 | 2093 | try code.ensureUnusedCapacity(gpa, ptr_size_bytes * 2 * tag_name_offs.len); |
| 1461 | 2094 | for (tag_name_offs) |off| { |
| 1462 | const name_len: u32 = @intCast(mem.indexOfScalar(u8, tag_name_bytes[off..], 0).?); | |
| 1463 | mem.writeInt(Int, code.addManyAsArrayAssumeCapacity(ptr_size_bytes), base + off, .little); | |
| 1464 | mem.writeInt(Int, code.addManyAsArrayAssumeCapacity(ptr_size_bytes), name_len, .little); | |
| 2095 | const name_len: u32 = @intCast(mem.findScalar(u8, tag_name_bytes[off..], 0).?); | |
| 2096 | if (is64) { | |
| 2097 | mem.writeInt(u64, code.addManyAsArrayAssumeCapacity(8), base + off, .little); | |
| 2098 | mem.writeInt(u64, code.addManyAsArrayAssumeCapacity(8), name_len, .little); | |
| 2099 | } else { | |
| 2100 | mem.writeInt(u32, code.addManyAsArrayAssumeCapacity(4), base + off, .little); | |
| 2101 | mem.writeInt(u32, code.addManyAsArrayAssumeCapacity(4), name_len, .little); | |
| 2102 | } | |
| 2103 | } | |
| 2104 | } | |
| 2105 | ||
| 2106 | fn 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 | ||
| 2144 | fn 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 | ||
| 2236 | fn 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 | } |
| 1467 | 2268 | |
| 2269 | fn 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 | ||
| 2456 | fn 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 | ||
| 1468 | 2473 | fn applyRelocs(code: []u8, code_offset: u32, relocs: Wasm.ObjectRelocation.IterableSlice, wasm: *const Wasm) void { |
| 1469 | 2474 | for ( |
| 1470 | 2475 | relocs.slice.tags(wasm), |
| ... | ... | @@ -1579,12 +2584,17 @@ const RelocAddr = struct { |
| 1579 | 2584 | fn fromSymbolName(wasm: *const Wasm, name: String, addend: i32) RelocAddr { |
| 1580 | 2585 | const flush = &wasm.flush_buffer; |
| 1581 | 2586 | if (wasm.object_data_imports.getPtr(name)) |import| { |
| 1582 | return fromDataLoc(flush, import.resolution.dataLoc(wasm), addend); | |
| 1583 | } else if (wasm.data_imports.get(name)) |id| { | |
| 2587 | if (import.resolution != .unresolved) { | |
| 2588 | return fromDataLoc(flush, import.resolution.dataLoc(wasm), addend); | |
| 2589 | } | |
| 2590 | } | |
| 2591 | if (flush.data_exports.get(name)) |symbol| { | |
| 2592 | return fromDataLoc(flush, symbol.resolution.dataLoc(wasm), addend); | |
| 2593 | } | |
| 2594 | if (wasm.data_imports.get(name)) |id| { | |
| 1584 | 2595 | return fromDataLoc(flush, .fromDataImportId(wasm, id), addend); |
| 1585 | } else { | |
| 1586 | unreachable; | |
| 1587 | 2596 | } |
| 2597 | unreachable; | |
| 1588 | 2598 | } |
| 1589 | 2599 | |
| 1590 | 2600 | fn fromDataLoc(flush: *const Flush, data_loc: Wasm.DataLoc, addend: i32) RelocAddr { |
| ... | ... | @@ -1702,13 +2712,11 @@ fn emitInitMemoryFunction( |
| 1702 | 2712 | } |
| 1703 | 2713 | |
| 1704 | 2714 | const segment_groups = wasm.flush_buffer.data_segment_groups.items; |
| 1705 | var prev_end: u32 = 0; | |
| 1706 | 2715 | for (segment_groups, 0..) |group, segment_index| { |
| 1707 | defer prev_end = group.end_addr; | |
| 1708 | 2716 | const segment = group.first_segment; |
| 1709 | 2717 | if (!segment.isPassive(wasm)) continue; |
| 1710 | 2718 | |
| 1711 | const start_addr: u32 = @intCast(segment.alignment(wasm).forward(prev_end)); | |
| 2719 | const start_addr = wasm.flush_buffer.data_segments.get(segment).?; | |
| 1712 | 2720 | const segment_size: u32 = group.end_addr - start_addr; |
| 1713 | 2721 | |
| 1714 | 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 | 3036 | }; |
| 2029 | 3037 | } |
| 2030 | 3038 | |
| 2031 | fn appendGlobal(gpa: Allocator, bytes: *ArrayList(u8), mutable: u8, val: u32) Allocator.Error!void { | |
| 2032 | try bytes.ensureUnusedCapacity(gpa, 9); | |
| 2033 | bytes.appendAssumeCapacity(@backingInt(std.wasm.Valtype.i32)); | |
| 3039 | fn appendGlobal(gpa: Allocator, bytes: *ArrayList(u8), mutable: u8, val: u64, is64: bool) Allocator.Error!void { | |
| 3040 | try bytes.ensureUnusedCapacity(gpa, if (is64) 14 else 9); | |
| 3041 | bytes.appendAssumeCapacity(@backingInt(@as(std.wasm.Valtype, if (is64) .i64 else .i32))); | |
| 2034 | 3042 | bytes.appendAssumeCapacity(mutable); |
| 2035 | bytes.appendAssumeCapacity(@backingInt(std.wasm.Opcode.i32_const)); | |
| 2036 | appendReservedUleb32(bytes, val); | |
| 3043 | if (is64) { | |
| 3044 | appendReservedI64Const(bytes, val); | |
| 3045 | } else { | |
| 3046 | appendReservedI32Const(bytes, @intCast(val)); | |
| 3047 | } | |
| 2037 | 3048 | bytes.appendAssumeCapacity(@backingInt(std.wasm.Opcode.end)); |
| 2038 | 3049 | } |
| 2039 | 3050 |
src/link/Wasm/Object.zig+2-2| ... | ... | @@ -146,7 +146,7 @@ pub const Symbol = struct { |
| 146 | 146 | pointee: Pointee, |
| 147 | 147 | |
| 148 | 148 | /// 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 | 150 | function, |
| 151 | 151 | data, |
| 152 | 152 | global, |
| ... | ... | @@ -856,7 +856,7 @@ pub fn parse( |
| 856 | 856 | start_function = @fromBackingInt(@intCast(functions_start + index)); |
| 857 | 857 | }, |
| 858 | 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 | 860 | pos = section_end; |
| 861 | 861 | }, |
| 862 | 862 | .code => { |
src/main.zig+40-54| ... | ... | @@ -44,9 +44,9 @@ pub const std_options: std.Options = .{ |
| 44 | 44 | .logFn = log, |
| 45 | 45 | |
| 46 | 46 | .log_level = switch (builtin.mode) { |
| 47 | .Debug => .debug, | |
| 48 | .ReleaseSafe, .ReleaseFast => .info, | |
| 49 | .ReleaseSmall => .err, | |
| 47 | .debug => .debug, | |
| 48 | .safe, .fast => .info, | |
| 49 | .small => .err, | |
| 50 | 50 | }, |
| 51 | 51 | }; |
| 52 | 52 | pub const std_options_cwd = if (native_os == .wasi) wasi_cwd else null; |
| ... | ... | @@ -158,8 +158,8 @@ pub fn log( |
| 158 | 158 | |
| 159 | 159 | const use_safe_allocator = build_options.debug_gpa or |
| 160 | 160 | (native_os != .wasi and !builtin.link_libc and switch (builtin.mode) { |
| 161 | .Debug, .ReleaseSafe => true, | |
| 162 | .ReleaseFast, .ReleaseSmall => false, | |
| 161 | .debug, .safe => true, | |
| 162 | .fast, .small => false, | |
| 163 | 163 | }); |
| 164 | 164 | |
| 165 | 165 | var safe_allocator: std.heap.SafeAllocator = .init(std.heap.page_allocator, .{ |
| ... | ... | @@ -359,8 +359,7 @@ fn mainArgs( |
| 359 | 359 | .prepend_global_cache_path = true, |
| 360 | 360 | .prepend_zig_exe_path = true, |
| 361 | 361 | .prepend_seed = true, |
| 362 | .debug_env_var = .ZIG_DEBUG_MAKER, | |
| 363 | .release_mode = .ReleaseSafe, | |
| 362 | .release_mode = .safe, | |
| 364 | 363 | }); |
| 365 | 364 | }, |
| 366 | 365 | .clang, .@"-cc1", .@"-cc1as" => { |
| ... | ... | @@ -557,10 +556,6 @@ const usage_build_generic = |
| 557 | 556 | \\ -fno-function-sections All functions go into same section |
| 558 | 557 | \\ -fdata-sections Places each data in a separate section |
| 559 | 558 | \\ -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 | 559 | \\ -mexec-model=[value] (WASI) Execution model |
| 565 | 560 | \\ -municode (Windows) Use wmain/wWinMain as entry point |
| 566 | 561 | \\ --time-report Send timing diagnostics to '--listen' clients |
| ... | ... | @@ -568,10 +563,10 @@ const usage_build_generic = |
| 568 | 563 | \\Per-Module Compile Options: |
| 569 | 564 | \\ -target [name] <arch><sub>-<os>-<abi> see the targets command |
| 570 | 565 | \\ -O [mode] Choose what to optimize for |
| 571 | \\ Debug (default) Optimizations off, safety on | |
| 572 | \\ ReleaseFast Optimize for performance, safety off | |
| 573 | \\ ReleaseSafe Optimize for performance, safety on | |
| 574 | \\ ReleaseSmall Optimize for small binary, safety off | |
| 566 | \\ debug (default) Prioritize bug detection, accurate debug info, compilation speed | |
| 567 | \\ fast Prioritize runtime performance. Safety checks off. | |
| 568 | \\ safe Enable both safety checks and machine code optimizations | |
| 569 | \\ small Prioritize small binary size. Safety checks off. | |
| 575 | 570 | \\ -ofmt=[fmt] Override target object format |
| 576 | 571 | \\ elf Executable and Linking Format |
| 577 | 572 | \\ c C source code |
| ... | ... | @@ -994,7 +989,7 @@ fn buildOutputType( |
| 994 | 989 | var minor_subsystem_version: ?u16 = null; |
| 995 | 990 | var mingw_unicode_entry_point: bool = false; |
| 996 | 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 | 993 | var install_name: ?[]const u8 = null; |
| 999 | 994 | var hash_style: link.File.Lld.Elf.HashStyle = .both; |
| 1000 | 995 | var entitlements: ?[]const u8 = null; |
| ... | ... | @@ -1200,10 +1195,6 @@ fn buildOutputType( |
| 1200 | 1195 | if (mem.eql(u8, next_arg, "--")) break; |
| 1201 | 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 | 1198 | } else if (mem.eql(u8, arg, "--color")) { |
| 1208 | 1199 | const next_arg = args_iter.next() orelse { |
| 1209 | 1200 | fatal("expected [auto|on|off] after --color", .{}); |
| ... | ... | @@ -1433,7 +1424,7 @@ fn buildOutputType( |
| 1433 | 1424 | enable_link_snapshots = true; |
| 1434 | 1425 | } |
| 1435 | 1426 | } else if (mem.eql(u8, arg, "--debug-rt")) { |
| 1436 | debug_compiler_runtime_libs = .Debug; | |
| 1427 | debug_compiler_runtime_libs = .debug; | |
| 1437 | 1428 | } else if (mem.cutPrefix(u8, arg, "--debug-rt=")) |rest| { |
| 1438 | 1429 | debug_compiler_runtime_libs = parseOptimizeMode(rest); |
| 1439 | 1430 | } else if (mem.eql(u8, arg, "--debug-incremental")) { |
| ... | ... | @@ -1650,12 +1641,6 @@ fn buildOutputType( |
| 1650 | 1641 | create_module.opts.debug_format = .{ .dwarf = .@"32" }; |
| 1651 | 1642 | } else if (mem.eql(u8, arg, "-gdwarf64")) { |
| 1652 | 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 | 1644 | } else if (mem.eql(u8, arg, "-fsingle-threaded")) { |
| 1660 | 1645 | mod_opts.single_threaded = true; |
| 1661 | 1646 | } else if (mem.eql(u8, arg, "-fno-single-threaded")) { |
| ... | ... | @@ -2162,7 +2147,7 @@ fn buildOutputType( |
| 2162 | 2147 | preprocessor_arg[0] == '-' and |
| 2163 | 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 | 2151 | const key = preprocessor_arg[0..equals_pos]; |
| 2167 | 2152 | const value = preprocessor_arg[equals_pos + 1 ..]; |
| 2168 | 2153 | try preprocessor_args.append(key); |
| ... | ... | @@ -2184,7 +2169,7 @@ fn buildOutputType( |
| 2184 | 2169 | linker_arg[0] == '-' and |
| 2185 | 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 | 2173 | const key = linker_arg[0..equals_pos]; |
| 2189 | 2174 | const value = linker_arg[equals_pos + 1 ..]; |
| 2190 | 2175 | |
| ... | ... | @@ -2271,18 +2256,18 @@ fn buildOutputType( |
| 2271 | 2256 | if (mem.eql(u8, level, "s") or |
| 2272 | 2257 | mem.eql(u8, level, "z")) |
| 2273 | 2258 | { |
| 2274 | mod_opts.optimize_mode = .ReleaseSmall; | |
| 2259 | mod_opts.optimize_mode = .small; | |
| 2275 | 2260 | } else if (mem.eql(u8, level, "1") or |
| 2276 | 2261 | mem.eql(u8, level, "2") or |
| 2277 | 2262 | mem.eql(u8, level, "3") or |
| 2278 | 2263 | mem.eql(u8, level, "4") or |
| 2279 | 2264 | mem.eql(u8, level, "fast")) |
| 2280 | 2265 | { |
| 2281 | mod_opts.optimize_mode = .ReleaseFast; | |
| 2266 | mod_opts.optimize_mode = .fast; | |
| 2282 | 2267 | } else if (mem.eql(u8, level, "g") or |
| 2283 | 2268 | mem.eql(u8, level, "0")) |
| 2284 | 2269 | { |
| 2285 | mod_opts.optimize_mode = .Debug; | |
| 2270 | mod_opts.optimize_mode = .debug; | |
| 2286 | 2271 | } else { |
| 2287 | 2272 | try cc_argv.appendSlice(arena, it.other_args); |
| 2288 | 2273 | } |
| ... | ... | @@ -2356,9 +2341,9 @@ fn buildOutputType( |
| 2356 | 2341 | // `sanitize_c` will resolve to! So we either have to pick `off` or `full`. |
| 2357 | 2342 | // |
| 2358 | 2343 | // `full` has the potential to be problematic if `optimize_mode` turns out to |
| 2359 | // be `ReleaseFast`/`ReleaseSmall` because the user will get a slower and larger | |
| 2344 | // be `fast`/`small` because the user will get a slower and larger | |
| 2360 | 2345 | // 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 | 2348 | // `off` seems very slightly less bad, so let's go with that. |
| 2364 | 2349 | mod_opts.sanitize_c = .off; |
| ... | ... | @@ -2392,7 +2377,7 @@ fn buildOutputType( |
| 2392 | 2377 | // Handle joined args like `--dependency-file=foo.d`. |
| 2393 | 2378 | // Must be prefixed with 1 or 2 dashes. |
| 2394 | 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 | 2381 | const key = it.only_arg[0..equals_pos]; |
| 2397 | 2382 | const value = it.only_arg[equals_pos + 1 ..]; |
| 2398 | 2383 | |
| ... | ... | @@ -2972,8 +2957,8 @@ fn buildOutputType( |
| 2972 | 2957 | } |
| 2973 | 2958 | |
| 2974 | 2959 | if (mod_opts.sanitize_c) |wsc| { |
| 2975 | if (wsc != .off and mod_opts.optimize_mode == .ReleaseFast) { | |
| 2976 | mod_opts.optimize_mode = .ReleaseSafe; | |
| 2960 | if (wsc != .off and mod_opts.optimize_mode == .fast) { | |
| 2961 | mod_opts.optimize_mode = .safe; | |
| 2977 | 2962 | } |
| 2978 | 2963 | } |
| 2979 | 2964 | |
| ... | ... | @@ -3835,11 +3820,17 @@ fn buildOutputType( |
| 3835 | 3820 | |
| 3836 | 3821 | var prev_has_cflags = false; |
| 3837 | 3822 | var prev_has_rcflags = false; |
| 3838 | if (dirs.zig_lib.path) |zig_lib_path| { | |
| 3839 | try test_exec_args.appendSlice(arena, &.{ "-cflags", "-I", zig_lib_path, "--" }); | |
| 3840 | prev_has_cflags = true; | |
| 3823 | { | |
| 3824 | if (dirs.zig_lib.path) |zig_lib_path| { | |
| 3825 | try test_exec_args.appendSlice(arena, &.{ "-cflags", "-I", zig_lib_path, "--" }); | |
| 3826 | prev_has_cflags = true; | |
| 3827 | } | |
| 3828 | const emit_ext: Compilation.FileExt = .c; | |
| 3829 | const need_lang = if (comp.emit_bin) |comp_emit_bin| Compilation.classifyFileExt(comp_emit_bin) != emit_ext else true; | |
| 3830 | if (need_lang) try test_exec_args.appendSlice(arena, &.{ "-x", emit_ext.toLang() }); | |
| 3831 | try test_exec_args.append(arena, null); | |
| 3832 | if (need_lang) try test_exec_args.appendSlice(arena, &.{ "-x", "none" }); | |
| 3841 | 3833 | } |
| 3842 | try test_exec_args.append(arena, null); | |
| 3843 | 3834 | for (create_module.modules.keys(), create_module.modules.values()) |mod_name, mod| { |
| 3844 | 3835 | for (create_module.c_source_files.items[mod.c_source_files_start..mod.c_source_files_end]) |c_source_file| { |
| 3845 | 3836 | const cflags_len = c_source_file.extra_flags.len + c_source_file.cache_exempt_flags.len; |
| ... | ... | @@ -4305,11 +4296,8 @@ fn serve( |
| 4305 | 4296 | const gpa = comp.gpa; |
| 4306 | 4297 | const io = comp.io; |
| 4307 | 4298 | |
| 4308 | var server = try Server.init(.{ | |
| 4309 | .in = in, | |
| 4310 | .out = out, | |
| 4311 | .zig_version = build_options.version, | |
| 4312 | }); | |
| 4299 | var server: Server = .{ .in = in, .out = out }; | |
| 4300 | try server.serveStringMessage(.zig_version, build_options.version); | |
| 4313 | 4301 | |
| 4314 | 4302 | var child_pid: ?std.process.Child.Id = null; |
| 4315 | 4303 | |
| ... | ... | @@ -4874,8 +4862,7 @@ const JitCmdOptions = struct { |
| 4874 | 4862 | capture: ?*[]u8 = null, |
| 4875 | 4863 | /// Send error bundles via std.zig.Server over stdout |
| 4876 | 4864 | server: bool = false, |
| 4877 | debug_env_var: EnvVar = .ZIG_DEBUG_CMD, | |
| 4878 | release_mode: std.lang.OptimizeMode = .ReleaseFast, | |
| 4865 | release_mode: std.lang.Optimize = .fast, | |
| 4879 | 4866 | }; |
| 4880 | 4867 | |
| 4881 | 4868 | fn jitCmd( |
| ... | ... | @@ -4926,11 +4913,11 @@ fn jitCmdInner( |
| 4926 | 4913 | const self_exe_path = process.executablePathAlloc(io, arena) catch |err| |
| 4927 | 4914 | fatal("unable to find self exe path: {t}", .{err}); |
| 4928 | 4915 | |
| 4929 | const optimize_mode: std.lang.OptimizeMode = if (options.debug_env_var.isSet(environ_map)) | |
| 4930 | .Debug | |
| 4916 | const optimize_mode: std.lang.Optimize = if (EnvVar.ZIG_DEBUG_CMD.isSet(environ_map)) | |
| 4917 | .debug | |
| 4931 | 4918 | else |
| 4932 | 4919 | options.release_mode; |
| 4933 | const strip = optimize_mode != .Debug; | |
| 4920 | const strip = optimize_mode != .debug; | |
| 4934 | 4921 | var override_lib_dir: ?[]const u8 = EnvVar.ZIG_LIB_DIR.get(environ_map); |
| 4935 | 4922 | const override_global_cache_dir: ?[]const u8 = EnvVar.ZIG_GLOBAL_CACHE_DIR.get(environ_map); |
| 4936 | 4923 | |
| ... | ... | @@ -6008,9 +5995,8 @@ fn parseRcIncludes(arg: []const u8) std.zig.RcIncludes { |
| 6008 | 5995 | fatal("unsupported rc includes type: {q}", .{arg}); |
| 6009 | 5996 | } |
| 6010 | 5997 | |
| 6011 | fn parseOptimizeMode(s: []const u8) std.lang.OptimizeMode { | |
| 6012 | return stringToEnum(std.lang.OptimizeMode, s) orelse | |
| 6013 | fatal("unrecognized optimization mode: {q}", .{s}); | |
| 5998 | fn parseOptimizeMode(s: []const u8) std.lang.Optimize { | |
| 5999 | return std.lang.Optimize.fromString(s) orelse fatal("unrecognized optimization mode: {q}", .{s}); | |
| 6014 | 6000 | } |
| 6015 | 6001 | |
| 6016 | 6002 | fn parseWasiExecModel(s: []const u8) std.lang.WasiExecModel { |
src/print_targets.zig+3-3| ... | ... | @@ -43,9 +43,9 @@ pub fn cmdTargets( |
| 43 | 43 | { |
| 44 | 44 | var root_obj = try serializer.beginStruct(.{}); |
| 45 | 45 | |
| 46 | try root_obj.field("arch", meta.fieldNames(Target.Cpu.Arch), .{}); | |
| 47 | try root_obj.field("os", meta.fieldNames(Target.Os.Tag), .{}); | |
| 48 | try root_obj.field("abi", meta.fieldNames(Target.Abi), .{}); | |
| 46 | try root_obj.field("arch", @typeInfo(Target.Cpu.Arch).@"enum".field_names, .{}); | |
| 47 | try root_obj.field("os", @typeInfo(Target.Os.Tag).@"enum".field_names, .{}); | |
| 48 | try root_obj.field("abi", @typeInfo(Target.Abi).@"enum".field_names, .{}); | |
| 49 | 49 | |
| 50 | 50 | { |
| 51 | 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 | 12 | |
| 13 | 13 | pub fn canDynamicLink(target: *const std.Target) bool { |
| 14 | 14 | return switch (target.cpu.arch) { |
| 15 | .amdgcn, | |
| 16 | 15 | .bpfeb, |
| 17 | 16 | .bpfel, |
| 18 | 17 | .nvptx, |
| ... | ... | @@ -119,10 +118,6 @@ pub fn defaultSingleThreaded(target: *const std.Target) bool { |
| 119 | 118 | .wasm32, .wasm64 => return true, |
| 120 | 119 | else => {}, |
| 121 | 120 | } |
| 122 | switch (target.os.tag) { | |
| 123 | .haiku => return true, | |
| 124 | else => {}, | |
| 125 | } | |
| 126 | 121 | return false; |
| 127 | 122 | } |
| 128 | 123 | |
| ... | ... | @@ -357,12 +352,12 @@ pub fn libcProvidesStackProtector(target: *const std.Target) bool { |
| 357 | 352 | |
| 358 | 353 | /// Returns true if `@returnAddress()` is supported by the target and has a |
| 359 | 354 | /// reasonably performant implementation for the requested optimization mode. |
| 360 | pub fn supportsReturnAddress(target: *const std.Target, optimize: std.lang.OptimizeMode) bool { | |
| 355 | pub fn supportsReturnAddress(target: *const std.Target, optimize: std.lang.Optimize) bool { | |
| 361 | 356 | return switch (target.cpu.arch) { |
| 362 | 357 | // Emscripten currently implements `emscripten_return_address()` by calling |
| 363 | 358 | // out into JavaScript and parsing a stack trace, which introduces significant |
| 364 | 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 | 361 | .bpfel, .bpfeb => false, |
| 367 | 362 | .spirv32, .spirv64 => false, |
| 368 | 363 | else => true, |
| ... | ... | @@ -417,11 +412,11 @@ pub fn hasDebugInfo(target: *const std.Target) bool { |
| 417 | 412 | }; |
| 418 | 413 | } |
| 419 | 414 | |
| 420 | pub fn defaultCompilerRtOptimizeMode(target: *const std.Target) std.lang.OptimizeMode { | |
| 415 | pub fn defaultCompilerRtOptimizeMode(target: *const std.Target) std.lang.Optimize { | |
| 421 | 416 | if (target.cpu.arch.isWasm() and target.os.tag == .freestanding) { |
| 422 | return .ReleaseSmall; | |
| 417 | return .small; | |
| 423 | 418 | } else { |
| 424 | return .ReleaseFast; | |
| 419 | return .fast; | |
| 425 | 420 | } |
| 426 | 421 | } |
| 427 | 422 | |
| ... | ... | @@ -437,7 +432,7 @@ pub fn canBuildLibCompilerRt(target: *const std.Target) enum { no, yes, llvm_onl |
| 437 | 432 | else => {}, |
| 438 | 433 | } |
| 439 | 434 | return switch (zigBackend(target, false)) { |
| 440 | .stage2_aarch64, .stage2_x86_64 => .yes, | |
| 435 | .stage2_aarch64, .stage2_wasm, .stage2_x86_64 => .yes, | |
| 441 | 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 | 445 | else => {}, |
| 451 | 446 | } |
| 452 | 447 | return switch (zigBackend(target, false)) { |
| 453 | .stage2_wasm => .llvm_lld_only, | |
| 448 | .stage2_wasm => .yes, | |
| 454 | 449 | .stage2_x86_64 => .yes, |
| 455 | 450 | else => .llvm_only, |
| 456 | 451 | }; |
| ... | ... | @@ -681,14 +676,14 @@ pub fn isDynamicAMDGCNFeature(target: *const std.Target, feature: std.Target.Cpu |
| 681 | 676 | const feature_tag: std.Target.amdgcn.Feature = @fromBackingInt(@intCast(feature.index)); |
| 682 | 677 | |
| 683 | 678 | if (feature_tag == .sramecc) { |
| 684 | if (std.mem.indexOfScalar( | |
| 679 | if (std.mem.findScalar( | |
| 685 | 680 | *const std.Target.Cpu.Model, |
| 686 | 681 | sramecc_only ++ xnack_or_sramecc, |
| 687 | 682 | target.cpu.model, |
| 688 | 683 | )) |_| return true; |
| 689 | 684 | } |
| 690 | 685 | if (feature_tag == .xnack) { |
| 691 | if (std.mem.indexOfScalar( | |
| 686 | if (std.mem.findScalar( | |
| 692 | 687 | *const std.Target.Cpu.Model, |
| 693 | 688 | xnack_or_sramecc, |
| 694 | 689 | target.cpu.model, |
| ... | ... | @@ -876,18 +871,18 @@ pub fn libcFloatSuffix(float_bits: u16) []const u8 { |
| 876 | 871 | 32 => "f", |
| 877 | 872 | 64 => "", |
| 878 | 873 | 80 => "x", // Non-standard |
| 879 | 128 => "q", // Non-standard (mimics convention in GCC libquadmath) | |
| 874 | 128 => "f128", | |
| 880 | 875 | else => unreachable, |
| 881 | 876 | }; |
| 882 | 877 | } |
| 883 | 878 | |
| 884 | pub fn compilerRtFloatAbbrev(float_bits: u16) []const u8 { | |
| 879 | pub fn compilerRtFloatAbbrev(target: *const std.Target, float_bits: u16) []const u8 { | |
| 885 | 880 | return switch (float_bits) { |
| 886 | 881 | 16 => "h", |
| 887 | 882 | 32 => "s", |
| 888 | 883 | 64 => "d", |
| 889 | 884 | 80 => "x", |
| 890 | 128 => "t", | |
| 885 | 128 => if (target.cpu.arch.isPowerPC()) "k" else "t", | |
| 891 | 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 | 473 | } |
| 474 | 474 | |
| 475 | 475 | bool 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 | 478 | SmallVector<NewArchiveMember, 4> new_members; |
| 479 | 479 | for (size_t i = 0; i < file_name_count; i += 1) { |
| 480 | 480 | Expected<NewArchiveMember> new_member = NewArchiveMember::getFile(file_names[i], true); |
| 481 | 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 | 489 | new_members.push_back(std::move(*new_member)); |
| 484 | 490 | } |
| 485 | 491 | Error err = writeArchive(archive_name, new_members, |
| 486 | 492 | SymtabWritingMode::NormalSymtab, static_cast<object::Archive::Kind>(archive_kind), true, false, nullptr); |
| 487 | 493 | |
| 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 | 502 | return false; |
| 490 | 503 | } |
| 491 | 504 |
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 | 121 | ZIG_EXTERN_C bool ZigLLDLinkELF(int argc, const char **argv, bool can_exit_early, bool disable_output); |
| 122 | 122 | ZIG_EXTERN_C bool ZigLLDLinkWasm(int argc, const char **argv, bool can_exit_early, bool disable_output); |
| 123 | 123 | |
| 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`. | |
| 124 | 129 | ZIG_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); | |
| 126 | 131 | |
| 127 | 132 | #endif |
stage1/FuncGen.h+3-3| ... | ... | @@ -52,17 +52,17 @@ static void FuncGen_free(struct FuncGen *self) { |
| 52 | 52 | } |
| 53 | 53 | |
| 54 | 54 | static 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 | } |
| 57 | 57 | |
| 58 | 58 | static void FuncGen_indent(struct FuncGen *self, FILE *out) { |
| 59 | 59 | FuncGen_outdent(self, out); |
| 60 | fputs(" ", out); | |
| 60 | fputs(" ", out); | |
| 61 | 61 | } |
| 62 | 62 | |
| 63 | 63 | static void FuncGen_cont(struct FuncGen *self, FILE *out) { |
| 64 | 64 | FuncGen_indent(self, out); |
| 65 | fputs(" ", out); | |
| 65 | fputs(" ", out); | |
| 66 | 66 | } |
| 67 | 67 | |
| 68 | 68 | static 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 | 518 | } |
| 519 | 519 | fprintf(out, |
| 520 | 520 | ") {\n" |
| 521 | " init();\n" | |
| 522 | " %sf%" PRIu32 "(", | |
| 521 | " init();\n" | |
| 522 | " %sf%" PRIu32 "(", | |
| 523 | 523 | func_type->result->len > 0 ? "return " : "", idx - imports_len); |
| 524 | 524 | for (uint32_t param_i = 0; param_i < func_type->param->len; param_i += 1) { |
| 525 | 525 | if (param_i > 0) fputs(", ", out); |
| ... | ... | @@ -552,7 +552,7 @@ int main(int argc, char **argv) { |
| 552 | 552 | uint32_t segment_len = InputStream_readLeb128_u32(&in); |
| 553 | 553 | for (uint32_t i = 0; i < segment_len; i += 1) { |
| 554 | 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 | 556 | table_idx, offset + i); |
| 557 | 557 | if (func_id < imports_len) |
| 558 | 558 | fprintf(out, "%s_%s", imports[func_id].mod, imports[func_id].name); |
| ... | ... | @@ -2260,9 +2260,9 @@ int main(int argc, char **argv) { |
| 2260 | 2260 | uint32_t len = InputStream_readLeb128_u32(&in); |
| 2261 | 2261 | fputs("static void init_data(void) {\n", out); |
| 2262 | 2262 | for (uint32_t i = 0; i < mems_len; i += 1) |
| 2263 | fprintf(out, " p%" PRIu32 " = UINT32_C(%" PRIu32 ");\n" | |
| 2264 | " c%" PRIu32 " = p%" PRIu32 ";\n" | |
| 2265 | " m%" PRIu32 " = calloc(c%" PRIu32 ", UINT32_C(1) << 16);\n", | |
| 2263 | fprintf(out, " p%" PRIu32 " = UINT32_C(%" PRIu32 ");\n" | |
| 2264 | " c%" PRIu32 " = p%" PRIu32 ";\n" | |
| 2265 | " m%" PRIu32 " = calloc(c%" PRIu32 ", UINT32_C(1) << 16);\n", | |
| 2266 | 2266 | i, mems[i].limits.min, i, i, i, i); |
| 2267 | 2267 | for (uint32_t segment_i = 0; segment_i < len; segment_i += 1) { |
| 2268 | 2268 | uint32_t mem_idx; |
| ... | ... | @@ -2280,15 +2280,15 @@ int main(int argc, char **argv) { |
| 2280 | 2280 | uint32_t offset = evalExpr(&in); |
| 2281 | 2281 | uint32_t segment_len = InputStream_readLeb128_u32(&in); |
| 2282 | 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 | 2284 | segment_i, segment_len); |
| 2285 | 2285 | for (uint32_t i = 0; i < segment_len; i += 1) { |
| 2286 | 2286 | if (i % 32 == 0) fputs("\n ", out); |
| 2287 | 2287 | fprintf(out, " 0x%02hhX,", InputStream_readByte(&in)); |
| 2288 | 2288 | } |
| 2289 | 2289 | fprintf(out, "\n" |
| 2290 | " };\n" | |
| 2291 | " memcpy(&m%" PRIu32 "[UINT32_C(0x%" PRIX32 ")], s%" PRIu32 ", UINT32_C(%" PRIu32 "));\n", | |
| 2290 | " };\n" | |
| 2291 | " memcpy(&m%" PRIu32 "[UINT32_C(0x%" PRIX32 ")], s%" PRIu32 ", UINT32_C(%" PRIu32 "));\n", | |
| 2292 | 2292 | mem_idx, offset, segment_i, segment_len); |
| 2293 | 2293 | } |
| 2294 | 2294 | fputs("}\n", out); |
stage1/zig.h+3079-991| ... | ... | @@ -166,6 +166,12 @@ |
| 166 | 166 | #endif |
| 167 | 167 | #define zig_expand_has_builtin(b) zig_has_builtin(b) |
| 168 | 168 | |
| 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 | 175 | #if defined(__has_attribute) |
| 170 | 176 | #define zig_has_attribute(attribute) __has_attribute(attribute) |
| 171 | 177 | #else |
| ... | ... | @@ -175,9 +181,9 @@ |
| 175 | 181 | #if __STDC_VERSION__ >= 201112L |
| 176 | 182 | #define zig_static_assert(cond, msg) _Static_assert(cond, msg) |
| 177 | 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 | 185 | #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 | 187 | #endif |
| 182 | 188 | |
| 183 | 189 | #if __STDC_VERSION__ >= 202311L |
| ... | ... | @@ -193,10 +199,8 @@ |
| 193 | 199 | #endif |
| 194 | 200 | |
| 195 | 201 | #if defined(zig_msvc) |
| 196 | #define zig_const_arr | |
| 197 | 202 | #define zig_callconv(c) __##c |
| 198 | 203 | #else |
| 199 | #define zig_const_arr static const | |
| 200 | 204 | #define zig_callconv(c) __attribute__((c)) |
| 201 | 205 | #endif |
| 202 | 206 | |
| ... | ... | @@ -267,12 +271,20 @@ |
| 267 | 271 | |
| 268 | 272 | #if __STDC_VERSION__ >= 202311L |
| 269 | 273 | #define zig_align(alignment) alignas(alignment) |
| 270 | #elif __STDC_VERSION__ >= 201112L | |
| 274 | #elif __STDC_VERSION__ >= 201112L || zig_has_feature(c_alignas) | |
| 271 | 275 | #define zig_align(alignment) _Alignas(alignment) |
| 272 | 276 | #else |
| 273 | 277 | #define zig_align(alignment) zig_under_align(alignment) |
| 274 | 278 | #endif |
| 275 | 279 | |
| 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 | 288 | #if zig_has_attribute(aligned) || defined(zig_tinyc) |
| 277 | 289 | #define zig_align_fn(alignment) __attribute__((aligned(alignment))) |
| 278 | 290 | #elif defined(zig_msvc) |
| ... | ... | @@ -350,11 +362,9 @@ |
| 350 | 362 | #define zig_export(symbol, name) __attribute__((alias(symbol))) |
| 351 | 363 | #else |
| 352 | 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 | 366 | #endif |
| 355 | 367 | |
| 356 | #define zig_mangled_tentative zig_mangled | |
| 357 | #define zig_mangled_final zig_mangled | |
| 358 | 368 | #if defined(zig_msvc) |
| 359 | 369 | #define zig_mangled(mangled, unmangled) ; \ |
| 360 | 370 | zig_export(#mangled, unmangled) |
| ... | ... | @@ -364,7 +374,7 @@ |
| 364 | 374 | #else /* zig_msvc */ |
| 365 | 375 | #define zig_mangled(mangled, unmangled) __asm(zig_mangle_c(unmangled)) |
| 366 | 376 | #define zig_mangled_export(mangled, unmangled, symbol) \ |
| 367 | zig_mangled_final(mangled, unmangled) \ | |
| 377 | zig_mangled(mangled, unmangled) \ | |
| 368 | 378 | zig_export(symbol, unmangled) |
| 369 | 379 | #endif /* zig_msvc */ |
| 370 | 380 | |
| ... | ... | @@ -550,6 +560,9 @@ |
| 550 | 560 | #define zig_noreturn |
| 551 | 561 | #endif |
| 552 | 562 | |
| 563 | #define zig_has_always 1 | |
| 564 | #define zig_has_never 0 | |
| 565 | ||
| 553 | 566 | #define zig_compiler_rt_abbrev_uint32_t si |
| 554 | 567 | #define zig_compiler_rt_abbrev_int32_t si |
| 555 | 568 | #define zig_compiler_rt_abbrev_uint64_t di |
| ... | ... | @@ -560,7 +573,11 @@ |
| 560 | 573 | #define zig_compiler_rt_abbrev_zig_f32 sf |
| 561 | 574 | #define zig_compiler_rt_abbrev_zig_f64 df |
| 562 | 575 | #define zig_compiler_rt_abbrev_zig_f80 xf |
| 576 | #ifdef zig_powerpc | |
| 577 | #define zig_compiler_rt_abbrev_zig_f128 kf | |
| 578 | #else | |
| 563 | 579 | #define zig_compiler_rt_abbrev_zig_f128 tf |
| 580 | #endif | |
| 564 | 581 | |
| 565 | 582 | zig_extern void *memcpy (void *zig_restrict, void const *zig_restrict, size_t); |
| 566 | 583 | zig_extern void *memset (void *, int, size_t); |
| ... | ... | @@ -645,16 +662,6 @@ typedef signed long long int16_t; |
| 645 | 662 | #define INT16_MAX ( INT16_C(0x7FFF)) |
| 646 | 663 | #define UINT16_MAX ( INT16_C(0xFFFF)) |
| 647 | 664 | |
| 648 | #if defined(zig_ez80) | |
| 649 | typedef unsigned int uint24_t; | |
| 650 | typedef 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 | 665 | #if SCHAR_MIN == ~0x7FFFFFFF && SCHAR_MAX == 0x7FFFFFFF && UCHAR_MAX == 0xFFFFFFFF |
| 659 | 666 | typedef unsigned char uint32_t; |
| 660 | 667 | typedef signed char int32_t; |
| ... | ... | @@ -685,17 +692,6 @@ typedef signed long long int32_t; |
| 685 | 692 | #define INT32_MAX ( INT32_C(0x7FFFFFFF)) |
| 686 | 693 | #define UINT32_MAX ( INT32_C(0xFFFFFFFF)) |
| 687 | 694 | |
| 688 | #if defined(zig_ez80) | |
| 689 | typedef unsigned __int48 uint48_t; | |
| 690 | typedef 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 | 695 | #if SCHAR_MIN == ~0x7FFFFFFFFFFFFFFF && SCHAR_MAX == 0x7FFFFFFFFFFFFFFF && UCHAR_MAX == 0xFFFFFFFFFFFFFFFF |
| 700 | 696 | typedef unsigned char uint64_t; |
| 701 | 697 | typedef signed char int64_t; |
| ... | ... | @@ -726,6 +722,27 @@ typedef signed long long int64_t; |
| 726 | 722 | #define INT64_MAX ( INT64_C(0x7FFFFFFFFFFFFFFF)) |
| 727 | 723 | #define UINT64_MAX ( INT64_C(0xFFFFFFFFFFFFFFFF)) |
| 728 | 724 | |
| 725 | #if defined(zig_ez80) | |
| 726 | ||
| 727 | typedef unsigned int uint24_t; | |
| 728 | typedef 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 | ||
| 735 | typedef unsigned __int48 uint48_t; | |
| 736 | typedef 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 | ||
| 729 | 746 | typedef size_t uintptr_t; |
| 730 | 747 | typedef ptrdiff_t intptr_t; |
| 731 | 748 | |
| ... | ... | @@ -739,23 +756,145 @@ typedef ptrdiff_t intptr_t; |
| 739 | 756 | #define zig_maxInt_i16 INT16_MAX |
| 740 | 757 | #define zig_minInt_u16 UINT16_C(0) |
| 741 | 758 | #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 | 759 | #define zig_minInt_i32 INT32_MIN |
| 747 | 760 | #define zig_maxInt_i32 INT32_MAX |
| 748 | 761 | #define zig_minInt_u32 UINT32_C(0) |
| 749 | 762 | #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 | 763 | #define zig_minInt_i64 INT64_MIN |
| 755 | 764 | #define zig_maxInt_i64 INT64_MAX |
| 756 | 765 | #define zig_minInt_u64 UINT64_C(0) |
| 757 | 766 | #define zig_maxInt_u64 UINT64_MAX |
| 758 | 767 | |
| 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 | |
| 772 | typedef unsigned int zig_promoted_i8; | |
| 773 | #elif INT8_MAX <= LONG_MAX | |
| 774 | typedef unsigned long zig_promoted_i8; | |
| 775 | #elif INT8_MAX <= LLONG_MAX | |
| 776 | typedef unsigned long long zig_promoted_i8; | |
| 777 | #else | |
| 778 | typedef int8_t zig_promoted_i8; | |
| 779 | #endif | |
| 780 | #if UINT8_MAX <= UINT_MAX | |
| 781 | typedef unsigned int zig_promoted_u8; | |
| 782 | #elif UINT8_MAX <= ULONG_MAX | |
| 783 | typedef unsigned long zig_promoted_u8; | |
| 784 | #elif UINT8_MAX <= ULLONG_MAX | |
| 785 | typedef unsigned long long zig_promoted_u8; | |
| 786 | #else | |
| 787 | typedef uint8_t zig_promoted_u8; | |
| 788 | #endif | |
| 789 | ||
| 790 | #if INT16_MAX <= INT_MAX | |
| 791 | typedef unsigned int zig_promoted_i16; | |
| 792 | #elif INT16_MAX <= LONG_MAX | |
| 793 | typedef unsigned long zig_promoted_i16; | |
| 794 | #elif INT16_MAX <= LLONG_MAX | |
| 795 | typedef unsigned long long zig_promoted_i16; | |
| 796 | #else | |
| 797 | typedef int16_t zig_promoted_i16; | |
| 798 | #endif | |
| 799 | #if UINT16_MAX <= UINT_MAX | |
| 800 | typedef unsigned int zig_promoted_u16; | |
| 801 | #elif UINT16_MAX <= ULONG_MAX | |
| 802 | typedef unsigned long zig_promoted_u16; | |
| 803 | #elif UINT16_MAX <= ULLONG_MAX | |
| 804 | typedef unsigned long long zig_promoted_u16; | |
| 805 | #else | |
| 806 | typedef uint16_t zig_promoted_u16; | |
| 807 | #endif | |
| 808 | ||
| 809 | #if INT32_MAX <= INT_MAX | |
| 810 | typedef unsigned int zig_promoted_i32; | |
| 811 | #elif INT32_MAX <= LONG_MAX | |
| 812 | typedef unsigned long zig_promoted_i32; | |
| 813 | #elif INT32_MAX <= LLONG_MAX | |
| 814 | typedef unsigned long long zig_promoted_i32; | |
| 815 | #else | |
| 816 | typedef int32_t zig_promoted_i32; | |
| 817 | #endif | |
| 818 | #if UINT32_MAX <= UINT_MAX | |
| 819 | typedef unsigned int zig_promoted_u32; | |
| 820 | #elif UINT32_MAX <= ULONG_MAX | |
| 821 | typedef unsigned long zig_promoted_u32; | |
| 822 | #elif UINT32_MAX <= ULLONG_MAX | |
| 823 | typedef unsigned long long zig_promoted_u32; | |
| 824 | #else | |
| 825 | typedef uint32_t zig_promoted_u32; | |
| 826 | #endif | |
| 827 | ||
| 828 | #if INT64_MAX <= INT_MAX | |
| 829 | typedef unsigned int zig_promoted_i64; | |
| 830 | #elif INT64_MAX <= LONG_MAX | |
| 831 | typedef unsigned long zig_promoted_i64; | |
| 832 | #elif INT64_MAX <= LLONG_MAX | |
| 833 | typedef unsigned long long zig_promoted_i64; | |
| 834 | #else | |
| 835 | typedef int64_t zig_promoted_i64; | |
| 836 | #endif | |
| 837 | #if UINT64_MAX <= UINT_MAX | |
| 838 | typedef unsigned int zig_promoted_u64; | |
| 839 | #elif UINT64_MAX <= ULONG_MAX | |
| 840 | typedef unsigned long zig_promoted_u64; | |
| 841 | #elif UINT64_MAX <= ULLONG_MAX | |
| 842 | typedef unsigned long long zig_promoted_u64; | |
| 843 | #else | |
| 844 | typedef 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 | |
| 859 | typedef unsigned int zig_promoted_i24; | |
| 860 | #elif INT24_MAX <= LONG_MAX | |
| 861 | typedef unsigned long zig_promoted_i24; | |
| 862 | #elif INT24_MAX <= LLONG_MAX | |
| 863 | typedef unsigned long long zig_promoted_i24; | |
| 864 | #else | |
| 865 | typedef int24_t zig_promoted_i24; | |
| 866 | #endif | |
| 867 | #if UINT24_MAX <= UINT_MAX | |
| 868 | typedef unsigned int zig_promoted_u24; | |
| 869 | #elif UINT24_MAX <= ULONG_MAX | |
| 870 | typedef unsigned long zig_promoted_u24; | |
| 871 | #elif UINT24_MAX <= ULLONG_MAX | |
| 872 | typedef unsigned long long zig_promoted_u24; | |
| 873 | #else | |
| 874 | typedef uint24_t zig_promoted_u24; | |
| 875 | #endif | |
| 876 | ||
| 877 | #if INT48_MAX <= INT_MAX | |
| 878 | typedef unsigned int zig_promoted_i48; | |
| 879 | #elif INT48_MAX <= LONG_MAX | |
| 880 | typedef unsigned long zig_promoted_i48; | |
| 881 | #elif INT48_MAX <= LLONG_MAX | |
| 882 | typedef unsigned long long zig_promoted_i48; | |
| 883 | #else | |
| 884 | typedef int48_t zig_promoted_i48; | |
| 885 | #endif | |
| 886 | #if UINT48_MAX <= UINT_MAX | |
| 887 | typedef unsigned int zig_promoted_u48; | |
| 888 | #elif UINT48_MAX <= ULONG_MAX | |
| 889 | typedef unsigned long zig_promoted_u48; | |
| 890 | #elif UINT48_MAX <= ULLONG_MAX | |
| 891 | typedef unsigned long long zig_promoted_u48; | |
| 892 | #else | |
| 893 | typedef uint48_t zig_promoted_u48; | |
| 894 | #endif | |
| 895 | ||
| 896 | #endif | |
| 897 | ||
| 759 | 898 | #define zig_intLimit(s, w, limit, bits) zig_shr_##s##w(zig_##limit##Int_##s##w, w - (bits)) |
| 760 | 899 | #define zig_minInt_i(w, bits) zig_intLimit(i, w, min, bits) |
| 761 | 900 | #define zig_maxInt_i(w, bits) zig_intLimit(i, w, max, bits) |
| ... | ... | @@ -770,7 +909,33 @@ typedef ptrdiff_t intptr_t; |
| 770 | 909 | zig_operator(Type, Type, operation, operator) |
| 771 | 910 | #define zig_shift_operator(Type, operation, operator) \ |
| 772 | 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 | 939 | zig_basic_operator(uint##w##_t, and_u##w, &) \ |
| 775 | 940 | zig_basic_operator( int##w##_t, and_i##w, &) \ |
| 776 | 941 | zig_basic_operator(uint##w##_t, or_u##w, |) \ |
| ... | ... | @@ -786,44 +951,48 @@ typedef ptrdiff_t intptr_t; |
| 786 | 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) { \ | |
| 790 | return val ^ zig_maxInt_u(w, bits); \ | |
| 954 | static inline uint##w##_t zig_not_u##w(uint##w##_t arg, uint8_t bits) { \ | |
| 955 | return arg ^ zig_maxInt_u(w, bits); \ | |
| 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 | 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) { \ | |
| 799 | return val & zig_maxInt_u(w, bits); \ | |
| 963 | zig_basic_operator(uint##w##_t, divFloor_u##w, /) \ | |
| 964 | \ | |
| 965 | static inline int##w##_t zig_divFloor_i##w(int##w##_t lhs, int##w##_t rhs) { \ | |
| 966 | return lhs / rhs + (lhs % rhs != INT##w##_C(0) ? zig_shr_i##w(lhs ^ rhs, UINT8_C(w) - UINT8_C(1)) : INT##w##_C(0)); \ | |
| 800 | 967 | } \ |
| 801 | 968 | \ |
| 802 | static inline int##w##_t zig_wrap_i##w(int##w##_t val, uint8_t bits) { \ | |
| 803 | return (val & UINT##w##_C(1) << (bits - UINT8_C(1))) != 0 \ | |
| 804 | ? val | zig_minInt_i(w, bits) : val & zig_maxInt_i(w, bits); \ | |
| 969 | static inline uint##w##_t zig_divCeil_u##w(uint##w##_t lhs, uint##w##_t rhs) { \ | |
| 970 | return lhs / rhs + (lhs % rhs != UINT##w##_C(0) ? UINT##w##_C(1) : UINT##w##_C(0)); \ | |
| 805 | 971 | } \ |
| 806 | 972 | \ |
| 807 | static inline uint##w##_t zig_abs_i##w(int##w##_t val) { \ | |
| 808 | return (val < 0) ? -(uint##w##_t)val : (uint##w##_t)val; \ | |
| 973 | static inline int##w##_t zig_divCeil_i##w(int##w##_t lhs, int##w##_t rhs) { \ | |
| 974 | return lhs / rhs + (lhs % rhs != INT##w##_C(0) \ | |
| 975 | ? zig_shr_i##w(lhs ^ rhs, UINT8_C(w) - UINT8_C(1)) + INT##w##_C(1) : INT##w##_C(0)); \ | |
| 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) { \ | |
| 814 | return lhs / rhs + (lhs % rhs != INT##w##_C(0) ? zig_shr_i##w(lhs ^ rhs, UINT8_C(w) - UINT8_C(1)) : INT##w##_C(0)); \ | |
| 981 | static inline uint##w##_t zig_u##w##_bitCast_u##w(uint##w##_t arg, uint8_t bits) { \ | |
| 982 | return zig_u##w##_truncate_u##w(arg, bits); \ | |
| 815 | 983 | } \ |
| 816 | 984 | \ |
| 817 | static inline uint##w##_t zig_div_ceil_u##w(uint##w##_t lhs, uint##w##_t rhs) { \ | |
| 818 | return lhs / rhs + (lhs % rhs != UINT##w##_C(0) ? UINT##w##_C(1) : UINT##w##_C(0)); \ | |
| 985 | static inline uint##w##_t zig_u##w##_bitCast_i##w(int##w##_t arg, uint8_t bits) { \ | |
| 986 | return zig_u##w##_bitCast_u##w((uint##w##_t)arg, bits); \ | |
| 819 | 987 | } \ |
| 820 | 988 | \ |
| 821 | static inline int##w##_t zig_div_ceil_i##w(int##w##_t lhs, int##w##_t rhs) { \ | |
| 822 | return lhs / rhs + (lhs % rhs != INT##w##_C(0) \ | |
| 823 | ? zig_shr_i##w(lhs ^ rhs, UINT8_C(w) - UINT8_C(1)) + INT##w##_C(1) : INT##w##_C(0)); \ | |
| 989 | static inline int##w##_t zig_i##w##_bitCast_i##w(int##w##_t arg, uint8_t bits) { \ | |
| 990 | return zig_i##w##_truncate_i##w(arg, bits); \ | |
| 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 | 997 | static inline int##w##_t zig_mod_i##w(int##w##_t lhs, int##w##_t rhs) { \ |
| 829 | 998 | int##w##_t rem = lhs % rhs; \ |
| ... | ... | @@ -831,100 +1000,102 @@ typedef ptrdiff_t intptr_t; |
| 831 | 1000 | } \ |
| 832 | 1001 | \ |
| 833 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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_MAX | |
| 865 | zig_int_helpers(8, unsigned int) | |
| 866 | #elif UINT8_MAX <= ULONG_MAX | |
| 867 | zig_int_helpers(8, unsigned long) | |
| 868 | #elif UINT8_MAX <= ULLONG_MAX | |
| 869 | zig_int_helpers(8, unsigned long long) | |
| 870 | #else | |
| 871 | zig_int_helpers(8, uint8_t) | |
| 872 | #endif | |
| 873 | #if UINT16_MAX <= UINT_MAX | |
| 874 | zig_int_helpers(16, unsigned int) | |
| 875 | #elif UINT16_MAX <= ULONG_MAX | |
| 876 | zig_int_helpers(16, unsigned long) | |
| 877 | #elif UINT16_MAX <= ULLONG_MAX | |
| 878 | zig_int_helpers(16, unsigned long long) | |
| 879 | #else | |
| 880 | zig_int_helpers(16, uint16_t) | |
| 881 | #endif | |
| 882 | #if defined(zig_ez80) | |
| 883 | #if UINT24_MAX <= UINT_MAX | |
| 884 | zig_int_helpers(24, unsigned int) | |
| 885 | #elif UINT24_MAX <= ULONG_MAX | |
| 886 | zig_int_helpers(24, unsigned long) | |
| 887 | #elif UINT24_MAX <= ULLONG_MAX | |
| 888 | zig_int_helpers(24, unsigned long long) | |
| 889 | #else | |
| 890 | zig_int_helpers(24, uint24_t) | |
| 891 | #endif | |
| 892 | #endif | |
| 893 | #if UINT32_MAX <= UINT_MAX | |
| 894 | zig_int_helpers(32, unsigned int) | |
| 895 | #elif UINT32_MAX <= ULONG_MAX | |
| 896 | zig_int_helpers(32, unsigned long) | |
| 897 | #elif UINT32_MAX <= ULLONG_MAX | |
| 898 | zig_int_helpers(32, unsigned long long) | |
| 899 | #else | |
| 900 | zig_int_helpers(32, uint32_t) | |
| 901 | #endif | |
| 902 | #if defined(zig_ez80) | |
| 903 | #if UINT24_MAX <= UINT_MAX | |
| 904 | zig_int_helpers(48, unsigned int) | |
| 905 | #elif UINT24_MAX <= ULONG_MAX | |
| 906 | zig_int_helpers(48, unsigned long) | |
| 907 | #elif UINT24_MAX <= ULLONG_MAX | |
| 908 | zig_int_helpers(48, unsigned long long) | |
| 909 | #else | |
| 910 | zig_int_helpers(48, uint48_t) | |
| 911 | #endif | |
| 912 | #endif | |
| 913 | #if UINT64_MAX <= UINT_MAX | |
| 914 | zig_int_helpers(64, unsigned int) | |
| 915 | #elif UINT64_MAX <= ULONG_MAX | |
| 916 | zig_int_helpers(64, unsigned long) | |
| 917 | #elif UINT64_MAX <= ULLONG_MAX | |
| 918 | zig_int_helpers(64, unsigned long long) | |
| 919 | #else | |
| 920 | zig_int_helpers(64, uint64_t) | |
| 1054 | zig_int_operators(8) | |
| 1055 | zig_int_operators(16) | |
| 1056 | zig_int_operators(32) | |
| 1057 | zig_int_operators(64) | |
| 1058 | #ifdef zig_ez80 | |
| 1059 | zig_int_operators(24) | |
| 1060 | zig_int_operators(48) | |
| 1061 | #endif | |
| 1062 | ||
| 1063 | #define zig_int_casts(bw, sw) \ | |
| 1064 | static inline uint##sw##_t zig_u##sw##_intCast_u##bw(uint##bw##_t arg) { \ | |
| 1065 | return (uint##sw##_t)arg; \ | |
| 1066 | } \ | |
| 1067 | \ | |
| 1068 | static inline uint##sw##_t zig_u##sw##_intCast_i##bw(int##bw##_t arg) { \ | |
| 1069 | return (uint##sw##_t)arg; \ | |
| 1070 | } \ | |
| 1071 | \ | |
| 1072 | static inline int##sw##_t zig_i##sw##_intCast_u##bw(uint##bw##_t arg) { \ | |
| 1073 | return (int##sw##_t)arg; \ | |
| 1074 | } \ | |
| 1075 | \ | |
| 1076 | static inline int##sw##_t zig_i##sw##_intCast_i##bw(int##bw##_t arg) { \ | |
| 1077 | return (int##sw##_t)arg; \ | |
| 1078 | } \ | |
| 1079 | \ | |
| 1080 | zig_int_casts_common(bw, sw) | |
| 1081 | zig_int_casts(16, 8) | |
| 1082 | zig_int_casts(32, 8) | |
| 1083 | zig_int_casts(64, 8) | |
| 1084 | zig_int_casts(32, 16) | |
| 1085 | zig_int_casts(64, 16) | |
| 1086 | zig_int_casts(64, 32) | |
| 1087 | #ifdef zig_ez80 | |
| 1088 | zig_int_casts(32, 24) | |
| 1089 | zig_int_casts(48, 24) | |
| 1090 | zig_int_casts(64, 24) | |
| 1091 | zig_int_casts(64, 48) | |
| 921 | 1092 | #endif |
| 922 | 1093 | |
| 923 | 1094 | static inline bool zig_addo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) { |
| 924 | 1095 | #if zig_has_builtin(add_overflow) || defined(zig_gcc) |
| 925 | 1096 | uint32_t full_res; |
| 926 | 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 | 1099 | return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits); |
| 929 | 1100 | #else |
| 930 | 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 | 1107 | #if zig_has_builtin(add_overflow) || defined(zig_gcc) |
| 937 | 1108 | int32_t full_res; |
| 938 | 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 | 1112 | #else |
| 940 | int32_t full_res = (int32_t)((uint32_t)lhs + (uint32_t)rhs); | |
| 941 | bool overflow = ((full_res ^ lhs) & (full_res ^ rhs)) < 0; | |
| 1113 | *res = zig_addw_i32(lhs, rhs, bits); | |
| 1114 | return ((*res ^ lhs) & (*res ^ rhs)) < INT32_C(0); | |
| 942 | 1115 | #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 | } |
| 946 | 1117 | |
| 947 | 1118 | static inline bool zig_addo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8_t bits) { |
| 948 | 1119 | #if zig_has_builtin(add_overflow) || defined(zig_gcc) |
| 949 | 1120 | uint64_t full_res; |
| 950 | 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 | 1123 | return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits); |
| 953 | 1124 | #else |
| 954 | 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 | 1131 | #if zig_has_builtin(add_overflow) || defined(zig_gcc) |
| 961 | 1132 | int64_t full_res; |
| 962 | 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 | 1136 | #else |
| 964 | int64_t full_res = (int64_t)((uint64_t)lhs + (uint64_t)rhs); | |
| 965 | bool overflow = ((full_res ^ lhs) & (full_res ^ rhs)) < 0; | |
| 1137 | *res = zig_addw_i64(lhs, rhs, bits); | |
| 1138 | return ((*res ^ lhs) & (*res ^ rhs)) < INT64_C(0); | |
| 966 | 1139 | #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 | } |
| 970 | 1141 | |
| 971 | 1142 | static inline bool zig_addo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t bits) { |
| 972 | 1143 | #if zig_has_builtin(add_overflow) || defined(zig_gcc) |
| 973 | 1144 | uint8_t full_res; |
| 974 | 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 | 1147 | return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits); |
| 977 | 1148 | #else |
| 978 | 1149 | uint32_t full_res; |
| 979 | 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 | 1152 | return overflow; |
| 982 | 1153 | #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 | 1157 | #if zig_has_builtin(add_overflow) || defined(zig_gcc) |
| 987 | 1158 | int8_t full_res; |
| 988 | 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 | 1161 | return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits); |
| 991 | 1162 | #else |
| 992 | 1163 | int32_t full_res; |
| 993 | 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 | 1166 | return overflow; |
| 996 | 1167 | #endif |
| 997 | 1168 | } |
| ... | ... | @@ -1000,12 +1171,12 @@ static inline bool zig_addo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8 |
| 1000 | 1171 | #if zig_has_builtin(add_overflow) || defined(zig_gcc) |
| 1001 | 1172 | uint16_t full_res; |
| 1002 | 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 | 1175 | return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits); |
| 1005 | 1176 | #else |
| 1006 | 1177 | uint32_t full_res; |
| 1007 | 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 | 1180 | return overflow; |
| 1010 | 1181 | #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 | 1185 | #if zig_has_builtin(add_overflow) || defined(zig_gcc) |
| 1015 | 1186 | int16_t full_res; |
| 1016 | 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 | 1189 | return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits); |
| 1019 | 1190 | #else |
| 1020 | 1191 | int32_t full_res; |
| 1021 | 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 | 1194 | return overflow; |
| 1024 | 1195 | #endif |
| 1025 | 1196 | } |
| 1026 | 1197 | |
| 1027 | 1198 | #if defined(zig_ez80) |
| 1199 | ||
| 1028 | 1200 | static inline bool zig_addo_u24(uint24_t *res, uint24_t lhs, uint24_t rhs, uint8_t bits) { |
| 1029 | 1201 | #if zig_has_builtin(add_overflow) || defined(zig_gcc) |
| 1030 | 1202 | uint24_t full_res; |
| 1031 | 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 | 1205 | return overflow || full_res < zig_minInt_u(24, bits) || full_res > zig_maxInt_u(24, bits); |
| 1034 | 1206 | #else |
| 1035 | 1207 | uint32_t full_res; |
| 1036 | 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 | 1210 | return overflow; |
| 1039 | 1211 | #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 | 1215 | #if zig_has_builtin(add_overflow) || defined(zig_gcc) |
| 1044 | 1216 | int24_t full_res; |
| 1045 | 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 | 1219 | return overflow || full_res < zig_minInt_i(24, bits) || full_res > zig_maxInt_i(24, bits); |
| 1048 | 1220 | #else |
| 1049 | 1221 | int32_t full_res; |
| 1050 | 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 | 1224 | return overflow; |
| 1053 | 1225 | #endif |
| 1054 | 1226 | } |
| 1055 | #endif | |
| 1056 | 1227 | |
| 1057 | #if defined(zig_ez80) | |
| 1058 | 1228 | static inline bool zig_addo_u48(uint48_t *res, uint48_t lhs, uint48_t rhs, uint8_t bits) { |
| 1059 | 1229 | #if zig_has_builtin(add_overflow) || defined(zig_gcc) |
| 1060 | 1230 | uint48_t full_res; |
| 1061 | 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 | 1233 | return overflow || full_res < zig_minInt_u(48, bits) || full_res > zig_maxInt_u(48, bits); |
| 1064 | 1234 | #else |
| 1065 | 1235 | uint64_t full_res; |
| 1066 | 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 | 1238 | return overflow; |
| 1069 | 1239 | #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 | 1243 | #if zig_has_builtin(add_overflow) || defined(zig_gcc) |
| 1074 | 1244 | int48_t full_res; |
| 1075 | 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 | 1247 | return overflow || full_res < zig_minInt_i(48, bits) || full_res > zig_maxInt_i(48, bits); |
| 1078 | 1248 | #else |
| 1079 | 1249 | int64_t full_res; |
| 1080 | 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 | 1252 | return overflow; |
| 1083 | 1253 | #endif |
| 1084 | 1254 | } |
| 1255 | ||
| 1085 | 1256 | #endif |
| 1086 | 1257 | |
| 1087 | 1258 | static inline bool zig_subo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) { |
| 1088 | 1259 | #if zig_has_builtin(sub_overflow) || defined(zig_gcc) |
| 1089 | 1260 | uint32_t full_res; |
| 1090 | 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 | 1263 | return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits); |
| 1093 | 1264 | #else |
| 1094 | 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 | 1271 | #if zig_has_builtin(sub_overflow) || defined(zig_gcc) |
| 1101 | 1272 | int32_t full_res; |
| 1102 | 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 | 1276 | #else |
| 1104 | int32_t full_res = (int32_t)((uint32_t)lhs - (uint32_t)rhs); | |
| 1105 | bool overflow = ((lhs ^ rhs) & (full_res ^ lhs)) < 0; | |
| 1277 | *res = zig_subw_i32(lhs, rhs, bits); | |
| 1278 | return ((lhs ^ rhs) & (*res ^ lhs)) < INT32_C(0); | |
| 1106 | 1279 | #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 | } |
| 1110 | 1281 | |
| 1111 | ||
| 1112 | 1282 | static inline bool zig_subo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8_t bits) { |
| 1113 | 1283 | #if zig_has_builtin(sub_overflow) || defined(zig_gcc) |
| 1114 | 1284 | uint64_t full_res; |
| 1115 | 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 | 1287 | return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits); |
| 1118 | 1288 | #else |
| 1119 | 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 | 1295 | #if zig_has_builtin(sub_overflow) || defined(zig_gcc) |
| 1126 | 1296 | int64_t full_res; |
| 1127 | 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 | 1300 | #else |
| 1129 | int64_t full_res = (int64_t)((uint64_t)lhs - (uint64_t)rhs); | |
| 1130 | bool overflow = ((lhs ^ rhs) & (full_res ^ lhs)) < 0; | |
| 1301 | *res = zig_subw_i64(lhs, rhs, bits); | |
| 1302 | return ((lhs ^ rhs) & (*res ^ lhs)) < INT64_C(0); | |
| 1131 | 1303 | #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 | } |
| 1135 | 1305 | |
| 1136 | 1306 | static inline bool zig_subo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t bits) { |
| 1137 | 1307 | #if zig_has_builtin(sub_overflow) || defined(zig_gcc) |
| 1138 | 1308 | uint8_t full_res; |
| 1139 | 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 | 1311 | return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits); |
| 1142 | 1312 | #else |
| 1143 | 1313 | uint32_t full_res; |
| 1144 | 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 | 1316 | return overflow; |
| 1147 | 1317 | #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 | 1321 | #if zig_has_builtin(sub_overflow) || defined(zig_gcc) |
| 1152 | 1322 | int8_t full_res; |
| 1153 | 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 | 1325 | return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits); |
| 1156 | 1326 | #else |
| 1157 | 1327 | int32_t full_res; |
| 1158 | 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 | 1330 | return overflow; |
| 1161 | 1331 | #endif |
| 1162 | 1332 | } |
| ... | ... | @@ -1165,12 +1335,12 @@ static inline bool zig_subo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8 |
| 1165 | 1335 | #if zig_has_builtin(sub_overflow) || defined(zig_gcc) |
| 1166 | 1336 | uint16_t full_res; |
| 1167 | 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 | 1339 | return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits); |
| 1170 | 1340 | #else |
| 1171 | 1341 | uint32_t full_res; |
| 1172 | 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 | 1344 | return overflow; |
| 1175 | 1345 | #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 | 1349 | #if zig_has_builtin(sub_overflow) || defined(zig_gcc) |
| 1180 | 1350 | int16_t full_res; |
| 1181 | 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 | 1353 | return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits); |
| 1184 | 1354 | #else |
| 1185 | 1355 | int32_t full_res; |
| 1186 | 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 | 1358 | return overflow; |
| 1189 | 1359 | #endif |
| 1190 | 1360 | } |
| 1191 | 1361 | |
| 1192 | 1362 | #if defined(zig_ez80) |
| 1363 | ||
| 1193 | 1364 | static inline bool zig_subo_u24(uint24_t *res, uint24_t lhs, uint24_t rhs, uint8_t bits) { |
| 1194 | 1365 | #if zig_has_builtin(sub_overflow) || defined(zig_gcc) |
| 1195 | 1366 | uint24_t full_res; |
| 1196 | 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 | 1369 | return overflow || full_res < zig_minInt_u(24, bits) || full_res > zig_maxInt_u(24, bits); |
| 1199 | 1370 | #else |
| 1200 | 1371 | uint32_t full_res; |
| 1201 | 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 | 1374 | return overflow; |
| 1204 | 1375 | #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 | 1379 | #if zig_has_builtin(sub_overflow) || defined(zig_gcc) |
| 1209 | 1380 | int24_t full_res; |
| 1210 | 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 | 1383 | return overflow || full_res < zig_minInt_i(24, bits) || full_res > zig_maxInt_i(24, bits); |
| 1213 | 1384 | #else |
| 1214 | 1385 | int32_t full_res; |
| 1215 | 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 | 1388 | return overflow; |
| 1218 | 1389 | #endif |
| 1219 | 1390 | } |
| 1220 | #endif | |
| 1221 | 1391 | |
| 1222 | #if defined(zig_ez80) | |
| 1223 | 1392 | static inline bool zig_subo_u48(uint48_t *res, uint48_t lhs, uint48_t rhs, uint8_t bits) { |
| 1224 | 1393 | #if zig_has_builtin(sub_overflow) || defined(zig_gcc) |
| 1225 | 1394 | uint48_t full_res; |
| 1226 | 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 | 1397 | return overflow || full_res < zig_minInt_u(48, bits) || full_res > zig_maxInt_u(48, bits); |
| 1229 | 1398 | #else |
| 1230 | 1399 | uint64_t full_res; |
| 1231 | 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 | 1402 | return overflow; |
| 1234 | 1403 | #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 | 1407 | #if zig_has_builtin(sub_overflow) || defined(zig_gcc) |
| 1239 | 1408 | int48_t full_res; |
| 1240 | 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 | 1411 | return overflow || full_res < zig_minInt_i(48, bits) || full_res > zig_maxInt_i(48, bits); |
| 1243 | 1412 | #else |
| 1244 | 1413 | int64_t full_res; |
| 1245 | 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 | 1416 | return overflow; |
| 1248 | 1417 | #endif |
| 1249 | 1418 | } |
| 1419 | ||
| 1250 | 1420 | #endif |
| 1251 | 1421 | |
| 1252 | 1422 | static inline bool zig_mulo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) { |
| 1253 | 1423 | #if zig_has_builtin(mul_overflow) || defined(zig_gcc) |
| 1254 | 1424 | uint32_t full_res; |
| 1255 | 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 | 1427 | return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits); |
| 1258 | 1428 | #else |
| 1259 | 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 | 1431 | #endif |
| 1262 | 1432 | } |
| 1263 | 1433 | |
| 1264 | zig_extern int32_t __mulosi4(int32_t lhs, int32_t rhs, int *overflow); | |
| 1265 | 1434 | static 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 | 1436 | #if zig_has_builtin(mul_overflow) || defined(zig_gcc) |
| 1267 | 1437 | int32_t full_res; |
| 1268 | 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 | 1441 | int32_t full_res = __mulosi4(lhs, rhs, &overflow_int); |
| 1272 | 1442 | bool overflow = overflow_int != 0; |
| 1273 | 1443 | #endif |
| 1274 | *res = zig_wrap_i32(full_res, bits); | |
| 1444 | *res = zig_i32_truncate_i32(full_res, bits); | |
| 1275 | 1445 | return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits); |
| 1276 | 1446 | } |
| 1277 | 1447 | |
| ... | ... | @@ -1279,7 +1449,7 @@ static inline bool zig_mulo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8 |
| 1279 | 1449 | #if zig_has_builtin(mul_overflow) || defined(zig_gcc) |
| 1280 | 1450 | uint64_t full_res; |
| 1281 | 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 | 1453 | return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits); |
| 1284 | 1454 | #else |
| 1285 | 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 | 1457 | #endif |
| 1288 | 1458 | } |
| 1289 | 1459 | |
| 1290 | zig_extern int64_t __mulodi4(int64_t lhs, int64_t rhs, int *overflow); | |
| 1291 | 1460 | static 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 | 1462 | #if zig_has_builtin(mul_overflow) || defined(zig_gcc) |
| 1293 | 1463 | int64_t full_res; |
| 1294 | 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 | 1467 | int64_t full_res = __mulodi4(lhs, rhs, &overflow_int); |
| 1298 | 1468 | bool overflow = overflow_int != 0; |
| 1299 | 1469 | #endif |
| 1300 | *res = zig_wrap_i64(full_res, bits); | |
| 1470 | *res = zig_i64_truncate_i64(full_res, bits); | |
| 1301 | 1471 | return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits); |
| 1302 | 1472 | } |
| 1303 | 1473 | |
| ... | ... | @@ -1305,12 +1475,12 @@ static inline bool zig_mulo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t b |
| 1305 | 1475 | #if zig_has_builtin(mul_overflow) || defined(zig_gcc) |
| 1306 | 1476 | uint8_t full_res; |
| 1307 | 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 | 1479 | return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits); |
| 1310 | 1480 | #else |
| 1311 | 1481 | uint32_t full_res; |
| 1312 | 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 | 1484 | return overflow; |
| 1315 | 1485 | #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 | 1489 | #if zig_has_builtin(mul_overflow) || defined(zig_gcc) |
| 1320 | 1490 | int8_t full_res; |
| 1321 | 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 | 1493 | return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits); |
| 1324 | 1494 | #else |
| 1325 | 1495 | int32_t full_res; |
| 1326 | 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 | 1498 | return overflow; |
| 1329 | 1499 | #endif |
| 1330 | 1500 | } |
| ... | ... | @@ -1333,12 +1503,12 @@ static inline bool zig_mulo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8 |
| 1333 | 1503 | #if zig_has_builtin(mul_overflow) || defined(zig_gcc) |
| 1334 | 1504 | uint16_t full_res; |
| 1335 | 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 | 1507 | return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits); |
| 1338 | 1508 | #else |
| 1339 | 1509 | uint32_t full_res; |
| 1340 | 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 | 1512 | return overflow; |
| 1343 | 1513 | #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 | 1517 | #if zig_has_builtin(mul_overflow) || defined(zig_gcc) |
| 1348 | 1518 | int16_t full_res; |
| 1349 | 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 | 1521 | return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits); |
| 1352 | 1522 | #else |
| 1353 | 1523 | int32_t full_res; |
| 1354 | 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 | 1526 | return overflow; |
| 1357 | 1527 | #endif |
| 1358 | 1528 | } |
| 1359 | 1529 | |
| 1360 | 1530 | #if defined(zig_ez80) |
| 1531 | ||
| 1361 | 1532 | static inline bool zig_mulo_u24(uint24_t *res, uint24_t lhs, uint24_t rhs, uint8_t bits) { |
| 1362 | 1533 | #if zig_has_builtin(mul_overflow) || defined(zig_gcc) |
| 1363 | 1534 | uint24_t full_res; |
| 1364 | 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 | 1537 | return overflow || full_res < zig_minInt_u(24, bits) || full_res > zig_maxInt_u(24, bits); |
| 1367 | 1538 | #else |
| 1368 | 1539 | uint32_t full_res; |
| 1369 | 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 | 1542 | return overflow; |
| 1372 | 1543 | #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 | 1547 | #if zig_has_builtin(mul_overflow) || defined(zig_gcc) |
| 1377 | 1548 | int24_t full_res; |
| 1378 | 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 | 1551 | return overflow || full_res < zig_minInt_i(24, bits) || full_res > zig_maxInt_i(24, bits); |
| 1381 | 1552 | #else |
| 1382 | 1553 | int32_t full_res; |
| 1383 | 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 | 1556 | return overflow; |
| 1386 | 1557 | #endif |
| 1387 | 1558 | } |
| 1388 | #endif | |
| 1389 | 1559 | |
| 1390 | #if defined(zig_ez80) | |
| 1391 | 1560 | static inline bool zig_mulo_u48(uint48_t *res, uint48_t lhs, uint48_t rhs, uint8_t bits) { |
| 1392 | 1561 | #if zig_has_builtin(mul_overflow) || defined(zig_gcc) |
| 1393 | 1562 | uint48_t full_res; |
| 1394 | 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 | 1565 | return overflow || full_res < zig_minInt_u(48, bits) || full_res > zig_maxInt_u(48, bits); |
| 1397 | 1566 | #else |
| 1398 | 1567 | uint64_t full_res; |
| 1399 | 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 | 1570 | return overflow; |
| 1402 | 1571 | #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 | 1575 | #if zig_has_builtin(mul_overflow) || defined(zig_gcc) |
| 1407 | 1576 | int48_t full_res; |
| 1408 | 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 | 1579 | return overflow || full_res < zig_minInt_i(48, bits) || full_res > zig_maxInt_i(48, bits); |
| 1411 | 1580 | #else |
| 1412 | 1581 | int64_t full_res; |
| 1413 | 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 | 1584 | return overflow; |
| 1416 | 1585 | #endif |
| 1417 | 1586 | } |
| 1587 | ||
| 1418 | 1588 | #endif |
| 1419 | 1589 | |
| 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 | 1604 | static inline bool zig_shlo_u##w(uint##w##_t *res, uint##w##_t lhs, uint8_t rhs, uint8_t bits) { \ |
| 1422 | 1605 | *res = zig_shlw_u##w(lhs, rhs, bits); \ |
| 1423 | 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 | 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) { \ | |
| 1433 | uint##w##_t res; \ | |
| 1434 | if (rhs < bits && !zig_shlo_u##w(&res, lhs, rhs, bits)) return res; \ | |
| 1435 | return lhs == INT##w##_C(0) ? INT##w##_C(0) : zig_maxInt_u(w, bits); \ | |
| 1436 | } \ | |
| 1437 | \ | |
| 1438 | static inline int##w##_t zig_shls_i##w(int##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \ | |
| 1439 | int##w##_t res; \ | |
| 1440 | if (rhs < bits && !zig_shlo_i##w(&res, lhs, rhs, bits)) return res; \ | |
| 1441 | return lhs == INT##w##_C(0) ? INT##w##_C(0) : \ | |
| 1442 | lhs < INT##w##_C(0) ? zig_minInt_i(w, bits) : zig_maxInt_i(w, bits); \ | |
| 1443 | } \ | |
| 1615 | zig_shls_builtins(w, 8) \ | |
| 1616 | zig_shls_builtins(w, 16) \ | |
| 1617 | zig_shls_builtins(w, 32) \ | |
| 1618 | zig_shls_builtins(w, 64) \ | |
| 1444 | 1619 | \ |
| 1445 | 1620 | static inline uint##w##_t zig_adds_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \ |
| 1446 | 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 | 1649 | if (!zig_mulo_i##w(&res, lhs, rhs, bits)) return res; \ |
| 1475 | 1650 | return (lhs ^ rhs) < INT##w##_C(0) ? zig_minInt_i(w, bits) : zig_maxInt_i(w, bits); \ |
| 1476 | 1651 | } |
| 1477 | zig_int_builtins(8) | |
| 1478 | zig_int_builtins(16) | |
| 1479 | #if defined(zig_ez80) | |
| 1480 | zig_int_builtins(24) | |
| 1481 | #endif | |
| 1482 | zig_int_builtins(32) | |
| 1652 | zig_int_sat_builtins(8) | |
| 1653 | zig_int_sat_builtins(16) | |
| 1654 | zig_int_sat_builtins(32) | |
| 1655 | zig_int_sat_builtins(64) | |
| 1483 | 1656 | #if defined(zig_ez80) |
| 1484 | zig_int_builtins(48) | |
| 1657 | zig_int_sat_builtins(24) | |
| 1658 | zig_int_sat_builtins(48) | |
| 1485 | 1659 | #endif |
| 1486 | zig_int_builtins(64) | |
| 1487 | 1660 | |
| 1488 | #define zig_builtin8(name, val) __builtin_##name(val) | |
| 1661 | #define zig_builtin8(name, arg) __builtin_##name(arg) | |
| 1489 | 1662 | typedef unsigned int zig_Builtin8; |
| 1490 | 1663 | |
| 1491 | #define zig_builtin16(name, val) __builtin_##name(val) | |
| 1664 | #define zig_builtin16(name, arg) __builtin_##name(arg) | |
| 1492 | 1665 | typedef unsigned int zig_Builtin16; |
| 1493 | 1666 | |
| 1494 | #if defined(zig_ez80) | |
| 1495 | #define zig_builtin24(name, val) __builtin_##name(val) | |
| 1496 | typedef unsigned int zig_Builtin24; | |
| 1497 | #endif | |
| 1498 | ||
| 1499 | 1667 | #if INT_MIN <= INT32_MIN |
| 1500 | #define zig_builtin32(name, val) __builtin_##name(val) | |
| 1668 | #define zig_builtin32(name, arg) __builtin_##name(arg) | |
| 1501 | 1669 | typedef unsigned int zig_Builtin32; |
| 1502 | 1670 | #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) | |
| 1504 | 1672 | typedef unsigned long zig_Builtin32; |
| 1505 | 1673 | #endif |
| 1506 | 1674 | |
| 1507 | #if defined(zig_ez80) | |
| 1508 | #define zig_builtin48(name, val) __builtin_##name(val) | |
| 1509 | typedef unsigned long long zig_Builtin48; | |
| 1510 | #endif | |
| 1511 | ||
| 1512 | 1675 | #if INT_MIN <= INT64_MIN |
| 1513 | #define zig_builtin64(name, val) __builtin_##name(val) | |
| 1676 | #define zig_builtin64(name, arg) __builtin_##name(arg) | |
| 1514 | 1677 | typedef unsigned int zig_Builtin64; |
| 1515 | 1678 | #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) | |
| 1517 | 1680 | typedef unsigned long zig_Builtin64; |
| 1518 | 1681 | #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) | |
| 1520 | 1683 | typedef unsigned long long zig_Builtin64; |
| 1521 | 1684 | #endif |
| 1522 | 1685 | |
| 1523 | static inline uint8_t zig_byte_swap_u8(uint8_t val, uint8_t bits) { | |
| 1524 | return zig_wrap_u8(val >> (8 - bits), bits); | |
| 1686 | #if defined(zig_ez80) | |
| 1687 | #define zig_builtin24(name, arg) __builtin_##name(arg) | |
| 1688 | typedef unsigned int zig_Builtin24; | |
| 1689 | #define zig_builtin48(name, arg) __builtin_##name(arg) | |
| 1690 | typedef unsigned long long zig_Builtin48; | |
| 1691 | #endif | |
| 1692 | ||
| 1693 | static inline uint8_t zig_byteSwap_u8(uint8_t arg, uint8_t bits) { | |
| 1694 | return zig_u8_truncate_u8(arg >> (8 - bits), bits); | |
| 1525 | 1695 | } |
| 1526 | 1696 | |
| 1527 | static inline int8_t zig_byte_swap_i8(int8_t val, uint8_t bits) { | |
| 1528 | return zig_wrap_i8((int8_t)zig_byte_swap_u8((uint8_t)val, bits), bits); | |
| 1697 | static inline int8_t zig_byteSwap_i8(int8_t arg, uint8_t bits) { | |
| 1698 | return zig_i8_truncate_i8((int8_t)zig_byteSwap_u8((uint8_t)arg, bits), bits); | |
| 1529 | 1699 | } |
| 1530 | 1700 | |
| 1531 | static inline uint16_t zig_byte_swap_u16(uint16_t val, uint8_t bits) { | |
| 1701 | static inline uint16_t zig_byteSwap_u16(uint16_t arg, uint8_t bits) { | |
| 1532 | 1702 | uint16_t full_res; |
| 1533 | 1703 | #if zig_has_builtin(bswap16) || defined(zig_gcc) |
| 1534 | full_res = __builtin_bswap16(val); | |
| 1704 | full_res = __builtin_bswap16(arg); | |
| 1535 | 1705 | #else |
| 1536 | full_res = (uint16_t)zig_byte_swap_u8((uint8_t)(val >> 0), 8) << 8 | | |
| 1537 | (uint16_t)zig_byte_swap_u8((uint8_t)(val >> 8), 8) >> 0; | |
| 1706 | full_res = (uint16_t)zig_byteSwap_u8((uint8_t)(arg >> 0), 8) << 8 | | |
| 1707 | (uint16_t)zig_byteSwap_u8((uint8_t)(arg >> 8), 8) >> 0; | |
| 1538 | 1708 | #endif |
| 1539 | return zig_wrap_u16(full_res >> (16 - bits), bits); | |
| 1709 | return zig_u16_truncate_u16(full_res >> (16 - bits), bits); | |
| 1540 | 1710 | } |
| 1541 | 1711 | |
| 1542 | static inline int16_t zig_byte_swap_i16(int16_t val, uint8_t bits) { | |
| 1543 | return zig_wrap_i16((int16_t)zig_byte_swap_u16((uint16_t)val, bits), bits); | |
| 1712 | static inline int16_t zig_byteSwap_i16(int16_t arg, uint8_t bits) { | |
| 1713 | return zig_i16_truncate_i16((int16_t)zig_byteSwap_u16((uint16_t)arg, bits), bits); | |
| 1544 | 1714 | } |
| 1545 | 1715 | |
| 1546 | 1716 | #if defined(zig_ez80) |
| 1547 | static inline uint16_t zig_byte_swap_u24(uint24_t val, uint8_t bits) { | |
| 1717 | static inline uint16_t zig_byteSwap_u24(uint24_t arg, uint8_t bits) { | |
| 1548 | 1718 | uint24_t full_res; |
| 1549 | 1719 | #if zig_has_builtin(bswap24) || defined(zig_gcc) |
| 1550 | full_res = __builtin_bswap24(val); | |
| 1720 | full_res = __builtin_bswap24(arg); | |
| 1551 | 1721 | #else |
| 1552 | full_res = (uint24_t)zig_byte_swap_u8((uint8_t)(val >> 0), 8) << 16 | | |
| 1553 | (uint24_t)zig_byte_swap_u16((uint16_t)(val >> 8), 16) >> 0; | |
| 1722 | full_res = (uint24_t)zig_byteSwap_u8((uint8_t)(arg >> 0), 8) << 16 | | |
| 1723 | (uint24_t)zig_byteSwap_u16((uint16_t)(arg >> 8), 16) >> 0; | |
| 1554 | 1724 | #endif |
| 1555 | return zig_wrap_u24(full_res >> (24 - bits), bits); | |
| 1725 | return zig_u24_truncate_u24(full_res >> (24 - bits), bits); | |
| 1556 | 1726 | } |
| 1557 | 1727 | |
| 1558 | static inline int16_t zig_byte_swap_i24(int24_t val, uint8_t bits) { | |
| 1559 | return zig_wrap_i24((int24_t)zig_byte_swap_u24((uint24_t)val, bits), bits); | |
| 1728 | static inline int16_t zig_byteSwap_i24(int24_t arg, uint8_t bits) { | |
| 1729 | return zig_i24_truncate_i24((int24_t)zig_byteSwap_u24((uint24_t)arg, bits), bits); | |
| 1560 | 1730 | } |
| 1561 | 1731 | #endif |
| 1562 | 1732 | |
| 1563 | static inline uint32_t zig_byte_swap_u32(uint32_t val, uint8_t bits) { | |
| 1733 | static inline uint32_t zig_byteSwap_u32(uint32_t arg, uint8_t bits) { | |
| 1564 | 1734 | uint32_t full_res; |
| 1565 | 1735 | #if zig_has_builtin(bswap32) || defined(zig_gcc) |
| 1566 | full_res = __builtin_bswap32(val); | |
| 1736 | full_res = __builtin_bswap32(arg); | |
| 1567 | 1737 | #else |
| 1568 | full_res = (uint32_t)zig_byte_swap_u16((uint16_t)(val >> 0), 16) << 16 | | |
| 1569 | (uint32_t)zig_byte_swap_u16((uint16_t)(val >> 16), 16) >> 0; | |
| 1738 | full_res = (uint32_t)zig_byteSwap_u16((uint16_t)(arg >> 0), 16) << 16 | | |
| 1739 | (uint32_t)zig_byteSwap_u16((uint16_t)(arg >> 16), 16) >> 0; | |
| 1570 | 1740 | #endif |
| 1571 | return zig_wrap_u32(full_res >> (32 - bits), bits); | |
| 1741 | return zig_u32_truncate_u32(full_res >> (32 - bits), bits); | |
| 1572 | 1742 | } |
| 1573 | 1743 | |
| 1574 | static inline int32_t zig_byte_swap_i32(int32_t val, uint8_t bits) { | |
| 1575 | return zig_wrap_i32((int32_t)zig_byte_swap_u32((uint32_t)val, bits), bits); | |
| 1744 | static inline int32_t zig_byteSwap_i32(int32_t arg, uint8_t bits) { | |
| 1745 | return zig_i32_truncate_i32((int32_t)zig_byteSwap_u32((uint32_t)arg, bits), bits); | |
| 1576 | 1746 | } |
| 1577 | 1747 | |
| 1578 | 1748 | #if defined(zig_ez80) |
| 1579 | static inline uint32_t zig_byte_swap_u48(uint48_t val, uint8_t bits) { | |
| 1749 | static inline uint32_t zig_byteSwap_u48(uint48_t arg, uint8_t bits) { | |
| 1580 | 1750 | uint48_t full_res; |
| 1581 | 1751 | #if zig_has_builtin(bswap48) || defined(zig_gcc) |
| 1582 | full_res = __builtin_bswap48(val); | |
| 1752 | full_res = __builtin_bswap48(arg); | |
| 1583 | 1753 | #else |
| 1584 | full_res = (uint48_t)zig_byte_swap_u24((uint24_t)(val >> 0), 24) << 24 | | |
| 1585 | (uint48_t)zig_byte_swap_u24((uint24_t)(val >> 24), 24) >> 0; | |
| 1754 | full_res = (uint48_t)zig_byteSwap_u24((uint24_t)(arg >> 0), 24) << 24 | | |
| 1755 | (uint48_t)zig_byteSwap_u24((uint24_t)(arg >> 24), 24) >> 0; | |
| 1586 | 1756 | #endif |
| 1587 | return zig_wrap_u48(full_res >> (48 - bits), bits); | |
| 1757 | return zig_u48_truncate_u48(full_res >> (48 - bits), bits); | |
| 1588 | 1758 | } |
| 1589 | 1759 | |
| 1590 | static inline int32_t zig_byte_swap_i48(int48_t val, uint8_t bits) { | |
| 1591 | return zig_wrap_i48((int48_t)zig_byte_swap_u48((uint48_t)val, bits), bits); | |
| 1760 | static inline int32_t zig_byteSwap_i48(int48_t arg, uint8_t bits) { | |
| 1761 | return zig_i48_truncate_i48((int48_t)zig_byteSwap_u48((uint48_t)arg, bits), bits); | |
| 1592 | 1762 | } |
| 1593 | 1763 | #endif |
| 1594 | 1764 | |
| 1595 | static inline uint64_t zig_byte_swap_u64(uint64_t val, uint8_t bits) { | |
| 1765 | static inline uint64_t zig_byteSwap_u64(uint64_t arg, uint8_t bits) { | |
| 1596 | 1766 | uint64_t full_res; |
| 1597 | 1767 | #if zig_has_builtin(bswap64) || defined(zig_gcc) |
| 1598 | full_res = __builtin_bswap64(val); | |
| 1768 | full_res = __builtin_bswap64(arg); | |
| 1599 | 1769 | #else |
| 1600 | full_res = (uint64_t)zig_byte_swap_u32((uint32_t)(val >> 0), 32) << 32 | | |
| 1601 | (uint64_t)zig_byte_swap_u32((uint32_t)(val >> 32), 32) >> 0; | |
| 1770 | full_res = (uint64_t)zig_byteSwap_u32((uint32_t)(arg >> 0), 32) << 32 | | |
| 1771 | (uint64_t)zig_byteSwap_u32((uint32_t)(arg >> 32), 32) >> 0; | |
| 1602 | 1772 | #endif |
| 1603 | return zig_wrap_u64(full_res >> (64 - bits), bits); | |
| 1773 | return zig_u64_truncate_u64(full_res >> (64 - bits), bits); | |
| 1604 | 1774 | } |
| 1605 | 1775 | |
| 1606 | static inline int64_t zig_byte_swap_i64(int64_t val, uint8_t bits) { | |
| 1607 | return zig_wrap_i64((int64_t)zig_byte_swap_u64((uint64_t)val, bits), bits); | |
| 1776 | static inline int64_t zig_byteSwap_i64(int64_t arg, uint8_t bits) { | |
| 1777 | return zig_i64_truncate_i64((int64_t)zig_byteSwap_u64((uint64_t)arg, bits), bits); | |
| 1608 | 1778 | } |
| 1609 | 1779 | |
| 1610 | static inline uint8_t zig_bit_reverse_u8(uint8_t val, uint8_t bits) { | |
| 1780 | static inline uint8_t zig_bitReverse_u8(uint8_t arg, uint8_t bits) { | |
| 1611 | 1781 | uint8_t full_res; |
| 1612 | 1782 | #if zig_has_builtin(bitreverse8) |
| 1613 | full_res = __builtin_bitreverse8(val); | |
| 1783 | full_res = __builtin_bitreverse8(arg); | |
| 1614 | 1784 | #else |
| 1615 | 1785 | static uint8_t const lut[0x10] = { |
| 1616 | 1786 | 0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe, |
| 1617 | 1787 | 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 | 1790 | #endif |
| 1621 | return zig_wrap_u8(full_res >> (8 - bits), bits); | |
| 1791 | return zig_u8_truncate_u8(full_res >> (8 - bits), bits); | |
| 1622 | 1792 | } |
| 1623 | 1793 | |
| 1624 | static inline int8_t zig_bit_reverse_i8(int8_t val, uint8_t bits) { | |
| 1625 | return zig_wrap_i8((int8_t)zig_bit_reverse_u8((uint8_t)val, bits), bits); | |
| 1794 | static inline int8_t zig_bitReverse_i8(int8_t arg, uint8_t bits) { | |
| 1795 | return zig_i8_truncate_i8((int8_t)zig_bitReverse_u8((uint8_t)arg, bits), bits); | |
| 1626 | 1796 | } |
| 1627 | 1797 | |
| 1628 | static inline uint16_t zig_bit_reverse_u16(uint16_t val, uint8_t bits) { | |
| 1798 | static inline uint16_t zig_bitReverse_u16(uint16_t arg, uint8_t bits) { | |
| 1629 | 1799 | uint16_t full_res; |
| 1630 | 1800 | #if zig_has_builtin(bitreverse16) |
| 1631 | full_res = __builtin_bitreverse16(val); | |
| 1801 | full_res = __builtin_bitreverse16(arg); | |
| 1632 | 1802 | #else |
| 1633 | full_res = (uint16_t)zig_bit_reverse_u8((uint8_t)(val >> 0), 8) << 8 | | |
| 1634 | (uint16_t)zig_bit_reverse_u8((uint8_t)(val >> 8), 8) >> 0; | |
| 1803 | full_res = (uint16_t)zig_bitReverse_u8((uint8_t)(arg >> 0), 8) << 8 | | |
| 1804 | (uint16_t)zig_bitReverse_u8((uint8_t)(arg >> 8), 8) >> 0; | |
| 1635 | 1805 | #endif |
| 1636 | return zig_wrap_u16(full_res >> (16 - bits), bits); | |
| 1806 | return zig_u16_truncate_u16(full_res >> (16 - bits), bits); | |
| 1637 | 1807 | } |
| 1638 | 1808 | |
| 1639 | static inline int16_t zig_bit_reverse_i16(int16_t val, uint8_t bits) { | |
| 1640 | return zig_wrap_i16((int16_t)zig_bit_reverse_u16((uint16_t)val, bits), bits); | |
| 1809 | static inline int16_t zig_bitReverse_i16(int16_t arg, uint8_t bits) { | |
| 1810 | return zig_i16_truncate_i16((int16_t)zig_bitReverse_u16((uint16_t)arg, bits), bits); | |
| 1641 | 1811 | } |
| 1642 | 1812 | |
| 1643 | 1813 | #if defined(zig_ez80) |
| 1644 | static inline uint24_t zig_bit_reverse_u24(uint24_t val, uint8_t bits) { | |
| 1814 | static inline uint24_t zig_bitReverse_u24(uint24_t arg, uint8_t bits) { | |
| 1645 | 1815 | uint24_t full_res; |
| 1646 | 1816 | #if zig_has_builtin(bitreverse24) |
| 1647 | full_res = __builtin_bitreverse24(val); | |
| 1817 | full_res = __builtin_bitreverse24(arg); | |
| 1648 | 1818 | #else |
| 1649 | full_res = (uint24_t)zig_bit_reverse_u8((uint8_t)(val >> 0), 8) << 16 | | |
| 1650 | (uint24_t)zig_bit_reverse_u16((uint16_t)(val >> 8), 16) >> 0; | |
| 1819 | full_res = (uint24_t)zig_bitReverse_u8((uint8_t)(arg >> 0), 8) << 16 | | |
| 1820 | (uint24_t)zig_bitReverse_u16((uint16_t)(arg >> 8), 16) >> 0; | |
| 1651 | 1821 | #endif |
| 1652 | return zig_wrap_u24(full_res >> (24 - bits), bits); | |
| 1822 | return zig_u24_truncate_u24(full_res >> (24 - bits), bits); | |
| 1653 | 1823 | } |
| 1654 | 1824 | |
| 1655 | static inline int24_t zig_bit_reverse_i24(int24_t val, uint8_t bits) { | |
| 1656 | return zig_wrap_i24((int24_t)zig_bit_reverse_u24((uint24_t)val, bits), bits); | |
| 1825 | static inline int24_t zig_bitReverse_i24(int24_t arg, uint8_t bits) { | |
| 1826 | return zig_i24_truncate_i24((int24_t)zig_bitReverse_u24((uint24_t)arg, bits), bits); | |
| 1657 | 1827 | } |
| 1658 | 1828 | #endif |
| 1659 | 1829 | |
| 1660 | static inline uint32_t zig_bit_reverse_u32(uint32_t val, uint8_t bits) { | |
| 1830 | static inline uint32_t zig_bitReverse_u32(uint32_t arg, uint8_t bits) { | |
| 1661 | 1831 | uint32_t full_res; |
| 1662 | 1832 | #if zig_has_builtin(bitreverse32) |
| 1663 | full_res = __builtin_bitreverse32(val); | |
| 1833 | full_res = __builtin_bitreverse32(arg); | |
| 1664 | 1834 | #else |
| 1665 | full_res = (uint32_t)zig_bit_reverse_u16((uint16_t)(val >> 0), 16) << 16 | | |
| 1666 | (uint32_t)zig_bit_reverse_u16((uint16_t)(val >> 16), 16) >> 0; | |
| 1835 | full_res = (uint32_t)zig_bitReverse_u16((uint16_t)(arg >> 0), 16) << 16 | | |
| 1836 | (uint32_t)zig_bitReverse_u16((uint16_t)(arg >> 16), 16) >> 0; | |
| 1667 | 1837 | #endif |
| 1668 | return zig_wrap_u32(full_res >> (32 - bits), bits); | |
| 1838 | return zig_u32_truncate_u32(full_res >> (32 - bits), bits); | |
| 1669 | 1839 | } |
| 1670 | 1840 | |
| 1671 | static inline int32_t zig_bit_reverse_i32(int32_t val, uint8_t bits) { | |
| 1672 | return zig_wrap_i32((int32_t)zig_bit_reverse_u32((uint32_t)val, bits), bits); | |
| 1841 | static inline int32_t zig_bitReverse_i32(int32_t arg, uint8_t bits) { | |
| 1842 | return zig_i32_truncate_i32((int32_t)zig_bitReverse_u32((uint32_t)arg, bits), bits); | |
| 1673 | 1843 | } |
| 1674 | 1844 | |
| 1675 | 1845 | #if defined(zig_ez80) |
| 1676 | static inline uint32_t zig_bit_reverse_u48(uint48_t val, uint8_t bits) { | |
| 1846 | static inline uint32_t zig_bitReverse_u48(uint48_t arg, uint8_t bits) { | |
| 1677 | 1847 | uint48_t full_res; |
| 1678 | 1848 | #if zig_has_builtin(bitreverse48) |
| 1679 | full_res = __builtin_bitreverse48(val); | |
| 1849 | full_res = __builtin_bitreverse48(arg); | |
| 1680 | 1850 | #else |
| 1681 | full_res = (uint48_t)zig_bit_reverse_u24((uint24_t)(val >> 0), 24) << 24 | | |
| 1682 | (uint48_t)zig_bit_reverse_u24((uint24_t)(val >> 24), 24) >> 0; | |
| 1851 | full_res = (uint48_t)zig_bitReverse_u24((uint24_t)(arg >> 0), 24) << 24 | | |
| 1852 | (uint48_t)zig_bitReverse_u24((uint24_t)(arg >> 24), 24) >> 0; | |
| 1683 | 1853 | #endif |
| 1684 | return zig_wrap_u32(full_res >> (48 - bits), bits); | |
| 1854 | return zig_u48_truncate_u48(full_res >> (48 - bits), bits); | |
| 1685 | 1855 | } |
| 1686 | 1856 | |
| 1687 | static inline int32_t zig_bit_reverse_i48(int48_t val, uint8_t bits) { | |
| 1688 | return zig_wrap_i48((int48_t)zig_bit_reverse_u48((uint48_t)val, bits), bits); | |
| 1857 | static inline int32_t zig_bitReverse_i48(int48_t arg, uint8_t bits) { | |
| 1858 | return zig_i48_truncate_i48((int48_t)zig_bitReverse_u48((uint48_t)arg, bits), bits); | |
| 1689 | 1859 | } |
| 1690 | 1860 | #endif |
| 1691 | 1861 | |
| 1692 | static inline uint64_t zig_bit_reverse_u64(uint64_t val, uint8_t bits) { | |
| 1862 | static inline uint64_t zig_bitReverse_u64(uint64_t arg, uint8_t bits) { | |
| 1693 | 1863 | uint64_t full_res; |
| 1694 | 1864 | #if zig_has_builtin(bitreverse64) |
| 1695 | full_res = __builtin_bitreverse64(val); | |
| 1865 | full_res = __builtin_bitreverse64(arg); | |
| 1696 | 1866 | #else |
| 1697 | full_res = (uint64_t)zig_bit_reverse_u32((uint32_t)(val >> 0), 32) << 32 | | |
| 1698 | (uint64_t)zig_bit_reverse_u32((uint32_t)(val >> 32), 32) >> 0; | |
| 1867 | full_res = (uint64_t)zig_bitReverse_u32((uint32_t)(arg >> 0), 32) << 32 | | |
| 1868 | (uint64_t)zig_bitReverse_u32((uint32_t)(arg >> 32), 32) >> 0; | |
| 1699 | 1869 | #endif |
| 1700 | return zig_wrap_u64(full_res >> (64 - bits), bits); | |
| 1870 | return zig_u64_truncate_u64(full_res >> (64 - bits), bits); | |
| 1701 | 1871 | } |
| 1702 | 1872 | |
| 1703 | static inline int64_t zig_bit_reverse_i64(int64_t val, uint8_t bits) { | |
| 1704 | return zig_wrap_i64((int64_t)zig_bit_reverse_u64((uint64_t)val, bits), bits); | |
| 1873 | static inline int64_t zig_bitReverse_i64(int64_t arg, uint8_t bits) { | |
| 1874 | return zig_i64_truncate_i64((int64_t)zig_bitReverse_u64((uint64_t)arg, bits), bits); | |
| 1705 | 1875 | } |
| 1706 | 1876 | |
| 1707 | #define zig_builtin_popcount_common(w) \ | |
| 1708 | static inline uint8_t zig_popcount_i##w(int##w##_t val, uint8_t bits) { \ | |
| 1709 | return zig_popcount_u##w((uint##w##_t)val, bits); \ | |
| 1877 | #define zig_builtin_popCount_common(w) \ | |
| 1878 | static inline uint8_t zig_popCount_i##w(int##w##_t arg, uint8_t bits) { \ | |
| 1879 | return zig_popCount_u##w((uint##w##_t)arg, bits); \ | |
| 1710 | 1880 | } |
| 1711 | #if zig_has_builtin(popcount) || defined(zig_gcc) || defined(zig_tinyc) | |
| 1712 | #define zig_builtin_popcount(w) \ | |
| 1713 | static inline uint8_t zig_popcount_u##w(uint##w##_t val, uint8_t bits) { \ | |
| 1881 | #if zig_has_builtin(popCount) || defined(zig_gcc) || defined(zig_tinyc) | |
| 1882 | #define zig_builtin_popCount(w) \ | |
| 1883 | static inline uint8_t zig_popCount_u##w(uint##w##_t arg, uint8_t bits) { \ | |
| 1714 | 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 | 1889 | #else |
| 1720 | #define zig_builtin_popcount(w) \ | |
| 1721 | static inline uint8_t zig_popcount_u##w(uint##w##_t val, uint8_t bits) { \ | |
| 1890 | #define zig_builtin_popCount(w) \ | |
| 1891 | static inline uint8_t zig_popCount_u##w(uint##w##_t arg, uint8_t bits) { \ | |
| 1722 | 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 | 1894 | temp = (temp & (UINT##w##_MAX / 5)) + ((temp >> 2) & (UINT##w##_MAX / 5)); \ |
| 1725 | 1895 | temp = (temp + (temp >> 4)) & (UINT##w##_MAX / 17); \ |
| 1726 | 1896 | return temp * (UINT##w##_MAX / 255) >> (UINT8_C(w) - UINT8_C(8)); \ |
| 1727 | 1897 | } \ |
| 1728 | 1898 | \ |
| 1729 | zig_builtin_popcount_common(w) | |
| 1730 | #endif | |
| 1731 | zig_builtin_popcount(8) | |
| 1732 | zig_builtin_popcount(16) | |
| 1733 | #if defined(zig_ez80) | |
| 1734 | zig_builtin_popcount(24) | |
| 1899 | zig_builtin_popCount_common(w) | |
| 1735 | 1900 | #endif |
| 1736 | zig_builtin_popcount(32) | |
| 1901 | zig_builtin_popCount(8) | |
| 1902 | zig_builtin_popCount(16) | |
| 1903 | zig_builtin_popCount(32) | |
| 1904 | zig_builtin_popCount(64) | |
| 1737 | 1905 | #if defined(zig_ez80) |
| 1738 | zig_builtin_popcount(48) | |
| 1906 | zig_builtin_popCount(24) | |
| 1907 | zig_builtin_popCount(48) | |
| 1739 | 1908 | #endif |
| 1740 | zig_builtin_popcount(64) | |
| 1741 | 1909 | |
| 1742 | 1910 | #define zig_builtin_ctz_common(w) \ |
| 1743 | static inline uint8_t zig_ctz_i##w(int##w##_t val, uint8_t bits) { \ | |
| 1744 | return zig_ctz_u##w((uint##w##_t)val, bits); \ | |
| 1911 | static inline uint8_t zig_ctz_i##w(int##w##_t arg, uint8_t bits) { \ | |
| 1912 | return zig_ctz_u##w((uint##w##_t)arg, bits); \ | |
| 1745 | 1913 | } |
| 1746 | 1914 | #if zig_has_builtin(ctz) || defined(zig_gcc) || defined(zig_tinyc) |
| 1747 | 1915 | #define zig_builtin_ctz(w) \ |
| 1748 | static inline uint8_t zig_ctz_u##w(uint##w##_t val, uint8_t bits) { \ | |
| 1749 | if (val == 0) return bits; \ | |
| 1750 | return zig_builtin##w(ctz, val); \ | |
| 1916 | static inline uint8_t zig_ctz_u##w(uint##w##_t arg, uint8_t bits) { \ | |
| 1917 | if (arg == 0) return bits; \ | |
| 1918 | return zig_builtin##w(ctz, arg); \ | |
| 1751 | 1919 | } \ |
| 1752 | 1920 | \ |
| 1753 | 1921 | zig_builtin_ctz_common(w) |
| 1754 | 1922 | #else |
| 1755 | 1923 | #define zig_builtin_ctz(w) \ |
| 1756 | static inline uint8_t zig_ctz_u##w(uint##w##_t val, uint8_t bits) { \ | |
| 1757 | return zig_popcount_u##w(zig_not_u##w(val, bits) & zig_subw_u##w(val, 1, bits), bits); \ | |
| 1924 | static inline uint8_t zig_ctz_u##w(uint##w##_t arg, uint8_t bits) { \ | |
| 1925 | return zig_popCount_u##w(zig_not_u##w(arg, bits) & zig_subw_u##w(arg, 1, bits), bits); \ | |
| 1758 | 1926 | } \ |
| 1759 | 1927 | \ |
| 1760 | 1928 | zig_builtin_ctz_common(w) |
| 1761 | 1929 | #endif |
| 1762 | 1930 | zig_builtin_ctz(8) |
| 1763 | 1931 | zig_builtin_ctz(16) |
| 1764 | #if defined(zig_ez80) | |
| 1765 | zig_builtin_ctz(24) | |
| 1766 | #endif | |
| 1767 | 1932 | zig_builtin_ctz(32) |
| 1933 | zig_builtin_ctz(64) | |
| 1768 | 1934 | #if defined(zig_ez80) |
| 1935 | zig_builtin_ctz(24) | |
| 1769 | 1936 | zig_builtin_ctz(48) |
| 1770 | 1937 | #endif |
| 1771 | zig_builtin_ctz(64) | |
| 1772 | 1938 | |
| 1773 | 1939 | #define zig_builtin_clz_common(w) \ |
| 1774 | static inline uint8_t zig_clz_i##w(int##w##_t val, uint8_t bits) { \ | |
| 1775 | return zig_clz_u##w((uint##w##_t)val, bits); \ | |
| 1940 | static inline uint8_t zig_clz_i##w(int##w##_t arg, uint8_t bits) { \ | |
| 1941 | return zig_clz_u##w((uint##w##_t)arg, bits); \ | |
| 1776 | 1942 | } |
| 1777 | 1943 | #if zig_has_builtin(clz) || defined(zig_gcc) || defined(zig_tinyc) |
| 1778 | 1944 | #define zig_builtin_clz(w) \ |
| 1779 | static inline uint8_t zig_clz_u##w(uint##w##_t val, uint8_t bits) { \ | |
| 1780 | if (val == 0) return bits; \ | |
| 1781 | return zig_builtin##w(clz, val) - (zig_bitSizeOf(zig_Builtin##w) - bits); \ | |
| 1945 | static inline uint8_t zig_clz_u##w(uint##w##_t arg, uint8_t bits) { \ | |
| 1946 | if (arg == 0) return bits; \ | |
| 1947 | return zig_builtin##w(clz, arg) - (zig_bitSizeOf(zig_Builtin##w) - bits); \ | |
| 1782 | 1948 | } \ |
| 1783 | 1949 | \ |
| 1784 | 1950 | zig_builtin_clz_common(w) |
| 1785 | 1951 | #else |
| 1786 | 1952 | #define zig_builtin_clz(w) \ |
| 1787 | static inline uint8_t zig_clz_u##w(uint##w##_t val, uint8_t bits) { \ | |
| 1788 | return zig_ctz_u##w(zig_bit_reverse_u##w(val, bits), bits); \ | |
| 1953 | static inline uint8_t zig_clz_u##w(uint##w##_t arg, uint8_t bits) { \ | |
| 1954 | return zig_ctz_u##w(zig_bitReverse_u##w(arg, bits), bits); \ | |
| 1789 | 1955 | } \ |
| 1790 | 1956 | \ |
| 1791 | 1957 | zig_builtin_clz_common(w) |
| 1792 | 1958 | #endif |
| 1793 | 1959 | zig_builtin_clz(8) |
| 1794 | 1960 | zig_builtin_clz(16) |
| 1795 | #if defined(zig_ez80) | |
| 1796 | zig_builtin_clz(24) | |
| 1797 | #endif | |
| 1798 | 1961 | zig_builtin_clz(32) |
| 1962 | zig_builtin_clz(64) | |
| 1799 | 1963 | #if defined(zig_ez80) |
| 1964 | zig_builtin_clz(24) | |
| 1800 | 1965 | zig_builtin_clz(48) |
| 1801 | 1966 | #endif |
| 1802 | zig_builtin_clz(64) | |
| 1803 | 1967 | |
| 1804 | 1968 | /* ======================== 128-bit Integer Support ========================= */ |
| 1805 | 1969 | |
| ... | ... | @@ -1816,16 +1980,14 @@ zig_builtin_clz(64) |
| 1816 | 1980 | typedef unsigned __int128 zig_u128; |
| 1817 | 1981 | typedef signed __int128 zig_i128; |
| 1818 | 1982 | |
| 1819 | #define zig_make_u128(hi, lo) ((zig_u128)(hi)<<64|(lo)) | |
| 1820 | #define zig_make_i128(hi, lo) ((zig_i128)zig_make_u128(hi, lo)) | |
| 1821 | #define zig_init_u128(hi, lo) zig_make_u128(hi, lo) | |
| 1822 | #define zig_init_i128(hi, lo) zig_make_i128(hi, lo) | |
| 1823 | #define zig_hi_u128(val) ((uint64_t)((val) >> 64)) | |
| 1824 | #define zig_lo_u128(val) ((uint64_t)((val) >> 0)) | |
| 1825 | #define zig_hi_i128(val) (( int64_t)((val) >> 64)) | |
| 1826 | #define zig_lo_i128(val) ((uint64_t)((val) >> 0)) | |
| 1827 | #define zig_bitCast_u128(val) ((zig_u128)(val)) | |
| 1828 | #define zig_bitCast_i128(val) ((zig_i128)(val)) | |
| 1983 | #define zig_init_u128(hi, lo) ((zig_u128)(hi)<<64|(lo)) | |
| 1984 | #define zig_init_i128(hi, lo) ((zig_i128)zig_make_u128(hi, lo)) | |
| 1985 | #define zig_make_u128(hi, lo) zig_init_u128(hi, lo) | |
| 1986 | #define zig_make_i128(hi, lo) zig_init_i128(hi, lo) | |
| 1987 | #define zig_hi_u128(arg) ((uint64_t)((arg) >> 64)) | |
| 1988 | #define zig_lo_u128(arg) ((uint64_t)((arg) >> 0)) | |
| 1989 | #define zig_hi_i128(arg) (( int64_t)((arg) >> 64)) | |
| 1990 | #define zig_lo_i128(arg) ((uint64_t)((arg) >> 0)) | |
| 1829 | 1991 | #define zig_cmp_int128(Type) \ |
| 1830 | 1992 | static inline int32_t zig_cmp_##Type(zig_##Type lhs, zig_##Type rhs) { \ |
| 1831 | 1993 | return (lhs > rhs) - (lhs < rhs); \ |
| ... | ... | @@ -1835,32 +1997,49 @@ typedef signed __int128 zig_i128; |
| 1835 | 1997 | return lhs operator rhs; \ |
| 1836 | 1998 | } |
| 1837 | 1999 | |
| 1838 | #else /* zig_has_int128 */ | |
| 2000 | static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) { | |
| 2001 | return lhs << rhs; | |
| 2002 | } | |
| 1839 | 2003 | |
| 1840 | #if zig_little_endian | |
| 1841 | typedef struct { zig_align(16) uint64_t lo; uint64_t hi; } zig_u128; | |
| 1842 | typedef struct { zig_align(16) uint64_t lo; int64_t hi; } zig_i128; | |
| 2004 | static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs) { | |
| 2005 | return lhs >> rhs; | |
| 2006 | } | |
| 2007 | ||
| 2008 | static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) { | |
| 2009 | return lhs << rhs; | |
| 2010 | } | |
| 2011 | ||
| 2012 | static 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 | 2019 | #else |
| 1844 | typedef struct { zig_align(16) uint64_t hi; uint64_t lo; } zig_u128; | |
| 1845 | typedef struct { zig_align(16) int64_t hi; uint64_t lo; } zig_i128; | |
| 2020 | zig_i128 sign_mask = lhs < zig_make_i128(0, 0) ? -zig_make_i128(0, 1) : zig_make_i128(0, 0); | |
| 2021 | return ((lhs ^ sign_mask) >> rhs) ^ sign_mask; | |
| 1846 | 2022 | #endif |
| 2023 | } | |
| 1847 | 2024 | |
| 1848 | #define zig_make_u128(hi, lo) ((zig_u128){ .h##i = (hi), .l##o = (lo) }) | |
| 1849 | #define zig_make_i128(hi, lo) ((zig_i128){ .h##i = (hi), .l##o = (lo) }) | |
| 2025 | #else /* zig_has_int128 */ | |
| 1850 | 2026 | |
| 1851 | #if defined(zig_msvc) /* MSVC doesn't allow struct literals in constant expressions */ | |
| 1852 | #define zig_init_u128(hi, lo) { .h##i = (hi), .l##o = (lo) } | |
| 1853 | #define zig_init_i128(hi, lo) { .h##i = (hi), .l##o = (lo) } | |
| 1854 | #else /* But non-MSVC doesn't like the unprotected commas */ | |
| 1855 | #define zig_init_u128(hi, lo) zig_make_u128(hi, lo) | |
| 1856 | #define zig_init_i128(hi, lo) zig_make_i128(hi, lo) | |
| 1857 | #endif | |
| 1858 | #define zig_hi_u128(val) ((val).hi) | |
| 1859 | #define zig_lo_u128(val) ((val).lo) | |
| 1860 | #define zig_hi_i128(val) ((val).hi) | |
| 1861 | #define zig_lo_i128(val) ((val).lo) | |
| 1862 | #define zig_bitCast_u128(val) zig_make_u128((uint64_t)(val).hi, (val).lo) | |
| 1863 | #define zig_bitCast_i128(val) zig_make_i128(( int64_t)(val).hi, (val).lo) | |
| 2027 | #if zig_little_endian | |
| 2028 | typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) uint64_t lo; uint64_t hi; } zig_u128; | |
| 2029 | typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) uint64_t lo; int64_t hi; } zig_i128; | |
| 2030 | #else | |
| 2031 | typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) uint64_t hi; uint64_t lo; } zig_u128; | |
| 2032 | typedef struct { zig_align(ZIG_TARGET_MAX_INT_ALIGNMENT) int64_t hi; uint64_t lo; } zig_i128; | |
| 2033 | #endif | |
| 2034 | ||
| 2035 | #define zig_init_u128(hi, lo) { .h##i = hi, .l##o = lo } | |
| 2036 | #define zig_init_i128(hi, lo) { .h##i = hi, .l##o = lo } | |
| 2037 | #define zig_make_u128(hi, lo) (zig_u128)zig_init_u128(hi, lo) | |
| 2038 | #define zig_make_i128(hi, lo) (zig_i128)zig_init_i128(hi, lo) | |
| 2039 | #define zig_hi_u128(arg) (arg).hi | |
| 2040 | #define zig_lo_u128(arg) (arg).lo | |
| 2041 | #define zig_hi_i128(arg) (arg).hi | |
| 2042 | #define zig_lo_i128(arg) (arg).lo | |
| 1864 | 2043 | #define zig_cmp_int128(Type) \ |
| 1865 | 2044 | static inline int32_t zig_cmp_##Type(zig_##Type lhs, zig_##Type rhs) { \ |
| 1866 | 2045 | return (lhs.hi == rhs.hi) \ |
| ... | ... | @@ -1872,6 +2051,30 @@ typedef struct { zig_align(16) int64_t hi; uint64_t lo; } zig_i128; |
| 1872 | 2051 | return (zig_##Type){ .hi = lhs.hi operator rhs.hi, .lo = lhs.lo operator rhs.lo }; \ |
| 1873 | 2052 | } |
| 1874 | 2053 | |
| 2054 | static 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 | ||
| 2060 | static 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 | ||
| 2066 | static 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 | ||
| 2072 | static 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 | 2078 | #endif /* zig_has_int128 */ |
| 1876 | 2079 | |
| 1877 | 2080 | #define zig_minInt_u128 zig_make_u128(zig_minInt_u64, zig_minInt_u64) |
| ... | ... | @@ -1891,42 +2094,177 @@ zig_bit_int128(i128, or, |) |
| 1891 | 2094 | zig_bit_int128(u128, xor, ^) |
| 1892 | 2095 | zig_bit_int128(i128, xor, ^) |
| 1893 | 2096 | |
| 1894 | static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs); | |
| 2097 | static inline uint8_t zig_u8_intCast_u128(zig_u128 arg) { | |
| 2098 | return (uint8_t)zig_lo_u128(arg); | |
| 2099 | } | |
| 2100 | static inline uint8_t zig_u8_intCast_i128(zig_i128 arg) { | |
| 2101 | return (uint8_t)zig_lo_i128(arg); | |
| 2102 | } | |
| 2103 | static inline int8_t zig_i8_intCast_i128(zig_i128 arg) { | |
| 2104 | return (int8_t)zig_lo_i128(arg); | |
| 2105 | } | |
| 2106 | static inline int8_t zig_i8_intCast_u128(zig_u128 arg) { | |
| 2107 | return (int8_t)zig_lo_u128(arg); | |
| 2108 | } | |
| 1895 | 2109 | |
| 1896 | #if zig_has_int128 | |
| 2110 | static inline uint16_t zig_u16_intCast_u128(zig_u128 arg) { | |
| 2111 | return (uint16_t)zig_lo_u128(arg); | |
| 2112 | } | |
| 2113 | static inline uint16_t zig_u16_intCast_i128(zig_i128 arg) { | |
| 2114 | return (uint16_t)zig_lo_i128(arg); | |
| 2115 | } | |
| 2116 | static inline int16_t zig_i16_intCast_i128(zig_i128 arg) { | |
| 2117 | return (int16_t)zig_lo_i128(arg); | |
| 2118 | } | |
| 2119 | static inline int16_t zig_i16_intCast_u128(zig_u128 arg) { | |
| 2120 | return (int16_t)zig_lo_u128(arg); | |
| 2121 | } | |
| 1897 | 2122 | |
| 1898 | static inline zig_u128 zig_not_u128(zig_u128 val, uint8_t bits) { | |
| 1899 | return val ^ zig_maxInt_u(128, bits); | |
| 2123 | static inline uint32_t zig_u32_intCast_u128(zig_u128 arg) { | |
| 2124 | return (uint32_t)zig_lo_u128(arg); | |
| 2125 | } | |
| 2126 | static inline uint32_t zig_u32_intCast_i128(zig_i128 arg) { | |
| 2127 | return (uint32_t)zig_lo_i128(arg); | |
| 2128 | } | |
| 2129 | static inline int32_t zig_i32_intCast_i128(zig_i128 arg) { | |
| 2130 | return (int32_t)zig_lo_i128(arg); | |
| 2131 | } | |
| 2132 | static inline int32_t zig_i32_intCast_u128(zig_u128 arg) { | |
| 2133 | return (int32_t)zig_lo_u128(arg); | |
| 1900 | 2134 | } |
| 1901 | 2135 | |
| 1902 | static inline zig_i128 zig_not_i128(zig_i128 val, uint8_t bits) { | |
| 1903 | (void)bits; | |
| 1904 | return ~val; | |
| 2136 | static inline uint64_t zig_u64_intCast_u128(zig_u128 arg) { | |
| 2137 | return zig_lo_u128(arg); | |
| 2138 | } | |
| 2139 | static inline uint64_t zig_u64_intCast_i128(zig_i128 arg) { | |
| 2140 | return zig_lo_i128(arg); | |
| 2141 | } | |
| 2142 | static inline int64_t zig_i64_intCast_i128(zig_i128 arg) { | |
| 2143 | return (int64_t)zig_lo_i128(arg); | |
| 2144 | } | |
| 2145 | static inline int64_t zig_i64_intCast_u128(zig_u128 arg) { | |
| 2146 | return (int64_t)zig_lo_u128(arg); | |
| 1905 | 2147 | } |
| 1906 | 2148 | |
| 1907 | static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs) { | |
| 1908 | return lhs >> rhs; | |
| 2149 | static inline zig_u128 zig_u128_intCast_u8(uint8_t arg) { | |
| 2150 | return zig_make_u128(UINT8_C(0), arg); | |
| 2151 | } | |
| 2152 | static inline zig_u128 zig_u128_intCast_i8(int8_t arg) { | |
| 2153 | return zig_make_u128(UINT8_C(0), (uint8_t)arg); | |
| 2154 | } | |
| 2155 | static inline zig_i128 zig_i128_intCast_i8(int8_t arg) { | |
| 2156 | return zig_make_i128(zig_shr_i64(arg, 63), (uint8_t)arg); | |
| 2157 | } | |
| 2158 | static inline zig_i128 zig_i128_intCast_u8(uint8_t arg) { | |
| 2159 | return zig_make_i128(INT8_C(0), arg); | |
| 1909 | 2160 | } |
| 1910 | 2161 | |
| 1911 | static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) { | |
| 1912 | return lhs << rhs; | |
| 2162 | static inline zig_u128 zig_u128_intCast_u16(uint16_t arg) { | |
| 2163 | return zig_make_u128(UINT16_C(0), arg); | |
| 2164 | } | |
| 2165 | static inline zig_u128 zig_u128_intCast_i16(int16_t arg) { | |
| 2166 | return zig_make_u128(UINT16_C(0), (uint16_t)arg); | |
| 2167 | } | |
| 2168 | static inline zig_i128 zig_i128_intCast_i16(int16_t arg) { | |
| 2169 | return zig_make_i128(zig_shr_i64(arg, 63), (uint16_t)arg); | |
| 2170 | } | |
| 2171 | static inline zig_i128 zig_i128_intCast_u16(uint16_t arg) { | |
| 2172 | return zig_make_i128(INT16_C(0), arg); | |
| 1913 | 2173 | } |
| 1914 | 2174 | |
| 1915 | static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) { | |
| 1916 | // This works around a GCC miscompilation, but it has the side benefit of | |
| 1917 | // emitting better code. It is behind the `#if` because it depends on | |
| 1918 | // arithmetic right shift, which is implementation-defined in C, but should | |
| 1919 | // be guaranteed on any GCC-compatible compiler. | |
| 1920 | #if defined(zig_gnuc) | |
| 1921 | return lhs >> rhs; | |
| 2175 | static inline zig_u128 zig_u128_intCast_u32(uint32_t arg) { | |
| 2176 | return zig_make_u128(UINT32_C(0), arg); | |
| 2177 | } | |
| 2178 | static inline zig_u128 zig_u128_intCast_i32(int32_t arg) { | |
| 2179 | return zig_make_u128(UINT32_C(0), (uint32_t)arg); | |
| 2180 | } | |
| 2181 | static inline zig_i128 zig_i128_intCast_i32(int32_t arg) { | |
| 2182 | return zig_make_i128(zig_shr_i64(arg, 63), (uint32_t)arg); | |
| 2183 | } | |
| 2184 | static inline zig_i128 zig_i128_intCast_u32(uint32_t arg) { | |
| 2185 | return zig_make_i128(INT32_C(0), arg); | |
| 2186 | } | |
| 2187 | ||
| 2188 | static inline zig_u128 zig_u128_intCast_u64(uint64_t arg) { | |
| 2189 | return zig_make_u128(UINT64_C(0), arg); | |
| 2190 | } | |
| 2191 | static inline zig_u128 zig_u128_intCast_i64(int64_t arg) { | |
| 2192 | return zig_make_u128(UINT64_C(0), (uint64_t)arg); | |
| 2193 | } | |
| 2194 | static inline zig_i128 zig_i128_intCast_i64(int64_t arg) { | |
| 2195 | return zig_make_i128(zig_shr_i64(arg, 63), (uint64_t)arg); | |
| 2196 | } | |
| 2197 | static inline zig_i128 zig_i128_intCast_u64(uint64_t arg) { | |
| 2198 | return zig_make_i128(INT64_C(0), arg); | |
| 2199 | } | |
| 2200 | ||
| 2201 | static inline zig_u128 zig_u128_intCast_u128(zig_u128 arg) { | |
| 2202 | return arg; | |
| 2203 | } | |
| 2204 | static inline zig_u128 zig_u128_intCast_i128(zig_i128 arg) { | |
| 2205 | #if zig_has_int128 | |
| 2206 | return (zig_u128)arg; | |
| 1922 | 2207 | #else |
| 1923 | zig_i128 sign_mask = lhs < zig_make_i128(0, 0) ? -zig_make_i128(0, 1) : zig_make_i128(0, 0); | |
| 1924 | return ((lhs ^ sign_mask) >> rhs) ^ sign_mask; | |
| 2208 | return zig_make_u128(zig_u64_bitCast_i64(zig_hi_i128(arg), UINT8_C(64)), zig_lo_u128(arg)); | |
| 2209 | #endif | |
| 2210 | } | |
| 2211 | static inline zig_i128 zig_i128_intCast_i128(zig_i128 arg) { | |
| 2212 | return arg; | |
| 2213 | } | |
| 2214 | static 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 | 2219 | #endif |
| 1926 | 2220 | } |
| 1927 | 2221 | |
| 1928 | static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) { | |
| 1929 | return lhs << rhs; | |
| 2222 | #define zig_int128_cast_builtins(w) \ | |
| 2223 | static inline uint##w##_t zig_u##w##_truncate_u128(zig_u128 arg, uint8_t bits) { \ | |
| 2224 | return zig_u##w##_truncate_u##w((uint##w##_t)zig_lo_u128(arg), bits); \ | |
| 2225 | } \ | |
| 2226 | \ | |
| 2227 | static inline int##w##_t zig_i##w##_truncate_i128(zig_i128 arg, uint8_t bits) { \ | |
| 2228 | return zig_i##w##_truncate_i##w((int##w##_t)zig_lo_i128(arg), bits); \ | |
| 2229 | } | |
| 2230 | zig_int128_cast_builtins(8) | |
| 2231 | zig_int128_cast_builtins(16) | |
| 2232 | zig_int128_cast_builtins(32) | |
| 2233 | zig_int128_cast_builtins(64) | |
| 2234 | ||
| 2235 | static 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 | } | |
| 2238 | static 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 | ||
| 2244 | static inline zig_u128 zig_u128_bitCast_u128(zig_u128 arg, uint8_t bits) { | |
| 2245 | (void)bits; | |
| 2246 | return arg; | |
| 2247 | } | |
| 2248 | static 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 | } | |
| 2251 | static inline zig_i128 zig_i128_bitCast_i128(zig_i128 arg, uint8_t bits) { | |
| 2252 | (void)bits; | |
| 2253 | return arg; | |
| 2254 | } | |
| 2255 | static 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 | ||
| 2261 | static inline zig_u128 zig_not_u128(zig_u128 arg, uint8_t bits) { | |
| 2262 | return arg ^ zig_maxInt_u(128, bits); | |
| 2263 | } | |
| 2264 | ||
| 2265 | static inline zig_i128 zig_not_i128(zig_i128 arg, uint8_t bits) { | |
| 2266 | (void)bits; | |
| 2267 | return ~arg; | |
| 1930 | 2268 | } |
| 1931 | 2269 | |
| 1932 | 2270 | static inline zig_u128 zig_add_u128(zig_u128 lhs, zig_u128 rhs) { |
| ... | ... | @@ -1953,11 +2291,11 @@ static inline zig_i128 zig_mul_i128(zig_i128 lhs, zig_i128 rhs) { |
| 1953 | 2291 | return lhs * rhs; |
| 1954 | 2292 | } |
| 1955 | 2293 | |
| 1956 | static inline zig_u128 zig_div_trunc_u128(zig_u128 lhs, zig_u128 rhs) { | |
| 2294 | static inline zig_u128 zig_divTrunc_u128(zig_u128 lhs, zig_u128 rhs) { | |
| 1957 | 2295 | return lhs / rhs; |
| 1958 | 2296 | } |
| 1959 | 2297 | |
| 1960 | static inline zig_i128 zig_div_trunc_i128(zig_i128 lhs, zig_i128 rhs) { | |
| 2298 | static inline zig_i128 zig_divTrunc_i128(zig_i128 lhs, zig_i128 rhs) { | |
| 1961 | 2299 | return lhs / rhs; |
| 1962 | 2300 | } |
| 1963 | 2301 | |
| ... | ... | @@ -1971,36 +2309,14 @@ static inline zig_i128 zig_rem_i128(zig_i128 lhs, zig_i128 rhs) { |
| 1971 | 2309 | |
| 1972 | 2310 | #else /* zig_has_int128 */ |
| 1973 | 2311 | |
| 1974 | static inline zig_u128 zig_not_u128(zig_u128 val, uint8_t bits) { | |
| 1975 | return (zig_u128){ .hi = zig_not_u64(val.hi, bits - UINT8_C(64)), .lo = zig_not_u64(val.lo, UINT8_C(64)) }; | |
| 1976 | } | |
| 1977 | ||
| 1978 | static 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 | ||
| 1982 | static 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 | ||
| 1988 | static 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 | ||
| 1994 | static 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) }; | |
| 2312 | static inline zig_u128 zig_not_u128(zig_u128 arg, uint8_t bits) { | |
| 2313 | if (bits <= UINT8_C(64)) return (zig_u128){ .hi = UINT64_C(0), .lo = zig_not_u64(arg.lo, bits) }; | |
| 2314 | return (zig_u128){ .hi = zig_not_u64(arg.hi, bits - UINT8_C(64)), .lo = zig_not_u64(arg.lo, UINT8_C(64)) }; | |
| 1998 | 2315 | } |
| 1999 | 2316 | |
| 2000 | static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) { | |
| 2001 | if (rhs == UINT8_C(0)) return lhs; | |
| 2002 | if (rhs >= UINT8_C(64)) return (zig_i128){ .hi = lhs.lo << (rhs - UINT8_C(64)), .lo = zig_minInt_u64 }; | |
| 2003 | return (zig_i128){ .hi = lhs.hi << rhs | lhs.lo >> (UINT8_C(64) - rhs), .lo = lhs.lo << rhs }; | |
| 2317 | static inline zig_i128 zig_not_i128(zig_i128 arg, uint8_t bits) { | |
| 2318 | (void)bits; | |
| 2319 | return (zig_i128){ .hi = ~arg.hi, .lo = ~arg.lo }; | |
| 2004 | 2320 | } |
| 2005 | 2321 | |
| 2006 | 2322 | static inline zig_u128 zig_add_u128(zig_u128 lhs, zig_u128 rhs) { |
| ... | ... | @@ -2027,59 +2343,59 @@ static inline zig_i128 zig_sub_i128(zig_i128 lhs, zig_i128 rhs) { |
| 2027 | 2343 | return res; |
| 2028 | 2344 | } |
| 2029 | 2345 | |
| 2030 | zig_extern zig_i128 __multi3(zig_i128 lhs, zig_i128 rhs); | |
| 2031 | 2346 | static zig_i128 zig_mul_i128(zig_i128 lhs, zig_i128 rhs) { |
| 2347 | zig_extern zig_i128 __multi3(zig_i128 lhs, zig_i128 rhs); | |
| 2032 | 2348 | return __multi3(lhs, rhs); |
| 2033 | 2349 | } |
| 2034 | 2350 | |
| 2035 | 2351 | static 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 | } |
| 2038 | 2354 | |
| 2039 | zig_extern zig_u128 __udivti3(zig_u128 lhs, zig_u128 rhs); | |
| 2040 | static zig_u128 zig_div_trunc_u128(zig_u128 lhs, zig_u128 rhs) { | |
| 2355 | static zig_u128 zig_divTrunc_u128(zig_u128 lhs, zig_u128 rhs) { | |
| 2356 | zig_extern zig_u128 __udivti3(zig_u128 lhs, zig_u128 rhs); | |
| 2041 | 2357 | return __udivti3(lhs, rhs); |
| 2042 | 2358 | } |
| 2043 | 2359 | |
| 2044 | zig_extern zig_i128 __divti3(zig_i128 lhs, zig_i128 rhs); | |
| 2045 | static zig_i128 zig_div_trunc_i128(zig_i128 lhs, zig_i128 rhs) { | |
| 2360 | static zig_i128 zig_divTrunc_i128(zig_i128 lhs, zig_i128 rhs) { | |
| 2361 | zig_extern zig_i128 __divti3(zig_i128 lhs, zig_i128 rhs); | |
| 2046 | 2362 | return __divti3(lhs, rhs); |
| 2047 | 2363 | } |
| 2048 | 2364 | |
| 2049 | zig_extern zig_u128 __umodti3(zig_u128 lhs, zig_u128 rhs); | |
| 2050 | 2365 | static zig_u128 zig_rem_u128(zig_u128 lhs, zig_u128 rhs) { |
| 2366 | zig_extern zig_u128 __umodti3(zig_u128 lhs, zig_u128 rhs); | |
| 2051 | 2367 | return __umodti3(lhs, rhs); |
| 2052 | 2368 | } |
| 2053 | 2369 | |
| 2054 | zig_extern zig_i128 __modti3(zig_i128 lhs, zig_i128 rhs); | |
| 2055 | 2370 | static zig_i128 zig_rem_i128(zig_i128 lhs, zig_i128 rhs) { |
| 2371 | zig_extern zig_i128 __modti3(zig_i128 lhs, zig_i128 rhs); | |
| 2056 | 2372 | return __modti3(lhs, rhs); |
| 2057 | 2373 | } |
| 2058 | 2374 | |
| 2059 | 2375 | #endif /* zig_has_int128 */ |
| 2060 | 2376 | |
| 2061 | #define zig_div_floor_u128 zig_div_trunc_u128 | |
| 2377 | #define zig_divFloor_u128 zig_divTrunc_u128 | |
| 2062 | 2378 | |
| 2063 | static inline zig_i128 zig_div_floor_i128(zig_i128 lhs, zig_i128 rhs) { | |
| 2379 | static inline zig_i128 zig_divFloor_i128(zig_i128 lhs, zig_i128 rhs) { | |
| 2064 | 2380 | zig_i128 rem = zig_rem_i128(lhs, rhs); |
| 2065 | 2381 | int64_t mask = zig_or_u64((uint64_t)zig_hi_i128(rem), zig_lo_i128(rem)) != UINT64_C(0) |
| 2066 | 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 | } |
| 2069 | 2385 | |
| 2070 | static inline zig_u128 zig_div_ceil_u128(zig_u128 lhs, zig_u128 rhs) { | |
| 2386 | static inline zig_u128 zig_divCeil_u128(zig_u128 lhs, zig_u128 rhs) { | |
| 2071 | 2387 | zig_u128 rem = zig_rem_u128(lhs, rhs); |
| 2072 | 2388 | uint64_t mask = zig_or_u64(zig_hi_u128(rem), zig_lo_u128(rem)) != UINT64_C(0) |
| 2073 | 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 | } |
| 2076 | 2392 | |
| 2077 | static inline zig_i128 zig_div_ceil_i128(zig_i128 lhs, zig_i128 rhs) { | |
| 2393 | static inline zig_i128 zig_divCeil_i128(zig_i128 lhs, zig_i128 rhs) { | |
| 2078 | 2394 | zig_i128 rem = zig_rem_i128(lhs, rhs); |
| 2079 | 2395 | int64_t mask = zig_or_u64((uint64_t)zig_hi_i128(rem), zig_lo_i128(rem)) != UINT64_C(0) |
| 2080 | 2396 | ? zig_shr_i64(zig_xor_i64(zig_hi_i128(lhs), zig_hi_i128(rhs)), UINT8_C(63)) + INT64_C(1) |
| 2081 | 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 | } |
| 2084 | 2400 | |
| 2085 | 2401 | #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 | 2423 | return zig_cmp_i128(lhs, rhs) > INT32_C(0) ? lhs : rhs; |
| 2108 | 2424 | } |
| 2109 | 2425 | |
| 2110 | static 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 | ||
| 2114 | static 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 | ||
| 2120 | 2426 | static 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 | } |
| 2123 | 2429 | |
| 2124 | 2430 | static 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 | } |
| 2127 | 2433 | |
| 2128 | 2434 | static 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 | } |
| 2131 | 2437 | |
| 2132 | 2438 | static 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 | } |
| 2135 | 2441 | |
| 2136 | 2442 | static 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 | } |
| 2139 | 2445 | |
| 2140 | 2446 | static 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 | } |
| 2143 | 2449 | |
| 2144 | 2450 | static 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 | } |
| 2147 | 2453 | |
| 2148 | 2454 | static 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 | } |
| 2151 | 2457 | |
| 2152 | static inline zig_u128 zig_abs_i128(zig_i128 val) { | |
| 2153 | zig_i128 tmp = zig_shr_i128(val, 127); | |
| 2154 | return zig_bitCast_u128(zig_sub_i128(zig_xor_i128(val, tmp), tmp)); | |
| 2458 | static inline zig_u128 zig_abs_i128(zig_i128 arg) { | |
| 2459 | zig_u128 tmp = zig_u128_bitCast_i128(zig_shr_i128(arg, 127), UINT8_C(128)); | |
| 2460 | return zig_sub_u128(zig_xor_u128(zig_u128_bitCast_i128(arg, UINT8_C(128)), tmp), tmp); | |
| 2155 | 2461 | } |
| 2156 | 2462 | |
| 2157 | 2463 | #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 | 2466 | #if zig_has_builtin(add_overflow) |
| 2161 | 2467 | zig_u128 full_res; |
| 2162 | 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 | 2470 | return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits); |
| 2165 | 2471 | #else |
| 2166 | 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 | 2482 | zig_i128 full_res = (zig_i128)((zig_u128)lhs + (zig_u128)rhs); |
| 2177 | 2483 | bool overflow = ((full_res ^ lhs) & (full_res ^ rhs)) < 0; |
| 2178 | 2484 | #endif |
| 2179 | *res = zig_wrap_i128(full_res, bits); | |
| 2485 | *res = zig_i128_truncate_i128(full_res, bits); | |
| 2180 | 2486 | return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits); |
| 2181 | 2487 | } |
| 2182 | 2488 | |
| ... | ... | @@ -2184,7 +2490,7 @@ static inline bool zig_subo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint |
| 2184 | 2490 | #if zig_has_builtin(sub_overflow) |
| 2185 | 2491 | zig_u128 full_res; |
| 2186 | 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 | 2494 | return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits); |
| 2189 | 2495 | #else |
| 2190 | 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 | 2506 | zig_i128 full_res = (zig_i128)((zig_u128)lhs - (zig_u128)rhs); |
| 2201 | 2507 | bool overflow = ((lhs ^ rhs) & (full_res ^ lhs)) < 0; |
| 2202 | 2508 | #endif |
| 2203 | *res = zig_wrap_i128(full_res, bits); | |
| 2509 | *res = zig_i128_truncate_i128(full_res, bits); | |
| 2204 | 2510 | return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits); |
| 2205 | 2511 | } |
| 2206 | 2512 | |
| ... | ... | @@ -2208,7 +2514,7 @@ static inline bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint |
| 2208 | 2514 | #if zig_has_builtin(mul_overflow) |
| 2209 | 2515 | zig_u128 full_res; |
| 2210 | 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 | 2518 | return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits); |
| 2213 | 2519 | #else |
| 2214 | 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 | 2522 | #endif |
| 2217 | 2523 | } |
| 2218 | 2524 | |
| 2219 | zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow); | |
| 2220 | 2525 | static 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 | 2527 | #if zig_has_builtin(mul_overflow) |
| 2222 | 2528 | zig_i128 full_res; |
| 2223 | 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 | 2532 | zig_i128 full_res = __muloti4(lhs, rhs, &overflow_int); |
| 2227 | 2533 | bool overflow = overflow_int != 0; |
| 2228 | 2534 | #endif |
| 2229 | *res = zig_wrap_i128(full_res, bits); | |
| 2535 | *res = zig_i128_truncate_i128(full_res, bits); | |
| 2230 | 2536 | return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits); |
| 2231 | 2537 | } |
| 2232 | 2538 | |
| 2233 | 2539 | #else /* zig_has_int128 */ |
| 2234 | 2540 | |
| 2235 | 2541 | static inline bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) { |
| 2236 | uint64_t hi; | |
| 2237 | bool overflow = zig_addo_u64(&hi, lhs.hi, rhs.hi, bits - 64); | |
| 2238 | return overflow ^ zig_addo_u64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64); | |
| 2542 | if (bits <= UINT8_C(64)) { | |
| 2543 | uint64_t lo; | |
| 2544 | bool overflow = zig_addo_u64(&lo, zig_u64_intCast_u128(lhs), zig_u64_intCast_u128(rhs), bits); | |
| 2545 | *res = zig_u128_intCast_u64(lo); | |
| 2546 | return overflow; | |
| 2547 | } else { | |
| 2548 | uint64_t hi; | |
| 2549 | bool overflow = zig_addo_u64(&hi, lhs.hi, rhs.hi, bits - UINT8_C(64)); | |
| 2550 | return overflow ^ zig_addo_u64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, UINT8_C(64)), bits - UINT8_C(64)); | |
| 2551 | } | |
| 2239 | 2552 | } |
| 2240 | 2553 | |
| 2241 | 2554 | static inline bool zig_addo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) { |
| 2242 | int64_t hi; | |
| 2243 | bool overflow = zig_addo_i64(&hi, lhs.hi, rhs.hi, bits - 64); | |
| 2244 | return overflow ^ zig_addo_i64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64); | |
| 2555 | if (bits <= UINT8_C(64)) { | |
| 2556 | int64_t lo; | |
| 2557 | bool overflow = zig_addo_i64(&lo, zig_i64_intCast_i128(lhs), zig_i64_intCast_i128(rhs), bits); | |
| 2558 | *res = zig_i128_intCast_i64(lo); | |
| 2559 | return overflow; | |
| 2560 | } else { | |
| 2561 | int64_t hi; | |
| 2562 | bool overflow = zig_addo_i64(&hi, lhs.hi, rhs.hi, bits - UINT8_C(64)); | |
| 2563 | return overflow ^ zig_addo_i64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, UINT8_C(64)), bits - UINT8_C(64)); | |
| 2564 | } | |
| 2245 | 2565 | } |
| 2246 | 2566 | |
| 2247 | 2567 | static inline bool zig_subo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) { |
| 2248 | uint64_t hi; | |
| 2249 | bool overflow = zig_subo_u64(&hi, lhs.hi, rhs.hi, bits - 64); | |
| 2250 | return overflow ^ zig_subo_u64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64); | |
| 2568 | if (bits <= UINT8_C(64)) { | |
| 2569 | uint64_t lo; | |
| 2570 | bool overflow = zig_subo_u64(&lo, zig_u64_intCast_u128(lhs), zig_u64_intCast_u128(rhs), bits); | |
| 2571 | *res = zig_u128_intCast_u64(lo); | |
| 2572 | return overflow; | |
| 2573 | } else { | |
| 2574 | uint64_t hi; | |
| 2575 | bool overflow = zig_subo_u64(&hi, lhs.hi, rhs.hi, bits - UINT8_C(64)); | |
| 2576 | return overflow ^ zig_subo_u64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, UINT8_C(64)), bits - UINT8_C(64)); | |
| 2577 | } | |
| 2251 | 2578 | } |
| 2252 | 2579 | |
| 2253 | 2580 | static inline bool zig_subo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) { |
| 2254 | int64_t hi; | |
| 2255 | bool overflow = zig_subo_i64(&hi, lhs.hi, rhs.hi, bits - 64); | |
| 2256 | return overflow ^ zig_subo_i64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64); | |
| 2581 | if (bits <= UINT8_C(64)) { | |
| 2582 | int64_t lo; | |
| 2583 | bool overflow = zig_subo_i64(&lo, zig_i64_intCast_i128(lhs), zig_i64_intCast_i128(rhs), bits); | |
| 2584 | *res = zig_i128_intCast_i64(lo); | |
| 2585 | return overflow; | |
| 2586 | } else { | |
| 2587 | int64_t hi; | |
| 2588 | bool overflow = zig_subo_i64(&hi, lhs.hi, rhs.hi, bits - UINT8_C(64)); | |
| 2589 | return overflow ^ zig_subo_i64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, UINT8_C(64)), bits - UINT8_C(64)); | |
| 2590 | } | |
| 2257 | 2591 | } |
| 2258 | 2592 | |
| 2259 | 2593 | static inline bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) { |
| 2260 | 2594 | *res = zig_mulw_u128(lhs, rhs, bits); |
| 2261 | return zig_cmp_u128(*res, zig_make_u128(0, 0)) != INT32_C(0) && | |
| 2262 | zig_cmp_u128(lhs, zig_div_trunc_u128(zig_maxInt_u(128, bits), rhs)) > INT32_C(0); | |
| 2595 | return zig_cmp_u128(rhs, zig_make_u128(0, 0)) != INT32_C(0) && | |
| 2596 | zig_cmp_u128(lhs, zig_divTrunc_u128(zig_maxInt_u(128, bits), rhs)) > INT32_C(0); | |
| 2263 | 2597 | } |
| 2264 | 2598 | |
| 2265 | zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow); | |
| 2266 | 2599 | static 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 | 2601 | int overflow_int; |
| 2268 | 2602 | zig_i128 full_res = __muloti4(lhs, rhs, &overflow_int); |
| 2269 | 2603 | bool overflow = overflow_int != 0 || |
| 2270 | 2604 | zig_cmp_i128(full_res, zig_minInt_i(128, bits)) < INT32_C(0) || |
| 2271 | 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 | 2607 | return overflow; |
| 2274 | 2608 | } |
| 2275 | 2609 | |
| ... | ... | @@ -2282,28 +2616,54 @@ static inline bool zig_shlo_u128(zig_u128 *res, zig_u128 lhs, uint8_t rhs, uint8 |
| 2282 | 2616 | |
| 2283 | 2617 | static inline bool zig_shlo_i128(zig_i128 *res, zig_i128 lhs, uint8_t rhs, uint8_t bits) { |
| 2284 | 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 | 2620 | return zig_cmp_i128(zig_and_i128(lhs, mask), zig_make_i128(0, 0)) != INT32_C(0) && |
| 2287 | 2621 | zig_cmp_i128(zig_and_i128(lhs, mask), mask) != INT32_C(0); |
| 2288 | 2622 | } |
| 2289 | 2623 | |
| 2290 | static 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 | } | |
| 2645 | zig_int128_shls_builtins(8) | |
| 2646 | zig_int128_shls_builtins(16) | |
| 2647 | zig_int128_shls_builtins(32) | |
| 2648 | zig_int128_shls_builtins(64) | |
| 2649 | ||
| 2650 | static inline zig_u128 zig_shls_u128_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) { | |
| 2291 | 2651 | zig_u128 res; |
| 2292 | 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 | 2653 | switch (zig_cmp_u128(lhs, zig_make_u128(0, 0))) { |
| 2294 | case 0: return zig_make_u128(0, 0); | |
| 2295 | case 1: return zig_maxInt_u(128, bits); | |
| 2654 | case INT32_C(0): return zig_make_u128(0, 0); | |
| 2655 | case INT32_C(1): return zig_maxInt_u(128, bits); | |
| 2296 | 2656 | default: zig_unreachable(); |
| 2297 | 2657 | } |
| 2298 | 2658 | } |
| 2299 | 2659 | |
| 2300 | static inline zig_i128 zig_shls_i128(zig_i128 lhs, zig_u128 rhs, uint8_t bits) { | |
| 2660 | static inline zig_i128 zig_shls_i128_u128(zig_i128 lhs, zig_u128 rhs, uint8_t bits) { | |
| 2301 | 2661 | zig_i128 res; |
| 2302 | 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 | 2663 | switch (zig_cmp_i128(lhs, zig_make_i128(0, 0))) { |
| 2304 | case -1: return zig_minInt_i(128, bits); | |
| 2305 | case 0: return zig_make_i128(0, 0); | |
| 2306 | case 1: return zig_maxInt_i(128, bits); | |
| 2664 | case -INT32_C(1): return zig_minInt_i(128, bits); | |
| 2665 | case INT32_C(0): return zig_make_i128(0, 0); | |
| 2666 | case INT32_C(1): return zig_maxInt_i(128, bits); | |
| 2307 | 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 | 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 | } |
| 2343 | 2703 | |
| 2344 | static inline uint8_t zig_clz_u128(zig_u128 val, uint8_t bits) { | |
| 2345 | if (bits <= UINT8_C(64)) return zig_clz_u64(zig_lo_u128(val), bits); | |
| 2346 | if (zig_hi_u128(val) != 0) return zig_clz_u64(zig_hi_u128(val), bits - UINT8_C(64)); | |
| 2347 | return zig_clz_u64(zig_lo_u128(val), UINT8_C(64)) + (bits - UINT8_C(64)); | |
| 2704 | static inline uint8_t zig_clz_u128(zig_u128 arg, uint8_t bits) { | |
| 2705 | if (bits <= UINT8_C(64)) return zig_clz_u64(zig_lo_u128(arg), bits); | |
| 2706 | if (zig_hi_u128(arg) != 0) return zig_clz_u64(zig_hi_u128(arg), bits - UINT8_C(64)); | |
| 2707 | return zig_clz_u64(zig_lo_u128(arg), UINT8_C(64)) + (bits - UINT8_C(64)); | |
| 2348 | 2708 | } |
| 2349 | 2709 | |
| 2350 | static inline uint8_t zig_clz_i128(zig_i128 val, uint8_t bits) { | |
| 2351 | return zig_clz_u128(zig_bitCast_u128(val), bits); | |
| 2710 | static inline uint8_t zig_clz_i128(zig_i128 arg, uint8_t bits) { | |
| 2711 | return zig_clz_u128(zig_u128_bitCast_i128(arg, bits), bits); | |
| 2352 | 2712 | } |
| 2353 | 2713 | |
| 2354 | static inline uint8_t zig_ctz_u128(zig_u128 val, uint8_t bits) { | |
| 2355 | if (zig_lo_u128(val) != 0) return zig_ctz_u64(zig_lo_u128(val), UINT8_C(64)); | |
| 2356 | return zig_ctz_u64(zig_hi_u128(val), bits - UINT8_C(64)) + UINT8_C(64); | |
| 2714 | static inline uint8_t zig_ctz_u128(zig_u128 arg, uint8_t bits) { | |
| 2715 | if (zig_lo_u128(arg) != 0) return zig_ctz_u64(zig_lo_u128(arg), UINT8_C(64)); | |
| 2716 | return zig_ctz_u64(zig_hi_u128(arg), bits - UINT8_C(64)) + UINT8_C(64); | |
| 2357 | 2717 | } |
| 2358 | 2718 | |
| 2359 | static inline uint8_t zig_ctz_i128(zig_i128 val, uint8_t bits) { | |
| 2360 | return zig_ctz_u128(zig_bitCast_u128(val), bits); | |
| 2719 | static inline uint8_t zig_ctz_i128(zig_i128 arg, uint8_t bits) { | |
| 2720 | return zig_ctz_u128(zig_u128_bitCast_i128(arg, bits), bits); | |
| 2361 | 2721 | } |
| 2362 | 2722 | |
| 2363 | static inline uint8_t zig_popcount_u128(zig_u128 val, uint8_t bits) { | |
| 2364 | return zig_popcount_u64(zig_hi_u128(val), bits - UINT8_C(64)) + | |
| 2365 | zig_popcount_u64(zig_lo_u128(val), UINT8_C(64)); | |
| 2723 | static inline uint8_t zig_popCount_u128(zig_u128 arg, uint8_t bits) { | |
| 2724 | return (bits > UINT8_C(64) ? zig_popCount_u64(zig_hi_u128(arg), bits - UINT8_C(64)) : UINT8_C(0)) + | |
| 2725 | zig_popCount_u64(zig_lo_u128(arg), UINT8_C(64)); | |
| 2366 | 2726 | } |
| 2367 | 2727 | |
| 2368 | static inline uint8_t zig_popcount_i128(zig_i128 val, uint8_t bits) { | |
| 2369 | return zig_popcount_u128(zig_bitCast_u128(val), bits); | |
| 2728 | static inline uint8_t zig_popCount_i128(zig_i128 arg, uint8_t bits) { | |
| 2729 | return zig_popCount_u128(zig_u128_bitCast_i128(arg, bits), bits); | |
| 2370 | 2730 | } |
| 2371 | 2731 | |
| 2372 | static inline zig_u128 zig_byte_swap_u128(zig_u128 val, uint8_t bits) { | |
| 2732 | static inline zig_u128 zig_byteSwap_u128(zig_u128 arg, uint8_t bits) { | |
| 2373 | 2733 | zig_u128 full_res; |
| 2374 | 2734 | #if zig_has_builtin(bswap128) |
| 2375 | full_res = __builtin_bswap128(val); | |
| 2735 | full_res = __builtin_bswap128(arg); | |
| 2376 | 2736 | #else |
| 2377 | full_res = zig_make_u128(zig_byte_swap_u64(zig_lo_u128(val), UINT8_C(64)), | |
| 2378 | zig_byte_swap_u64(zig_hi_u128(val), UINT8_C(64))); | |
| 2737 | full_res = zig_make_u128( | |
| 2738 | zig_byteSwap_u64(zig_lo_u128(arg), UINT8_C(64)), | |
| 2739 | zig_byteSwap_u64(zig_hi_u128(arg), UINT8_C(64)) | |
| 2740 | ); | |
| 2379 | 2741 | #endif |
| 2380 | 2742 | return zig_shr_u128(full_res, UINT8_C(128) - bits); |
| 2381 | 2743 | } |
| 2382 | 2744 | |
| 2383 | static inline zig_i128 zig_byte_swap_i128(zig_i128 val, uint8_t bits) { | |
| 2384 | return zig_bitCast_i128(zig_byte_swap_u128(zig_bitCast_u128(val), bits)); | |
| 2745 | static inline zig_i128 zig_byteSwap_i128(zig_i128 arg, uint8_t bits) { | |
| 2746 | return zig_i128_bitCast_u128(zig_byteSwap_u128(zig_u128_bitCast_i128(arg, bits), bits), bits); | |
| 2385 | 2747 | } |
| 2386 | 2748 | |
| 2387 | static inline zig_u128 zig_bit_reverse_u128(zig_u128 val, uint8_t bits) { | |
| 2388 | return zig_shr_u128(zig_make_u128(zig_bit_reverse_u64(zig_lo_u128(val), UINT8_C(64)), | |
| 2389 | zig_bit_reverse_u64(zig_hi_u128(val), UINT8_C(64))), | |
| 2390 | UINT8_C(128) - bits); | |
| 2749 | static inline zig_u128 zig_bitReverse_u128(zig_u128 arg, uint8_t bits) { | |
| 2750 | return zig_shr_u128(zig_make_u128( | |
| 2751 | zig_bitReverse_u64(zig_lo_u128(arg), UINT8_C(64)), | |
| 2752 | zig_bitReverse_u64(zig_hi_u128(arg), UINT8_C(64)) | |
| 2753 | ), UINT8_C(128) - bits); | |
| 2391 | 2754 | } |
| 2392 | 2755 | |
| 2393 | static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, uint8_t bits) { | |
| 2394 | return zig_bitCast_i128(zig_bit_reverse_u128(zig_bitCast_u128(val), bits)); | |
| 2756 | static inline zig_i128 zig_bitReverse_i128(zig_i128 arg, uint8_t bits) { | |
| 2757 | return zig_i128_bitCast_u128(zig_bitReverse_u128(zig_u128_bitCast_i128(arg, bits), bits), bits); | |
| 2395 | 2758 | } |
| 2396 | 2759 | |
| 2397 | 2760 | #if zig_has_int128 |
| ... | ... | @@ -2411,15 +2774,218 @@ static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, uint8_t bits) { |
| 2411 | 2774 | /* ========================== Big Integer Support =========================== */ |
| 2412 | 2775 | |
| 2413 | 2776 | static 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 | 2778 | uint16_t alignment = ZIG_TARGET_MAX_INT_ALIGNMENT; |
| 2779 | ||
| 2416 | 2780 | while (alignment / 2 >= bytes) alignment /= 2; |
| 2417 | 2781 | return (bytes + alignment - 1) / alignment * alignment; |
| 2418 | 2782 | } |
| 2419 | 2783 | |
| 2420 | static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { | |
| 2784 | static 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 | ||
| 2816 | static 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 | ||
| 2848 | static 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 | ||
| 2859 | static inline void zig_big_intCast_big(void *res, const void *arg, bool res_is_signed, uint16_t res_bits, bool arg_is_signed, uint16_t arg_bits) { | |
| 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 | ||
| 2876 | static inline void zig_big_truncate_big(void *res, const void *arg, bool res_is_signed, uint16_t res_bits, bool arg_is_signed, uint16_t arg_bits) { | |
| 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 | } | |
| 2940 | zig_big_casts(false, u, 8, uint8_t) | |
| 2941 | zig_big_casts(true , i, 8, int8_t) | |
| 2942 | zig_big_casts(false, u, 16, uint16_t) | |
| 2943 | zig_big_casts(true , i, 16, int16_t) | |
| 2944 | zig_big_casts(false, u, 32, uint32_t) | |
| 2945 | zig_big_casts(true , i, 32, int32_t) | |
| 2946 | zig_big_casts(false, u, 64, uint64_t) | |
| 2947 | zig_big_casts(true , i, 64, int64_t) | |
| 2948 | zig_big_casts(false, u, 128, zig_u128) | |
| 2949 | zig_big_casts(true , i, 128, zig_i128) | |
| 2950 | ||
| 2951 | static 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 | ||
| 2987 | static inline int32_t zig_cmp_big_u8(const void *lhs, uint8_t rhs, bool is_signed, uint16_t bits) { | |
| 2421 | 2988 | const uint8_t *lhs_bytes = lhs; |
| 2422 | const uint8_t *rhs_bytes = rhs; | |
| 2423 | 2989 | uint16_t byte_offset = 0; |
| 2424 | 2990 | bool do_signed = is_signed; |
| 2425 | 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 | 2995 | #endif |
| 2430 | 2996 | |
| 2431 | 2997 | while (remaining_bytes >= 128 / CHAR_BIT) { |
| 2998 | uint8_t rhs_byte = remaining_bytes == 128 / CHAR_BIT ? rhs : UINT8_C(0); | |
| 2432 | 2999 | int32_t limb_cmp; |
| 2433 | 3000 | |
| 2434 | 3001 | #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 | 3004 | |
| 2438 | 3005 | if (do_signed) { |
| 2439 | 3006 | zig_i128 lhs_limb; |
| 2440 | zig_i128 rhs_limb; | |
| 3007 | zig_i128 rhs_limb = zig_i128_intCast_u8(rhs_byte); | |
| 2441 | 3008 | |
| 2442 | 3009 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); |
| 2443 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 2444 | 3010 | limb_cmp = zig_cmp_i128(lhs_limb, rhs_limb); |
| 2445 | 3011 | do_signed = false; |
| 2446 | 3012 | } else { |
| 2447 | 3013 | zig_u128 lhs_limb; |
| 2448 | zig_u128 rhs_limb; | |
| 3014 | zig_u128 rhs_limb = zig_u128_intCast_u8(rhs_byte); | |
| 2449 | 3015 | |
| 2450 | 3016 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); |
| 2451 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 2452 | 3017 | limb_cmp = zig_cmp_u128(lhs_limb, rhs_limb); |
| 2453 | 3018 | } |
| 2454 | 3019 | |
| ... | ... | @@ -2461,24 +3026,24 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign |
| 2461 | 3026 | } |
| 2462 | 3027 | |
| 2463 | 3028 | while (remaining_bytes >= 64 / CHAR_BIT) { |
| 3029 | uint8_t rhs_byte = remaining_bytes == 64 / CHAR_BIT ? rhs : UINT8_C(0); | |
| 3030 | ||
| 2464 | 3031 | #if zig_little_endian |
| 2465 | 3032 | byte_offset -= 64 / CHAR_BIT; |
| 2466 | 3033 | #endif |
| 2467 | 3034 | |
| 2468 | 3035 | if (do_signed) { |
| 2469 | 3036 | int64_t lhs_limb; |
| 2470 | int64_t rhs_limb; | |
| 3037 | int64_t rhs_limb = zig_i64_intCast_u8(rhs_byte); | |
| 2471 | 3038 | |
| 2472 | 3039 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); |
| 2473 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 2474 | 3040 | if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); |
| 2475 | 3041 | do_signed = false; |
| 2476 | 3042 | } else { |
| 2477 | 3043 | uint64_t lhs_limb; |
| 2478 | uint64_t rhs_limb; | |
| 3044 | uint64_t rhs_limb = zig_u64_intCast_u8(rhs_byte); | |
| 2479 | 3045 | |
| 2480 | 3046 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); |
| 2481 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 2482 | 3047 | if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); |
| 2483 | 3048 | } |
| 2484 | 3049 | |
| ... | ... | @@ -2490,24 +3055,24 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign |
| 2490 | 3055 | } |
| 2491 | 3056 | |
| 2492 | 3057 | while (remaining_bytes >= 32 / CHAR_BIT) { |
| 3058 | uint8_t rhs_byte = remaining_bytes == 32 / CHAR_BIT ? rhs : UINT8_C(0); | |
| 3059 | ||
| 2493 | 3060 | #if zig_little_endian |
| 2494 | 3061 | byte_offset -= 32 / CHAR_BIT; |
| 2495 | 3062 | #endif |
| 2496 | 3063 | |
| 2497 | 3064 | if (do_signed) { |
| 2498 | 3065 | int32_t lhs_limb; |
| 2499 | int32_t rhs_limb; | |
| 3066 | int32_t rhs_limb = zig_i32_intCast_u8(rhs_byte); | |
| 2500 | 3067 | |
| 2501 | 3068 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); |
| 2502 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 2503 | 3069 | if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); |
| 2504 | 3070 | do_signed = false; |
| 2505 | 3071 | } else { |
| 2506 | 3072 | uint32_t lhs_limb; |
| 2507 | uint32_t rhs_limb; | |
| 3073 | uint32_t rhs_limb = zig_u32_intCast_u8(rhs_byte); | |
| 2508 | 3074 | |
| 2509 | 3075 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); |
| 2510 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 2511 | 3076 | if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); |
| 2512 | 3077 | } |
| 2513 | 3078 | |
| ... | ... | @@ -2519,24 +3084,24 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign |
| 2519 | 3084 | } |
| 2520 | 3085 | |
| 2521 | 3086 | while (remaining_bytes >= 16 / CHAR_BIT) { |
| 3087 | uint8_t rhs_byte = remaining_bytes == 16 / CHAR_BIT ? rhs : UINT8_C(0); | |
| 3088 | ||
| 2522 | 3089 | #if zig_little_endian |
| 2523 | 3090 | byte_offset -= 16 / CHAR_BIT; |
| 2524 | 3091 | #endif |
| 2525 | 3092 | |
| 2526 | 3093 | if (do_signed) { |
| 2527 | 3094 | int16_t lhs_limb; |
| 2528 | int16_t rhs_limb; | |
| 3095 | int16_t rhs_limb = zig_i16_intCast_u8(rhs_byte); | |
| 2529 | 3096 | |
| 2530 | 3097 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); |
| 2531 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 2532 | 3098 | if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); |
| 2533 | 3099 | do_signed = false; |
| 2534 | 3100 | } else { |
| 2535 | 3101 | uint16_t lhs_limb; |
| 2536 | uint16_t rhs_limb; | |
| 3102 | uint16_t rhs_limb = zig_u16_intCast_u8(rhs_byte); | |
| 2537 | 3103 | |
| 2538 | 3104 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); |
| 2539 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 2540 | 3105 | if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); |
| 2541 | 3106 | } |
| 2542 | 3107 | |
| ... | ... | @@ -2548,24 +3113,26 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign |
| 2548 | 3113 | } |
| 2549 | 3114 | |
| 2550 | 3115 | while (remaining_bytes >= 8 / CHAR_BIT) { |
| 3116 | uint8_t rhs_byte = remaining_bytes == 16 / CHAR_BIT ? rhs : UINT8_C(0); | |
| 3117 | ||
| 2551 | 3118 | #if zig_little_endian |
| 2552 | 3119 | byte_offset -= 8 / CHAR_BIT; |
| 2553 | 3120 | #endif |
| 2554 | 3121 | |
| 2555 | 3122 | if (do_signed) { |
| 2556 | 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); | |
| 2558 | 3126 | |
| 2559 | 3127 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); |
| 2560 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 2561 | if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); | |
| 3128 | lhs_cmp_limb = zig_i16_intCast_i8(lhs_limb); | |
| 3129 | if (lhs_cmp_limb != rhs_cmp_limb) return (lhs_cmp_limb > rhs_cmp_limb) - (lhs_cmp_limb < rhs_cmp_limb); | |
| 2562 | 3130 | do_signed = false; |
| 2563 | 3131 | } else { |
| 2564 | 3132 | uint8_t lhs_limb; |
| 2565 | uint8_t rhs_limb; | |
| 3133 | uint8_t rhs_limb = rhs_byte; | |
| 2566 | 3134 | |
| 2567 | 3135 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); |
| 2568 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 2569 | 3136 | if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); |
| 2570 | 3137 | } |
| 2571 | 3138 | |
| ... | ... | @@ -2579,148 +3146,472 @@ static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_sign |
| 2579 | 3146 | return 0; |
| 2580 | 3147 | } |
| 2581 | 3148 | |
| 2582 | static inline void zig_and_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { | |
| 2583 | uint8_t *res_bytes = res; | |
| 3149 | static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { | |
| 2584 | 3150 | const uint8_t *lhs_bytes = lhs; |
| 2585 | 3151 | const uint8_t *rhs_bytes = rhs; |
| 2586 | 3152 | uint16_t byte_offset = 0; |
| 3153 | bool do_signed = is_signed; | |
| 2587 | 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 | |
| 2589 | 3159 | |
| 2590 | 3160 | while (remaining_bytes >= 128 / CHAR_BIT) { |
| 2591 | zig_u128 res_limb; | |
| 2592 | zig_u128 lhs_limb; | |
| 2593 | zig_u128 rhs_limb; | |
| 3161 | int32_t limb_cmp; | |
| 2594 | 3162 | |
| 2595 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); | |
| 2596 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 2597 | res_limb = zig_and_u128(lhs_limb, rhs_limb); | |
| 2598 | memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); | |
| 3163 | #if zig_little_endian | |
| 3164 | byte_offset -= 128 / CHAR_BIT; | |
| 3165 | #endif | |
| 3166 | ||
| 3167 | if (do_signed) { | |
| 3168 | zig_i128 lhs_limb; | |
| 3169 | zig_i128 rhs_limb; | |
| 3170 | ||
| 3171 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); | |
| 3172 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 3173 | limb_cmp = zig_cmp_i128(lhs_limb, rhs_limb); | |
| 3174 | do_signed = false; | |
| 3175 | } else { | |
| 3176 | zig_u128 lhs_limb; | |
| 3177 | zig_u128 rhs_limb; | |
| 3178 | ||
| 3179 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); | |
| 3180 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 3181 | limb_cmp = zig_cmp_u128(lhs_limb, rhs_limb); | |
| 3182 | } | |
| 2599 | 3183 | |
| 3184 | if (limb_cmp != 0) return limb_cmp; | |
| 2600 | 3185 | remaining_bytes -= 128 / CHAR_BIT; |
| 3186 | ||
| 3187 | #if zig_big_endian | |
| 2601 | 3188 | byte_offset += 128 / CHAR_BIT; |
| 3189 | #endif | |
| 2602 | 3190 | } |
| 2603 | 3191 | |
| 2604 | 3192 | while (remaining_bytes >= 64 / CHAR_BIT) { |
| 2605 | uint64_t res_limb; | |
| 2606 | uint64_t lhs_limb; | |
| 2607 | uint64_t rhs_limb; | |
| 3193 | #if zig_little_endian | |
| 3194 | byte_offset -= 64 / CHAR_BIT; | |
| 3195 | #endif | |
| 2608 | 3196 | |
| 2609 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); | |
| 2610 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 2611 | res_limb = zig_and_u64(lhs_limb, rhs_limb); | |
| 2612 | memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); | |
| 3197 | if (do_signed) { | |
| 3198 | int64_t lhs_limb; | |
| 3199 | int64_t rhs_limb; | |
| 3200 | ||
| 3201 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); | |
| 3202 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 3203 | if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); | |
| 3204 | do_signed = false; | |
| 3205 | } else { | |
| 3206 | uint64_t lhs_limb; | |
| 3207 | uint64_t rhs_limb; | |
| 3208 | ||
| 3209 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); | |
| 3210 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 3211 | if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); | |
| 3212 | } | |
| 2613 | 3213 | |
| 2614 | 3214 | remaining_bytes -= 64 / CHAR_BIT; |
| 3215 | ||
| 3216 | #if zig_big_endian | |
| 2615 | 3217 | byte_offset += 64 / CHAR_BIT; |
| 3218 | #endif | |
| 2616 | 3219 | } |
| 2617 | 3220 | |
| 2618 | 3221 | while (remaining_bytes >= 32 / CHAR_BIT) { |
| 2619 | uint32_t res_limb; | |
| 2620 | uint32_t lhs_limb; | |
| 2621 | uint32_t rhs_limb; | |
| 3222 | #if zig_little_endian | |
| 3223 | byte_offset -= 32 / CHAR_BIT; | |
| 3224 | #endif | |
| 2622 | 3225 | |
| 2623 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); | |
| 2624 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 2625 | res_limb = zig_and_u32(lhs_limb, rhs_limb); | |
| 2626 | memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); | |
| 3226 | if (do_signed) { | |
| 3227 | int32_t lhs_limb; | |
| 3228 | int32_t rhs_limb; | |
| 3229 | ||
| 3230 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); | |
| 3231 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 3232 | if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); | |
| 3233 | do_signed = false; | |
| 3234 | } else { | |
| 3235 | uint32_t lhs_limb; | |
| 3236 | uint32_t rhs_limb; | |
| 3237 | ||
| 3238 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); | |
| 3239 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 3240 | if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); | |
| 3241 | } | |
| 2627 | 3242 | |
| 2628 | 3243 | remaining_bytes -= 32 / CHAR_BIT; |
| 3244 | ||
| 3245 | #if zig_big_endian | |
| 2629 | 3246 | byte_offset += 32 / CHAR_BIT; |
| 3247 | #endif | |
| 2630 | 3248 | } |
| 2631 | 3249 | |
| 2632 | 3250 | while (remaining_bytes >= 16 / CHAR_BIT) { |
| 2633 | uint16_t res_limb; | |
| 2634 | uint16_t lhs_limb; | |
| 2635 | uint16_t rhs_limb; | |
| 3251 | #if zig_little_endian | |
| 3252 | byte_offset -= 16 / CHAR_BIT; | |
| 3253 | #endif | |
| 2636 | 3254 | |
| 2637 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); | |
| 2638 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 2639 | res_limb = zig_and_u16(lhs_limb, rhs_limb); | |
| 2640 | memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); | |
| 3255 | if (do_signed) { | |
| 3256 | int16_t lhs_limb; | |
| 3257 | int16_t rhs_limb; | |
| 3258 | ||
| 3259 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); | |
| 3260 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 3261 | if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); | |
| 3262 | do_signed = false; | |
| 3263 | } else { | |
| 3264 | uint16_t lhs_limb; | |
| 3265 | uint16_t rhs_limb; | |
| 3266 | ||
| 3267 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); | |
| 3268 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 3269 | if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); | |
| 3270 | } | |
| 2641 | 3271 | |
| 2642 | 3272 | remaining_bytes -= 16 / CHAR_BIT; |
| 3273 | ||
| 3274 | #if zig_big_endian | |
| 2643 | 3275 | byte_offset += 16 / CHAR_BIT; |
| 3276 | #endif | |
| 2644 | 3277 | } |
| 2645 | 3278 | |
| 2646 | 3279 | while (remaining_bytes >= 8 / CHAR_BIT) { |
| 2647 | uint8_t res_limb; | |
| 2648 | uint8_t lhs_limb; | |
| 2649 | uint8_t rhs_limb; | |
| 3280 | #if zig_little_endian | |
| 3281 | byte_offset -= 8 / CHAR_BIT; | |
| 3282 | #endif | |
| 2650 | 3283 | |
| 2651 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); | |
| 2652 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 2653 | res_limb = zig_and_u8(lhs_limb, rhs_limb); | |
| 2654 | memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); | |
| 3284 | if (do_signed) { | |
| 3285 | int8_t lhs_limb; | |
| 3286 | int8_t rhs_limb; | |
| 3287 | ||
| 3288 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); | |
| 3289 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 3290 | if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); | |
| 3291 | do_signed = false; | |
| 3292 | } else { | |
| 3293 | uint8_t lhs_limb; | |
| 3294 | uint8_t rhs_limb; | |
| 3295 | ||
| 3296 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); | |
| 3297 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 3298 | if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb); | |
| 3299 | } | |
| 2655 | 3300 | |
| 2656 | 3301 | remaining_bytes -= 8 / CHAR_BIT; |
| 3302 | ||
| 3303 | #if zig_big_endian | |
| 2657 | 3304 | byte_offset += 8 / CHAR_BIT; |
| 3305 | #endif | |
| 2658 | 3306 | } |
| 3307 | ||
| 3308 | return 0; | |
| 2659 | 3309 | } |
| 2660 | 3310 | |
| 2661 | static inline void zig_or_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { | |
| 3311 | static inline void zig_not_big(void *res, const void *arg, bool is_signed, uint16_t bits) { | |
| 2662 | 3312 | uint8_t *res_bytes = res; |
| 2663 | const uint8_t *lhs_bytes = lhs; | |
| 2664 | const uint8_t *rhs_bytes = rhs; | |
| 3313 | const uint8_t *arg_bytes = arg; | |
| 2665 | 3314 | uint16_t byte_offset = 0; |
| 2666 | 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 | |
| 2668 | 3321 | |
| 2669 | 3322 | while (remaining_bytes >= 128 / CHAR_BIT) { |
| 2670 | zig_u128 res_limb; | |
| 2671 | zig_u128 lhs_limb; | |
| 2672 | zig_u128 rhs_limb; | |
| 3323 | uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0); | |
| 2673 | 3324 | |
| 2674 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); | |
| 2675 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 2676 | res_limb = zig_or_u128(lhs_limb, rhs_limb); | |
| 2677 | memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); | |
| 3325 | #if zig_big_endian | |
| 3326 | byte_offset -= 128 / CHAR_BIT; | |
| 3327 | #endif | |
| 3328 | ||
| 3329 | if (remaining_bytes != 128 / CHAR_BIT || is_signed) { | |
| 3330 | zig_i128 res_limb; | |
| 3331 | zig_i128 arg_limb; | |
| 3332 | ||
| 3333 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 3334 | res_limb = zig_not_i128(arg_limb, limb_bits); | |
| 3335 | memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); | |
| 3336 | } else { | |
| 3337 | zig_u128 res_limb; | |
| 3338 | zig_u128 arg_limb; | |
| 3339 | ||
| 3340 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 3341 | res_limb = zig_not_u128(arg_limb, limb_bits); | |
| 3342 | memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); | |
| 3343 | } | |
| 2678 | 3344 | |
| 2679 | 3345 | remaining_bytes -= 128 / CHAR_BIT; |
| 3346 | ||
| 3347 | #if zig_little_endian | |
| 2680 | 3348 | byte_offset += 128 / CHAR_BIT; |
| 3349 | #endif | |
| 2681 | 3350 | } |
| 2682 | 3351 | |
| 2683 | 3352 | while (remaining_bytes >= 64 / CHAR_BIT) { |
| 2684 | uint64_t res_limb; | |
| 2685 | uint64_t lhs_limb; | |
| 2686 | uint64_t rhs_limb; | |
| 3353 | uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0); | |
| 2687 | 3354 | |
| 2688 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); | |
| 2689 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 2690 | res_limb = zig_or_u64(lhs_limb, rhs_limb); | |
| 2691 | memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); | |
| 3355 | #if zig_big_endian | |
| 3356 | byte_offset -= 64 / CHAR_BIT; | |
| 3357 | #endif | |
| 3358 | ||
| 3359 | if (remaining_bytes != 64 / CHAR_BIT || is_signed) { | |
| 3360 | int64_t res_limb; | |
| 3361 | int64_t arg_limb; | |
| 3362 | ||
| 3363 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 3364 | res_limb = zig_not_i64(arg_limb, limb_bits); | |
| 3365 | memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); | |
| 3366 | } else { | |
| 3367 | uint64_t res_limb; | |
| 3368 | uint64_t arg_limb; | |
| 3369 | ||
| 3370 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 3371 | res_limb = zig_not_u64(arg_limb, limb_bits); | |
| 3372 | memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); | |
| 3373 | } | |
| 2692 | 3374 | |
| 2693 | 3375 | remaining_bytes -= 64 / CHAR_BIT; |
| 3376 | ||
| 3377 | #if zig_little_endian | |
| 2694 | 3378 | byte_offset += 64 / CHAR_BIT; |
| 3379 | #endif | |
| 2695 | 3380 | } |
| 2696 | 3381 | |
| 2697 | 3382 | while (remaining_bytes >= 32 / CHAR_BIT) { |
| 2698 | uint32_t res_limb; | |
| 2699 | uint32_t lhs_limb; | |
| 2700 | uint32_t rhs_limb; | |
| 3383 | uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0); | |
| 2701 | 3384 | |
| 2702 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); | |
| 2703 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 2704 | res_limb = zig_or_u32(lhs_limb, rhs_limb); | |
| 2705 | memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); | |
| 3385 | #if zig_big_endian | |
| 3386 | byte_offset -= 32 / CHAR_BIT; | |
| 3387 | #endif | |
| 3388 | ||
| 3389 | if (remaining_bytes != 32 / CHAR_BIT || is_signed) { | |
| 3390 | int32_t res_limb; | |
| 3391 | int32_t arg_limb; | |
| 3392 | ||
| 3393 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 3394 | res_limb = zig_not_i32(arg_limb, limb_bits); | |
| 3395 | memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); | |
| 3396 | } else { | |
| 3397 | uint32_t res_limb; | |
| 3398 | uint32_t arg_limb; | |
| 3399 | ||
| 3400 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 3401 | res_limb = zig_not_u32(arg_limb, limb_bits); | |
| 3402 | memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); | |
| 3403 | } | |
| 2706 | 3404 | |
| 2707 | 3405 | remaining_bytes -= 32 / CHAR_BIT; |
| 3406 | ||
| 3407 | #if zig_little_endian | |
| 2708 | 3408 | byte_offset += 32 / CHAR_BIT; |
| 3409 | #endif | |
| 2709 | 3410 | } |
| 2710 | 3411 | |
| 2711 | 3412 | while (remaining_bytes >= 16 / CHAR_BIT) { |
| 2712 | uint16_t res_limb; | |
| 2713 | uint16_t lhs_limb; | |
| 2714 | uint16_t rhs_limb; | |
| 3413 | uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0); | |
| 2715 | 3414 | |
| 2716 | memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb)); | |
| 2717 | memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb)); | |
| 2718 | res_limb = zig_or_u16(lhs_limb, rhs_limb); | |
| 2719 | memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); | |
| 3415 | #if zig_big_endian | |
| 3416 | byte_offset -= 16 / CHAR_BIT; | |
| 3417 | #endif | |
| 2720 | 3418 | |
| 2721 | remaining_bytes -= 16 / CHAR_BIT; | |
| 2722 | byte_offset += 16 / CHAR_BIT; | |
| 2723 | } | |
| 3419 | if (remaining_bytes != 16 / CHAR_BIT || is_signed) { | |
| 3420 | int16_t res_limb; | |
| 3421 | int16_t arg_limb; | |
| 3422 | ||
| 3423 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 3424 | res_limb = zig_not_i16(arg_limb, limb_bits); | |
| 3425 | memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); | |
| 3426 | } else { | |
| 3427 | uint16_t res_limb; | |
| 3428 | uint16_t arg_limb; | |
| 3429 | ||
| 3430 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 3431 | res_limb = zig_not_u16(arg_limb, limb_bits); | |
| 3432 | memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); | |
| 3433 | } | |
| 3434 | ||
| 3435 | remaining_bytes -= 16 / CHAR_BIT; | |
| 3436 | ||
| 3437 | #if zig_little_endian | |
| 3438 | byte_offset += 16 / CHAR_BIT; | |
| 3439 | #endif | |
| 3440 | } | |
| 3441 | ||
| 3442 | while (remaining_bytes >= 8 / CHAR_BIT) { | |
| 3443 | uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0); | |
| 3444 | ||
| 3445 | #if zig_big_endian | |
| 3446 | byte_offset -= 8 / CHAR_BIT; | |
| 3447 | #endif | |
| 3448 | ||
| 3449 | if (remaining_bytes != 8 / CHAR_BIT || is_signed) { | |
| 3450 | int8_t res_limb; | |
| 3451 | int8_t arg_limb; | |
| 3452 | ||
| 3453 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 3454 | res_limb = zig_not_i8(arg_limb, limb_bits); | |
| 3455 | memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); | |
| 3456 | } else { | |
| 3457 | uint8_t res_limb; | |
| 3458 | uint8_t arg_limb; | |
| 3459 | ||
| 3460 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 3461 | res_limb = zig_not_u8(arg_limb, limb_bits); | |
| 3462 | memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); | |
| 3463 | } | |
| 3464 | ||
| 3465 | remaining_bytes -= 8 / CHAR_BIT; | |
| 3466 | ||
| 3467 | #if zig_little_endian | |
| 3468 | byte_offset += 8 / CHAR_BIT; | |
| 3469 | #endif | |
| 3470 | } | |
| 3471 | } | |
| 3472 | ||
| 3473 | static 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 | ||
| 3552 | static 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 | } | |
| 2724 | 3615 | |
| 2725 | 3616 | while (remaining_bytes >= 8 / CHAR_BIT) { |
| 2726 | 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 | 3707 | } |
| 2817 | 3708 | } |
| 2818 | 3709 | |
| 3710 | static 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 | ||
| 3841 | static 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 | ||
| 3972 | static 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 | ||
| 4104 | static 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 | ||
| 4108 | static 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 | ||
| 2819 | 4112 | static inline bool zig_addo_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { |
| 2820 | 4113 | uint8_t *res_bytes = res; |
| 2821 | 4114 | const uint8_t *lhs_bytes = lhs; |
| 2822 | 4115 | const uint8_t *rhs_bytes = rhs; |
| 2823 | 4116 | uint16_t byte_offset = 0; |
| 2824 | 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 | 4119 | bool overflow = false; |
| 2827 | 4120 | |
| 2828 | 4121 | #if zig_big_endian |
| ... | ... | @@ -3038,7 +4331,7 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo |
| 3038 | 4331 | const uint8_t *rhs_bytes = rhs; |
| 3039 | 4332 | uint16_t byte_offset = 0; |
| 3040 | 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 | 4335 | bool overflow = false; |
| 3043 | 4336 | |
| 3044 | 4337 | #if zig_big_endian |
| ... | ... | @@ -3238,218 +4531,890 @@ static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, boo |
| 3238 | 4531 | memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb)); |
| 3239 | 4532 | } |
| 3240 | 4533 | |
| 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 | ||
| 4544 | static 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 | ||
| 4548 | static 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 | ||
| 4552 | static 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 | ||
| 4562 | static 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 | ||
| 4566 | static 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 | ||
| 4570 | static 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 | ||
| 4580 | static 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 | ||
| 4801 | static 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 | ||
| 4805 | static 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 | ||
| 4809 | static 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 | ||
| 4819 | static 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 | ||
| 4829 | static 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 | ||
| 4839 | static 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 | ||
| 4853 | static 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 | ||
| 4865 | static 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 | ||
| 4875 | static 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 | ||
| 4950 | static 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 | ||
| 5094 | static 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 | ||
| 5098 | static 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 | } | |
| 5132 | zig_big_shls_builtin(8) | |
| 5133 | zig_big_shls_builtin(16) | |
| 5134 | zig_big_shls_builtin(32) | |
| 5135 | zig_big_shls_builtin(64) | |
| 5136 | ||
| 5137 | static 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]; | |
| 3242 | 5159 | |
| 3243 | 5160 | #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 | 5164 | #endif |
| 3246 | 5165 | } |
| 3247 | 5166 | |
| 3248 | return overflow; | |
| 3249 | } | |
| 5167 | { | |
| 5168 | #if zig_little_endian | |
| 5169 | arg_byte_offset -= UINT16_C(1); | |
| 5170 | #else | |
| 5171 | res_byte_offset -= UINT16_C(1); | |
| 5172 | #endif | |
| 3250 | 5173 | |
| 3251 | static inline void zig_addw_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { | |
| 3252 | (void)zig_addo_big(res, lhs, rhs, is_signed, bits); | |
| 3253 | } | |
| 5174 | { | |
| 5175 | uint8_t byte = arg_bytes[arg_byte_offset]; | |
| 5176 | uint8_t fill = is_signed | |
| 5177 | ? zig_u8_bitCast_i8(zig_shr_i8(zig_i8_bitCast_u8(byte, UINT8_C(8)), UINT8_C(7)), UINT8_C(8)) | |
| 5178 | : UINT8_C(0); | |
| 3254 | 5179 | |
| 3255 | static inline void zig_subw_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { | |
| 3256 | (void)zig_subo_big(res, lhs, rhs, is_signed, bits); | |
| 3257 | } | |
| 5180 | res_bytes[res_byte_offset] = byte; | |
| 3258 | 5181 | |
| 3259 | zig_extern void __udivei4(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uintptr_t bits); | |
| 3260 | static inline void zig_div_trunc_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { | |
| 3261 | if (!is_signed) { | |
| 3262 | __udivei4(res, lhs, rhs, bits); | |
| 3263 | return; | |
| 5182 | #if zig_little_endian | |
| 5183 | res_byte_offset += UINT16_C(1); | |
| 5184 | memset(&res_bytes[res_byte_offset], fill, size - res_byte_offset); | |
| 5185 | #else | |
| 5186 | memset(&res_bytes[0], fill, res_byte_offset); | |
| 5187 | #endif | |
| 5188 | } | |
| 3264 | 5189 | } |
| 3265 | ||
| 3266 | zig_trap(); | |
| 3267 | 5190 | } |
| 3268 | 5191 | |
| 3269 | static inline void zig_div_floor_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { | |
| 3270 | if (!is_signed) { | |
| 3271 | zig_div_trunc_big(res, lhs, rhs, is_signed, bits); | |
| 3272 | return; | |
| 3273 | } | |
| 5192 | static inline void zig_bitReverse_big(void *res, const void *arg, bool is_signed, uint16_t bits) { | |
| 5193 | uint8_t *res_bytes = res; | |
| 5194 | const uint8_t *arg_bytes = arg; | |
| 5195 | uint16_t size = zig_int_bytes(bits); | |
| 5196 | uint16_t res_byte_offset = UINT16_C(0); | |
| 5197 | uint16_t arg_byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1); | |
| 5198 | uint16_t end_byte_offset = UINT16_C(0); | |
| 5199 | uint8_t arg_prev_byte; | |
| 5200 | uint8_t byte_shift = zig_u8_intCast_u16(zig_subw_u16(UINT16_C(0), bits, UINT8_C(3))); | |
| 3274 | 5201 | |
| 3275 | zig_trap(); | |
| 3276 | } | |
| 5202 | #if zig_big_endian | |
| 5203 | res_byte_offset = size - res_byte_offset; | |
| 5204 | arg_byte_offset = size - arg_byte_offset; | |
| 5205 | end_byte_offset = size - end_byte_offset; | |
| 5206 | #endif | |
| 3277 | 5207 | |
| 3278 | static inline void zig_div_ceil_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { | |
| 3279 | zig_trap(); | |
| 3280 | } | |
| 5208 | { | |
| 5209 | #if zig_little_endian | |
| 5210 | arg_byte_offset -= UINT16_C(1); | |
| 5211 | #endif | |
| 3281 | 5212 | |
| 3282 | zig_extern void __umodei4(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uintptr_t bits); | |
| 3283 | static inline void zig_rem_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { | |
| 3284 | if (!is_signed) { | |
| 3285 | __umodei4(res, lhs, rhs, bits); | |
| 3286 | return; | |
| 5213 | arg_prev_byte = zig_bitReverse_u8(arg_bytes[arg_byte_offset], UINT8_C(8)); | |
| 5214 | ||
| 5215 | #if zig_big_endian | |
| 5216 | arg_byte_offset += UINT16_C(1); | |
| 5217 | #endif | |
| 3287 | 5218 | } |
| 3288 | 5219 | |
| 3289 | zig_trap(); | |
| 3290 | } | |
| 5220 | while (arg_byte_offset != end_byte_offset) { | |
| 5221 | #if zig_big_endian | |
| 5222 | res_byte_offset -= UINT16_C(1); | |
| 5223 | #else | |
| 5224 | arg_byte_offset -= UINT16_C(1); | |
| 5225 | #endif | |
| 3291 | 5226 | |
| 3292 | static inline void zig_mod_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) { | |
| 3293 | if (!is_signed) { | |
| 3294 | zig_rem_big(res, lhs, rhs, is_signed, bits); | |
| 3295 | return; | |
| 5227 | { | |
| 5228 | uint8_t arg_byte = zig_bitReverse_u8(arg_bytes[arg_byte_offset], UINT8_C(8)); | |
| 5229 | ||
| 5230 | res_bytes[res_byte_offset] = zig_u8_intCast_u16(zig_shr_u16(zig_or_u16( | |
| 5231 | zig_shl_u16(zig_u16_intCast_u8(arg_byte), UINT8_C(8)), | |
| 5232 | zig_u16_intCast_u8(arg_prev_byte) | |
| 5233 | ), byte_shift)); | |
| 5234 | arg_prev_byte = arg_byte; | |
| 5235 | } | |
| 5236 | ||
| 5237 | #if zig_little_endian | |
| 5238 | res_byte_offset += UINT16_C(1); | |
| 5239 | #else | |
| 5240 | arg_byte_offset += UINT16_C(1); | |
| 5241 | #endif | |
| 3296 | 5242 | } |
| 3297 | 5243 | |
| 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 | } |
| 3300 | 5268 | |
| 3301 | static inline uint16_t zig_clz_big(const void *val, bool is_signed, uint16_t bits) { | |
| 3302 | const uint8_t *val_bytes = val; | |
| 5269 | static inline uint16_t zig_popCount_big(const void *arg, bool is_signed, uint16_t bits) { | |
| 5270 | const uint8_t *arg_bytes = arg; | |
| 3303 | 5271 | uint16_t byte_offset = 0; |
| 3304 | uint16_t remaining_bytes = zig_int_bytes(bits); | |
| 3305 | uint16_t skip_bits = remaining_bytes * 8 - bits; | |
| 3306 | uint16_t total_lz = 0; | |
| 3307 | uint16_t limb_lz; | |
| 5272 | uint16_t remaining_bytes = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1); | |
| 5273 | uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); | |
| 5274 | uint16_t total_pc = 0; | |
| 3308 | 5275 | (void)is_signed; |
| 3309 | 5276 | |
| 3310 | #if zig_little_endian | |
| 3311 | byte_offset = remaining_bytes; | |
| 5277 | #if zig_big_endian | |
| 5278 | byte_offset = zig_int_bytes(bits); | |
| 3312 | 5279 | #endif |
| 3313 | 5280 | |
| 3314 | 5281 | while (remaining_bytes >= 128 / CHAR_BIT) { |
| 3315 | #if zig_little_endian | |
| 5282 | uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0); | |
| 5283 | ||
| 5284 | #if zig_big_endian | |
| 3316 | 5285 | byte_offset -= 128 / CHAR_BIT; |
| 3317 | 5286 | #endif |
| 3318 | 5287 | |
| 3319 | 5288 | { |
| 3320 | zig_u128 val_limb; | |
| 5289 | zig_u128 arg_limb; | |
| 3321 | 5290 | |
| 3322 | memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); | |
| 3323 | limb_lz = zig_clz_u128(val_limb, 128 - skip_bits); | |
| 5291 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 5292 | total_pc += zig_popCount_u128(zig_u128_truncate_u128(arg_limb, limb_bits), limb_bits); | |
| 3324 | 5293 | } |
| 3325 | 5294 | |
| 3326 | total_lz += limb_lz; | |
| 3327 | if (limb_lz < 128 - skip_bits) return total_lz; | |
| 3328 | skip_bits = 0; | |
| 3329 | 5295 | remaining_bytes -= 128 / CHAR_BIT; |
| 3330 | 5296 | |
| 3331 | #if zig_big_endian | |
| 5297 | #if zig_little_endian | |
| 3332 | 5298 | byte_offset += 128 / CHAR_BIT; |
| 3333 | 5299 | #endif |
| 3334 | 5300 | } |
| 3335 | 5301 | |
| 3336 | 5302 | while (remaining_bytes >= 64 / CHAR_BIT) { |
| 3337 | #if zig_little_endian | |
| 5303 | uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0); | |
| 5304 | ||
| 5305 | #if zig_big_endian | |
| 3338 | 5306 | byte_offset -= 64 / CHAR_BIT; |
| 3339 | 5307 | #endif |
| 3340 | 5308 | |
| 3341 | 5309 | { |
| 3342 | uint64_t val_limb; | |
| 5310 | uint64_t arg_limb; | |
| 3343 | 5311 | |
| 3344 | memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); | |
| 3345 | limb_lz = zig_clz_u64(val_limb, 64 - skip_bits); | |
| 5312 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 5313 | total_pc += zig_popCount_u64(zig_u64_truncate_u64(arg_limb, limb_bits), limb_bits); | |
| 3346 | 5314 | } |
| 3347 | 5315 | |
| 3348 | total_lz += limb_lz; | |
| 3349 | if (limb_lz < 64 - skip_bits) return total_lz; | |
| 3350 | skip_bits = 0; | |
| 3351 | 5316 | remaining_bytes -= 64 / CHAR_BIT; |
| 3352 | 5317 | |
| 3353 | #if zig_big_endian | |
| 5318 | #if zig_little_endian | |
| 3354 | 5319 | byte_offset += 64 / CHAR_BIT; |
| 3355 | 5320 | #endif |
| 3356 | 5321 | } |
| 3357 | 5322 | |
| 3358 | 5323 | while (remaining_bytes >= 32 / CHAR_BIT) { |
| 3359 | #if zig_little_endian | |
| 5324 | uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0); | |
| 5325 | ||
| 5326 | #if zig_big_endian | |
| 3360 | 5327 | byte_offset -= 32 / CHAR_BIT; |
| 3361 | 5328 | #endif |
| 3362 | 5329 | |
| 3363 | 5330 | { |
| 3364 | uint32_t val_limb; | |
| 5331 | uint32_t arg_limb; | |
| 3365 | 5332 | |
| 3366 | memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); | |
| 3367 | limb_lz = zig_clz_u32(val_limb, 32 - skip_bits); | |
| 5333 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 5334 | total_pc += zig_popCount_u32(zig_u32_truncate_u32(arg_limb, limb_bits), limb_bits); | |
| 3368 | 5335 | } |
| 3369 | 5336 | |
| 3370 | total_lz += limb_lz; | |
| 3371 | if (limb_lz < 32 - skip_bits) return total_lz; | |
| 3372 | skip_bits = 0; | |
| 3373 | 5337 | remaining_bytes -= 32 / CHAR_BIT; |
| 3374 | 5338 | |
| 3375 | #if zig_big_endian | |
| 5339 | #if zig_little_endian | |
| 3376 | 5340 | byte_offset += 32 / CHAR_BIT; |
| 3377 | 5341 | #endif |
| 3378 | 5342 | } |
| 3379 | 5343 | |
| 3380 | 5344 | while (remaining_bytes >= 16 / CHAR_BIT) { |
| 3381 | #if zig_little_endian | |
| 5345 | uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0); | |
| 5346 | ||
| 5347 | #if zig_big_endian | |
| 3382 | 5348 | byte_offset -= 16 / CHAR_BIT; |
| 3383 | 5349 | #endif |
| 3384 | 5350 | |
| 3385 | 5351 | { |
| 3386 | uint16_t val_limb; | |
| 5352 | uint16_t arg_limb; | |
| 3387 | 5353 | |
| 3388 | memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); | |
| 3389 | limb_lz = zig_clz_u16(val_limb, 16 - skip_bits); | |
| 5354 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 5355 | total_pc += zig_popCount_u16(zig_u16_truncate_u16(arg_limb, limb_bits), limb_bits); | |
| 3390 | 5356 | } |
| 3391 | 5357 | |
| 3392 | total_lz += limb_lz; | |
| 3393 | if (limb_lz < 16 - skip_bits) return total_lz; | |
| 3394 | skip_bits = 0; | |
| 3395 | 5358 | remaining_bytes -= 16 / CHAR_BIT; |
| 3396 | 5359 | |
| 3397 | #if zig_big_endian | |
| 5360 | #if zig_little_endian | |
| 3398 | 5361 | byte_offset += 16 / CHAR_BIT; |
| 3399 | 5362 | #endif |
| 3400 | 5363 | } |
| 3401 | 5364 | |
| 3402 | 5365 | while (remaining_bytes >= 8 / CHAR_BIT) { |
| 3403 | #if zig_little_endian | |
| 5366 | uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0); | |
| 5367 | ||
| 5368 | #if zig_big_endian | |
| 3404 | 5369 | byte_offset -= 8 / CHAR_BIT; |
| 3405 | 5370 | #endif |
| 3406 | 5371 | |
| 3407 | 5372 | { |
| 3408 | uint8_t val_limb; | |
| 5373 | uint8_t arg_limb; | |
| 3409 | 5374 | |
| 3410 | memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); | |
| 3411 | limb_lz = zig_clz_u8(val_limb, 8 - skip_bits); | |
| 5375 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 5376 | total_pc += zig_popCount_u8(zig_u8_truncate_u8(arg_limb, limb_bits), limb_bits); | |
| 3412 | 5377 | } |
| 3413 | 5378 | |
| 3414 | total_lz += limb_lz; | |
| 3415 | if (limb_lz < 8 - skip_bits) return total_lz; | |
| 3416 | skip_bits = 0; | |
| 3417 | 5379 | remaining_bytes -= 8 / CHAR_BIT; |
| 3418 | 5380 | |
| 3419 | #if zig_big_endian | |
| 5381 | #if zig_little_endian | |
| 3420 | 5382 | byte_offset += 8 / CHAR_BIT; |
| 3421 | 5383 | #endif |
| 3422 | 5384 | } |
| 3423 | 5385 | |
| 3424 | return total_lz; | |
| 5386 | return total_pc; | |
| 3425 | 5387 | } |
| 3426 | 5388 | |
| 3427 | static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bits) { | |
| 3428 | const uint8_t *val_bytes = val; | |
| 3429 | uint16_t byte_offset = 0; | |
| 3430 | uint16_t remaining_bytes = zig_int_bytes(bits); | |
| 3431 | uint16_t total_tz = 0; | |
| 5389 | static inline uint16_t zig_ctz_big(const void *arg, bool is_signed, uint16_t bits) { | |
| 5390 | const uint8_t *arg_bytes = arg; | |
| 5391 | uint16_t byte_offset = UINT16_C(0); | |
| 5392 | uint16_t remaining_bytes = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1); | |
| 5393 | uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); | |
| 5394 | uint16_t total_tz = UINT16_C(0); | |
| 3432 | 5395 | uint16_t limb_tz; |
| 3433 | 5396 | (void)is_signed; |
| 3434 | 5397 | |
| 3435 | 5398 | #if zig_big_endian |
| 3436 | byte_offset = remaining_bytes; | |
| 5399 | byte_offset = zig_int_bytes(bits); | |
| 3437 | 5400 | #endif |
| 3438 | 5401 | |
| 3439 | 5402 | while (remaining_bytes >= 128 / CHAR_BIT) { |
| 5403 | uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0); | |
| 5404 | ||
| 3440 | 5405 | #if zig_big_endian |
| 3441 | 5406 | byte_offset -= 128 / CHAR_BIT; |
| 3442 | 5407 | #endif |
| 3443 | 5408 | |
| 3444 | 5409 | { |
| 3445 | zig_u128 val_limb; | |
| 5410 | zig_u128 arg_limb; | |
| 3446 | 5411 | |
| 3447 | memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); | |
| 3448 | limb_tz = zig_ctz_u128(val_limb, 128); | |
| 5412 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 5413 | limb_tz = zig_ctz_u128(zig_u128_truncate_u128(arg_limb, limb_bits), limb_bits); | |
| 3449 | 5414 | } |
| 3450 | 5415 | |
| 3451 | 5416 | total_tz += limb_tz; |
| 3452 | if (limb_tz < 128) return total_tz; | |
| 5417 | if (limb_tz < limb_bits) return total_tz; | |
| 3453 | 5418 | remaining_bytes -= 128 / CHAR_BIT; |
| 3454 | 5419 | |
| 3455 | 5420 | #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 | 5423 | } |
| 3459 | 5424 | |
| 3460 | 5425 | while (remaining_bytes >= 64 / CHAR_BIT) { |
| 5426 | uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0); | |
| 5427 | ||
| 3461 | 5428 | #if zig_big_endian |
| 3462 | 5429 | byte_offset -= 64 / CHAR_BIT; |
| 3463 | 5430 | #endif |
| 3464 | 5431 | |
| 3465 | 5432 | { |
| 3466 | uint64_t val_limb; | |
| 5433 | uint64_t arg_limb; | |
| 3467 | 5434 | |
| 3468 | memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); | |
| 3469 | limb_tz = zig_ctz_u64(val_limb, 64); | |
| 5435 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 5436 | limb_tz = zig_ctz_u64(zig_u64_truncate_u64(arg_limb, limb_bits), limb_bits); | |
| 3470 | 5437 | } |
| 3471 | 5438 | |
| 3472 | 5439 | total_tz += limb_tz; |
| 3473 | if (limb_tz < 64) return total_tz; | |
| 5440 | if (limb_tz < limb_bits) return total_tz; | |
| 3474 | 5441 | remaining_bytes -= 64 / CHAR_BIT; |
| 3475 | 5442 | |
| 3476 | 5443 | #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 | 5446 | } |
| 3480 | 5447 | |
| 3481 | 5448 | while (remaining_bytes >= 32 / CHAR_BIT) { |
| 5449 | uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0); | |
| 5450 | ||
| 3482 | 5451 | #if zig_big_endian |
| 3483 | 5452 | byte_offset -= 32 / CHAR_BIT; |
| 3484 | 5453 | #endif |
| 3485 | 5454 | |
| 3486 | 5455 | { |
| 3487 | uint32_t val_limb; | |
| 5456 | uint32_t arg_limb; | |
| 3488 | 5457 | |
| 3489 | memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); | |
| 3490 | limb_tz = zig_ctz_u32(val_limb, 32); | |
| 5458 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 5459 | limb_tz = zig_ctz_u32(zig_u32_truncate_u32(arg_limb, limb_bits), limb_bits); | |
| 3491 | 5460 | } |
| 3492 | 5461 | |
| 3493 | 5462 | total_tz += limb_tz; |
| 3494 | if (limb_tz < 32) return total_tz; | |
| 5463 | if (limb_tz < limb_bits) return total_tz; | |
| 3495 | 5464 | remaining_bytes -= 32 / CHAR_BIT; |
| 3496 | 5465 | |
| 3497 | 5466 | #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 | 5469 | } |
| 3501 | 5470 | |
| 3502 | 5471 | while (remaining_bytes >= 16 / CHAR_BIT) { |
| 5472 | uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0); | |
| 5473 | ||
| 3503 | 5474 | #if zig_big_endian |
| 3504 | 5475 | byte_offset -= 16 / CHAR_BIT; |
| 3505 | 5476 | #endif |
| 3506 | 5477 | |
| 3507 | 5478 | { |
| 3508 | uint16_t val_limb; | |
| 5479 | uint16_t arg_limb; | |
| 3509 | 5480 | |
| 3510 | memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); | |
| 3511 | limb_tz = zig_ctz_u16(val_limb, 16); | |
| 5481 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 5482 | limb_tz = zig_ctz_u16(zig_u16_truncate_u16(arg_limb, limb_bits), limb_bits); | |
| 3512 | 5483 | } |
| 3513 | 5484 | |
| 3514 | 5485 | total_tz += limb_tz; |
| 3515 | if (limb_tz < 16) return total_tz; | |
| 5486 | if (limb_tz < limb_bits) return total_tz; | |
| 3516 | 5487 | remaining_bytes -= 16 / CHAR_BIT; |
| 3517 | 5488 | |
| 3518 | 5489 | #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 | 5492 | } |
| 3522 | 5493 | |
| 3523 | 5494 | while (remaining_bytes >= 8 / CHAR_BIT) { |
| 5495 | uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0); | |
| 5496 | ||
| 3524 | 5497 | #if zig_big_endian |
| 3525 | 5498 | byte_offset -= 8 / CHAR_BIT; |
| 3526 | 5499 | #endif |
| 3527 | 5500 | |
| 3528 | 5501 | { |
| 3529 | uint8_t val_limb; | |
| 5502 | uint8_t arg_limb; | |
| 3530 | 5503 | |
| 3531 | memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); | |
| 3532 | limb_tz = zig_ctz_u8(val_limb, 8); | |
| 5504 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 5505 | limb_tz = zig_ctz_u8(zig_u8_truncate_u8(arg_limb, limb_bits), limb_bits); | |
| 3533 | 5506 | } |
| 3534 | 5507 | |
| 3535 | 5508 | total_tz += limb_tz; |
| 3536 | if (limb_tz < 8) return total_tz; | |
| 5509 | if (limb_tz < limb_bits) return total_tz; | |
| 3537 | 5510 | remaining_bytes -= 8 / CHAR_BIT; |
| 3538 | 5511 | |
| 3539 | 5512 | #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 | 5517 | return total_tz; |
| 3545 | 5518 | } |
| 3546 | 5519 | |
| 3547 | static inline uint16_t zig_popcount_big(const void *val, bool is_signed, uint16_t bits) { | |
| 3548 | const uint8_t *val_bytes = val; | |
| 3549 | uint16_t byte_offset = 0; | |
| 3550 | uint16_t remaining_bytes = zig_int_bytes(bits); | |
| 3551 | uint16_t total_pc = 0; | |
| 5520 | static inline uint16_t zig_clz_big(const void *arg, bool is_signed, uint16_t bits) { | |
| 5521 | const uint8_t *arg_bytes = arg; | |
| 5522 | uint16_t byte_offset = zig_shr_u16(bits - UINT16_C(1), UINT8_C(3)) + UINT16_C(1); | |
| 5523 | uint16_t remaining_bytes = byte_offset; | |
| 5524 | uint8_t top_bits = zig_u8_intCast_u16(remaining_bytes * CHAR_BIT - bits); | |
| 5525 | bool sign_limb = true; | |
| 5526 | uint16_t total_lz = UINT16_C(0); | |
| 5527 | uint16_t limb_lz; | |
| 3552 | 5528 | (void)is_signed; |
| 3553 | 5529 | |
| 3554 | 5530 | #if zig_big_endian |
| 3555 | byte_offset = remaining_bytes; | |
| 5531 | byte_offset = zig_int_bytes(bits) - remaining_bytes; | |
| 3556 | 5532 | #endif |
| 3557 | 5533 | |
| 3558 | 5534 | while (remaining_bytes >= 128 / CHAR_BIT) { |
| 3559 | #if zig_big_endian | |
| 5535 | uint8_t limb_bits = UINT8_C(128) - (sign_limb ? top_bits : UINT8_C(0)); | |
| 5536 | ||
| 5537 | #if zig_little_endian | |
| 3560 | 5538 | byte_offset -= 128 / CHAR_BIT; |
| 3561 | 5539 | #endif |
| 3562 | 5540 | |
| 3563 | 5541 | { |
| 3564 | zig_u128 val_limb; | |
| 5542 | zig_u128 arg_limb; | |
| 3565 | 5543 | |
| 3566 | memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); | |
| 3567 | total_pc += zig_popcount_u128(val_limb, 128); | |
| 5544 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 5545 | limb_lz = zig_clz_u128(zig_u128_truncate_u128(arg_limb, limb_bits), limb_bits); | |
| 3568 | 5546 | } |
| 3569 | 5547 | |
| 5548 | total_lz += limb_lz; | |
| 5549 | if (limb_lz < limb_bits) return total_lz; | |
| 5550 | sign_limb = false; | |
| 3570 | 5551 | remaining_bytes -= 128 / CHAR_BIT; |
| 3571 | 5552 | |
| 3572 | #if zig_little_endian | |
| 5553 | #if zig_big_endian | |
| 3573 | 5554 | byte_offset += 128 / CHAR_BIT; |
| 3574 | 5555 | #endif |
| 3575 | 5556 | } |
| 3576 | 5557 | |
| 3577 | 5558 | while (remaining_bytes >= 64 / CHAR_BIT) { |
| 3578 | #if zig_big_endian | |
| 5559 | uint8_t limb_bits = UINT8_C(64) - (sign_limb ? top_bits : UINT8_C(0)); | |
| 5560 | ||
| 5561 | #if zig_little_endian | |
| 3579 | 5562 | byte_offset -= 64 / CHAR_BIT; |
| 3580 | 5563 | #endif |
| 3581 | 5564 | |
| 3582 | 5565 | { |
| 3583 | uint64_t val_limb; | |
| 5566 | uint64_t arg_limb; | |
| 3584 | 5567 | |
| 3585 | memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); | |
| 3586 | total_pc += zig_popcount_u64(val_limb, 64); | |
| 5568 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 5569 | limb_lz = zig_clz_u64(zig_u64_truncate_u64(arg_limb, limb_bits), limb_bits); | |
| 3587 | 5570 | } |
| 3588 | 5571 | |
| 5572 | total_lz += limb_lz; | |
| 5573 | if (limb_lz < limb_bits) return total_lz; | |
| 5574 | sign_limb = false; | |
| 3589 | 5575 | remaining_bytes -= 64 / CHAR_BIT; |
| 3590 | 5576 | |
| 3591 | #if zig_little_endian | |
| 5577 | #if zig_big_endian | |
| 3592 | 5578 | byte_offset += 64 / CHAR_BIT; |
| 3593 | 5579 | #endif |
| 3594 | 5580 | } |
| 3595 | 5581 | |
| 3596 | 5582 | while (remaining_bytes >= 32 / CHAR_BIT) { |
| 3597 | #if zig_big_endian | |
| 5583 | uint8_t limb_bits = UINT8_C(32) - (sign_limb ? top_bits : UINT8_C(0)); | |
| 5584 | ||
| 5585 | #if zig_little_endian | |
| 3598 | 5586 | byte_offset -= 32 / CHAR_BIT; |
| 3599 | 5587 | #endif |
| 3600 | 5588 | |
| 3601 | 5589 | { |
| 3602 | uint32_t val_limb; | |
| 5590 | uint32_t arg_limb; | |
| 3603 | 5591 | |
| 3604 | memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); | |
| 3605 | total_pc += zig_popcount_u32(val_limb, 32); | |
| 5592 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 5593 | limb_lz = zig_clz_u32(zig_u32_truncate_u32(arg_limb, limb_bits), limb_bits); | |
| 3606 | 5594 | } |
| 3607 | 5595 | |
| 5596 | total_lz += limb_lz; | |
| 5597 | if (limb_lz < limb_bits) return total_lz; | |
| 5598 | sign_limb = false; | |
| 3608 | 5599 | remaining_bytes -= 32 / CHAR_BIT; |
| 3609 | 5600 | |
| 3610 | #if zig_little_endian | |
| 5601 | #if zig_big_endian | |
| 3611 | 5602 | byte_offset += 32 / CHAR_BIT; |
| 3612 | 5603 | #endif |
| 3613 | 5604 | } |
| 3614 | 5605 | |
| 3615 | 5606 | while (remaining_bytes >= 16 / CHAR_BIT) { |
| 3616 | #if zig_big_endian | |
| 5607 | uint8_t limb_bits = UINT8_C(16) - (sign_limb ? top_bits : UINT8_C(0)); | |
| 5608 | ||
| 5609 | #if zig_little_endian | |
| 3617 | 5610 | byte_offset -= 16 / CHAR_BIT; |
| 3618 | 5611 | #endif |
| 3619 | 5612 | |
| 3620 | 5613 | { |
| 3621 | uint16_t val_limb; | |
| 5614 | uint16_t arg_limb; | |
| 3622 | 5615 | |
| 3623 | memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); | |
| 3624 | total_pc = zig_popcount_u16(val_limb, 16); | |
| 5616 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 5617 | limb_lz = zig_clz_u16(zig_u16_truncate_u16(arg_limb, limb_bits), limb_bits); | |
| 3625 | 5618 | } |
| 3626 | 5619 | |
| 5620 | total_lz += limb_lz; | |
| 5621 | if (limb_lz < limb_bits) return total_lz; | |
| 5622 | sign_limb = false; | |
| 3627 | 5623 | remaining_bytes -= 16 / CHAR_BIT; |
| 3628 | 5624 | |
| 3629 | #if zig_little_endian | |
| 5625 | #if zig_big_endian | |
| 3630 | 5626 | byte_offset += 16 / CHAR_BIT; |
| 3631 | 5627 | #endif |
| 3632 | 5628 | } |
| 3633 | 5629 | |
| 3634 | 5630 | while (remaining_bytes >= 8 / CHAR_BIT) { |
| 3635 | #if zig_big_endian | |
| 5631 | uint8_t limb_bits = UINT8_C(8) - (sign_limb ? top_bits : UINT8_C(0)); | |
| 5632 | ||
| 5633 | #if zig_little_endian | |
| 3636 | 5634 | byte_offset -= 8 / CHAR_BIT; |
| 3637 | 5635 | #endif |
| 3638 | 5636 | |
| 3639 | 5637 | { |
| 3640 | uint8_t val_limb; | |
| 5638 | uint8_t arg_limb; | |
| 3641 | 5639 | |
| 3642 | memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb)); | |
| 3643 | total_pc = zig_popcount_u8(val_limb, 8); | |
| 5640 | memcpy(&arg_limb, &arg_bytes[byte_offset], sizeof(arg_limb)); | |
| 5641 | limb_lz = zig_clz_u8(zig_u8_truncate_u8(arg_limb, limb_bits), limb_bits); | |
| 3644 | 5642 | } |
| 3645 | 5643 | |
| 5644 | total_lz += limb_lz; | |
| 5645 | if (limb_lz < limb_bits) return total_lz; | |
| 5646 | sign_limb = false; | |
| 3646 | 5647 | remaining_bytes -= 8 / CHAR_BIT; |
| 3647 | 5648 | |
| 3648 | #if zig_little_endian | |
| 5649 | #if zig_big_endian | |
| 3649 | 5650 | byte_offset += 8 / CHAR_BIT; |
| 3650 | 5651 | #endif |
| 3651 | 5652 | } |
| 3652 | 5653 | |
| 3653 | return total_pc; | |
| 5654 | return total_lz; | |
| 3654 | 5655 | } |
| 3655 | 5656 | |
| 3656 | 5657 | /* ========================= Floating Point Support ========================= */ |
| ... | ... | @@ -3687,29 +5688,29 @@ long double __cdecl nanl(char const* input); |
| 3687 | 5688 | #define zig_make_special_f80(sign, name, arg, repr) sign zig_make_f80 (__builtin_##name, )(arg) |
| 3688 | 5689 | #define zig_make_special_f128(sign, name, arg, repr) sign zig_make_f128(__builtin_##name, )(arg) |
| 3689 | 5690 | #else |
| 3690 | #define zig_make_special_f16(sign, name, arg, repr) zig_bitCast_f16 (repr) | |
| 3691 | #define zig_make_special_f32(sign, name, arg, repr) zig_bitCast_f32 (repr) | |
| 3692 | #define zig_make_special_f64(sign, name, arg, repr) zig_bitCast_f64 (repr) | |
| 3693 | #define zig_make_special_f80(sign, name, arg, repr) zig_bitCast_f80 (repr) | |
| 3694 | #define zig_make_special_f128(sign, name, arg, repr) zig_bitCast_f128(repr) | |
| 5691 | #define zig_make_special_f16(sign, name, arg, repr) zig_f16_bitCast_u16 (repr) | |
| 5692 | #define zig_make_special_f32(sign, name, arg, repr) zig_f32_bitCast_u32 (repr) | |
| 5693 | #define zig_make_special_f64(sign, name, arg, repr) zig_f64_bitCast_u64 (repr) | |
| 5694 | #define zig_make_special_f80(sign, name, arg, repr) zig_f80_bitCast_u128(repr) | |
| 5695 | #define zig_make_special_f128(sign, name, arg, repr) zig_f128_bitCast_u128(repr) | |
| 3695 | 5696 | #endif |
| 3696 | 5697 | |
| 3697 | 5698 | #define zig_has_f16 1 |
| 3698 | 5699 | #define zig_libc_name_f16(name) __##name##h |
| 3699 | 5700 | #define zig_init_special_f16(sign, name, arg, repr) zig_make_special_f16(sign, name, arg, repr) |
| 3700 | #if FLT_MANT_DIG == 11 | |
| 5701 | #if !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && FLT_MANT_DIG == 11 | |
| 3701 | 5702 | typedef float zig_f16; |
| 3702 | 5703 | #define zig_make_f16(fp, repr) fp##f |
| 3703 | #elif DBL_MANT_DIG == 11 | |
| 5704 | #elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && DBL_MANT_DIG == 11 | |
| 3704 | 5705 | typedef double zig_f16; |
| 3705 | 5706 | #define zig_make_f16(fp, repr) fp |
| 3706 | #elif LDBL_MANT_DIG == 11 | |
| 5707 | #elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F16_ABI) && LDBL_MANT_DIG == 11 | |
| 3707 | 5708 | typedef long double zig_f16; |
| 3708 | 5709 | #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)) | |
| 3710 | 5711 | typedef _Float16 zig_f16; |
| 3711 | 5712 | #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__) | |
| 3713 | 5714 | typedef __fp16 zig_f16; |
| 3714 | 5715 | #define zig_make_f16(fp, repr) fp##f16 |
| 3715 | 5716 | #else |
| ... | ... | @@ -3723,11 +5724,6 @@ typedef uint16_t zig_f16; |
| 3723 | 5724 | #undef zig_init_special_f16 |
| 3724 | 5725 | #define zig_init_special_f16(sign, name, arg, repr) repr |
| 3725 | 5726 | #endif |
| 3726 | #if defined(zig_darwin) && defined(zig_x86) | |
| 3727 | typedef uint16_t zig_compiler_rt_f16; | |
| 3728 | #else | |
| 3729 | typedef zig_f16 zig_compiler_rt_f16; | |
| 3730 | #endif | |
| 3731 | 5727 | |
| 3732 | 5728 | #define zig_has_f32 1 |
| 3733 | 5729 | #define zig_libc_name_f32(name) name##f |
| ... | ... | @@ -3736,16 +5732,16 @@ typedef zig_f16 zig_compiler_rt_f16; |
| 3736 | 5732 | #else |
| 3737 | 5733 | #define zig_init_special_f32(sign, name, arg, repr) zig_make_special_f32(sign, name, arg, repr) |
| 3738 | 5734 | #endif |
| 3739 | #if FLT_MANT_DIG == 24 | |
| 5735 | #if !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && FLT_MANT_DIG == 24 | |
| 3740 | 5736 | typedef float zig_f32; |
| 3741 | 5737 | #define zig_make_f32(fp, repr) fp##f |
| 3742 | #elif DBL_MANT_DIG == 24 | |
| 5738 | #elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && DBL_MANT_DIG == 24 | |
| 3743 | 5739 | typedef double zig_f32; |
| 3744 | 5740 | #define zig_make_f32(fp, repr) fp |
| 3745 | #elif LDBL_MANT_DIG == 24 | |
| 5741 | #elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && LDBL_MANT_DIG == 24 | |
| 3746 | 5742 | typedef long double zig_f32; |
| 3747 | 5743 | #define zig_make_f32(fp, repr) fp##l |
| 3748 | #elif FLT32_MANT_DIG == 24 | |
| 5744 | #elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F32_ABI) && FLT32_MANT_DIG == 24 | |
| 3749 | 5745 | typedef _Float32 zig_f32; |
| 3750 | 5746 | #define zig_make_f32(fp, repr) fp##f32 |
| 3751 | 5747 | #else |
| ... | ... | @@ -3768,19 +5764,19 @@ typedef uint32_t zig_f32; |
| 3768 | 5764 | #else |
| 3769 | 5765 | #define zig_init_special_f64(sign, name, arg, repr) zig_make_special_f64(sign, name, arg, repr) |
| 3770 | 5766 | #endif |
| 3771 | #if FLT_MANT_DIG == 53 | |
| 5767 | #if !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && FLT_MANT_DIG == 53 | |
| 3772 | 5768 | typedef float zig_f64; |
| 3773 | 5769 | #define zig_make_f64(fp, repr) fp##f |
| 3774 | #elif DBL_MANT_DIG == 53 | |
| 5770 | #elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && DBL_MANT_DIG == 53 | |
| 3775 | 5771 | typedef double zig_f64; |
| 3776 | 5772 | #define zig_make_f64(fp, repr) fp |
| 3777 | #elif LDBL_MANT_DIG == 53 | |
| 5773 | #elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && LDBL_MANT_DIG == 53 | |
| 3778 | 5774 | typedef long double zig_f64; |
| 3779 | 5775 | #define zig_make_f64(fp, repr) fp##l |
| 3780 | #elif FLT64_MANT_DIG == 53 | |
| 5776 | #elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && FLT64_MANT_DIG == 53 | |
| 3781 | 5777 | typedef _Float64 zig_f64; |
| 3782 | 5778 | #define zig_make_f64(fp, repr) fp##f64 |
| 3783 | #elif FLT32X_MANT_DIG == 53 | |
| 5779 | #elif !defined(ZIG_TARGET_SOFT_COMPILER_RT_F64_ABI) && FLT32X_MANT_DIG == 53 | |
| 3784 | 5780 | typedef _Float32x zig_f64; |
| 3785 | 5781 | #define zig_make_f64(fp, repr) fp##f32x |
| 3786 | 5782 | #else |
| ... | ... | @@ -3798,7 +5794,14 @@ typedef uint64_t zig_f64; |
| 3798 | 5794 | #define zig_has_f80 1 |
| 3799 | 5795 | #define zig_libc_name_f80(name) __##name##x |
| 3800 | 5796 | #define zig_init_special_f80(sign, name, arg, repr) zig_make_special_f80(sign, name, arg, repr) |
| 3801 | #if FLT_MANT_DIG == 64 | |
| 5797 | #ifdef ZIG_TARGET_SOFT_COMPILER_RT_F80_ABI | |
| 5798 | #undef zig_has_f80 | |
| 5799 | typedef 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 | |
| 3802 | 5805 | typedef float zig_f80; |
| 3803 | 5806 | #define zig_make_f80(fp, repr) fp##f |
| 3804 | 5807 | #elif DBL_MANT_DIG == 64 |
| ... | ... | @@ -3818,68 +5821,91 @@ typedef __float80 zig_f80; |
| 3818 | 5821 | #define zig_make_f80(fp, repr) fp##l |
| 3819 | 5822 | #else |
| 3820 | 5823 | #undef zig_has_f80 |
| 3821 | #define zig_has_f80 0 | |
| 3822 | #define zig_repr_f80 u128 | |
| 3823 | 5824 | typedef 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 | 5832 | #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 | 5836 | #undef zig_make_special_f80 |
| 3826 | 5837 | #define zig_make_special_f80(sign, name, arg, repr) repr |
| 3827 | 5838 | #undef zig_init_special_f80 |
| 3828 | 5839 | #define zig_init_special_f80(sign, name, arg, repr) repr |
| 3829 | 5840 | #endif |
| 3830 | 5841 | |
| 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 | 5842 | #define zig_has_f128 1 |
| 3838 | #define zig_libc_name_f128(name) name##q | |
| 5843 | #define zig_libc_name_f128(name) name##f128 | |
| 3839 | 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 == 113 | |
| 5845 | #ifdef ZIG_TARGET_SOFT_COMPILER_RT_F128_ABI | |
| 5846 | #undef zig_has_f128 | |
| 5847 | #if zig_little_endian | |
| 5848 | typedef struct { uint64_t lo, hi; } zig_f128; | |
| 5849 | #else | |
| 5850 | typedef 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 | |
| 3841 | 5856 | typedef float zig_f128; |
| 3842 | 5857 | #define zig_make_f128(fp, repr) fp##f |
| 3843 | #elif !zig_f128_has_miscompilations && DBL_MANT_DIG == 113 | |
| 5858 | #elif DBL_MANT_DIG == 113 | |
| 3844 | 5859 | typedef double zig_f128; |
| 3845 | 5860 | #define zig_make_f128(fp, repr) fp |
| 3846 | #elif !zig_f128_has_miscompilations && LDBL_MANT_DIG == 113 | |
| 5861 | #elif LDBL_MANT_DIG == 113 | |
| 3847 | 5862 | typedef long double zig_f128; |
| 3848 | 5863 | #define zig_make_f128(fp, repr) fp##l |
| 3849 | #elif !zig_f128_has_miscompilations && FLT128_MANT_DIG == 113 | |
| 5864 | #elif FLT128_MANT_DIG == 113 | |
| 3850 | 5865 | typedef _Float128 zig_f128; |
| 3851 | 5866 | #define zig_make_f128(fp, repr) fp##f128 |
| 3852 | #elif !zig_f128_has_miscompilations && FLT64X_MANT_DIG == 113 | |
| 5867 | #elif FLT64X_MANT_DIG == 113 | |
| 3853 | 5868 | typedef _Float64x zig_f128; |
| 3854 | 5869 | #define zig_make_f128(fp, repr) fp##f64x |
| 3855 | #elif !zig_f128_has_miscompilations && defined(__SIZEOF_FLOAT128__) | |
| 5870 | #elif defined(__SIZEOF_FLOAT128__) | |
| 3856 | 5871 | typedef __float128 zig_f128; |
| 3857 | 5872 | #define zig_make_f128(fp, repr) fp##q |
| 3858 | 5873 | #undef zig_make_special_f128 |
| 3859 | 5874 | #define zig_make_special_f128(sign, name, arg, repr) sign __builtin_##name##f128(arg) |
| 3860 | 5875 | #else |
| 3861 | 5876 | #undef zig_has_f128 |
| 3862 | #define zig_has_f128 0 | |
| 3863 | #undef zig_make_special_f128 | |
| 3864 | #undef zig_init_special_f128 | |
| 3865 | #if defined(zig_darwin) || defined(zig_aarch64) | |
| 3866 | typedef __attribute__((__vector_size__(2 * sizeof(uint64_t)))) uint64_t zig_v2u64; | |
| 3867 | zig_basic_operator(zig_v2u64, xor_v2u64, ^) | |
| 3868 | #define zig_repr_f128 v2u64 | |
| 3869 | typedef zig_v2u64 zig_f128; | |
| 3870 | #define zig_make_f128_zig_make_u128(hi, lo) (zig_f128){ lo, hi } | |
| 3871 | #define zig_make_f128_zig_init_u128 zig_make_f128_zig_make_u128 | |
| 3872 | #define zig_make_f128(fp, repr) zig_make_f128_##repr | |
| 3873 | #define zig_make_special_f128(sign, name, arg, repr) zig_make_f128_##repr | |
| 3874 | #define zig_init_special_f128(sign, name, arg, repr) zig_make_f128_##repr | |
| 3875 | #else | |
| 3876 | #define zig_repr_f128 u128 | |
| 5877 | #if defined(zig_x86_64) && defined(ZIG_TARGET_ABI_MSVC) | |
| 5878 | #if defined(zig_msvc) && !defined(__clang__) | |
| 5879 | #include <emmintrin.h> | |
| 5880 | typedef __m128i zig_f128; | |
| 5881 | #define zig_init_repr_f128(hi, lo) { .m128i_u64 = { lo, hi } } | |
| 5882 | #define zig_lo_repr_f128(arg) (arg).m128i_u64[0] | |
| 5883 | #define zig_hi_repr_f128(arg) (arg).m128i_u64[1] | |
| 5884 | #else | |
| 5885 | typedef __attribute__((__vector_size__(2 * sizeof(uint64_t)))) uint64_t zig_f128; | |
| 5886 | #define zig_init_repr_f128(hi, lo) { lo, hi } | |
| 5887 | #define zig_lo_repr_f128(arg) (arg)[0] | |
| 5888 | #define zig_hi_repr_f128(arg) (arg)[1] | |
| 5889 | #endif | |
| 5890 | #else | |
| 3877 | 5891 | typedef 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 | 5900 | #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 | 5905 | #define zig_make_special_f128(sign, name, arg, repr) repr |
| 5906 | #undef zig_init_special_f128 | |
| 3880 | 5907 | #define zig_init_special_f128(sign, name, arg, repr) repr |
| 3881 | 5908 | #endif |
| 3882 | #endif | |
| 3883 | 5909 | |
| 3884 | 5910 | #if !defined(zig_msvc) && defined(ZIG_TARGET_ABI_MSVC) |
| 3885 | 5911 | /* Emulate msvc abi on a gnu compiler */ |
| ... | ... | @@ -3892,84 +5918,141 @@ typedef zig_f128 zig_c_longdouble; |
| 3892 | 5918 | typedef long double zig_c_longdouble; |
| 3893 | 5919 | #endif |
| 3894 | 5920 | |
| 3895 | #define zig_bitCast_float(Type, ReprType) \ | |
| 3896 | static inline zig_##Type zig_bitCast_##Type(ReprType repr) { \ | |
| 3897 | zig_##Type result; \ | |
| 3898 | memcpy(&result, &repr, sizeof(result)); \ | |
| 3899 | return result; \ | |
| 5921 | #if __AVR__ | |
| 5922 | typedef signed char zig_FloatCompareResult; | |
| 5923 | #elif defined(zig_aarch64) | |
| 5924 | typedef signed int zig_FloatCompareResult; | |
| 5925 | #elif __SIZEOF_LONG__ >= __SIZEOF_POINTER__ | |
| 5926 | typedef signed long zig_FloatCompareResult; | |
| 5927 | #else | |
| 5928 | typedef 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 | } |
| 3901 | zig_bitCast_float(f16, uint16_t) | |
| 3902 | zig_bitCast_float(f32, uint32_t) | |
| 3903 | zig_bitCast_float(f64, uint64_t) | |
| 3904 | zig_bitCast_float(f80, zig_u128) | |
| 3905 | zig_bitCast_float(f128, zig_u128) | |
| 5952 | zig_bitCast_float(16, 16, uint16_t, int16_t) | |
| 5953 | zig_bitCast_float(32, 32, uint32_t, int32_t) | |
| 5954 | zig_bitCast_float(64, 64, uint64_t, int64_t) | |
| 5955 | #if zig_has_f80 | |
| 5956 | zig_bitCast_float(80, 128, zig_u128, zig_i128) | |
| 5957 | #else | |
| 5958 | static 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 | } | |
| 5961 | static 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 | } | |
| 5964 | static 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 | } | |
| 5967 | static 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 | |
| 5971 | static 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 | } | |
| 5974 | static 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 | |
| 5982 | zig_bitCast_float(128, 128, zig_u128, zig_i128) | |
| 5983 | #else | |
| 5984 | static 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 | } | |
| 5987 | static 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 | } | |
| 5990 | static 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 | } | |
| 5993 | static 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 | |
| 3906 | 5997 | |
| 3907 | #define zig_convert_builtin(ExternResType, ResType, operation, ExternArgType, ArgType, version) \ | |
| 3908 | zig_extern ExternResType zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \ | |
| 3909 | zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(ExternArgType); \ | |
| 5998 | #define zig_convert_float_00(ResType, operation, ArgType, version) \ | |
| 5999 | zig_extern ResType zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \ | |
| 6000 | zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(ArgType arg); \ | |
| 6001 | return zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \ | |
| 6002 | zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(arg) | |
| 6003 | #define zig_convert_float_01(ResType, operation, ArgType, version) \ | |
| 6004 | zig_convert_float_00(ResType, operation, ArgType, version) | |
| 6005 | #define zig_convert_float_10(ResType, operation, ArgType, version) \ | |
| 6006 | zig_convert_float_00(ResType, operation, ArgType, version) | |
| 6007 | #define zig_convert_float_11(ResType, operation, ArgType, version) \ | |
| 6008 | return (ResType)arg | |
| 6009 | #define zig_convert_float(res_when, ResType, operation, arg_when, ArgType, version) \ | |
| 3910 | 6010 | static inline ResType zig_expand_concat(zig_expand_concat(zig_##operation, \ |
| 3911 | 6011 | zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType)(ArgType arg) { \ |
| 3912 | ResType res; \ | |
| 3913 | ExternResType extern_res; \ | |
| 3914 | ExternArgType extern_arg; \ | |
| 3915 | memcpy(&extern_arg, &arg, sizeof(extern_arg)); \ | |
| 3916 | extern_res = zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \ | |
| 3917 | zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(extern_arg); \ | |
| 3918 | memcpy(&res, &extern_res, sizeof(res)); \ | |
| 3919 | return extern_res; \ | |
| 3920 | } | |
| 3921 | zig_convert_builtin(zig_compiler_rt_f16, zig_f16, trunc, zig_f32, zig_f32, 2) | |
| 3922 | zig_convert_builtin(zig_compiler_rt_f16, zig_f16, trunc, zig_f64, zig_f64, 2) | |
| 3923 | zig_convert_builtin(zig_f16, zig_f16, trunc, zig_f80, zig_f80, 2) | |
| 3924 | zig_convert_builtin(zig_f16, zig_f16, trunc, zig_f128, zig_f128, 2) | |
| 3925 | zig_convert_builtin(zig_f32, zig_f32, extend, zig_compiler_rt_f16, zig_f16, 2) | |
| 3926 | zig_convert_builtin(zig_f32, zig_f32, trunc, zig_f80, zig_f80, 2) | |
| 3927 | zig_convert_builtin(zig_f32, zig_f32, trunc, zig_f128, zig_f128, 2) | |
| 3928 | zig_convert_builtin(zig_f64, zig_f64, extend, zig_compiler_rt_f16, zig_f16, 2) | |
| 3929 | zig_convert_builtin(zig_f64, zig_f64, trunc, zig_f80, zig_f80, 2) | |
| 3930 | zig_convert_builtin(zig_f64, zig_f64, trunc, zig_f128, zig_f128, 2) | |
| 3931 | zig_convert_builtin(zig_f80, zig_f80, extend, zig_f16, zig_f16, 2) | |
| 3932 | zig_convert_builtin(zig_f80, zig_f80, extend, zig_f32, zig_f32, 2) | |
| 3933 | zig_convert_builtin(zig_f80, zig_f80, extend, zig_f64, zig_f64, 2) | |
| 3934 | zig_convert_builtin(zig_f80, zig_f80, trunc, zig_f128, zig_f128, 2) | |
| 3935 | zig_convert_builtin(zig_f128, zig_f128, extend, zig_f16, zig_f16, 2) | |
| 3936 | zig_convert_builtin(zig_f128, zig_f128, extend, zig_f32, zig_f32, 2) | |
| 3937 | zig_convert_builtin(zig_f128, zig_f128, extend, zig_f64, zig_f64, 2) | |
| 3938 | zig_convert_builtin(zig_f128, zig_f128, extend, zig_f80, zig_f80, 2) | |
| 3939 | ||
| 3940 | #ifdef __ARM_EABI__ | |
| 3941 | ||
| 3942 | zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_d2f(zig_f64); | |
| 3943 | static inline zig_f32 zig_truncdfsf(zig_f64 arg) { return __aeabi_d2f(arg); } | |
| 3944 | ||
| 3945 | zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_f2d(zig_f32); | |
| 3946 | static inline zig_f64 zig_extendsfdf(zig_f32 arg) { return __aeabi_f2d(arg); } | |
| 3947 | ||
| 3948 | #else /* __ARM_EABI__ */ | |
| 3949 | ||
| 3950 | zig_convert_builtin(zig_f32, zig_f32, trunc, zig_f64, zig_f64, 2) | |
| 3951 | zig_convert_builtin(zig_f64, zig_f64, extend, zig_f32, zig_f32, 2) | |
| 3952 | ||
| 3953 | #endif /* __ARM_EABI__ */ | |
| 3954 | ||
| 3955 | #define zig_float_negate_builtin_0(w, c, sb) \ | |
| 3956 | zig_expand_concat(zig_xor_, zig_repr_f##w)(arg, zig_make_f##w(-0x0.0p0, c sb)) | |
| 3957 | #define zig_float_negate_builtin_1(w, c, sb) -arg | |
| 3958 | #define zig_float_negate_builtin(w, c, sb) \ | |
| 6012 | zig_expand_concat(zig_expand_concat(zig_convert_float_, zig_has_##res_when), \ | |
| 6013 | zig_has_##arg_when)(ResType, operation, ArgType, version); \ | |
| 6014 | } | |
| 6015 | ||
| 6016 | #define zig_convert_floats(SmallType, BigType) \ | |
| 6017 | zig_convert_float(SmallType, zig_##SmallType, trunc, BigType, zig_##BigType, 2) \ | |
| 6018 | zig_convert_float(BigType, zig_##BigType, extend, SmallType, zig_##SmallType, 2) | |
| 6019 | zig_convert_floats(f16, f32) | |
| 6020 | zig_convert_floats(f16, f64) | |
| 6021 | zig_convert_floats(f16, f80) | |
| 6022 | zig_convert_floats(f16, f128) | |
| 6023 | zig_convert_floats(f32, f64) | |
| 6024 | zig_convert_floats(f32, f80) | |
| 6025 | zig_convert_floats(f32, f128) | |
| 6026 | zig_convert_floats(f64, f80) | |
| 6027 | zig_convert_floats(f64, f128) | |
| 6028 | zig_convert_floats(f80, f128) | |
| 6029 | ||
| 6030 | #define zig_float_negate_builtin_0(w, sb) \ | |
| 6031 | zig_expand_concat(zig_xor_, zig_repr_f##w)(arg, zig_make_f##w(-0x0.0p0, sb)) | |
| 6032 | #define zig_float_negate_builtin_1(w, sb) -arg | |
| 6033 | #define zig_float_negate_builtin(w, sb) \ | |
| 3959 | 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 | } |
| 3962 | zig_float_negate_builtin(16, , UINT16_C(1) << 15 ) | |
| 3963 | zig_float_negate_builtin(32, , UINT32_C(1) << 31 ) | |
| 3964 | zig_float_negate_builtin(64, , UINT64_C(1) << 63 ) | |
| 3965 | zig_float_negate_builtin(80, zig_make_u128, (UINT64_C(1) << 15, UINT64_C(0))) | |
| 3966 | zig_float_negate_builtin(128, zig_make_u128, (UINT64_C(1) << 63, UINT64_C(0))) | |
| 6037 | zig_float_negate_builtin(16, UINT16_C(1) << 15) | |
| 6038 | zig_float_negate_builtin(32, UINT32_C(1) << 31) | |
| 6039 | zig_float_negate_builtin(64, UINT64_C(1) << 63) | |
| 6040 | ||
| 6041 | #undef zig_float_negate_builtin_0 | |
| 6042 | #define zig_float_negate_builtin_0(w, sb) \ | |
| 6043 | zig_make_repr_f##w(zig_mantissa_repr_f##w(arg), zig_xor_u16(zig_exponent_repr_f##w(arg), sb)) | |
| 6044 | zig_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)) | |
| 6049 | zig_float_negate_builtin(128, UINT64_C(1) << 63) | |
| 3967 | 6050 | |
| 3968 | 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 | 6053 | zig_compiler_rt_abbrev_zig_##Type), 2)(zig_##Type, zig_##Type); \ |
| 3971 | 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 | 6057 | #define zig_float_less_builtin_1(Type, operation) \ |
| 3975 | 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 | 6077 | return lhs operator rhs; \ |
| 3995 | 6078 | } |
| 3996 | 6079 | |
| 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 | 6084 | #define zig_common_float_builtins(w) \ |
| 3998 | zig_convert_builtin( int64_t, int64_t, fix, zig_f##w, zig_f##w, ) \ | |
| 3999 | zig_convert_builtin(zig_i128, zig_i128, fix, zig_f##w, zig_f##w, ) \ | |
| 4000 | zig_convert_builtin(zig_u128, zig_u128, fixuns, zig_f##w, zig_f##w, ) \ | |
| 4001 | zig_convert_builtin(zig_f##w, zig_f##w, float, int64_t, int64_t, ) \ | |
| 4002 | zig_convert_builtin(zig_f##w, zig_f##w, float, zig_i128, zig_i128, ) \ | |
| 4003 | zig_convert_builtin(zig_f##w, zig_f##w, floatun, zig_u128, zig_u128, ) \ | |
| 6085 | zig_convert_float(always, int32_t, fix, f##w, zig_f##w, ) \ | |
| 6086 | zig_convert_float(always, int64_t, fix, f##w, zig_f##w, ) \ | |
| 6087 | zig_convert_float(int128, zig_i128, fix, f##w, zig_f##w, ) \ | |
| 6088 | zig_convert_float(always, uint32_t, fixuns, f##w, zig_f##w, ) \ | |
| 6089 | zig_convert_float(always, uint64_t, fixuns, f##w, zig_f##w, ) \ | |
| 6090 | zig_convert_float(int128, zig_u128, fixuns, f##w, zig_f##w, ) \ | |
| 6091 | zig_convert_float(f##w, zig_f##w, float, always, int32_t, ) \ | |
| 6092 | zig_convert_float(f##w, zig_f##w, float, always, int64_t, ) \ | |
| 6093 | zig_convert_float(f##w, zig_f##w, floatun, always, uint32_t, ) \ | |
| 6094 | zig_convert_float(f##w, zig_f##w, floatun, always, uint64_t, ) \ | |
| 6095 | \ | |
| 6096 | static inline void zig_expand_concat(zig_expand_concat(zig_fix, \ | |
| 6097 | zig_compiler_rt_abbrev_zig_f##w), ei)(void *res, zig_f##w arg, uint16_t bits) { \ | |
| 6098 | zig_extern void zig_expand_concat(zig_expand_concat(__fix, \ | |
| 6099 | zig_compiler_rt_abbrev_zig_f##w), ei)(uint8_t *res, uintptr_t bits, zig_f##w arg); \ | |
| 6100 | zig_expand_concat(zig_expand_concat(__fix, \ | |
| 6101 | zig_compiler_rt_abbrev_zig_f##w), ei)(res, bits, arg); \ | |
| 6102 | } \ | |
| 6103 | \ | |
| 6104 | static inline void zig_expand_concat(zig_expand_concat(zig_fixuns, \ | |
| 6105 | zig_compiler_rt_abbrev_zig_f##w), ei)(void *res, zig_f##w arg, uint16_t bits) { \ | |
| 6106 | zig_extern void zig_expand_concat(zig_expand_concat(__fixuns, \ | |
| 6107 | zig_compiler_rt_abbrev_zig_f##w), ei)(uint8_t *res, uintptr_t bits, zig_f##w arg); \ | |
| 6108 | zig_expand_concat(zig_expand_concat(__fixuns, \ | |
| 6109 | zig_compiler_rt_abbrev_zig_f##w), ei)(res, bits, arg); \ | |
| 6110 | } \ | |
| 6111 | \ | |
| 6112 | static inline zig_f##w zig_expand_concat(zig_floatei, \ | |
| 6113 | zig_compiler_rt_abbrev_zig_f##w)(void *res, uint16_t bits) { \ | |
| 6114 | zig_extern zig_f##w zig_expand_concat(__floatei, \ | |
| 6115 | zig_compiler_rt_abbrev_zig_f##w)(const uint8_t *arg, uintptr_t bits); \ | |
| 6116 | return zig_expand_concat(__floatei, zig_compiler_rt_abbrev_zig_f##w)(res, bits); \ | |
| 6117 | } \ | |
| 6118 | \ | |
| 6119 | static inline zig_f##w zig_expand_concat(zig_floatunei, \ | |
| 6120 | zig_compiler_rt_abbrev_zig_f##w)(void *res, uint16_t bits) { \ | |
| 6121 | zig_extern zig_f##w zig_expand_concat(__floatunei, \ | |
| 6122 | zig_compiler_rt_abbrev_zig_f##w)(const uint8_t *arg, uintptr_t bits); \ | |
| 6123 | return zig_expand_concat(__floatunei, zig_compiler_rt_abbrev_zig_f##w)(res, bits); \ | |
| 6124 | } \ | |
| 6125 | \ | |
| 4004 | 6126 | zig_expand_concat(zig_float_less_builtin_, zig_has_f##w)(f##w, cmp) \ |
| 4005 | 6127 | zig_expand_concat(zig_float_less_builtin_, zig_has_f##w)(f##w, ne) \ |
| 4006 | 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 | 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 | 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 | 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 | 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 | 6165 | return zig_ceil_f##w(zig_div_f##w(lhs, rhs)); \ |
| 4044 | 6166 | } \ |
| 4045 | 6167 | \ |
| 4046 | 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 | } |
| 4049 | zig_common_float_builtins(16) | |
| 4050 | zig_common_float_builtins(32) | |
| 4051 | zig_common_float_builtins(64) | |
| 4052 | zig_common_float_builtins(80) | |
| 4053 | zig_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, ) | |
| 4062 | 6171 | zig_float_builtins(16) |
| 4063 | zig_float_builtins(80) | |
| 4064 | zig_float_builtins(128) | |
| 4065 | ||
| 4066 | #ifdef __ARM_EABI__ | |
| 4067 | ||
| 4068 | zig_extern zig_callconv(pcs("aapcs")) int32_t __aeabi_f2iz(zig_f32); | |
| 4069 | static inline int32_t zig_fixsfsi(zig_f32 arg) { return __aeabi_f2iz(arg); } | |
| 4070 | ||
| 4071 | zig_extern zig_callconv(pcs("aapcs")) uint32_t __aeabi_f2uiz(zig_f32); | |
| 4072 | static inline uint32_t zig_fixunssfsi(zig_f32 arg) { return __aeabi_f2uiz(arg); } | |
| 4073 | ||
| 4074 | zig_extern zig_callconv(pcs("aapcs")) uint64_t __aeabi_f2ulz(zig_f32); | |
| 4075 | static inline uint64_t zig_fixunssfdi(zig_f32 arg) { return __aeabi_f2ulz(arg); } | |
| 4076 | ||
| 4077 | zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_i2f(int32_t); | |
| 4078 | static inline zig_f32 zig_floatsisf(int32_t arg) { return __aeabi_i2f(arg); } | |
| 4079 | ||
| 4080 | zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_ui2f(uint32_t); | |
| 4081 | static inline zig_f32 zig_floatunsisf(uint32_t arg) { return __aeabi_ui2f(arg); } | |
| 4082 | ||
| 4083 | zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_ul2f(uint64_t); | |
| 4084 | static inline zig_f32 zig_floatundisf(uint64_t arg) { return __aeabi_ul2f(arg); } | |
| 4085 | ||
| 4086 | zig_extern zig_callconv(pcs("aapcs")) int32_t __aeabi_d2iz(zig_f64); | |
| 4087 | static inline int32_t zig_fixdfsi(zig_f64 arg) { return __aeabi_d2iz(arg); } | |
| 4088 | ||
| 4089 | zig_extern zig_callconv(pcs("aapcs")) uint32_t __aeabi_d2uiz(zig_f64); | |
| 4090 | static inline uint32_t zig_fixunsdfsi(zig_f64 arg) { return __aeabi_d2uiz(arg); } | |
| 4091 | ||
| 4092 | zig_extern zig_callconv(pcs("aapcs")) uint64_t __aeabi_d2ulz(zig_f64); | |
| 4093 | static inline uint64_t zig_fixunsdfdi(zig_f64 arg) { return __aeabi_d2ulz(arg); } | |
| 4094 | ||
| 4095 | zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_i2d(int32_t); | |
| 4096 | static inline zig_f64 zig_floatsidf(int32_t arg) { return __aeabi_i2d(arg); } | |
| 4097 | ||
| 4098 | zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_ui2d(uint32_t); | |
| 4099 | static inline zig_f64 zig_floatunsidf(uint32_t arg) { return __aeabi_ui2d(arg); } | |
| 4100 | ||
| 4101 | zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_ul2d(uint64_t); | |
| 4102 | static inline zig_f64 zig_floatundidf(uint64_t arg) { return __aeabi_ul2d(arg); } | |
| 4103 | ||
| 4104 | #else /* __ARM_EABI__ */ | |
| 4105 | ||
| 4106 | 6172 | zig_float_builtins(32) |
| 4107 | 6173 | zig_float_builtins(64) |
| 4108 | ||
| 4109 | #endif /* __ARM_EABI__ */ | |
| 6174 | zig_float_builtins(80) | |
| 6175 | #if defined(zig_x86_32) | |
| 6176 | zig_common_float_builtins(128) | |
| 6177 | static 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 | } | |
| 6181 | static 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) | |
| 6186 | zig_common_float_builtins(128) | |
| 6187 | static inline zig_f128 zig_floattitf(zig_i128 arg) { | |
| 6188 | extern zig_f128 __floattitf(zig_i128 arg); | |
| 6189 | return __floattitf(arg); | |
| 6190 | } | |
| 6191 | static 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 | |
| 6196 | zig_float_builtins(128) | |
| 6197 | #endif | |
| 4110 | 6198 | |
| 4111 | 6199 | /* ============================ Atomics Support ============================= */ |
| 4112 | 6200 | |
| ... | ... | @@ -4410,19 +6498,19 @@ typedef int zig_memory_order; |
| 4410 | 6498 | } \ |
| 4411 | 6499 | static inline void zig_msvc_atomic_store_##ZigType(Type volatile* obj, Type value) { \ |
| 4412 | 6500 | (void)_InterlockedExchange##suffix((SigType volatile*)obj, (SigType)value); \ |
| 4413 | } \ | |
| 6501 | } \ | |
| 4414 | 6502 | static inline Type zig_msvc_atomic_load_zig_memory_order_relaxed_##ZigType(Type volatile* obj) { \ |
| 4415 | 6503 | return __iso_volatile_load##iso_suffix((SigType volatile*)obj); \ |
| 4416 | 6504 | } \ |
| 4417 | 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 | 6507 | _ReadWriteBarrier(); \ |
| 4420 | return val; \ | |
| 6508 | return value; \ | |
| 4421 | 6509 | } \ |
| 4422 | 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 | 6512 | _ReadWriteBarrier(); \ |
| 4425 | return val; \ | |
| 6513 | return value; \ | |
| 4426 | 6514 | } |
| 4427 | 6515 | |
| 4428 | 6516 | zig_msvc_atomics( u8, uint8_t, char, 8, 8) |
| ... | ... | @@ -4465,14 +6553,14 @@ zig_msvc_atomics(i64, int64_t, __int64, 64, 64) |
| 4465 | 6553 | zig_##Type result; \ |
| 4466 | 6554 | SigType initial = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \ |
| 4467 | 6555 | _ReadWriteBarrier(); \ |
| 4468 | memcpy(&result, &initial, sizeof(result)); \ | |
| 6556 | memcpy(&result, &initial, sizeof(result)); \ | |
| 4469 | 6557 | return result; \ |
| 4470 | 6558 | } \ |
| 4471 | 6559 | static inline zig_##Type zig_msvc_atomic_load_zig_memory_order_seq_cst_##Type(zig_##Type volatile* obj) { \ |
| 4472 | 6560 | zig_##Type result; \ |
| 4473 | 6561 | SigType initial = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \ |
| 4474 | 6562 | _ReadWriteBarrier(); \ |
| 4475 | memcpy(&result, &initial, sizeof(result)); \ | |
| 6563 | memcpy(&result, &initial, sizeof(result)); \ | |
| 4476 | 6564 | return result; \ |
| 4477 | 6565 | } |
| 4478 | 6566 | |
| ... | ... | @@ -4502,9 +6590,9 @@ static inline void* zig_msvc_atomic_load_zig_memory_order_relaxed_p32(void volat |
| 4502 | 6590 | } |
| 4503 | 6591 | |
| 4504 | 6592 | static 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 | 6594 | _ReadWriteBarrier(); |
| 4507 | return val; | |
| 6595 | return value; | |
| 4508 | 6596 | } |
| 4509 | 6597 | |
| 4510 | 6598 | static inline void* zig_msvc_atomic_load_zig_memory_order_seq_cst_p32(void volatile* obj) { |
| ... | ... | @@ -4532,9 +6620,9 @@ static inline void* zig_msvc_atomic_load_zig_memory_order_relaxed_p64(void volat |
| 4532 | 6620 | } |
| 4533 | 6621 | |
| 4534 | 6622 | static 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 | 6624 | _ReadWriteBarrier(); |
| 4537 | return val; | |
| 6625 | return value; | |
| 4538 | 6626 | } |
| 4539 | 6627 | |
| 4540 | 6628 | static 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 | 144 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 145 | 145 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 146 | 146 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO |
| 147 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 148 | 147 | |
| 149 | 148 | try comptime testAbsSignedBigInt(); |
| 150 | 149 | try testAbsSignedBigInt(); |
| ... | ... | @@ -256,7 +255,6 @@ fn testAbsFloats(comptime T: type) !void { |
| 256 | 255 | |
| 257 | 256 | test "@abs int vectors" { |
| 258 | 257 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 259 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 260 | 258 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 261 | 259 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 262 | 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 | 129 | y: u8, |
| 130 | 130 | }; |
| 131 | 131 | const expected = switch (builtin.cpu.arch) { |
| 132 | .s390x, | |
| 133 | => .{ | |
| 132 | .s390x => .{ | |
| 134 | 133 | .a_align = 8, |
| 135 | 134 | .a_size = 16, |
| 136 | 135 | |
| ... | ... | @@ -142,7 +141,32 @@ test "alignment and size of structs with 128-bit fields" { |
| 142 | 141 | .u129_align = 8, |
| 143 | 142 | .u129_size = 24, |
| 144 | 143 | }, |
| 145 | ||
| 144 | .x86 => switch (builtin.os.tag) { | |
| 145 | else => .{ | |
| 146 | .a_align = 4, | |
| 147 | .a_size = 16, | |
| 148 | ||
| 149 | .b_align = 4, | |
| 150 | .b_size = 20, | |
| 151 | ||
| 152 | .u128_align = 4, | |
| 153 | .u128_size = 16, | |
| 154 | .u129_align = 4, | |
| 155 | .u129_size = 20, | |
| 156 | }, | |
| 157 | .uefi, .windows => .{ | |
| 158 | .a_align = 8, | |
| 159 | .a_size = 16, | |
| 160 | ||
| 161 | .b_align = 8, | |
| 162 | .b_size = 24, | |
| 163 | ||
| 164 | .u128_align = 8, | |
| 165 | .u128_size = 16, | |
| 166 | .u129_align = 8, | |
| 167 | .u129_size = 24, | |
| 168 | }, | |
| 169 | }, | |
| 146 | 170 | .amdgcn, |
| 147 | 171 | .arm, |
| 148 | 172 | .armeb, |
| ... | ... | @@ -155,12 +179,13 @@ test "alignment and size of structs with 128-bit fields" { |
| 155 | 179 | .powerpc, |
| 156 | 180 | .powerpcle, |
| 157 | 181 | .riscv32, |
| 182 | .sparc, | |
| 158 | 183 | => .{ |
| 159 | 184 | .a_align = 8, |
| 160 | 185 | .a_size = 16, |
| 161 | 186 | |
| 162 | .b_align = 16, | |
| 163 | .b_size = 32, | |
| 187 | .b_align = 8, | |
| 188 | .b_size = 24, | |
| 164 | 189 | |
| 165 | 190 | .u128_align = 8, |
| 166 | 191 | .u128_size = 16, |
| ... | ... | @@ -178,12 +203,10 @@ test "alignment and size of structs with 128-bit fields" { |
| 178 | 203 | .nvptx64, |
| 179 | 204 | .powerpc64, |
| 180 | 205 | .powerpc64le, |
| 181 | .sparc, | |
| 182 | 206 | .sparc64, |
| 183 | 207 | .riscv64, |
| 184 | 208 | .wasm32, |
| 185 | 209 | .wasm64, |
| 186 | .x86, | |
| 187 | 210 | .x86_64, |
| 188 | 211 | => .{ |
| 189 | 212 | .a_align = 16, |
| ... | ... | @@ -200,12 +223,11 @@ test "alignment and size of structs with 128-bit fields" { |
| 200 | 223 | |
| 201 | 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 | 226 | comptime { |
| 205 | assert(@alignOf(A) == @max(expected.a_align, min_struct_align)); | |
| 227 | assert(@alignOf(A) == expected.a_align); | |
| 206 | 228 | assert(@sizeOf(A) == expected.a_size); |
| 207 | 229 | |
| 208 | assert(@alignOf(B) == @max(expected.b_align, min_struct_align)); | |
| 230 | assert(@alignOf(B) == expected.b_align); | |
| 209 | 231 | assert(@sizeOf(B) == expected.b_size); |
| 210 | 232 | |
| 211 | 233 | assert(@alignOf(u128) == expected.u128_align); |
| ... | ... | @@ -547,8 +569,6 @@ test "sub-aligned pointer field access" { |
| 547 | 569 | } |
| 548 | 570 | |
| 549 | 571 | test "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 | 572 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 553 | 573 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO |
| 554 | 574 | |
| ... | ... | @@ -582,7 +602,6 @@ test "zero-bit fields in extern struct pad fields appropriately" { |
| 582 | 602 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 583 | 603 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; |
| 584 | 604 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 585 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 586 | 605 | |
| 587 | 606 | const S = extern struct { |
| 588 | 607 | x: u8, |
test/behavior/basic.zig-3| ... | ... | @@ -797,10 +797,8 @@ test "auto created variables have correct alignment" { |
| 797 | 797 | } |
| 798 | 798 | |
| 799 | 799 | test "extern variable with non-pointer opaque type" { |
| 800 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | |
| 801 | 800 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 802 | 801 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 803 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 804 | 802 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO |
| 805 | 803 | |
| 806 | 804 | @export(&var_to_export, .{ .name = "opaque_extern_var" }); |
| ... | ... | @@ -1398,7 +1396,6 @@ test "allocation and looping over 3-byte integer" { |
| 1398 | 1396 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1399 | 1397 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 1400 | 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 | |
| 1402 | 1399 | |
| 1403 | 1400 | try expect(@sizeOf(u24) == 4); |
| 1404 | 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 | 147 | |
| 148 | 148 | test "Saturating Shift Left" { |
| 149 | 149 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 150 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 151 | 150 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; |
| 152 | 151 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 153 | 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 | 210 | |
| 211 | 211 | test "@bitCast packed struct of floats" { |
| 212 | 212 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 213 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 214 | 213 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 215 | 214 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 216 | 215 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| ... | ... | @@ -247,7 +246,6 @@ test "@bitCast packed struct of floats" { |
| 247 | 246 | |
| 248 | 247 | test "comptime @bitCast packed struct to int and back" { |
| 249 | 248 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 250 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 251 | 249 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 252 | 250 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 253 | 251 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| ... | ... | @@ -283,7 +281,6 @@ test "comptime @bitCast packed struct to int and back" { |
| 283 | 281 | test "bitcast vector to integer and back" { |
| 284 | 282 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 285 | 283 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 286 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 287 | 284 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 288 | 285 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 289 | 286 | |
| ... | ... | @@ -329,10 +326,10 @@ fn bitCastWrapper128(x: f128) u128 { |
| 329 | 326 | } |
| 330 | 327 | test "bitcast nan float does not modify signaling bit" { |
| 331 | 328 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 332 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 333 | 329 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 334 | 330 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 335 | 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; | |
| 336 | 333 | |
| 337 | 334 | const snan_u16: u16 = 0x7D00; |
| 338 | 335 | const snan_u32: u32 = 0x7FA00000; |
| ... | ... | @@ -383,7 +380,6 @@ test "bitcast nan float does not modify signaling bit" { |
| 383 | 380 | test "@bitCast of packed struct of bools all true" { |
| 384 | 381 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 385 | 382 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 386 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 387 | 383 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO |
| 388 | 384 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO |
| 389 | 385 | |
| ... | ... | @@ -404,7 +400,6 @@ test "@bitCast of packed struct of bools all true" { |
| 404 | 400 | test "@bitCast of packed struct of bools all false" { |
| 405 | 401 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 406 | 402 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 407 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 408 | 403 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO |
| 409 | 404 | |
| 410 | 405 | const P = packed struct { |
| ... | ... | @@ -437,6 +432,22 @@ test "@bitCast of packed struct with void field to integer" { |
| 437 | 432 | try comptime S.doTheTest(123); |
| 438 | 433 | } |
| 439 | 434 | |
| 435 | test "@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 | ||
| 440 | 451 | test "@bitCast vector to array with different element size" { |
| 441 | 452 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 442 | 453 |
test/behavior/builtin_functions_returning_void_or_noreturn.zig-1| ... | ... | @@ -6,7 +6,6 @@ var x: u8 = 1; |
| 6 | 6 | |
| 7 | 7 | // This excludes builtin functions that return void or noreturn that cannot be tested. |
| 8 | 8 | test { |
| 9 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | |
| 10 | 9 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 11 | 10 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 12 | 11 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
test/behavior/call.zig-1| ... | ... | @@ -21,7 +21,6 @@ test "super basic invocations" { |
| 21 | 21 | |
| 22 | 22 | test "basic invocations" { |
| 23 | 23 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 24 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | |
| 25 | 24 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 26 | 25 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 27 | 26 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
test/behavior/cast.zig+7-19| ... | ... | @@ -120,6 +120,7 @@ test "@floatFromInt" { |
| 120 | 120 | try expect(@as(i32, @floor(f)) == k); |
| 121 | 121 | try expect(@as(i32, @ceil(f)) == k); |
| 122 | 122 | try expect(@as(i32, @trunc(f)) == k); |
| 123 | try expect(@as(i32, @trunc(@floor(f))) == k); | |
| 123 | 124 | } |
| 124 | 125 | }; |
| 125 | 126 | try S.doTheTest(); |
| ... | ... | @@ -134,7 +135,6 @@ test "@intFromFloat > 128 bits" { |
| 134 | 135 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 135 | 136 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 136 | 137 | if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; |
| 137 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 138 | 138 | |
| 139 | 139 | try testIntFromFloat(f16, 1024, u140, 1024); |
| 140 | 140 | try testIntFromFloat(f16, -1024, i140, -1024); |
| ... | ... | @@ -160,7 +160,6 @@ test "@floatFromInt > 128 bits" { |
| 160 | 160 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 161 | 161 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 162 | 162 | if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; |
| 163 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 164 | 163 | |
| 165 | 164 | try testFloatFromInt(u140, 1024, f16, 1024); |
| 166 | 165 | try testFloatFromInt(i140, -1024, f16, -1024); |
| ... | ... | @@ -182,8 +181,8 @@ test "@floatFromInt(f80)" { |
| 182 | 181 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 183 | 182 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 184 | 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 | 184 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 185 | if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; | |
| 187 | 186 | |
| 188 | 187 | const S = struct { |
| 189 | 188 | fn doTheTest(comptime Int: type) !void { |
| ... | ... | @@ -199,6 +198,7 @@ test "@floatFromInt(f80)" { |
| 199 | 198 | try expect(@as(Int, @floor(f)) == k); |
| 200 | 199 | try expect(@as(Int, @ceil(f)) == k); |
| 201 | 200 | try expect(@as(Int, @trunc(f)) == k); |
| 201 | try expect(@as(Int, @trunc(@floor(f))) == k); | |
| 202 | 202 | } |
| 203 | 203 | }; |
| 204 | 204 | try S.doTheTest(i31); |
| ... | ... | @@ -207,7 +207,7 @@ test "@floatFromInt(f80)" { |
| 207 | 207 | try S.doTheTest(i64); |
| 208 | 208 | try S.doTheTest(i80); |
| 209 | 209 | try S.doTheTest(i128); |
| 210 | // try S.doTheTest(i256); // TODO missing compiler_rt symbols | |
| 210 | try S.doTheTest(i256); | |
| 211 | 211 | try comptime S.doTheTest(i31); |
| 212 | 212 | try comptime S.doTheTest(i32); |
| 213 | 213 | try comptime S.doTheTest(i45); |
| ... | ... | @@ -281,6 +281,7 @@ test "type coercion from int to float" { |
| 281 | 281 | test "@intFromFloat" { |
| 282 | 282 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 283 | 283 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 284 | ||
| 284 | 285 | try testIntFromFloats(); |
| 285 | 286 | try comptime testIntFromFloats(); |
| 286 | 287 | } |
| ... | ... | @@ -498,7 +499,7 @@ test "array coercion to undefined at runtime" { |
| 498 | 499 | |
| 499 | 500 | @setRuntimeSafety(true); |
| 500 | 501 | |
| 501 | if (builtin.mode != .Debug and builtin.mode != .ReleaseSafe) { | |
| 502 | if (builtin.mode != .debug and builtin.mode != .safe) { | |
| 502 | 503 | return error.SkipZigTest; |
| 503 | 504 | } |
| 504 | 505 | |
| ... | ... | @@ -1473,11 +1474,6 @@ fn foobar(func: PFN_void) !void { |
| 1473 | 1474 | test "cast function with an opaque parameter" { |
| 1474 | 1475 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 1475 | 1476 | |
| 1476 | if (builtin.zig_backend == .stage2_c) { | |
| 1477 | // https://github.com/ziglang/zig/issues/16845 | |
| 1478 | return error.SkipZigTest; | |
| 1479 | } | |
| 1480 | ||
| 1481 | 1477 | const Container = struct { |
| 1482 | 1478 | const Ctx = opaque {}; |
| 1483 | 1479 | ctx: *Ctx, |
| ... | ... | @@ -1724,9 +1720,7 @@ test "cast f16 to wider types" { |
| 1724 | 1720 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1725 | 1721 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1726 | 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 | 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; | |
| 1730 | 1724 | |
| 1731 | 1725 | const S = struct { |
| 1732 | 1726 | fn doTheTest() !void { |
| ... | ... | @@ -1831,21 +1825,15 @@ test "pointer to empty struct literal to mutable slice" { |
| 1831 | 1825 | |
| 1832 | 1826 | test "coerce between pointers of compatible differently-named floats" { |
| 1833 | 1827 | 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 | 1828 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1836 | 1829 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 1837 | 1830 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 1838 | 1831 | |
| 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 | 1832 | const F = switch (@typeInfo(c_longdouble).float.bits) { |
| 1845 | 1833 | 64 => f64, |
| 1846 | 1834 | 80 => f80, |
| 1847 | 1835 | 128 => f128, |
| 1848 | else => @compileError("unreachable"), | |
| 1836 | else => comptime unreachable, | |
| 1849 | 1837 | }; |
| 1850 | 1838 | var f1: F = 12.34; |
| 1851 | 1839 | const f2: *c_longdouble = &f1; |
test/behavior/cast_int.zig-1| ... | ... | @@ -168,7 +168,6 @@ test "@intCast <= 64 bits" { |
| 168 | 168 | |
| 169 | 169 | test "@intCast > 128 bits" { |
| 170 | 170 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 171 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 172 | 171 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 173 | 172 | |
| 174 | 173 | try testIntCast(u8, 123, u140, 123); |
test/behavior/eval.zig-1| ... | ... | @@ -513,7 +513,6 @@ test "runtime 128 bit integer division" { |
| 513 | 513 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 514 | 514 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 515 | 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 | 516 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 518 | 517 | |
| 519 | 518 | var a: u128 = 152313999999999991610955792383; |
test/behavior/export_builtin.zig-15| ... | ... | @@ -5,11 +5,6 @@ const expect = std.testing.expect; |
| 5 | 5 | test "exporting enum value" { |
| 6 | 6 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 7 | 7 | |
| 8 | if (builtin.cpu.arch.isWasm()) { | |
| 9 | // https://github.com/ziglang/zig/issues/4866 | |
| 10 | return error.SkipZigTest; | |
| 11 | } | |
| 12 | ||
| 13 | 8 | const S = struct { |
| 14 | 9 | const E = enum(c_int) { one, two }; |
| 15 | 10 | const e: E = .two; |
| ... | ... | @@ -35,11 +30,6 @@ test "exporting with internal linkage" { |
| 35 | 30 | test "exporting using namespace access" { |
| 36 | 31 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 37 | 32 | |
| 38 | if (builtin.cpu.arch.isWasm()) { | |
| 39 | // https://github.com/ziglang/zig/issues/4866 | |
| 40 | return error.SkipZigTest; | |
| 41 | } | |
| 42 | ||
| 43 | 33 | const S = struct { |
| 44 | 34 | const Inner = struct { |
| 45 | 35 | const x: u32 = 5; |
| ... | ... | @@ -57,11 +47,6 @@ test "exporting comptime-known value" { |
| 57 | 47 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; |
| 58 | 48 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 59 | 49 | |
| 60 | if (builtin.cpu.arch.isWasm()) { | |
| 61 | // https://github.com/ziglang/zig/issues/4866 | |
| 62 | return error.SkipZigTest; | |
| 63 | } | |
| 64 | ||
| 65 | 50 | const x: u32 = 10; |
| 66 | 51 | @export(&x, .{ .name = "exporting_comptime_known_value_foo" }); |
| 67 | 52 | const S = struct { |
test/behavior/extern.zig-1| ... | ... | @@ -3,7 +3,6 @@ const std = @import("std"); |
| 3 | 3 | const expect = std.testing.expect; |
| 4 | 4 | |
| 5 | 5 | test "anyopaque extern symbol" { |
| 6 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 7 | 6 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; |
| 8 | 7 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 9 | 8 |
test/behavior/field_parent_ptr.zig-3| ... | ... | @@ -586,7 +586,6 @@ test "@fieldParentPtr extern struct last zero-bit field" { |
| 586 | 586 | } |
| 587 | 587 | |
| 588 | 588 | test "@fieldParentPtr unaligned packed struct" { |
| 589 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 590 | 589 | if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; |
| 591 | 590 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 592 | 591 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| ... | ... | @@ -725,7 +724,6 @@ test "@fieldParentPtr unaligned packed struct" { |
| 725 | 724 | } |
| 726 | 725 | |
| 727 | 726 | test "@fieldParentPtr aligned packed struct" { |
| 728 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 729 | 727 | if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; |
| 730 | 728 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 731 | 729 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| ... | ... | @@ -1897,7 +1895,6 @@ test "@fieldParentPtr packed union" { |
| 1897 | 1895 | } |
| 1898 | 1896 | |
| 1899 | 1897 | test "@fieldParentPtr tagged union all zero-bit fields" { |
| 1900 | if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; | |
| 1901 | 1898 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 1902 | 1899 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 1903 | 1900 |
test/behavior/floatop.zig+10-50| ... | ... | @@ -118,7 +118,6 @@ fn testMul(comptime T: type) !void { |
| 118 | 118 | test "cmp f16" { |
| 119 | 119 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 120 | 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 | |
| 122 | 121 | |
| 123 | 122 | try testCmp(f16); |
| 124 | 123 | try comptime testCmp(f16); |
| ... | ... | @@ -127,7 +126,6 @@ test "cmp f16" { |
| 127 | 126 | test "cmp f32" { |
| 128 | 127 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 129 | 128 | 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 | |
| 131 | 129 | |
| 132 | 130 | try testCmp(f32); |
| 133 | 131 | try comptime testCmp(f32); |
| ... | ... | @@ -142,7 +140,6 @@ test "cmp f64" { |
| 142 | 140 | |
| 143 | 141 | test "cmp f128" { |
| 144 | 142 | 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 | 143 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 147 | 144 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 148 | 145 | |
| ... | ... | @@ -152,7 +149,6 @@ test "cmp f128" { |
| 152 | 149 | |
| 153 | 150 | test "cmp f80/c_longdouble" { |
| 154 | 151 | 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 | 152 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 157 | 153 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 158 | 154 | |
| ... | ... | @@ -220,7 +216,6 @@ test "vector cmp f16" { |
| 220 | 216 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 221 | 217 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 222 | 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 | 219 | if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .hexagon) return error.SkipZigTest; |
| 225 | 220 | |
| 226 | 221 | try testCmpVector(f16); |
| ... | ... | @@ -233,7 +228,7 @@ test "vector cmp f32" { |
| 233 | 228 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 234 | 229 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 235 | 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 | 232 | if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .hexagon) return error.SkipZigTest; |
| 238 | 233 | |
| 239 | 234 | try testCmpVector(f32); |
| ... | ... | @@ -253,10 +248,9 @@ test "vector cmp f64" { |
| 253 | 248 | test "vector cmp f128" { |
| 254 | 249 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 255 | 250 | 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 | 251 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 258 | 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 | 254 | if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .hexagon) return error.SkipZigTest; |
| 261 | 255 | |
| 262 | 256 | try testCmpVector(f128); |
| ... | ... | @@ -266,7 +260,7 @@ test "vector cmp f128" { |
| 266 | 260 | test "vector cmp f80/c_longdouble" { |
| 267 | 261 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 268 | 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 | 264 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 271 | 265 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 272 | 266 | |
| ... | ... | @@ -381,11 +375,7 @@ test "@sqrt f80/f128/c_longdouble" { |
| 381 | 375 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 382 | 376 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 383 | 377 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 384 | ||
| 385 | if (builtin.os.tag == .freebsd) { | |
| 386 | // TODO https://github.com/ziglang/zig/issues/10875 | |
| 387 | return error.SkipZigTest; | |
| 388 | } | |
| 378 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; | |
| 389 | 379 | |
| 390 | 380 | try testSqrt(f80); |
| 391 | 381 | try comptime testSqrt(f80); |
| ... | ... | @@ -431,9 +421,9 @@ fn testSqrt(comptime T: type) !void { |
| 431 | 421 | var inf: T = math.inf(T); |
| 432 | 422 | try expect(math.isPositiveInf(@sqrt(inf))); |
| 433 | 423 | var zero: T = 0.0; |
| 434 | try expect(@sqrt(zero) == 0.0); | |
| 424 | try expect(math.isPositiveZero(@sqrt(zero))); | |
| 435 | 425 | var neg_zero: T = -0.0; |
| 436 | try expect(@sqrt(neg_zero) == 0.0); | |
| 426 | try expect(math.isNegativeZero(@sqrt(neg_zero))); | |
| 437 | 427 | var neg_one: T = -1.0; |
| 438 | 428 | try expect(math.isNan(@sqrt(neg_one))); |
| 439 | 429 | var nan: T = math.nan(T); |
| ... | ... | @@ -947,7 +937,7 @@ test "@log2 with vectors" { |
| 947 | 937 | builtin.cpu.arch == .aarch64 and |
| 948 | 938 | builtin.os.tag == .windows) return error.SkipZigTest; |
| 949 | 939 | |
| 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 | 941 | // https://codeberg.org/ziglang/zig/issues/35518 |
| 952 | 942 | return error.SkipZigTest; |
| 953 | 943 | } |
| ... | ... | @@ -1054,7 +1044,6 @@ test "@abs f32/f64" { |
| 1054 | 1044 | |
| 1055 | 1045 | test "@abs f80/f128/c_longdouble" { |
| 1056 | 1046 | 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 | 1047 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1059 | 1048 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 1060 | 1049 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| ... | ... | @@ -1172,16 +1161,10 @@ test "@floor f32/f64" { |
| 1172 | 1161 | |
| 1173 | 1162 | test "@floor f80/f128/c_longdouble" { |
| 1174 | 1163 | 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 | 1164 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1177 | 1165 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 1178 | 1166 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 1179 | 1167 | |
| 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 | 1168 | try testFloor(f80); |
| 1186 | 1169 | try comptime testFloor(f80); |
| 1187 | 1170 | try testFloor(f128); |
| ... | ... | @@ -1261,16 +1244,10 @@ test "@ceil f32/f64" { |
| 1261 | 1244 | |
| 1262 | 1245 | test "@ceil f80/f128/c_longdouble" { |
| 1263 | 1246 | 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 | 1247 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1266 | 1248 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 1267 | 1249 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 1268 | 1250 | |
| 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 | 1251 | try testCeil(f80); |
| 1275 | 1252 | try comptime testCeil(f80); |
| 1276 | 1253 | try testCeil(f128); |
| ... | ... | @@ -1281,16 +1258,10 @@ test "@ceil f80/f128/c_longdouble" { |
| 1281 | 1258 | |
| 1282 | 1259 | test "@ceil f80 maxInt(u64)" { |
| 1283 | 1260 | 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 | 1261 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1286 | 1262 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 1287 | 1263 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 1288 | 1264 | |
| 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 | 1265 | var x: u64 = std.math.maxInt(u64); |
| 1295 | 1266 | x = x; |
| 1296 | 1267 | const float: f80 = @floatFromInt(x); |
| ... | ... | @@ -1368,16 +1339,10 @@ test "@trunc f32/f64" { |
| 1368 | 1339 | |
| 1369 | 1340 | test "@trunc f80/f128/c_longdouble" { |
| 1370 | 1341 | 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 | 1342 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1373 | 1343 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 1374 | 1344 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 1375 | 1345 | |
| 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 | 1346 | try testTrunc(f80); |
| 1382 | 1347 | try comptime testTrunc(f80); |
| 1383 | 1348 | try testTrunc(f128); |
| ... | ... | @@ -1440,11 +1405,6 @@ test "neg f16" { |
| 1440 | 1405 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1441 | 1406 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 1442 | 1407 | |
| 1443 | if (builtin.os.tag == .freebsd) { | |
| 1444 | // TODO file issue to track this failure | |
| 1445 | return error.SkipZigTest; | |
| 1446 | } | |
| 1447 | ||
| 1448 | 1408 | try testNeg(f16); |
| 1449 | 1409 | try comptime testNeg(f16); |
| 1450 | 1410 | } |
| ... | ... | @@ -1501,9 +1461,9 @@ fn testNeg(comptime T: type) !void { |
| 1501 | 1461 | |
| 1502 | 1462 | // subnormals |
| 1503 | 1463 | var zero: T = 0.0; |
| 1504 | try expect(-zero == -0.0); | |
| 1464 | try expect(math.isNegativeZero(-zero)); | |
| 1505 | 1465 | var neg_zero: T = -0.0; |
| 1506 | try expect(-neg_zero == 0.0); | |
| 1466 | try expect(math.isPositiveZero(-neg_zero)); | |
| 1507 | 1467 | var true_min: T = math.floatTrueMin(T); |
| 1508 | 1468 | try expect(-true_min == -math.floatTrueMin(T)); |
| 1509 | 1469 | var neg_true_min: T = -math.floatTrueMin(T); |
| ... | ... | @@ -1678,7 +1638,7 @@ test "runtime isNan(inf * 0)" { |
| 1678 | 1638 | |
| 1679 | 1639 | test "optimized float mode" { |
| 1680 | 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; | |
| 1682 | 1642 | |
| 1683 | 1643 | const big = 0x1p40; |
| 1684 | 1644 | const small = 0.001; |
test/behavior/fn.zig-2| ... | ... | @@ -147,7 +147,6 @@ fn fnWithUnreachable() noreturn { |
| 147 | 147 | |
| 148 | 148 | test "extern struct with stdcallcc fn pointer" { |
| 149 | 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 | 150 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 152 | 151 | |
| 153 | 152 | const S = extern struct { |
| ... | ... | @@ -419,7 +418,6 @@ test "import passed byref to function in return type" { |
| 419 | 418 | |
| 420 | 419 | test "implicit cast function to function ptr" { |
| 421 | 420 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 422 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | |
| 423 | 421 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 424 | 422 | |
| 425 | 423 | const S1 = struct { |
test/behavior/int128.zig+1-1| ... | ... | @@ -31,7 +31,7 @@ test "undefined 128 bit int" { |
| 31 | 31 | @setRuntimeSafety(true); |
| 32 | 32 | |
| 33 | 33 | // TODO implement @setRuntimeSafety |
| 34 | if (builtin.mode != .Debug and builtin.mode != .ReleaseSafe) { | |
| 34 | if (builtin.mode != .debug and builtin.mode != .safe) { | |
| 35 | 35 | return error.SkipZigTest; |
| 36 | 36 | } |
| 37 | 37 |
test/behavior/math.zig-35| ... | ... | @@ -873,7 +873,6 @@ test "umax wrapped squaring" { |
| 873 | 873 | test "128-bit multiplication" { |
| 874 | 874 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 875 | 875 | 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 | 876 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 878 | 877 | |
| 879 | 878 | { |
| ... | ... | @@ -968,7 +967,6 @@ test "@addWithOverflow > 128 bits" { |
| 968 | 967 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 969 | 968 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 970 | 969 | 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; | |
| 972 | 970 | |
| 973 | 971 | try testAddWithOverflow(u129, 4, 105, 109, 0); |
| 974 | 972 | try testAddWithOverflow(u129, 1000, 100, 1100, 0); |
| ... | ... | @@ -1136,7 +1134,6 @@ test "Multiply unwrap error * immediate" { |
| 1136 | 1134 | |
| 1137 | 1135 | test "@mulWithOverflow bitsize 128 bits" { |
| 1138 | 1136 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 1139 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 1140 | 1137 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 1141 | 1138 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1142 | 1139 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| ... | ... | @@ -1163,7 +1160,6 @@ test "@mulWithOverflow bitsize 128 bits" { |
| 1163 | 1160 | |
| 1164 | 1161 | test "@mulWithOverflow > 128 bits" { |
| 1165 | 1162 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 1166 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 1167 | 1163 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 1168 | 1164 | |
| 1169 | 1165 | try testMulWithOverflow(u140, 0, maxInt(u140), 0, 0); |
| ... | ... | @@ -1193,7 +1189,6 @@ test "@mulWithOverflow > 128 bits" { |
| 1193 | 1189 | |
| 1194 | 1190 | test "@mulWithOverflow bitsize 256 bits" { |
| 1195 | 1191 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 1196 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 1197 | 1192 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 1198 | 1193 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 1199 | 1194 | |
| ... | ... | @@ -1298,7 +1293,6 @@ test "@subWithOverflow > 128 bits" { |
| 1298 | 1293 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1299 | 1294 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 1300 | 1295 | 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; | |
| 1302 | 1296 | |
| 1303 | 1297 | try testSubWithOverflow(u129, 4, 105, maxInt(u129) - 100, 1); |
| 1304 | 1298 | try testSubWithOverflow(u129, 1000, 100, 900, 0); |
| ... | ... | @@ -1389,7 +1383,6 @@ test "@shlWithOverflow > 64 bits" { |
| 1389 | 1383 | |
| 1390 | 1384 | test "@shlWithOverflow > 128 bits" { |
| 1391 | 1385 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 1392 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 1393 | 1386 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 1394 | 1387 | |
| 1395 | 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 | 1412 | |
| 1420 | 1413 | test "and > 128 bits" { |
| 1421 | 1414 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 1422 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 1423 | 1415 | |
| 1424 | 1416 | try testAnd(u140, (1 << 139) | (1 << 70) | 0xaa, (1 << 139) | (1 << 69) | 0xcc, (1 << 139) | 0x88); |
| 1425 | 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 | 1440 | |
| 1449 | 1441 | test "or > 128 bits" { |
| 1450 | 1442 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 1451 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 1452 | 1443 | |
| 1453 | 1444 | try testOr(u140, 0, 1 << 139, 1 << 139); |
| 1454 | 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 | 1468 | |
| 1478 | 1469 | test "xor > 128 bits" { |
| 1479 | 1470 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 1480 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 1481 | 1471 | |
| 1482 | 1472 | try testXor(u140, 0, maxInt(u140), maxInt(u140)); |
| 1483 | 1473 | try testXor(u140, 1 << 139, 1 << 139, 0); |
| ... | ... | @@ -1506,7 +1496,6 @@ fn testNot(comptime T: type, a: T, expected: T) !void { |
| 1506 | 1496 | |
| 1507 | 1497 | test "not > 128 bits" { |
| 1508 | 1498 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 1509 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 1510 | 1499 | |
| 1511 | 1500 | try testNot(u140, 0, maxInt(u140)); |
| 1512 | 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 | 1524 | |
| 1536 | 1525 | test "shl > 128 bits" { |
| 1537 | 1526 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 1538 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 1539 | 1527 | |
| 1540 | 1528 | try testShl(u140, 1 << 5, 10, 1 << 15); |
| 1541 | 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 | 1552 | |
| 1565 | 1553 | test "shr > 128 bits" { |
| 1566 | 1554 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 1567 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 1568 | 1555 | |
| 1569 | 1556 | try testShr(u140, 1 << 139, 39, 1 << 100); |
| 1570 | 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 | 1580 | |
| 1594 | 1581 | test "@clz > 128 bits" { |
| 1595 | 1582 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 1596 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 1597 | 1583 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 1598 | 1584 | |
| 1599 | 1585 | try testClz(u140, 0, 140); |
| ... | ... | @@ -1623,7 +1609,6 @@ fn testCtz(comptime T: type, a: T, expected: u16) !void { |
| 1623 | 1609 | |
| 1624 | 1610 | test "@ctz > 128 bits" { |
| 1625 | 1611 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 1626 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 1627 | 1612 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 1628 | 1613 | |
| 1629 | 1614 | try testCtz(u140, 0, 140); |
| ... | ... | @@ -1653,7 +1638,6 @@ fn testPopCount(comptime T: type, a: T, expected: u16) !void { |
| 1653 | 1638 | |
| 1654 | 1639 | test "@popCount > 128 bits" { |
| 1655 | 1640 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 1656 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 1657 | 1641 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 1658 | 1642 | |
| 1659 | 1643 | try testPopCount(u140, 0, 0); |
| ... | ... | @@ -1683,7 +1667,6 @@ fn testBitReverse(comptime T: type, a: T, expected: T) !void { |
| 1683 | 1667 | |
| 1684 | 1668 | test "@bitReverse > 128 bits" { |
| 1685 | 1669 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 1686 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 1687 | 1670 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 1688 | 1671 | |
| 1689 | 1672 | try testBitReverse(u140, 1 << 139, 1); |
| ... | ... | @@ -1713,7 +1696,6 @@ fn testByteSwap(comptime T: type, a: T, expected: T) !void { |
| 1713 | 1696 | |
| 1714 | 1697 | test "@byteSwap > 128 bits" { |
| 1715 | 1698 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 1716 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 1717 | 1699 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 1718 | 1700 | |
| 1719 | 1701 | try testByteSwap(u144, 1 << 136, 1); |
| ... | ... | @@ -1743,7 +1725,6 @@ fn testMax(comptime T: type, a: T, b: T, expected: T) !void { |
| 1743 | 1725 | |
| 1744 | 1726 | test "@max > 128 bits" { |
| 1745 | 1727 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 1746 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 1747 | 1728 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 1748 | 1729 | |
| 1749 | 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 | 1754 | |
| 1774 | 1755 | test "@min > 128 bits" { |
| 1775 | 1756 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 1776 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 1777 | 1757 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 1778 | 1758 | |
| 1779 | 1759 | try testMin(u140, 0, maxInt(u140), 0); |
| ... | ... | @@ -1803,7 +1783,6 @@ fn testAbs(comptime T: type, a: T, expected: anytype) !void { |
| 1803 | 1783 | |
| 1804 | 1784 | test "@abs > 128 bits" { |
| 1805 | 1785 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 1806 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 1807 | 1786 | |
| 1808 | 1787 | try testAbs(u140, 0, 0); |
| 1809 | 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 | 1806 | |
| 1828 | 1807 | test "@rem > 128 bits" { |
| 1829 | 1808 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 1830 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 1831 | 1809 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 1832 | 1810 | |
| 1833 | 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 | 1833 | |
| 1856 | 1834 | test "@mod > 128 bits" { |
| 1857 | 1835 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 1858 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 1859 | 1836 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 1860 | 1837 | |
| 1861 | 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 | 1860 | |
| 1884 | 1861 | test "@divFloor > 128 bits" { |
| 1885 | 1862 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 1886 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 1887 | 1863 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 1888 | 1864 | |
| 1889 | 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 | 1888 | |
| 1913 | 1889 | test "@divCeil > 128 bits" { |
| 1914 | 1890 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 1915 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 1916 | 1891 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 1917 | 1892 | |
| 1918 | 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 | 1916 | |
| 1942 | 1917 | test "@divTrunc > 128 bits" { |
| 1943 | 1918 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 1944 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 1945 | 1919 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 1946 | 1920 | |
| 1947 | 1921 | try testDivTrunc(u140, 0, maxInt(u140), 0); |
| ... | ... | @@ -2166,14 +2140,8 @@ test "remainder division" { |
| 2166 | 2140 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 2167 | 2141 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 2168 | 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 | 2143 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 2171 | 2144 | |
| 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 | 2145 | if (builtin.zig_backend == .stage2_x86_64 and builtin.object_format == .coff and builtin.abi != .gnu) return error.SkipZigTest; |
| 2178 | 2146 | |
| 2179 | 2147 | try comptime remdiv(f16); |
| ... | ... | @@ -2315,7 +2283,6 @@ test "@round f80" { |
| 2315 | 2283 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 2316 | 2284 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 2317 | 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 | 2286 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 2320 | 2287 | |
| 2321 | 2288 | try testRound(f80, 12.0); |
| ... | ... | @@ -2326,7 +2293,6 @@ test "@round f128" { |
| 2326 | 2293 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 2327 | 2294 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 2328 | 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 | 2296 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 2331 | 2297 | |
| 2332 | 2298 | try testRound(f128, 12.0); |
| ... | ... | @@ -2366,7 +2332,6 @@ test "NaN comparison" { |
| 2366 | 2332 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 2367 | 2333 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 2368 | 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 | |
| 2370 | 2335 | |
| 2371 | 2336 | try testNanEqNan(f16); |
| 2372 | 2337 | try testNanEqNan(f32); |
test/behavior/maximum_minimum.zig-1| ... | ... | @@ -115,7 +115,6 @@ test "@min/max for floats" { |
| 115 | 115 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 116 | 116 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 117 | 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 | 118 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 120 | 119 | |
| 121 | 120 | const S = struct { |
test/behavior/muladd.zig-4| ... | ... | @@ -49,7 +49,6 @@ test "@mulAdd f80" { |
| 49 | 49 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 50 | 50 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 51 | 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 | 52 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 54 | 53 | |
| 55 | 54 | try comptime testMulAdd80(); |
| ... | ... | @@ -68,7 +67,6 @@ test "@mulAdd f128" { |
| 68 | 67 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 69 | 68 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 70 | 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 | 70 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 73 | 71 | |
| 74 | 72 | try comptime testMulAdd128(); |
| ... | ... | @@ -169,7 +167,6 @@ test "vector f80" { |
| 169 | 167 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 170 | 168 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 171 | 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 | 170 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 174 | 171 | |
| 175 | 172 | try comptime vector80(); |
| ... | ... | @@ -194,7 +191,6 @@ test "vector f128" { |
| 194 | 191 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 195 | 192 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 196 | 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 | 194 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 199 | 195 | |
| 200 | 196 | try comptime vector128(); |
test/behavior/packed-struct.zig-4| ... | ... | @@ -404,7 +404,6 @@ test "nested packed struct field pointers" { |
| 404 | 404 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 405 | 405 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 406 | 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 | 407 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO |
| 409 | 408 | const S2 = packed struct { |
| 410 | 409 | base: u8, |
| ... | ... | @@ -579,7 +578,6 @@ test "packed struct fields modification" { |
| 579 | 578 | } |
| 580 | 579 | |
| 581 | 580 | test "nested packed struct field access test" { |
| 582 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 583 | 581 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 584 | 582 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 585 | 583 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| ... | ... | @@ -733,7 +731,6 @@ test "nested packed struct at non-zero offset 2" { |
| 733 | 731 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 734 | 732 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 735 | 733 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 736 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 737 | 734 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 738 | 735 | |
| 739 | 736 | const S = struct { |
| ... | ... | @@ -1171,7 +1168,6 @@ test "packed struct equality" { |
| 1171 | 1168 | |
| 1172 | 1169 | test "packed struct equality ignores padding bits" { |
| 1173 | 1170 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 1174 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 1175 | 1171 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 1176 | 1172 | |
| 1177 | 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 | 275 | } |
| 276 | 276 | |
| 277 | 277 | test "allowzero pointer and slice" { |
| 278 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 278 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 279 | 279 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 280 | 280 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 281 | 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 | 144 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 145 | 145 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 146 | 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 | 147 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 149 | 148 | |
| 150 | 149 | try testSatMul(u8, 0, maxInt(u8), 0); |
| ... | ... | @@ -238,7 +237,6 @@ test "saturating multiplication" { |
| 238 | 237 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 239 | 238 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 240 | 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 | 240 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 243 | 241 | |
| 244 | 242 | const S = struct { |
| ... | ... | @@ -313,7 +311,6 @@ test "saturating shift-left" { |
| 313 | 311 | |
| 314 | 312 | test "saturating shift-left large rhs" { |
| 315 | 313 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 316 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 317 | 314 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 318 | 315 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 319 | 316 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; |
| ... | ... | @@ -361,7 +358,6 @@ test "saturating shl uses the LHS type" { |
| 361 | 358 | |
| 362 | 359 | test "sat add > 128 bits" { |
| 363 | 360 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 364 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 365 | 361 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 366 | 362 | |
| 367 | 363 | try testSatAdd(u140, 0, 0, 0); |
| ... | ... | @@ -377,7 +373,6 @@ test "sat add > 128 bits" { |
| 377 | 373 | |
| 378 | 374 | test "sat sub > 128 bits" { |
| 379 | 375 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 380 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 381 | 376 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 382 | 377 | |
| 383 | 378 | try testSatSub(u140, 0, 1, 0); |
| ... | ... | @@ -393,7 +388,6 @@ test "sat sub > 128 bits" { |
| 393 | 388 | |
| 394 | 389 | test "sat mul > 128 bits" { |
| 395 | 390 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 396 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 397 | 391 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 398 | 392 | |
| 399 | 393 | try testSatMul(u140, 0, maxInt(u140), 0); |
| ... | ... | @@ -409,7 +403,6 @@ test "sat mul > 128 bits" { |
| 409 | 403 | |
| 410 | 404 | test "sat shl > 128 bits" { |
| 411 | 405 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 412 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 413 | 406 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 414 | 407 | |
| 415 | 408 | try testSatShl(u140, 0, u8, 17, 0); |
test/behavior/select.zig+14| ... | ... | @@ -31,6 +31,20 @@ fn selectVectors() !void { |
| 31 | 31 | _ = .{ &x, &y, &z }; |
| 32 | 32 | const xyz = @select(f32, x, y, z); |
| 33 | 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 | } |
| 35 | 49 | |
| 36 | 50 | test "@select arrays" { |
test/behavior/shuffle.zig+20| ... | ... | @@ -170,3 +170,23 @@ test "@shuffle bool 2" { |
| 170 | 170 | try S.doTheTest(); |
| 171 | 171 | try comptime S.doTheTest(); |
| 172 | 172 | } |
| 173 | ||
| 174 | test "@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 | 1089 | var arr: [10]u8 = @splat(0); |
| 1090 | 1090 | try S.doTheTest(&&arr); |
| 1091 | 1091 | } |
| 1092 | ||
| 1093 | test "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 | ||
| 1115 | test "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 | ||
| 1137 | test "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 | ||
| 1165 | test "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 | 535 | test "packed struct with non-ABI-aligned field" { |
| 536 | 536 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 537 | 537 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 538 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 539 | 538 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 540 | 539 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 541 | 540 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| ... | ... | @@ -792,7 +791,6 @@ test "non-packed struct with u128 entry in union" { |
| 792 | 791 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 793 | 792 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 794 | 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 | 794 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 797 | 795 | |
| 798 | 796 | const U = union(enum) { |
| ... | ... | @@ -1539,7 +1537,6 @@ test "instantiate struct with comptime field" { |
| 1539 | 1537 | } |
| 1540 | 1538 | |
| 1541 | 1539 | test "struct field pointer has correct alignment" { |
| 1542 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 1543 | 1540 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1544 | 1541 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1545 | 1542 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| ... | ... | @@ -1569,7 +1566,6 @@ test "struct field pointer has correct alignment" { |
| 1569 | 1566 | } |
| 1570 | 1567 | |
| 1571 | 1568 | test "extern struct field pointer has correct alignment" { |
| 1572 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 1573 | 1569 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1574 | 1570 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1575 | 1571 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| ... | ... | @@ -2007,7 +2003,6 @@ test "initiate global variable with runtime value" { |
| 2007 | 2003 | } |
| 2008 | 2004 | |
| 2009 | 2005 | test "struct containing optional pointer to array of @This()" { |
| 2010 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 2011 | 2006 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 2012 | 2007 | |
| 2013 | 2008 | const S = struct { |
| ... | ... | @@ -2266,7 +2261,8 @@ test "struct contains aligned pointer to itself through type decl" { |
| 2266 | 2261 | |
| 2267 | 2262 | test "struct contains underaligned field with overaligned pointer to itself" { |
| 2268 | 2263 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 2269 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 2264 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 2265 | ||
| 2270 | 2266 | const S = struct { |
| 2271 | 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 | 1267 | test "switch evaluation order" { |
| 1268 | 1268 | const eu: anyerror!u32 = 0; |
| 1269 | 1269 | _ = eu catch |err| switch (err) { |
| 1270 | if (true) @compileError("unreachable") => unreachable, | |
| 1270 | if (true) comptime unreachable => unreachable, | |
| 1271 | 1271 | else => unreachable, |
| 1272 | 1272 | }; |
| 1273 | 1273 | } |
test/behavior/switch_loop.zig+1-2| ... | ... | @@ -223,7 +223,6 @@ test "unanalyzed continue with operand" { |
| 223 | 223 | |
| 224 | 224 | test "switch loop on larger than pointer integer" { |
| 225 | 225 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 226 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 227 | 226 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 228 | 227 | |
| 229 | 228 | var entry: @Int(.unsigned, @bitSizeOf(usize) + 1) = undefined; |
| ... | ... | @@ -268,7 +267,7 @@ test "switch loop on non-exhaustive enum" { |
| 268 | 267 | |
| 269 | 268 | test "switch loop with discarded tag capture" { |
| 270 | 269 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 271 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 270 | ||
| 272 | 271 | const S = struct { |
| 273 | 272 | const U = union(enum) { |
| 274 | 273 | a: u32, |
test/behavior/switch_on_captured_error.zig+3-3| ... | ... | @@ -243,7 +243,7 @@ test "switch on error union catch capture" { |
| 243 | 243 | var a: error{}!u64 = 0; |
| 244 | 244 | _ = &a; |
| 245 | 245 | const b = a catch |err| switch (err) { |
| 246 | undefined => @compileError("unreachable"), | |
| 246 | undefined => comptime unreachable, | |
| 247 | 247 | }; |
| 248 | 248 | try expectEqual(@as(u64, 0), b); |
| 249 | 249 | } |
| ... | ... | @@ -829,7 +829,7 @@ test "switch on error union if else capture" { |
| 829 | 829 | var a: error{}!u64 = 0; |
| 830 | 830 | _ = &a; |
| 831 | 831 | const b = if (a) |x| x else |err| switch (err) { |
| 832 | undefined => @compileError("unreachable"), | |
| 832 | undefined => comptime unreachable, | |
| 833 | 833 | }; |
| 834 | 834 | try expectEqual(@as(u64, 0), b); |
| 835 | 835 | } |
| ... | ... | @@ -840,7 +840,7 @@ test "switch on error union if else capture" { |
| 840 | 840 | var a: error{}!u64 = 0; |
| 841 | 841 | _ = &a; |
| 842 | 842 | const b = if (a) |*x| x.* else |err| switch (err) { |
| 843 | undefined => @compileError("unreachable"), | |
| 843 | undefined => comptime unreachable, | |
| 844 | 844 | }; |
| 845 | 845 | try expectEqual(@as(u64, 0), b); |
| 846 | 846 | } |
test/behavior/threadlocal.zig-5| ... | ... | @@ -9,11 +9,6 @@ test "thread local variable" { |
| 9 | 9 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 10 | 10 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; // TODO |
| 11 | 11 | |
| 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 | 12 | const S = struct { |
| 18 | 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 | 49 | |
| 50 | 50 | test "@truncate > 128 bits" { |
| 51 | 51 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 52 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 53 | 52 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 54 | 53 | |
| 55 | 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 | 1437 | } |
| 1438 | 1438 | |
| 1439 | 1439 | test "defined-layout union field pointer has correct alignment" { |
| 1440 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 1441 | 1440 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1442 | 1441 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1443 | 1442 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| ... | ... | @@ -1472,7 +1471,6 @@ test "defined-layout union field pointer has correct alignment" { |
| 1472 | 1471 | } |
| 1473 | 1472 | |
| 1474 | 1473 | test "undefined-layout union field pointer has correct alignment" { |
| 1475 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 1476 | 1474 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1477 | 1475 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1478 | 1476 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| ... | ... | @@ -1611,6 +1609,10 @@ fn littleToNativeEndian(comptime T: type, v: T) T { |
| 1611 | 1609 | } |
| 1612 | 1610 | |
| 1613 | 1611 | test "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 | 1616 | if (true) { |
| 1615 | 1617 | // https://github.com/ziglang/zig/issues/19389 |
| 1616 | 1618 | return error.SkipZigTest; |
| ... | ... | @@ -1678,8 +1680,6 @@ test "reinterpret extern union" { |
| 1678 | 1680 | }; |
| 1679 | 1681 | |
| 1680 | 1682 | try comptime S.doTheTest(); |
| 1681 | ||
| 1682 | if (builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; // TODO | |
| 1683 | 1683 | try S.doTheTest(); |
| 1684 | 1684 | } |
| 1685 | 1685 | |
| ... | ... | @@ -1758,8 +1758,6 @@ test "reinterpret packed union" { |
| 1758 | 1758 | }; |
| 1759 | 1759 | |
| 1760 | 1760 | try comptime S.doTheTest(); |
| 1761 | ||
| 1762 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 1763 | 1761 | try S.doTheTest(); |
| 1764 | 1762 | } |
| 1765 | 1763 | |
| ... | ... | @@ -1800,8 +1798,6 @@ test "reinterpret packed union inside packed struct" { |
| 1800 | 1798 | }; |
| 1801 | 1799 | |
| 1802 | 1800 | try comptime S.doTheTest(); |
| 1803 | ||
| 1804 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 1805 | 1801 | try S.doTheTest(); |
| 1806 | 1802 | } |
| 1807 | 1803 |
test/behavior/vector.zig+19-18| ... | ... | @@ -128,13 +128,6 @@ test "vector float operators" { |
| 128 | 128 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 129 | 129 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 130 | 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 | } | |
| 138 | 131 | |
| 139 | 132 | const S = struct { |
| 140 | 133 | fn doTheTest(T: type) !void { |
| ... | ... | @@ -280,7 +273,6 @@ test "array to vector with element type coercion" { |
| 280 | 273 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 281 | 274 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 282 | 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; | |
| 284 | 276 | |
| 285 | 277 | const S = struct { |
| 286 | 278 | fn doTheTest() !void { |
| ... | ... | @@ -736,9 +728,7 @@ test "vector reduce operation" { |
| 736 | 728 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 737 | 729 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 738 | 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 | 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 | |
| 742 | 732 | |
| 743 | 733 | const S = struct { |
| 744 | 734 | fn testReduce(comptime op: std.builtin.ReduceOp, x: anytype, expected: anytype) !void { |
| ... | ... | @@ -776,6 +766,8 @@ test "vector reduce operation" { |
| 776 | 766 | try testReduce(.Add, [4]f16{ -1.9, 5.1, -60.3, 100.0 }, @as(f16, 42.9)); |
| 777 | 767 | try testReduce(.Add, [4]f32{ -1.9, 5.1, -60.3, 100.0 }, @as(f32, 42.9)); |
| 778 | 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)); | |
| 779 | 771 | |
| 780 | 772 | try testReduce(.And, [4]bool{ true, false, true, true }, @as(bool, false)); |
| 781 | 773 | try testReduce(.And, [4]u1{ 1, 0, 1, 1 }, @as(u1, 0)); |
| ... | ... | @@ -794,6 +786,8 @@ test "vector reduce operation" { |
| 794 | 786 | try testReduce(.Min, [4]f16{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f16, -100.0)); |
| 795 | 787 | try testReduce(.Min, [4]f32{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f32, -100.0)); |
| 796 | 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)); | |
| 797 | 791 | |
| 798 | 792 | try testReduce(.Max, [4]i16{ -1, 2, 3, 4 }, @as(i16, 4)); |
| 799 | 793 | try testReduce(.Max, [4]u16{ 1, 2, 3, 4 }, @as(u16, 4)); |
| ... | ... | @@ -806,6 +800,8 @@ test "vector reduce operation" { |
| 806 | 800 | try testReduce(.Max, [4]f16{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f16, 10.0e9)); |
| 807 | 801 | try testReduce(.Max, [4]f32{ -10.3, 10.0e9, 13.0, -100.0 }, @as(f32, 10.0e9)); |
| 808 | 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)); | |
| 809 | 805 | |
| 810 | 806 | try testReduce(.Mul, [4]i16{ -1, 2, 3, 4 }, @as(i16, -24)); |
| 811 | 807 | try testReduce(.Mul, [4]u16{ 1, 2, 3, 4 }, @as(u16, 24)); |
| ... | ... | @@ -818,6 +814,8 @@ test "vector reduce operation" { |
| 818 | 814 | try testReduce(.Mul, [4]f16{ -1.9, 5.1, -60.3, 100.0 }, @as(f16, 58430.7)); |
| 819 | 815 | try testReduce(.Mul, [4]f32{ -1.9, 5.1, -60.3, 100.0 }, @as(f32, 58430.7)); |
| 820 | 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)); | |
| 821 | 819 | |
| 822 | 820 | try testReduce(.Or, [4]bool{ false, true, false, false }, @as(bool, true)); |
| 823 | 821 | try testReduce(.Or, [4]u1{ 0, 1, 0, 0 }, @as(u1, 1)); |
| ... | ... | @@ -825,6 +823,7 @@ test "vector reduce operation" { |
| 825 | 823 | try testReduce(.Or, [4]u32{ 0xffff0000, 0xff00, 0xf0, 0xf }, ~@as(u32, 0)); |
| 826 | 824 | try testReduce(.Or, [4]u64{ 0xffff0000, 0xff00, 0xf0, 0xf }, @as(u64, 0xffffffff)); |
| 827 | 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)); | |
| 828 | 827 | |
| 829 | 828 | try testReduce(.Xor, [4]bool{ true, true, true, false }, @as(bool, true)); |
| 830 | 829 | try testReduce(.Xor, [4]u1{ 1, 1, 1, 0 }, @as(u1, 1)); |
| ... | ... | @@ -837,22 +836,32 @@ test "vector reduce operation" { |
| 837 | 836 | const f16_nan = math.nan(f16); |
| 838 | 837 | const f32_nan = math.nan(f32); |
| 839 | 838 | const f64_nan = math.nan(f64); |
| 839 | const f80_nan = math.nan(f80); | |
| 840 | const f128_nan = math.nan(f128); | |
| 840 | 841 | |
| 841 | 842 | try testReduce(.Add, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, f16_nan); |
| 842 | 843 | try testReduce(.Add, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, f32_nan); |
| 843 | 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); | |
| 844 | 847 | |
| 845 | 848 | try testReduce(.Min, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, @as(f16, -1.9)); |
| 846 | 849 | try testReduce(.Min, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, @as(f32, -1.9)); |
| 847 | 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)); | |
| 848 | 853 | |
| 849 | 854 | try testReduce(.Max, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, @as(f16, 100.0)); |
| 850 | 855 | try testReduce(.Max, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, @as(f32, 100.0)); |
| 851 | 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)); | |
| 852 | 859 | |
| 853 | 860 | try testReduce(.Mul, [4]f16{ -1.9, 5.1, f16_nan, 100.0 }, f16_nan); |
| 854 | 861 | try testReduce(.Mul, [4]f32{ -1.9, 5.1, f32_nan, 100.0 }, f32_nan); |
| 855 | 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 | }; |
| 858 | 867 | |
| ... | ... | @@ -1321,11 +1330,6 @@ test "byte vector initialized in inline function" { |
| 1321 | 1330 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 1322 | 1331 | if (builtin.cpu.arch == .hexagon and builtin.zig_backend == .stage2_llvm) return error.SkipZigTest; |
| 1323 | 1332 | |
| 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 | 1333 | const S = struct { |
| 1330 | 1334 | fn boolx4(e0: bool, e1: bool, e2: bool, e3: bool) @Vector(4, bool) { |
| 1331 | 1335 | return .{ e0, e1, e2, e3 }; |
| ... | ... | @@ -1437,7 +1441,6 @@ test "store packed vector element" { |
| 1437 | 1441 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 1438 | 1442 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1439 | 1443 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1440 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 1441 | 1444 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 1442 | 1445 | |
| 1443 | 1446 | var v = @Vector(4, u1){ 1, 1, 1, 1 }; |
| ... | ... | @@ -1469,7 +1472,6 @@ test "store vector with memset" { |
| 1469 | 1472 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1470 | 1473 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1471 | 1474 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; // TODO |
| 1472 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO | |
| 1473 | 1475 | if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; |
| 1474 | 1476 | |
| 1475 | 1477 | var a: [5]@Vector(2, i1) = undefined; |
| ... | ... | @@ -1610,7 +1612,6 @@ test "bitcast vector to array of smaller vectors" { |
| 1610 | 1612 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 1611 | 1613 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1612 | 1614 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 1613 | if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; | |
| 1614 | 1615 | |
| 1615 | 1616 | const u8x32 = @Vector(32, u8); |
| 1616 | 1617 | const u8x64 = @Vector(64, u8); |
test/behavior/widening.zig-1| ... | ... | @@ -41,7 +41,6 @@ test "float widening" { |
| 41 | 41 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 42 | 42 | if (builtin.zig_backend == .stage2_spirv) return error.SkipZigTest; |
| 43 | 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; | |
| 45 | 44 | |
| 46 | 45 | var a: f16 = 12.34; |
| 47 | 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 | 56 | f32 => libc_name ++ "f", |
| 57 | 57 | f64 => libc_name, |
| 58 | 58 | f80 => "__" ++ libc_name ++ "x", |
| 59 | f128 => libc_name ++ "q", | |
| 59 | f128 => libc_name ++ "f128", | |
| 60 | 60 | else => break :libc, |
| 61 | 61 | }, |
| 62 | 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 | 77 | # define ZIG_NO_COMPLEX |
| 78 | 78 | #endif |
| 79 | 79 | |
| 80 | #ifdef ZIG_PPC32 | |
| 80 | #ifdef __powerpc__ | |
| 81 | 81 | # define ZIG_NO_COMPLEX |
| 82 | 82 | #endif |
| 83 | 83 | |
| ... | ... | @@ -191,9 +191,6 @@ void zig_struct_i128(struct i128); |
| 191 | 191 | #endif |
| 192 | 192 | void zig_five_integers(int32_t, int32_t, int32_t, int32_t, int32_t); |
| 193 | 193 | |
| 194 | void zig_f32(float); | |
| 195 | void zig_f64(double); | |
| 196 | void zig_longdouble(long double); | |
| 197 | 194 | void zig_five_floats(float, float, float, float, float); |
| 198 | 195 | |
| 199 | 196 | bool zig_ret_bool(); |
| ... | ... | @@ -219,7 +216,203 @@ float complex zig_cmultf(float complex a, float complex b); |
| 219 | 216 | double complex zig_cmultd(double complex a, double complex b); |
| 220 | 217 | #endif |
| 221 | 218 | |
| 222 | #if defined(ZIG_BACKEND_STAGE2_X86_64) || defined(ZIG_PPC32) || defined(__wasm__) | |
| 219 | float zig_ret_f32(void); | |
| 220 | void zig_f32(float, size_t); | |
| 221 | void zig_1_f32(size_t, float, size_t); | |
| 222 | void zig_2_f32(size_t, size_t, float, size_t); | |
| 223 | void zig_3_f32(size_t, size_t, size_t, float, size_t); | |
| 224 | void zig_4_f32(size_t, size_t, size_t, size_t, float, size_t); | |
| 225 | void zig_5_f32(size_t, size_t, size_t, size_t, size_t, float, size_t); | |
| 226 | void zig_6_f32(size_t, size_t, size_t, size_t, size_t, size_t, float, size_t); | |
| 227 | void zig_7_f32(size_t, size_t, size_t, size_t, size_t, size_t, size_t, float, size_t); | |
| 228 | void zig_8_f32(size_t, size_t, size_t, size_t, size_t, size_t, size_t, size_t, float, size_t); | |
| 229 | ||
| 230 | float c_ret_f32(void) { | |
| 231 | return 11; | |
| 232 | } | |
| 233 | void c_f32(float f, size_t i) { | |
| 234 | assert_or_panic(f == 12); | |
| 235 | assert_or_panic(i == 1); | |
| 236 | } | |
| 237 | void c_1_f32(size_t a0, float f, size_t i) { | |
| 238 | assert_or_panic(f == 13); | |
| 239 | assert_or_panic(i == 2); | |
| 240 | } | |
| 241 | void 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 | } | |
| 245 | void 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 | } | |
| 249 | void 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 | } | |
| 253 | void 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 | } | |
| 257 | void c_6_f32(size_t a0, size_t a1, size_t a2, size_t a3, size_t a4, size_t a5, float f, size_t i) { | |
| 258 | assert_or_panic(f == 18); | |
| 259 | assert_or_panic(i == 7); | |
| 260 | } | |
| 261 | void c_7_f32(size_t a0, size_t a1, size_t a2, size_t a3, size_t a4, size_t a5, size_t a6, float f, size_t i) { | |
| 262 | assert_or_panic(f == 19); | |
| 263 | assert_or_panic(i == 8); | |
| 264 | } | |
| 265 | void c_8_f32(size_t a0, size_t a1, size_t a2, size_t a3, size_t a4, size_t a5, size_t a6, size_t a7, float f, size_t i) { | |
| 266 | assert_or_panic(f == 20); | |
| 267 | assert_or_panic(i == 9); | |
| 268 | } | |
| 269 | void 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 | ||
| 283 | double zig_ret_f64(void); | |
| 284 | void zig_f64(double, size_t); | |
| 285 | void zig_1_f64(size_t, double, size_t); | |
| 286 | void zig_2_f64(size_t, size_t, double, size_t); | |
| 287 | void zig_3_f64(size_t, size_t, size_t, double, size_t); | |
| 288 | void zig_4_f64(size_t, size_t, size_t, size_t, double, size_t); | |
| 289 | void zig_5_f64(size_t, size_t, size_t, size_t, size_t, double, size_t); | |
| 290 | void zig_6_f64(size_t, size_t, size_t, size_t, size_t, size_t, double, size_t); | |
| 291 | void zig_7_f64(size_t, size_t, size_t, size_t, size_t, size_t, size_t, double, size_t); | |
| 292 | void zig_8_f64(size_t, size_t, size_t, size_t, size_t, size_t, size_t, size_t, double, size_t); | |
| 293 | ||
| 294 | double c_ret_f64(void) { | |
| 295 | return 11; | |
| 296 | } | |
| 297 | void c_f64(double f, size_t i) { | |
| 298 | assert_or_panic(f == 12); | |
| 299 | assert_or_panic(i == 1); | |
| 300 | } | |
| 301 | void c_1_f64(size_t a0, double f, size_t i) { | |
| 302 | assert_or_panic(f == 13); | |
| 303 | assert_or_panic(i == 2); | |
| 304 | } | |
| 305 | void 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 | } | |
| 309 | void 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 | } | |
| 313 | void 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 | } | |
| 317 | void 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 | } | |
| 321 | void c_6_f64(size_t a0, size_t a1, size_t a2, size_t a3, size_t a4, size_t a5, double f, size_t i) { | |
| 322 | assert_or_panic(f == 18); | |
| 323 | assert_or_panic(i == 7); | |
| 324 | } | |
| 325 | void c_7_f64(size_t a0, size_t a1, size_t a2, size_t a3, size_t a4, size_t a5, size_t a6, double f, size_t i) { | |
| 326 | assert_or_panic(f == 19); | |
| 327 | assert_or_panic(i == 8); | |
| 328 | } | |
| 329 | void c_8_f64(size_t a0, size_t a1, size_t a2, size_t a3, size_t a4, size_t a5, size_t a6, size_t a7, double f, size_t i) { | |
| 330 | assert_or_panic(f == 20); | |
| 331 | assert_or_panic(i == 9); | |
| 332 | } | |
| 333 | void 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 | ||
| 347 | long double zig_ret_longdouble(void); | |
| 348 | void zig_longdouble(long double, size_t); | |
| 349 | void zig_1_longdouble(size_t, long double, size_t); | |
| 350 | void zig_2_longdouble(size_t, size_t, long double, size_t); | |
| 351 | void zig_3_longdouble(size_t, size_t, size_t, long double, size_t); | |
| 352 | void zig_4_longdouble(size_t, size_t, size_t, size_t, long double, size_t); | |
| 353 | void zig_5_longdouble(size_t, size_t, size_t, size_t, size_t, long double, size_t); | |
| 354 | void zig_6_longdouble(size_t, size_t, size_t, size_t, size_t, size_t, long double, size_t); | |
| 355 | void zig_7_longdouble(size_t, size_t, size_t, size_t, size_t, size_t, size_t, long double, size_t); | |
| 356 | void zig_8_longdouble(size_t, size_t, size_t, size_t, size_t, size_t, size_t, size_t, long double, size_t); | |
| 357 | ||
| 358 | long double c_ret_longdouble(void) { | |
| 359 | return 11; | |
| 360 | } | |
| 361 | void c_longdouble(long double f, size_t i) { | |
| 362 | assert_or_panic(f == 12); | |
| 363 | assert_or_panic(i == 1); | |
| 364 | } | |
| 365 | void 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 | } | |
| 369 | void 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 | } | |
| 373 | void 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 | } | |
| 377 | void 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 | } | |
| 381 | void c_5_longdouble(size_t a0, size_t a1, size_t a2, size_t a3, size_t a4, long double f, size_t i) { | |
| 382 | assert_or_panic(f == 17); | |
| 383 | assert_or_panic(i == 6); | |
| 384 | } | |
| 385 | void c_6_longdouble(size_t a0, size_t a1, size_t a2, size_t a3, size_t a4, size_t a5, long double f, size_t i) { | |
| 386 | assert_or_panic(f == 18); | |
| 387 | assert_or_panic(i == 7); | |
| 388 | } | |
| 389 | void c_7_longdouble(size_t a0, size_t a1, size_t a2, size_t a3, size_t a4, size_t a5, size_t a6, long double f, size_t i) { | |
| 390 | assert_or_panic(f == 19); | |
| 391 | assert_or_panic(i == 8); | |
| 392 | } | |
| 393 | void c_8_longdouble(size_t a0, size_t a1, size_t a2, size_t a3, size_t a4, size_t a5, size_t a6, size_t a7, long double f, size_t i) { | |
| 394 | assert_or_panic(f == 20); | |
| 395 | assert_or_panic(i == 9); | |
| 396 | } | |
| 397 | void 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)) | |
| 223 | 416 | |
| 224 | 417 | typedef bool Vector_2_bool __attribute__((ext_vector_type(2))); |
| 225 | 418 | |
| ... | ... | @@ -4468,6 +4661,10 @@ void c_test_vector_512_bool(void) { |
| 4468 | 4661 | }); |
| 4469 | 4662 | } |
| 4470 | 4663 | |
| 4664 | #endif | |
| 4665 | #endif | |
| 4666 | #endif | |
| 4667 | #endif | |
| 4471 | 4668 | #endif |
| 4472 | 4669 | |
| 4473 | 4670 | typedef 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 | 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 | } |
| 14999 | 15196 | |
| 15197 | struct Struct_f32 zig_ret_struct_void_f32(void); | |
| 15198 | void zig_struct_void_f32(struct Struct_f32, size_t); | |
| 15199 | ||
| 15200 | struct Struct_f32 c_ret_struct_void_f32(void) { | |
| 15201 | return (struct Struct_f32){ .a = 4 }; | |
| 15202 | } | |
| 15203 | void 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 | } | |
| 15207 | void 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 | ||
| 15213 | struct Struct_array_1_f32 { | |
| 15214 | float a[1]; | |
| 15215 | }; | |
| 15216 | ||
| 15217 | struct Struct_array_1_f32 zig_ret_struct_array_1_f32(void); | |
| 15218 | void zig_struct_array_1_f32(struct Struct_array_1_f32, size_t); | |
| 15219 | ||
| 15220 | struct Struct_array_1_f32 c_ret_struct_array_1_f32(void) { | |
| 15221 | return (struct Struct_array_1_f32){ .a = { 4 } }; | |
| 15222 | } | |
| 15223 | void 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 | } | |
| 15227 | void 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 | ||
| 15233 | struct Struct_array_2_f32 { | |
| 15234 | float a[2]; | |
| 15235 | }; | |
| 15236 | ||
| 15237 | struct Struct_array_2_f32 zig_ret_struct_array_2_f32(void); | |
| 15238 | void zig_struct_array_2_f32(struct Struct_array_2_f32, size_t); | |
| 15239 | ||
| 15240 | struct Struct_array_2_f32 c_ret_struct_array_2_f32(void) { | |
| 15241 | return (struct Struct_array_2_f32){ .a = { 6, 7 } }; | |
| 15242 | } | |
| 15243 | void 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 | } | |
| 15248 | void 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 | ||
| 15255 | struct Struct_array_3_f32 { | |
| 15256 | float a[3]; | |
| 15257 | }; | |
| 15258 | ||
| 15259 | struct Struct_array_3_f32 zig_ret_struct_array_3_f32(void); | |
| 15260 | void zig_struct_array_3_f32(struct Struct_array_3_f32, size_t); | |
| 15261 | ||
| 15262 | struct Struct_array_3_f32 c_ret_struct_array_3_f32(void) { | |
| 15263 | return (struct Struct_array_3_f32){ .a = { 8, 9, 10 } }; | |
| 15264 | } | |
| 15265 | void 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 | } | |
| 15271 | void 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 | ||
| 15279 | struct Struct_array_4_f32 { | |
| 15280 | float a[4]; | |
| 15281 | }; | |
| 15282 | ||
| 15283 | struct Struct_array_4_f32 zig_ret_struct_array_4_f32(void); | |
| 15284 | void zig_struct_array_4_f32(struct Struct_array_4_f32, size_t); | |
| 15285 | ||
| 15286 | struct Struct_array_4_f32 c_ret_struct_array_4_f32(void) { | |
| 15287 | return (struct Struct_array_4_f32){ .a = { 10, 11, 12, 13 } }; | |
| 15288 | } | |
| 15289 | void 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 | } | |
| 15296 | void 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 | ||
| 15305 | struct Struct_array_5_f32 { | |
| 15306 | float a[5]; | |
| 15307 | }; | |
| 15308 | ||
| 15309 | struct Struct_array_5_f32 zig_ret_struct_array_5_f32(void); | |
| 15310 | void zig_struct_array_5_f32(struct Struct_array_5_f32, size_t); | |
| 15311 | ||
| 15312 | struct 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 | } | |
| 15315 | void 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 | } | |
| 15323 | void 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 | ||
| 15333 | struct Struct_array_1_f32 zig_ret_struct_array_0_sentinel_f32(void); | |
| 15334 | void zig_struct_array_0_sentinel_f32(struct Struct_array_1_f32, size_t); | |
| 15335 | ||
| 15336 | struct Struct_array_1_f32 c_ret_struct_array_0_sentinel_f32(void) { | |
| 15337 | return (struct Struct_array_1_f32){ .a = { 0x1e1 } }; | |
| 15338 | } | |
| 15339 | void 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 | } | |
| 15343 | void 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 | ||
| 15349 | struct Struct_array_2_f32 zig_ret_struct_array_1_sentinel_f32(void); | |
| 15350 | void zig_struct_array_1_sentinel_f32(struct Struct_array_2_f32, size_t); | |
| 15351 | ||
| 15352 | struct Struct_array_2_f32 c_ret_struct_array_1_sentinel_f32(void) { | |
| 15353 | return (struct Struct_array_2_f32){ .a = { 4, 0x1e1 } }; | |
| 15354 | } | |
| 15355 | void 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 | } | |
| 15360 | void 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 | ||
| 15367 | struct Struct_array_3_f32 zig_ret_struct_array_2_sentinel_f32(void); | |
| 15368 | void zig_struct_array_2_sentinel_f32(struct Struct_array_3_f32, size_t); | |
| 15369 | ||
| 15370 | struct Struct_array_3_f32 c_ret_struct_array_2_sentinel_f32(void) { | |
| 15371 | return (struct Struct_array_3_f32){ .a = { 6, 7, 0x1e1 } }; | |
| 15372 | } | |
| 15373 | void 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 | } | |
| 15379 | void 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 | ||
| 15387 | struct Struct_array_4_f32 zig_ret_struct_array_3_sentinel_f32(void); | |
| 15388 | void zig_struct_array_3_sentinel_f32(struct Struct_array_4_f32, size_t); | |
| 15389 | ||
| 15390 | struct 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 | } | |
| 15393 | void 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 | } | |
| 15400 | void 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 | ||
| 15409 | struct Struct_array_5_f32 zig_ret_struct_array_4_sentinel_f32(void); | |
| 15410 | void zig_struct_array_4_sentinel_f32(struct Struct_array_5_f32, size_t); | |
| 15411 | ||
| 15412 | struct 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 | } | |
| 15415 | void 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 | } | |
| 15423 | void 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 | ||
| 15000 | 15433 | struct Struct_f32a8 { |
| 15001 | 15434 | alignas(8) float a; |
| 15002 | 15435 | }; |
| ... | ... | @@ -15212,6 +15645,146 @@ void c_test_struct_f64_f64_f64_f64_f64(void) { |
| 15212 | 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 | } |
| 15214 | 15647 | |
| 15648 | struct Struct_array_1_f64 { | |
| 15649 | double a[1]; | |
| 15650 | }; | |
| 15651 | ||
| 15652 | struct Struct_array_1_f64 zig_ret_struct_array_1_f64(void); | |
| 15653 | void zig_struct_array_1_f64(struct Struct_array_1_f64, size_t); | |
| 15654 | ||
| 15655 | struct Struct_array_1_f64 c_ret_struct_array_1_f64(void) { | |
| 15656 | return (struct Struct_array_1_f64){ .a = { 4 } }; | |
| 15657 | } | |
| 15658 | void 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 | } | |
| 15662 | void 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 | ||
| 15668 | struct Struct_array_2_f64 { | |
| 15669 | double a[2]; | |
| 15670 | }; | |
| 15671 | ||
| 15672 | struct Struct_array_2_f64 zig_ret_struct_array_2_f64(void); | |
| 15673 | void zig_struct_array_2_f64(struct Struct_array_2_f64, size_t); | |
| 15674 | ||
| 15675 | struct Struct_array_2_f64 c_ret_struct_array_2_f64(void) { | |
| 15676 | return (struct Struct_array_2_f64){ .a = { 6, 7 } }; | |
| 15677 | } | |
| 15678 | void 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 | } | |
| 15683 | void 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 | ||
| 15690 | struct Struct_array_3_f64 { | |
| 15691 | double a[3]; | |
| 15692 | }; | |
| 15693 | ||
| 15694 | struct Struct_array_3_f64 zig_ret_struct_array_3_f64(void); | |
| 15695 | void zig_struct_array_3_f64(struct Struct_array_3_f64, size_t); | |
| 15696 | ||
| 15697 | struct Struct_array_3_f64 c_ret_struct_array_3_f64(void) { | |
| 15698 | return (struct Struct_array_3_f64){ .a = { 8, 9, 10 } }; | |
| 15699 | } | |
| 15700 | void 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 | } | |
| 15706 | void 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 | ||
| 15714 | struct Struct_array_4_f64 { | |
| 15715 | double a[4]; | |
| 15716 | }; | |
| 15717 | ||
| 15718 | struct Struct_array_4_f64 zig_ret_struct_array_4_f64(void); | |
| 15719 | void zig_struct_array_4_f64(struct Struct_array_4_f64, size_t); | |
| 15720 | ||
| 15721 | struct Struct_array_4_f64 c_ret_struct_array_4_f64(void) { | |
| 15722 | return (struct Struct_array_4_f64){ .a = { 10, 11, 12, 13 } }; | |
| 15723 | } | |
| 15724 | void 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 | } | |
| 15731 | void 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 | ||
| 15740 | struct Struct_array_5_f64 { | |
| 15741 | double a[5]; | |
| 15742 | }; | |
| 15743 | ||
| 15744 | struct Struct_array_5_f64 zig_ret_struct_array_5_f64(void); | |
| 15745 | void zig_struct_array_5_f64(struct Struct_array_5_f64, size_t); | |
| 15746 | ||
| 15747 | struct 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 | } | |
| 15750 | void 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 | } | |
| 15758 | void 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 | ||
| 15768 | union Union_f64 { | |
| 15769 | double a; | |
| 15770 | }; | |
| 15771 | ||
| 15772 | union Union_f64 zig_ret_union_f64(void); | |
| 15773 | void zig_union_f64(union Union_f64, size_t); | |
| 15774 | ||
| 15775 | union Union_f64 c_ret_union_f64(void) { | |
| 15776 | return (union Union_f64){ .a = 4 }; | |
| 15777 | } | |
| 15778 | void c_union_f64(union Union_f64 s, size_t i) { | |
| 15779 | assert_or_panic(s.a == 5); | |
| 15780 | assert_or_panic(i == 6); | |
| 15781 | } | |
| 15782 | void 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 | ||
| 15215 | 15788 | struct Struct_u32_Union_u32_u32u32 { |
| 15216 | 15789 | uint32_t a; |
| 15217 | 15790 | union { |
| ... | ... | @@ -15326,9 +15899,6 @@ void run_c_tests(void) { |
| 15326 | 15899 | |
| 15327 | 15900 | zig_five_integers(12, 34, 56, 78, 90); |
| 15328 | 15901 | |
| 15329 | zig_f32(12.34f); | |
| 15330 | zig_f64(56.78); | |
| 15331 | zig_longdouble(12.34l); | |
| 15332 | 15902 | zig_five_floats(1.0f, 2.0f, 3.0f, 4.0f, 5.0f); |
| 15333 | 15903 | |
| 15334 | 15904 | zig_ptr((void *)0xdeadbeefL); |
| ... | ... | @@ -15377,8 +15947,7 @@ void run_c_tests(void) { |
| 15377 | 15947 | #if !(defined(__i386__) && defined(_WIN32)) |
| 15378 | 15948 | #ifndef __loongarch__ |
| 15379 | 15949 | #ifndef ZIG_MIPS64 |
| 15380 | #ifndef __powerpc__ | |
| 15381 | #ifndef __s390x__ | |
| 15950 | #ifndef ZIG_PPC32 | |
| 15382 | 15951 | { |
| 15383 | 15952 | struct Struct_i32_i32 s = {1, 2}; |
| 15384 | 15953 | zig_struct_i32_i32(s); |
| ... | ... | @@ -15387,13 +15956,11 @@ void run_c_tests(void) { |
| 15387 | 15956 | #endif |
| 15388 | 15957 | #endif |
| 15389 | 15958 | #endif |
| 15390 | #endif | |
| 15391 | 15959 | |
| 15392 | 15960 | #ifndef __hexagon__ |
| 15393 | 15961 | #ifndef __loongarch__ |
| 15394 | 15962 | #ifndef ZIG_MIPS64 |
| 15395 | #ifndef __powerpc__ | |
| 15396 | #ifndef __s390x__ | |
| 15963 | #ifndef ZIG_PPC32 | |
| 15397 | 15964 | { |
| 15398 | 15965 | struct BigStruct s = {1, 2, 3, 4, 5}; |
| 15399 | 15966 | zig_big_struct(s); |
| ... | ... | @@ -15402,7 +15969,6 @@ void run_c_tests(void) { |
| 15402 | 15969 | #endif |
| 15403 | 15970 | #endif |
| 15404 | 15971 | #endif |
| 15405 | #endif | |
| 15406 | 15972 | |
| 15407 | 15973 | #ifndef ZIG_NO_I128 |
| 15408 | 15974 | { |
| ... | ... | @@ -15426,8 +15992,7 @@ void run_c_tests(void) { |
| 15426 | 15992 | #ifndef __i386__ |
| 15427 | 15993 | #ifndef __loongarch__ |
| 15428 | 15994 | #ifndef ZIG_MIPS64 |
| 15429 | #ifndef __powerpc__ | |
| 15430 | #ifndef __s390x__ | |
| 15995 | #ifndef ZIG_PPC32 | |
| 15431 | 15996 | { |
| 15432 | 15997 | struct SplitStructInts s = {1234, 100, 1337}; |
| 15433 | 15998 | zig_split_struct_ints(s); |
| ... | ... | @@ -15437,13 +16002,11 @@ void run_c_tests(void) { |
| 15437 | 16002 | #endif |
| 15438 | 16003 | #endif |
| 15439 | 16004 | #endif |
| 15440 | #endif | |
| 15441 | 16005 | |
| 15442 | 16006 | #ifndef __hexagon__ |
| 15443 | 16007 | #ifndef __loongarch__ |
| 15444 | 16008 | #ifndef ZIG_MIPS64 |
| 15445 | #ifndef __powerpc__ | |
| 15446 | #ifndef __s390x__ | |
| 16009 | #ifndef ZIG_PPC32 | |
| 15447 | 16010 | { |
| 15448 | 16011 | struct MedStructMixed s = {1234, 100.0f, 1337.0f}; |
| 15449 | 16012 | zig_med_struct_mixed(s); |
| ... | ... | @@ -15452,14 +16015,12 @@ void run_c_tests(void) { |
| 15452 | 16015 | #endif |
| 15453 | 16016 | #endif |
| 15454 | 16017 | #endif |
| 15455 | #endif | |
| 15456 | 16018 | |
| 15457 | 16019 | #ifndef __hexagon__ |
| 15458 | 16020 | #ifndef __i386__ |
| 15459 | 16021 | #ifndef __loongarch__ |
| 15460 | 16022 | #ifndef ZIG_MIPS64 |
| 15461 | #ifndef __powerpc__ | |
| 15462 | #ifndef __s390x__ | |
| 16023 | #ifndef ZIG_PPC32 | |
| 15463 | 16024 | { |
| 15464 | 16025 | struct SplitStructMixed s = {1234, 100, 1337.0f}; |
| 15465 | 16026 | zig_split_struct_mixed(s); |
| ... | ... | @@ -15469,13 +16030,11 @@ void run_c_tests(void) { |
| 15469 | 16030 | #endif |
| 15470 | 16031 | #endif |
| 15471 | 16032 | #endif |
| 15472 | #endif | |
| 15473 | 16033 | |
| 15474 | 16034 | #ifndef __hexagon__ |
| 15475 | 16035 | #ifndef __loongarch__ |
| 15476 | 16036 | #ifndef ZIG_MIPS64 |
| 15477 | #ifndef __powerpc__ | |
| 15478 | #ifndef __s390x__ | |
| 16037 | #ifndef ZIG_PPC32 | |
| 15479 | 16038 | { |
| 15480 | 16039 | struct BigStruct s = {30, 31, 32, 33, 34}; |
| 15481 | 16040 | struct BigStruct res = zig_big_struct_both(s); |
| ... | ... | @@ -15488,7 +16047,6 @@ void run_c_tests(void) { |
| 15488 | 16047 | #endif |
| 15489 | 16048 | #endif |
| 15490 | 16049 | #endif |
| 15491 | #endif | |
| 15492 | 16050 | #endif |
| 15493 | 16051 | |
| 15494 | 16052 | { |
| ... | ... | @@ -15550,18 +16108,6 @@ void c_struct_i128(struct i128 x) { |
| 15550 | 16108 | } |
| 15551 | 16109 | #endif |
| 15552 | 16110 | |
| 15553 | void c_f32(float x) { | |
| 15554 | assert_or_panic(x == 12.34f); | |
| 15555 | } | |
| 15556 | ||
| 15557 | void c_f64(double x) { | |
| 15558 | assert_or_panic(x == 56.78); | |
| 15559 | } | |
| 15560 | ||
| 15561 | void c_long_double(long double x) { | |
| 15562 | assert_or_panic(x == 12.34l); | |
| 15563 | } | |
| 15564 | ||
| 15565 | 16111 | void c_ptr(void *x) { |
| 15566 | 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 | 16624 | } |
| 16079 | 16625 | #endif |
| 16080 | 16626 | |
| 16627 | #if defined __x86_64__ || defined __aarch64__ | |
| 16628 | int __attribute__((preserve_none)) c_preserve_none(int x) { | |
| 16629 | return x + 1; | |
| 16630 | } | |
| 16631 | int __attribute__((preserve_none)) zig_preserve_none(int); | |
| 16632 | void c_preserve_none_check(void) { | |
| 16633 | assert_or_panic(zig_preserve_none(41) == 42); | |
| 16634 | } | |
| 16635 | #endif | |
| 16636 | ||
| 16081 | 16637 | struct byval_tail_callsite_attr_Point { |
| 16082 | 16638 | double x; |
| 16083 | 16639 | double y; |
| ... | ... | @@ -16212,7 +16768,13 @@ void __attribute__((vectorcall)) c_vectorcall_check(int a, float b, double c, vo |
| 16212 | 16768 | } |
| 16213 | 16769 | #endif |
| 16214 | 16770 | |
| 16215 | #if defined(__x86_64__) && defined(_WIN64) | |
| 16771 | void 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 | ||
| 16216 | 16778 | void c_win64_varargs_u64_f64_u64_f64(uint64_t a, double b, uint64_t c, double d) { |
| 16217 | 16779 | assert_or_panic(a == UINT64_C(0x3ff0000000000000)); |
| 16218 | 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 | 16787 | assert_or_panic(c == 7.0); |
| 16226 | 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 | 13 | const have_i128 = builtin.cpu.arch != .x86 and !builtin.cpu.arch.isArm() and |
| 14 | 14 | !builtin.cpu.arch.isMIPS() and !builtin.cpu.arch.isPowerPC32() and builtin.cpu.arch != .riscv32 and |
| 15 | 15 | builtin.cpu.arch != .hexagon and |
| 16 | builtin.cpu.arch != .s390x; // https://github.com/llvm/llvm-project/issues/168460 | |
| 16 | builtin.cpu.arch != .s390x; | |
| 17 | 17 | |
| 18 | 18 | const have_f128 = builtin.cpu.arch.isWasm() or (builtin.cpu.arch.isX86() and !builtin.os.tag.isDarwin() and builtin.abi != .msvc); |
| 19 | 19 | const have_f80 = builtin.cpu.arch.isX86() and builtin.abi != .msvc; |
| ... | ... | @@ -104,10 +104,6 @@ export fn zig_struct_u128(a: U128) void { |
| 104 | 104 | expect(a.value == 0xfffffffffffffffc) catch @panic("test failure: zig_struct_u128"); |
| 105 | 105 | } |
| 106 | 106 | |
| 107 | extern fn c_f32(f32) void; | |
| 108 | extern fn c_f64(f64) void; | |
| 109 | extern fn c_long_double(c_longdouble) void; | |
| 110 | ||
| 111 | 107 | // On windows x64, the first 4 are passed via registers, others on the stack. |
| 112 | 108 | extern fn c_five_floats(f32, f32, f32, f32, f32) void; |
| 113 | 109 | |
| ... | ... | @@ -120,28 +116,9 @@ export fn zig_five_floats(a: f32, b: f32, c: f32, d: f32, e: f32) void { |
| 120 | 116 | } |
| 121 | 117 | |
| 122 | 118 | test "floats" { |
| 123 | c_f32(12.34); | |
| 124 | c_f64(56.78); | |
| 125 | 119 | c_five_floats(1.0, 2.0, 3.0, 4.0, 5.0); |
| 126 | 120 | } |
| 127 | 121 | |
| 128 | test "long double" { | |
| 129 | if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; | |
| 130 | ||
| 131 | c_long_double(12.34); | |
| 132 | } | |
| 133 | ||
| 134 | export fn zig_f32(x: f32) void { | |
| 135 | expect(x == 12.34) catch @panic("test failure: zig_f32"); | |
| 136 | } | |
| 137 | export fn zig_f64(x: f64) void { | |
| 138 | expect(x == 56.78) catch @panic("test failure: zig_f64"); | |
| 139 | } | |
| 140 | export 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 | ||
| 145 | 122 | extern fn c_ptr(*anyopaque) void; |
| 146 | 123 | |
| 147 | 124 | test "pointer" { |
| ... | ... | @@ -184,7 +161,7 @@ extern fn c_cmultf(a: ComplexFloat, b: ComplexFloat) ComplexFloat; |
| 184 | 161 | extern fn c_cmultd(a: ComplexDouble, b: ComplexDouble) ComplexDouble; |
| 185 | 162 | |
| 186 | 163 | const complex_abi_compatible = builtin.cpu.arch != .x86 and !builtin.cpu.arch.isMIPS() and |
| 187 | !builtin.cpu.arch.isArm() and !builtin.cpu.arch.isPowerPC32() and !builtin.cpu.arch.isRISCV() and | |
| 164 | !builtin.cpu.arch.isArm() and !builtin.cpu.arch.isPowerPC() and !builtin.cpu.arch.isRISCV() and | |
| 188 | 165 | builtin.cpu.arch != .hexagon and |
| 189 | 166 | builtin.cpu.arch != .s390x and |
| 190 | 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 | 246 | return .{ .real = 1.5, .imag = 13.5 }; |
| 270 | 247 | } |
| 271 | 248 | |
| 249 | export fn zig_ret_f32() f32 { | |
| 250 | return 1; | |
| 251 | } | |
| 252 | export 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 | } | |
| 256 | export 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 | } | |
| 260 | export 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 | } | |
| 264 | export 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 | } | |
| 268 | export 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 | } | |
| 272 | export 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 | } | |
| 276 | export 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 | } | |
| 280 | export 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 | } | |
| 284 | export 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 | ||
| 289 | extern fn c_ret_f32() f32; | |
| 290 | extern fn c_f32(f32, usize) void; | |
| 291 | extern fn c_1_f32(usize, f32, usize) void; | |
| 292 | extern fn c_2_f32(usize, usize, f32, usize) void; | |
| 293 | extern fn c_3_f32(usize, usize, usize, f32, usize) void; | |
| 294 | extern fn c_4_f32(usize, usize, usize, usize, f32, usize) void; | |
| 295 | extern fn c_5_f32(usize, usize, usize, usize, usize, f32, usize) void; | |
| 296 | extern fn c_6_f32(usize, usize, usize, usize, usize, usize, f32, usize) void; | |
| 297 | extern fn c_7_f32(usize, usize, usize, usize, usize, usize, usize, f32, usize) void; | |
| 298 | extern fn c_8_f32(usize, usize, usize, usize, usize, usize, usize, usize, f32, usize) void; | |
| 299 | extern fn c_test_f32() void; | |
| 300 | ||
| 301 | test "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 | ||
| 316 | export fn zig_ret_f64() f64 { | |
| 317 | return 1; | |
| 318 | } | |
| 319 | export 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 | } | |
| 323 | export 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 | } | |
| 327 | export 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 | } | |
| 331 | export 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 | } | |
| 335 | export 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 | } | |
| 339 | export 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 | } | |
| 343 | export 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 | } | |
| 347 | export 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 | } | |
| 351 | export 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 | ||
| 356 | extern fn c_ret_f64() f64; | |
| 357 | extern fn c_f64(f64, usize) void; | |
| 358 | extern fn c_1_f64(usize, f64, usize) void; | |
| 359 | extern fn c_2_f64(usize, usize, f64, usize) void; | |
| 360 | extern fn c_3_f64(usize, usize, usize, f64, usize) void; | |
| 361 | extern fn c_4_f64(usize, usize, usize, usize, f64, usize) void; | |
| 362 | extern fn c_5_f64(usize, usize, usize, usize, usize, f64, usize) void; | |
| 363 | extern fn c_6_f64(usize, usize, usize, usize, usize, usize, f64, usize) void; | |
| 364 | extern fn c_7_f64(usize, usize, usize, usize, usize, usize, usize, f64, usize) void; | |
| 365 | extern fn c_8_f64(usize, usize, usize, usize, usize, usize, usize, usize, f64, usize) void; | |
| 366 | extern fn c_test_f64() void; | |
| 367 | ||
| 368 | test "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 | ||
| 383 | export fn zig_ret_longdouble() c_longdouble { | |
| 384 | return 1; | |
| 385 | } | |
| 386 | export 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 | } | |
| 390 | export 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 | } | |
| 394 | export 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 | } | |
| 398 | export 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 | } | |
| 402 | export 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 | } | |
| 406 | export 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 | } | |
| 410 | export 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 | } | |
| 414 | export 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 | } | |
| 418 | export 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 | ||
| 423 | extern fn c_ret_longdouble() c_longdouble; | |
| 424 | extern fn @"c_longdouble"(c_longdouble, usize) void; | |
| 425 | extern fn c_1_longdouble(usize, c_longdouble, usize) void; | |
| 426 | extern fn c_2_longdouble(usize, usize, c_longdouble, usize) void; | |
| 427 | extern fn c_3_longdouble(usize, usize, usize, c_longdouble, usize) void; | |
| 428 | extern fn c_4_longdouble(usize, usize, usize, usize, c_longdouble, usize) void; | |
| 429 | extern fn c_5_longdouble(usize, usize, usize, usize, usize, c_longdouble, usize) void; | |
| 430 | extern fn c_6_longdouble(usize, usize, usize, usize, usize, usize, c_longdouble, usize) void; | |
| 431 | extern fn c_7_longdouble(usize, usize, usize, usize, usize, usize, usize, c_longdouble, usize) void; | |
| 432 | extern fn c_8_longdouble(usize, usize, usize, usize, usize, usize, usize, usize, c_longdouble, usize) void; | |
| 433 | extern fn c_test_longdouble() void; | |
| 434 | ||
| 435 | test "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 | ||
| 272 | 452 | comptime { |
| 273 | 453 | skip: { |
| 274 | if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip; | |
| 275 | if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip; | |
| 454 | if (builtin.zig_backend == .stage2_wasm) break :skip; | |
| 455 | if (builtin.cpu.arch == .hexagon) break :skip; | |
| 456 | if (builtin.cpu.arch == .loongarch64) break :skip; | |
| 457 | if (builtin.cpu.arch.isMIPS()) break :skip; | |
| 458 | if (builtin.cpu.arch.isPowerPC64()) break :skip; | |
| 459 | if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) break :skip; | |
| 276 | 460 | |
| 277 | 461 | _ = struct { |
| 278 | 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 | 478 | extern fn c_test_vector_2_bool() void; |
| 295 | 479 | |
| 296 | 480 | test "@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; | |
| 298 | 489 | |
| 299 | 490 | const vec = c_ret_vector_2_bool(); |
| 300 | 491 | try expect(vec[0] == true); |
| ... | ... | @@ -308,8 +499,12 @@ test "@Vector(2, bool)" { |
| 308 | 499 | |
| 309 | 500 | comptime { |
| 310 | 501 | skip: { |
| 311 | if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip; | |
| 312 | if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip; | |
| 502 | if (builtin.zig_backend == .stage2_wasm) break :skip; | |
| 503 | if (builtin.cpu.arch == .hexagon) break :skip; | |
| 504 | if (builtin.cpu.arch == .loongarch64) break :skip; | |
| 505 | if (builtin.cpu.arch.isMIPS()) break :skip; | |
| 506 | if (builtin.cpu.arch.isPowerPC64()) break :skip; | |
| 507 | if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) break :skip; | |
| 313 | 508 | |
| 314 | 509 | _ = struct { |
| 315 | 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 | 530 | extern fn c_test_vector_4_bool() void; |
| 336 | 531 | |
| 337 | 532 | test "@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; | |
| 339 | 541 | |
| 340 | 542 | const vec = c_ret_vector_4_bool(); |
| 341 | 543 | try expect(vec[0] == true); |
| ... | ... | @@ -353,8 +555,12 @@ test "@Vector(4, bool)" { |
| 353 | 555 | |
| 354 | 556 | comptime { |
| 355 | 557 | skip: { |
| 356 | if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip; | |
| 357 | if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip; | |
| 558 | if (builtin.zig_backend == .stage2_wasm) break :skip; | |
| 559 | if (builtin.cpu.arch == .hexagon) break :skip; | |
| 560 | if (builtin.cpu.arch == .loongarch64) break :skip; | |
| 561 | if (builtin.cpu.arch.isMIPS()) break :skip; | |
| 562 | if (builtin.cpu.arch.isPowerPC64()) break :skip; | |
| 563 | if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) break :skip; | |
| 358 | 564 | |
| 359 | 565 | _ = struct { |
| 360 | 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 | 594 | extern fn c_test_vector_8_bool() void; |
| 389 | 595 | |
| 390 | 596 | test "@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; | |
| 392 | 605 | |
| 393 | 606 | const vec = c_ret_vector_8_bool(); |
| 394 | 607 | try expect(vec[0] == false); |
| ... | ... | @@ -414,8 +627,12 @@ test "@Vector(8, bool)" { |
| 414 | 627 | |
| 415 | 628 | comptime { |
| 416 | 629 | skip: { |
| 417 | if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip; | |
| 418 | if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip; | |
| 630 | if (builtin.zig_backend == .stage2_wasm) break :skip; | |
| 631 | if (builtin.cpu.arch == .hexagon) break :skip; | |
| 632 | if (builtin.cpu.arch == .loongarch64) break :skip; | |
| 633 | if (builtin.cpu.arch.isMIPS()) break :skip; | |
| 634 | if (builtin.cpu.arch.isPowerPC64()) break :skip; | |
| 635 | if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) break :skip; | |
| 419 | 636 | |
| 420 | 637 | _ = struct { |
| 421 | 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 | 682 | extern fn c_test_vector_16_bool() void; |
| 466 | 683 | |
| 467 | 684 | test "@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; | |
| 469 | 693 | |
| 470 | 694 | const vec = c_ret_vector_16_bool(); |
| 471 | 695 | try expect(vec[0] == true); |
| ... | ... | @@ -507,8 +731,12 @@ test "@Vector(16, bool)" { |
| 507 | 731 | |
| 508 | 732 | comptime { |
| 509 | 733 | skip: { |
| 510 | if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip; | |
| 511 | if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip; | |
| 734 | if (builtin.zig_backend == .stage2_wasm) break :skip; | |
| 735 | if (builtin.cpu.arch == .hexagon) break :skip; | |
| 736 | if (builtin.cpu.arch == .loongarch64) break :skip; | |
| 737 | if (builtin.cpu.arch.isMIPS()) break :skip; | |
| 738 | if (builtin.cpu.arch.isPowerPC64()) break :skip; | |
| 739 | if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) break :skip; | |
| 512 | 740 | |
| 513 | 741 | _ = struct { |
| 514 | 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 | 818 | extern fn c_test_vector_32_bool() void; |
| 591 | 819 | |
| 592 | 820 | test "@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; | |
| 594 | 829 | |
| 595 | 830 | const vec = c_ret_vector_32_bool(); |
| 596 | 831 | try expect(vec[0] == true); |
| ... | ... | @@ -664,8 +899,12 @@ test "@Vector(32, bool)" { |
| 664 | 899 | |
| 665 | 900 | comptime { |
| 666 | 901 | skip: { |
| 667 | if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip; | |
| 668 | if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip; | |
| 902 | if (builtin.zig_backend == .stage2_wasm) break :skip; | |
| 903 | if (builtin.cpu.arch == .hexagon) break :skip; | |
| 904 | if (builtin.cpu.arch == .loongarch64) break :skip; | |
| 905 | if (builtin.cpu.arch.isMIPS()) break :skip; | |
| 906 | if (builtin.cpu.arch.isPowerPC64()) break :skip; | |
| 907 | if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) break :skip; | |
| 669 | 908 | |
| 670 | 909 | _ = struct { |
| 671 | 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 | 1050 | extern fn c_test_vector_64_bool() void; |
| 812 | 1051 | |
| 813 | 1052 | test "@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; | |
| 815 | 1059 | |
| 816 | 1060 | const vec = c_ret_vector_64_bool(); |
| 817 | 1061 | try expect(vec[0] == false); |
| ... | ... | @@ -949,8 +1193,12 @@ test "@Vector(64, bool)" { |
| 949 | 1193 | |
| 950 | 1194 | comptime { |
| 951 | 1195 | skip: { |
| 952 | if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip; | |
| 953 | if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip; | |
| 1196 | if (builtin.zig_backend == .stage2_wasm) break :skip; | |
| 1197 | if (builtin.cpu.arch == .hexagon) break :skip; | |
| 1198 | if (builtin.cpu.arch == .loongarch64) break :skip; | |
| 1199 | if (builtin.cpu.arch.isMIPS()) break :skip; | |
| 1200 | if (builtin.cpu.arch.isPowerPC64()) break :skip; | |
| 1201 | if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) break :skip; | |
| 954 | 1202 | |
| 955 | 1203 | _ = struct { |
| 956 | 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 | 1472 | extern fn c_test_vector_128_bool() void; |
| 1225 | 1473 | |
| 1226 | 1474 | test "@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; | |
| 1228 | 1481 | |
| 1229 | 1482 | const vec = c_ret_vector_128_bool(); |
| 1230 | 1483 | try expect(vec[0] == false); |
| ... | ... | @@ -1490,8 +1743,12 @@ test "@Vector(128, bool)" { |
| 1490 | 1743 | |
| 1491 | 1744 | comptime { |
| 1492 | 1745 | skip: { |
| 1493 | if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip; | |
| 1494 | if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip; | |
| 1746 | if (builtin.zig_backend == .stage2_wasm) break :skip; | |
| 1747 | if (builtin.cpu.arch == .hexagon) break :skip; | |
| 1748 | if (builtin.cpu.arch == .loongarch64) break :skip; | |
| 1749 | if (builtin.cpu.arch.isMIPS()) break :skip; | |
| 1750 | if (builtin.cpu.arch.isPowerPC64()) break :skip; | |
| 1751 | if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) break :skip; | |
| 1495 | 1752 | |
| 1496 | 1753 | _ = struct { |
| 1497 | 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 | 2278 | extern fn c_test_vector_256_bool() void; |
| 2022 | 2279 | |
| 2023 | 2280 | test "@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; | |
| 2025 | 2287 | |
| 2026 | 2288 | const vec = c_ret_vector_256_bool(); |
| 2027 | 2289 | try expect(vec[0] == true); |
| ... | ... | @@ -2543,8 +2805,12 @@ test "@Vector(256, bool)" { |
| 2543 | 2805 | |
| 2544 | 2806 | comptime { |
| 2545 | 2807 | skip: { |
| 2546 | if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch == .x86_64) break :skip; | |
| 2547 | if (builtin.zig_backend == .stage2_llvm and builtin.cpu.arch.isPowerPC64()) break :skip; | |
| 2808 | if (builtin.zig_backend == .stage2_wasm) break :skip; | |
| 2809 | if (builtin.cpu.arch == .hexagon) break :skip; | |
| 2810 | if (builtin.cpu.arch == .loongarch64) break :skip; | |
| 2811 | if (builtin.cpu.arch.isMIPS()) break :skip; | |
| 2812 | if (builtin.cpu.arch.isPowerPC64()) break :skip; | |
| 2813 | if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) break :skip; | |
| 2548 | 2814 | |
| 2549 | 2815 | _ = struct { |
| 2550 | 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 | 3852 | extern fn c_test_vector_512_bool() void; |
| 3587 | 3853 | |
| 3588 | 3854 | test "@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; | |
| 3590 | 3861 | |
| 3591 | 3862 | const vec = c_ret_vector_512_bool(); |
| 3592 | 3863 | try expect(vec[0] == false); |
| ... | ... | @@ -4660,7 +4931,7 @@ test "@Vector(2, u8)" { |
| 4660 | 4931 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 4661 | 4932 | if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; |
| 4662 | 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; | |
| 4664 | 4935 | |
| 4665 | 4936 | const v = c_ret_vector_2_u8(); |
| 4666 | 4937 | try expect(v[0] == 9); |
| ... | ... | @@ -4689,7 +4960,6 @@ test "@Vector(3, u8)" { |
| 4689 | 4960 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 4690 | 4961 | if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; |
| 4691 | 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; | |
| 4693 | 4963 | |
| 4694 | 4964 | const v = c_ret_vector_3_u8(); |
| 4695 | 4965 | try expect(v[0] == 19); |
| ... | ... | @@ -4732,7 +5002,7 @@ test "@Vector(4, u8)" { |
| 4732 | 5002 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 4733 | 5003 | if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; |
| 4734 | 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; | |
| 4736 | 5006 | |
| 4737 | 5007 | const v = c_ret_vector_4_u8(); |
| 4738 | 5008 | try expect(v[0] == 41); |
| ... | ... | @@ -4766,7 +5036,6 @@ test "@Vector(6, u8)" { |
| 4766 | 5036 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 4767 | 5037 | if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; |
| 4768 | 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; | |
| 4770 | 5039 | |
| 4771 | 5040 | const v = c_ret_vector_6_u8(); |
| 4772 | 5041 | try expect(v[0] == 53); |
| ... | ... | @@ -4956,7 +5225,6 @@ test "@Vector(24, u8)" { |
| 4956 | 5225 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 4957 | 5226 | if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; |
| 4958 | 5227 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 4959 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 4960 | 5228 | |
| 4961 | 5229 | const v = c_ret_vector_24_u8(); |
| 4962 | 5230 | try expect(v[0] == 57); |
| ... | ... | @@ -5040,7 +5308,6 @@ test "@Vector(32, u8)" { |
| 5040 | 5308 | if (builtin.cpu.arch.isArm()) return error.SkipZigTest; |
| 5041 | 5309 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 5042 | 5310 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 5043 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 5044 | 5311 | |
| 5045 | 5312 | const v = c_ret_vector_32_u8(); |
| 5046 | 5313 | try expect(v[0] == 69); |
| ... | ... | @@ -5150,7 +5417,6 @@ test "@Vector(48, u8)" { |
| 5150 | 5417 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 5151 | 5418 | if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; |
| 5152 | 5419 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 5153 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 5154 | 5420 | |
| 5155 | 5421 | const v = c_ret_vector_48_u8(); |
| 5156 | 5422 | try expect(v[0] == 29); |
| ... | ... | @@ -5293,7 +5559,6 @@ test "@Vector(64, u8)" { |
| 5293 | 5559 | if (builtin.cpu.arch.isArm()) return error.SkipZigTest; |
| 5294 | 5560 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 5295 | 5561 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 5296 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 5297 | 5562 | |
| 5298 | 5563 | const v = c_ret_vector_64_u8(); |
| 5299 | 5564 | try expect(v[0] == 53); |
| ... | ... | @@ -5488,7 +5753,6 @@ test "@Vector(96, u8)" { |
| 5488 | 5753 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 5489 | 5754 | if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; |
| 5490 | 5755 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 5491 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 5492 | 5756 | |
| 5493 | 5757 | const v = c_ret_vector_96_u8(); |
| 5494 | 5758 | try expect(v[0] == 82); |
| ... | ... | @@ -5751,7 +6015,6 @@ test "@Vector(128, u8)" { |
| 5751 | 6015 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 5752 | 6016 | if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; |
| 5753 | 6017 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 5754 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 5755 | 6018 | |
| 5756 | 6019 | const v = c_ret_vector_128_u8(); |
| 5757 | 6020 | try expect(v[0] == 30); |
| ... | ... | @@ -6116,7 +6379,6 @@ test "@Vector(192, u8)" { |
| 6116 | 6379 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 6117 | 6380 | if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; |
| 6118 | 6381 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 6119 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 6120 | 6382 | |
| 6121 | 6383 | const v = c_ret_vector_192_u8(); |
| 6122 | 6384 | try expect(v[0] == 70); |
| ... | ... | @@ -6617,7 +6879,6 @@ test "@Vector(256, u8)" { |
| 6617 | 6879 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 6618 | 6880 | if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; |
| 6619 | 6881 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 6620 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 6621 | 6882 | |
| 6622 | 6883 | const v = c_ret_vector_256_u8(); |
| 6623 | 6884 | try expect(v[0] == 66); |
| ... | ... | @@ -7322,7 +7583,6 @@ test "@Vector(384, u8)" { |
| 7322 | 7583 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 7323 | 7584 | if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; |
| 7324 | 7585 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 7325 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 7326 | 7586 | |
| 7327 | 7587 | const v = c_ret_vector_384_u8(); |
| 7328 | 7588 | try expect(v[0] == 46); |
| ... | ... | @@ -8299,7 +8559,6 @@ test "@Vector(512, u8)" { |
| 8299 | 8559 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 8300 | 8560 | if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; |
| 8301 | 8561 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 8302 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 8303 | 8562 | |
| 8304 | 8563 | const v = c_ret_vector_512_u8(); |
| 8305 | 8564 | try expect(v[0] == 38); |
| ... | ... | @@ -8893,7 +9152,7 @@ test "@Vector(2, u16)" { |
| 8893 | 9152 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 8894 | 9153 | if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; |
| 8895 | 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; | |
| 8897 | 9156 | |
| 8898 | 9157 | const v = c_ret_vector_2_u16(); |
| 8899 | 9158 | try expect(v[0] == 9); |
| ... | ... | @@ -8921,7 +9180,6 @@ test "@Vector(3, u16)" { |
| 8921 | 9180 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 8922 | 9181 | if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; |
| 8923 | 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; | |
| 8925 | 9183 | |
| 8926 | 9184 | const v = c_ret_vector_3_u16(); |
| 8927 | 9185 | try expect(v[0] == 19); |
| ... | ... | @@ -9070,7 +9328,6 @@ test "@Vector(12, u16)" { |
| 9070 | 9328 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 9071 | 9329 | if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; |
| 9072 | 9330 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 9073 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 9074 | 9331 | |
| 9075 | 9332 | const v = c_ret_vector_12_u16(); |
| 9076 | 9333 | try expect(v[0] == 121); |
| ... | ... | @@ -9120,7 +9377,6 @@ test "@Vector(16, u16)" { |
| 9120 | 9377 | if (builtin.cpu.arch.isArm()) return error.SkipZigTest; |
| 9121 | 9378 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 9122 | 9379 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 9123 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 9124 | 9380 | |
| 9125 | 9381 | const v = c_ret_vector_16_u16(); |
| 9126 | 9382 | try expect(v[0] == 177); |
| ... | ... | @@ -9186,7 +9442,6 @@ test "@Vector(24, u16)" { |
| 9186 | 9442 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 9187 | 9443 | if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; |
| 9188 | 9444 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 9189 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 9190 | 9445 | |
| 9191 | 9446 | const v = c_ret_vector_24_u16(); |
| 9192 | 9447 | try expect(v[0] == 257); |
| ... | ... | @@ -9270,7 +9525,6 @@ test "@Vector(32, u16)" { |
| 9270 | 9525 | if (builtin.cpu.arch.isArm()) return error.SkipZigTest; |
| 9271 | 9526 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 9272 | 9527 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 9273 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 9274 | 9528 | |
| 9275 | 9529 | const v = c_ret_vector_32_u16(); |
| 9276 | 9530 | try expect(v[0] == 369); |
| ... | ... | @@ -9380,7 +9634,6 @@ test "@Vector(48, u16)" { |
| 9380 | 9634 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 9381 | 9635 | if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; |
| 9382 | 9636 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 9383 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 9384 | 9637 | |
| 9385 | 9638 | const v = c_ret_vector_48_u16(); |
| 9386 | 9639 | try expect(v[0] == 529); |
| ... | ... | @@ -9524,7 +9777,6 @@ test "@Vector(64, u16)" { |
| 9524 | 9777 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 9525 | 9778 | if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; |
| 9526 | 9779 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 9527 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 9528 | 9780 | |
| 9529 | 9781 | const v = c_ret_vector_64_u16(); |
| 9530 | 9782 | try expect(v[0] == 753); |
| ... | ... | @@ -9719,7 +9971,6 @@ test "@Vector(96, u16)" { |
| 9719 | 9971 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 9720 | 9972 | if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; |
| 9721 | 9973 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 9722 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 9723 | 9974 | |
| 9724 | 9975 | const v = c_ret_vector_96_u16(); |
| 9725 | 9976 | try expect(v[0] == 1082); |
| ... | ... | @@ -9982,7 +10233,6 @@ test "@Vector(128, u16)" { |
| 9982 | 10233 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 9983 | 10234 | if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; |
| 9984 | 10235 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 9985 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 9986 | 10236 | |
| 9987 | 10237 | const v = c_ret_vector_128_u16(); |
| 9988 | 10238 | try expect(v[0] == 1530); |
| ... | ... | @@ -10347,7 +10597,6 @@ test "@Vector(192, u16)" { |
| 10347 | 10597 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 10348 | 10598 | if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; |
| 10349 | 10599 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 10350 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 10351 | 10600 | |
| 10352 | 10601 | const v = c_ret_vector_192_u16(); |
| 10353 | 10602 | try expect(v[0] == 2170); |
| ... | ... | @@ -10848,7 +11097,6 @@ test "@Vector(256, u16)" { |
| 10848 | 11097 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 10849 | 11098 | if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; |
| 10850 | 11099 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 10851 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 10852 | 11100 | |
| 10853 | 11101 | const v = c_ret_vector_256_u16(); |
| 10854 | 11102 | try expect(v[0] == 3066); |
| ... | ... | @@ -11265,7 +11513,6 @@ test "@Vector(6, u32)" { |
| 11265 | 11513 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 11266 | 11514 | if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; |
| 11267 | 11515 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 11268 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 11269 | 11516 | |
| 11270 | 11517 | const v = c_ret_vector_6_u32(); |
| 11271 | 11518 | try expect(v[0] == 53); |
| ... | ... | @@ -11301,7 +11548,6 @@ test "@Vector(8, u32)" { |
| 11301 | 11548 | if (builtin.cpu.arch.isArm()) return error.SkipZigTest; |
| 11302 | 11549 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 11303 | 11550 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 11304 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 11305 | 11551 | |
| 11306 | 11552 | const v = c_ret_vector_8_u32(); |
| 11307 | 11553 | try expect(v[0] == 81); |
| ... | ... | @@ -11344,7 +11590,6 @@ test "@Vector(12, u32)" { |
| 11344 | 11590 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 11345 | 11591 | if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; |
| 11346 | 11592 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 11347 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 11348 | 11593 | |
| 11349 | 11594 | const v = c_ret_vector_12_u32(); |
| 11350 | 11595 | try expect(v[0] == 121); |
| ... | ... | @@ -11394,7 +11639,6 @@ test "@Vector(16, u32)" { |
| 11394 | 11639 | if (builtin.cpu.arch.isArm()) return error.SkipZigTest; |
| 11395 | 11640 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 11396 | 11641 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 11397 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 11398 | 11642 | |
| 11399 | 11643 | const v = c_ret_vector_16_u32(); |
| 11400 | 11644 | try expect(v[0] == 177); |
| ... | ... | @@ -11460,7 +11704,6 @@ test "@Vector(24, u32)" { |
| 11460 | 11704 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 11461 | 11705 | if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; |
| 11462 | 11706 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 11463 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 11464 | 11707 | |
| 11465 | 11708 | const v = c_ret_vector_24_u32(); |
| 11466 | 11709 | try expect(v[0] == 257); |
| ... | ... | @@ -11545,7 +11788,6 @@ test "@Vector(32, u32)" { |
| 11545 | 11788 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 11546 | 11789 | if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; |
| 11547 | 11790 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 11548 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 11549 | 11791 | |
| 11550 | 11792 | const v = c_ret_vector_32_u32(); |
| 11551 | 11793 | try expect(v[0] == 369); |
| ... | ... | @@ -11655,7 +11897,6 @@ test "@Vector(48, u32)" { |
| 11655 | 11897 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 11656 | 11898 | if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; |
| 11657 | 11899 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 11658 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 11659 | 11900 | |
| 11660 | 11901 | const v = c_ret_vector_48_u32(); |
| 11661 | 11902 | try expect(v[0] == 529); |
| ... | ... | @@ -11799,7 +12040,6 @@ test "@Vector(64, u32)" { |
| 11799 | 12040 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 11800 | 12041 | if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; |
| 11801 | 12042 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 11802 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 11803 | 12043 | |
| 11804 | 12044 | const v = c_ret_vector_64_u32(); |
| 11805 | 12045 | try expect(v[0] == 753); |
| ... | ... | @@ -11994,7 +12234,6 @@ test "@Vector(96, u32)" { |
| 11994 | 12234 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 11995 | 12235 | if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; |
| 11996 | 12236 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 11997 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 11998 | 12237 | |
| 11999 | 12238 | const v = c_ret_vector_96_u32(); |
| 12000 | 12239 | try expect(v[0] == 1082); |
| ... | ... | @@ -12257,7 +12496,6 @@ test "@Vector(128, u32)" { |
| 12257 | 12496 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 12258 | 12497 | if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; |
| 12259 | 12498 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 12260 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 12261 | 12499 | |
| 12262 | 12500 | const v = c_ret_vector_128_u32(); |
| 12263 | 12501 | try expect(v[0] == 1530); |
| ... | ... | @@ -12414,8 +12652,6 @@ extern fn c_vector_1_u64(@Vector(1, u64), usize) void; |
| 12414 | 12652 | extern fn c_test_vector_1_u64() void; |
| 12415 | 12653 | |
| 12416 | 12654 | test "@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 | 12655 | const v = c_ret_vector_1_u64(); |
| 12420 | 12656 | try expect(v[0] == 3); |
| 12421 | 12657 | c_vector_1_u64(.{4}, 1); |
| ... | ... | @@ -12464,7 +12700,6 @@ test "@Vector(3, u64)" { |
| 12464 | 12700 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 12465 | 12701 | if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; |
| 12466 | 12702 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 12467 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 12468 | 12703 | |
| 12469 | 12704 | const v = c_ret_vector_3_u64(); |
| 12470 | 12705 | try expect(v[0] == 19); |
| ... | ... | @@ -12493,7 +12728,6 @@ test "@Vector(4, u64)" { |
| 12493 | 12728 | if (builtin.cpu.arch.isArm()) return error.SkipZigTest; |
| 12494 | 12729 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 12495 | 12730 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 12496 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 12497 | 12731 | |
| 12498 | 12732 | const v = c_ret_vector_4_u64(); |
| 12499 | 12733 | try expect(v[0] == 33); |
| ... | ... | @@ -12560,7 +12794,6 @@ test "@Vector(8, u64)" { |
| 12560 | 12794 | if (builtin.cpu.arch.isArm()) return error.SkipZigTest; |
| 12561 | 12795 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 12562 | 12796 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 12563 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 12564 | 12797 | |
| 12565 | 12798 | const v = c_ret_vector_8_u64(); |
| 12566 | 12799 | try expect(v[0] == 81); |
| ... | ... | @@ -12652,7 +12885,6 @@ test "@Vector(16, u64)" { |
| 12652 | 12885 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 12653 | 12886 | if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; |
| 12654 | 12887 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 12655 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 12656 | 12888 | |
| 12657 | 12889 | const v = c_ret_vector_16_u64(); |
| 12658 | 12890 | try expect(v[0] == 177); |
| ... | ... | @@ -12801,7 +13033,6 @@ test "@Vector(32, u64)" { |
| 12801 | 13033 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 12802 | 13034 | if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; |
| 12803 | 13035 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 12804 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 12805 | 13036 | |
| 12806 | 13037 | const v = c_ret_vector_32_u64(); |
| 12807 | 13038 | try expect(v[0] == 369); |
| ... | ... | @@ -13053,7 +13284,6 @@ test "@Vector(64, u64)" { |
| 13053 | 13284 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 13054 | 13285 | if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; |
| 13055 | 13286 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 13056 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 13057 | 13287 | |
| 13058 | 13288 | const v = c_ret_vector_64_u64(); |
| 13059 | 13289 | try expect(v[0] == 753); |
| ... | ... | @@ -13147,7 +13377,6 @@ test "@Vector(1, f32)" { |
| 13147 | 13377 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 13148 | 13378 | if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; |
| 13149 | 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; | |
| 13151 | 13380 | |
| 13152 | 13381 | const v = c_ret_vector_1_f32(); |
| 13153 | 13382 | try expect(v[0] == 3); |
| ... | ... | @@ -13269,7 +13498,6 @@ test "@Vector(6, f32)" { |
| 13269 | 13498 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 13270 | 13499 | if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; |
| 13271 | 13500 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 13272 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 13273 | 13501 | |
| 13274 | 13502 | const v = c_ret_vector_6_f32(); |
| 13275 | 13503 | try expect(v[0] == 53); |
| ... | ... | @@ -13306,7 +13534,6 @@ test "@Vector(8, f32)" { |
| 13306 | 13534 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 13307 | 13535 | if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; |
| 13308 | 13536 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 13309 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 13310 | 13537 | |
| 13311 | 13538 | const v = c_ret_vector_8_f32(); |
| 13312 | 13539 | try expect(v[0] == 81); |
| ... | ... | @@ -13349,7 +13576,6 @@ test "@Vector(12, f32)" { |
| 13349 | 13576 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 13350 | 13577 | if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; |
| 13351 | 13578 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 13352 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 13353 | 13579 | |
| 13354 | 13580 | const v = c_ret_vector_12_f32(); |
| 13355 | 13581 | try expect(v[0] == 121); |
| ... | ... | @@ -13400,7 +13626,6 @@ test "@Vector(16, f32)" { |
| 13400 | 13626 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 13401 | 13627 | if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; |
| 13402 | 13628 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 13403 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 13404 | 13629 | |
| 13405 | 13630 | const v = c_ret_vector_16_f32(); |
| 13406 | 13631 | try expect(v[0] == 177); |
| ... | ... | @@ -13466,7 +13691,6 @@ test "@Vector(24, f32)" { |
| 13466 | 13691 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 13467 | 13692 | if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; |
| 13468 | 13693 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 13469 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 13470 | 13694 | |
| 13471 | 13695 | const v = c_ret_vector_24_f32(); |
| 13472 | 13696 | try expect(v[0] == 257); |
| ... | ... | @@ -13551,7 +13775,6 @@ test "@Vector(32, f32)" { |
| 13551 | 13775 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 13552 | 13776 | if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; |
| 13553 | 13777 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 13554 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 13555 | 13778 | |
| 13556 | 13779 | const v = c_ret_vector_32_f32(); |
| 13557 | 13780 | try expect(v[0] == 369); |
| ... | ... | @@ -13661,7 +13884,6 @@ test "@Vector(48, f32)" { |
| 13661 | 13884 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 13662 | 13885 | if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; |
| 13663 | 13886 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 13664 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 13665 | 13887 | |
| 13666 | 13888 | const v = c_ret_vector_48_f32(); |
| 13667 | 13889 | try expect(v[0] == 529); |
| ... | ... | @@ -13805,7 +14027,6 @@ test "@Vector(64, f32)" { |
| 13805 | 14027 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 13806 | 14028 | if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; |
| 13807 | 14029 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 13808 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 13809 | 14030 | |
| 13810 | 14031 | const v = c_ret_vector_64_f32(); |
| 13811 | 14032 | try expect(v[0] == 753); |
| ... | ... | @@ -14000,7 +14221,6 @@ test "@Vector(96, f32)" { |
| 14000 | 14221 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 14001 | 14222 | if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; |
| 14002 | 14223 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 14003 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 14004 | 14224 | |
| 14005 | 14225 | const v = c_ret_vector_96_f32(); |
| 14006 | 14226 | try expect(v[0] == 1082); |
| ... | ... | @@ -14263,7 +14483,6 @@ test "@Vector(128, f32)" { |
| 14263 | 14483 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 14264 | 14484 | if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; |
| 14265 | 14485 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 14266 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 14267 | 14486 | |
| 14268 | 14487 | const v = c_ret_vector_128_f32(); |
| 14269 | 14488 | try expect(v[0] == 1530); |
| ... | ... | @@ -14471,7 +14690,6 @@ test "@Vector(3, f64)" { |
| 14471 | 14690 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 14472 | 14691 | if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; |
| 14473 | 14692 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 14474 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 14475 | 14693 | |
| 14476 | 14694 | const v = c_ret_vector_3_f64(); |
| 14477 | 14695 | try expect(v[0] == 19); |
| ... | ... | @@ -14500,8 +14718,6 @@ test "@Vector(4, f64)" { |
| 14500 | 14718 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 14501 | 14719 | if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; |
| 14502 | 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 | |
| 14505 | 14721 | |
| 14506 | 14722 | const v = c_ret_vector_4_f64(); |
| 14507 | 14723 | try expect(v[0] == 33); |
| ... | ... | @@ -14534,7 +14750,6 @@ test "@Vector(6, f64)" { |
| 14534 | 14750 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 14535 | 14751 | if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; |
| 14536 | 14752 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 14537 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 14538 | 14753 | |
| 14539 | 14754 | const v = c_ret_vector_6_f64(); |
| 14540 | 14755 | try expect(v[0] == 53); |
| ... | ... | @@ -14570,8 +14785,6 @@ test "@Vector(8, f64)" { |
| 14570 | 14785 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 14571 | 14786 | if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; |
| 14572 | 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 | |
| 14575 | 14788 | |
| 14576 | 14789 | const v = c_ret_vector_8_f64(); |
| 14577 | 14790 | try expect(v[0] == 81); |
| ... | ... | @@ -14614,7 +14827,6 @@ test "@Vector(12, f64)" { |
| 14614 | 14827 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 14615 | 14828 | if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; |
| 14616 | 14829 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 14617 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 14618 | 14830 | |
| 14619 | 14831 | const v = c_ret_vector_12_f64(); |
| 14620 | 14832 | try expect(v[0] == 121); |
| ... | ... | @@ -14665,7 +14877,6 @@ test "@Vector(16, f64)" { |
| 14665 | 14877 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 14666 | 14878 | if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; |
| 14667 | 14879 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 14668 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 14669 | 14880 | |
| 14670 | 14881 | const v = c_ret_vector_16_f64(); |
| 14671 | 14882 | try expect(v[0] == 177); |
| ... | ... | @@ -14731,7 +14942,6 @@ test "@Vector(24, f64)" { |
| 14731 | 14942 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 14732 | 14943 | if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; |
| 14733 | 14944 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 14734 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 14735 | 14945 | |
| 14736 | 14946 | const v = c_ret_vector_24_f64(); |
| 14737 | 14947 | try expect(v[0] == 257); |
| ... | ... | @@ -14816,7 +15026,6 @@ test "@Vector(32, f64)" { |
| 14816 | 15026 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 14817 | 15027 | if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; |
| 14818 | 15028 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 14819 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 14820 | 15029 | |
| 14821 | 15030 | const v = c_ret_vector_32_f64(); |
| 14822 | 15031 | try expect(v[0] == 369); |
| ... | ... | @@ -14926,7 +15135,6 @@ test "@Vector(48, f64)" { |
| 14926 | 15135 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 14927 | 15136 | if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; |
| 14928 | 15137 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 14929 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 14930 | 15138 | |
| 14931 | 15139 | const v = c_ret_vector_48_f64(); |
| 14932 | 15140 | try expect(v[0] == 529); |
| ... | ... | @@ -15070,7 +15278,6 @@ test "@Vector(64, f64)" { |
| 15070 | 15278 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 15071 | 15279 | if (builtin.cpu.arch.isMIPS32()) return error.SkipZigTest; |
| 15072 | 15280 | if (builtin.cpu.arch.isPowerPC64()) return error.SkipZigTest; |
| 15073 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 15074 | 15281 | |
| 15075 | 15282 | const v = c_ret_vector_64_f64(); |
| 15076 | 15283 | try expect(v[0] == 753); |
| ... | ... | @@ -15165,7 +15372,6 @@ extern fn c_test_struct_u8() void; |
| 15165 | 15372 | test "struct u8" { |
| 15166 | 15373 | if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; |
| 15167 | 15374 | if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; |
| 15168 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 15169 | 15375 | if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; |
| 15170 | 15376 | |
| 15171 | 15377 | const s = c_ret_struct_u8(); |
| ... | ... | @@ -15196,8 +15402,7 @@ test "struct u8, u8" { |
| 15196 | 15402 | if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; |
| 15197 | 15403 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 15198 | 15404 | if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; |
| 15199 | if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; | |
| 15200 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 15405 | if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; | |
| 15201 | 15406 | if (builtin.cpu.arch == .x86) return error.SkipZigTest; |
| 15202 | 15407 | |
| 15203 | 15408 | const s = c_ret_struct_u8_u8(); |
| ... | ... | @@ -15231,8 +15436,7 @@ test "struct u8, u8, u8" { |
| 15231 | 15436 | if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; |
| 15232 | 15437 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 15233 | 15438 | if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; |
| 15234 | if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; | |
| 15235 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 15439 | if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; | |
| 15236 | 15440 | if (builtin.cpu.arch == .x86) return error.SkipZigTest; |
| 15237 | 15441 | |
| 15238 | 15442 | const s = c_ret_struct_u8_u8_u8(); |
| ... | ... | @@ -15269,8 +15473,7 @@ test "struct u8, u8, u8, u8" { |
| 15269 | 15473 | if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; |
| 15270 | 15474 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 15271 | 15475 | if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; |
| 15272 | if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; | |
| 15273 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 15476 | if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; | |
| 15274 | 15477 | if (builtin.cpu.arch == .x86) return error.SkipZigTest; |
| 15275 | 15478 | |
| 15276 | 15479 | const s = c_ret_struct_u8_u8_u8_u8(); |
| ... | ... | @@ -15301,7 +15504,6 @@ extern fn c_test_struct_u16() void; |
| 15301 | 15504 | test "struct u16" { |
| 15302 | 15505 | if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; |
| 15303 | 15506 | if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; |
| 15304 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 15305 | 15507 | if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; |
| 15306 | 15508 | |
| 15307 | 15509 | const s = c_ret_struct_u16(); |
| ... | ... | @@ -15332,8 +15534,7 @@ test "struct u16, u16" { |
| 15332 | 15534 | if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; |
| 15333 | 15535 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 15334 | 15536 | if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; |
| 15335 | if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; | |
| 15336 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 15537 | if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; | |
| 15337 | 15538 | if (builtin.cpu.arch == .x86) return error.SkipZigTest; |
| 15338 | 15539 | |
| 15339 | 15540 | const s = c_ret_struct_u16_u16(); |
| ... | ... | @@ -15367,9 +15568,8 @@ test "struct u16, u16, u16" { |
| 15367 | 15568 | if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; |
| 15368 | 15569 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 15369 | 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 | 15572 | if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest; |
| 15372 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 15373 | 15573 | if (builtin.cpu.arch == .x86) return error.SkipZigTest; |
| 15374 | 15574 | |
| 15375 | 15575 | const s = c_ret_struct_u16_u16_u16(); |
| ... | ... | @@ -15406,9 +15606,8 @@ test "struct u16, u16, u16, u16" { |
| 15406 | 15606 | if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; |
| 15407 | 15607 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 15408 | 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 | 15610 | if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest; |
| 15411 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 15412 | 15611 | if (builtin.cpu.arch == .x86) return error.SkipZigTest; |
| 15413 | 15612 | |
| 15414 | 15613 | const s = c_ret_struct_u16_u16_u16_u16(); |
| ... | ... | @@ -15439,7 +15638,6 @@ extern fn c_test_struct_u32() void; |
| 15439 | 15638 | test "struct u32" { |
| 15440 | 15639 | if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; |
| 15441 | 15640 | if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; |
| 15442 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 15443 | 15641 | if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; |
| 15444 | 15642 | |
| 15445 | 15643 | const s = c_ret_struct_u32(); |
| ... | ... | @@ -15469,9 +15667,8 @@ extern fn c_test_struct_u32_u32() void; |
| 15469 | 15667 | test "struct u32, u32" { |
| 15470 | 15668 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 15471 | 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 | 15671 | if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest; |
| 15474 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 15475 | 15672 | if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; |
| 15476 | 15673 | |
| 15477 | 15674 | const s = c_ret_struct_u32_u32(); |
| ... | ... | @@ -15505,8 +15702,7 @@ test "struct u32, u32, u32" { |
| 15505 | 15702 | if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; |
| 15506 | 15703 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 15507 | 15704 | if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; |
| 15508 | if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; | |
| 15509 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 15705 | if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; | |
| 15510 | 15706 | |
| 15511 | 15707 | const s = c_ret_struct_u32_u32_u32(); |
| 15512 | 15708 | try expect(s.a == 8); |
| ... | ... | @@ -15542,8 +15738,7 @@ test "struct u32, u32, u32, u32" { |
| 15542 | 15738 | if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; |
| 15543 | 15739 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 15544 | 15740 | if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; |
| 15545 | if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; | |
| 15546 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 15741 | if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; | |
| 15547 | 15742 | |
| 15548 | 15743 | const s = c_ret_struct_u32_u32_u32_u32(); |
| 15549 | 15744 | try expect(s.a == 10); |
| ... | ... | @@ -15573,7 +15768,6 @@ extern fn c_test_struct_u64() void; |
| 15573 | 15768 | test "struct u64" { |
| 15574 | 15769 | if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; |
| 15575 | 15770 | if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest; |
| 15576 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 15577 | 15771 | if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; |
| 15578 | 15772 | |
| 15579 | 15773 | const s = c_ret_struct_u64(); |
| ... | ... | @@ -15651,7 +15845,6 @@ extern fn c_test_struct_u64_u64() void; |
| 15651 | 15845 | test "struct u64, u64" { |
| 15652 | 15846 | if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; |
| 15653 | 15847 | if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; |
| 15654 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 15655 | 15848 | |
| 15656 | 15849 | const s = c_ret_struct_u64_u64(); |
| 15657 | 15850 | try expect(s.a == 21); |
| ... | ... | @@ -15691,8 +15884,7 @@ extern fn c_test_struct_u64_u64_u64() void; |
| 15691 | 15884 | test "struct u64, u64, u64" { |
| 15692 | 15885 | if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; |
| 15693 | 15886 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 15694 | if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; | |
| 15695 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 15887 | if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; | |
| 15696 | 15888 | |
| 15697 | 15889 | const s = c_ret_struct_u64_u64_u64(); |
| 15698 | 15890 | try expect(s.a == 8); |
| ... | ... | @@ -15727,8 +15919,7 @@ extern fn c_test_struct_u64_u64_u64_u64() void; |
| 15727 | 15919 | test "struct u64, u64, u64, u64" { |
| 15728 | 15920 | if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; |
| 15729 | 15921 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 15730 | if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; | |
| 15731 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 15922 | if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; | |
| 15732 | 15923 | |
| 15733 | 15924 | const s = c_ret_struct_u64_u64_u64_u64(); |
| 15734 | 15925 | try expect(s.a == 10); |
| ... | ... | @@ -15757,8 +15948,7 @@ extern fn c_test_struct_f32() void; |
| 15757 | 15948 | |
| 15758 | 15949 | test "struct f32" { |
| 15759 | 15950 | if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; |
| 15760 | if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; | |
| 15761 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 15951 | if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; | |
| 15762 | 15952 | if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; |
| 15763 | 15953 | |
| 15764 | 15954 | const s = c_ret_struct_f32(); |
| ... | ... | @@ -15791,7 +15981,6 @@ test "struct f32, f32" { |
| 15791 | 15981 | if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; |
| 15792 | 15982 | if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; |
| 15793 | 15983 | if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest; |
| 15794 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 15795 | 15984 | if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; |
| 15796 | 15985 | |
| 15797 | 15986 | const s = c_ret_struct_f32_f32(); |
| ... | ... | @@ -15827,7 +16016,6 @@ test "struct f32, f32, f32" { |
| 15827 | 16016 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 15828 | 16017 | if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; |
| 15829 | 16018 | if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; |
| 15830 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 15831 | 16019 | |
| 15832 | 16020 | const s = c_ret_struct_f32_f32_f32(); |
| 15833 | 16021 | try expect(s.a == 8); |
| ... | ... | @@ -15865,7 +16053,6 @@ test "struct f32, f32, f32, f32" { |
| 15865 | 16053 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 15866 | 16054 | if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; |
| 15867 | 16055 | if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; |
| 15868 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 15869 | 16056 | |
| 15870 | 16057 | const s = c_ret_struct_f32_f32_f32_f32(); |
| 15871 | 16058 | try expect(s.a == 10); |
| ... | ... | @@ -15905,7 +16092,6 @@ test "struct f32, f32, f32, f32, f32" { |
| 15905 | 16092 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 15906 | 16093 | if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; |
| 15907 | 16094 | if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; |
| 15908 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 15909 | 16095 | |
| 15910 | 16096 | const s = c_ret_struct_f32_f32_f32_f32_f32(); |
| 15911 | 16097 | try expect(s.a == 12); |
| ... | ... | @@ -15917,31 +16103,408 @@ test "struct f32, f32, f32, f32, f32" { |
| 15917 | 16103 | c_test_struct_f32_f32_f32_f32_f32(); |
| 15918 | 16104 | } |
| 15919 | 16105 | |
| 15920 | const Struct_f32a8 = extern struct { | |
| 15921 | a: f32 align(8), | |
| 16106 | const Struct_void_f32 = extern struct { | |
| 16107 | _: void = {}, | |
| 16108 | a: f32, | |
| 15922 | 16109 | }; |
| 15923 | 16110 | |
| 15924 | export fn zig_ret_struct_f32a8() Struct_f32a8 { | |
| 15925 | return .{ .a = 1.25 }; | |
| 16111 | export fn zig_ret_struct_void_f32() Struct_void_f32 { | |
| 16112 | return .{ .a = 1 }; | |
| 15926 | 16113 | } |
| 15927 | export fn zig_struct_f32a8(s: Struct_f32a8, f: f32) void { | |
| 15928 | expect(s.a == 2.75) catch @panic("test failure"); | |
| 15929 | expect(f == 3.5) catch @panic("test failure"); | |
| 16114 | export fn zig_struct_void_f32(s: Struct_void_f32, i: usize) void { | |
| 16115 | expect(s.a == 2) catch @panic("test failure"); | |
| 16116 | expect(i == 3) catch @panic("test failure"); | |
| 15930 | 16117 | } |
| 15931 | 16118 | |
| 15932 | extern fn c_ret_struct_f32a8() Struct_f32a8; | |
| 15933 | extern fn c_struct_f32a8(Struct_f32a8, f32) void; | |
| 15934 | extern fn c_test_struct_f32a8() void; | |
| 16119 | extern fn c_ret_struct_void_f32() Struct_void_f32; | |
| 16120 | extern fn c_struct_void_f32(Struct_void_f32, usize) void; | |
| 16121 | extern fn c_test_struct_void_f32() void; | |
| 15935 | 16122 | |
| 15936 | test "struct f32 align(8)" { | |
| 15937 | if (builtin.cpu.arch.isArm()) return error.SkipZigTest; | |
| 15938 | if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; | |
| 15939 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; | |
| 16123 | test "struct void, f32" { | |
| 15940 | 16124 | if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; |
| 15941 | 16125 | if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; |
| 15942 | if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest; | |
| 15943 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 15944 | if (builtin.cpu.arch == .x86) return error.SkipZigTest; | |
| 16126 | if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; | |
| 16127 | ||
| 16128 | const s = c_ret_struct_void_f32(); | |
| 16129 | try expect(s.a == 4); | |
| 16130 | c_struct_void_f32(.{ .a = 5 }, 6); | |
| 16131 | c_test_struct_void_f32(); | |
| 16132 | } | |
| 16133 | ||
| 16134 | const Struct_array_1_f32 = extern struct { | |
| 16135 | a: [1]f32, | |
| 16136 | }; | |
| 16137 | ||
| 16138 | export fn zig_ret_struct_array_1_f32() Struct_array_1_f32 { | |
| 16139 | return .{ .a = .{1} }; | |
| 16140 | } | |
| 16141 | export 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 | ||
| 16146 | extern fn c_ret_struct_array_1_f32() Struct_array_1_f32; | |
| 16147 | extern fn c_struct_array_1_f32(Struct_array_1_f32, usize) void; | |
| 16148 | extern fn c_test_struct_array_1_f32() void; | |
| 16149 | ||
| 16150 | test "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 | ||
| 16163 | const Struct_array_2_f32 = extern struct { | |
| 16164 | a: [2]f32, | |
| 16165 | }; | |
| 16166 | ||
| 16167 | export fn zig_ret_struct_array_2_f32() Struct_array_2_f32 { | |
| 16168 | return .{ .a = .{ 1, 2 } }; | |
| 16169 | } | |
| 16170 | export 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 | ||
| 16176 | extern fn c_ret_struct_array_2_f32() Struct_array_2_f32; | |
| 16177 | extern fn c_struct_array_2_f32(Struct_array_2_f32, usize) void; | |
| 16178 | extern fn c_test_struct_array_2_f32() void; | |
| 16179 | ||
| 16180 | test "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 | ||
| 16195 | const Struct_array_3_f32 = extern struct { | |
| 16196 | a: [3]f32, | |
| 16197 | }; | |
| 16198 | ||
| 16199 | export fn zig_ret_struct_array_3_f32() Struct_array_3_f32 { | |
| 16200 | return .{ .a = .{ 1, 2, 3 } }; | |
| 16201 | } | |
| 16202 | export 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 | ||
| 16209 | extern fn c_ret_struct_array_3_f32() Struct_array_3_f32; | |
| 16210 | extern fn c_struct_array_3_f32(Struct_array_3_f32, usize) void; | |
| 16211 | extern fn c_test_struct_array_3_f32() void; | |
| 16212 | ||
| 16213 | test "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 | ||
| 16228 | const Struct_array_4_f32 = extern struct { | |
| 16229 | a: [4]f32, | |
| 16230 | }; | |
| 16231 | ||
| 16232 | export fn zig_ret_struct_array_4_f32() Struct_array_4_f32 { | |
| 16233 | return .{ .a = .{ 1, 2, 3, 4 } }; | |
| 16234 | } | |
| 16235 | export 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 | ||
| 16243 | extern fn c_ret_struct_array_4_f32() Struct_array_4_f32; | |
| 16244 | extern fn c_struct_array_4_f32(Struct_array_4_f32, usize) void; | |
| 16245 | extern fn c_test_struct_array_4_f32() void; | |
| 16246 | ||
| 16247 | test "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 | ||
| 16263 | const Struct_array_5_f32 = extern struct { | |
| 16264 | a: [5]f32, | |
| 16265 | }; | |
| 16266 | ||
| 16267 | export fn zig_ret_struct_array_5_f32() Struct_array_5_f32 { | |
| 16268 | return .{ .a = .{ 1, 2, 3, 4, 5 } }; | |
| 16269 | } | |
| 16270 | export 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 | ||
| 16279 | extern fn c_ret_struct_array_5_f32() Struct_array_5_f32; | |
| 16280 | extern fn c_struct_array_5_f32(Struct_array_5_f32, usize) void; | |
| 16281 | extern fn c_test_struct_array_5_f32() void; | |
| 16282 | ||
| 16283 | test "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 | ||
| 16299 | const Struct_array_0_sentinel_f32 = extern struct { | |
| 16300 | a: [0:0x1e1]f32, | |
| 16301 | }; | |
| 16302 | ||
| 16303 | export fn zig_ret_struct_array_0_sentinel_f32() Struct_array_0_sentinel_f32 { | |
| 16304 | return .{ .a = .{} }; | |
| 16305 | } | |
| 16306 | export 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 | ||
| 16313 | extern fn c_ret_struct_array_0_sentinel_f32() Struct_array_0_sentinel_f32; | |
| 16314 | extern fn c_struct_array_0_sentinel_f32(Struct_array_0_sentinel_f32, usize) void; | |
| 16315 | extern fn c_test_struct_array_0_sentinel_f32() void; | |
| 16316 | ||
| 16317 | test "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 | ||
| 16332 | const Struct_array_1_sentinel_f32 = extern struct { | |
| 16333 | a: [1:0x1e1]f32, | |
| 16334 | }; | |
| 16335 | ||
| 16336 | export fn zig_ret_struct_array_1_sentinel_f32() Struct_array_1_sentinel_f32 { | |
| 16337 | return .{ .a = .{1} }; | |
| 16338 | } | |
| 16339 | export 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 | ||
| 16347 | extern fn c_ret_struct_array_1_sentinel_f32() Struct_array_1_sentinel_f32; | |
| 16348 | extern fn c_struct_array_1_sentinel_f32(Struct_array_1_sentinel_f32, usize) void; | |
| 16349 | extern fn c_test_struct_array_1_sentinel_f32() void; | |
| 16350 | ||
| 16351 | test "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 | ||
| 16368 | const Struct_array_2_sentinel_f32 = extern struct { | |
| 16369 | a: [2:0x1e1]f32, | |
| 16370 | }; | |
| 16371 | ||
| 16372 | export fn zig_ret_struct_array_2_sentinel_f32() Struct_array_2_sentinel_f32 { | |
| 16373 | return .{ .a = .{ 1, 2 } }; | |
| 16374 | } | |
| 16375 | export 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 | ||
| 16384 | extern fn c_ret_struct_array_2_sentinel_f32() Struct_array_2_sentinel_f32; | |
| 16385 | extern fn c_struct_array_2_sentinel_f32(Struct_array_2_sentinel_f32, usize) void; | |
| 16386 | extern fn c_test_struct_array_2_sentinel_f32() void; | |
| 16387 | ||
| 16388 | test "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 | ||
| 16405 | const Struct_array_3_sentinel_f32 = extern struct { | |
| 16406 | a: [3:0x1e1]f32, | |
| 16407 | }; | |
| 16408 | ||
| 16409 | export fn zig_ret_struct_array_3_sentinel_f32() Struct_array_3_sentinel_f32 { | |
| 16410 | return .{ .a = .{ 1, 2, 3 } }; | |
| 16411 | } | |
| 16412 | export 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 | ||
| 16422 | extern fn c_ret_struct_array_3_sentinel_f32() Struct_array_3_sentinel_f32; | |
| 16423 | extern fn c_struct_array_3_sentinel_f32(Struct_array_3_sentinel_f32, usize) void; | |
| 16424 | extern fn c_test_struct_array_3_sentinel_f32() void; | |
| 16425 | ||
| 16426 | test "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 | ||
| 16444 | const Struct_array_4_sentinel_f32 = extern struct { | |
| 16445 | a: [4:0x1e1]f32, | |
| 16446 | }; | |
| 16447 | ||
| 16448 | export fn zig_ret_struct_array_4_sentinel_f32() Struct_array_4_sentinel_f32 { | |
| 16449 | return .{ .a = .{ 1, 2, 3, 4 } }; | |
| 16450 | } | |
| 16451 | export 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 | ||
| 16462 | extern fn c_ret_struct_array_4_sentinel_f32() Struct_array_4_sentinel_f32; | |
| 16463 | extern fn c_struct_array_4_sentinel_f32(Struct_array_4_sentinel_f32, usize) void; | |
| 16464 | extern fn c_test_struct_array_4_sentinel_f32() void; | |
| 16465 | ||
| 16466 | test "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 | ||
| 16484 | const Struct_f32a8 = extern struct { | |
| 16485 | a: f32 align(8), | |
| 16486 | }; | |
| 16487 | ||
| 16488 | export fn zig_ret_struct_f32a8() Struct_f32a8 { | |
| 16489 | return .{ .a = 1.25 }; | |
| 16490 | } | |
| 16491 | export 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 | ||
| 16496 | extern fn c_ret_struct_f32a8() Struct_f32a8; | |
| 16497 | extern fn c_struct_f32a8(Struct_f32a8, f32) void; | |
| 16498 | extern fn c_test_struct_f32a8() void; | |
| 16499 | ||
| 16500 | test "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; | |
| 15945 | 16508 | |
| 15946 | 16509 | const s = c_ret_struct_f32a8(); |
| 15947 | 16510 | try expect(s.a == 4.125); |
| ... | ... | @@ -15974,7 +16537,6 @@ test "struct f32 align(8), f32 align(8)" { |
| 15974 | 16537 | if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; |
| 15975 | 16538 | if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; |
| 15976 | 16539 | if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest; |
| 15977 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 15978 | 16540 | if (builtin.cpu.arch == .x86) return error.SkipZigTest; |
| 15979 | 16541 | |
| 15980 | 16542 | const s = c_ret_struct_f32a8_f32a8(); |
| ... | ... | @@ -16007,8 +16569,7 @@ test "struct {f32, f32}, f32" { |
| 16007 | 16569 | if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; |
| 16008 | 16570 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 16009 | 16571 | if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; |
| 16010 | if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; | |
| 16011 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 16572 | if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; | |
| 16012 | 16573 | |
| 16013 | 16574 | const s = c_ret_struct_f32f32_f32(); |
| 16014 | 16575 | try expect(s.a.b == 1.0); |
| ... | ... | @@ -16041,8 +16602,7 @@ test "struct f32, {f32, f32}" { |
| 16041 | 16602 | if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; |
| 16042 | 16603 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 16043 | 16604 | if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; |
| 16044 | if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; | |
| 16045 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 16605 | if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; | |
| 16046 | 16606 | |
| 16047 | 16607 | const s = c_ret_struct_f32_f32f32(); |
| 16048 | 16608 | try expect(s.a == 1.0); |
| ... | ... | @@ -16070,9 +16630,8 @@ extern fn c_test_struct_f64() void; |
| 16070 | 16630 | |
| 16071 | 16631 | test "struct f64" { |
| 16072 | 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 | 16634 | if (builtin.cpu.arch.isRiscv32()) return error.SkipZigTest; |
| 16075 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 16076 | 16635 | if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; |
| 16077 | 16636 | |
| 16078 | 16637 | const s = c_ret_struct_f64(); |
| ... | ... | @@ -16102,8 +16661,7 @@ extern fn c_test_struct_f64_f64() void; |
| 16102 | 16661 | test "struct f64, f64" { |
| 16103 | 16662 | if (builtin.cpu.arch.isArm() and builtin.abi.float() == .soft) return error.SkipZigTest; |
| 16104 | 16663 | if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; |
| 16105 | if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; | |
| 16106 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 16664 | if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; | |
| 16107 | 16665 | |
| 16108 | 16666 | const s = c_ret_struct_f64_f64(); |
| 16109 | 16667 | try expect(s.a == 6); |
| ... | ... | @@ -16135,8 +16693,7 @@ extern fn c_test_struct_f64_f64_f64() void; |
| 16135 | 16693 | test "struct f64, f64, f64" { |
| 16136 | 16694 | if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; |
| 16137 | 16695 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 16138 | if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; | |
| 16139 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 16696 | if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; | |
| 16140 | 16697 | |
| 16141 | 16698 | const s = c_ret_struct_f64_f64_f64(); |
| 16142 | 16699 | try expect(s.a == 8); |
| ... | ... | @@ -16171,8 +16728,7 @@ extern fn c_test_struct_f64_f64_f64_f64() void; |
| 16171 | 16728 | test "struct f64, f64, f64, f64" { |
| 16172 | 16729 | if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; |
| 16173 | 16730 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 16174 | if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; | |
| 16175 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 16731 | if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; | |
| 16176 | 16732 | |
| 16177 | 16733 | const s = c_ret_struct_f64_f64_f64_f64(); |
| 16178 | 16734 | try expect(s.a == 10); |
| ... | ... | @@ -16210,8 +16766,7 @@ extern fn c_test_struct_f64_f64_f64_f64_f64() void; |
| 16210 | 16766 | test "struct f64, f64, f64, f64, f64" { |
| 16211 | 16767 | if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; |
| 16212 | 16768 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 16213 | if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; | |
| 16214 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 16769 | if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; | |
| 16215 | 16770 | |
| 16216 | 16771 | const s = c_ret_struct_f64_f64_f64_f64_f64(); |
| 16217 | 16772 | try expect(s.a == 12); |
| ... | ... | @@ -16223,6 +16778,201 @@ test "struct f64, f64, f64, f64, f64" { |
| 16223 | 16778 | c_test_struct_f64_f64_f64_f64_f64(); |
| 16224 | 16779 | } |
| 16225 | 16780 | |
| 16781 | const Struct_array_1_f64 = extern struct { | |
| 16782 | a: [1]f64, | |
| 16783 | }; | |
| 16784 | ||
| 16785 | export fn zig_ret_struct_array_1_f64() Struct_array_1_f64 { | |
| 16786 | return .{ .a = .{1} }; | |
| 16787 | } | |
| 16788 | export 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 | ||
| 16793 | extern fn c_ret_struct_array_1_f64() Struct_array_1_f64; | |
| 16794 | extern fn c_struct_array_1_f64(Struct_array_1_f64, usize) void; | |
| 16795 | extern fn c_test_struct_array_1_f64() void; | |
| 16796 | ||
| 16797 | test "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 | ||
| 16810 | const Struct_array_2_f64 = extern struct { | |
| 16811 | a: [2]f64, | |
| 16812 | }; | |
| 16813 | ||
| 16814 | export fn zig_ret_struct_array_2_f64() Struct_array_2_f64 { | |
| 16815 | return .{ .a = .{ 1, 2 } }; | |
| 16816 | } | |
| 16817 | export 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 | ||
| 16823 | extern fn c_ret_struct_array_2_f64() Struct_array_2_f64; | |
| 16824 | extern fn c_struct_array_2_f64(Struct_array_2_f64, usize) void; | |
| 16825 | extern fn c_test_struct_array_2_f64() void; | |
| 16826 | ||
| 16827 | test "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 | ||
| 16843 | const Struct_array_3_f64 = extern struct { | |
| 16844 | a: [3]f64, | |
| 16845 | }; | |
| 16846 | ||
| 16847 | export fn zig_ret_struct_array_3_f64() Struct_array_3_f64 { | |
| 16848 | return .{ .a = .{ 1, 2, 3 } }; | |
| 16849 | } | |
| 16850 | export 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 | ||
| 16857 | extern fn c_ret_struct_array_3_f64() Struct_array_3_f64; | |
| 16858 | extern fn c_struct_array_3_f64(Struct_array_3_f64, usize) void; | |
| 16859 | extern fn c_test_struct_array_3_f64() void; | |
| 16860 | ||
| 16861 | test "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 | ||
| 16876 | const Struct_array_4_f64 = extern struct { | |
| 16877 | a: [4]f64, | |
| 16878 | }; | |
| 16879 | ||
| 16880 | export fn zig_ret_struct_array_4_f64() Struct_array_4_f64 { | |
| 16881 | return .{ .a = .{ 1, 2, 3, 4 } }; | |
| 16882 | } | |
| 16883 | export 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 | ||
| 16891 | extern fn c_ret_struct_array_4_f64() Struct_array_4_f64; | |
| 16892 | extern fn c_struct_array_4_f64(Struct_array_4_f64, usize) void; | |
| 16893 | extern fn c_test_struct_array_4_f64() void; | |
| 16894 | ||
| 16895 | test "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 | ||
| 16911 | const Struct_array_5_f64 = extern struct { | |
| 16912 | a: [5]f64, | |
| 16913 | }; | |
| 16914 | ||
| 16915 | export fn zig_ret_struct_array_5_f64() Struct_array_5_f64 { | |
| 16916 | return .{ .a = .{ 1, 2, 3, 4, 5 } }; | |
| 16917 | } | |
| 16918 | export 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 | ||
| 16927 | extern fn c_ret_struct_array_5_f64() Struct_array_5_f64; | |
| 16928 | extern fn c_struct_array_5_f64(Struct_array_5_f64, usize) void; | |
| 16929 | extern fn c_test_struct_array_5_f64() void; | |
| 16930 | ||
| 16931 | test "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 | ||
| 16946 | const Union_f64 = extern union { | |
| 16947 | a: f64, | |
| 16948 | }; | |
| 16949 | ||
| 16950 | export fn zig_ret_union_f64() Union_f64 { | |
| 16951 | return .{ .a = 1 }; | |
| 16952 | } | |
| 16953 | export 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 | ||
| 16958 | extern fn c_ret_union_f64() Union_f64; | |
| 16959 | extern fn c_union_f64(Union_f64, usize) void; | |
| 16960 | extern fn c_test_union_f64() void; | |
| 16961 | ||
| 16962 | test "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 | ||
| 16226 | 16976 | const Struct_u32_Union_u32_u32u32 = extern struct { |
| 16227 | 16977 | a: u32, |
| 16228 | 16978 | b: extern union { |
| ... | ... | @@ -16250,8 +17000,7 @@ test "struct{u32,union{u32,struct{u32,u32}}}" { |
| 16250 | 17000 | if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; |
| 16251 | 17001 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 16252 | 17002 | if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; |
| 16253 | if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; | |
| 16254 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 17003 | if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; | |
| 16255 | 17004 | |
| 16256 | 17005 | const s = c_ret_struct_u32_union_u32_u32u32(); |
| 16257 | 17006 | try expect(s.a == 1); |
| ... | ... | @@ -16269,11 +17018,10 @@ extern fn c_mut_struct_i32_i32(Struct_i32_i32) Struct_i32_i32; |
| 16269 | 17018 | extern fn c_struct_i32_i32(Struct_i32_i32) void; |
| 16270 | 17019 | |
| 16271 | 17020 | test "struct i32 i32" { |
| 17021 | if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; | |
| 16272 | 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 | 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 | 17025 | if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; |
| 16278 | 17026 | |
| 16279 | 17027 | const s: Struct_i32_i32 = .{ |
| ... | ... | @@ -16303,11 +17051,10 @@ const BigStruct = extern struct { |
| 16303 | 17051 | extern fn c_big_struct(BigStruct) void; |
| 16304 | 17052 | |
| 16305 | 17053 | test "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 | 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; | |
| 16311 | 17058 | |
| 16312 | 17059 | const s = BigStruct{ |
| 16313 | 17060 | .a = 1, |
| ... | ... | @@ -16333,10 +17080,9 @@ const BigUnion = extern union { |
| 16333 | 17080 | extern fn c_big_union(BigUnion) void; |
| 16334 | 17081 | |
| 16335 | 17082 | test "big union" { |
| 16336 | if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; | |
| 16337 | if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; | |
| 16338 | 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; | |
| 16340 | 17086 | |
| 16341 | 17087 | const x = BigUnion{ |
| 16342 | 17088 | .a = BigStruct{ |
| ... | ... | @@ -16368,11 +17114,10 @@ extern fn c_med_struct_mixed(MedStructMixed) void; |
| 16368 | 17114 | extern fn c_ret_med_struct_mixed() MedStructMixed; |
| 16369 | 17115 | |
| 16370 | 17116 | test "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 | 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; | |
| 16376 | 17121 | |
| 16377 | 17122 | const s = MedStructMixed{ |
| 16378 | 17123 | .a = 1234, |
| ... | ... | @@ -16448,12 +17193,11 @@ const SplitStructInt = extern struct { |
| 16448 | 17193 | extern fn c_split_struct_ints(SplitStructInt) void; |
| 16449 | 17194 | |
| 16450 | 17195 | test "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 | 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; | |
| 16457 | 17201 | |
| 16458 | 17202 | const s = SplitStructInt{ |
| 16459 | 17203 | .a = 1234, |
| ... | ... | @@ -16478,12 +17222,11 @@ extern fn c_split_struct_mixed(SplitStructMixed) void; |
| 16478 | 17222 | extern fn c_ret_split_struct_mixed() SplitStructMixed; |
| 16479 | 17223 | |
| 16480 | 17224 | test "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 | 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; | |
| 16487 | 17230 | |
| 16488 | 17231 | const s = SplitStructMixed{ |
| 16489 | 17232 | .a = 1234, |
| ... | ... | @@ -16506,11 +17249,10 @@ export fn zig_split_struct_mixed(x: SplitStructMixed) void { |
| 16506 | 17249 | extern fn c_big_struct_both(BigStruct) BigStruct; |
| 16507 | 17250 | |
| 16508 | 17251 | test "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 | 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; | |
| 16514 | 17256 | |
| 16515 | 17257 | const s = BigStruct{ |
| 16516 | 17258 | .a = 1, |
| ... | ... | @@ -16620,12 +17362,11 @@ extern fn c_struct_with_array(StructWithArray) void; |
| 16620 | 17362 | extern fn c_ret_struct_with_array() StructWithArray; |
| 16621 | 17363 | |
| 16622 | 17364 | test "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 | 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; | |
| 16629 | 17370 | |
| 16630 | 17371 | c_struct_with_array(.{ .a = 1, .padding = undefined, .b = 2 }); |
| 16631 | 17372 | |
| ... | ... | @@ -16649,11 +17390,10 @@ extern fn c_float_array_struct(FloatArrayStruct) void; |
| 16649 | 17390 | extern fn c_ret_float_array_struct() FloatArrayStruct; |
| 16650 | 17391 | |
| 16651 | 17392 | test "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 | 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; | |
| 16657 | 17397 | |
| 16658 | 17398 | c_float_array_struct(.{ |
| 16659 | 17399 | .origin = .{ |
| ... | ... | @@ -16684,37 +17424,37 @@ pub inline fn expectOk(c_err: c_int) !void { |
| 16684 | 17424 | /// Tests for Double + Char struct |
| 16685 | 17425 | const DC = extern struct { v1: f64, v2: u8 }; |
| 16686 | 17426 | test "DC: Zig passes to C" { |
| 17427 | if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; | |
| 17428 | if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; | |
| 16687 | 17429 | if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; |
| 17430 | if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; | |
| 16688 | 17431 | if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest; |
| 16689 | if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; | |
| 16690 | if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; | |
| 16691 | if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; | |
| 16692 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 17432 | ||
| 16693 | 17433 | try expectOk(c_assert_DC(.{ .v1 = -0.25, .v2 = 15 })); |
| 16694 | 17434 | } |
| 16695 | 17435 | test "DC: Zig returns to C" { |
| 17436 | if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; | |
| 16696 | 17437 | if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; |
| 17438 | if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; | |
| 16697 | 17439 | if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest; |
| 16698 | if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; | |
| 16699 | if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; | |
| 16700 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 17440 | ||
| 16701 | 17441 | try expectOk(c_assert_ret_DC()); |
| 16702 | 17442 | } |
| 16703 | 17443 | test "DC: C passes to Zig" { |
| 17444 | if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; | |
| 17445 | if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; | |
| 16704 | 17446 | if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; |
| 17447 | if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; | |
| 16705 | 17448 | if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest; |
| 16706 | if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; | |
| 16707 | if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; | |
| 16708 | if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; | |
| 16709 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 17449 | ||
| 16710 | 17450 | try expectOk(c_send_DC()); |
| 16711 | 17451 | } |
| 16712 | 17452 | test "DC: C returns to Zig" { |
| 17453 | if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; | |
| 16713 | 17454 | if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; |
| 17455 | if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; | |
| 16714 | 17456 | if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest; |
| 16715 | if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; | |
| 16716 | if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; | |
| 16717 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 17457 | ||
| 16718 | 17458 | try expectEqual(DC{ .v1 = -0.25, .v2 = 15 }, c_ret_DC()); |
| 16719 | 17459 | } |
| 16720 | 17460 | |
| ... | ... | @@ -16739,36 +17479,35 @@ const CFF = extern struct { v1: u8, v2: f32, v3: f32 }; |
| 16739 | 17479 | test "CFF: Zig passes to C" { |
| 16740 | 17480 | if (builtin.target.cpu.arch == .x86) return error.SkipZigTest; |
| 16741 | 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 | 17483 | if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; |
| 16744 | 17484 | if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; |
| 16745 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 17485 | ||
| 16746 | 17486 | try expectOk(c_assert_CFF(.{ .v1 = 39, .v2 = 0.875, .v3 = 1.0 })); |
| 16747 | 17487 | } |
| 16748 | 17488 | test "CFF: Zig returns to C" { |
| 16749 | 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 | 17491 | if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; |
| 16752 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 17492 | ||
| 16753 | 17493 | try expectOk(c_assert_ret_CFF()); |
| 16754 | 17494 | } |
| 16755 | 17495 | test "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 | 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; | |
| 16763 | 17502 | |
| 16764 | 17503 | try expectOk(c_send_CFF()); |
| 16765 | 17504 | } |
| 16766 | 17505 | test "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 | 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 | 17511 | try expectEqual(CFF{ .v1 = 39, .v2 = 0.875, .v3 = 1.0 }, c_ret_CFF()); |
| 16773 | 17512 | } |
| 16774 | 17513 | pub extern fn c_assert_CFF(lv: CFF) c_int; |
| ... | ... | @@ -16791,35 +17530,35 @@ pub export fn zig_ret_CFF() CFF { |
| 16791 | 17530 | const PD = extern struct { v1: ?*anyopaque, v2: f64 }; |
| 16792 | 17531 | |
| 16793 | 17532 | test "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 | 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 | 17537 | if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; |
| 17538 | ||
| 16800 | 17539 | try expectOk(c_assert_PD(.{ .v1 = null, .v2 = 0.5 })); |
| 16801 | 17540 | } |
| 16802 | 17541 | test "PD: Zig returns to C" { |
| 16803 | if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; | |
| 16804 | if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; | |
| 16805 | 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 | 17546 | try expectOk(c_assert_ret_PD()); |
| 16808 | 17547 | } |
| 16809 | 17548 | test "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 | 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 | 17553 | if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; |
| 17554 | ||
| 16816 | 17555 | try expectOk(c_send_PD()); |
| 16817 | 17556 | } |
| 16818 | 17557 | test "PD: C returns to Zig" { |
| 16819 | if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; | |
| 16820 | if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; | |
| 16821 | 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 | 17562 | try expectEqual(PD{ .v1 = null, .v2 = 0.5 }, c_ret_PD()); |
| 16824 | 17563 | } |
| 16825 | 17564 | pub extern fn c_assert_PD(lv: PD) c_int; |
| ... | ... | @@ -16853,7 +17592,6 @@ extern fn c_modify_by_ref_param(ByRef) ByRef; |
| 16853 | 17592 | test "C function modifies by ref param" { |
| 16854 | 17593 | if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; |
| 16855 | 17594 | if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; |
| 16856 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; | |
| 16857 | 17595 | |
| 16858 | 17596 | const res = c_modify_by_ref_param(.{ .val = 1, .arr = undefined }); |
| 16859 | 17597 | try expect(res.val == 42); |
| ... | ... | @@ -16874,11 +17612,10 @@ const ByVal = extern struct { |
| 16874 | 17612 | |
| 16875 | 17613 | extern fn c_func_ptr_byval(*anyopaque, *anyopaque, ByVal, c_ulong, *anyopaque, c_ulong) void; |
| 16876 | 17614 | test "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 | 17617 | if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; |
| 16878 | 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; | |
| 16882 | 17619 | |
| 16883 | 17620 | var fn_ptr = &c_func_ptr_byval; |
| 16884 | 17621 | _ = &fn_ptr; |
| ... | ... | @@ -16897,17 +17634,16 @@ test "C function that takes byval struct called via function pointer" { |
| 16897 | 17634 | |
| 16898 | 17635 | extern fn c_f16(f16) f16; |
| 16899 | 17636 | test "f16 bare" { |
| 16900 | if (builtin.cpu.arch == .x86_64) return error.SkipZigTest; | |
| 16901 | if (builtin.cpu.arch == .x86) return error.SkipZigTest; | |
| 17637 | if (builtin.cpu.arch.isArm()) return error.SkipZigTest; | |
| 16902 | 17638 | if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; |
| 16903 | 17639 | if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; |
| 16904 | 17640 | if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; |
| 17641 | if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; | |
| 16905 | 17642 | if (builtin.cpu.arch.isRISCV()) return error.SkipZigTest; |
| 16906 | 17643 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; |
| 16907 | 17644 | if (builtin.cpu.arch.isWasm()) return error.SkipZigTest; |
| 16908 | if (builtin.cpu.arch.isPowerPC()) return error.SkipZigTest; | |
| 16909 | ||
| 16910 | if (builtin.cpu.arch.isArm()) return error.SkipZigTest; | |
| 17645 | if (builtin.cpu.arch == .x86) return error.SkipZigTest; | |
| 17646 | if (builtin.cpu.arch == .x86_64) return error.SkipZigTest; | |
| 16911 | 17647 | |
| 16912 | 17648 | const a = c_f16(12); |
| 16913 | 17649 | try expect(a == 34); |
| ... | ... | @@ -16918,9 +17654,9 @@ const f16_struct = extern struct { |
| 16918 | 17654 | }; |
| 16919 | 17655 | extern fn c_f16_struct(f16_struct) f16_struct; |
| 16920 | 17656 | test "f16 struct" { |
| 17657 | if (builtin.cpu.arch.isArm() and builtin.mode != .debug) return error.SkipZigTest; | |
| 16921 | 17658 | if (builtin.target.cpu.arch.isMIPS64()) return error.SkipZigTest; |
| 16922 | 17659 | if (builtin.target.cpu.arch.isPowerPC32()) return error.SkipZigTest; |
| 16923 | if (builtin.cpu.arch.isArm() and builtin.mode != .Debug) return error.SkipZigTest; | |
| 16924 | 17660 | if (builtin.cpu.arch == .s390x) return error.SkipZigTest; |
| 16925 | 17661 | if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; |
| 16926 | 17662 | |
| ... | ... | @@ -17027,11 +17763,10 @@ const Coord2 = extern struct { |
| 17027 | 17763 | |
| 17028 | 17764 | extern fn stdcall_coord2(Coord2, Coord2, Coord2) callconv(stdcall_callconv) Coord2; |
| 17029 | 17765 | test "Stdcall ABI structs" { |
| 17766 | if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; | |
| 17767 | if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; | |
| 17030 | 17768 | if (builtin.cpu.arch.isMIPS64()) return error.SkipZigTest; |
| 17031 | 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 | 17770 | if (builtin.cpu.arch == .x86 and builtin.os.tag == .windows) return error.SkipZigTest; |
| 17036 | 17771 | |
| 17037 | 17772 | const res = stdcall_coord2( |
| ... | ... | @@ -17045,10 +17780,9 @@ test "Stdcall ABI structs" { |
| 17045 | 17780 | |
| 17046 | 17781 | extern fn stdcall_big_union(BigUnion) callconv(stdcall_callconv) void; |
| 17047 | 17782 | test "Stdcall ABI big union" { |
| 17048 | if (builtin.cpu.arch.isPowerPC32()) return error.SkipZigTest; | |
| 17049 | if (builtin.cpu.arch.isLoongArch()) return error.SkipZigTest; | |
| 17050 | 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; | |
| 17052 | 17786 | |
| 17053 | 17787 | const x = BigUnion{ |
| 17054 | 17788 | .a = BigStruct{ |
| ... | ... | @@ -17120,11 +17854,10 @@ const byval_tail_callsite_attr = struct { |
| 17120 | 17854 | }; |
| 17121 | 17855 | |
| 17122 | 17856 | test "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 | 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; | |
| 17128 | 17861 | |
| 17129 | 17862 | // Originally reported at https://github.com/ziglang/zig/issues/16290 |
| 17130 | 17863 | // the bug was that the extern function had the byval attribute, but |
| ... | ... | @@ -17268,11 +18001,19 @@ test "x86 vectorcall calling convention" { |
| 17268 | 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 | } |
| 17270 | 18003 | |
| 18004 | extern fn c_x86_64_sysv_uint_int_uint_int(a: u8, b: i8, c: u16, d: i16) void; | |
| 18005 | ||
| 18006 | test "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 | ||
| 17271 | 18012 | extern fn c_win64_varargs_u64_f64_u64_f64(...) void; |
| 17272 | 18013 | extern fn c_win64_varargs_f64_u64_f64_u64(...) void; |
| 17273 | 18014 | |
| 17274 | 18015 | test "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; | |
| 17276 | 18017 | |
| 17277 | 18018 | const Opv = extern struct {}; |
| 17278 | 18019 | c_win64_varargs_u64_f64_u64_f64( |
| ... | ... | @@ -17298,3 +18039,25 @@ test "win64 varargs" { |
| 17298 | 18039 | @as(Opv, .{}), |
| 17299 | 18040 | ); |
| 17300 | 18041 | } |
| 18042 | ||
| 18043 | const preserve_none_cc: ?std.lang.CallingConvention = if (builtin.zig_backend != .stage2_llvm) | |
| 18044 | null | |
| 18045 | else switch (builtin.cpu.arch) { | |
| 18046 | .x86_64 => .{ .x86_64_preserve_none = .{} }, | |
| 18047 | .aarch64, .aarch64_be => .{ .aarch64_preserve_none = .{} }, | |
| 18048 | else => null, | |
| 18049 | }; | |
| 18050 | ||
| 18051 | export fn zig_preserve_none(x: i32) callconv(preserve_none_cc orelse .c) i32 { | |
| 18052 | return x + 1; | |
| 18053 | } | |
| 18054 | ||
| 18055 | test "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 | 15 | pub const castToNull = simple_panic.castToNull; |
| 16 | 16 | pub const incorrectAlignment = simple_panic.incorrectAlignment; |
| 17 | 17 | pub const invalidErrorCode = simple_panic.invalidErrorCode; |
| 18 | pub const unexpectedErrorCode = simple_panic.unexpectedErrorCode; | |
| 18 | 19 | pub const integerOutOfBounds = simple_panic.integerOutOfBounds; |
| 19 | 20 | pub const integerOverflow = simple_panic.integerOverflow; |
| 20 | 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 | 11 | pub const castToNull = simple_panic.castToNull; |
| 12 | 12 | pub const incorrectAlignment = simple_panic.incorrectAlignment; |
| 13 | 13 | pub const invalidErrorCode = simple_panic.invalidErrorCode; |
| 14 | pub const unexpectedErrorCode = simple_panic.unexpectedErrorCode; | |
| 14 | 15 | pub const integerOutOfBounds = simple_panic.integerOutOfBounds; |
| 15 | 16 | pub const integerOverflow = simple_panic.integerOverflow; |
| 16 | 17 | pub const shlOverflow = simple_panic.shlOverflow; |
test/cases/compile_errors/callconv_preserve_none_on_unsupported_platform.zig created+16| ... | ... | @@ -0,0 +1,16 @@ |
| 1 | const F1 = fn () callconv(.{ .x86_64_preserve_none = .{} }) void; | |
| 2 | const F2 = fn () callconv(.{ .aarch64_preserve_none = .{} }) void; | |
| 3 | export fn entry1() void { | |
| 4 | const a: F1 = undefined; | |
| 5 | _ = a; | |
| 6 | } | |
| 7 | export 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 | 16 | while (null) |*_| {} |
| 17 | 17 | } |
| 18 | 18 | |
| 19 | export fn e() void { | |
| 20 | if (0) |*_| {} else |err| switch (err) {} | |
| 21 | } | |
| 22 | ||
| 19 | 23 | // error |
| 20 | 24 | // |
| 21 | 25 | // :2:16: error: pointer modifier invalid on discard |
| 22 | 26 | // :7:18: error: pointer modifier invalid on discard |
| 23 | 27 | // :12:16: error: pointer modifier invalid on discard |
| 24 | 28 | // :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 | 28 | _ = q; |
| 29 | 29 | } |
| 30 | 30 | |
| 31 | export fn entry6(p: **[3]u8) void { | |
| 32 | const q: *[]u8 = p; | |
| 33 | _ = q; | |
| 34 | } | |
| 35 | ||
| 36 | export fn entry7(p: *[]u8) void { | |
| 37 | const q: **[3]u8 = p; | |
| 38 | _ = q; | |
| 39 | } | |
| 40 | ||
| 31 | 41 | // error |
| 32 | 42 | // |
| 33 | 43 | // :3:22: error: expected type '**i32', found '**u32' |
| ... | ... | @@ -50,3 +60,7 @@ export fn entry5() void { |
| 50 | 60 | // :27:24: note: pointer type child '*[1:42]u8' cannot cast into pointer type child '*[1]u8' |
| 51 | 61 | // :27:24: note: pointer type child '[1:42]u8' cannot cast into pointer type child '[1]u8' |
| 52 | 62 | // :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 @@ |
| 1 | export fn foo() void { | |
| 2 | var size: @Vector(4, c_int) = undefined; | |
| 3 | bar(&size[0]); | |
| 4 | } | |
| 5 | extern 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 | 6 | |
| 7 | 7 | // 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 @@ |
| 1 | export fn entry2() void { | |
| 2 | comptime var slice: []const u16 = &.{ 1, 2, 3 }; | |
| 3 | slice.len = undefined; | |
| 4 | _ = slice.*; | |
| 5 | } | |
| 6 | ||
| 7 | export fn entry3() void { | |
| 8 | comptime var slice: []const u16 = &.{ 1, 2, 3 }; | |
| 9 | slice.len = undefined; | |
| 10 | _ = &slice.*; | |
| 11 | } | |
| 12 | ||
| 13 | export 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 | 7 | |
| 8 | 8 | // 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 | 17 | |
| 18 | 18 | // error |
| 19 | 19 | // |
| 20 | // :5:9: error: duplicate switch value | |
| 20 | // :5:9: error: duplicate switch value 'true' | |
| 21 | 21 | // :3:9: note: previous value here |
| 22 | // :13:9: error: duplicate switch value | |
| 22 | // :13:9: error: duplicate switch value 'false' | |
| 23 | 23 | // :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 | 16 | |
| 17 | 17 | // error |
| 18 | 18 | // |
| 19 | // :5:9: error: duplicate switch value | |
| 19 | // :5:9: error: duplicate switch value 'error.Foo' | |
| 20 | 20 | // :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 | 14 | |
| 15 | 15 | // error |
| 16 | 16 | // |
| 17 | // :2:14: error: error union is ignored | |
| 17 | // :2:14: error: error union of type 'anyerror!i32' is ignored | |
| 18 | 18 | // :2:14: note: consider using 'try', 'catch', or 'if' |
| 19 | // :9:15: error: error set is ignored | |
| 19 | // :9:15: error: error set of type 'anyerror' is ignored |
test/cases/compile_errors/ignored_expression_in_while_continuation.zig+4-4| ... | ... | @@ -24,10 +24,10 @@ fn bad2() anyerror { |
| 24 | 24 | |
| 25 | 25 | // error |
| 26 | 26 | // |
| 27 | // :2:24: error: error union is ignored | |
| 27 | // :2:24: error: error union of type 'anyerror!void' is ignored | |
| 28 | 28 | // :2:24: note: consider using 'try', 'catch', or 'if' |
| 29 | // :7:25: error: error union is ignored | |
| 29 | // :7:25: error: error union of type 'anyerror!void' is ignored | |
| 30 | 30 | // :7:25: note: consider using 'try', 'catch', or 'if' |
| 31 | // :12:25: error: error union is ignored | |
| 31 | // :12:25: error: error union of type 'anyerror!void' is ignored | |
| 32 | 32 | // :12:25: note: consider using 'try', 'catch', or 'if' |
| 33 | // :19:25: error: error set is ignored | |
| 33 | // :19:25: error: error set of type 'anyerror' is ignored |
test/cases/compile_errors/initialize_empty_union.zig-31| ... | ... | @@ -28,25 +28,6 @@ export fn init5() void { |
| 28 | 28 | _ = @as(U5, undefined); |
| 29 | 29 | } |
| 30 | 30 | |
| 31 | export fn deref0(ptr: *const U0) void { | |
| 32 | _ = ptr.*; | |
| 33 | } | |
| 34 | export fn deref1(ptr: *const U1) void { | |
| 35 | _ = ptr.*; | |
| 36 | } | |
| 37 | export fn deref2(ptr: *const U2) void { | |
| 38 | _ = ptr.*; | |
| 39 | } | |
| 40 | export fn deref3(ptr: *const U3) void { | |
| 41 | _ = ptr.*; | |
| 42 | } | |
| 43 | export fn deref4(ptr: *const U4) void { | |
| 44 | _ = ptr.*; | |
| 45 | } | |
| 46 | export fn deref5(ptr: *const U5) void { | |
| 47 | _ = ptr.*; | |
| 48 | } | |
| 49 | ||
| 50 | 31 | // error |
| 51 | 32 | // |
| 52 | 33 | // :13:17: error: expected type 'tmp.U0', found '@TypeOf(undefined)' |
| ... | ... | @@ -67,15 +48,3 @@ export fn deref5(ptr: *const U5) void { |
| 67 | 48 | // :28:17: error: expected type 'tmp.U5', found '@TypeOf(undefined)' |
| 68 | 49 | // :28:17: note: cannot coerce to uninstantiable type 'tmp.U5' |
| 69 | 50 | // :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 | 22 | // error |
| 23 | 23 | // |
| 24 | 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 | 26 | // :14:32: error: expected integer type, found 'f32' |
| 27 | 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 | 8 | _ = &a; |
| 9 | 9 | _ = @as(u32, @floatFromInt(a)); |
| 10 | 10 | } |
| 11 | export fn bar2() void { | |
| 12 | _ = @as(comptime_int, @floatFromInt(2)); | |
| 13 | } | |
| 11 | 14 | export fn baz() void { |
| 12 | 15 | var a: u32 = 2; |
| 13 | 16 | _ = &a; |
| ... | ... | @@ -22,6 +25,7 @@ export fn qux() void { |
| 22 | 25 | // error |
| 23 | 26 | // |
| 24 | 27 | // :4:36: error: unable to cast runtime value to 'comptime_int' |
| 25 | // :9:18: error: expected float type, found 'u32' | |
| 26 | // :14:32: error: expected float type, found 'u32' | |
| 27 | // :19:27: error: expected integer or vector, found 'f32' | |
| 28 | // :9:18: error: expected float result type, found 'u32' | |
| 29 | // :12:27: error: expected float result type, found 'comptime_int' | |
| 30 | // :17:32: error: expected float type, found 'u32' | |
| 31 | // :22:27: error: expected integer or vector, found 'f32' |
test/cases/compile_errors/invalid_member_of_builtin_enum.zig+1-1| ... | ... | @@ -6,5 +6,5 @@ export fn entry() void { |
| 6 | 6 | |
| 7 | 7 | // 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 | 10 | // : note: enum declared here |
test/cases/compile_errors/slice_to_array_pointer.zig created+70| ... | ... | @@ -0,0 +1,70 @@ |
| 1 | export fn entry1() void { | |
| 2 | var array: [2]u16 = .{ 1, 2 }; | |
| 3 | const slice: []const u16 = &array; | |
| 4 | foo(slice); | |
| 5 | } | |
| 6 | ||
| 7 | export fn entry2() void { | |
| 8 | const slice: []const u16 = undefined; | |
| 9 | foo(slice); | |
| 10 | } | |
| 11 | ||
| 12 | export fn entry3() void { | |
| 13 | comptime var slice: []const u16 = &.{ 1, 2 }; | |
| 14 | slice.len = undefined; | |
| 15 | foo(slice); | |
| 16 | } | |
| 17 | ||
| 18 | export fn entry4() void { | |
| 19 | const slice: []const u16 = &.{ 1, 2, 3 }; | |
| 20 | foo(slice); | |
| 21 | } | |
| 22 | ||
| 23 | export fn entry5() void { | |
| 24 | const slice: []const u8 = &.{ 1, 2 }; | |
| 25 | foo(slice); | |
| 26 | } | |
| 27 | ||
| 28 | fn foo(x: *const [2]u16) void { | |
| 29 | _ = x; | |
| 30 | } | |
| 31 | ||
| 32 | export fn entry6() void { | |
| 33 | const slice: [:0]const u16 = &.{ 1, 2, 3 }; | |
| 34 | bar(slice); | |
| 35 | } | |
| 36 | ||
| 37 | export fn entry7() void { | |
| 38 | const slice: [:1]const u16 = &.{ 1, 2 }; | |
| 39 | bar(slice); | |
| 40 | } | |
| 41 | ||
| 42 | export fn entry8() void { | |
| 43 | const slice: []const u16 = &.{ 1, 2 }; | |
| 44 | bar(slice); | |
| 45 | } | |
| 46 | ||
| 47 | fn 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 | 20 | |
| 21 | 21 | // error |
| 22 | 22 | // |
| 23 | // :13:15: error: duplicate switch value | |
| 23 | // :13:15: error: duplicate switch value '.Two' | |
| 24 | 24 | // :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 | 21 | |
| 22 | 22 | // error |
| 23 | 23 | // |
| 24 | // :13:15: error: duplicate switch value | |
| 24 | // :13:15: error: duplicate switch value '.Two' | |
| 25 | 25 | // :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 | 25 | |
| 26 | 26 | // error |
| 27 | 27 | // |
| 28 | // :8:9: error: duplicate switch value | |
| 28 | // :8:9: error: duplicate switch value 'error.Foo' | |
| 29 | 29 | // :5:9: note: previous value here |
| 30 | // :16:9: error: duplicate switch value | |
| 30 | // :16:9: error: duplicate switch value 'error.Foo' | |
| 31 | 31 | // :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 | 27 | |
| 28 | 28 | // error |
| 29 | 29 | // |
| 30 | // :8:9: error: duplicate switch value | |
| 30 | // :8:9: error: duplicate switch value 'error.Foo' | |
| 31 | 31 | // :5:9: note: previous value here |
| 32 | // :17:9: error: duplicate switch value | |
| 32 | // :17:9: error: duplicate switch value 'error.Foo' | |
| 33 | 33 | // :14:9: note: previous value here |
test/cases/compile_errors/switch_expression-duplicate_or_overlapping_integer_value.zig deleted-16| ... | ... | @@ -1,16 +0,0 @@ |
| 1 | fn 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 | } | |
| 9 | export 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 | 13 | |
| 14 | 14 | // error |
| 15 | 15 | // |
| 16 | // :6:9: error: duplicate switch value | |
| 16 | // :6:9: error: duplicate switch value 'u32' | |
| 17 | 17 | // :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 | 17 | |
| 18 | 18 | // error |
| 19 | 19 | // |
| 20 | // :10:9: error: duplicate switch value | |
| 20 | // :10:9: error: duplicate switch value 'tmp.Test' | |
| 21 | 21 | // :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 @@ |
| 1 | const AutoUnion = union { a: u8 }; | |
| 2 | export fn entry1() void { | |
| 3 | switch (@as(AutoUnion, .{ .a = 123 })) { | |
| 4 | else => {}, | |
| 5 | } | |
| 6 | } | |
| 7 | ||
| 8 | const ExternUnion = union { a: u8 }; | |
| 9 | export fn entry2() void { | |
| 10 | switch (@as(ExternUnion, .{ .a = 123 })) { | |
| 11 | else => {}, | |
| 12 | } | |
| 13 | } | |
| 14 | ||
| 15 | const AutoStruct = struct { a: u8 }; | |
| 16 | export fn entry3() void { | |
| 17 | switch (@as(AutoStruct, .{ .a = 123 })) { | |
| 18 | else => {}, | |
| 19 | } | |
| 20 | } | |
| 21 | ||
| 22 | const ExternStruct = extern struct { a: u8 }; | |
| 23 | export fn entry4() void { | |
| 24 | switch (@as(ExternStruct, .{ .a = 123 })) { | |
| 25 | else => {}, | |
| 26 | } | |
| 27 | } | |
| 28 | ||
| 29 | export fn entry5() void { | |
| 30 | switch (@as([]const u16, &.{ 1, 2, 3 })) { | |
| 31 | else => {}, | |
| 32 | } | |
| 33 | } | |
| 34 | ||
| 35 | export fn entry6() void { | |
| 36 | switch (@as([3]u16, .{ 1, 2, 3 })) { | |
| 37 | else => {}, | |
| 38 | } | |
| 39 | } | |
| 40 | ||
| 41 | export fn entry7() void { | |
| 42 | switch (@as(@Vector(3, u16), .{ 1, 2, 3 })) { | |
| 43 | else => {}, | |
| 44 | } | |
| 45 | } | |
| 46 | ||
| 47 | export fn entry8() void { | |
| 48 | switch (@as(?u16, 123)) { | |
| 49 | else => {}, | |
| 50 | } | |
| 51 | } | |
| 52 | ||
| 53 | export fn entry9() void { | |
| 54 | switch (@as(anyerror!u16, 123)) { | |
| 55 | else => {}, | |
| 56 | } | |
| 57 | } | |
| 58 | ||
| 59 | export fn entry10() void { | |
| 60 | switch (@as(f32, 123)) { | |
| 61 | else => {}, | |
| 62 | } | |
| 63 | } | |
| 64 | ||
| 65 | export fn entry11() void { | |
| 66 | switch (@as(comptime_float, 123)) { | |
| 67 | else => {}, | |
| 68 | } | |
| 69 | } | |
| 70 | ||
| 71 | export fn entry12() void { | |
| 72 | switch (undefined) { | |
| 73 | else => {}, | |
| 74 | } | |
| 75 | } | |
| 76 | ||
| 77 | export 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 @@ |
| 1 | const Auto = struct { | |
| 2 | a: u8, | |
| 3 | }; | |
| 4 | export fn entry1(a: u8) void { | |
| 5 | const s: Auto = .{ .a = a }; | |
| 6 | switch (s) { | |
| 7 | else => {}, | |
| 8 | } | |
| 9 | } | |
| 10 | ||
| 11 | const Extern = extern struct { | |
| 12 | a: u8, | |
| 13 | }; | |
| 14 | export 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 @@ |
| 1 | const E = enum(u8) { | |
| 2 | a, | |
| 3 | b, | |
| 4 | _, | |
| 5 | }; | |
| 6 | const U = union(E) { | |
| 7 | a, | |
| 8 | b, | |
| 9 | }; | |
| 10 | fn foo() U { | |
| 11 | return undefined; | |
| 12 | } | |
| 13 | ||
| 14 | export fn entry1() void { | |
| 15 | const u = foo(); | |
| 16 | switch (u) { | |
| 17 | .a => {}, | |
| 18 | } | |
| 19 | } | |
| 20 | export fn entry2() void { | |
| 21 | const u = foo(); | |
| 22 | switch (u) { | |
| 23 | .a => {}, | |
| 24 | .b => {}, | |
| 25 | else => {}, | |
| 26 | } | |
| 27 | } | |
| 28 | export fn entry3() void { | |
| 29 | const u = foo(); | |
| 30 | switch (u) { | |
| 31 | .a => {}, | |
| 32 | .b => {}, | |
| 33 | _ => {}, | |
| 34 | } | |
| 35 | } | |
| 36 | export 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 | 28 | } |
| 29 | 29 | } |
| 30 | 30 | |
| 31 | export fn entry5(x: u8) void { | |
| 32 | switch (x) { | |
| 33 | 0...255 => {}, | |
| 34 | 4...120 => {}, | |
| 35 | } | |
| 36 | } | |
| 37 | ||
| 38 | export fn entry6(x: u8) void { | |
| 39 | switch (x) { | |
| 40 | 0...130 => {}, | |
| 41 | 120...255 => {}, | |
| 42 | } | |
| 43 | } | |
| 44 | ||
| 45 | export fn entry7(x: u8) void { | |
| 46 | switch (x) { | |
| 47 | 2 => {}, | |
| 48 | 0...255 => {}, | |
| 49 | } | |
| 50 | } | |
| 51 | ||
| 31 | 52 | // error |
| 32 | 53 | // |
| 33 | // :4:10: error: duplicate switch value | |
| 34 | // :3:10: note: previous value here | |
| 35 | // :11:10: error: duplicate switch value | |
| 36 | // :10:13: note: previous value here | |
| 37 | // :17:10: error: duplicate switch value | |
| 54 | // :4:10: error: duplicate switch ranges | |
| 55 | // :3:10: note: overlaps with previous range here | |
| 56 | // :3:10: note: ranges overlap from '1' to '2' | |
| 57 | // :11:10: error: duplicate switch value '5' | |
| 58 | // :10:13: note: previous value inside range here | |
| 59 | // :17:10: error: duplicate switch value '5' | |
| 38 | 60 | // :18:9: note: previous value here |
| 39 | // :27:10: error: duplicate switch value | |
| 61 | // :27:10: error: duplicate switch value '6' | |
| 40 | 62 | // :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 | 2 | |
| 3 | 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn { |
| 4 | 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 | 6 | std.process.exit(0); |
| 7 | 7 | } |
| 8 | 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 | 2 | |
| 3 | 3 | pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn { |
| 4 | 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 | 6 | std.process.exit(0); |
| 7 | 7 | } |
| 8 | 8 | std.process.exit(1); |
test/cases/safety/load_uninstantiable_enum.zig created+20| ... | ... | @@ -0,0 +1,20 @@ |
| 1 | const std = @import("std"); | |
| 2 | ||
| 3 | pub 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 | ||
| 11 | const E = enum {}; | |
| 12 | pub 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 @@ |
| 1 | const std = @import("std"); | |
| 2 | ||
| 3 | pub 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 | ||
| 11 | const E = enum {}; | |
| 12 | pub 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 @@ |
| 1 | const std = @import("std"); | |
| 2 | ||
| 3 | pub 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 | ||
| 11 | const U = union { | |
| 12 | foo: struct { a: u8, b: noreturn, }, | |
| 13 | bar: enum {}, | |
| 14 | }; | |
| 15 | pub 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 @@ |
| 1 | const std = @import("std"); | |
| 2 | ||
| 3 | pub 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 | ||
| 11 | const U = union { | |
| 12 | foo: struct { a: u8, b: noreturn, }, | |
| 13 | bar: enum {}, | |
| 14 | }; | |
| 15 | pub 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 | 1 | const std = @import("std"); |
| 2 | const Context = @import("tests.zig").ErrorTracesContext; | |
| 2 | 3 | |
| 3 | pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target.Os.Tag) void { | |
| 4 | pub fn addCases(cases: *Context, params: *const Context.CaseParameters, target: *const std.Target) void { | |
| 4 | 5 | cases.addCase(.{ |
| 6 | .params = params, | |
| 7 | .target = target, | |
| 5 | 8 | .name = "return", |
| 6 | 9 | .source = |
| 7 | 10 | \\pub fn main() !void { |
| ... | ... | @@ -17,6 +20,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. |
| 17 | 20 | }); |
| 18 | 21 | |
| 19 | 22 | cases.addCase(.{ |
| 23 | .params = params, | |
| 24 | .target = target, | |
| 20 | 25 | .name = "try return", |
| 21 | 26 | .source = |
| 22 | 27 | \\fn foo() !void { |
| ... | ... | @@ -44,6 +49,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. |
| 44 | 49 | }, |
| 45 | 50 | }); |
| 46 | 51 | cases.addCase(.{ |
| 52 | .params = params, | |
| 53 | .target = target, | |
| 47 | 54 | .name = "non-error return pops error trace", |
| 48 | 55 | .source = |
| 49 | 56 | \\fn bar() !void { |
| ... | ... | @@ -70,6 +77,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. |
| 70 | 77 | }); |
| 71 | 78 | |
| 72 | 79 | cases.addCase(.{ |
| 80 | .params = params, | |
| 81 | .target = target, | |
| 73 | 82 | .name = "continue in while loop", |
| 74 | 83 | .source = |
| 75 | 84 | \\fn foo() !void { |
| ... | ... | @@ -93,6 +102,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. |
| 93 | 102 | }); |
| 94 | 103 | |
| 95 | 104 | cases.addCase(.{ |
| 105 | .params = params, | |
| 106 | .target = target, | |
| 96 | 107 | .name = "for loop pops error return trace", |
| 97 | 108 | .source = |
| 98 | 109 | \\fn foo() !void { return error.FooError; } |
| ... | ... | @@ -123,6 +134,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. |
| 123 | 134 | }); |
| 124 | 135 | |
| 125 | 136 | cases.addCase(.{ |
| 137 | .params = params, | |
| 138 | .target = target, | |
| 126 | 139 | .name = "implicit continue in for loop pops stale error return trace", |
| 127 | 140 | .source = |
| 128 | 141 | \\fn foo() !void { return error.FooError; } |
| ... | ... | @@ -154,6 +167,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. |
| 154 | 167 | }); |
| 155 | 168 | |
| 156 | 169 | cases.addCase(.{ |
| 170 | .params = params, | |
| 171 | .target = target, | |
| 157 | 172 | .name = "while loop pops error return trace", |
| 158 | 173 | .source = |
| 159 | 174 | \\fn foo() !void { return error.FooError; } |
| ... | ... | @@ -186,6 +201,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. |
| 186 | 201 | }); |
| 187 | 202 | |
| 188 | 203 | cases.addCase(.{ |
| 204 | .params = params, | |
| 205 | .target = target, | |
| 189 | 206 | .name = "implicit continue in while loop pops stale error return trace", |
| 190 | 207 | .source = |
| 191 | 208 | \\fn foo() !void { return error.FooError; } |
| ... | ... | @@ -219,6 +236,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. |
| 219 | 236 | }); |
| 220 | 237 | |
| 221 | 238 | cases.addCase(.{ |
| 239 | .params = params, | |
| 240 | .target = target, | |
| 222 | 241 | .name = "try return + handled catch/if-else", |
| 223 | 242 | .source = |
| 224 | 243 | \\fn foo() !void { |
| ... | ... | @@ -251,6 +270,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. |
| 251 | 270 | }); |
| 252 | 271 | |
| 253 | 272 | cases.addCase(.{ |
| 273 | .params = params, | |
| 274 | .target = target, | |
| 254 | 275 | .name = "break from inline loop pops error return trace", |
| 255 | 276 | .source = |
| 256 | 277 | \\fn foo() !void { return error.FooBar; } |
| ... | ... | @@ -276,6 +297,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. |
| 276 | 297 | }); |
| 277 | 298 | |
| 278 | 299 | cases.addCase(.{ |
| 300 | .params = params, | |
| 301 | .target = target, | |
| 279 | 302 | .name = "catch and re-throw error", |
| 280 | 303 | .source = |
| 281 | 304 | \\fn foo() !void { |
| ... | ... | @@ -304,6 +327,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. |
| 304 | 327 | }); |
| 305 | 328 | |
| 306 | 329 | cases.addCase(.{ |
| 330 | .params = params, | |
| 331 | .target = target, | |
| 307 | 332 | .name = "errors stored in var do not contribute to error trace", |
| 308 | 333 | .source = |
| 309 | 334 | \\fn foo() !void { |
| ... | ... | @@ -328,6 +353,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. |
| 328 | 353 | }); |
| 329 | 354 | |
| 330 | 355 | cases.addCase(.{ |
| 356 | .params = params, | |
| 357 | .target = target, | |
| 331 | 358 | .name = "error stored in const has trace preserved for duration of block", |
| 332 | 359 | .source = |
| 333 | 360 | \\fn foo() !void { return error.TheSkyIsFalling; } |
| ... | ... | @@ -376,6 +403,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. |
| 376 | 403 | }); |
| 377 | 404 | |
| 378 | 405 | cases.addCase(.{ |
| 406 | .params = params, | |
| 407 | .target = target, | |
| 379 | 408 | .name = "error passed to function has its trace preserved for duration of the call", |
| 380 | 409 | .source = |
| 381 | 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 | 447 | }); |
| 419 | 448 | |
| 420 | 449 | cases.addCase(.{ |
| 450 | .params = params, | |
| 451 | .target = target, | |
| 421 | 452 | .name = "try return from within catch", |
| 422 | 453 | .source = |
| 423 | 454 | \\fn foo() !void { |
| ... | ... | @@ -455,6 +486,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. |
| 455 | 486 | }); |
| 456 | 487 | |
| 457 | 488 | cases.addCase(.{ |
| 489 | .params = params, | |
| 490 | .target = target, | |
| 458 | 491 | .name = "try return from within if-else", |
| 459 | 492 | .source = |
| 460 | 493 | \\fn foo() !void { |
| ... | ... | @@ -492,6 +525,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. |
| 492 | 525 | }); |
| 493 | 526 | |
| 494 | 527 | cases.addCase(.{ |
| 528 | .params = params, | |
| 529 | .target = target, | |
| 495 | 530 | .name = "try try return return", |
| 496 | 531 | .source = |
| 497 | 532 | \\fn foo() !void { |
| ... | ... | @@ -534,6 +569,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. |
| 534 | 569 | }); |
| 535 | 570 | |
| 536 | 571 | cases.addCase(.{ |
| 572 | .params = params, | |
| 573 | .target = target, | |
| 537 | 574 | .name = "error union switch with call operand", |
| 538 | 575 | .source = |
| 539 | 576 | \\pub fn main() !void { |
| ... | ... | @@ -579,6 +616,8 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. |
| 579 | 616 | }); |
| 580 | 617 | |
| 581 | 618 | cases.addCase(.{ |
| 619 | .params = params, | |
| 620 | .target = target, | |
| 582 | 621 | .name = "trace through inline call", |
| 583 | 622 | // The main function has two inline calls to ensure |
| 584 | 623 | // that inlinees in PDBs are properly deduplicated. |
| ... | ... | @@ -595,7 +634,7 @@ pub fn addCases(cases: *@import("tests.zig").ErrorTracesContext, os: std.Target. |
| 595 | 634 | \\} |
| 596 | 635 | , |
| 597 | 636 | .expect_error = "ThisIsSoSad", |
| 598 | .expect_trace = switch (os) { | |
| 637 | .expect_trace = switch (target.os.tag) { | |
| 599 | 638 | // LLVM doesn't emit column info in the binary annotations for inlinee callees in PDBs, |
| 600 | 639 | // so our expected result is slightly different for Windows than on other operating |
| 601 | 640 | // systems. |
test/incremental/change_panic_handler_explicit+6| ... | ... | @@ -23,6 +23,7 @@ pub const panic = struct { |
| 23 | 23 | pub const castToNull = no_panic.castToNull; |
| 24 | 24 | pub const incorrectAlignment = no_panic.incorrectAlignment; |
| 25 | 25 | pub const invalidErrorCode = no_panic.invalidErrorCode; |
| 26 | pub const unexpectedErrorCode = no_panic.unexpectedErrorCode; | |
| 26 | 27 | pub const integerOutOfBounds = no_panic.integerOutOfBounds; |
| 27 | 28 | pub const shlOverflow = no_panic.shlOverflow; |
| 28 | 29 | pub const shrOverflow = no_panic.shrOverflow; |
| ... | ... | @@ -36,6 +37,7 @@ pub const panic = struct { |
| 36 | 37 | pub const copyLenMismatch = no_panic.copyLenMismatch; |
| 37 | 38 | pub const memcpyAlias = no_panic.memcpyAlias; |
| 38 | 39 | pub const noreturnReturned = no_panic.noreturnReturned; |
| 40 | pub const loadUninstantiableType = no_panic.loadUninstantiableType; | |
| 39 | 41 | }; |
| 40 | 42 | fn myPanic(msg: []const u8, _: ?usize) noreturn { |
| 41 | 43 | var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); |
| ... | ... | @@ -71,6 +73,7 @@ pub const panic = struct { |
| 71 | 73 | pub const castToNull = no_panic.castToNull; |
| 72 | 74 | pub const incorrectAlignment = no_panic.incorrectAlignment; |
| 73 | 75 | pub const invalidErrorCode = no_panic.invalidErrorCode; |
| 76 | pub const unexpectedErrorCode = no_panic.unexpectedErrorCode; | |
| 74 | 77 | pub const integerOutOfBounds = no_panic.integerOutOfBounds; |
| 75 | 78 | pub const shlOverflow = no_panic.shlOverflow; |
| 76 | 79 | pub const shrOverflow = no_panic.shrOverflow; |
| ... | ... | @@ -84,6 +87,7 @@ pub const panic = struct { |
| 84 | 87 | pub const copyLenMismatch = no_panic.copyLenMismatch; |
| 85 | 88 | pub const memcpyAlias = no_panic.memcpyAlias; |
| 86 | 89 | pub const noreturnReturned = no_panic.noreturnReturned; |
| 90 | pub const loadUninstantiableType = no_panic.loadUninstantiableType; | |
| 87 | 91 | }; |
| 88 | 92 | fn myPanic(msg: []const u8, _: ?usize) noreturn { |
| 89 | 93 | var stdout_writer = std.Io.File.stdout().writerStreaming(io, &.{}); |
| ... | ... | @@ -119,6 +123,7 @@ pub const panic = struct { |
| 119 | 123 | pub const castToNull = no_panic.castToNull; |
| 120 | 124 | pub const incorrectAlignment = no_panic.incorrectAlignment; |
| 121 | 125 | pub const invalidErrorCode = no_panic.invalidErrorCode; |
| 126 | pub const unexpectedErrorCode = no_panic.unexpectedErrorCode; | |
| 122 | 127 | pub const integerOutOfBounds = no_panic.integerOutOfBounds; |
| 123 | 128 | pub const shlOverflow = no_panic.shlOverflow; |
| 124 | 129 | pub const shrOverflow = no_panic.shrOverflow; |
| ... | ... | @@ -132,6 +137,7 @@ pub const panic = struct { |
| 132 | 137 | pub const copyLenMismatch = no_panic.copyLenMismatch; |
| 133 | 138 | pub const memcpyAlias = no_panic.memcpyAlias; |
| 134 | 139 | pub const noreturnReturned = no_panic.noreturnReturned; |
| 140 | pub const loadUninstantiableType = no_panic.loadUninstantiableType; | |
| 135 | 141 | }; |
| 136 | 142 | fn myPanicNew(msg: []const u8, _: ?usize) noreturn { |
| 137 | 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. | |
| 5 | const Foo = struct { x: u8 }; | |
| 6 | pub 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 | } | |
| 10 | fn bar(comptime x: u8) @This().Foo { | |
| 11 | return .{ .x = x }; | |
| 12 | } | |
| 13 | const 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. | |
| 20 | const Foo = struct { x: u8 }; | |
| 21 | pub 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 | } | |
| 25 | fn bar(comptime x: u8) @This().FooAlias { | |
| 26 | return .{ .x = x }; | |
| 27 | } | |
| 28 | const 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. | |
| 36 | const Foo = struct { x: u8 }; | |
| 37 | const FooAlias = Foo; | |
| 38 | pub 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 | } | |
| 42 | fn bar(comptime x: u8) @This().FooAlias { | |
| 43 | return .{ .x = x }; | |
| 44 | } | |
| 45 | const 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 | 116 | "null_pointer_is_valid", |
| 117 | 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 | } |
| 120 | 140 | |
| 121 | 141 | const std = @import("std"); |
test/llvm_targets.zig+2-2| ... | ... | @@ -106,9 +106,9 @@ const targets = [_]std.Target.Query{ |
| 106 | 106 | .{ .cpu_arch = .lanai, .os_tag = .freestanding, .abi = .none }, |
| 107 | 107 | |
| 108 | 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 | 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 | 112 | // .{ .cpu_arch = .loongarch32, .os_tag = .linux, .abi = .musl }, |
| 113 | 113 | // .{ .cpu_arch = .loongarch32, .os_tag = .linux, .abi = .muslf32 }, |
| 114 | 114 | // .{ .cpu_arch = .loongarch32, .os_tag = .linux, .abi = .muslsf }, |
test/src/Cases.zig+2-2| ... | ... | @@ -491,7 +491,7 @@ pub fn lowerToBuildSteps( |
| 491 | 491 | |
| 492 | 492 | for (self.cases.items) |case| { |
| 493 | 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 | 495 | } else if (options.test_filters.len > 0) continue; |
| 496 | 496 | |
| 497 | 497 | if (case.case.? == .Error and options.skip_compile_errors) continue; |
| ... | ... | @@ -524,7 +524,7 @@ pub fn lowerToBuildSteps( |
| 524 | 524 | |
| 525 | 525 | if (options.test_target_filters.len > 0) { |
| 526 | 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 | 528 | } else continue; |
| 529 | 529 | } |
| 530 | 530 |
test/src/Debugger.zig+2-2| ... | ... | @@ -2384,13 +2384,13 @@ fn addTest( |
| 2384 | 2384 | ) void { |
| 2385 | 2385 | if (db.options.test_filters.len > 0) { |
| 2386 | 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 | 2388 | } else return; |
| 2389 | 2389 | } |
| 2390 | 2390 | if (db.options.test_target_filters.len > 0) { |
| 2391 | 2391 | const triple_txt = target.resolved.query.zigTriple(db.b.allocator) catch @panic("OOM"); |
| 2392 | 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 | 2394 | } else return; |
| 2395 | 2395 | } |
| 2396 | 2396 | const files_wf = db.b.addWriteFiles(); |
test/src/ErrorTrace.zig+120-53| ... | ... | @@ -1,11 +1,81 @@ |
| 1 | const ErrorTrace = @This(); | |
| 2 | ||
| 3 | const builtin = @import("builtin"); | |
| 4 | ||
| 5 | const std = @import("std"); | |
| 6 | const Step = std.Build.Step; | |
| 7 | const OptimizeMode = std.lang.Optimize; | |
| 8 | const mem = std.mem; | |
| 9 | ||
| 10 | const error_traces_cases = @import("../error_traces.zig"); | |
| 11 | ||
| 1 | 12 | b: *std.Build, |
| 2 | 13 | step: *Step, |
| 3 | 14 | test_filters: []const []const u8, |
| 4 | targets: []const std.Build.ResolvedTarget, | |
| 15 | skip_non_native: bool, | |
| 5 | 16 | optimize_modes: []const OptimizeMode, |
| 6 | 17 | convert_exe: *std.Build.Step.Compile, |
| 7 | 18 | |
| 19 | pub const CaseParameters = @import("StackTrace.zig").CaseParameters; | |
| 20 | ||
| 21 | const 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 | ||
| 8 | 76 | pub const Case = struct { |
| 77 | params: *const CaseParameters, | |
| 78 | target: *const std.Target, | |
| 9 | 79 | name: []const u8, |
| 10 | 80 | source: []const u8, |
| 11 | 81 | expect_error: []const u8, |
| ... | ... | @@ -22,50 +92,47 @@ pub const Case = struct { |
| 22 | 92 | pub const Backend = enum { llvm, selfhosted }; |
| 23 | 93 | }; |
| 24 | 94 | |
| 25 | pub fn addCase(self: *ErrorTrace, case: Case) void { | |
| 26 | for (self.targets) |*target| { | |
| 27 | const triple: ?[]const u8 = if (target.query.isNative()) null else t: { | |
| 28 | break :t target.query.zigTriple(self.b.graph.arena) catch @panic("OOM"); | |
| 29 | }; | |
| 30 | for (self.optimize_modes) |optimize| { | |
| 31 | self.addCaseConfig(case, target, triple, optimize, .llvm); | |
| 32 | } | |
| 33 | if (shouldTestNonLlvm(&target.result)) { | |
| 34 | for (self.optimize_modes) |optimize| { | |
| 35 | self.addCaseConfig(case, target, triple, optimize, .selfhosted); | |
| 36 | } | |
| 95 | pub fn addCases(self: *ErrorTrace) void { | |
| 96 | const b = self.b; | |
| 97 | ||
| 98 | for (&param_sets) |*params| { | |
| 99 | const resolved_target = b.resolveTargetQuery(params.target); | |
| 100 | ||
| 101 | if (self.skip_non_native and !resolved_target.query.isNative()) continue; | |
| 102 | ||
| 103 | // To avoid redundant testing, skip cross-compilation targets matching the host. | |
| 104 | if (resolved_target.result.os.tag == builtin.target.os.tag and | |
| 105 | resolved_target.result.cpu.arch == builtin.target.cpu.arch) | |
| 106 | { | |
| 107 | continue; | |
| 37 | 108 | } |
| 38 | } | |
| 39 | } | |
| 40 | 109 | |
| 41 | fn shouldTestNonLlvm(target: *const std.Target) bool { | |
| 42 | if (comptime builtin.cpu.arch.endian() == .big) return false; // https://github.com/ziglang/zig/issues/25961 | |
| 43 | return switch (target.cpu.arch) { | |
| 44 | .x86_64 => switch (target.ofmt) { | |
| 45 | .elf => !target.os.tag.isBSD() and target.os.tag != .illumos, | |
| 46 | else => false, | |
| 47 | }, | |
| 48 | else => false, | |
| 49 | }; | |
| 110 | for (self.optimize_modes) |optimize| { | |
| 111 | if (optimize == params.optimize) break; | |
| 112 | } else return; | |
| 113 | ||
| 114 | error_traces_cases.addCases(self, params, &resolved_target.result); | |
| 115 | } | |
| 50 | 116 | } |
| 51 | 117 | |
| 52 | fn addCaseConfig( | |
| 53 | self: *ErrorTrace, | |
| 54 | case: Case, | |
| 55 | target: *const std.Build.ResolvedTarget, | |
| 56 | triple: ?[]const u8, | |
| 57 | optimize: OptimizeMode, | |
| 58 | backend: Case.Backend, | |
| 59 | ) void { | |
| 118 | /// Called from test/error_traces.zig | |
| 119 | pub fn addCase(self: *ErrorTrace, case: Case) void { | |
| 60 | 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 | }; | |
| 61 | 128 | |
| 62 | 129 | const error_tracing: bool = tracing: { |
| 63 | if (optimize == .Debug) break :tracing true; | |
| 64 | if (backend != .llvm) break :tracing true; | |
| 65 | if (optimize == .ReleaseSmall) break :tracing false; | |
| 130 | if (params.optimize == .debug) break :tracing true; | |
| 131 | if (params.use_llvm == false) break :tracing true; | |
| 132 | if (params.optimize == .small) break :tracing false; | |
| 66 | 133 | for (case.disable_trace_optimized) |disable| { |
| 67 | 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 | 136 | // This particular configuration cannot do error tracing in optimized LLVM builds. |
| 70 | 137 | break :tracing false; |
| 71 | 138 | } |
| ... | ... | @@ -73,16 +140,23 @@ fn addCaseConfig( |
| 73 | 140 | break :tracing true; |
| 74 | 141 | }; |
| 75 | 142 | |
| 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 | 151 | case.name, |
| 78 | 152 | triple orelse "", |
| 79 | 153 | if (triple != null) " " else "", |
| 80 | @tagName(optimize), | |
| 81 | @tagName(backend), | |
| 154 | params.optimize, | |
| 155 | backend_string, | |
| 82 | 156 | }); |
| 83 | 157 | if (self.test_filters.len > 0) { |
| 84 | 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 | 160 | } else return; |
| 87 | 161 | } |
| 88 | 162 | |
| ... | ... | @@ -92,19 +166,18 @@ fn addCaseConfig( |
| 92 | 166 | .name = "test", |
| 93 | 167 | .root_module = b.createModule(.{ |
| 94 | 168 | .root_source_file = source_zig, |
| 95 | .optimize = optimize, | |
| 96 | .target = target.*, | |
| 169 | .optimize = params.optimize, | |
| 170 | .target = .{ .result = target.*, .query = target_query }, | |
| 97 | 171 | .error_tracing = error_tracing, |
| 98 | 172 | .strip = false, |
| 99 | 173 | }), |
| 100 | .use_llvm = switch (backend) { | |
| 101 | .llvm => true, | |
| 102 | .selfhosted => false, | |
| 103 | }, | |
| 174 | .use_llvm = params.use_llvm, | |
| 175 | .use_lld = params.use_lld, | |
| 104 | 176 | }); |
| 105 | 177 | exe.bundle_ubsan_rt = false; |
| 106 | 178 | |
| 107 | 179 | const run = b.addRunArtifact(exe); |
| 180 | run.skip_foreign_checks = true; | |
| 108 | 181 | run.removeEnvironmentVariable("CLICOLOR_FORCE"); |
| 109 | 182 | run.setEnvironmentVariable("NO_COLOR", "1"); |
| 110 | 183 | run.expectExitCode(1); |
| ... | ... | @@ -116,16 +189,10 @@ fn addCaseConfig( |
| 116 | 189 | }; |
| 117 | 190 | |
| 118 | 191 | const check_run = b.addRunArtifact(self.convert_exe); |
| 192 | check_run.skip_foreign_checks = true; | |
| 119 | 193 | check_run.setName(annotated_case_name); |
| 120 | 194 | check_run.addFileArg(run.captureStdErr(.{})); |
| 121 | 195 | check_run.expectStdOutEqual(expected_stderr); |
| 122 | 196 | |
| 123 | 197 | self.step.dependOn(&check_run.step); |
| 124 | 198 | } |
| 125 | ||
| 126 | const ErrorTrace = @This(); | |
| 127 | const std = @import("std"); | |
| 128 | const builtin = @import("builtin"); | |
| 129 | const Step = std.Build.Step; | |
| 130 | const OptimizeMode = std.builtin.OptimizeMode; | |
| 131 | const 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 | 49 | if (libc.options.test_target_filters.len > 0) { |
| 50 | 50 | const triple_txt = target.query.zigTriple(libc.b.allocator) catch @panic("OOM"); |
| 51 | 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 | 53 | } else return; |
| 54 | 54 | } |
| 55 | 55 | |
| ... | ... | @@ -82,7 +82,7 @@ pub fn addTarget(libc: *const Libc, target: std.Build.ResolvedTarget) void { |
| 82 | 82 | |
| 83 | 83 | const annotated_case_name = libc.b.fmt("run libc-test {s} ({t})", .{ test_case.name, optimize }); |
| 84 | 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 | 86 | } else if (libc.options.test_filters.len > 0) continue; |
| 87 | 87 | |
| 88 | 88 | const mod = libc.b.createModule(.{ |
test/src/Link.zig+1-1| ... | ... | @@ -8,7 +8,7 @@ use_lld: bool, |
| 8 | 8 | link_libc: bool, |
| 9 | 9 | test_filters: []const []const u8, |
| 10 | 10 | update_step: ?*Step.UpdateSourceFiles, |
| 11 | updated_snapshots: std.StringArrayHashMapUnmanaged(void), | |
| 11 | updated_snapshots: std.array_hash_map.String(void), | |
| 12 | 12 | max_rss: usize, |
| 13 | 13 | |
| 14 | 14 | pub 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 | 77 | if (self.options.test_target_filters.len > 0) { |
| 78 | 78 | const triple_txt = target.query.zigTriple(self.b.allocator) catch @panic("OOM"); |
| 79 | 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 | 81 | } else return; |
| 82 | 82 | } |
| 83 | 83 | |
| 84 | 84 | const name = std.fmt.allocPrint(self.b.allocator, "check llvm-ir {s}", .{case.name}) catch @panic("OOM"); |
| 85 | 85 | if (self.options.test_filters.len > 0) { |
| 86 | 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 | 88 | } else return; |
| 89 | 89 | } |
| 90 | 90 |
test/src/RunTranslatedC.zig+1-1| ... | ... | @@ -68,7 +68,7 @@ pub fn addCase(self: *RunTranslatedCContext, case: *const TestCase) void { |
| 68 | 68 | |
| 69 | 69 | const annotated_case_name = fmt.allocPrint(self.b.allocator, "run-translated-c {s}", .{case.name}) catch unreachable; |
| 70 | 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 | 72 | } else if (self.test_filters.len > 0) return; |
| 73 | 73 | |
| 74 | 74 | const write_src = b.addWriteFiles(); |
test/src/StackTrace.zig+156-93| ... | ... | @@ -1,10 +1,91 @@ |
| 1 | const StackTrace = @This(); | |
| 2 | ||
| 3 | const builtin = @import("builtin"); | |
| 4 | ||
| 5 | const std = @import("std"); | |
| 6 | const Step = std.Build.Step; | |
| 7 | const OptimizeMode = std.lang.Optimize; | |
| 8 | const mem = std.mem; | |
| 9 | ||
| 10 | const stack_traces_cases = @import("../stack_traces.zig"); | |
| 11 | ||
| 1 | 12 | b: *std.Build, |
| 2 | 13 | step: *Step, |
| 3 | 14 | test_filters: []const []const u8, |
| 4 | targets: []const std.Build.ResolvedTarget, | |
| 15 | skip_non_native: bool, | |
| 5 | 16 | convert_exe: *std.Build.Step.Compile, |
| 6 | 17 | |
| 18 | pub 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 | ||
| 31 | const 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 | ||
| 7 | 86 | const Config = struct { |
| 87 | params: *const CaseParameters, | |
| 88 | target: *const std.Target, | |
| 8 | 89 | name: []const u8, |
| 9 | 90 | source: []const u8, |
| 10 | 91 | /// Whether this test case expects to have unwind tables / frame pointers. |
| ... | ... | @@ -26,42 +107,37 @@ const Config = struct { |
| 26 | 107 | expect_strip: []const u8, |
| 27 | 108 | }; |
| 28 | 109 | |
| 29 | pub fn addCase(self: *StackTrace, config: Config) void { | |
| 30 | for (self.targets) |*target| { | |
| 31 | addCaseTarget( | |
| 32 | self, | |
| 33 | config, | |
| 34 | target, | |
| 35 | if (target.query.isNative()) null else t: { | |
| 36 | break :t target.query.zigTriple(self.b.graph.arena) catch @panic("OOM"); | |
| 37 | }, | |
| 38 | ); | |
| 110 | pub fn addCases(self: *StackTrace) void { | |
| 111 | const b = self.b; | |
| 112 | ||
| 113 | for (&param_sets) |*params| { | |
| 114 | const resolved_target = b.resolveTargetQuery(params.target); | |
| 115 | ||
| 116 | if (self.skip_non_native and !resolved_target.query.isNative()) continue; | |
| 117 | ||
| 118 | // To avoid redundant testing, skip cross-compilation targets matching the host. | |
| 119 | if (resolved_target.result.os.tag == builtin.target.os.tag and | |
| 120 | resolved_target.result.cpu.arch == builtin.target.cpu.arch) | |
| 121 | { | |
| 122 | continue; | |
| 123 | } | |
| 124 | ||
| 125 | stack_traces_cases.addCases(self, params, &resolved_target.result); | |
| 39 | 126 | } |
| 40 | 127 | } |
| 41 | fn addCaseTarget( | |
| 42 | self: *StackTrace, | |
| 43 | config: Config, | |
| 44 | target: *const std.Build.ResolvedTarget, | |
| 45 | triple: ?[]const u8, | |
| 46 | ) void { | |
| 47 | const both_backends = b: { | |
| 48 | if (comptime builtin.cpu.arch.endian() == .big) break :b false; // https://github.com/ziglang/zig/issues/25961 | |
| 49 | break :b switch (target.result.cpu.arch) { | |
| 50 | .x86_64 => switch (target.result.ofmt) { | |
| 51 | .elf => !target.result.os.tag.isBSD() and target.result.os.tag != .illumos, | |
| 52 | else => false, | |
| 53 | }, | |
| 54 | else => false, | |
| 55 | }; | |
| 56 | }; | |
| 57 | const both_pie = switch (target.result.os.tag) { | |
| 58 | .fuchsia => false, | |
| 59 | else => true, | |
| 128 | ||
| 129 | /// Called from test/stack_traces.zig | |
| 130 | pub fn addCase(self: *StackTrace, config: Config) void { | |
| 131 | const params = config.params; | |
| 132 | const target = config.target; | |
| 133 | const target_query = config.params.target; | |
| 134 | ||
| 135 | const triple: ?[]const u8 = if (target_query.isNative()) null else t: { | |
| 136 | break :t target_query.zigTriple(self.b.graph.arena) catch @panic("OOM"); | |
| 60 | 137 | }; |
| 61 | const both_libc = !std.os.targetRequiresLibC(&target.result); | |
| 62 | 138 | |
| 63 | 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 | 141 | .alpha, |
| 66 | 142 | .csky, |
| 67 | 143 | .microblaze, |
| ... | ... | @@ -83,20 +159,15 @@ fn addCaseTarget( |
| 83 | 159 | .sparc, |
| 84 | 160 | .sparc64, |
| 85 | 161 | => .ideal, |
| 86 | .aarch64 => if (target.result.os.tag.isDarwin()) .safe else .unsafe, | |
| 162 | .aarch64 => if (target.os.tag.isDarwin()) .safe else .unsafe, | |
| 87 | 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 | 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 | 168 | else => true, |
| 93 | 169 | }; |
| 94 | 170 | |
| 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 | 171 | const UnwindInfo = packed struct(u2) { |
| 101 | 172 | tables: bool, |
| 102 | 173 | fp: bool, |
| ... | ... | @@ -126,43 +197,33 @@ fn addCaseTarget( |
| 126 | 197 | }, |
| 127 | 198 | }; |
| 128 | 199 | |
| 129 | for (use_llvm_vals) |use_llvm| { | |
| 130 | for (pie_vals) |pie| { | |
| 131 | for (link_libc_vals) |link_libc| { | |
| 132 | for (strip_debug_vals) |strip_debug| { | |
| 133 | for (unwind_info_vals) |unwind_info| { | |
| 134 | if (unwind_info.tables and !supports_unwind_tables) continue; | |
| 135 | self.addCaseInstance( | |
| 136 | target, | |
| 137 | triple, | |
| 138 | config.name, | |
| 139 | config.source, | |
| 140 | use_llvm, | |
| 141 | pie, | |
| 142 | link_libc, | |
| 143 | strip_debug, | |
| 144 | !unwind_info.tables and supports_unwind_tables, | |
| 145 | !unwind_info.fp, | |
| 146 | config.expect_panic, | |
| 147 | if (strip_debug) config.expect_strip else config.expect, | |
| 148 | ); | |
| 149 | } | |
| 150 | } | |
| 151 | } | |
| 152 | } | |
| 200 | for (unwind_info_vals) |unwind_info| { | |
| 201 | if (unwind_info.tables and !supports_unwind_tables) continue; | |
| 202 | const strip = params.strip orelse switch (params.optimize) { | |
| 203 | .debug, .fast, .safe => false, | |
| 204 | .small => true, | |
| 205 | }; | |
| 206 | self.addCaseInstance( | |
| 207 | .{ .result = target.*, .query = target_query }, | |
| 208 | triple, | |
| 209 | config.name, | |
| 210 | config.source, | |
| 211 | params, | |
| 212 | !unwind_info.tables and supports_unwind_tables, | |
| 213 | !unwind_info.fp, | |
| 214 | config.expect_panic, | |
| 215 | if (strip) config.expect_strip else config.expect, | |
| 216 | ); | |
| 153 | 217 | } |
| 154 | 218 | } |
| 155 | 219 | |
| 156 | 220 | fn addCaseInstance( |
| 157 | 221 | self: *StackTrace, |
| 158 | target: *const std.Build.ResolvedTarget, | |
| 222 | resolved_target: std.Build.ResolvedTarget, | |
| 159 | 223 | triple: ?[]const u8, |
| 160 | 224 | name: []const u8, |
| 161 | 225 | source: []const u8, |
| 162 | use_llvm: bool, | |
| 163 | pie: ?bool, | |
| 164 | link_libc: ?bool, | |
| 165 | strip_debug: bool, | |
| 226 | params: *const CaseParameters, | |
| 166 | 227 | strip_unwind: bool, |
| 167 | 228 | omit_frame_pointer: bool, |
| 168 | 229 | expect_panic: bool, |
| ... | ... | @@ -170,13 +231,6 @@ fn addCaseInstance( |
| 170 | 231 | ) void { |
| 171 | 232 | const b = self.b; |
| 172 | 233 | |
| 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 | 234 | if (strip_unwind) { |
| 181 | 235 | // To enable this coverage, `std.Build.Step.ObjCopy` needs to be un-regressed and gain the |
| 182 | 236 | // ability to remove individual sections. `-fno-unwind-tables` is insufficient because it |
| ... | ... | @@ -187,20 +241,34 @@ fn addCaseInstance( |
| 187 | 241 | return; |
| 188 | 242 | } |
| 189 | 243 | |
| 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 | 258 | const annotated_case_name = b.fmt("check {s} ({s}{s}{s}{s}{s}{s}{s}{s})", .{ |
| 191 | 259 | name, |
| 192 | 260 | triple orelse "", |
| 193 | 261 | if (triple != null) " " else "", |
| 194 | if (use_llvm) "llvm" else "selfhosted", | |
| 195 | if (pie == true) " pie" else "", | |
| 196 | if (link_libc == true) " libc" else "", | |
| 197 | if (strip_debug) " strip" else "", | |
| 262 | backend_string, | |
| 263 | if (params.pie == true) " pie" else "", | |
| 264 | if (params.link_libc == true) " libc" else "", | |
| 265 | strip_string, | |
| 198 | 266 | if (strip_unwind) " no_unwind" else "", |
| 199 | 267 | if (omit_frame_pointer) " no_fp" else "", |
| 200 | 268 | }); |
| 201 | 269 | if (self.test_filters.len > 0) { |
| 202 | 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 | 272 | } else return; |
| 205 | 273 | } |
| 206 | 274 | |
| ... | ... | @@ -211,24 +279,26 @@ fn addCaseInstance( |
| 211 | 279 | .root_module = b.createModule(.{ |
| 212 | 280 | .root_source_file = source_zig, |
| 213 | 281 | .optimize = .Debug, |
| 214 | .target = target.*, | |
| 282 | .target = resolved_target, | |
| 215 | 283 | .omit_frame_pointer = omit_frame_pointer, |
| 216 | .link_libc = link_libc, | |
| 284 | .link_libc = params.link_libc, | |
| 217 | 285 | .unwind_tables = if (strip_unwind) .none else null, |
| 218 | 286 | // make panics single-threaded so that they don't include a thread ID |
| 219 | 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 | 293 | exe.bundle_ubsan_rt = false; |
| 225 | 294 | |
| 226 | 295 | const run = b.addRunArtifact(exe); |
| 296 | run.skip_foreign_checks = true; | |
| 227 | 297 | run.removeEnvironmentVariable("CLICOLOR_FORCE"); |
| 228 | 298 | run.setEnvironmentVariable("NO_COLOR", "1"); |
| 229 | 299 | run.addCheck(.{ .expect_term = term: { |
| 230 | 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 | 302 | break :term .{ .signal = @fromBackingInt(@intCast(6)) }; |
| 233 | 303 | } }); |
| 234 | 304 | run.expectStdOutEqual(""); |
| ... | ... | @@ -241,10 +311,3 @@ fn addCaseInstance( |
| 241 | 311 | |
| 242 | 312 | self.step.dependOn(&check_run.step); |
| 243 | 313 | } |
| 244 | ||
| 245 | const StackTrace = @This(); | |
| 246 | const std = @import("std"); | |
| 247 | const builtin = @import("builtin"); | |
| 248 | const Step = std.Build.Step; | |
| 249 | const OptimizeMode = std.builtin.OptimizeMode; | |
| 250 | const mem = std.mem; |
test/src/TranslateC.zig+2-2| ... | ... | @@ -90,7 +90,7 @@ pub fn addCase(self: *TranslateCContext, case: *const TestCase) void { |
| 90 | 90 | const translate_c_cmd = "translate-c"; |
| 91 | 91 | const annotated_case_name = fmt.allocPrint(self.b.allocator, "{s} {s}", .{ translate_c_cmd, case.name }) catch unreachable; |
| 92 | 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 | 94 | } else if (self.test_filters.len > 0) return; |
| 95 | 95 | |
| 96 | 96 | const target = b.resolveTargetQuery(case.target); |
| ... | ... | @@ -99,7 +99,7 @@ pub fn addCase(self: *TranslateCContext, case: *const TestCase) void { |
| 99 | 99 | const triple_txt = target.query.zigTriple(b.allocator) catch @panic("OOM"); |
| 100 | 100 | |
| 101 | 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 | 103 | } else return; |
| 104 | 104 | } |
| 105 | 105 |
test/src/convert-stack-trace.zig+3-3| ... | ... | @@ -52,13 +52,13 @@ pub fn main(init: std.process.Init) !void { |
| 52 | 52 | continue; |
| 53 | 53 | } |
| 54 | 54 | |
| 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 | 56 | try w.writeAll(in_line); |
| 57 | 57 | continue; |
| 58 | 58 | }; |
| 59 | 59 | const src_pos_start = b: { |
| 60 | 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 | 62 | try w.writeAll(in_line); |
| 63 | 63 | continue; |
| 64 | 64 | }; |
| ... | ... | @@ -89,7 +89,7 @@ pub fn main(init: std.process.Init) !void { |
| 89 | 89 | // ...with that first '_' being replaced by its basename. |
| 90 | 90 | |
| 91 | 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 | 93 | const symbol_start = addr_end + " in ".len; |
| 94 | 94 | try w.writeAll(in_line[basename_start..src_pos_end]); |
| 95 | 95 | try w.writeAll(": [address] in "); |
test/stack_traces.zig+24-5| ... | ... | @@ -1,7 +1,10 @@ |
| 1 | 1 | const std = @import("std"); |
| 2 | const Context = @import("tests.zig").StackTracesContext; | |
| 2 | 3 | |
| 3 | pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target.Os.Tag) void { | |
| 4 | pub fn addCases(cases: *Context, params: *const Context.CaseParameters, target: *const std.Target) void { | |
| 4 | 5 | cases.addCase(.{ |
| 6 | .params = params, | |
| 7 | .target = target, | |
| 5 | 8 | .name = "simple panic", |
| 6 | 9 | .source = |
| 7 | 10 | \\pub fn main() void { |
| ... | ... | @@ -33,6 +36,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target. |
| 33 | 36 | }); |
| 34 | 37 | |
| 35 | 38 | cases.addCase(.{ |
| 39 | .params = params, | |
| 40 | .target = target, | |
| 36 | 41 | .name = "simple panic with no unwind strategy", |
| 37 | 42 | .source = |
| 38 | 43 | \\pub fn main() void { |
| ... | ... | @@ -50,6 +55,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target. |
| 50 | 55 | }); |
| 51 | 56 | |
| 52 | 57 | cases.addCase(.{ |
| 58 | .params = params, | |
| 59 | .target = target, | |
| 53 | 60 | .name = "dump current trace", |
| 54 | 61 | .source = |
| 55 | 62 | \\pub fn main() void { |
| ... | ... | @@ -89,6 +96,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target. |
| 89 | 96 | }); |
| 90 | 97 | |
| 91 | 98 | cases.addCase(.{ |
| 99 | .params = params, | |
| 100 | .target = target, | |
| 92 | 101 | .name = "dump current trace with no unwind strategy", |
| 93 | 102 | .source = |
| 94 | 103 | \\pub fn main() void { |
| ... | ... | @@ -114,6 +123,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target. |
| 114 | 123 | }); |
| 115 | 124 | |
| 116 | 125 | cases.addCase(.{ |
| 126 | .params = params, | |
| 127 | .target = target, | |
| 117 | 128 | .name = "dump captured trace", |
| 118 | 129 | .source = |
| 119 | 130 | \\pub fn main() void { |
| ... | ... | @@ -155,6 +166,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target. |
| 155 | 166 | }); |
| 156 | 167 | |
| 157 | 168 | cases.addCase(.{ |
| 169 | .params = params, | |
| 170 | .target = target, | |
| 158 | 171 | .name = "dump captured trace with no unwind strategy", |
| 159 | 172 | .source = |
| 160 | 173 | \\pub fn main() void { |
| ... | ... | @@ -180,6 +193,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target. |
| 180 | 193 | }); |
| 181 | 194 | |
| 182 | 195 | cases.addCase(.{ |
| 196 | .params = params, | |
| 197 | .target = target, | |
| 183 | 198 | .name = "dump captured trace on thread", |
| 184 | 199 | .source = |
| 185 | 200 | \\pub fn main() !void { |
| ... | ... | @@ -225,6 +240,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target. |
| 225 | 240 | }); |
| 226 | 241 | |
| 227 | 242 | cases.addCase(.{ |
| 243 | .params = params, | |
| 244 | .target = target, | |
| 228 | 245 | .name = "simple inline panic", |
| 229 | 246 | // The main function has two inline calls to ensure |
| 230 | 247 | // that inlinees in PDBs are properly deduplicated. |
| ... | ... | @@ -240,7 +257,7 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target. |
| 240 | 257 | , |
| 241 | 258 | .unwind = .any, |
| 242 | 259 | .expect_panic = true, |
| 243 | .expect = switch (os) { | |
| 260 | .expect = switch (target.os.tag) { | |
| 244 | 261 | // LLVM doesn't emit column info in the binary annotations for inlinee callees in PDBs, |
| 245 | 262 | // so the first location has only a row. |
| 246 | 263 | .windows => |
| ... | ... | @@ -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 | 283 | .windows => |
| 267 | 284 | \\panic: oh no |
| 268 | 285 | \\???:?:?: [address] in source.foo |
| ... | ... | @@ -279,6 +296,8 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target. |
| 279 | 296 | |
| 280 | 297 | // Make sure all inline calls are resolved and in the right order! |
| 281 | 298 | cases.addCase(.{ |
| 299 | .params = params, | |
| 300 | .target = target, | |
| 282 | 301 | .name = "nested inline panic", |
| 283 | 302 | .source = |
| 284 | 303 | \\pub fn main() void { |
| ... | ... | @@ -298,7 +317,7 @@ pub fn addCases(cases: *@import("tests.zig").StackTracesContext, os: std.Target. |
| 298 | 317 | .unwind = .any, |
| 299 | 318 | .expect_panic = true, |
| 300 | 319 | // This switch serves a similar purpose as in "inline panic". |
| 301 | .expect = switch (os) { | |
| 320 | .expect = switch (target.os.tag) { | |
| 302 | 321 | .windows => |
| 303 | 322 | \\panic: oh no |
| 304 | 323 | \\source.zig:11: [address] in baz |
| ... | ... | @@ -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 | 345 | .windows => |
| 327 | 346 | \\panic: oh no |
| 328 | 347 | \\???:?:?: [address] in baz |
test/standalone/build.zig+1-1| ... | ... | @@ -31,6 +31,7 @@ pub fn build(b: *std.Build) void { |
| 31 | 31 | const tools_target = b.resolveTargetQuery(.{}); |
| 32 | 32 | for ([_][]const u8{ |
| 33 | 33 | // Alphabetically sorted. No need to build `tools/spirv/grammar.zig`. |
| 34 | "../../tools/bsp.zig", | |
| 34 | 35 | "../../tools/check_mingw.zig", |
| 35 | 36 | "../../tools/dump-cov.zig", |
| 36 | 37 | "../../tools/fetch_them_macos_headers.zig", |
| ... | ... | @@ -39,7 +40,6 @@ pub fn build(b: *std.Build) void { |
| 39 | 40 | "../../tools/gen_parser_oracle.zig", |
| 40 | 41 | "../../tools/gen_spirv_spec.zig", |
| 41 | 42 | "../../tools/gen_stubs.zig", |
| 42 | "../../tools/generate_c_size_and_align_checks.zig", | |
| 43 | 43 | "../../tools/generate_JSONTestSuite.zig", |
| 44 | 44 | "../../tools/generate_linux_syscalls.zig", |
| 45 | 45 | "../../tools/process_headers.zig", |
test/standalone/build.zig.zon-3| ... | ... | @@ -187,9 +187,6 @@ |
| 187 | 187 | .posix = .{ |
| 188 | 188 | .path = "posix", |
| 189 | 189 | }, |
| 190 | .debug_io_color = .{ | |
| 191 | .path = "debug_io_color", | |
| 192 | }, | |
| 193 | 190 | .elf2 = .{ |
| 194 | 191 | .path = "elf2", |
| 195 | 192 | }, |
test/standalone/compiler_rt_panic/main.c+2-2| ... | ... | @@ -1,11 +1,11 @@ |
| 1 | 1 | #include <stddef.h> |
| 2 | 2 | |
| 3 | void* __memset(void* dest, char c, size_t n, size_t dest_n); | |
| 3 | void *__memset_chk(void *dest, int c, size_t n, size_t dest_n); | |
| 4 | 4 | |
| 5 | 5 | char foo[128]; |
| 6 | 6 | |
| 7 | 7 | int main() { |
| 8 | __memset(&foo[0], 0xff, 128, 128); | |
| 8 | __memset_chk(&foo[0], 0xff, 128, 128); | |
| 9 | 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 | 51 | }); |
| 52 | 52 | test_step.dependOn(&check_config_header_autoconf_at.step); |
| 53 | 53 | |
| 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 | 75 | const config_header_blank = b.addConfigHeader( |
| 55 | 76 | .{ |
| 56 | 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 @@ |
| 1 | const std = @import("std"); | |
| 2 | ||
| 3 | pub 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 | ||
| 20 | fn 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 | ||
| 62 | fn 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 @@ |
| 1 | const std = @import("std"); | |
| 2 | ||
| 3 | pub 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 | const none_specified_mod = none_specified.module("dummy"); |
| 12 | 12 | if (!none_specified_mod.resolved_target.?.query.eql(b.graph.host.query)) return error.TestFailed; |
| 13 | 13 | const expected_optimize: std.builtin.OptimizeMode = switch (b.graph.release_mode) { |
| 14 | .off => .Debug, | |
| 14 | .off => .debug, | |
| 15 | 15 | .any => unreachable, |
| 16 | .fast => .ReleaseFast, | |
| 17 | .safe => .ReleaseSafe, | |
| 18 | .small => .ReleaseSmall, | |
| 16 | .fast => .fast, | |
| 17 | .safe => .safe, | |
| 18 | .small => .small, | |
| 19 | 19 | }; |
| 20 | 20 | if (none_specified_mod.optimize.? != expected_optimize) return error.TestFailed; |
| 21 | 21 | |
| ... | ... | @@ -44,7 +44,7 @@ pub fn build(b: *std.Build) !void { |
| 44 | 44 | |
| 45 | 45 | const all_specified = b.dependency("other", .{ |
| 46 | 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 | 48 | .bool = @as(bool, true), |
| 49 | 49 | .int = @as(i64, 123), |
| 50 | 50 | .float = @as(f64, 0.5), |
| ... | ... | @@ -66,11 +66,11 @@ pub fn build(b: *std.Build) !void { |
| 66 | 66 | if (all_specified_mod.resolved_target.?.result.cpu.arch != .x86_64) return error.TestFailed; |
| 67 | 67 | if (all_specified_mod.resolved_target.?.result.os.tag != .windows) return error.TestFailed; |
| 68 | 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; | |
| 70 | 70 | |
| 71 | 71 | const all_specified_optional = b.dependency("other", .{ |
| 72 | 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 | 74 | .bool = @as(?bool, true), |
| 75 | 75 | .int = @as(?i64, 123), |
| 76 | 76 | .float = @as(?f64, 0.5), |
| ... | ... | @@ -92,7 +92,7 @@ pub fn build(b: *std.Build) !void { |
| 92 | 92 | |
| 93 | 93 | const all_specified_literal = b.dependency("other", .{ |
| 94 | 94 | .target = b.resolveTargetQuery(.{ .cpu_arch = .x86_64, .os_tag = .windows, .abi = .gnu }), |
| 95 | .optimize = .ReleaseSafe, | |
| 95 | .optimize = .safe, | |
| 96 | 96 | .bool = true, |
| 97 | 97 | .int = 123, |
| 98 | 98 | .float = 0.5, |
| ... | ... | @@ -130,7 +130,7 @@ pub fn build(b: *std.Build) !void { |
| 130 | 130 | // to the same cached dependency instance. |
| 131 | 131 | const all_specified_alt = b.dependency("other", .{ |
| 132 | 132 | .target = @as(std.Target.Query, .{ .cpu_arch = .x86_64, .os_tag = .windows, .abi = .gnu }), |
| 133 | .optimize = "ReleaseSafe", | |
| 133 | .optimize = "safe", | |
| 134 | 134 | .bool = .true, |
| 135 | 135 | .int = "123", |
| 136 | 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 | 103 | .{ .arch_os_abi = t }, |
| 104 | 104 | ) catch unreachable); |
| 105 | 105 | |
| 106 | if (target.result.cpu.arch.isLoongArch()) continue; // https://github.com/Vexu/arocc/issues/1096 | |
| 107 | ||
| 106 | 108 | const glibc_ver = target.result.os.version_range.linux.glibc; |
| 107 | 109 | |
| 108 | 110 | // 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 | 13 | var optimize_modes_buf: [4]std.builtin.OptimizeMode = undefined; |
| 14 | 14 | var optimize_modes_len: usize = 0; |
| 15 | 15 | if (!skip_debug) { |
| 16 | optimize_modes_buf[optimize_modes_len] = .Debug; | |
| 16 | optimize_modes_buf[optimize_modes_len] = .debug; | |
| 17 | 17 | optimize_modes_len += 1; |
| 18 | 18 | } |
| 19 | 19 | if (!skip_release_safe) { |
| 20 | optimize_modes_buf[optimize_modes_len] = .ReleaseSafe; | |
| 20 | optimize_modes_buf[optimize_modes_len] = .safe; | |
| 21 | 21 | optimize_modes_len += 1; |
| 22 | 22 | } |
| 23 | 23 | if (!skip_release_fast) { |
| 24 | optimize_modes_buf[optimize_modes_len] = .ReleaseFast; | |
| 24 | optimize_modes_buf[optimize_modes_len] = .fast; | |
| 25 | 25 | optimize_modes_len += 1; |
| 26 | 26 | } |
| 27 | 27 | if (!skip_release_small) { |
| 28 | optimize_modes_buf[optimize_modes_len] = .ReleaseSmall; | |
| 28 | optimize_modes_buf[optimize_modes_len] = .small; | |
| 29 | 29 | optimize_modes_len += 1; |
| 30 | 30 | } |
| 31 | 31 | const optimize_modes = optimize_modes_buf[0..optimize_modes_len]; |
| 32 | 32 | |
| 33 | 33 | for (cases) |case| { |
| 34 | 34 | for (optimize_modes) |optimize| { |
| 35 | if (!case.all_modes and optimize != .Debug) continue; | |
| 35 | if (!case.all_modes and optimize != .debug) continue; | |
| 36 | 36 | if (case.os_filter) |os_tag| { |
| 37 | 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 | 147 | break :spawn proc_info.hProcess; |
| 148 | 148 | }; |
| 149 | 149 | defer windows.CloseHandle(child_proc); |
| 150 | const infinite_timeout: windows.LARGE_INTEGER = std.math.minInt(windows.LARGE_INTEGER); | |
| 151 | switch (windows.ntdll.NtWaitForSingleObject(child_proc, .FALSE, &infinite_timeout)) { | |
| 150 | switch (windows.ntdll.NtWaitForSingleObject(child_proc, .FALSE, null)) { | |
| 152 | 151 | windows.NTSTATUS.WAIT_0 => {}, |
| 153 | 152 | .TIMEOUT => return error.WaitTimeOut, |
| 154 | 153 | else => |status| return windows.unexpectedStatus(status), |
test/tests.zig+129-177| ... | ... | @@ -6,8 +6,6 @@ const OptimizeMode = std.builtin.OptimizeMode; |
| 6 | 6 | const Step = std.Build.Step; |
| 7 | 7 | |
| 8 | 8 | // Cases |
| 9 | const error_traces = @import("error_traces.zig"); | |
| 10 | const stack_traces = @import("stack_traces.zig"); | |
| 11 | 9 | const llvm_ir = @import("llvm_ir.zig"); |
| 12 | 10 | const libc = @import("libc.zig"); |
| 13 | 11 | const link = @import("link.zig"); |
| ... | ... | @@ -23,7 +21,7 @@ pub const LinkContext = @import("src/Link.zig"); |
| 23 | 21 | const ModuleTestTarget = struct { |
| 24 | 22 | linkage: ?std.builtin.LinkMode = null, |
| 25 | 23 | target: std.Target.Query = .{}, |
| 26 | optimize_mode: std.builtin.OptimizeMode = .Debug, | |
| 24 | optimize_mode: std.builtin.OptimizeMode = .debug, | |
| 27 | 25 | link_libc: ?bool = null, |
| 28 | 26 | single_threaded: ?bool = null, |
| 29 | 27 | use_llvm: ?bool = null, |
| ... | ... | @@ -57,38 +55,38 @@ const module_test_targets = blk: { |
| 57 | 55 | }, |
| 58 | 56 | |
| 59 | 57 | .{ |
| 60 | .optimize_mode = .ReleaseFast, | |
| 58 | .optimize_mode = .fast, | |
| 61 | 59 | }, |
| 62 | 60 | .{ |
| 63 | 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 | 66 | .single_threaded = true, |
| 69 | 67 | }, |
| 70 | 68 | |
| 71 | 69 | .{ |
| 72 | .optimize_mode = .ReleaseSafe, | |
| 70 | .optimize_mode = .safe, | |
| 73 | 71 | }, |
| 74 | 72 | .{ |
| 75 | 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 | 78 | .single_threaded = true, |
| 81 | 79 | }, |
| 82 | 80 | |
| 83 | 81 | .{ |
| 84 | .optimize_mode = .ReleaseSmall, | |
| 82 | .optimize_mode = .small, | |
| 85 | 83 | }, |
| 86 | 84 | .{ |
| 87 | 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 | 90 | .single_threaded = true, |
| 93 | 91 | }, |
| 94 | 92 | |
| ... | ... | @@ -200,7 +198,7 @@ const module_test_targets = blk: { |
| 200 | 198 | // }, |
| 201 | 199 | // .use_llvm = false, |
| 202 | 200 | // .use_lld = false, |
| 203 | // .optimize_mode = .ReleaseFast, | |
| 201 | // .optimize_mode = .fast, | |
| 204 | 202 | // .strip = true, |
| 205 | 203 | // .skip_modules = &.{"std"}, // TODO get these passing |
| 206 | 204 | //}, |
| ... | ... | @@ -213,7 +211,7 @@ const module_test_targets = blk: { |
| 213 | 211 | // }, |
| 214 | 212 | // .use_llvm = false, |
| 215 | 213 | // .use_lld = false, |
| 216 | // .optimize_mode = .ReleaseFast, | |
| 214 | // .optimize_mode = .fast, | |
| 217 | 215 | // .strip = true, |
| 218 | 216 | // .skip_modules = &.{"std"}, // TODO get these passing |
| 219 | 217 | //}, |
| ... | ... | @@ -274,6 +272,15 @@ const module_test_targets = blk: { |
| 274 | 272 | }, |
| 275 | 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 | 285 | .target = .{ |
| 279 | 286 | .cpu_arch = .arm, |
| ... | ... | @@ -292,6 +299,15 @@ const module_test_targets = blk: { |
| 292 | 299 | }, |
| 293 | 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 | 312 | .target = .{ |
| 297 | 313 | .cpu_arch = .arm, |
| ... | ... | @@ -341,6 +357,15 @@ const module_test_targets = blk: { |
| 341 | 357 | }, |
| 342 | 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 | 369 | // Crashes in weird ways when applying relocations. |
| 345 | 370 | // .{ |
| 346 | 371 | // .target = .{ |
| ... | ... | @@ -360,6 +385,15 @@ const module_test_targets = blk: { |
| 360 | 385 | }, |
| 361 | 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 | 397 | // Crashes in weird ways when applying relocations. |
| 364 | 398 | // .{ |
| 365 | 399 | // .target = .{ |
| ... | ... | @@ -419,6 +453,23 @@ const module_test_targets = blk: { |
| 419 | 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 | }, | |
| 422 | 473 | |
| 423 | 474 | .{ |
| 424 | 475 | .target = .{ |
| ... | ... | @@ -1107,6 +1158,15 @@ const module_test_targets = blk: { |
| 1107 | 1158 | }, |
| 1108 | 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 | 1171 | .target = .{ |
| 1112 | 1172 | .cpu_arch = .x86, |
| ... | ... | @@ -1257,7 +1317,7 @@ const module_test_targets = blk: { |
| 1257 | 1317 | // }, |
| 1258 | 1318 | // .use_llvm = false, |
| 1259 | 1319 | // .use_lld = false, |
| 1260 | // .optimize_mode = .ReleaseFast, | |
| 1320 | // .optimize_mode = .fast, | |
| 1261 | 1321 | // .strip = true, |
| 1262 | 1322 | //}, |
| 1263 | 1323 | |
| ... | ... | @@ -1523,7 +1583,6 @@ const module_test_targets = blk: { |
| 1523 | 1583 | .os_tag = .wasi, |
| 1524 | 1584 | .abi = .none, |
| 1525 | 1585 | }, |
| 1526 | .skip_modules = &.{"compiler-rt"}, | |
| 1527 | 1586 | .use_llvm = false, |
| 1528 | 1587 | .use_lld = false, |
| 1529 | 1588 | }, |
| ... | ... | @@ -1645,6 +1704,15 @@ const module_test_targets = blk: { |
| 1645 | 1704 | }, |
| 1646 | 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 | }, | |
| 1648 | 1716 | |
| 1649 | 1717 | .{ |
| 1650 | 1718 | .target = .{ |
| ... | ... | @@ -1961,7 +2029,6 @@ const c_abi_targets = blk: { |
| 1961 | 2029 | .abi = .musl, |
| 1962 | 2030 | }, |
| 1963 | 2031 | .use_llvm = false, |
| 1964 | .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"}, | |
| 1965 | 2032 | }, |
| 1966 | 2033 | .{ |
| 1967 | 2034 | .target = .{ |
| ... | ... | @@ -1972,7 +2039,6 @@ const c_abi_targets = blk: { |
| 1972 | 2039 | }, |
| 1973 | 2040 | .use_llvm = false, |
| 1974 | 2041 | .strip = true, |
| 1975 | .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"}, | |
| 1976 | 2042 | }, |
| 1977 | 2043 | .{ |
| 1978 | 2044 | .target = .{ |
| ... | ... | @@ -1983,7 +2049,6 @@ const c_abi_targets = blk: { |
| 1983 | 2049 | }, |
| 1984 | 2050 | .use_llvm = false, |
| 1985 | 2051 | .pic = true, |
| 1986 | .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"}, | |
| 1987 | 2052 | }, |
| 1988 | 2053 | .{ |
| 1989 | 2054 | .target = .{ |
| ... | ... | @@ -2010,6 +2075,15 @@ const c_abi_targets = blk: { |
| 2010 | 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 | }, | |
| 2013 | 2087 | |
| 2014 | 2088 | // Windows Targets |
| 2015 | 2089 | |
| ... | ... | @@ -2028,7 +2102,6 @@ const c_abi_targets = blk: { |
| 2028 | 2102 | .abi = .gnu, |
| 2029 | 2103 | }, |
| 2030 | 2104 | .use_llvm = false, |
| 2031 | .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"}, | |
| 2032 | 2105 | }, |
| 2033 | 2106 | .{ |
| 2034 | 2107 | .target = .{ |
| ... | ... | @@ -2038,7 +2111,6 @@ const c_abi_targets = blk: { |
| 2038 | 2111 | .abi = .gnu, |
| 2039 | 2112 | }, |
| 2040 | 2113 | .use_llvm = false, |
| 2041 | .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"}, | |
| 2042 | 2114 | }, |
| 2043 | 2115 | .{ |
| 2044 | 2116 | .target = .{ |
| ... | ... | @@ -2048,7 +2120,6 @@ const c_abi_targets = blk: { |
| 2048 | 2120 | .abi = .gnu, |
| 2049 | 2121 | }, |
| 2050 | 2122 | .use_llvm = false, |
| 2051 | .c_defines = &.{"ZIG_BACKEND_STAGE2_X86_64"}, | |
| 2052 | 2123 | }, |
| 2053 | 2124 | .{ |
| 2054 | 2125 | .target = .{ |
| ... | ... | @@ -2063,7 +2134,7 @@ const c_abi_targets = blk: { |
| 2063 | 2134 | |
| 2064 | 2135 | const LinkTarget = struct { |
| 2065 | 2136 | target: std.Target.Query = .{}, |
| 2066 | optimize_mode: std.builtin.OptimizeMode = .Debug, | |
| 2137 | optimize_mode: std.builtin.OptimizeMode = .debug, | |
| 2067 | 2138 | link_libc: bool = false, |
| 2068 | 2139 | use_llvm: bool = false, |
| 2069 | 2140 | use_lld: bool = false, |
| ... | ... | @@ -2308,59 +2379,7 @@ pub fn isNative(actual_target: *const std.Build.ResolvedTarget, host: *const std |
| 2308 | 2379 | return true; |
| 2309 | 2380 | } |
| 2310 | 2381 | |
| 2311 | /// For stack trace tests, we only test native by default, because external executors are pretty | |
| 2312 | /// unreliable at stack tracing. However, if there's a 32-bit equivalent target which the host can | |
| 2313 | /// trivially run, we may as well at least test that! | |
| 2314 | fn 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 | ||
| 2325 | fn 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 | ||
| 2346 | fn 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 | ||
| 2359 | pub fn addStackTraceTests( | |
| 2360 | b: *std.Build, | |
| 2361 | test_filters: []const []const u8, | |
| 2362 | skip_non_native: bool, | |
| 2363 | ) *Step { | |
| 2382 | pub fn addStackTraceTests(b: *std.Build, test_filters: []const []const u8, skip_non_native: bool) *Step { | |
| 2364 | 2383 | const step = b.step("test-stack-traces", "Run the stack trace tests"); |
| 2365 | 2384 | |
| 2366 | 2385 | const convert_exe = b.addExecutable(.{ |
| ... | ... | @@ -2368,43 +2387,19 @@ pub fn addStackTraceTests( |
| 2368 | 2387 | .root_module = b.createModule(.{ |
| 2369 | 2388 | .root_source_file = b.path("test/src/convert-stack-trace.zig"), |
| 2370 | 2389 | .target = b.graph.host, |
| 2371 | .optimize = .Debug, | |
| 2390 | .optimize = .debug, | |
| 2372 | 2391 | }), |
| 2373 | 2392 | }); |
| 2374 | 2393 | |
| 2375 | const host_cases = b.allocator.create(StackTracesContext) catch @panic("OOM"); | |
| 2376 | host_cases.* = .{ | |
| 2394 | const stack_traces_context = b.allocator.create(StackTracesContext) catch @panic("OOM"); | |
| 2395 | stack_traces_context.* = .{ | |
| 2377 | 2396 | .b = b, |
| 2378 | 2397 | .step = step, |
| 2379 | 2398 | .test_filters = test_filters, |
| 2380 | .targets = nativeAndCompatible32bit(b, skip_non_native), | |
| 2399 | .skip_non_native = skip_non_native, | |
| 2381 | 2400 | .convert_exe = convert_exe, |
| 2382 | 2401 | }; |
| 2383 | stack_traces.addCases(host_cases, b.graph.host.result.os.tag); | |
| 2384 | ||
| 2385 | if (b.enable_wine) { | |
| 2386 | const wine_cases = b.allocator.create(StackTracesContext) catch @panic("OOM"); | |
| 2387 | wine_cases.* = .{ | |
| 2388 | .b = b, | |
| 2389 | .step = step, | |
| 2390 | .test_filters = test_filters, | |
| 2391 | .targets = wineAndCompatible32bit(b, skip_non_native), | |
| 2392 | .convert_exe = convert_exe, | |
| 2393 | }; | |
| 2394 | stack_traces.addCases(wine_cases, .windows); | |
| 2395 | } | |
| 2396 | ||
| 2397 | if (b.enable_darling) { | |
| 2398 | const darling_cases = b.allocator.create(StackTracesContext) catch @panic("OOM"); | |
| 2399 | darling_cases.* = .{ | |
| 2400 | .b = b, | |
| 2401 | .step = step, | |
| 2402 | .test_filters = test_filters, | |
| 2403 | .targets = darlingTargets(b), | |
| 2404 | .convert_exe = convert_exe, | |
| 2405 | }; | |
| 2406 | stack_traces.addCases(darling_cases, .macos); | |
| 2407 | } | |
| 2402 | stack_traces_context.addCases(); | |
| 2408 | 2403 | |
| 2409 | 2404 | return step; |
| 2410 | 2405 | } |
| ... | ... | @@ -2422,56 +2417,24 @@ pub fn addErrorTraceTests( |
| 2422 | 2417 | .root_module = b.createModule(.{ |
| 2423 | 2418 | .root_source_file = b.path("test/src/convert-stack-trace.zig"), |
| 2424 | 2419 | .target = b.graph.host, |
| 2425 | .optimize = .Debug, | |
| 2420 | .optimize = .debug, | |
| 2426 | 2421 | }), |
| 2427 | 2422 | }); |
| 2428 | 2423 | |
| 2429 | const host_cases = b.allocator.create(ErrorTracesContext) catch @panic("OOM"); | |
| 2430 | host_cases.* = .{ | |
| 2424 | const error_traces_context = b.allocator.create(ErrorTracesContext) catch @panic("OOM"); | |
| 2425 | error_traces_context.* = .{ | |
| 2431 | 2426 | .b = b, |
| 2432 | 2427 | .step = step, |
| 2433 | 2428 | .test_filters = test_filters, |
| 2434 | .targets = nativeAndCompatible32bit(b, skip_non_native), | |
| 2429 | .skip_non_native = skip_non_native, | |
| 2435 | 2430 | .optimize_modes = optimize_modes, |
| 2436 | 2431 | .convert_exe = convert_exe, |
| 2437 | 2432 | }; |
| 2438 | error_traces.addCases(host_cases, b.graph.host.result.os.tag); | |
| 2439 | ||
| 2440 | if (b.enable_wine) { | |
| 2441 | const wine_cases = b.allocator.create(ErrorTracesContext) catch @panic("OOM"); | |
| 2442 | wine_cases.* = .{ | |
| 2443 | .b = b, | |
| 2444 | .step = step, | |
| 2445 | .test_filters = test_filters, | |
| 2446 | .targets = wineAndCompatible32bit(b, skip_non_native), | |
| 2447 | .optimize_modes = optimize_modes, | |
| 2448 | .convert_exe = convert_exe, | |
| 2449 | }; | |
| 2450 | error_traces.addCases(wine_cases, .windows); | |
| 2451 | } | |
| 2452 | ||
| 2453 | if (b.enable_darling) { | |
| 2454 | const darling_cases = b.allocator.create(ErrorTracesContext) catch @panic("OOM"); | |
| 2455 | darling_cases.* = .{ | |
| 2456 | .b = b, | |
| 2457 | .step = step, | |
| 2458 | .test_filters = test_filters, | |
| 2459 | .targets = darlingTargets(b), | |
| 2460 | .optimize_modes = optimize_modes, | |
| 2461 | .convert_exe = convert_exe, | |
| 2462 | }; | |
| 2463 | error_traces.addCases(darling_cases, .macos); | |
| 2464 | } | |
| 2433 | error_traces_context.addCases(); | |
| 2465 | 2434 | |
| 2466 | 2435 | return step; |
| 2467 | 2436 | } |
| 2468 | 2437 | |
| 2469 | fn 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 | ||
| 2475 | 2438 | pub fn addStandaloneTests( |
| 2476 | 2439 | b: *std.Build, |
| 2477 | 2440 | optimize_modes: []const OptimizeMode, |
| ... | ... | @@ -2480,21 +2443,19 @@ pub fn addStandaloneTests( |
| 2480 | 2443 | enable_symlinks_windows: bool, |
| 2481 | 2444 | ) *Step { |
| 2482 | 2445 | const step = b.step("test-standalone", "Run the standalone tests"); |
| 2483 | if (compilerHasPackageManager(b)) { | |
| 2484 | const test_cases_dep_name = "standalone_test_cases"; | |
| 2485 | const test_cases_dep = b.dependency(test_cases_dep_name, .{ | |
| 2486 | .enable_ios_sdk = enable_ios_sdk, | |
| 2487 | .enable_macos_sdk = enable_macos_sdk, | |
| 2488 | .enable_symlinks_windows = enable_symlinks_windows, | |
| 2489 | .simple_skip_debug = mem.indexOfScalar(OptimizeMode, optimize_modes, .Debug) == null, | |
| 2490 | .simple_skip_release_safe = mem.indexOfScalar(OptimizeMode, optimize_modes, .ReleaseSafe) == null, | |
| 2491 | .simple_skip_release_fast = mem.indexOfScalar(OptimizeMode, optimize_modes, .ReleaseFast) == null, | |
| 2492 | .simple_skip_release_small = mem.indexOfScalar(OptimizeMode, optimize_modes, .ReleaseSmall) == null, | |
| 2493 | }); | |
| 2494 | const test_cases_dep_step = test_cases_dep.builder.default_step; | |
| 2495 | test_cases_dep_step.name = b.dupe(test_cases_dep_name); | |
| 2496 | step.dependOn(test_cases_dep.builder.default_step); | |
| 2497 | } | |
| 2446 | const test_cases_dep_name = "standalone_test_cases"; | |
| 2447 | const test_cases_dep = b.dependency(test_cases_dep_name, .{ | |
| 2448 | .enable_ios_sdk = enable_ios_sdk, | |
| 2449 | .enable_macos_sdk = enable_macos_sdk, | |
| 2450 | .enable_symlinks_windows = enable_symlinks_windows, | |
| 2451 | .simple_skip_debug = mem.findScalar(OptimizeMode, optimize_modes, .debug) == null, | |
| 2452 | .simple_skip_release_safe = mem.findScalar(OptimizeMode, optimize_modes, .safe) == null, | |
| 2453 | .simple_skip_release_fast = mem.findScalar(OptimizeMode, optimize_modes, .fast) == null, | |
| 2454 | .simple_skip_release_small = mem.findScalar(OptimizeMode, optimize_modes, .small) == null, | |
| 2455 | }); | |
| 2456 | const test_cases_dep_step = test_cases_dep.builder.default_step; | |
| 2457 | test_cases_dep_step.name = b.graph.dupeString(test_cases_dep_name); | |
| 2458 | step.dependOn(test_cases_dep.builder.default_step); | |
| 2498 | 2459 | return step; |
| 2499 | 2460 | } |
| 2500 | 2461 | |
| ... | ... | @@ -2782,16 +2743,6 @@ pub fn addModuleTests(b: *std.Build, options: ModuleTestOptions) *Step { |
| 2782 | 2743 | |
| 2783 | 2744 | const target = &resolved_target.result; |
| 2784 | 2745 | |
| 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 | 2746 | if (std.mem.eql(u8, options.name, "libc")) { |
| 2796 | 2747 | // The libc API tests obviously need to link libc. So for test |
| 2797 | 2748 | // 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 | 2767 | |
| 2817 | 2768 | if (options.test_target_filters.len > 0) { |
| 2818 | 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 | 2771 | } else continue; |
| 2821 | 2772 | } |
| 2822 | 2773 | |
| ... | ... | @@ -3057,7 +3008,7 @@ pub fn wouldUseLlvm(use_llvm: ?bool, query: std.Target.Query, optimize_mode: Opt |
| 3057 | 3008 | if (use_llvm) |x| return x; |
| 3058 | 3009 | if (query.ofmt == .c) return false; |
| 3059 | 3010 | switch (optimize_mode) { |
| 3060 | .Debug => {}, | |
| 3011 | .debug => {}, | |
| 3061 | 3012 | else => return true, |
| 3062 | 3013 | } |
| 3063 | 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 | 3065 | |
| 3115 | 3066 | if (options.test_target_filters.len > 0) { |
| 3116 | 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 | 3069 | } else continue; |
| 3119 | 3070 | } |
| 3120 | 3071 | |
| ... | ... | @@ -3203,7 +3154,7 @@ pub fn addLinkTests(b: *std.Build, options: LinkTestOptions) *Step { |
| 3203 | 3154 | |
| 3204 | 3155 | if (options.test_target_filters.len > 0) { |
| 3205 | 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 | 3158 | } else continue; |
| 3208 | 3159 | } |
| 3209 | 3160 | |
| ... | ... | @@ -3314,7 +3265,7 @@ pub fn addIncrementalTests(b: *std.Build, test_step: *Step, test_filters: []cons |
| 3314 | 3265 | .root_module = b.createModule(.{ |
| 3315 | 3266 | .root_source_file = b.path("tools/incr-check.zig"), |
| 3316 | 3267 | .target = b.graph.host, |
| 3317 | .optimize = .Debug, | |
| 3268 | .optimize = .debug, | |
| 3318 | 3269 | }), |
| 3319 | 3270 | }); |
| 3320 | 3271 | |
| ... | ... | @@ -3328,7 +3279,7 @@ pub fn addIncrementalTests(b: *std.Build, test_step: *Step, test_filters: []cons |
| 3328 | 3279 | if (std.mem.endsWith(u8, entry.basename, ".swp")) continue; |
| 3329 | 3280 | |
| 3330 | 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 | 3283 | } else if (test_filters.len > 0) continue; |
| 3333 | 3284 | |
| 3334 | 3285 | switch (entry.kind) { |
| ... | ... | @@ -3354,10 +3305,11 @@ pub fn addIncrementalTests(b: *std.Build, test_step: *Step, test_filters: []cons |
| 3354 | 3305 | |
| 3355 | 3306 | run.addArg("--quiet"); // don't fill stderr telling us about skipped tests etc |
| 3356 | 3307 | |
| 3357 | if (b.enable_qemu) run.addArg("-fqemu"); | |
| 3358 | if (b.enable_wine) run.addArg("-fwine"); | |
| 3359 | if (b.enable_wasmtime) run.addArg("-fwasmtime"); | |
| 3360 | if (b.enable_darling) run.addArg("-fdarling"); | |
| 3308 | run.addThirdPartyEnabledArgDarling(.{ .enabled = "-fdarling" }); | |
| 3309 | run.addThirdPartyEnabledArgQemu(.{ .enabled = "-fqemu" }); | |
| 3310 | run.addThirdPartyEnabledArgRosetta(.{ .enabled = "-frosetta" }); | |
| 3311 | run.addThirdPartyEnabledArgWasmtime(.{ .enabled = "-fwasmtime" }); | |
| 3312 | run.addThirdPartyEnabledArgWine(.{ .enabled = "-fwine" }); | |
| 3361 | 3313 | |
| 3362 | 3314 | run.addCheck(.{ .expect_term = .{ .exited = 0 } }); |
| 3363 | 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 | ||
| 3 | const std = @import("std"); | |
| 4 | const Io = std.Io; | |
| 5 | const Allocator = std.mem.Allocator; | |
| 6 | const Configuration = std.Build.Configuration; | |
| 7 | const Client = std.zig.Client; | |
| 8 | const Server = std.zig.Server; | |
| 9 | const log = std.log.scoped(.bsp); | |
| 10 | ||
| 11 | pub 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 | ||
| 218 | const 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 | ||
| 236 | fn 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 | 712 | next_tok_is_fn = false; |
| 713 | 713 | |
| 714 | 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 | 716 | // render one comment |
| 717 | 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 | 719 | const comment_end = if (comment_end_off) |o| comment_start + o else token.loc.start; |
| 720 | 720 | |
| 721 | 721 | try writeEscapedLines(out, src[index..comment_start]); |
tools/doctest.zig+11-11| ... | ... | @@ -383,7 +383,7 @@ fn printOutput( |
| 383 | 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 | 387 | print("{s}\nExpected to find '{s}' in stderr\n", .{ result.stderr, error_match }); |
| 388 | 388 | fatal("example did not have expected compile error", .{}); |
| 389 | 389 | } |
| ... | ... | @@ -438,7 +438,7 @@ fn printOutput( |
| 438 | 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 | 442 | print("{s}\nExpected to find '{s}' in stderr\n", .{ result.stderr, error_match }); |
| 443 | 443 | fatal("example did not have expected runtime safety error message", .{}); |
| 444 | 444 | } |
| ... | ... | @@ -513,7 +513,7 @@ fn printOutput( |
| 513 | 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 | 517 | print("{s}\nExpected to find '{s}' in stderr\n", .{ result.stderr, error_match }); |
| 518 | 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 | 623 | next_tok_is_fn = false; |
| 624 | 624 | |
| 625 | 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 | 627 | // render one comment |
| 628 | 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 | 630 | const comment_end = if (comment_end_off) |o| comment_start + o else token.loc.start; |
| 631 | 631 | |
| 632 | 632 | try writeEscapedLines(out, src[index..comment_start]); |
| ... | ... | @@ -870,13 +870,13 @@ const Code = struct { |
| 870 | 870 | }; |
| 871 | 871 | |
| 872 | 872 | fn stripManifest(source_bytes: []const u8) []const u8 { |
| 873 | const manifest_start = mem.lastIndexOf(u8, source_bytes, "\n\n// ") orelse | |
| 873 | const manifest_start = mem.findLast(u8, source_bytes, "\n\n// ") orelse | |
| 874 | 874 | fatal("missing manifest comment", .{}); |
| 875 | 875 | return source_bytes[0 .. manifest_start + 1]; |
| 876 | 876 | } |
| 877 | 877 | |
| 878 | 878 | fn parseManifest(arena: Allocator, source_bytes: []const u8) !Code { |
| 879 | const manifest_start = mem.lastIndexOf(u8, source_bytes, "\n\n// ") orelse | |
| 879 | const manifest_start = mem.findLast(u8, source_bytes, "\n\n// ") orelse | |
| 880 | 880 | fatal("missing manifest comment", .{}); |
| 881 | 881 | var it = mem.tokenizeScalar(u8, source_bytes[manifest_start..], '\n'); |
| 882 | 882 | const first_line = skipPrefix(it.next().?); |
| ... | ... | @@ -915,11 +915,11 @@ fn parseManifest(arena: Allocator, source_bytes: []const u8) !Code { |
| 915 | 915 | while (it.next()) |prefixed_line| { |
| 916 | 916 | const line = skipPrefix(prefixed_line); |
| 917 | 917 | if (mem.startsWith(u8, line, "optimize=")) { |
| 918 | mode = std.meta.stringToEnum(std.builtin.OptimizeMode, line["optimize=".len..]) orelse | |
| 919 | fatal("bad optimization mode line: '{s}'", .{line}); | |
| 918 | mode = std.builtin.Optimize.fromString(line["optimize=".len..]) orelse | |
| 919 | fatal("bad optimization mode line: {q}", .{line}); | |
| 920 | 920 | } else if (mem.startsWith(u8, line, "link_mode=")) { |
| 921 | 921 | 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 | 923 | } else if (mem.startsWith(u8, line, "link_object=")) { |
| 924 | 924 | try link_objects.append(arena, line["link_object=".len..]); |
| 925 | 925 | } else if (mem.startsWith(u8, line, "additional_option=")) { |
| ... | ... | @@ -1104,7 +1104,7 @@ fn termColor(allocator: Allocator, input: []const u8) ![]u8 { |
| 1104 | 1104 | |
| 1105 | 1105 | // Returns true if number is in slice. |
| 1106 | 1106 | fn 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 | } |
| 1109 | 1109 | |
| 1110 | 1110 | fn run( |
tools/fetch_them_macos_headers.zig+2-2| ... | ... | @@ -187,8 +187,8 @@ fn fetchTarget( |
| 187 | 187 | |
| 188 | 188 | var it = mem.splitScalar(u8, headers_list_str, '\n'); |
| 189 | 189 | while (it.next()) |line| { |
| 190 | if (mem.lastIndexOf(u8, line, "clang") != null) continue; | |
| 191 | if (mem.lastIndexOf(u8, line, prefix[0..])) |idx| { | |
| 190 | if (mem.findLast(u8, line, "clang") != null) continue; | |
| 191 | if (mem.findLast(u8, line, prefix[0..])) |idx| { | |
| 192 | 192 | const out_rel_path = line[idx + prefix.len + 1 ..]; |
| 193 | 193 | const out_rel_path_stripped = mem.trim(u8, out_rel_path, " \\"); |
| 194 | 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 | ||
| 9 | const std = @import("std"); | |
| 10 | const Io = std.Io; | |
| 11 | ||
| 12 | fn 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 | ||
| 29 | var general_purpose_allocator: std.heap.DebugAllocator(.{}) = .init; | |
| 30 | ||
| 31 | pub 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 | 305 | |
| 306 | 306 | fn check(eval: *Eval, mr: *Io.File.MultiReader, update: Case.Update, prog_node: std.Progress.Node) !void { |
| 307 | 307 | const arena = eval.arena; |
| 308 | const stdout = mr.fileReader(0); | |
| 309 | const stderr = &mr.fileReader(1).interface; | |
| 310 | const Header = std.zig.Server.Message.Header; | |
| 308 | const stdout = mr.reader(0); | |
| 309 | const stderr = mr.reader(1); | |
| 310 | ||
| 311 | var client: std.zig.Client = .{ | |
| 312 | .in = stdout, | |
| 313 | .out = undefined, | |
| 314 | }; | |
| 311 | 315 | |
| 312 | 316 | while (true) { |
| 313 | const header = stdout.interface.takeStruct(Header, .little) catch |err| switch (err) { | |
| 314 | error.EndOfStream => break, | |
| 315 | error.ReadFailed => return stdout.err.?, | |
| 316 | }; | |
| 317 | const body = stdout.interface.take(header.bytes_len) catch |err| switch (err) { | |
| 317 | const header = client.receiveMessageWithMultiReader(mr, .none) catch |err| switch (err) { | |
| 318 | error.Timeout => unreachable, | |
| 318 | 319 | // If this panic triggers it might be helpful to rework this |
| 319 | 320 | // code to print the stderr from the abnormally terminated child. |
| 320 | 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; | |
| 323 | 325 | |
| 324 | 326 | switch (header.tag) { |
| 325 | 327 | .error_bundle => { |
| ... | ... | @@ -448,7 +450,7 @@ const Eval = struct { |
| 448 | 450 | const raw_filename = eb.nullTerminatedString(src.src_path); |
| 449 | 451 | // We need to replace backslashes for consistency between platforms. |
| 450 | 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 | 454 | const copied = try eval.arena.dupe(u8, raw_filename); |
| 453 | 455 | std.mem.replaceScalar(u8, copied, '\\', '/'); |
| 454 | 456 | break :name copied; |
| ... | ... | @@ -605,12 +607,13 @@ const Eval = struct { |
| 605 | 607 | |
| 606 | 608 | fn requestUpdate(eval: *Eval) !void { |
| 607 | 609 | const io = eval.io; |
| 608 | const header: std.zig.Client.Message.Header = .{ | |
| 609 | .tag = .update, | |
| 610 | .bytes_len = 0, | |
| 610 | ||
| 611 | var w = eval.child.stdin.?.writerStreaming(io, &.{}); | |
| 612 | var client: std.zig.Client = .{ | |
| 613 | .in = undefined, | |
| 614 | .out = &w.interface, | |
| 611 | 615 | }; |
| 612 | var w = eval.child.stdin.?.writer(io, &.{}); | |
| 613 | w.interface.writeStruct(header, .little) catch |err| switch (err) { | |
| 616 | client.serveBodylessMessage(.update) catch |err| switch (err) { | |
| 614 | 617 | error.WriteFailed => return w.err.?, |
| 615 | 618 | }; |
| 616 | 619 | } |
| ... | ... | @@ -618,22 +621,23 @@ const Eval = struct { |
| 618 | 621 | fn end(eval: *Eval, mr: *Io.File.MultiReader) !void { |
| 619 | 622 | requestExit(eval.child, eval); |
| 620 | 623 | |
| 621 | const stdout = mr.fileReader(0); | |
| 622 | const Header = std.zig.Server.Message.Header; | |
| 624 | var client: std.zig.Client = .{ | |
| 625 | .in = mr.reader(0), | |
| 626 | .out = undefined, | |
| 627 | }; | |
| 623 | 628 | |
| 624 | 629 | while (true) { |
| 625 | const header = stdout.interface.takeStruct(Header, .little) catch |err| switch (err) { | |
| 626 | error.EndOfStream => break, | |
| 627 | error.ReadFailed => return stdout.err.?, | |
| 628 | }; | |
| 629 | stdout.interface.discardAll(header.bytes_len) catch |err| switch (err) { | |
| 630 | error.ReadFailed => return stdout.err.?, | |
| 631 | error.EndOfStream => |e| return e, | |
| 630 | const header = client.receiveMessageWithMultiReader(mr, .none) catch |err| switch (err) { | |
| 631 | error.Timeout => unreachable, | |
| 632 | error.EndOfStream => |e| { | |
| 633 | if (client.in.bufferedLen() == 0) break; | |
| 634 | return e; | |
| 635 | }, | |
| 636 | else => |e| return e, | |
| 632 | 637 | }; |
| 638 | try client.in.discardAll(header.bytes_len); | |
| 633 | 639 | } |
| 634 | 640 | |
| 635 | try mr.fillRemaining(.none); | |
| 636 | ||
| 637 | 641 | const stderr = mr.reader(1).buffered(); |
| 638 | 642 | if (stderr.len > 0) eval.fatal("unexpected stderr:\n{s}", .{stderr}); |
| 639 | 643 | } |
| ... | ... | @@ -773,7 +777,7 @@ const Case = struct { |
| 773 | 777 | .backend = backend, |
| 774 | 778 | }); |
| 775 | 779 | } else if (std.mem.eql(u8, key, "module")) { |
| 776 | const split_idx = std.mem.indexOfScalar(u8, val, '=') orelse | |
| 780 | const split_idx = std.mem.findScalar(u8, val, '=') orelse | |
| 777 | 781 | fatal("line {d}: module does not include file", .{line_n}); |
| 778 | 782 | const name = val[0..split_idx]; |
| 779 | 783 | const file = val[split_idx + 1 ..]; |
| ... | ... | @@ -899,12 +903,12 @@ fn requestExit(child: *std.process.Child, eval: *Eval) void { |
| 899 | 903 | if (child.stdin == null) return; |
| 900 | 904 | const io = eval.io; |
| 901 | 905 | |
| 902 | const header: std.zig.Client.Message.Header = .{ | |
| 903 | .tag = .exit, | |
| 904 | .bytes_len = 0, | |
| 906 | var w = eval.child.stdin.?.writerStreaming(io, &.{}); | |
| 907 | var client: std.zig.Client = .{ | |
| 908 | .in = undefined, | |
| 909 | .out = &w.interface, | |
| 905 | 910 | }; |
| 906 | var w = eval.child.stdin.?.writer(io, &.{}); | |
| 907 | w.interface.writeStruct(header, .little) catch |err| switch (err) { | |
| 911 | client.serveBodylessMessage(.exit) catch |err| switch (err) { | |
| 908 | 912 | error.WriteFailed => switch (w.err.?) { |
| 909 | 913 | error.BrokenPipe => {}, |
| 910 | 914 | else => |e| eval.fatal("failed to send exit: {t}", .{e}), |
| ... | ... | @@ -979,7 +983,7 @@ fn rand64(io: Io) u64 { |
| 979 | 983 | fn parseTargetQueryAndBackend(input_str: []const u8, err_prefix: []const u8) struct { std.Target.Query, Backend } { |
| 980 | 984 | const fatal = std.process.fatal; |
| 981 | 985 | |
| 982 | const split_idx = std.mem.lastIndexOfScalar(u8, input_str, '-') orelse | |
| 986 | const split_idx = std.mem.findScalarLast(u8, input_str, '-') orelse | |
| 983 | 987 | fatal("{s}target does not include backend", .{err_prefix}); |
| 984 | 988 | |
| 985 | 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 | 319 | return parseError(tokenizer, code_kind_tok, "unrecognized code kind: {s}", .{code_kind_str}); |
| 320 | 320 | } |
| 321 | 321 | |
| 322 | var mode: std.builtin.OptimizeMode = .Debug; | |
| 322 | var mode: std.builtin.OptimizeMode = .debug; | |
| 323 | 323 | var link_objects = std.array_list.Managed([]const u8).init(arena); |
| 324 | 324 | var target_str: ?[]const u8 = null; |
| 325 | 325 | var link_libc = false; |
| ... | ... | @@ -403,7 +403,7 @@ fn walk(arena: Allocator, io: Io, tokenizer: *Tokenizer, out_dir: Dir, w: anytyp |
| 403 | 403 | }, |
| 404 | 404 | } |
| 405 | 405 | |
| 406 | if (mode != .Debug) | |
| 406 | if (mode != .debug) | |
| 407 | 407 | try code.print("// optimize={s}\n", .{@tagName(mode)}); |
| 408 | 408 | |
| 409 | 409 | for (link_objects.items) |link_object| { |
tools/process_headers.zig+2| ... | ... | @@ -36,6 +36,8 @@ const glibc_targets = [_]LibCTarget{ |
| 36 | 36 | .{ .arch = .aarch64_be, .abi = .gnu, .dest = "aarch64-linux-gnu" }, |
| 37 | 37 | .{ .arch = .csky, .abi = .gnueabi, .dest = "csky-linux-gnu" }, |
| 38 | 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 | 41 | .{ .arch = .loongarch64, .abi = .gnu, .dest = "loongarch-linux-gnu" }, |
| 40 | 42 | .{ .arch = .loongarch64, .abi = .gnusf, .dest = "loongarch-linux-gnu" }, |
| 41 | 43 | .{ .arch = .m68k, .abi = .gnu }, |
tools/update_clang_options.zig+1-1| ... | ... | @@ -599,7 +599,7 @@ const known_options = [_]KnownOpt{ |
| 599 | 599 | const blacklisted_options = [_][]const u8{}; |
| 600 | 600 | |
| 601 | 601 | fn 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 | 603 | for (known_options) |item| { |
| 604 | 604 | if (std.mem.eql(u8, chopped_name, item.name)) { |
| 605 | 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 | 99 | |
| 100 | 100 | var it = mem.splitSequence(u8, line, " "); |
| 101 | 101 | while (it.next()) |property| { |
| 102 | const i = mem.indexOf(u8, property, "=").?; | |
| 102 | const i = mem.find(u8, property, "=").?; | |
| 103 | 103 | const key = property[0..i]; |
| 104 | 104 | const value = property[i + 1 ..]; |
| 105 | 105 | if (mem.eql(u8, key, "width")) { |
tools/update_glibc.zig+1| ... | ... | @@ -36,6 +36,7 @@ const exempt_extensions = [_][]const u8{ |
| 36 | 36 | // These are the start files we use when targeting glibc <= 2.33. |
| 37 | 37 | "-2.33.S", |
| 38 | 38 | "-2.33.c", |
| 39 | "-2.32.c", | |
| 39 | 40 | }; |
| 40 | 41 | |
| 41 | 42 | pub fn main(init: std.process.Init) !void { |