| author | |
| committer | |
| log | fc40d2372335e69be175972ffabb55bc7fb77230 |
| tree | 184daa7845a95f54da0c8c5c6ffba0feffa01b6c |
| parent | 7a27f0d80c5ce9d596b2b43699e131ab387e1317 |
| parent | 9d409233b2c62e1d24635165ac6b3b7686ffd5e4 |
Conflicts:
* build.zig
* lib/std/array_list.zig
* lib/std/c/ast.zig
* lib/std/c/parse.zig
* lib/std/os/bits/linux.zig54 files changed, 7625 insertions(+), 2956 deletions(-)
build.zig+25-21| ... | @@ -36,7 +36,7 @@ pub fn build(b: *Builder) !void { | ... | @@ -36,7 +36,7 @@ pub fn build(b: *Builder) !void { |
| 36 | const docs_step = b.step("docs", "Build documentation"); | 36 | const docs_step = b.step("docs", "Build documentation"); |
| 37 | docs_step.dependOn(&docgen_cmd.step); | 37 | docs_step.dependOn(&docgen_cmd.step); |
| 38 | 38 | ||
| 39 | const test_step = b.step("test", "Run all the tests"); | 39 | const toolchain_step = b.step("test-toolchain", "Run the tests for the toolchain"); |
| 40 | 40 | ||
| 41 | var test_stage2 = b.addTest("src/test.zig"); | 41 | var test_stage2 = b.addTest("src/test.zig"); |
| 42 | test_stage2.setBuildMode(mode); | 42 | test_stage2.setBuildMode(mode); |
| ... | @@ -99,7 +99,7 @@ pub fn build(b: *Builder) !void { | ... | @@ -99,7 +99,7 @@ pub fn build(b: *Builder) !void { |
| 99 | exe.install(); | 99 | exe.install(); |
| 100 | exe.setBuildMode(mode); | 100 | exe.setBuildMode(mode); |
| 101 | exe.setTarget(target); | 101 | exe.setTarget(target); |
| 102 | test_step.dependOn(&exe.step); | 102 | toolchain_step.dependOn(&exe.step); |
| 103 | b.default_step.dependOn(&exe.step); | 103 | b.default_step.dependOn(&exe.step); |
| 104 | 104 | ||
| 105 | exe.addBuildOption(u32, "mem_leak_frames", mem_leak_frames); | 105 | exe.addBuildOption(u32, "mem_leak_frames", mem_leak_frames); |
| ... | @@ -244,7 +244,7 @@ pub fn build(b: *Builder) !void { | ... | @@ -244,7 +244,7 @@ pub fn build(b: *Builder) !void { |
| 244 | const test_stage2_step = b.step("test-stage2", "Run the stage2 compiler tests"); | 244 | const test_stage2_step = b.step("test-stage2", "Run the stage2 compiler tests"); |
| 245 | test_stage2_step.dependOn(&test_stage2.step); | 245 | test_stage2_step.dependOn(&test_stage2.step); |
| 246 | if (!skip_stage2_tests) { | 246 | if (!skip_stage2_tests) { |
| 247 | test_step.dependOn(test_stage2_step); | 247 | toolchain_step.dependOn(test_stage2_step); |
| 248 | } | 248 | } |
| 249 | 249 | ||
| 250 | var chosen_modes: [4]builtin.Mode = undefined; | 250 | var chosen_modes: [4]builtin.Mode = undefined; |
| ... | @@ -268,33 +268,37 @@ pub fn build(b: *Builder) !void { | ... | @@ -268,33 +268,37 @@ pub fn build(b: *Builder) !void { |
| 268 | const modes = chosen_modes[0..chosen_mode_index]; | 268 | const modes = chosen_modes[0..chosen_mode_index]; |
| 269 | 269 | ||
| 270 | // run stage1 `zig fmt` on this build.zig file just to make sure it works | 270 | // run stage1 `zig fmt` on this build.zig file just to make sure it works |
| 271 | test_step.dependOn(&fmt_build_zig.step); | 271 | toolchain_step.dependOn(&fmt_build_zig.step); |
| 272 | const fmt_step = b.step("test-fmt", "Run zig fmt against build.zig to make sure it works"); | 272 | const fmt_step = b.step("test-fmt", "Run zig fmt against build.zig to make sure it works"); |
| 273 | fmt_step.dependOn(&fmt_build_zig.step); | 273 | fmt_step.dependOn(&fmt_build_zig.step); |
| 274 | 274 | ||
| 275 | // TODO for the moment, skip wasm32-wasi until bugs are sorted out. | 275 | // TODO for the moment, skip wasm32-wasi until bugs are sorted out. |
| 276 | test_step.dependOn(tests.addPkgTests(b, test_filter, "test/behavior.zig", "behavior", "Run the behavior tests", modes, false, skip_non_native, skip_libc, is_wine_enabled, is_qemu_enabled, is_wasmtime_enabled, glibc_multi_dir)); | 276 | toolchain_step.dependOn(tests.addPkgTests(b, test_filter, "test/behavior.zig", "behavior", "Run the behavior tests", modes, false, skip_non_native, skip_libc, is_wine_enabled, is_qemu_enabled, is_wasmtime_enabled, glibc_multi_dir)); |
| 277 | 277 | ||
| 278 | test_step.dependOn(tests.addPkgTests(b, test_filter, "lib/std/std.zig", "std", "Run the standard library tests", modes, false, skip_non_native, skip_libc, is_wine_enabled, is_qemu_enabled, is_wasmtime_enabled, glibc_multi_dir)); | 278 | toolchain_step.dependOn(tests.addPkgTests(b, test_filter, "lib/std/special/compiler_rt.zig", "compiler-rt", "Run the compiler_rt tests", modes, true, skip_non_native, true, is_wine_enabled, is_qemu_enabled, is_wasmtime_enabled, glibc_multi_dir)); |
| 279 | 279 | toolchain_step.dependOn(tests.addPkgTests(b, test_filter, "lib/std/special/c.zig", "minilibc", "Run the mini libc tests", modes, true, skip_non_native, true, is_wine_enabled, is_qemu_enabled, is_wasmtime_enabled, glibc_multi_dir)); | |
| 280 | test_step.dependOn(tests.addPkgTests(b, test_filter, "lib/std/special/compiler_rt.zig", "compiler-rt", "Run the compiler_rt tests", modes, true, skip_non_native, true, is_wine_enabled, is_qemu_enabled, is_wasmtime_enabled, glibc_multi_dir)); | 280 | |
| 281 | test_step.dependOn(tests.addPkgTests(b, test_filter, "lib/std/special/c.zig", "minilibc", "Run the mini libc tests", modes, true, skip_non_native, true, is_wine_enabled, is_qemu_enabled, is_wasmtime_enabled, glibc_multi_dir)); | 281 | toolchain_step.dependOn(tests.addCompareOutputTests(b, test_filter, modes)); |
| 282 | 282 | toolchain_step.dependOn(tests.addStandaloneTests(b, test_filter, modes)); | |
| 283 | test_step.dependOn(tests.addCompareOutputTests(b, test_filter, modes)); | 283 | toolchain_step.dependOn(tests.addStackTraceTests(b, test_filter, modes)); |
| 284 | test_step.dependOn(tests.addStandaloneTests(b, test_filter, modes)); | 284 | toolchain_step.dependOn(tests.addCliTests(b, test_filter, modes)); |
| 285 | test_step.dependOn(tests.addStackTraceTests(b, test_filter, modes)); | 285 | toolchain_step.dependOn(tests.addAssembleAndLinkTests(b, test_filter, modes)); |
| 286 | test_step.dependOn(tests.addCliTests(b, test_filter, modes)); | 286 | toolchain_step.dependOn(tests.addRuntimeSafetyTests(b, test_filter, modes)); |
| 287 | test_step.dependOn(tests.addAssembleAndLinkTests(b, test_filter, modes)); | 287 | toolchain_step.dependOn(tests.addTranslateCTests(b, test_filter)); |
| 288 | test_step.dependOn(tests.addRuntimeSafetyTests(b, test_filter, modes)); | ||
| 289 | test_step.dependOn(tests.addTranslateCTests(b, test_filter)); | ||
| 290 | if (!skip_run_translated_c) { | 288 | if (!skip_run_translated_c) { |
| 291 | test_step.dependOn(tests.addRunTranslatedCTests(b, test_filter, target)); | 289 | toolchain_step.dependOn(tests.addRunTranslatedCTests(b, test_filter, target)); |
| 292 | } | 290 | } |
| 293 | // tests for this feature are disabled until we have the self-hosted compiler available | 291 | // tests for this feature are disabled until we have the self-hosted compiler available |
| 294 | // test_step.dependOn(tests.addGenHTests(b, test_filter)); | 292 | // toolchain_step.dependOn(tests.addGenHTests(b, test_filter)); |
| 295 | if (!skip_compile_errors) { | 293 | if (!skip_compile_errors) { |
| 296 | test_step.dependOn(tests.addCompileErrorTests(b, test_filter, modes)); | 294 | toolchain_step.dependOn(tests.addCompileErrorTests(b, test_filter, modes)); |
| 297 | } | 295 | } |
| 296 | |||
| 297 | const std_step = tests.addPkgTests(b, test_filter, "lib/std/std.zig", "std", "Run the standard library tests", modes, false, skip_non_native, skip_libc, is_wine_enabled, is_qemu_enabled, is_wasmtime_enabled, glibc_multi_dir); | ||
| 298 | |||
| 299 | const test_step = b.step("test", "Run all the tests"); | ||
| 300 | test_step.dependOn(toolchain_step); | ||
| 301 | test_step.dependOn(std_step); | ||
| 298 | test_step.dependOn(docs_step); | 302 | test_step.dependOn(docs_step); |
| 299 | } | 303 | } |
| 300 | 304 |
ci/azure/linux_script+3-1| ... | @@ -65,7 +65,9 @@ make $JOBS install | ... | @@ -65,7 +65,9 @@ make $JOBS install |
| 65 | cmake .. -DZIG_EXECUTABLE="$(pwd)/release/bin/zig" | 65 | cmake .. -DZIG_EXECUTABLE="$(pwd)/release/bin/zig" |
| 66 | make $JOBS install | 66 | make $JOBS install |
| 67 | 67 | ||
| 68 | release/bin/zig build test -Denable-qemu -Denable-wasmtime | 68 | for step in test-toolchain test-std docs; do |
| 69 | release/bin/zig build $step -Denable-qemu -Denable-wasmtime | ||
| 70 | done | ||
| 69 | 71 | ||
| 70 | # Look for HTML errors. | 72 | # Look for HTML errors. |
| 71 | tidy -qe ../zig-cache/langref.html | 73 | tidy -qe ../zig-cache/langref.html |
ci/azure/macos_script+4-2| ... | @@ -18,7 +18,7 @@ tar xf "$CACHE_BASENAME.tar.xz" | ... | @@ -18,7 +18,7 @@ tar xf "$CACHE_BASENAME.tar.xz" |
| 18 | 18 | ||
| 19 | ZIG="$PREFIX/bin/zig" | 19 | ZIG="$PREFIX/bin/zig" |
| 20 | NATIVE_LIBC_TXT="$HOME/native_libc.txt" | 20 | NATIVE_LIBC_TXT="$HOME/native_libc.txt" |
| 21 | $ZIG libc > "$NATIVE_LIBC_TXT" | 21 | $ZIG libc >"$NATIVE_LIBC_TXT" |
| 22 | export ZIG_LIBC="$NATIVE_LIBC_TXT" | 22 | export ZIG_LIBC="$NATIVE_LIBC_TXT" |
| 23 | export CC="$ZIG cc" | 23 | export CC="$ZIG cc" |
| 24 | export CXX="$ZIG c++" | 24 | export CXX="$ZIG c++" |
| ... | @@ -55,7 +55,9 @@ make $JOBS install | ... | @@ -55,7 +55,9 @@ make $JOBS install |
| 55 | cmake .. -DZIG_EXECUTABLE="$(pwd)/release/bin/zig" -DZIG_TARGET_MCPU="x86_64_v2" | 55 | cmake .. -DZIG_EXECUTABLE="$(pwd)/release/bin/zig" -DZIG_TARGET_MCPU="x86_64_v2" |
| 56 | make $JOBS install | 56 | make $JOBS install |
| 57 | 57 | ||
| 58 | release/bin/zig build test | 58 | for step in test-toolchain test-std docs; do |
| 59 | release/bin/zig build $step | ||
| 60 | done | ||
| 59 | 61 | ||
| 60 | if [ "${BUILD_REASON}" != "PullRequest" ]; then | 62 | if [ "${BUILD_REASON}" != "PullRequest" ]; then |
| 61 | mv ../LICENSE release/ | 63 | mv ../LICENSE release/ |
ci/azure/windows_msvc_script.bat+1-13| ... | @@ -26,20 +26,8 @@ cd %ZIGBUILDDIR% | ... | @@ -26,20 +26,8 @@ cd %ZIGBUILDDIR% |
| 26 | cmake.exe .. -Thost=x64 -G"Visual Studio 16 2019" -A x64 "-DCMAKE_INSTALL_PREFIX=%ZIGINSTALLDIR%" "-DCMAKE_PREFIX_PATH=%ZIGPREFIXPATH%" -DCMAKE_BUILD_TYPE=Release -DZIG_OMIT_STAGE2=ON || exit /b | 26 | cmake.exe .. -Thost=x64 -G"Visual Studio 16 2019" -A x64 "-DCMAKE_INSTALL_PREFIX=%ZIGINSTALLDIR%" "-DCMAKE_PREFIX_PATH=%ZIGPREFIXPATH%" -DCMAKE_BUILD_TYPE=Release -DZIG_OMIT_STAGE2=ON || exit /b |
| 27 | msbuild /maxcpucount /p:Configuration=Release INSTALL.vcxproj || exit /b | 27 | msbuild /maxcpucount /p:Configuration=Release INSTALL.vcxproj || exit /b |
| 28 | 28 | ||
| 29 | "%ZIGINSTALLDIR%\bin\zig.exe" build test-behavior -Dskip-non-native || exit /b | 29 | "%ZIGINSTALLDIR%\bin\zig.exe" build test-toolchain -Dskip-non-native -Dskip-stage2-tests || exit /b |
| 30 | REM Disabled to prevent OOM | ||
| 31 | REM "%ZIGINSTALLDIR%\bin\zig.exe" build test-stage2 -Dskip-non-native || exit /b | ||
| 32 | "%ZIGINSTALLDIR%\bin\zig.exe" build test-fmt -Dskip-non-native || exit /b | ||
| 33 | "%ZIGINSTALLDIR%\bin\zig.exe" build test-std -Dskip-non-native || exit /b | 30 | "%ZIGINSTALLDIR%\bin\zig.exe" build test-std -Dskip-non-native || exit /b |
| 34 | "%ZIGINSTALLDIR%\bin\zig.exe" build test-compiler-rt -Dskip-non-native || exit /b | ||
| 35 | "%ZIGINSTALLDIR%\bin\zig.exe" build test-compare-output -Dskip-non-native || exit /b | ||
| 36 | "%ZIGINSTALLDIR%\bin\zig.exe" build test-standalone -Dskip-non-native || exit /b | ||
| 37 | "%ZIGINSTALLDIR%\bin\zig.exe" build test-stack-traces -Dskip-non-native || exit /b | ||
| 38 | "%ZIGINSTALLDIR%\bin\zig.exe" build test-cli -Dskip-non-native || exit /b | ||
| 39 | "%ZIGINSTALLDIR%\bin\zig.exe" build test-asm-link -Dskip-non-native || exit /b | ||
| 40 | "%ZIGINSTALLDIR%\bin\zig.exe" build test-runtime-safety -Dskip-non-native || exit /b | ||
| 41 | "%ZIGINSTALLDIR%\bin\zig.exe" build test-translate-c -Dskip-non-native || exit /b | ||
| 42 | "%ZIGINSTALLDIR%\bin\zig.exe" build test-run-translated-c -Dskip-non-native || exit /b | ||
| 43 | "%ZIGINSTALLDIR%\bin\zig.exe" build docs || exit /b | 31 | "%ZIGINSTALLDIR%\bin\zig.exe" build docs || exit /b |
| 44 | 32 | ||
| 45 | set "PATH=%CD:~0,2%\msys64\usr\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem" | 33 | set "PATH=%CD:~0,2%\msys64\usr\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem" |
ci/srht/freebsd_script+1-1| ... | @@ -4,7 +4,7 @@ set -x | ... | @@ -4,7 +4,7 @@ set -x |
| 4 | set -e | 4 | set -e |
| 5 | 5 | ||
| 6 | sudo pkg update -fq | 6 | sudo pkg update -fq |
| 7 | sudo pkg install -y cmake py37-s3cmd wget curl jq samurai | 7 | sudo pkg install -y cmake py38-s3cmd wget curl jq samurai |
| 8 | 8 | ||
| 9 | ZIGDIR="$(pwd)" | 9 | ZIGDIR="$(pwd)" |
| 10 | CACHE_BASENAME="zig+llvm+lld+clang-x86_64-freebsd-gnu-0.8.0-dev.1939+5a3ea9bec" | 10 | CACHE_BASENAME="zig+llvm+lld+clang-x86_64-freebsd-gnu-0.8.0-dev.1939+5a3ea9bec" |
lib/std/Thread.zig+23-4| ... | @@ -68,11 +68,30 @@ else switch (std.Target.current.os.tag) { | ... | @@ -68,11 +68,30 @@ else switch (std.Target.current.os.tag) { |
| 68 | }; | 68 | }; |
| 69 | 69 | ||
| 70 | /// Signals the processor that it is inside a busy-wait spin-loop ("spin lock"). | 70 | /// Signals the processor that it is inside a busy-wait spin-loop ("spin lock"). |
| 71 | pub fn spinLoopHint() void { | 71 | pub fn spinLoopHint() callconv(.Inline) void { |
| 72 | switch (std.Target.current.cpu.arch) { | 72 | switch (std.Target.current.cpu.arch) { |
| 73 | .i386, .x86_64 => asm volatile ("pause" ::: "memory"), | 73 | .i386, .x86_64 => { |
| 74 | .arm, .aarch64 => asm volatile ("yield" ::: "memory"), | 74 | asm volatile ("pause" ::: "memory"); |
| 75 | else => {}, | 75 | }, |
| 76 | .arm, .armeb, .thumb, .thumbeb => { | ||
| 77 | // `yield` was introduced in v6k but are also available on v6m. | ||
| 78 | const can_yield = comptime std.Target.arm.featureSetHasAny(std.Target.current.cpu.features, .{ .has_v6k, .has_v6m }); | ||
| 79 | if (can_yield) asm volatile ("yield" ::: "memory") | ||
| 80 | // Fallback. | ||
| 81 | else asm volatile ("" ::: "memory"); | ||
| 82 | }, | ||
| 83 | .aarch64, .aarch64_be, .aarch64_32 => { | ||
| 84 | asm volatile ("isb" ::: "memory"); | ||
| 85 | }, | ||
| 86 | .powerpc64, .powerpc64le => { | ||
| 87 | // No-op that serves as `yield` hint. | ||
| 88 | asm volatile ("or 27, 27, 27" ::: "memory"); | ||
| 89 | }, | ||
| 90 | else => { | ||
| 91 | // Do nothing but prevent the compiler from optimizing away the | ||
| 92 | // spinning loop. | ||
| 93 | asm volatile ("" ::: "memory"); | ||
| 94 | }, | ||
| 76 | } | 95 | } |
| 77 | } | 96 | } |
| 78 | 97 |
lib/std/array_list.zig+55-29| ... | @@ -50,7 +50,6 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { | ... | @@ -50,7 +50,6 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 50 | allocator: *Allocator, | 50 | allocator: *Allocator, |
| 51 | 51 | ||
| 52 | pub const Slice = if (alignment) |a| ([]align(a) T) else []T; | 52 | pub const Slice = if (alignment) |a| ([]align(a) T) else []T; |
| 53 | pub const SliceConst = if (alignment) |a| ([]align(a) const T) else []const T; | ||
| 54 | 53 | ||
| 55 | /// Deinitialize with `deinit` or use `toOwnedSlice`. | 54 | /// Deinitialize with `deinit` or use `toOwnedSlice`. |
| 56 | pub fn init(allocator: *Allocator) Self { | 55 | pub fn init(allocator: *Allocator) Self { |
| ... | @@ -141,7 +140,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { | ... | @@ -141,7 +140,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 141 | 140 | ||
| 142 | /// Insert slice `items` at index `i` by moving `list[i .. list.len]` to make room. | 141 | /// Insert slice `items` at index `i` by moving `list[i .. list.len]` to make room. |
| 143 | /// This operation is O(N). | 142 | /// This operation is O(N). |
| 144 | pub fn insertSlice(self: *Self, i: usize, items: SliceConst) !void { | 143 | pub fn insertSlice(self: *Self, i: usize, items: []const T) !void { |
| 145 | try self.ensureUnusedCapacity(items.len); | 144 | try self.ensureUnusedCapacity(items.len); |
| 146 | self.items.len += items.len; | 145 | self.items.len += items.len; |
| 147 | 146 | ||
| ... | @@ -153,7 +152,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { | ... | @@ -153,7 +152,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 153 | /// Grows list if `len < new_items.len`. | 152 | /// Grows list if `len < new_items.len`. |
| 154 | /// Shrinks list if `len > new_items.len`. | 153 | /// Shrinks list if `len > new_items.len`. |
| 155 | /// Invalidates pointers if this ArrayList is resized. | 154 | /// Invalidates pointers if this ArrayList is resized. |
| 156 | pub fn replaceRange(self: *Self, start: usize, len: usize, new_items: SliceConst) !void { | 155 | pub fn replaceRange(self: *Self, start: usize, len: usize, new_items: []const T) !void { |
| 157 | const after_range = start + len; | 156 | const after_range = start + len; |
| 158 | const range = self.items[start..after_range]; | 157 | const range = self.items[start..after_range]; |
| 159 | 158 | ||
| ... | @@ -220,14 +219,14 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { | ... | @@ -220,14 +219,14 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type { |
| 220 | 219 | ||
| 221 | /// Append the slice of items to the list. Allocates more | 220 | /// Append the slice of items to the list. Allocates more |
| 222 | /// memory as necessary. | 221 | /// memory as necessary. |
| 223 | pub fn appendSlice(self: *Self, items: SliceConst) !void { | 222 | pub fn appendSlice(self: *Self, items: []const T) !void { |
| 224 | try self.ensureUnusedCapacity(items.len); | 223 | try self.ensureUnusedCapacity(items.len); |
| 225 | self.appendSliceAssumeCapacity(items); | 224 | self.appendSliceAssumeCapacity(items); |
| 226 | } | 225 | } |
| 227 | 226 | ||
| 228 | /// Append the slice of items to the list, asserting the capacity is already | 227 | /// Append the slice of items to the list, asserting the capacity is already |
| 229 | /// enough to store the new items. **Does not** invalidate pointers. | 228 | /// enough to store the new items. **Does not** invalidate pointers. |
| 230 | pub fn appendSliceAssumeCapacity(self: *Self, items: SliceConst) void { | 229 | pub fn appendSliceAssumeCapacity(self: *Self, items: []const T) void { |
| 231 | const oldlen = self.items.len; | 230 | const oldlen = self.items.len; |
| 232 | const newlen = self.items.len + items.len; | 231 | const newlen = self.items.len + items.len; |
| 233 | self.items.len = newlen; | 232 | self.items.len = newlen; |
| ... | @@ -438,7 +437,6 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ | ... | @@ -438,7 +437,6 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 438 | capacity: usize = 0, | 437 | capacity: usize = 0, |
| 439 | 438 | ||
| 440 | pub const Slice = if (alignment) |a| ([]align(a) T) else []T; | 439 | pub const Slice = if (alignment) |a| ([]align(a) T) else []T; |
| 441 | pub const SliceConst = if (alignment) |a| ([]align(a) const T) else []const T; | ||
| 442 | 440 | ||
| 443 | /// Initialize with capacity to hold at least num elements. | 441 | /// Initialize with capacity to hold at least num elements. |
| 444 | /// Deinitialize with `deinit` or use `toOwnedSlice`. | 442 | /// Deinitialize with `deinit` or use `toOwnedSlice`. |
| ... | @@ -492,7 +490,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ | ... | @@ -492,7 +490,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 492 | /// Insert slice `items` at index `i`. Moves `list[i .. list.len]` to | 490 | /// Insert slice `items` at index `i`. Moves `list[i .. list.len]` to |
| 493 | /// higher indicices make room. | 491 | /// higher indicices make room. |
| 494 | /// This operation is O(N). | 492 | /// This operation is O(N). |
| 495 | pub fn insertSlice(self: *Self, allocator: *Allocator, i: usize, items: SliceConst) !void { | 493 | pub fn insertSlice(self: *Self, allocator: *Allocator, i: usize, items: []const T) !void { |
| 496 | try self.ensureUnusedCapacity(allocator, items.len); | 494 | try self.ensureUnusedCapacity(allocator, items.len); |
| 497 | self.items.len += items.len; | 495 | self.items.len += items.len; |
| 498 | 496 | ||
| ... | @@ -504,7 +502,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ | ... | @@ -504,7 +502,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 504 | /// Grows list if `len < new_items.len`. | 502 | /// Grows list if `len < new_items.len`. |
| 505 | /// Shrinks list if `len > new_items.len` | 503 | /// Shrinks list if `len > new_items.len` |
| 506 | /// Invalidates pointers if this ArrayList is resized. | 504 | /// Invalidates pointers if this ArrayList is resized. |
| 507 | pub fn replaceRange(self: *Self, allocator: *Allocator, start: usize, len: usize, new_items: SliceConst) !void { | 505 | pub fn replaceRange(self: *Self, allocator: *Allocator, start: usize, len: usize, new_items: []const T) !void { |
| 508 | var managed = self.toManaged(allocator); | 506 | var managed = self.toManaged(allocator); |
| 509 | try managed.replaceRange(start, len, new_items); | 507 | try managed.replaceRange(start, len, new_items); |
| 510 | self.* = managed.toUnmanaged(); | 508 | self.* = managed.toUnmanaged(); |
| ... | @@ -552,14 +550,14 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ | ... | @@ -552,14 +550,14 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ |
| 552 | 550 | ||
| 553 | /// Append the slice of items to the list. Allocates more | 551 | /// Append the slice of items to the list. Allocates more |
| 554 | /// memory as necessary. | 552 | /// memory as necessary. |
| 555 | pub fn appendSlice(self: *Self, allocator: *Allocator, items: SliceConst) !void { | 553 | pub fn appendSlice(self: *Self, allocator: *Allocator, items: []const T) !void { |
| 556 | try self.ensureUnusedCapacity(allocator, items.len); | 554 | try self.ensureUnusedCapacity(allocator, items.len); |
| 557 | self.appendSliceAssumeCapacity(items); | 555 | self.appendSliceAssumeCapacity(items); |
| 558 | } | 556 | } |
| 559 | 557 | ||
| 560 | /// Append the slice of items to the list, asserting the capacity is enough | 558 | /// Append the slice of items to the list, asserting the capacity is enough |
| 561 | /// to store the new items. | 559 | /// to store the new items. |
| 562 | pub fn appendSliceAssumeCapacity(self: *Self, items: SliceConst) void { | 560 | pub fn appendSliceAssumeCapacity(self: *Self, items: []const T) void { |
| 563 | const oldlen = self.items.len; | 561 | const oldlen = self.items.len; |
| 564 | const newlen = self.items.len + items.len; | 562 | const newlen = self.items.len + items.len; |
| 565 | 563 | ||
| ... | @@ -1150,15 +1148,31 @@ test "std.ArrayList/ArrayListUnmanaged: ArrayList(T) of struct T" { | ... | @@ -1150,15 +1148,31 @@ test "std.ArrayList/ArrayListUnmanaged: ArrayList(T) of struct T" { |
| 1150 | } | 1148 | } |
| 1151 | } | 1149 | } |
| 1152 | 1150 | ||
| 1153 | test "std.ArrayList(u8) implements writer" { | 1151 | test "std.ArrayList(u8)/ArrayListAligned implements writer" { |
| 1154 | var buffer = ArrayList(u8).init(std.testing.allocator); | 1152 | const a = testing.allocator; |
| 1155 | defer buffer.deinit(); | 1153 | |
| 1154 | { | ||
| 1155 | var buffer = ArrayList(u8).init(a); | ||
| 1156 | defer buffer.deinit(); | ||
| 1157 | |||
| 1158 | const x: i32 = 42; | ||
| 1159 | const y: i32 = 1234; | ||
| 1160 | try buffer.writer().print("x: {}\ny: {}\n", .{ x, y }); | ||
| 1156 | 1161 | ||
| 1157 | const x: i32 = 42; | 1162 | testing.expectEqualSlices(u8, "x: 42\ny: 1234\n", buffer.items); |
| 1158 | const y: i32 = 1234; | 1163 | } |
| 1159 | try buffer.writer().print("x: {}\ny: {}\n", .{ x, y }); | 1164 | { |
| 1165 | var list = ArrayListAligned(u8, 2).init(a); | ||
| 1166 | defer list.deinit(); | ||
| 1160 | 1167 | ||
| 1161 | testing.expectEqualSlices(u8, "x: 42\ny: 1234\n", buffer.items); | 1168 | const writer = list.writer(); |
| 1169 | try writer.writeAll("a"); | ||
| 1170 | try writer.writeAll("bc"); | ||
| 1171 | try writer.writeAll("d"); | ||
| 1172 | try writer.writeAll("efg"); | ||
| 1173 | |||
| 1174 | testing.expectEqualSlices(u8, list.items, "abcdefg"); | ||
| 1175 | } | ||
| 1162 | } | 1176 | } |
| 1163 | 1177 | ||
| 1164 | test "std.ArrayList/ArrayListUnmanaged.shrink still sets length on error.OutOfMemory" { | 1178 | test "std.ArrayList/ArrayListUnmanaged.shrink still sets length on error.OutOfMemory" { |
| ... | @@ -1189,18 +1203,6 @@ test "std.ArrayList/ArrayListUnmanaged.shrink still sets length on error.OutOfMe | ... | @@ -1189,18 +1203,6 @@ test "std.ArrayList/ArrayListUnmanaged.shrink still sets length on error.OutOfMe |
| 1189 | } | 1203 | } |
| 1190 | } | 1204 | } |
| 1191 | 1205 | ||
| 1192 | test "std.ArrayList.writer" { | ||
| 1193 | var list = ArrayList(u8).init(std.testing.allocator); | ||
| 1194 | defer list.deinit(); | ||
| 1195 | |||
| 1196 | const writer = list.writer(); | ||
| 1197 | try writer.writeAll("a"); | ||
| 1198 | try writer.writeAll("bc"); | ||
| 1199 | try writer.writeAll("d"); | ||
| 1200 | try writer.writeAll("efg"); | ||
| 1201 | testing.expectEqualSlices(u8, list.items, "abcdefg"); | ||
| 1202 | } | ||
| 1203 | |||
| 1204 | test "std.ArrayList/ArrayListUnmanaged.addManyAsArray" { | 1206 | test "std.ArrayList/ArrayListUnmanaged.addManyAsArray" { |
| 1205 | const a = std.testing.allocator; | 1207 | const a = std.testing.allocator; |
| 1206 | { | 1208 | { |
| ... | @@ -1248,3 +1250,27 @@ test "std.ArrayList/ArrayListUnmanaged.toOwnedSliceSentinel" { | ... | @@ -1248,3 +1250,27 @@ test "std.ArrayList/ArrayListUnmanaged.toOwnedSliceSentinel" { |
| 1248 | testing.expectEqualStrings(result, mem.spanZ(result.ptr)); | 1250 | testing.expectEqualStrings(result, mem.spanZ(result.ptr)); |
| 1249 | } | 1251 | } |
| 1250 | } | 1252 | } |
| 1253 | |||
| 1254 | test "ArrayListAligned/ArrayListAlignedUnmanaged accepts unaligned slices" { | ||
| 1255 | const a = testing.allocator; | ||
| 1256 | { | ||
| 1257 | var list = std.ArrayListAligned(u8, 8).init(a); | ||
| 1258 | defer list.deinit(); | ||
| 1259 | |||
| 1260 | try list.appendSlice(&.{ 0, 1, 2, 3 }); | ||
| 1261 | try list.insertSlice(2, &.{ 4, 5, 6, 7 }); | ||
| 1262 | try list.replaceRange(1, 3, &.{ 8, 9 }); | ||
| 1263 | |||
| 1264 | testing.expectEqualSlices(u8, list.items, &.{ 0, 8, 9, 6, 7, 2, 3 }); | ||
| 1265 | } | ||
| 1266 | { | ||
| 1267 | var list = std.ArrayListAlignedUnmanaged(u8, 8){}; | ||
| 1268 | defer list.deinit(a); | ||
| 1269 | |||
| 1270 | try list.appendSlice(a, &.{ 0, 1, 2, 3 }); | ||
| 1271 | try list.insertSlice(a, 2, &.{ 4, 5, 6, 7 }); | ||
| 1272 | try list.replaceRange(a, 1, 3, &.{ 8, 9 }); | ||
| 1273 | |||
| 1274 | testing.expectEqualSlices(u8, list.items, &.{ 0, 8, 9, 6, 7, 2, 3 }); | ||
| 1275 | } | ||
| 1276 | } |
lib/std/build/run.zig+7| ... | @@ -191,6 +191,13 @@ pub const RunStep = struct { | ... | @@ -191,6 +191,13 @@ pub const RunStep = struct { |
| 191 | child.stdout_behavior = stdIoActionToBehavior(self.stdout_action); | 191 | child.stdout_behavior = stdIoActionToBehavior(self.stdout_action); |
| 192 | child.stderr_behavior = stdIoActionToBehavior(self.stderr_action); | 192 | child.stderr_behavior = stdIoActionToBehavior(self.stderr_action); |
| 193 | 193 | ||
| 194 | if (self.builder.verbose) { | ||
| 195 | for (argv) |arg| { | ||
| 196 | warn("{s} ", .{arg}); | ||
| 197 | } | ||
| 198 | warn("\n", .{}); | ||
| 199 | } | ||
| 200 | |||
| 194 | child.spawn() catch |err| { | 201 | child.spawn() catch |err| { |
| 195 | warn("Unable to spawn {s}: {s}\n", .{ argv[0], @errorName(err) }); | 202 | warn("Unable to spawn {s}: {s}\n", .{ argv[0], @errorName(err) }); |
| 196 | return err; | 203 | return err; |
lib/std/builtin.zig+1-1| ... | @@ -166,7 +166,7 @@ pub const CallingConvention = enum { | ... | @@ -166,7 +166,7 @@ pub const CallingConvention = enum { |
| 166 | APCS, | 166 | APCS, |
| 167 | AAPCS, | 167 | AAPCS, |
| 168 | AAPCSVFP, | 168 | AAPCSVFP, |
| 169 | SysV | 169 | SysV, |
| 170 | }; | 170 | }; |
| 171 | 171 | ||
| 172 | /// This data structure is used by the Zig language code generation and | 172 | /// This data structure is used by the Zig language code generation and |
lib/std/c.zig-2| ... | @@ -10,8 +10,6 @@ const page_size = std.mem.page_size; | ... | @@ -10,8 +10,6 @@ const page_size = std.mem.page_size; |
| 10 | pub const tokenizer = @import("c/tokenizer.zig"); | 10 | pub const tokenizer = @import("c/tokenizer.zig"); |
| 11 | pub const Token = tokenizer.Token; | 11 | pub const Token = tokenizer.Token; |
| 12 | pub const Tokenizer = tokenizer.Tokenizer; | 12 | pub const Tokenizer = tokenizer.Tokenizer; |
| 13 | pub const parse = @import("c/parse.zig").parse; | ||
| 14 | pub const ast = @import("c/ast.zig"); | ||
| 15 | pub const builtins = @import("c/builtins.zig"); | 13 | pub const builtins = @import("c/builtins.zig"); |
| 16 | 14 | ||
| 17 | test { | 15 | test { |
lib/std/c/ast.zig deleted-678| ... | @@ -1,678 +0,0 @@ | ||
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2021 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 6 | const std = @import("std"); | ||
| 7 | const ArrayList = std.ArrayList; | ||
| 8 | const Token = std.c.Token; | ||
| 9 | const Source = std.c.tokenizer.Source; | ||
| 10 | |||
| 11 | pub const TokenIndex = usize; | ||
| 12 | |||
| 13 | pub const Tree = struct { | ||
| 14 | tokens: []Token, | ||
| 15 | sources: []Source, | ||
| 16 | root_node: *Node.Root, | ||
| 17 | arena_state: std.heap.ArenaAllocator.State, | ||
| 18 | gpa: *mem.Allocator, | ||
| 19 | msgs: []Msg, | ||
| 20 | |||
| 21 | pub fn deinit(self: *Tree) void { | ||
| 22 | self.arena_state.promote(self.gpa).deinit(); | ||
| 23 | } | ||
| 24 | |||
| 25 | pub fn tokenSlice(tree: *Tree, token: TokenIndex) []const u8 { | ||
| 26 | return tree.tokens.at(token).slice(); | ||
| 27 | } | ||
| 28 | |||
| 29 | pub fn tokenEql(tree: *Tree, a: TokenIndex, b: TokenIndex) bool { | ||
| 30 | const atok = tree.tokens.at(a); | ||
| 31 | const btok = tree.tokens.at(b); | ||
| 32 | return atok.eql(btok.*); | ||
| 33 | } | ||
| 34 | }; | ||
| 35 | |||
| 36 | pub const Msg = struct { | ||
| 37 | kind: enum { | ||
| 38 | Error, | ||
| 39 | Warning, | ||
| 40 | Note, | ||
| 41 | }, | ||
| 42 | inner: Error, | ||
| 43 | }; | ||
| 44 | |||
| 45 | pub const Error = union(enum) { | ||
| 46 | InvalidToken: SingleTokenError("invalid token '{}'"), | ||
| 47 | ExpectedToken: ExpectedToken, | ||
| 48 | ExpectedExpr: SingleTokenError("expected expression, found '{}'"), | ||
| 49 | ExpectedTypeName: SingleTokenError("expected type name, found '{}'"), | ||
| 50 | ExpectedFnBody: SingleTokenError("expected function body, found '{}'"), | ||
| 51 | ExpectedDeclarator: SingleTokenError("expected declarator, found '{}'"), | ||
| 52 | ExpectedInitializer: SingleTokenError("expected initializer, found '{}'"), | ||
| 53 | ExpectedEnumField: SingleTokenError("expected enum field, found '{}'"), | ||
| 54 | ExpectedType: SingleTokenError("expected enum field, found '{}'"), | ||
| 55 | InvalidTypeSpecifier: InvalidTypeSpecifier, | ||
| 56 | InvalidStorageClass: SingleTokenError("invalid storage class, found '{}'"), | ||
| 57 | InvalidDeclarator: SimpleError("invalid declarator"), | ||
| 58 | DuplicateQualifier: SingleTokenError("duplicate type qualifier '{}'"), | ||
| 59 | DuplicateSpecifier: SingleTokenError("duplicate declaration specifier '{}'"), | ||
| 60 | MustUseKwToRefer: MustUseKwToRefer, | ||
| 61 | FnSpecOnNonFn: SingleTokenError("function specifier '{}' on non function"), | ||
| 62 | NothingDeclared: SimpleError("declaration doesn't declare anything"), | ||
| 63 | QualifierIgnored: SingleTokenError("qualifier '{}' ignored"), | ||
| 64 | |||
| 65 | pub fn render(self: *const Error, tree: *Tree, stream: anytype) !void { | ||
| 66 | switch (self.*) { | ||
| 67 | .InvalidToken => |*x| return x.render(tree, stream), | ||
| 68 | .ExpectedToken => |*x| return x.render(tree, stream), | ||
| 69 | .ExpectedExpr => |*x| return x.render(tree, stream), | ||
| 70 | .ExpectedTypeName => |*x| return x.render(tree, stream), | ||
| 71 | .ExpectedDeclarator => |*x| return x.render(tree, stream), | ||
| 72 | .ExpectedFnBody => |*x| return x.render(tree, stream), | ||
| 73 | .ExpectedInitializer => |*x| return x.render(tree, stream), | ||
| 74 | .ExpectedEnumField => |*x| return x.render(tree, stream), | ||
| 75 | .ExpectedType => |*x| return x.render(tree, stream), | ||
| 76 | .InvalidTypeSpecifier => |*x| return x.render(tree, stream), | ||
| 77 | .InvalidStorageClass => |*x| return x.render(tree, stream), | ||
| 78 | .InvalidDeclarator => |*x| return x.render(tree, stream), | ||
| 79 | .DuplicateQualifier => |*x| return x.render(tree, stream), | ||
| 80 | .DuplicateSpecifier => |*x| return x.render(tree, stream), | ||
| 81 | .MustUseKwToRefer => |*x| return x.render(tree, stream), | ||
| 82 | .FnSpecOnNonFn => |*x| return x.render(tree, stream), | ||
| 83 | .NothingDeclared => |*x| return x.render(tree, stream), | ||
| 84 | .QualifierIgnored => |*x| return x.render(tree, stream), | ||
| 85 | } | ||
| 86 | } | ||
| 87 | |||
| 88 | pub fn loc(self: *const Error) TokenIndex { | ||
| 89 | switch (self.*) { | ||
| 90 | .InvalidToken => |x| return x.token, | ||
| 91 | .ExpectedToken => |x| return x.token, | ||
| 92 | .ExpectedExpr => |x| return x.token, | ||
| 93 | .ExpectedTypeName => |x| return x.token, | ||
| 94 | .ExpectedDeclarator => |x| return x.token, | ||
| 95 | .ExpectedFnBody => |x| return x.token, | ||
| 96 | .ExpectedInitializer => |x| return x.token, | ||
| 97 | .ExpectedEnumField => |x| return x.token, | ||
| 98 | .ExpectedType => |*x| return x.token, | ||
| 99 | .InvalidTypeSpecifier => |x| return x.token, | ||
| 100 | .InvalidStorageClass => |x| return x.token, | ||
| 101 | .InvalidDeclarator => |x| return x.token, | ||
| 102 | .DuplicateQualifier => |x| return x.token, | ||
| 103 | .DuplicateSpecifier => |x| return x.token, | ||
| 104 | .MustUseKwToRefer => |*x| return x.name, | ||
| 105 | .FnSpecOnNonFn => |*x| return x.name, | ||
| 106 | .NothingDeclared => |*x| return x.name, | ||
| 107 | .QualifierIgnored => |*x| return x.name, | ||
| 108 | } | ||
| 109 | } | ||
| 110 | |||
| 111 | pub const ExpectedToken = struct { | ||
| 112 | token: TokenIndex, | ||
| 113 | expected_id: std.meta.Tag(Token.Id), | ||
| 114 | |||
| 115 | pub fn render(self: *const ExpectedToken, tree: *Tree, stream: anytype) !void { | ||
| 116 | const found_token = tree.tokens.at(self.token); | ||
| 117 | if (found_token.id == .Invalid) { | ||
| 118 | return stream.print("expected '{s}', found invalid bytes", .{self.expected_id.symbol()}); | ||
| 119 | } else { | ||
| 120 | const token_name = found_token.id.symbol(); | ||
| 121 | return stream.print("expected '{s}', found '{s}'", .{ self.expected_id.symbol(), token_name }); | ||
| 122 | } | ||
| 123 | } | ||
| 124 | }; | ||
| 125 | |||
| 126 | pub const InvalidTypeSpecifier = struct { | ||
| 127 | token: TokenIndex, | ||
| 128 | type_spec: *Node.TypeSpec, | ||
| 129 | |||
| 130 | pub fn render(self: *const ExpectedToken, tree: *Tree, stream: anytype) !void { | ||
| 131 | try stream.write("invalid type specifier '"); | ||
| 132 | try type_spec.spec.print(tree, stream); | ||
| 133 | const token_name = tree.tokens.at(self.token).id.symbol(); | ||
| 134 | return stream.print("{s}'", .{token_name}); | ||
| 135 | } | ||
| 136 | }; | ||
| 137 | |||
| 138 | pub const MustUseKwToRefer = struct { | ||
| 139 | kw: TokenIndex, | ||
| 140 | name: TokenIndex, | ||
| 141 | |||
| 142 | pub fn render(self: *const ExpectedToken, tree: *Tree, stream: anytype) !void { | ||
| 143 | return stream.print("must use '{s}' tag to refer to type '{s}'", .{ tree.slice(kw), tree.slice(name) }); | ||
| 144 | } | ||
| 145 | }; | ||
| 146 | |||
| 147 | fn SingleTokenError(comptime msg: []const u8) type { | ||
| 148 | return struct { | ||
| 149 | token: TokenIndex, | ||
| 150 | |||
| 151 | pub fn render(self: *const @This(), tree: *Tree, stream: anytype) !void { | ||
| 152 | const actual_token = tree.tokens.at(self.token); | ||
| 153 | return stream.print(msg, .{actual_token.id.symbol()}); | ||
| 154 | } | ||
| 155 | }; | ||
| 156 | } | ||
| 157 | |||
| 158 | fn SimpleError(comptime msg: []const u8) type { | ||
| 159 | return struct { | ||
| 160 | const ThisError = @This(); | ||
| 161 | |||
| 162 | token: TokenIndex, | ||
| 163 | |||
| 164 | pub fn render(self: *const ThisError, tokens: *Tree.TokenList, stream: anytype) !void { | ||
| 165 | return stream.write(msg); | ||
| 166 | } | ||
| 167 | }; | ||
| 168 | } | ||
| 169 | }; | ||
| 170 | |||
| 171 | pub const Type = struct { | ||
| 172 | pub const TypeList = ArrayList(*Type); | ||
| 173 | |||
| 174 | @"const": bool = false, | ||
| 175 | atomic: bool = false, | ||
| 176 | @"volatile": bool = false, | ||
| 177 | restrict: bool = false, | ||
| 178 | |||
| 179 | id: union(enum) { | ||
| 180 | Int: struct { | ||
| 181 | id: Id, | ||
| 182 | is_signed: bool, | ||
| 183 | |||
| 184 | pub const Id = enum { | ||
| 185 | Char, | ||
| 186 | Short, | ||
| 187 | Int, | ||
| 188 | Long, | ||
| 189 | LongLong, | ||
| 190 | }; | ||
| 191 | }, | ||
| 192 | Float: struct { | ||
| 193 | id: Id, | ||
| 194 | |||
| 195 | pub const Id = enum { | ||
| 196 | Float, | ||
| 197 | Double, | ||
| 198 | LongDouble, | ||
| 199 | }; | ||
| 200 | }, | ||
| 201 | Pointer: *Type, | ||
| 202 | Function: struct { | ||
| 203 | return_type: *Type, | ||
| 204 | param_types: TypeList, | ||
| 205 | }, | ||
| 206 | Typedef: *Type, | ||
| 207 | Record: *Node.RecordType, | ||
| 208 | Enum: *Node.EnumType, | ||
| 209 | |||
| 210 | /// Special case for macro parameters that can be any type. | ||
| 211 | /// Only present if `retain_macros == true`. | ||
| 212 | Macro, | ||
| 213 | }, | ||
| 214 | }; | ||
| 215 | |||
| 216 | pub const Node = struct { | ||
| 217 | id: Id, | ||
| 218 | |||
| 219 | pub const Id = enum { | ||
| 220 | Root, | ||
| 221 | EnumField, | ||
| 222 | RecordField, | ||
| 223 | RecordDeclarator, | ||
| 224 | JumpStmt, | ||
| 225 | ExprStmt, | ||
| 226 | LabeledStmt, | ||
| 227 | CompoundStmt, | ||
| 228 | IfStmt, | ||
| 229 | SwitchStmt, | ||
| 230 | WhileStmt, | ||
| 231 | DoStmt, | ||
| 232 | ForStmt, | ||
| 233 | StaticAssert, | ||
| 234 | Declarator, | ||
| 235 | Pointer, | ||
| 236 | FnDecl, | ||
| 237 | Typedef, | ||
| 238 | VarDecl, | ||
| 239 | }; | ||
| 240 | |||
| 241 | pub const Root = struct { | ||
| 242 | base: Node = Node{ .id = .Root }, | ||
| 243 | decls: DeclList, | ||
| 244 | eof: TokenIndex, | ||
| 245 | |||
| 246 | pub const DeclList = ArrayList(*Node); | ||
| 247 | }; | ||
| 248 | |||
| 249 | pub const DeclSpec = struct { | ||
| 250 | storage_class: union(enum) { | ||
| 251 | Auto: TokenIndex, | ||
| 252 | Extern: TokenIndex, | ||
| 253 | Register: TokenIndex, | ||
| 254 | Static: TokenIndex, | ||
| 255 | Typedef: TokenIndex, | ||
| 256 | None, | ||
| 257 | } = .None, | ||
| 258 | thread_local: ?TokenIndex = null, | ||
| 259 | type_spec: TypeSpec = TypeSpec{}, | ||
| 260 | fn_spec: union(enum) { | ||
| 261 | Inline: TokenIndex, | ||
| 262 | Noreturn: TokenIndex, | ||
| 263 | None, | ||
| 264 | } = .None, | ||
| 265 | align_spec: ?struct { | ||
| 266 | alignas: TokenIndex, | ||
| 267 | expr: *Node, | ||
| 268 | rparen: TokenIndex, | ||
| 269 | } = null, | ||
| 270 | }; | ||
| 271 | |||
| 272 | pub const TypeSpec = struct { | ||
| 273 | qual: TypeQual = TypeQual{}, | ||
| 274 | spec: union(enum) { | ||
| 275 | /// error or default to int | ||
| 276 | None, | ||
| 277 | Void: TokenIndex, | ||
| 278 | Char: struct { | ||
| 279 | sign: ?TokenIndex = null, | ||
| 280 | char: TokenIndex, | ||
| 281 | }, | ||
| 282 | Short: struct { | ||
| 283 | sign: ?TokenIndex = null, | ||
| 284 | short: TokenIndex = null, | ||
| 285 | int: ?TokenIndex = null, | ||
| 286 | }, | ||
| 287 | Int: struct { | ||
| 288 | sign: ?TokenIndex = null, | ||
| 289 | int: ?TokenIndex = null, | ||
| 290 | }, | ||
| 291 | Long: struct { | ||
| 292 | sign: ?TokenIndex = null, | ||
| 293 | long: TokenIndex, | ||
| 294 | longlong: ?TokenIndex = null, | ||
| 295 | int: ?TokenIndex = null, | ||
| 296 | }, | ||
| 297 | Float: struct { | ||
| 298 | float: TokenIndex, | ||
| 299 | complex: ?TokenIndex = null, | ||
| 300 | }, | ||
| 301 | Double: struct { | ||
| 302 | long: ?TokenIndex = null, | ||
| 303 | double: ?TokenIndex, | ||
| 304 | complex: ?TokenIndex = null, | ||
| 305 | }, | ||
| 306 | Bool: TokenIndex, | ||
| 307 | Atomic: struct { | ||
| 308 | atomic: TokenIndex, | ||
| 309 | typename: *Node, | ||
| 310 | rparen: TokenIndex, | ||
| 311 | }, | ||
| 312 | Enum: *EnumType, | ||
| 313 | Record: *RecordType, | ||
| 314 | Typedef: struct { | ||
| 315 | sym: TokenIndex, | ||
| 316 | sym_type: *Type, | ||
| 317 | }, | ||
| 318 | |||
| 319 | pub fn print(self: *@This(), self: *const @This(), tree: *Tree, stream: anytype) !void { | ||
| 320 | switch (self.spec) { | ||
| 321 | .None => unreachable, | ||
| 322 | .Void => |index| try stream.write(tree.slice(index)), | ||
| 323 | .Char => |char| { | ||
| 324 | if (char.sign) |s| { | ||
| 325 | try stream.write(tree.slice(s)); | ||
| 326 | try stream.writeByte(' '); | ||
| 327 | } | ||
| 328 | try stream.write(tree.slice(char.char)); | ||
| 329 | }, | ||
| 330 | .Short => |short| { | ||
| 331 | if (short.sign) |s| { | ||
| 332 | try stream.write(tree.slice(s)); | ||
| 333 | try stream.writeByte(' '); | ||
| 334 | } | ||
| 335 | try stream.write(tree.slice(short.short)); | ||
| 336 | if (short.int) |i| { | ||
| 337 | try stream.writeByte(' '); | ||
| 338 | try stream.write(tree.slice(i)); | ||
| 339 | } | ||
| 340 | }, | ||
| 341 | .Int => |int| { | ||
| 342 | if (int.sign) |s| { | ||
| 343 | try stream.write(tree.slice(s)); | ||
| 344 | try stream.writeByte(' '); | ||
| 345 | } | ||
| 346 | if (int.int) |i| { | ||
| 347 | try stream.writeByte(' '); | ||
| 348 | try stream.write(tree.slice(i)); | ||
| 349 | } | ||
| 350 | }, | ||
| 351 | .Long => |long| { | ||
| 352 | if (long.sign) |s| { | ||
| 353 | try stream.write(tree.slice(s)); | ||
| 354 | try stream.writeByte(' '); | ||
| 355 | } | ||
| 356 | try stream.write(tree.slice(long.long)); | ||
| 357 | if (long.longlong) |l| { | ||
| 358 | try stream.writeByte(' '); | ||
| 359 | try stream.write(tree.slice(l)); | ||
| 360 | } | ||
| 361 | if (long.int) |i| { | ||
| 362 | try stream.writeByte(' '); | ||
| 363 | try stream.write(tree.slice(i)); | ||
| 364 | } | ||
| 365 | }, | ||
| 366 | .Float => |float| { | ||
| 367 | try stream.write(tree.slice(float.float)); | ||
| 368 | if (float.complex) |c| { | ||
| 369 | try stream.writeByte(' '); | ||
| 370 | try stream.write(tree.slice(c)); | ||
| 371 | } | ||
| 372 | }, | ||
| 373 | .Double => |double| { | ||
| 374 | if (double.long) |l| { | ||
| 375 | try stream.write(tree.slice(l)); | ||
| 376 | try stream.writeByte(' '); | ||
| 377 | } | ||
| 378 | try stream.write(tree.slice(double.double)); | ||
| 379 | if (double.complex) |c| { | ||
| 380 | try stream.writeByte(' '); | ||
| 381 | try stream.write(tree.slice(c)); | ||
| 382 | } | ||
| 383 | }, | ||
| 384 | .Bool => |index| try stream.write(tree.slice(index)), | ||
| 385 | .Typedef => |typedef| try stream.write(tree.slice(typedef.sym)), | ||
| 386 | else => try stream.print("TODO print {}", self.spec), | ||
| 387 | } | ||
| 388 | } | ||
| 389 | } = .None, | ||
| 390 | }; | ||
| 391 | |||
| 392 | pub const EnumType = struct { | ||
| 393 | tok: TokenIndex, | ||
| 394 | name: ?TokenIndex, | ||
| 395 | body: ?struct { | ||
| 396 | lbrace: TokenIndex, | ||
| 397 | |||
| 398 | /// always EnumField | ||
| 399 | fields: FieldList, | ||
| 400 | rbrace: TokenIndex, | ||
| 401 | }, | ||
| 402 | |||
| 403 | pub const FieldList = Root.DeclList; | ||
| 404 | }; | ||
| 405 | |||
| 406 | pub const EnumField = struct { | ||
| 407 | base: Node = Node{ .id = .EnumField }, | ||
| 408 | name: TokenIndex, | ||
| 409 | value: ?*Node, | ||
| 410 | }; | ||
| 411 | |||
| 412 | pub const RecordType = struct { | ||
| 413 | tok: TokenIndex, | ||
| 414 | kind: enum { | ||
| 415 | Struct, | ||
| 416 | Union, | ||
| 417 | }, | ||
| 418 | name: ?TokenIndex, | ||
| 419 | body: ?struct { | ||
| 420 | lbrace: TokenIndex, | ||
| 421 | |||
| 422 | /// RecordField or StaticAssert | ||
| 423 | fields: FieldList, | ||
| 424 | rbrace: TokenIndex, | ||
| 425 | }, | ||
| 426 | |||
| 427 | pub const FieldList = Root.DeclList; | ||
| 428 | }; | ||
| 429 | |||
| 430 | pub const RecordField = struct { | ||
| 431 | base: Node = Node{ .id = .RecordField }, | ||
| 432 | type_spec: TypeSpec, | ||
| 433 | declarators: DeclaratorList, | ||
| 434 | semicolon: TokenIndex, | ||
| 435 | |||
| 436 | pub const DeclaratorList = Root.DeclList; | ||
| 437 | }; | ||
| 438 | |||
| 439 | pub const RecordDeclarator = struct { | ||
| 440 | base: Node = Node{ .id = .RecordDeclarator }, | ||
| 441 | declarator: ?*Declarator, | ||
| 442 | bit_field_expr: ?*Expr, | ||
| 443 | }; | ||
| 444 | |||
| 445 | pub const TypeQual = struct { | ||
| 446 | @"const": ?TokenIndex = null, | ||
| 447 | atomic: ?TokenIndex = null, | ||
| 448 | @"volatile": ?TokenIndex = null, | ||
| 449 | restrict: ?TokenIndex = null, | ||
| 450 | }; | ||
| 451 | |||
| 452 | pub const JumpStmt = struct { | ||
| 453 | base: Node = Node{ .id = .JumpStmt }, | ||
| 454 | ltoken: TokenIndex, | ||
| 455 | kind: union(enum) { | ||
| 456 | Break, | ||
| 457 | Continue, | ||
| 458 | Return: ?*Node, | ||
| 459 | Goto: TokenIndex, | ||
| 460 | }, | ||
| 461 | semicolon: TokenIndex, | ||
| 462 | }; | ||
| 463 | |||
| 464 | pub const ExprStmt = struct { | ||
| 465 | base: Node = Node{ .id = .ExprStmt }, | ||
| 466 | expr: ?*Expr, | ||
| 467 | semicolon: TokenIndex, | ||
| 468 | }; | ||
| 469 | |||
| 470 | pub const LabeledStmt = struct { | ||
| 471 | base: Node = Node{ .id = .LabeledStmt }, | ||
| 472 | kind: union(enum) { | ||
| 473 | Label: TokenIndex, | ||
| 474 | Case: TokenIndex, | ||
| 475 | Default: TokenIndex, | ||
| 476 | }, | ||
| 477 | stmt: *Node, | ||
| 478 | }; | ||
| 479 | |||
| 480 | pub const CompoundStmt = struct { | ||
| 481 | base: Node = Node{ .id = .CompoundStmt }, | ||
| 482 | lbrace: TokenIndex, | ||
| 483 | statements: StmtList, | ||
| 484 | rbrace: TokenIndex, | ||
| 485 | |||
| 486 | pub const StmtList = Root.DeclList; | ||
| 487 | }; | ||
| 488 | |||
| 489 | pub const IfStmt = struct { | ||
| 490 | base: Node = Node{ .id = .IfStmt }, | ||
| 491 | @"if": TokenIndex, | ||
| 492 | cond: *Node, | ||
| 493 | body: *Node, | ||
| 494 | @"else": ?struct { | ||
| 495 | tok: TokenIndex, | ||
| 496 | body: *Node, | ||
| 497 | }, | ||
| 498 | }; | ||
| 499 | |||
| 500 | pub const SwitchStmt = struct { | ||
| 501 | base: Node = Node{ .id = .SwitchStmt }, | ||
| 502 | @"switch": TokenIndex, | ||
| 503 | expr: *Expr, | ||
| 504 | rparen: TokenIndex, | ||
| 505 | stmt: *Node, | ||
| 506 | }; | ||
| 507 | |||
| 508 | pub const WhileStmt = struct { | ||
| 509 | base: Node = Node{ .id = .WhileStmt }, | ||
| 510 | @"while": TokenIndex, | ||
| 511 | cond: *Expr, | ||
| 512 | rparen: TokenIndex, | ||
| 513 | body: *Node, | ||
| 514 | }; | ||
| 515 | |||
| 516 | pub const DoStmt = struct { | ||
| 517 | base: Node = Node{ .id = .DoStmt }, | ||
| 518 | do: TokenIndex, | ||
| 519 | body: *Node, | ||
| 520 | @"while": TokenIndex, | ||
| 521 | cond: *Expr, | ||
| 522 | semicolon: TokenIndex, | ||
| 523 | }; | ||
| 524 | |||
| 525 | pub const ForStmt = struct { | ||
| 526 | base: Node = Node{ .id = .ForStmt }, | ||
| 527 | @"for": TokenIndex, | ||
| 528 | init: ?*Node, | ||
| 529 | cond: ?*Expr, | ||
| 530 | semicolon: TokenIndex, | ||
| 531 | incr: ?*Expr, | ||
| 532 | rparen: TokenIndex, | ||
| 533 | body: *Node, | ||
| 534 | }; | ||
| 535 | |||
| 536 | pub const StaticAssert = struct { | ||
| 537 | base: Node = Node{ .id = .StaticAssert }, | ||
| 538 | assert: TokenIndex, | ||
| 539 | expr: *Node, | ||
| 540 | semicolon: TokenIndex, | ||
| 541 | }; | ||
| 542 | |||
| 543 | pub const Declarator = struct { | ||
| 544 | base: Node = Node{ .id = .Declarator }, | ||
| 545 | pointer: ?*Pointer, | ||
| 546 | prefix: union(enum) { | ||
| 547 | None, | ||
| 548 | Identifer: TokenIndex, | ||
| 549 | Complex: struct { | ||
| 550 | lparen: TokenIndex, | ||
| 551 | inner: *Node, | ||
| 552 | rparen: TokenIndex, | ||
| 553 | }, | ||
| 554 | }, | ||
| 555 | suffix: union(enum) { | ||
| 556 | None, | ||
| 557 | Fn: struct { | ||
| 558 | lparen: TokenIndex, | ||
| 559 | params: Params, | ||
| 560 | rparen: TokenIndex, | ||
| 561 | }, | ||
| 562 | Array: Arrays, | ||
| 563 | }, | ||
| 564 | |||
| 565 | pub const Arrays = ArrayList(*Array); | ||
| 566 | pub const Params = ArrayList(*Param); | ||
| 567 | }; | ||
| 568 | |||
| 569 | pub const Array = struct { | ||
| 570 | lbracket: TokenIndex, | ||
| 571 | inner: union(enum) { | ||
| 572 | Inferred, | ||
| 573 | Unspecified: TokenIndex, | ||
| 574 | Variable: struct { | ||
| 575 | asterisk: ?TokenIndex, | ||
| 576 | static: ?TokenIndex, | ||
| 577 | qual: TypeQual, | ||
| 578 | expr: *Expr, | ||
| 579 | }, | ||
| 580 | }, | ||
| 581 | rbracket: TokenIndex, | ||
| 582 | }; | ||
| 583 | |||
| 584 | pub const Pointer = struct { | ||
| 585 | base: Node = Node{ .id = .Pointer }, | ||
| 586 | asterisk: TokenIndex, | ||
| 587 | qual: TypeQual, | ||
| 588 | pointer: ?*Pointer, | ||
| 589 | }; | ||
| 590 | |||
| 591 | pub const Param = struct { | ||
| 592 | kind: union(enum) { | ||
| 593 | Variable, | ||
| 594 | Old: TokenIndex, | ||
| 595 | Normal: struct { | ||
| 596 | decl_spec: *DeclSpec, | ||
| 597 | declarator: *Node, | ||
| 598 | }, | ||
| 599 | }, | ||
| 600 | }; | ||
| 601 | |||
| 602 | pub const FnDecl = struct { | ||
| 603 | base: Node = Node{ .id = .FnDecl }, | ||
| 604 | decl_spec: DeclSpec, | ||
| 605 | declarator: *Declarator, | ||
| 606 | old_decls: OldDeclList, | ||
| 607 | body: ?*CompoundStmt, | ||
| 608 | |||
| 609 | pub const OldDeclList = ArrayList(*Node); | ||
| 610 | }; | ||
| 611 | |||
| 612 | pub const Typedef = struct { | ||
| 613 | base: Node = Node{ .id = .Typedef }, | ||
| 614 | decl_spec: DeclSpec, | ||
| 615 | declarators: DeclaratorList, | ||
| 616 | semicolon: TokenIndex, | ||
| 617 | |||
| 618 | pub const DeclaratorList = Root.DeclList; | ||
| 619 | }; | ||
| 620 | |||
| 621 | pub const VarDecl = struct { | ||
| 622 | base: Node = Node{ .id = .VarDecl }, | ||
| 623 | decl_spec: DeclSpec, | ||
| 624 | initializers: Initializers, | ||
| 625 | semicolon: TokenIndex, | ||
| 626 | |||
| 627 | pub const Initializers = Root.DeclList; | ||
| 628 | }; | ||
| 629 | |||
| 630 | pub const Initialized = struct { | ||
| 631 | base: Node = Node{ .id = Initialized }, | ||
| 632 | declarator: *Declarator, | ||
| 633 | eq: TokenIndex, | ||
| 634 | init: Initializer, | ||
| 635 | }; | ||
| 636 | |||
| 637 | pub const Initializer = union(enum) { | ||
| 638 | list: struct { | ||
| 639 | initializers: List, | ||
| 640 | rbrace: TokenIndex, | ||
| 641 | }, | ||
| 642 | expr: *Expr, | ||
| 643 | |||
| 644 | pub const List = ArrayList(*Initializer); | ||
| 645 | }; | ||
| 646 | |||
| 647 | pub const Macro = struct { | ||
| 648 | base: Node = Node{ .id = Macro }, | ||
| 649 | kind: union(enum) { | ||
| 650 | Undef: []const u8, | ||
| 651 | Fn: struct { | ||
| 652 | params: []const []const u8, | ||
| 653 | expr: *Expr, | ||
| 654 | }, | ||
| 655 | Expr: *Expr, | ||
| 656 | }, | ||
| 657 | }; | ||
| 658 | }; | ||
| 659 | |||
| 660 | pub const Expr = struct { | ||
| 661 | id: Id, | ||
| 662 | ty: *Type, | ||
| 663 | value: union(enum) { | ||
| 664 | None, | ||
| 665 | }, | ||
| 666 | |||
| 667 | pub const Id = enum { | ||
| 668 | Infix, | ||
| 669 | Literal, | ||
| 670 | }; | ||
| 671 | |||
| 672 | pub const Infix = struct { | ||
| 673 | base: Expr = Expr{ .id = .Infix }, | ||
| 674 | lhs: *Expr, | ||
| 675 | op_token: TokenIndex, | ||
| 676 | rhs: *Expr, | ||
| 677 | }; | ||
| 678 | }; | ||
lib/std/c/parse.zig deleted-1434| ... | @@ -1,1434 +0,0 @@ | ||
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2021 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 6 | const std = @import("std"); | ||
| 7 | const mem = std.mem; | ||
| 8 | const assert = std.debug.assert; | ||
| 9 | const Allocator = std.mem.Allocator; | ||
| 10 | const ast = std.c.ast; | ||
| 11 | const Node = ast.Node; | ||
| 12 | const Type = ast.Type; | ||
| 13 | const Tree = ast.Tree; | ||
| 14 | const TokenIndex = ast.TokenIndex; | ||
| 15 | const Token = std.c.Token; | ||
| 16 | const TokenIterator = ast.Tree.TokenList.Iterator; | ||
| 17 | |||
| 18 | pub const Error = error{ParseError} || Allocator.Error; | ||
| 19 | |||
| 20 | pub const Options = struct { | ||
| 21 | // /// Keep simple macros unexpanded and add the definitions to the ast | ||
| 22 | // retain_macros: bool = false, | ||
| 23 | /// Warning or error | ||
| 24 | warn_as_err: union(enum) { | ||
| 25 | /// All warnings are warnings | ||
| 26 | None, | ||
| 27 | |||
| 28 | /// Some warnings are errors | ||
| 29 | Some: []std.meta.Tag(ast.Error), | ||
| 30 | |||
| 31 | /// All warnings are errors | ||
| 32 | All, | ||
| 33 | } = .All, | ||
| 34 | }; | ||
| 35 | |||
| 36 | /// Result should be freed with tree.deinit() when there are | ||
| 37 | /// no more references to any of the tokens or nodes. | ||
| 38 | pub fn parse(allocator: *Allocator, source: []const u8, options: Options) !*Tree { | ||
| 39 | const tree = blk: { | ||
| 40 | // This block looks unnecessary, but is a "foot-shield" to prevent the SegmentedLists | ||
| 41 | // from being initialized with a pointer to this `arena`, which is created on | ||
| 42 | // the stack. Following code should instead refer to `&tree.arena_allocator`, a | ||
| 43 | // pointer to data which lives safely on the heap and will outlive `parse`. | ||
| 44 | var arena = std.heap.ArenaAllocator.init(allocator); | ||
| 45 | errdefer arena.deinit(); | ||
| 46 | const tree = try arena.allocator.create(ast.Tree); | ||
| 47 | tree.* = .{ | ||
| 48 | .root_node = undefined, | ||
| 49 | .arena_allocator = arena, | ||
| 50 | .tokens = undefined, | ||
| 51 | .sources = undefined, | ||
| 52 | }; | ||
| 53 | break :blk tree; | ||
| 54 | }; | ||
| 55 | errdefer tree.deinit(); | ||
| 56 | const arena = &tree.arena_allocator.allocator; | ||
| 57 | |||
| 58 | tree.tokens = ast.Tree.TokenList.init(arena); | ||
| 59 | tree.sources = ast.Tree.SourceList.init(arena); | ||
| 60 | |||
| 61 | var tokenizer = std.zig.Tokenizer.init(source); | ||
| 62 | while (true) { | ||
| 63 | const tree_token = try tree.tokens.addOne(); | ||
| 64 | tree_token.* = tokenizer.next(); | ||
| 65 | if (tree_token.id == .Eof) break; | ||
| 66 | } | ||
| 67 | // TODO preprocess here | ||
| 68 | var it = tree.tokens.iterator(0); | ||
| 69 | |||
| 70 | while (true) { | ||
| 71 | const tok = it.peek().?.id; | ||
| 72 | switch (id) { | ||
| 73 | .LineComment, | ||
| 74 | .MultiLineComment, | ||
| 75 | => { | ||
| 76 | _ = it.next(); | ||
| 77 | }, | ||
| 78 | else => break, | ||
| 79 | } | ||
| 80 | } | ||
| 81 | |||
| 82 | var parse_arena = std.heap.ArenaAllocator.init(allocator); | ||
| 83 | defer parse_arena.deinit(); | ||
| 84 | |||
| 85 | var parser = Parser{ | ||
| 86 | .scopes = Parser.SymbolList.init(allocator), | ||
| 87 | .arena = &parse_arena.allocator, | ||
| 88 | .it = &it, | ||
| 89 | .tree = tree, | ||
| 90 | .options = options, | ||
| 91 | }; | ||
| 92 | defer parser.symbols.deinit(); | ||
| 93 | |||
| 94 | tree.root_node = try parser.root(); | ||
| 95 | return tree; | ||
| 96 | } | ||
| 97 | |||
| 98 | const Parser = struct { | ||
| 99 | arena: *Allocator, | ||
| 100 | it: *TokenIterator, | ||
| 101 | tree: *Tree, | ||
| 102 | |||
| 103 | arena: *Allocator, | ||
| 104 | scopes: ScopeList, | ||
| 105 | options: Options, | ||
| 106 | |||
| 107 | const ScopeList = std.SegmentedLists(Scope); | ||
| 108 | const SymbolList = std.SegmentedLists(Symbol); | ||
| 109 | |||
| 110 | const Scope = struct { | ||
| 111 | kind: ScopeKind, | ||
| 112 | syms: SymbolList, | ||
| 113 | }; | ||
| 114 | |||
| 115 | const Symbol = struct { | ||
| 116 | name: []const u8, | ||
| 117 | ty: *Type, | ||
| 118 | }; | ||
| 119 | |||
| 120 | const ScopeKind = enum { | ||
| 121 | Block, | ||
| 122 | Loop, | ||
| 123 | Root, | ||
| 124 | Switch, | ||
| 125 | }; | ||
| 126 | |||
| 127 | fn pushScope(parser: *Parser, kind: ScopeKind) !void { | ||
| 128 | const new = try parser.scopes.addOne(); | ||
| 129 | new.* = .{ | ||
| 130 | .kind = kind, | ||
| 131 | .syms = SymbolList.init(parser.arena), | ||
| 132 | }; | ||
| 133 | } | ||
| 134 | |||
| 135 | fn popScope(parser: *Parser, len: usize) void { | ||
| 136 | _ = parser.scopes.pop(); | ||
| 137 | } | ||
| 138 | |||
| 139 | fn getSymbol(parser: *Parser, tok: TokenIndex) ?*Symbol { | ||
| 140 | const name = parser.tree.tokenSlice(tok); | ||
| 141 | var scope_it = parser.scopes.iterator(parser.scopes.len); | ||
| 142 | while (scope_it.prev()) |scope| { | ||
| 143 | var sym_it = scope.syms.iterator(scope.syms.len); | ||
| 144 | while (sym_it.prev()) |sym| { | ||
| 145 | if (mem.eql(u8, sym.name, name)) { | ||
| 146 | return sym; | ||
| 147 | } | ||
| 148 | } | ||
| 149 | } | ||
| 150 | return null; | ||
| 151 | } | ||
| 152 | |||
| 153 | fn declareSymbol(parser: *Parser, type_spec: Node.TypeSpec, dr: *Node.Declarator) Error!void { | ||
| 154 | return; // TODO | ||
| 155 | } | ||
| 156 | |||
| 157 | /// Root <- ExternalDeclaration* eof | ||
| 158 | fn root(parser: *Parser) Allocator.Error!*Node.Root { | ||
| 159 | try parser.pushScope(.Root); | ||
| 160 | defer parser.popScope(); | ||
| 161 | const node = try parser.arena.create(Node.Root); | ||
| 162 | node.* = .{ | ||
| 163 | .decls = Node.Root.DeclList.init(parser.arena), | ||
| 164 | .eof = undefined, | ||
| 165 | }; | ||
| 166 | while (parser.externalDeclarations() catch |e| switch (e) { | ||
| 167 | error.OutOfMemory => return error.OutOfMemory, | ||
| 168 | error.ParseError => return node, | ||
| 169 | }) |decl| { | ||
| 170 | try node.decls.push(decl); | ||
| 171 | } | ||
| 172 | node.eof = parser.eatToken(.Eof) orelse return node; | ||
| 173 | return node; | ||
| 174 | } | ||
| 175 | |||
| 176 | /// ExternalDeclaration | ||
| 177 | /// <- DeclSpec Declarator OldStyleDecl* CompoundStmt | ||
| 178 | /// / Declaration | ||
| 179 | /// OldStyleDecl <- DeclSpec Declarator (COMMA Declarator)* SEMICOLON | ||
| 180 | fn externalDeclarations(parser: *Parser) !?*Node { | ||
| 181 | return parser.declarationExtra(false); | ||
| 182 | } | ||
| 183 | |||
| 184 | /// Declaration | ||
| 185 | /// <- DeclSpec DeclInit SEMICOLON | ||
| 186 | /// / StaticAssert | ||
| 187 | /// DeclInit <- Declarator (EQUAL Initializer)? (COMMA Declarator (EQUAL Initializer)?)* | ||
| 188 | fn declaration(parser: *Parser) !?*Node { | ||
| 189 | return parser.declarationExtra(true); | ||
| 190 | } | ||
| 191 | |||
| 192 | fn declarationExtra(parser: *Parser, local: bool) !?*Node { | ||
| 193 | if (try parser.staticAssert()) |decl| return decl; | ||
| 194 | const begin = parser.it.index + 1; | ||
| 195 | var ds = Node.DeclSpec{}; | ||
| 196 | const got_ds = try parser.declSpec(&ds); | ||
| 197 | if (local and !got_ds) { | ||
| 198 | // not a declaration | ||
| 199 | return null; | ||
| 200 | } | ||
| 201 | switch (ds.storage_class) { | ||
| 202 | .Auto, .Register => |tok| return parser.err(.{ | ||
| 203 | .InvalidStorageClass = .{ .token = tok }, | ||
| 204 | }), | ||
| 205 | .Typedef => { | ||
| 206 | const node = try parser.arena.create(Node.Typedef); | ||
| 207 | node.* = .{ | ||
| 208 | .decl_spec = ds, | ||
| 209 | .declarators = Node.Typedef.DeclaratorList.init(parser.arena), | ||
| 210 | .semicolon = undefined, | ||
| 211 | }; | ||
| 212 | while (true) { | ||
| 213 | const dr = @fieldParentPtr(Node.Declarator, "base", (try parser.declarator(.Must)) orelse return parser.err(.{ | ||
| 214 | .ExpectedDeclarator = .{ .token = parser.it.index }, | ||
| 215 | })); | ||
| 216 | try parser.declareSymbol(ds.type_spec, dr); | ||
| 217 | try node.declarators.push(&dr.base); | ||
| 218 | if (parser.eatToken(.Comma)) |_| {} else break; | ||
| 219 | } | ||
| 220 | return &node.base; | ||
| 221 | }, | ||
| 222 | else => {}, | ||
| 223 | } | ||
| 224 | var first_dr = try parser.declarator(.Must); | ||
| 225 | if (first_dr != null and declaratorIsFunction(first_dr.?)) { | ||
| 226 | // TODO typedeffed fn proto-only | ||
| 227 | const dr = @fieldParentPtr(Node.Declarator, "base", first_dr.?); | ||
| 228 | try parser.declareSymbol(ds.type_spec, dr); | ||
| 229 | var old_decls = Node.FnDecl.OldDeclList.init(parser.arena); | ||
| 230 | const body = if (parser.eatToken(.Semicolon)) |_| | ||
| 231 | null | ||
| 232 | else blk: { | ||
| 233 | if (local) { | ||
| 234 | // TODO nested function warning | ||
| 235 | } | ||
| 236 | // TODO first_dr.is_old | ||
| 237 | // while (true) { | ||
| 238 | // var old_ds = Node.DeclSpec{}; | ||
| 239 | // if (!(try parser.declSpec(&old_ds))) { | ||
| 240 | // // not old decl | ||
| 241 | // break; | ||
| 242 | // } | ||
| 243 | // var old_dr = (try parser.declarator(.Must)); | ||
| 244 | // // if (old_dr == null) | ||
| 245 | // // try parser.err(.{ | ||
| 246 | // // .NoParamName = .{ .token = parser.it.index }, | ||
| 247 | // // }); | ||
| 248 | // // try old_decls.push(decl); | ||
| 249 | // } | ||
| 250 | const body_node = (try parser.compoundStmt()) orelse return parser.err(.{ | ||
| 251 | .ExpectedFnBody = .{ .token = parser.it.index }, | ||
| 252 | }); | ||
| 253 | break :blk @fieldParentPtr(Node.CompoundStmt, "base", body_node); | ||
| 254 | }; | ||
| 255 | |||
| 256 | const node = try parser.arena.create(Node.FnDecl); | ||
| 257 | node.* = .{ | ||
| 258 | .decl_spec = ds, | ||
| 259 | .declarator = dr, | ||
| 260 | .old_decls = old_decls, | ||
| 261 | .body = body, | ||
| 262 | }; | ||
| 263 | return &node.base; | ||
| 264 | } else { | ||
| 265 | switch (ds.fn_spec) { | ||
| 266 | .Inline, .Noreturn => |tok| return parser.err(.{ | ||
| 267 | .FnSpecOnNonFn = .{ .token = tok }, | ||
| 268 | }), | ||
| 269 | else => {}, | ||
| 270 | } | ||
| 271 | // TODO threadlocal without static or extern on local variable | ||
| 272 | const node = try parser.arena.create(Node.VarDecl); | ||
| 273 | node.* = .{ | ||
| 274 | .decl_spec = ds, | ||
| 275 | .initializers = Node.VarDecl.Initializers.init(parser.arena), | ||
| 276 | .semicolon = undefined, | ||
| 277 | }; | ||
| 278 | if (first_dr == null) { | ||
| 279 | node.semicolon = try parser.expectToken(.Semicolon); | ||
| 280 | const ok = switch (ds.type_spec.spec) { | ||
| 281 | .Enum => |e| e.name != null, | ||
| 282 | .Record => |r| r.name != null, | ||
| 283 | else => false, | ||
| 284 | }; | ||
| 285 | const q = ds.type_spec.qual; | ||
| 286 | if (!ok) | ||
| 287 | try parser.warn(.{ | ||
| 288 | .NothingDeclared = .{ .token = begin }, | ||
| 289 | }) | ||
| 290 | else if (q.@"const" orelse q.atomic orelse q.@"volatile" orelse q.restrict) |tok| | ||
| 291 | try parser.warn(.{ | ||
| 292 | .QualifierIgnored = .{ .token = tok }, | ||
| 293 | }); | ||
| 294 | return &node.base; | ||
| 295 | } | ||
| 296 | var dr = @fieldParentPtr(Node.Declarator, "base", first_dr.?); | ||
| 297 | while (true) { | ||
| 298 | try parser.declareSymbol(ds.type_spec, dr); | ||
| 299 | if (parser.eatToken(.Equal)) |tok| { | ||
| 300 | try node.initializers.push((try parser.initializer(dr)) orelse return parser.err(.{ | ||
| 301 | .ExpectedInitializer = .{ .token = parser.it.index }, | ||
| 302 | })); | ||
| 303 | } else try node.initializers.push(&dr.base); | ||
| 304 | if (parser.eatToken(.Comma) != null) break; | ||
| 305 | dr = @fieldParentPtr(Node.Declarator, "base", (try parser.declarator(.Must)) orelse return parser.err(.{ | ||
| 306 | .ExpectedDeclarator = .{ .token = parser.it.index }, | ||
| 307 | })); | ||
| 308 | } | ||
| 309 | node.semicolon = try parser.expectToken(.Semicolon); | ||
| 310 | return &node.base; | ||
| 311 | } | ||
| 312 | } | ||
| 313 | |||
| 314 | fn declaratorIsFunction(node: *Node) bool { | ||
| 315 | if (node.id != .Declarator) return false; | ||
| 316 | assert(node.id == .Declarator); | ||
| 317 | const dr = @fieldParentPtr(Node.Declarator, "base", node); | ||
| 318 | if (dr.suffix != .Fn) return false; | ||
| 319 | switch (dr.prefix) { | ||
| 320 | .None, .Identifer => return true, | ||
| 321 | .Complex => |inner| { | ||
| 322 | var inner_node = inner.inner; | ||
| 323 | while (true) { | ||
| 324 | if (inner_node.id != .Declarator) return false; | ||
| 325 | assert(inner_node.id == .Declarator); | ||
| 326 | const inner_dr = @fieldParentPtr(Node.Declarator, "base", inner_node); | ||
| 327 | if (inner_dr.pointer != null) return false; | ||
| 328 | switch (inner_dr.prefix) { | ||
| 329 | .None, .Identifer => return true, | ||
| 330 | .Complex => |c| inner_node = c.inner, | ||
| 331 | } | ||
| 332 | } | ||
| 333 | }, | ||
| 334 | } | ||
| 335 | } | ||
| 336 | |||
| 337 | /// StaticAssert <- Keyword_static_assert LPAREN ConstExpr COMMA STRINGLITERAL RPAREN SEMICOLON | ||
| 338 | fn staticAssert(parser: *Parser) !?*Node { | ||
| 339 | const tok = parser.eatToken(.Keyword_static_assert) orelse return null; | ||
| 340 | _ = try parser.expectToken(.LParen); | ||
| 341 | const const_expr = (try parser.constExpr()) orelse parser.err(.{ | ||
| 342 | .ExpectedExpr = .{ .token = parser.it.index }, | ||
| 343 | }); | ||
| 344 | _ = try parser.expectToken(.Comma); | ||
| 345 | const str = try parser.expectToken(.StringLiteral); | ||
| 346 | _ = try parser.expectToken(.RParen); | ||
| 347 | const node = try parser.arena.create(Node.StaticAssert); | ||
| 348 | node.* = .{ | ||
| 349 | .assert = tok, | ||
| 350 | .expr = const_expr, | ||
| 351 | .semicolon = try parser.expectToken(.Semicolon), | ||
| 352 | }; | ||
| 353 | return &node.base; | ||
| 354 | } | ||
| 355 | |||
| 356 | /// DeclSpec <- (StorageClassSpec / TypeSpec / FnSpec / AlignSpec)* | ||
| 357 | /// returns true if any tokens were consumed | ||
| 358 | fn declSpec(parser: *Parser, ds: *Node.DeclSpec) !bool { | ||
| 359 | var got = false; | ||
| 360 | while ((try parser.storageClassSpec(ds)) or (try parser.typeSpec(&ds.type_spec)) or (try parser.fnSpec(ds)) or (try parser.alignSpec(ds))) { | ||
| 361 | got = true; | ||
| 362 | } | ||
| 363 | return got; | ||
| 364 | } | ||
| 365 | |||
| 366 | /// StorageClassSpec | ||
| 367 | /// <- Keyword_typedef / Keyword_extern / Keyword_static / Keyword_thread_local / Keyword_auto / Keyword_register | ||
| 368 | fn storageClassSpec(parser: *Parser, ds: *Node.DeclSpec) !bool { | ||
| 369 | blk: { | ||
| 370 | if (parser.eatToken(.Keyword_typedef)) |tok| { | ||
| 371 | if (ds.storage_class != .None or ds.thread_local != null) | ||
| 372 | break :blk; | ||
| 373 | ds.storage_class = .{ .Typedef = tok }; | ||
| 374 | } else if (parser.eatToken(.Keyword_extern)) |tok| { | ||
| 375 | if (ds.storage_class != .None) | ||
| 376 | break :blk; | ||
| 377 | ds.storage_class = .{ .Extern = tok }; | ||
| 378 | } else if (parser.eatToken(.Keyword_static)) |tok| { | ||
| 379 | if (ds.storage_class != .None) | ||
| 380 | break :blk; | ||
| 381 | ds.storage_class = .{ .Static = tok }; | ||
| 382 | } else if (parser.eatToken(.Keyword_thread_local)) |tok| { | ||
| 383 | switch (ds.storage_class) { | ||
| 384 | .None, .Extern, .Static => {}, | ||
| 385 | else => break :blk, | ||
| 386 | } | ||
| 387 | ds.thread_local = tok; | ||
| 388 | } else if (parser.eatToken(.Keyword_auto)) |tok| { | ||
| 389 | if (ds.storage_class != .None or ds.thread_local != null) | ||
| 390 | break :blk; | ||
| 391 | ds.storage_class = .{ .Auto = tok }; | ||
| 392 | } else if (parser.eatToken(.Keyword_register)) |tok| { | ||
| 393 | if (ds.storage_class != .None or ds.thread_local != null) | ||
| 394 | break :blk; | ||
| 395 | ds.storage_class = .{ .Register = tok }; | ||
| 396 | } else return false; | ||
| 397 | return true; | ||
| 398 | } | ||
| 399 | try parser.warn(.{ | ||
| 400 | .DuplicateSpecifier = .{ .token = parser.it.index }, | ||
| 401 | }); | ||
| 402 | return true; | ||
| 403 | } | ||
| 404 | |||
| 405 | /// TypeSpec | ||
| 406 | /// <- Keyword_void / Keyword_char / Keyword_short / Keyword_int / Keyword_long / Keyword_float / Keyword_double | ||
| 407 | /// / Keyword_signed / Keyword_unsigned / Keyword_bool / Keyword_complex / Keyword_imaginary / | ||
| 408 | /// / Keyword_atomic LPAREN TypeName RPAREN | ||
| 409 | /// / EnumSpec | ||
| 410 | /// / RecordSpec | ||
| 411 | /// / IDENTIFIER // typedef name | ||
| 412 | /// / TypeQual | ||
| 413 | fn typeSpec(parser: *Parser, type_spec: *Node.TypeSpec) !bool { | ||
| 414 | blk: { | ||
| 415 | if (parser.eatToken(.Keyword_void)) |tok| { | ||
| 416 | if (type_spec.spec != .None) | ||
| 417 | break :blk; | ||
| 418 | type_spec.spec = .{ .Void = tok }; | ||
| 419 | } else if (parser.eatToken(.Keyword_char)) |tok| { | ||
| 420 | switch (type_spec.spec) { | ||
| 421 | .None => { | ||
| 422 | type_spec.spec = .{ | ||
| 423 | .Char = .{ | ||
| 424 | .char = tok, | ||
| 425 | }, | ||
| 426 | }; | ||
| 427 | }, | ||
| 428 | .Int => |int| { | ||
| 429 | if (int.int != null) | ||
| 430 | break :blk; | ||
| 431 | type_spec.spec = .{ | ||
| 432 | .Char = .{ | ||
| 433 | .char = tok, | ||
| 434 | .sign = int.sign, | ||
| 435 | }, | ||
| 436 | }; | ||
| 437 | }, | ||
| 438 | else => break :blk, | ||
| 439 | } | ||
| 440 | } else if (parser.eatToken(.Keyword_short)) |tok| { | ||
| 441 | switch (type_spec.spec) { | ||
| 442 | .None => { | ||
| 443 | type_spec.spec = .{ | ||
| 444 | .Short = .{ | ||
| 445 | .short = tok, | ||
| 446 | }, | ||
| 447 | }; | ||
| 448 | }, | ||
| 449 | .Int => |int| { | ||
| 450 | if (int.int != null) | ||
| 451 | break :blk; | ||
| 452 | type_spec.spec = .{ | ||
| 453 | .Short = .{ | ||
| 454 | .short = tok, | ||
| 455 | .sign = int.sign, | ||
| 456 | }, | ||
| 457 | }; | ||
| 458 | }, | ||
| 459 | else => break :blk, | ||
| 460 | } | ||
| 461 | } else if (parser.eatToken(.Keyword_long)) |tok| { | ||
| 462 | switch (type_spec.spec) { | ||
| 463 | .None => { | ||
| 464 | type_spec.spec = .{ | ||
| 465 | .Long = .{ | ||
| 466 | .long = tok, | ||
| 467 | }, | ||
| 468 | }; | ||
| 469 | }, | ||
| 470 | .Int => |int| { | ||
| 471 | type_spec.spec = .{ | ||
| 472 | .Long = .{ | ||
| 473 | .long = tok, | ||
| 474 | .sign = int.sign, | ||
| 475 | .int = int.int, | ||
| 476 | }, | ||
| 477 | }; | ||
| 478 | }, | ||
| 479 | .Long => |*long| { | ||
| 480 | if (long.longlong != null) | ||
| 481 | break :blk; | ||
| 482 | long.longlong = tok; | ||
| 483 | }, | ||
| 484 | .Double => |*double| { | ||
| 485 | if (double.long != null) | ||
| 486 | break :blk; | ||
| 487 | double.long = tok; | ||
| 488 | }, | ||
| 489 | else => break :blk, | ||
| 490 | } | ||
| 491 | } else if (parser.eatToken(.Keyword_int)) |tok| { | ||
| 492 | switch (type_spec.spec) { | ||
| 493 | .None => { | ||
| 494 | type_spec.spec = .{ | ||
| 495 | .Int = .{ | ||
| 496 | .int = tok, | ||
| 497 | }, | ||
| 498 | }; | ||
| 499 | }, | ||
| 500 | .Short => |*short| { | ||
| 501 | if (short.int != null) | ||
| 502 | break :blk; | ||
| 503 | short.int = tok; | ||
| 504 | }, | ||
| 505 | .Int => |*int| { | ||
| 506 | if (int.int != null) | ||
| 507 | break :blk; | ||
| 508 | int.int = tok; | ||
| 509 | }, | ||
| 510 | .Long => |*long| { | ||
| 511 | if (long.int != null) | ||
| 512 | break :blk; | ||
| 513 | long.int = tok; | ||
| 514 | }, | ||
| 515 | else => break :blk, | ||
| 516 | } | ||
| 517 | } else if (parser.eatToken(.Keyword_signed) orelse parser.eatToken(.Keyword_unsigned)) |tok| { | ||
| 518 | switch (type_spec.spec) { | ||
| 519 | .None => { | ||
| 520 | type_spec.spec = .{ | ||
| 521 | .Int = .{ | ||
| 522 | .sign = tok, | ||
| 523 | }, | ||
| 524 | }; | ||
| 525 | }, | ||
| 526 | .Char => |*char| { | ||
| 527 | if (char.sign != null) | ||
| 528 | break :blk; | ||
| 529 | char.sign = tok; | ||
| 530 | }, | ||
| 531 | .Short => |*short| { | ||
| 532 | if (short.sign != null) | ||
| 533 | break :blk; | ||
| 534 | short.sign = tok; | ||
| 535 | }, | ||
| 536 | .Int => |*int| { | ||
| 537 | if (int.sign != null) | ||
| 538 | break :blk; | ||
| 539 | int.sign = tok; | ||
| 540 | }, | ||
| 541 | .Long => |*long| { | ||
| 542 | if (long.sign != null) | ||
| 543 | break :blk; | ||
| 544 | long.sign = tok; | ||
| 545 | }, | ||
| 546 | else => break :blk, | ||
| 547 | } | ||
| 548 | } else if (parser.eatToken(.Keyword_float)) |tok| { | ||
| 549 | if (type_spec.spec != .None) | ||
| 550 | break :blk; | ||
| 551 | type_spec.spec = .{ | ||
| 552 | .Float = .{ | ||
| 553 | .float = tok, | ||
| 554 | }, | ||
| 555 | }; | ||
| 556 | } else if (parser.eatToken(.Keyword_double)) |tok| { | ||
| 557 | if (type_spec.spec != .None) | ||
| 558 | break :blk; | ||
| 559 | type_spec.spec = .{ | ||
| 560 | .Double = .{ | ||
| 561 | .double = tok, | ||
| 562 | }, | ||
| 563 | }; | ||
| 564 | } else if (parser.eatToken(.Keyword_complex)) |tok| { | ||
| 565 | switch (type_spec.spec) { | ||
| 566 | .None => { | ||
| 567 | type_spec.spec = .{ | ||
| 568 | .Double = .{ | ||
| 569 | .complex = tok, | ||
| 570 | .double = null, | ||
| 571 | }, | ||
| 572 | }; | ||
| 573 | }, | ||
| 574 | .Float => |*float| { | ||
| 575 | if (float.complex != null) | ||
| 576 | break :blk; | ||
| 577 | float.complex = tok; | ||
| 578 | }, | ||
| 579 | .Double => |*double| { | ||
| 580 | if (double.complex != null) | ||
| 581 | break :blk; | ||
| 582 | double.complex = tok; | ||
| 583 | }, | ||
| 584 | else => break :blk, | ||
| 585 | } | ||
| 586 | } else if (parser.eatToken(.Keyword_bool)) |tok| { | ||
| 587 | if (type_spec.spec != .None) | ||
| 588 | break :blk; | ||
| 589 | type_spec.spec = .{ .Bool = tok }; | ||
| 590 | } else if (parser.eatToken(.Keyword_atomic)) |tok| { | ||
| 591 | // might be _Atomic qualifier | ||
| 592 | if (parser.eatToken(.LParen)) |_| { | ||
| 593 | if (type_spec.spec != .None) | ||
| 594 | break :blk; | ||
| 595 | const name = (try parser.typeName()) orelse return parser.err(.{ | ||
| 596 | .ExpectedTypeName = .{ .token = parser.it.index }, | ||
| 597 | }); | ||
| 598 | type_spec.spec.Atomic = .{ | ||
| 599 | .atomic = tok, | ||
| 600 | .typename = name, | ||
| 601 | .rparen = try parser.expectToken(.RParen), | ||
| 602 | }; | ||
| 603 | } else { | ||
| 604 | parser.putBackToken(tok); | ||
| 605 | } | ||
| 606 | } else if (parser.eatToken(.Keyword_enum)) |tok| { | ||
| 607 | if (type_spec.spec != .None) | ||
| 608 | break :blk; | ||
| 609 | type_spec.spec.Enum = try parser.enumSpec(tok); | ||
| 610 | } else if (parser.eatToken(.Keyword_union) orelse parser.eatToken(.Keyword_struct)) |tok| { | ||
| 611 | if (type_spec.spec != .None) | ||
| 612 | break :blk; | ||
| 613 | type_spec.spec.Record = try parser.recordSpec(tok); | ||
| 614 | } else if (parser.eatToken(.Identifier)) |tok| { | ||
| 615 | const ty = parser.getSymbol(tok) orelse { | ||
| 616 | parser.putBackToken(tok); | ||
| 617 | return false; | ||
| 618 | }; | ||
| 619 | switch (ty.id) { | ||
| 620 | .Enum => |e| inner: { | ||
| 621 | if (e.name) |some| | ||
| 622 | if (!parser.tree.tokenEql(some, tok)) | ||
| 623 | break :inner; | ||
| 624 | return parser.err(.{ | ||
| 625 | .MustUseKwToRefer = .{ .kw = e.tok, .name = tok }, | ||
| 626 | }); | ||
| 627 | }, | ||
| 628 | .Record => |r| inner: { | ||
| 629 | if (r.name) |some| | ||
| 630 | if (!parser.tree.tokenEql(some, tok)) | ||
| 631 | break :inner; | ||
| 632 | return parser.err(.{ | ||
| 633 | .MustUseKwToRefer = .{ | ||
| 634 | .kw = r.tok, | ||
| 635 | .name = tok, | ||
| 636 | }, | ||
| 637 | }); | ||
| 638 | }, | ||
| 639 | .Typedef => { | ||
| 640 | type_spec.spec = .{ | ||
| 641 | .Typedef = .{ | ||
| 642 | .sym = tok, | ||
| 643 | .sym_type = ty, | ||
| 644 | }, | ||
| 645 | }; | ||
| 646 | return true; | ||
| 647 | }, | ||
| 648 | else => {}, | ||
| 649 | } | ||
| 650 | parser.putBackToken(tok); | ||
| 651 | return false; | ||
| 652 | } | ||
| 653 | return parser.typeQual(&type_spec.qual); | ||
| 654 | } | ||
| 655 | return parser.err(.{ | ||
| 656 | .InvalidTypeSpecifier = .{ | ||
| 657 | .token = parser.it.index, | ||
| 658 | .type_spec = type_spec, | ||
| 659 | }, | ||
| 660 | }); | ||
| 661 | } | ||
| 662 | |||
| 663 | /// TypeQual <- Keyword_const / Keyword_restrict / Keyword_volatile / Keyword_atomic | ||
| 664 | fn typeQual(parser: *Parser, qual: *Node.TypeQual) !bool { | ||
| 665 | blk: { | ||
| 666 | if (parser.eatToken(.Keyword_const)) |tok| { | ||
| 667 | if (qual.@"const" != null) | ||
| 668 | break :blk; | ||
| 669 | qual.@"const" = tok; | ||
| 670 | } else if (parser.eatToken(.Keyword_restrict)) |tok| { | ||
| 671 | if (qual.atomic != null) | ||
| 672 | break :blk; | ||
| 673 | qual.atomic = tok; | ||
| 674 | } else if (parser.eatToken(.Keyword_volatile)) |tok| { | ||
| 675 | if (qual.@"volatile" != null) | ||
| 676 | break :blk; | ||
| 677 | qual.@"volatile" = tok; | ||
| 678 | } else if (parser.eatToken(.Keyword_atomic)) |tok| { | ||
| 679 | if (qual.atomic != null) | ||
| 680 | break :blk; | ||
| 681 | qual.atomic = tok; | ||
| 682 | } else return false; | ||
| 683 | return true; | ||
| 684 | } | ||
| 685 | try parser.warn(.{ | ||
| 686 | .DuplicateQualifier = .{ .token = parser.it.index }, | ||
| 687 | }); | ||
| 688 | return true; | ||
| 689 | } | ||
| 690 | |||
| 691 | /// FnSpec <- Keyword_inline / Keyword_noreturn | ||
| 692 | fn fnSpec(parser: *Parser, ds: *Node.DeclSpec) !bool { | ||
| 693 | blk: { | ||
| 694 | if (parser.eatToken(.Keyword_inline)) |tok| { | ||
| 695 | if (ds.fn_spec != .None) | ||
| 696 | break :blk; | ||
| 697 | ds.fn_spec = .{ .Inline = tok }; | ||
| 698 | } else if (parser.eatToken(.Keyword_noreturn)) |tok| { | ||
| 699 | if (ds.fn_spec != .None) | ||
| 700 | break :blk; | ||
| 701 | ds.fn_spec = .{ .Noreturn = tok }; | ||
| 702 | } else return false; | ||
| 703 | return true; | ||
| 704 | } | ||
| 705 | try parser.warn(.{ | ||
| 706 | .DuplicateSpecifier = .{ .token = parser.it.index }, | ||
| 707 | }); | ||
| 708 | return true; | ||
| 709 | } | ||
| 710 | |||
| 711 | /// AlignSpec <- Keyword_alignas LPAREN (TypeName / ConstExpr) RPAREN | ||
| 712 | fn alignSpec(parser: *Parser, ds: *Node.DeclSpec) !bool { | ||
| 713 | if (parser.eatToken(.Keyword_alignas)) |tok| { | ||
| 714 | _ = try parser.expectToken(.LParen); | ||
| 715 | const node = (try parser.typeName()) orelse (try parser.constExpr()) orelse parser.err(.{ | ||
| 716 | .ExpectedExpr = .{ .token = parser.it.index }, | ||
| 717 | }); | ||
| 718 | if (ds.align_spec != null) { | ||
| 719 | try parser.warn(.{ | ||
| 720 | .DuplicateSpecifier = .{ .token = parser.it.index }, | ||
| 721 | }); | ||
| 722 | } | ||
| 723 | ds.align_spec = .{ | ||
| 724 | .alignas = tok, | ||
| 725 | .expr = node, | ||
| 726 | .rparen = try parser.expectToken(.RParen), | ||
| 727 | }; | ||
| 728 | return true; | ||
| 729 | } | ||
| 730 | return false; | ||
| 731 | } | ||
| 732 | |||
| 733 | /// EnumSpec <- Keyword_enum IDENTIFIER? (LBRACE EnumField RBRACE)? | ||
| 734 | fn enumSpec(parser: *Parser, tok: TokenIndex) !*Node.EnumType { | ||
| 735 | const node = try parser.arena.create(Node.EnumType); | ||
| 736 | const name = parser.eatToken(.Identifier); | ||
| 737 | node.* = .{ | ||
| 738 | .tok = tok, | ||
| 739 | .name = name, | ||
| 740 | .body = null, | ||
| 741 | }; | ||
| 742 | const ty = try parser.arena.create(Type); | ||
| 743 | ty.* = .{ | ||
| 744 | .id = .{ | ||
| 745 | .Enum = node, | ||
| 746 | }, | ||
| 747 | }; | ||
| 748 | if (name) |some| | ||
| 749 | try parser.symbols.append(.{ | ||
| 750 | .name = parser.tree.tokenSlice(some), | ||
| 751 | .ty = ty, | ||
| 752 | }); | ||
| 753 | if (parser.eatToken(.LBrace)) |lbrace| { | ||
| 754 | var fields = Node.EnumType.FieldList.init(parser.arena); | ||
| 755 | try fields.push((try parser.enumField()) orelse return parser.err(.{ | ||
| 756 | .ExpectedEnumField = .{ .token = parser.it.index }, | ||
| 757 | })); | ||
| 758 | while (parser.eatToken(.Comma)) |_| { | ||
| 759 | try fields.push((try parser.enumField()) orelse break); | ||
| 760 | } | ||
| 761 | node.body = .{ | ||
| 762 | .lbrace = lbrace, | ||
| 763 | .fields = fields, | ||
| 764 | .rbrace = try parser.expectToken(.RBrace), | ||
| 765 | }; | ||
| 766 | } | ||
| 767 | return node; | ||
| 768 | } | ||
| 769 | |||
| 770 | /// EnumField <- IDENTIFIER (EQUAL ConstExpr)? (COMMA EnumField) COMMA? | ||
| 771 | fn enumField(parser: *Parser) !?*Node { | ||
| 772 | const name = parser.eatToken(.Identifier) orelse return null; | ||
| 773 | const node = try parser.arena.create(Node.EnumField); | ||
| 774 | node.* = .{ | ||
| 775 | .name = name, | ||
| 776 | .value = null, | ||
| 777 | }; | ||
| 778 | if (parser.eatToken(.Equal)) |eq| { | ||
| 779 | node.value = (try parser.constExpr()) orelse parser.err(.{ | ||
| 780 | .ExpectedExpr = .{ .token = parser.it.index }, | ||
| 781 | }); | ||
| 782 | } | ||
| 783 | return &node.base; | ||
| 784 | } | ||
| 785 | |||
| 786 | /// RecordSpec <- (Keyword_struct / Keyword_union) IDENTIFIER? (LBRACE RecordField+ RBRACE)? | ||
| 787 | fn recordSpec(parser: *Parser, tok: TokenIndex) !*Node.RecordType { | ||
| 788 | const node = try parser.arena.create(Node.RecordType); | ||
| 789 | const name = parser.eatToken(.Identifier); | ||
| 790 | const is_struct = parser.tree.tokenSlice(tok)[0] == 's'; | ||
| 791 | node.* = .{ | ||
| 792 | .tok = tok, | ||
| 793 | .kind = if (is_struct) .Struct else .Union, | ||
| 794 | .name = name, | ||
| 795 | .body = null, | ||
| 796 | }; | ||
| 797 | const ty = try parser.arena.create(Type); | ||
| 798 | ty.* = .{ | ||
| 799 | .id = .{ | ||
| 800 | .Record = node, | ||
| 801 | }, | ||
| 802 | }; | ||
| 803 | if (name) |some| | ||
| 804 | try parser.symbols.append(.{ | ||
| 805 | .name = parser.tree.tokenSlice(some), | ||
| 806 | .ty = ty, | ||
| 807 | }); | ||
| 808 | if (parser.eatToken(.LBrace)) |lbrace| { | ||
| 809 | try parser.pushScope(.Block); | ||
| 810 | defer parser.popScope(); | ||
| 811 | var fields = Node.RecordType.FieldList.init(parser.arena); | ||
| 812 | while (true) { | ||
| 813 | if (parser.eatToken(.RBrace)) |rbrace| { | ||
| 814 | node.body = .{ | ||
| 815 | .lbrace = lbrace, | ||
| 816 | .fields = fields, | ||
| 817 | .rbrace = rbrace, | ||
| 818 | }; | ||
| 819 | break; | ||
| 820 | } | ||
| 821 | try fields.push(try parser.recordField()); | ||
| 822 | } | ||
| 823 | } | ||
| 824 | return node; | ||
| 825 | } | ||
| 826 | |||
| 827 | /// RecordField | ||
| 828 | /// <- TypeSpec* (RecordDeclarator (COMMA RecordDeclarator))? SEMICOLON | ||
| 829 | /// \ StaticAssert | ||
| 830 | fn recordField(parser: *Parser) Error!*Node { | ||
| 831 | if (try parser.staticAssert()) |decl| return decl; | ||
| 832 | var got = false; | ||
| 833 | var type_spec = Node.TypeSpec{}; | ||
| 834 | while (try parser.typeSpec(&type_spec)) got = true; | ||
| 835 | if (!got) | ||
| 836 | return parser.err(.{ | ||
| 837 | .ExpectedType = .{ .token = parser.it.index }, | ||
| 838 | }); | ||
| 839 | const node = try parser.arena.create(Node.RecordField); | ||
| 840 | node.* = .{ | ||
| 841 | .type_spec = type_spec, | ||
| 842 | .declarators = Node.RecordField.DeclaratorList.init(parser.arena), | ||
| 843 | .semicolon = undefined, | ||
| 844 | }; | ||
| 845 | while (true) { | ||
| 846 | const rdr = try parser.recordDeclarator(); | ||
| 847 | try parser.declareSymbol(type_spec, rdr.declarator); | ||
| 848 | try node.declarators.push(&rdr.base); | ||
| 849 | if (parser.eatToken(.Comma)) |_| {} else break; | ||
| 850 | } | ||
| 851 | |||
| 852 | node.semicolon = try parser.expectToken(.Semicolon); | ||
| 853 | return &node.base; | ||
| 854 | } | ||
| 855 | |||
| 856 | /// TypeName <- TypeSpec* AbstractDeclarator? | ||
| 857 | fn typeName(parser: *Parser) Error!?*Node { | ||
| 858 | @panic("TODO"); | ||
| 859 | } | ||
| 860 | |||
| 861 | /// RecordDeclarator <- Declarator? (COLON ConstExpr)? | ||
| 862 | fn recordDeclarator(parser: *Parser) Error!*Node.RecordDeclarator { | ||
| 863 | @panic("TODO"); | ||
| 864 | } | ||
| 865 | |||
| 866 | /// Pointer <- ASTERISK TypeQual* Pointer? | ||
| 867 | fn pointer(parser: *Parser) Error!?*Node.Pointer { | ||
| 868 | const asterisk = parser.eatToken(.Asterisk) orelse return null; | ||
| 869 | const node = try parser.arena.create(Node.Pointer); | ||
| 870 | node.* = .{ | ||
| 871 | .asterisk = asterisk, | ||
| 872 | .qual = .{}, | ||
| 873 | .pointer = null, | ||
| 874 | }; | ||
| 875 | while (try parser.typeQual(&node.qual)) {} | ||
| 876 | node.pointer = try parser.pointer(); | ||
| 877 | return node; | ||
| 878 | } | ||
| 879 | |||
| 880 | const Named = enum { | ||
| 881 | Must, | ||
| 882 | Allowed, | ||
| 883 | Forbidden, | ||
| 884 | }; | ||
| 885 | |||
| 886 | /// Declarator <- Pointer? DeclaratorSuffix | ||
| 887 | /// DeclaratorPrefix | ||
| 888 | /// <- IDENTIFIER // if named != .Forbidden | ||
| 889 | /// / LPAREN Declarator RPAREN | ||
| 890 | /// / (none) // if named != .Must | ||
| 891 | /// DeclaratorSuffix | ||
| 892 | /// <- DeclaratorPrefix (LBRACKET ArrayDeclarator? RBRACKET)* | ||
| 893 | /// / DeclaratorPrefix LPAREN (ParamDecl (COMMA ParamDecl)* (COMMA ELLIPSIS)?)? RPAREN | ||
| 894 | fn declarator(parser: *Parser, named: Named) Error!?*Node { | ||
| 895 | const ptr = try parser.pointer(); | ||
| 896 | var node: *Node.Declarator = undefined; | ||
| 897 | var inner_fn = false; | ||
| 898 | |||
| 899 | // TODO sizof(int (int)) | ||
| 900 | // prefix | ||
| 901 | if (parser.eatToken(.LParen)) |lparen| { | ||
| 902 | const inner = (try parser.declarator(named)) orelse return parser.err(.{ | ||
| 903 | .ExpectedDeclarator = .{ .token = lparen + 1 }, | ||
| 904 | }); | ||
| 905 | inner_fn = declaratorIsFunction(inner); | ||
| 906 | node = try parser.arena.create(Node.Declarator); | ||
| 907 | node.* = .{ | ||
| 908 | .pointer = ptr, | ||
| 909 | .prefix = .{ | ||
| 910 | .Complex = .{ | ||
| 911 | .lparen = lparen, | ||
| 912 | .inner = inner, | ||
| 913 | .rparen = try parser.expectToken(.RParen), | ||
| 914 | }, | ||
| 915 | }, | ||
| 916 | .suffix = .None, | ||
| 917 | }; | ||
| 918 | } else if (named != .Forbidden) { | ||
| 919 | if (parser.eatToken(.Identifier)) |tok| { | ||
| 920 | node = try parser.arena.create(Node.Declarator); | ||
| 921 | node.* = .{ | ||
| 922 | .pointer = ptr, | ||
| 923 | .prefix = .{ .Identifer = tok }, | ||
| 924 | .suffix = .None, | ||
| 925 | }; | ||
| 926 | } else if (named == .Must) { | ||
| 927 | return parser.err(.{ | ||
| 928 | .ExpectedToken = .{ .token = parser.it.index, .expected_id = .Identifier }, | ||
| 929 | }); | ||
| 930 | } else { | ||
| 931 | if (ptr) |some| | ||
| 932 | return &some.base; | ||
| 933 | return null; | ||
| 934 | } | ||
| 935 | } else { | ||
| 936 | node = try parser.arena.create(Node.Declarator); | ||
| 937 | node.* = .{ | ||
| 938 | .pointer = ptr, | ||
| 939 | .prefix = .None, | ||
| 940 | .suffix = .None, | ||
| 941 | }; | ||
| 942 | } | ||
| 943 | // suffix | ||
| 944 | if (parser.eatToken(.LParen)) |lparen| { | ||
| 945 | if (inner_fn) | ||
| 946 | return parser.err(.{ | ||
| 947 | .InvalidDeclarator = .{ .token = lparen }, | ||
| 948 | }); | ||
| 949 | node.suffix = .{ | ||
| 950 | .Fn = .{ | ||
| 951 | .lparen = lparen, | ||
| 952 | .params = Node.Declarator.Params.init(parser.arena), | ||
| 953 | .rparen = undefined, | ||
| 954 | }, | ||
| 955 | }; | ||
| 956 | try parser.paramDecl(node); | ||
| 957 | node.suffix.Fn.rparen = try parser.expectToken(.RParen); | ||
| 958 | } else if (parser.eatToken(.LBracket)) |tok| { | ||
| 959 | if (inner_fn) | ||
| 960 | return parser.err(.{ | ||
| 961 | .InvalidDeclarator = .{ .token = tok }, | ||
| 962 | }); | ||
| 963 | node.suffix = .{ .Array = Node.Declarator.Arrays.init(parser.arena) }; | ||
| 964 | var lbrace = tok; | ||
| 965 | while (true) { | ||
| 966 | try node.suffix.Array.push(try parser.arrayDeclarator(lbrace)); | ||
| 967 | if (parser.eatToken(.LBracket)) |t| lbrace = t else break; | ||
| 968 | } | ||
| 969 | } | ||
| 970 | if (parser.eatToken(.LParen) orelse parser.eatToken(.LBracket)) |tok| | ||
| 971 | return parser.err(.{ | ||
| 972 | .InvalidDeclarator = .{ .token = tok }, | ||
| 973 | }); | ||
| 974 | return &node.base; | ||
| 975 | } | ||
| 976 | |||
| 977 | /// ArrayDeclarator | ||
| 978 | /// <- ASTERISK | ||
| 979 | /// / Keyword_static TypeQual* AssignmentExpr | ||
| 980 | /// / TypeQual+ (ASTERISK / Keyword_static AssignmentExpr) | ||
| 981 | /// / TypeQual+ AssignmentExpr? | ||
| 982 | /// / AssignmentExpr | ||
| 983 | fn arrayDeclarator(parser: *Parser, lbracket: TokenIndex) !*Node.Array { | ||
| 984 | const arr = try parser.arena.create(Node.Array); | ||
| 985 | arr.* = .{ | ||
| 986 | .lbracket = lbracket, | ||
| 987 | .inner = .Inferred, | ||
| 988 | .rbracket = undefined, | ||
| 989 | }; | ||
| 990 | if (parser.eatToken(.Asterisk)) |tok| { | ||
| 991 | arr.inner = .{ .Unspecified = tok }; | ||
| 992 | } else { | ||
| 993 | // TODO | ||
| 994 | } | ||
| 995 | arr.rbracket = try parser.expectToken(.RBracket); | ||
| 996 | return arr; | ||
| 997 | } | ||
| 998 | |||
| 999 | /// Params <- ParamDecl (COMMA ParamDecl)* (COMMA ELLIPSIS)? | ||
| 1000 | /// ParamDecl <- DeclSpec (Declarator / AbstractDeclarator) | ||
| 1001 | fn paramDecl(parser: *Parser, dr: *Node.Declarator) !void { | ||
| 1002 | var old_style = false; | ||
| 1003 | while (true) { | ||
| 1004 | var ds = Node.DeclSpec{}; | ||
| 1005 | if (try parser.declSpec(&ds)) { | ||
| 1006 | //TODO | ||
| 1007 | // TODO try parser.declareSymbol(ds.type_spec, dr); | ||
| 1008 | } else if (parser.eatToken(.Identifier)) |tok| { | ||
| 1009 | old_style = true; | ||
| 1010 | } else if (parser.eatToken(.Ellipsis)) |tok| { | ||
| 1011 | // TODO | ||
| 1012 | } | ||
| 1013 | } | ||
| 1014 | } | ||
| 1015 | |||
| 1016 | /// Expr <- AssignmentExpr (COMMA Expr)* | ||
| 1017 | fn expr(parser: *Parser) Error!?*Expr { | ||
| 1018 | @panic("TODO"); | ||
| 1019 | } | ||
| 1020 | |||
| 1021 | /// AssignmentExpr | ||
| 1022 | /// <- ConditionalExpr // TODO recursive? | ||
| 1023 | /// / UnaryExpr (EQUAL / ASTERISKEQUAL / SLASHEQUAL / PERCENTEQUAL / PLUSEQUAL / MINUSEQUA / | ||
| 1024 | /// / ANGLEBRACKETANGLEBRACKETLEFTEQUAL / ANGLEBRACKETANGLEBRACKETRIGHTEQUAL / | ||
| 1025 | /// / AMPERSANDEQUAL / CARETEQUAL / PIPEEQUAL) AssignmentExpr | ||
| 1026 | fn assignmentExpr(parser: *Parser) !?*Expr { | ||
| 1027 | @panic("TODO"); | ||
| 1028 | } | ||
| 1029 | |||
| 1030 | /// ConstExpr <- ConditionalExpr | ||
| 1031 | fn constExpr(parser: *Parser) Error!?*Expr { | ||
| 1032 | const start = parser.it.index; | ||
| 1033 | const expression = try parser.conditionalExpr(); | ||
| 1034 | if (expression != null and expression.?.value == .None) | ||
| 1035 | return parser.err(.{ | ||
| 1036 | .ConsExpr = start, | ||
| 1037 | }); | ||
| 1038 | return expression; | ||
| 1039 | } | ||
| 1040 | |||
| 1041 | /// ConditionalExpr <- LogicalOrExpr (QUESTIONMARK Expr COLON ConditionalExpr)? | ||
| 1042 | fn conditionalExpr(parser: *Parser) Error!?*Expr { | ||
| 1043 | @panic("TODO"); | ||
| 1044 | } | ||
| 1045 | |||
| 1046 | /// LogicalOrExpr <- LogicalAndExpr (PIPEPIPE LogicalOrExpr)* | ||
| 1047 | fn logicalOrExpr(parser: *Parser) !*Node { | ||
| 1048 | const lhs = (try parser.logicalAndExpr()) orelse return null; | ||
| 1049 | } | ||
| 1050 | |||
| 1051 | /// LogicalAndExpr <- BinOrExpr (AMPERSANDAMPERSAND LogicalAndExpr)* | ||
| 1052 | fn logicalAndExpr(parser: *Parser) !*Node { | ||
| 1053 | @panic("TODO"); | ||
| 1054 | } | ||
| 1055 | |||
| 1056 | /// BinOrExpr <- BinXorExpr (PIPE BinOrExpr)* | ||
| 1057 | fn binOrExpr(parser: *Parser) !*Node { | ||
| 1058 | @panic("TODO"); | ||
| 1059 | } | ||
| 1060 | |||
| 1061 | /// BinXorExpr <- BinAndExpr (CARET BinXorExpr)* | ||
| 1062 | fn binXorExpr(parser: *Parser) !*Node { | ||
| 1063 | @panic("TODO"); | ||
| 1064 | } | ||
| 1065 | |||
| 1066 | /// BinAndExpr <- EqualityExpr (AMPERSAND BinAndExpr)* | ||
| 1067 | fn binAndExpr(parser: *Parser) !*Node { | ||
| 1068 | @panic("TODO"); | ||
| 1069 | } | ||
| 1070 | |||
| 1071 | /// EqualityExpr <- ComparisionExpr ((EQUALEQUAL / BANGEQUAL) EqualityExpr)* | ||
| 1072 | fn equalityExpr(parser: *Parser) !*Node { | ||
| 1073 | @panic("TODO"); | ||
| 1074 | } | ||
| 1075 | |||
| 1076 | /// ComparisionExpr <- ShiftExpr (ANGLEBRACKETLEFT / ANGLEBRACKETLEFTEQUAL /ANGLEBRACKETRIGHT / ANGLEBRACKETRIGHTEQUAL) ComparisionExpr)* | ||
| 1077 | fn comparisionExpr(parser: *Parser) !*Node { | ||
| 1078 | @panic("TODO"); | ||
| 1079 | } | ||
| 1080 | |||
| 1081 | /// ShiftExpr <- AdditiveExpr (ANGLEBRACKETANGLEBRACKETLEFT / ANGLEBRACKETANGLEBRACKETRIGHT) ShiftExpr)* | ||
| 1082 | fn shiftExpr(parser: *Parser) !*Node { | ||
| 1083 | @panic("TODO"); | ||
| 1084 | } | ||
| 1085 | |||
| 1086 | /// AdditiveExpr <- MultiplicativeExpr (PLUS / MINUS) AdditiveExpr)* | ||
| 1087 | fn additiveExpr(parser: *Parser) !*Node { | ||
| 1088 | @panic("TODO"); | ||
| 1089 | } | ||
| 1090 | |||
| 1091 | /// MultiplicativeExpr <- UnaryExpr (ASTERISK / SLASH / PERCENT) MultiplicativeExpr)* | ||
| 1092 | fn multiplicativeExpr(parser: *Parser) !*Node { | ||
| 1093 | @panic("TODO"); | ||
| 1094 | } | ||
| 1095 | |||
| 1096 | /// UnaryExpr | ||
| 1097 | /// <- LPAREN TypeName RPAREN UnaryExpr | ||
| 1098 | /// / Keyword_sizeof LAPERN TypeName RPAREN | ||
| 1099 | /// / Keyword_sizeof UnaryExpr | ||
| 1100 | /// / Keyword_alignof LAPERN TypeName RPAREN | ||
| 1101 | /// / (AMPERSAND / ASTERISK / PLUS / PLUSPLUS / MINUS / MINUSMINUS / TILDE / BANG) UnaryExpr | ||
| 1102 | /// / PrimaryExpr PostFixExpr* | ||
| 1103 | fn unaryExpr(parser: *Parser) !*Node { | ||
| 1104 | @panic("TODO"); | ||
| 1105 | } | ||
| 1106 | |||
| 1107 | /// PrimaryExpr | ||
| 1108 | /// <- IDENTIFIER | ||
| 1109 | /// / INTEGERLITERAL / FLOATLITERAL / STRINGLITERAL / CHARLITERAL | ||
| 1110 | /// / LPAREN Expr RPAREN | ||
| 1111 | /// / Keyword_generic LPAREN AssignmentExpr (COMMA Generic)+ RPAREN | ||
| 1112 | fn primaryExpr(parser: *Parser) !*Node { | ||
| 1113 | @panic("TODO"); | ||
| 1114 | } | ||
| 1115 | |||
| 1116 | /// Generic | ||
| 1117 | /// <- TypeName COLON AssignmentExpr | ||
| 1118 | /// / Keyword_default COLON AssignmentExpr | ||
| 1119 | fn generic(parser: *Parser) !*Node { | ||
| 1120 | @panic("TODO"); | ||
| 1121 | } | ||
| 1122 | |||
| 1123 | /// PostFixExpr | ||
| 1124 | /// <- LPAREN TypeName RPAREN LBRACE Initializers RBRACE | ||
| 1125 | /// / LBRACKET Expr RBRACKET | ||
| 1126 | /// / LPAREN (AssignmentExpr (COMMA AssignmentExpr)*)? RPAREN | ||
| 1127 | /// / (PERIOD / ARROW) IDENTIFIER | ||
| 1128 | /// / (PLUSPLUS / MINUSMINUS) | ||
| 1129 | fn postFixExpr(parser: *Parser) !*Node { | ||
| 1130 | @panic("TODO"); | ||
| 1131 | } | ||
| 1132 | |||
| 1133 | /// Initializers <- ((Designator+ EQUAL)? Initializer COMMA)* (Designator+ EQUAL)? Initializer COMMA? | ||
| 1134 | fn initializers(parser: *Parser) !*Node { | ||
| 1135 | @panic("TODO"); | ||
| 1136 | } | ||
| 1137 | |||
| 1138 | /// Initializer | ||
| 1139 | /// <- LBRACE Initializers RBRACE | ||
| 1140 | /// / AssignmentExpr | ||
| 1141 | fn initializer(parser: *Parser, dr: *Node.Declarator) Error!?*Node { | ||
| 1142 | @panic("TODO"); | ||
| 1143 | } | ||
| 1144 | |||
| 1145 | /// Designator | ||
| 1146 | /// <- LBRACKET ConstExpr RBRACKET | ||
| 1147 | /// / PERIOD IDENTIFIER | ||
| 1148 | fn designator(parser: *Parser) !*Node { | ||
| 1149 | @panic("TODO"); | ||
| 1150 | } | ||
| 1151 | |||
| 1152 | /// CompoundStmt <- LBRACE (Declaration / Stmt)* RBRACE | ||
| 1153 | fn compoundStmt(parser: *Parser) Error!?*Node { | ||
| 1154 | const lbrace = parser.eatToken(.LBrace) orelse return null; | ||
| 1155 | try parser.pushScope(.Block); | ||
| 1156 | defer parser.popScope(); | ||
| 1157 | const body_node = try parser.arena.create(Node.CompoundStmt); | ||
| 1158 | body_node.* = .{ | ||
| 1159 | .lbrace = lbrace, | ||
| 1160 | .statements = Node.CompoundStmt.StmtList.init(parser.arena), | ||
| 1161 | .rbrace = undefined, | ||
| 1162 | }; | ||
| 1163 | while (true) { | ||
| 1164 | if (parser.eatToken(.RBRACE)) |rbrace| { | ||
| 1165 | body_node.rbrace = rbrace; | ||
| 1166 | break; | ||
| 1167 | } | ||
| 1168 | try body_node.statements.push((try parser.declaration()) orelse (try parser.stmt())); | ||
| 1169 | } | ||
| 1170 | return &body_node.base; | ||
| 1171 | } | ||
| 1172 | |||
| 1173 | /// Stmt | ||
| 1174 | /// <- CompoundStmt | ||
| 1175 | /// / Keyword_if LPAREN Expr RPAREN Stmt (Keyword_ELSE Stmt)? | ||
| 1176 | /// / Keyword_switch LPAREN Expr RPAREN Stmt | ||
| 1177 | /// / Keyword_while LPAREN Expr RPAREN Stmt | ||
| 1178 | /// / Keyword_do statement Keyword_while LPAREN Expr RPAREN SEMICOLON | ||
| 1179 | /// / Keyword_for LPAREN (Declaration / ExprStmt) ExprStmt Expr? RPAREN Stmt | ||
| 1180 | /// / Keyword_default COLON Stmt | ||
| 1181 | /// / Keyword_case ConstExpr COLON Stmt | ||
| 1182 | /// / Keyword_goto IDENTIFIER SEMICOLON | ||
| 1183 | /// / Keyword_continue SEMICOLON | ||
| 1184 | /// / Keyword_break SEMICOLON | ||
| 1185 | /// / Keyword_return Expr? SEMICOLON | ||
| 1186 | /// / IDENTIFIER COLON Stmt | ||
| 1187 | /// / ExprStmt | ||
| 1188 | fn stmt(parser: *Parser) Error!*Node { | ||
| 1189 | if (try parser.compoundStmt()) |node| return node; | ||
| 1190 | if (parser.eatToken(.Keyword_if)) |tok| { | ||
| 1191 | const node = try parser.arena.create(Node.IfStmt); | ||
| 1192 | _ = try parser.expectToken(.LParen); | ||
| 1193 | node.* = .{ | ||
| 1194 | .@"if" = tok, | ||
| 1195 | .cond = (try parser.expr()) orelse return parser.err(.{ | ||
| 1196 | .ExpectedExpr = .{ .token = parser.it.index }, | ||
| 1197 | }), | ||
| 1198 | .body = undefined, | ||
| 1199 | .@"else" = null, | ||
| 1200 | }; | ||
| 1201 | _ = try parser.expectToken(.RParen); | ||
| 1202 | node.body = try parser.stmt(); | ||
| 1203 | if (parser.eatToken(.Keyword_else)) |else_tok| { | ||
| 1204 | node.@"else" = .{ | ||
| 1205 | .tok = else_tok, | ||
| 1206 | .body = try parser.stmt(), | ||
| 1207 | }; | ||
| 1208 | } | ||
| 1209 | return &node.base; | ||
| 1210 | } | ||
| 1211 | if (parser.eatToken(.Keyword_while)) |tok| { | ||
| 1212 | try parser.pushScope(.Loop); | ||
| 1213 | defer parser.popScope(); | ||
| 1214 | _ = try parser.expectToken(.LParen); | ||
| 1215 | const cond = (try parser.expr()) orelse return parser.err(.{ | ||
| 1216 | .ExpectedExpr = .{ .token = parser.it.index }, | ||
| 1217 | }); | ||
| 1218 | const rparen = try parser.expectToken(.RParen); | ||
| 1219 | const node = try parser.arena.create(Node.WhileStmt); | ||
| 1220 | node.* = .{ | ||
| 1221 | .@"while" = tok, | ||
| 1222 | .cond = cond, | ||
| 1223 | .rparen = rparen, | ||
| 1224 | .body = try parser.stmt(), | ||
| 1225 | .semicolon = try parser.expectToken(.Semicolon), | ||
| 1226 | }; | ||
| 1227 | return &node.base; | ||
| 1228 | } | ||
| 1229 | if (parser.eatToken(.Keyword_do)) |tok| { | ||
| 1230 | try parser.pushScope(.Loop); | ||
| 1231 | defer parser.popScope(); | ||
| 1232 | const body = try parser.stmt(); | ||
| 1233 | _ = try parser.expectToken(.LParen); | ||
| 1234 | const cond = (try parser.expr()) orelse return parser.err(.{ | ||
| 1235 | .ExpectedExpr = .{ .token = parser.it.index }, | ||
| 1236 | }); | ||
| 1237 | _ = try parser.expectToken(.RParen); | ||
| 1238 | const node = try parser.arena.create(Node.DoStmt); | ||
| 1239 | node.* = .{ | ||
| 1240 | .do = tok, | ||
| 1241 | .body = body, | ||
| 1242 | .cond = cond, | ||
| 1243 | .@"while" = @"while", | ||
| 1244 | .semicolon = try parser.expectToken(.Semicolon), | ||
| 1245 | }; | ||
| 1246 | return &node.base; | ||
| 1247 | } | ||
| 1248 | if (parser.eatToken(.Keyword_for)) |tok| { | ||
| 1249 | try parser.pushScope(.Loop); | ||
| 1250 | defer parser.popScope(); | ||
| 1251 | _ = try parser.expectToken(.LParen); | ||
| 1252 | const init = if (try parser.declaration()) |decl| blk: { | ||
| 1253 | // TODO disallow storage class other than auto and register | ||
| 1254 | break :blk decl; | ||
| 1255 | } else try parser.exprStmt(); | ||
| 1256 | const cond = try parser.expr(); | ||
| 1257 | const semicolon = try parser.expectToken(.Semicolon); | ||
| 1258 | const incr = try parser.expr(); | ||
| 1259 | const rparen = try parser.expectToken(.RParen); | ||
| 1260 | const node = try parser.arena.create(Node.ForStmt); | ||
| 1261 | node.* = .{ | ||
| 1262 | .@"for" = tok, | ||
| 1263 | .init = init, | ||
| 1264 | .cond = cond, | ||
| 1265 | .semicolon = semicolon, | ||
| 1266 | .incr = incr, | ||
| 1267 | .rparen = rparen, | ||
| 1268 | .body = try parser.stmt(), | ||
| 1269 | }; | ||
| 1270 | return &node.base; | ||
| 1271 | } | ||
| 1272 | if (parser.eatToken(.Keyword_switch)) |tok| { | ||
| 1273 | try parser.pushScope(.Switch); | ||
| 1274 | defer parser.popScope(); | ||
| 1275 | _ = try parser.expectToken(.LParen); | ||
| 1276 | const switch_expr = try parser.exprStmt(); | ||
| 1277 | const rparen = try parser.expectToken(.RParen); | ||
| 1278 | const node = try parser.arena.create(Node.SwitchStmt); | ||
| 1279 | node.* = .{ | ||
| 1280 | .@"switch" = tok, | ||
| 1281 | .expr = switch_expr, | ||
| 1282 | .rparen = rparen, | ||
| 1283 | .body = try parser.stmt(), | ||
| 1284 | }; | ||
| 1285 | return &node.base; | ||
| 1286 | } | ||
| 1287 | if (parser.eatToken(.Keyword_default)) |tok| { | ||
| 1288 | _ = try parser.expectToken(.Colon); | ||
| 1289 | const node = try parser.arena.create(Node.LabeledStmt); | ||
| 1290 | node.* = .{ | ||
| 1291 | .kind = .{ .Default = tok }, | ||
| 1292 | .stmt = try parser.stmt(), | ||
| 1293 | }; | ||
| 1294 | return &node.base; | ||
| 1295 | } | ||
| 1296 | if (parser.eatToken(.Keyword_case)) |tok| { | ||
| 1297 | _ = try parser.expectToken(.Colon); | ||
| 1298 | const node = try parser.arena.create(Node.LabeledStmt); | ||
| 1299 | node.* = .{ | ||
| 1300 | .kind = .{ .Case = tok }, | ||
| 1301 | .stmt = try parser.stmt(), | ||
| 1302 | }; | ||
| 1303 | return &node.base; | ||
| 1304 | } | ||
| 1305 | if (parser.eatToken(.Keyword_goto)) |tok| { | ||
| 1306 | const node = try parser.arena.create(Node.JumpStmt); | ||
| 1307 | node.* = .{ | ||
| 1308 | .ltoken = tok, | ||
| 1309 | .kind = .{ .Goto = tok }, | ||
| 1310 | .semicolon = try parser.expectToken(.Semicolon), | ||
| 1311 | }; | ||
| 1312 | return &node.base; | ||
| 1313 | } | ||
| 1314 | if (parser.eatToken(.Keyword_continue)) |tok| { | ||
| 1315 | const node = try parser.arena.create(Node.JumpStmt); | ||
| 1316 | node.* = .{ | ||
| 1317 | .ltoken = tok, | ||
| 1318 | .kind = .Continue, | ||
| 1319 | .semicolon = try parser.expectToken(.Semicolon), | ||
| 1320 | }; | ||
| 1321 | return &node.base; | ||
| 1322 | } | ||
| 1323 | if (parser.eatToken(.Keyword_break)) |tok| { | ||
| 1324 | const node = try parser.arena.create(Node.JumpStmt); | ||
| 1325 | node.* = .{ | ||
| 1326 | .ltoken = tok, | ||
| 1327 | .kind = .Break, | ||
| 1328 | .semicolon = try parser.expectToken(.Semicolon), | ||
| 1329 | }; | ||
| 1330 | return &node.base; | ||
| 1331 | } | ||
| 1332 | if (parser.eatToken(.Keyword_return)) |tok| { | ||
| 1333 | const node = try parser.arena.create(Node.JumpStmt); | ||
| 1334 | node.* = .{ | ||
| 1335 | .ltoken = tok, | ||
| 1336 | .kind = .{ .Return = try parser.expr() }, | ||
| 1337 | .semicolon = try parser.expectToken(.Semicolon), | ||
| 1338 | }; | ||
| 1339 | return &node.base; | ||
| 1340 | } | ||
| 1341 | if (parser.eatToken(.Identifier)) |tok| { | ||
| 1342 | if (parser.eatToken(.Colon)) |_| { | ||
| 1343 | const node = try parser.arena.create(Node.LabeledStmt); | ||
| 1344 | node.* = .{ | ||
| 1345 | .kind = .{ .Label = tok }, | ||
| 1346 | .stmt = try parser.stmt(), | ||
| 1347 | }; | ||
| 1348 | return &node.base; | ||
| 1349 | } | ||
| 1350 | parser.putBackToken(tok); | ||
| 1351 | } | ||
| 1352 | return parser.exprStmt(); | ||
| 1353 | } | ||
| 1354 | |||
| 1355 | /// ExprStmt <- Expr? SEMICOLON | ||
| 1356 | fn exprStmt(parser: *Parser) !*Node { | ||
| 1357 | const node = try parser.arena.create(Node.ExprStmt); | ||
| 1358 | node.* = .{ | ||
| 1359 | .expr = try parser.expr(), | ||
| 1360 | .semicolon = try parser.expectToken(.Semicolon), | ||
| 1361 | }; | ||
| 1362 | return &node.base; | ||
| 1363 | } | ||
| 1364 | |||
| 1365 | fn eatToken(parser: *Parser, id: std.meta.Tag(Token.Id)) ?TokenIndex { | ||
| 1366 | while (true) { | ||
| 1367 | switch ((parser.it.next() orelse return null).id) { | ||
| 1368 | .LineComment, .MultiLineComment, .Nl => continue, | ||
| 1369 | else => |next_id| if (next_id == id) { | ||
| 1370 | return parser.it.index; | ||
| 1371 | } else { | ||
| 1372 | _ = parser.it.prev(); | ||
| 1373 | return null; | ||
| 1374 | }, | ||
| 1375 | } | ||
| 1376 | } | ||
| 1377 | } | ||
| 1378 | |||
| 1379 | fn expectToken(parser: *Parser, id: std.meta.Tag(Token.Id)) Error!TokenIndex { | ||
| 1380 | while (true) { | ||
| 1381 | switch ((parser.it.next() orelse return error.ParseError).id) { | ||
| 1382 | .LineComment, .MultiLineComment, .Nl => continue, | ||
| 1383 | else => |next_id| if (next_id != id) { | ||
| 1384 | return parser.err(.{ | ||
| 1385 | .ExpectedToken = .{ .token = parser.it.index, .expected_id = id }, | ||
| 1386 | }); | ||
| 1387 | } else { | ||
| 1388 | return parser.it.index; | ||
| 1389 | }, | ||
| 1390 | } | ||
| 1391 | } | ||
| 1392 | } | ||
| 1393 | |||
| 1394 | fn putBackToken(parser: *Parser, putting_back: TokenIndex) void { | ||
| 1395 | while (true) { | ||
| 1396 | const prev_tok = parser.it.next() orelse return; | ||
| 1397 | switch (prev_tok.id) { | ||
| 1398 | .LineComment, .MultiLineComment, .Nl => continue, | ||
| 1399 | else => { | ||
| 1400 | assert(parser.it.list.at(putting_back) == prev_tok); | ||
| 1401 | return; | ||
| 1402 | }, | ||
| 1403 | } | ||
| 1404 | } | ||
| 1405 | } | ||
| 1406 | |||
| 1407 | fn err(parser: *Parser, msg: ast.Error) Error { | ||
| 1408 | try parser.tree.msgs.push(.{ | ||
| 1409 | .kind = .Error, | ||
| 1410 | .inner = msg, | ||
| 1411 | }); | ||
| 1412 | return error.ParseError; | ||
| 1413 | } | ||
| 1414 | |||
| 1415 | fn warn(parser: *Parser, msg: ast.Error) Error!void { | ||
| 1416 | const is_warning = switch (parser.options.warn_as_err) { | ||
| 1417 | .None => true, | ||
| 1418 | .Some => |list| for (list) |item| (if (item == msg) break false) else true, | ||
| 1419 | .All => false, | ||
| 1420 | }; | ||
| 1421 | try parser.tree.msgs.push(.{ | ||
| 1422 | .kind = if (is_warning) .Warning else .Error, | ||
| 1423 | .inner = msg, | ||
| 1424 | }); | ||
| 1425 | if (!is_warning) return error.ParseError; | ||
| 1426 | } | ||
| 1427 | |||
| 1428 | fn note(parser: *Parser, msg: ast.Error) Error!void { | ||
| 1429 | try parser.tree.msgs.push(.{ | ||
| 1430 | .kind = .Note, | ||
| 1431 | .inner = msg, | ||
| 1432 | }); | ||
| 1433 | } | ||
| 1434 | }; | ||
lib/std/compress/deflate.zig+2-4| ... | @@ -662,14 +662,12 @@ test "lengths overflow" { | ... | @@ -662,14 +662,12 @@ test "lengths overflow" { |
| 662 | // malformed final dynamic block, tries to write 321 code lengths (MAXCODES is 316) | 662 | // malformed final dynamic block, tries to write 321 code lengths (MAXCODES is 316) |
| 663 | // f dy hlit hdist hclen 16 17 18 0 (18) x138 (18) x138 (18) x39 (16) x6 | 663 | // f dy hlit hdist hclen 16 17 18 0 (18) x138 (18) x138 (18) x39 (16) x6 |
| 664 | // 1 10 11101 11101 0000 010 010 010 010 (11) 1111111 (11) 1111111 (11) 0011100 (01) 11 | 664 | // 1 10 11101 11101 0000 010 010 010 010 (11) 1111111 (11) 1111111 (11) 0011100 (01) 11 |
| 665 | const stream = [_]u8{ | 665 | const stream = [_]u8{ 0b11101101, 0b00011101, 0b00100100, 0b11101001, 0b11111111, 0b11111111, 0b00111001, 0b00001110 }; |
| 666 | 0b11101101, 0b00011101, 0b00100100, 0b11101001, 0b11111111, 0b11111111, 0b00111001, 0b00001110 | ||
| 667 | }; | ||
| 668 | 666 | ||
| 669 | const reader = std.io.fixedBufferStream(&stream).reader(); | 667 | const reader = std.io.fixedBufferStream(&stream).reader(); |
| 670 | var window: [0x8000]u8 = undefined; | 668 | var window: [0x8000]u8 = undefined; |
| 671 | var inflate = inflateStream(reader, &window); | 669 | var inflate = inflateStream(reader, &window); |
| 672 | 670 | ||
| 673 | var buf: [1]u8 = undefined; | 671 | var buf: [1]u8 = undefined; |
| 674 | std.testing.expectError(error.InvalidLength, inflate.read(&buf)); | 672 | std.testing.expectError(error.InvalidLength, inflate.read(&buf)); |
| 675 | } | 673 | } |
lib/std/crypto.zig+1| ... | @@ -67,6 +67,7 @@ pub const dh = struct { | ... | @@ -67,6 +67,7 @@ pub const dh = struct { |
| 67 | pub const ecc = struct { | 67 | pub const ecc = struct { |
| 68 | pub const Curve25519 = @import("crypto/25519/curve25519.zig").Curve25519; | 68 | pub const Curve25519 = @import("crypto/25519/curve25519.zig").Curve25519; |
| 69 | pub const Edwards25519 = @import("crypto/25519/edwards25519.zig").Edwards25519; | 69 | pub const Edwards25519 = @import("crypto/25519/edwards25519.zig").Edwards25519; |
| 70 | pub const P256 = @import("crypto/pcurves/p256.zig").P256; | ||
| 70 | pub const Ristretto255 = @import("crypto/25519/ristretto255.zig").Ristretto255; | 71 | pub const Ristretto255 = @import("crypto/25519/ristretto255.zig").Ristretto255; |
| 71 | }; | 72 | }; |
| 72 | 73 |
lib/std/crypto/pcurves/common.zig created+284| ... | @@ -0,0 +1,284 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const builtin = std.builtin; | ||
| 3 | const crypto = std.crypto; | ||
| 4 | const debug = std.debug; | ||
| 5 | const mem = std.mem; | ||
| 6 | const meta = std.meta; | ||
| 7 | |||
| 8 | const NonCanonicalError = crypto.errors.NonCanonicalError; | ||
| 9 | const NotSquareError = crypto.errors.NotSquareError; | ||
| 10 | |||
| 11 | /// Parameters to create a finite field type. | ||
| 12 | pub const FieldParams = struct { | ||
| 13 | fiat: type, | ||
| 14 | field_order: comptime_int, | ||
| 15 | field_bits: comptime_int, | ||
| 16 | saturated_bits: comptime_int, | ||
| 17 | encoded_length: comptime_int, | ||
| 18 | }; | ||
| 19 | |||
| 20 | /// A field element, internally stored in Montgomery domain. | ||
| 21 | pub fn Field(comptime params: FieldParams) type { | ||
| 22 | const fiat = params.fiat; | ||
| 23 | const Limbs = fiat.Limbs; | ||
| 24 | |||
| 25 | return struct { | ||
| 26 | const Fe = @This(); | ||
| 27 | |||
| 28 | limbs: Limbs, | ||
| 29 | |||
| 30 | /// Field size. | ||
| 31 | pub const field_order = params.field_order; | ||
| 32 | |||
| 33 | /// Number of bits to represent the set of all elements. | ||
| 34 | pub const field_bits = params.field_bits; | ||
| 35 | |||
| 36 | /// Number of bits that can be saturated without overflowing. | ||
| 37 | pub const saturated_bits = params.saturated_bits; | ||
| 38 | |||
| 39 | /// Number of bytes required to encode an element. | ||
| 40 | pub const encoded_length = params.encoded_length; | ||
| 41 | |||
| 42 | /// Zero. | ||
| 43 | pub const zero: Fe = Fe{ .limbs = mem.zeroes(Limbs) }; | ||
| 44 | |||
| 45 | /// One. | ||
| 46 | pub const one = comptime one: { | ||
| 47 | var fe: Fe = undefined; | ||
| 48 | fiat.setOne(&fe.limbs); | ||
| 49 | break :one fe; | ||
| 50 | }; | ||
| 51 | |||
| 52 | /// Reject non-canonical encodings of an element. | ||
| 53 | pub fn rejectNonCanonical(s_: [encoded_length]u8, endian: builtin.Endian) NonCanonicalError!void { | ||
| 54 | var s = if (endian == .Little) s_ else orderSwap(s_); | ||
| 55 | const field_order_s = comptime fos: { | ||
| 56 | var fos: [encoded_length]u8 = undefined; | ||
| 57 | mem.writeIntLittle(std.meta.Int(.unsigned, encoded_length * 8), &fos, field_order); | ||
| 58 | break :fos fos; | ||
| 59 | }; | ||
| 60 | if (crypto.utils.timingSafeCompare(u8, &s, &field_order_s, .Little) != .lt) { | ||
| 61 | return error.NonCanonical; | ||
| 62 | } | ||
| 63 | } | ||
| 64 | |||
| 65 | /// Swap the endianness of an encoded element. | ||
| 66 | pub fn orderSwap(s: [encoded_length]u8) [encoded_length]u8 { | ||
| 67 | var t = s; | ||
| 68 | for (s) |x, i| t[t.len - 1 - i] = x; | ||
| 69 | return t; | ||
| 70 | } | ||
| 71 | |||
| 72 | /// Unpack a field element. | ||
| 73 | pub fn fromBytes(s_: [encoded_length]u8, endian: builtin.Endian) NonCanonicalError!Fe { | ||
| 74 | var s = if (endian == .Little) s_ else orderSwap(s_); | ||
| 75 | try rejectNonCanonical(s, .Little); | ||
| 76 | var limbs_z: Limbs = undefined; | ||
| 77 | fiat.fromBytes(&limbs_z, s); | ||
| 78 | var limbs: Limbs = undefined; | ||
| 79 | fiat.toMontgomery(&limbs, limbs_z); | ||
| 80 | return Fe{ .limbs = limbs }; | ||
| 81 | } | ||
| 82 | |||
| 83 | /// Pack a field element. | ||
| 84 | pub fn toBytes(fe: Fe, endian: builtin.Endian) [encoded_length]u8 { | ||
| 85 | var limbs_z: Limbs = undefined; | ||
| 86 | fiat.fromMontgomery(&limbs_z, fe.limbs); | ||
| 87 | var s: [encoded_length]u8 = undefined; | ||
| 88 | fiat.toBytes(&s, limbs_z); | ||
| 89 | return if (endian == .Little) s else orderSwap(s); | ||
| 90 | } | ||
| 91 | |||
| 92 | /// Element as an integer. | ||
| 93 | pub const IntRepr = meta.Int(.unsigned, params.field_bits); | ||
| 94 | |||
| 95 | /// Create a field element from an integer. | ||
| 96 | pub fn fromInt(comptime x: IntRepr) NonCanonicalError!Fe { | ||
| 97 | var s: [encoded_length]u8 = undefined; | ||
| 98 | mem.writeIntLittle(IntRepr, &s, x); | ||
| 99 | return fromBytes(s, .Little); | ||
| 100 | } | ||
| 101 | |||
| 102 | /// Return the field element as an integer. | ||
| 103 | pub fn toInt(fe: Fe) IntRepr { | ||
| 104 | const s = fe.toBytes(.Little); | ||
| 105 | return mem.readIntLittle(IntRepr, &s); | ||
| 106 | } | ||
| 107 | |||
| 108 | /// Return true if the field element is zero. | ||
| 109 | pub fn isZero(fe: Fe) bool { | ||
| 110 | var z: @TypeOf(fe.limbs[0]) = undefined; | ||
| 111 | fiat.nonzero(&z, fe.limbs); | ||
| 112 | return z == 0; | ||
| 113 | } | ||
| 114 | |||
| 115 | /// Return true if both field elements are equivalent. | ||
| 116 | pub fn equivalent(a: Fe, b: Fe) bool { | ||
| 117 | return a.sub(b).isZero(); | ||
| 118 | } | ||
| 119 | |||
| 120 | /// Return true if the element is odd. | ||
| 121 | pub fn isOdd(fe: Fe) bool { | ||
| 122 | const s = fe.toBytes(.Little); | ||
| 123 | return @truncate(u1, s[0]) != 0; | ||
| 124 | } | ||
| 125 | |||
| 126 | /// Conditonally replace a field element with `a` if `c` is positive. | ||
| 127 | pub fn cMov(fe: *Fe, a: Fe, c: u1) void { | ||
| 128 | fiat.selectznz(&fe.limbs, c, fe.limbs, a.limbs); | ||
| 129 | } | ||
| 130 | |||
| 131 | /// Add field elements. | ||
| 132 | pub fn add(a: Fe, b: Fe) Fe { | ||
| 133 | var fe: Fe = undefined; | ||
| 134 | fiat.add(&fe.limbs, a.limbs, b.limbs); | ||
| 135 | return fe; | ||
| 136 | } | ||
| 137 | |||
| 138 | /// Subtract field elements. | ||
| 139 | pub fn sub(a: Fe, b: Fe) Fe { | ||
| 140 | var fe: Fe = undefined; | ||
| 141 | fiat.sub(&fe.limbs, a.limbs, b.limbs); | ||
| 142 | return fe; | ||
| 143 | } | ||
| 144 | |||
| 145 | /// Double a field element. | ||
| 146 | pub fn dbl(a: Fe) Fe { | ||
| 147 | var fe: Fe = undefined; | ||
| 148 | fiat.add(&fe.limbs, a.limbs, a.limbs); | ||
| 149 | return fe; | ||
| 150 | } | ||
| 151 | |||
| 152 | /// Multiply field elements. | ||
| 153 | pub fn mul(a: Fe, b: Fe) Fe { | ||
| 154 | var fe: Fe = undefined; | ||
| 155 | fiat.mul(&fe.limbs, a.limbs, b.limbs); | ||
| 156 | return fe; | ||
| 157 | } | ||
| 158 | |||
| 159 | /// Square a field element. | ||
| 160 | pub fn sq(a: Fe) Fe { | ||
| 161 | var fe: Fe = undefined; | ||
| 162 | fiat.square(&fe.limbs, a.limbs); | ||
| 163 | return fe; | ||
| 164 | } | ||
| 165 | |||
| 166 | /// Square a field element n times. | ||
| 167 | fn sqn(a: Fe, comptime n: comptime_int) Fe { | ||
| 168 | var i: usize = 0; | ||
| 169 | var fe = a; | ||
| 170 | while (i < n) : (i += 1) { | ||
| 171 | fe = fe.sq(); | ||
| 172 | } | ||
| 173 | return fe; | ||
| 174 | } | ||
| 175 | |||
| 176 | /// Compute a^n. | ||
| 177 | pub fn pow(a: Fe, comptime T: type, comptime n: T) Fe { | ||
| 178 | var fe = one; | ||
| 179 | var x: T = n; | ||
| 180 | var t = a; | ||
| 181 | while (true) { | ||
| 182 | if (@truncate(u1, x) != 0) fe = fe.mul(t); | ||
| 183 | x >>= 1; | ||
| 184 | if (x == 0) break; | ||
| 185 | t = t.sq(); | ||
| 186 | } | ||
| 187 | return fe; | ||
| 188 | } | ||
| 189 | |||
| 190 | /// Negate a field element. | ||
| 191 | pub fn neg(a: Fe) Fe { | ||
| 192 | var fe: Fe = undefined; | ||
| 193 | fiat.opp(&fe.limbs, a.limbs); | ||
| 194 | return fe; | ||
| 195 | } | ||
| 196 | |||
| 197 | /// Return the inverse of a field element, or 0 if a=0. | ||
| 198 | // Field inversion from https://eprint.iacr.org/2021/549.pdf | ||
| 199 | pub fn invert(a: Fe) Fe { | ||
| 200 | const iterations = (49 * field_bits + 57) / 17; | ||
| 201 | const Word = @TypeOf(a.limbs[0]); | ||
| 202 | const XLimbs = [a.limbs.len + 1]Word; | ||
| 203 | |||
| 204 | var d: Word = 1; | ||
| 205 | var f: XLimbs = undefined; | ||
| 206 | fiat.msat(&f); | ||
| 207 | |||
| 208 | var g: XLimbs = undefined; | ||
| 209 | fiat.fromMontgomery(g[0..a.limbs.len], a.limbs); | ||
| 210 | g[g.len - 1] = 0; | ||
| 211 | |||
| 212 | var r: Limbs = undefined; | ||
| 213 | fiat.setOne(&r); | ||
| 214 | var v = mem.zeroes(Limbs); | ||
| 215 | |||
| 216 | var precomp: Limbs = undefined; | ||
| 217 | fiat.divstepPrecomp(&precomp); | ||
| 218 | |||
| 219 | var out1: Word = undefined; | ||
| 220 | var out2: XLimbs = undefined; | ||
| 221 | var out3: XLimbs = undefined; | ||
| 222 | var out4: Limbs = undefined; | ||
| 223 | var out5: Limbs = undefined; | ||
| 224 | |||
| 225 | var i: usize = 0; | ||
| 226 | while (i < iterations - iterations % 2) : (i += 2) { | ||
| 227 | fiat.divstep(&out1, &out2, &out3, &out4, &out5, d, f, g, v, r); | ||
| 228 | fiat.divstep(&d, &f, &g, &v, &r, out1, out2, out3, out4, out5); | ||
| 229 | } | ||
| 230 | if (iterations % 2 != 0) { | ||
| 231 | fiat.divstep(&out1, &out2, &out3, &out4, &out5, d, f, g, v, r); | ||
| 232 | mem.copy(Word, &v, &out4); | ||
| 233 | mem.copy(Word, &f, &out2); | ||
| 234 | } | ||
| 235 | var v_opp: Limbs = undefined; | ||
| 236 | fiat.opp(&v_opp, v); | ||
| 237 | fiat.selectznz(&v, @truncate(u1, f[f.len - 1] >> (meta.bitCount(Word) - 1)), v, v_opp); | ||
| 238 | var fe: Fe = undefined; | ||
| 239 | fiat.mul(&fe.limbs, v, precomp); | ||
| 240 | return fe; | ||
| 241 | } | ||
| 242 | |||
| 243 | /// Return true if the field element is a square. | ||
| 244 | pub fn isSquare(x2: Fe) bool { | ||
| 245 | if (field_order == 115792089210356248762697446949407573530086143415290314195533631308867097853951) { | ||
| 246 | const t110 = x2.mul(x2.sq()).sq(); | ||
| 247 | const t111 = x2.mul(t110); | ||
| 248 | const t111111 = t111.mul(x2.mul(t110).sqn(3)); | ||
| 249 | const x15 = t111111.sqn(6).mul(t111111).sqn(3).mul(t111); | ||
| 250 | const x16 = x15.sq().mul(x2); | ||
| 251 | const x53 = x16.sqn(16).mul(x16).sqn(15); | ||
| 252 | const x47 = x15.mul(x53); | ||
| 253 | const ls = x47.mul(((x53.sqn(17).mul(x2)).sqn(143).mul(x47)).sqn(47)).sq().mul(x2); | ||
| 254 | return ls.equivalent(Fe.one); | ||
| 255 | } else { | ||
| 256 | const ls = x2.pow(std.meta.Int(.unsigned, field_bits), (field_order - 1) / 2); // Legendre symbol | ||
| 257 | return ls.equivalent(Fe.one); | ||
| 258 | } | ||
| 259 | } | ||
| 260 | |||
| 261 | // x=x2^((field_order+1)/4) w/ field order=3 (mod 4). | ||
| 262 | fn uncheckedSqrt(x2: Fe) Fe { | ||
| 263 | comptime debug.assert(field_order % 4 == 3); | ||
| 264 | if (field_order == 115792089210356248762697446949407573530086143415290314195533631308867097853951) { | ||
| 265 | const t11 = x2.mul(x2.sq()); | ||
| 266 | const t1111 = t11.mul(t11.sqn(2)); | ||
| 267 | const t11111111 = t1111.mul(t1111.sqn(4)); | ||
| 268 | const x16 = t11111111.sqn(8).mul(t11111111); | ||
| 269 | return x16.sqn(16).mul(x16).sqn(32).mul(x2).sqn(96).mul(x2).sqn(94); | ||
| 270 | } else { | ||
| 271 | return x2.pow(std.meta.Int(.unsigned, field_bits), (field_order + 1) / 4); | ||
| 272 | } | ||
| 273 | } | ||
| 274 | |||
| 275 | /// Compute the square root of `x2`, returning `error.NotSquare` if `x2` was not a square. | ||
| 276 | pub fn sqrt(x2: Fe) NotSquareError!Fe { | ||
| 277 | const x = x2.uncheckedSqrt(); | ||
| 278 | if (x.sq().equivalent(x2)) { | ||
| 279 | return x; | ||
| 280 | } | ||
| 281 | return error.NotSquare; | ||
| 282 | } | ||
| 283 | }; | ||
| 284 | } | ||
lib/std/crypto/pcurves/p256.zig created+412| ... | @@ -0,0 +1,412 @@ | ||
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2021 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 6 | |||
| 7 | const std = @import("std"); | ||
| 8 | const builtin = std.builtin; | ||
| 9 | const crypto = std.crypto; | ||
| 10 | const mem = std.mem; | ||
| 11 | const meta = std.meta; | ||
| 12 | |||
| 13 | const EncodingError = crypto.errors.EncodingError; | ||
| 14 | const IdentityElementError = crypto.errors.IdentityElementError; | ||
| 15 | const NonCanonicalError = crypto.errors.NonCanonicalError; | ||
| 16 | const NotSquareError = crypto.errors.NotSquareError; | ||
| 17 | |||
| 18 | /// Group operations over P256. | ||
| 19 | pub const P256 = struct { | ||
| 20 | /// The underlying prime field. | ||
| 21 | pub const Fe = @import("p256/field.zig").Fe; | ||
| 22 | /// Field arithmetic mod the order of the main subgroup. | ||
| 23 | pub const scalar = @import("p256/scalar.zig"); | ||
| 24 | |||
| 25 | x: Fe, | ||
| 26 | y: Fe, | ||
| 27 | z: Fe = Fe.one, | ||
| 28 | |||
| 29 | is_base: bool = false, | ||
| 30 | |||
| 31 | /// The P256 base point. | ||
| 32 | pub const basePoint = P256{ | ||
| 33 | .x = try Fe.fromInt(48439561293906451759052585252797914202762949526041747995844080717082404635286), | ||
| 34 | .y = try Fe.fromInt(36134250956749795798585127919587881956611106672985015071877198253568414405109), | ||
| 35 | .z = Fe.one, | ||
| 36 | .is_base = true, | ||
| 37 | }; | ||
| 38 | |||
| 39 | /// The P256 neutral element. | ||
| 40 | pub const identityElement = P256{ .x = Fe.zero, .y = Fe.one, .z = Fe.zero }; | ||
| 41 | |||
| 42 | pub const B = try Fe.fromInt(41058363725152142129326129780047268409114441015993725554835256314039467401291); | ||
| 43 | |||
| 44 | /// Reject the neutral element. | ||
| 45 | pub fn rejectIdentity(p: P256) IdentityElementError!void { | ||
| 46 | if (p.x.isZero()) { | ||
| 47 | return error.IdentityElement; | ||
| 48 | } | ||
| 49 | } | ||
| 50 | |||
| 51 | /// Create a point from affine coordinates after checking that they match the curve equation. | ||
| 52 | pub fn fromAffineCoordinates(x: Fe, y: Fe) EncodingError!P256 { | ||
| 53 | const x3AxB = x.sq().mul(x).sub(x).sub(x).sub(x).add(B); | ||
| 54 | const yy = y.sq(); | ||
| 55 | if (!x3AxB.equivalent(yy)) { | ||
| 56 | return error.InvalidEncoding; | ||
| 57 | } | ||
| 58 | const p: P256 = .{ .x = x, .y = y, .z = Fe.one }; | ||
| 59 | return p; | ||
| 60 | } | ||
| 61 | |||
| 62 | /// Create a point from serialized affine coordinates. | ||
| 63 | pub fn fromSerializedAffineCoordinates(xs: [32]u8, ys: [32]u8, endian: builtin.Endian) (NonCanonicalError || EncodingError)!P256 { | ||
| 64 | const x = try Fe.fromBytes(xs, endian); | ||
| 65 | const y = try Fe.fromBytes(ys, endian); | ||
| 66 | return fromAffineCoordinates(x, y); | ||
| 67 | } | ||
| 68 | |||
| 69 | /// Recover the Y coordinate from the X coordinate. | ||
| 70 | pub fn recoverY(x: Fe, is_odd: bool) NotSquareError!Fe { | ||
| 71 | const x3AxB = x.sq().mul(x).sub(x).sub(x).sub(x).add(B); | ||
| 72 | var y = try x3AxB.sqrt(); | ||
| 73 | const yn = y.neg(); | ||
| 74 | y.cMov(yn, @boolToInt(is_odd) ^ @boolToInt(y.isOdd())); | ||
| 75 | return y; | ||
| 76 | } | ||
| 77 | |||
| 78 | /// Deserialize a SEC1-encoded point. | ||
| 79 | pub fn fromSec1(s: []const u8) (EncodingError || NotSquareError || NonCanonicalError)!P256 { | ||
| 80 | if (s.len < 1) return error.InvalidEncoding; | ||
| 81 | const encoding_type = s[0]; | ||
| 82 | const encoded = s[1..]; | ||
| 83 | switch (encoding_type) { | ||
| 84 | 0 => { | ||
| 85 | if (encoded.len != 0) return error.InvalidEncoding; | ||
| 86 | return P256.identityElement; | ||
| 87 | }, | ||
| 88 | 2, 3 => { | ||
| 89 | if (encoded.len != 32) return error.InvalidEncoding; | ||
| 90 | const x = try Fe.fromBytes(encoded[0..32].*, .Big); | ||
| 91 | const y_is_odd = (encoding_type == 3); | ||
| 92 | const y = try recoverY(x, y_is_odd); | ||
| 93 | return P256{ .x = x, .y = y }; | ||
| 94 | }, | ||
| 95 | 4 => { | ||
| 96 | if (encoded.len != 64) return error.InvalidEncoding; | ||
| 97 | const x = try Fe.fromBytes(encoded[0..32].*, .Big); | ||
| 98 | const y = try Fe.fromBytes(encoded[32..64].*, .Big); | ||
| 99 | return P256.fromAffineCoordinates(x, y); | ||
| 100 | }, | ||
| 101 | else => return error.InvalidEncoding, | ||
| 102 | } | ||
| 103 | } | ||
| 104 | |||
| 105 | /// Serialize a point using the compressed SEC-1 format. | ||
| 106 | pub fn toCompressedSec1(p: P256) [33]u8 { | ||
| 107 | var out: [33]u8 = undefined; | ||
| 108 | const xy = p.affineCoordinates(); | ||
| 109 | out[0] = if (xy.y.isOdd()) 3 else 2; | ||
| 110 | mem.copy(u8, out[1..], &xy.x.toBytes(.Big)); | ||
| 111 | return out; | ||
| 112 | } | ||
| 113 | |||
| 114 | /// Serialize a point using the uncompressed SEC-1 format. | ||
| 115 | pub fn toUncompressedSec1(p: P256) [65]u8 { | ||
| 116 | var out: [65]u8 = undefined; | ||
| 117 | out[0] = 4; | ||
| 118 | const xy = p.affineCoordinates(); | ||
| 119 | mem.copy(u8, out[1..33], &xy.x.toBytes(.Big)); | ||
| 120 | mem.copy(u8, out[33..65], &xy.y.toBytes(.Big)); | ||
| 121 | return out; | ||
| 122 | } | ||
| 123 | |||
| 124 | /// Return a random point. | ||
| 125 | pub fn random() P256 { | ||
| 126 | const n = scalar.random(.Little); | ||
| 127 | return basePoint.mul(n, .Little) catch unreachable; | ||
| 128 | } | ||
| 129 | |||
| 130 | /// Flip the sign of the X coordinate. | ||
| 131 | pub fn neg(p: P256) P256 { | ||
| 132 | return .{ .x = p.x, .y = p.y.neg(), .z = p.z }; | ||
| 133 | } | ||
| 134 | |||
| 135 | /// Double a P256 point. | ||
| 136 | // Algorithm 6 from https://eprint.iacr.org/2015/1060.pdf | ||
| 137 | pub fn dbl(p: P256) P256 { | ||
| 138 | var t0 = p.x.sq(); | ||
| 139 | var t1 = p.y.sq(); | ||
| 140 | var t2 = p.z.sq(); | ||
| 141 | var t3 = p.x.mul(p.y); | ||
| 142 | t3 = t3.dbl(); | ||
| 143 | var Z3 = p.x.mul(p.z); | ||
| 144 | Z3 = Z3.add(Z3); | ||
| 145 | var Y3 = B.mul(t2); | ||
| 146 | Y3 = Y3.sub(Z3); | ||
| 147 | var X3 = Y3.dbl(); | ||
| 148 | Y3 = X3.add(Y3); | ||
| 149 | X3 = t1.sub(Y3); | ||
| 150 | Y3 = t1.add(Y3); | ||
| 151 | Y3 = X3.mul(Y3); | ||
| 152 | X3 = X3.mul(t3); | ||
| 153 | t3 = t2.dbl(); | ||
| 154 | t2 = t2.add(t3); | ||
| 155 | Z3 = B.mul(Z3); | ||
| 156 | Z3 = Z3.sub(t2); | ||
| 157 | Z3 = Z3.sub(t0); | ||
| 158 | t3 = Z3.dbl(); | ||
| 159 | Z3 = Z3.add(t3); | ||
| 160 | t3 = t0.dbl(); | ||
| 161 | t0 = t3.add(t0); | ||
| 162 | t0 = t0.sub(t2); | ||
| 163 | t0 = t0.mul(Z3); | ||
| 164 | Y3 = Y3.add(t0); | ||
| 165 | t0 = p.y.mul(p.z); | ||
| 166 | t0 = t0.dbl(); | ||
| 167 | Z3 = t0.mul(Z3); | ||
| 168 | X3 = X3.sub(Z3); | ||
| 169 | Z3 = t0.mul(t1); | ||
| 170 | Z3 = Z3.dbl().dbl(); | ||
| 171 | return .{ | ||
| 172 | .x = X3, | ||
| 173 | .y = Y3, | ||
| 174 | .z = Z3, | ||
| 175 | }; | ||
| 176 | } | ||
| 177 | |||
| 178 | /// Add P256 points, the second being specified using affine coordinates. | ||
| 179 | // Algorithm 5 from https://eprint.iacr.org/2015/1060.pdf | ||
| 180 | pub fn addMixed(p: P256, q: struct { x: Fe, y: Fe }) P256 { | ||
| 181 | var t0 = p.x.mul(q.x); | ||
| 182 | var t1 = p.y.mul(q.y); | ||
| 183 | var t3 = q.x.add(q.y); | ||
| 184 | var t4 = p.x.add(p.y); | ||
| 185 | t3 = t3.mul(t4); | ||
| 186 | t4 = t0.add(t1); | ||
| 187 | t3 = t3.sub(t4); | ||
| 188 | t4 = q.y.mul(p.z); | ||
| 189 | t4 = t4.add(p.y); | ||
| 190 | var Y3 = q.x.mul(p.z); | ||
| 191 | Y3 = Y3.add(p.x); | ||
| 192 | var Z3 = B.mul(p.z); | ||
| 193 | var X3 = Y3.sub(Z3); | ||
| 194 | Z3 = X3.dbl(); | ||
| 195 | X3 = X3.add(Z3); | ||
| 196 | Z3 = t1.sub(X3); | ||
| 197 | X3 = t1.dbl(); | ||
| 198 | Y3 = B.mul(Y3); | ||
| 199 | t1 = p.z.add(p.z); | ||
| 200 | var t2 = t1.add(p.z); | ||
| 201 | Y3 = Y3.sub(t2); | ||
| 202 | Y3 = Y3.sub(t0); | ||
| 203 | t1 = Y3.dbl(); | ||
| 204 | Y3 = t1.add(Y3); | ||
| 205 | t1 = t0.dbl(); | ||
| 206 | t0 = t1.add(t0); | ||
| 207 | t0 = t0.sub(t2); | ||
| 208 | t1 = t4.mul(Y3); | ||
| 209 | t2 = t0.mul(Y3); | ||
| 210 | Y3 = X3.mul(Z3); | ||
| 211 | Y3 = Y3.add(t2); | ||
| 212 | X3 = t3.mul(X3); | ||
| 213 | X3 = X3.sub(t1); | ||
| 214 | Z3 = t4.mul(Z3); | ||
| 215 | t1 = t3.mul(t0); | ||
| 216 | Z3 = Z3.add(t1); | ||
| 217 | return .{ | ||
| 218 | .x = X3, | ||
| 219 | .y = Y3, | ||
| 220 | .z = Z3, | ||
| 221 | }; | ||
| 222 | } | ||
| 223 | |||
| 224 | // Add P256 points. | ||
| 225 | // Algorithm 4 from https://eprint.iacr.org/2015/1060.pdf | ||
| 226 | pub fn add(p: P256, q: P256) P256 { | ||
| 227 | var t0 = p.x.mul(q.x); | ||
| 228 | var t1 = p.y.mul(q.y); | ||
| 229 | var t2 = p.z.mul(q.z); | ||
| 230 | var t3 = p.x.add(p.y); | ||
| 231 | var t4 = q.x.add(q.y); | ||
| 232 | t3 = t3.mul(t4); | ||
| 233 | t4 = t0.add(t1); | ||
| 234 | t3 = t3.sub(t4); | ||
| 235 | t4 = p.y.add(p.z); | ||
| 236 | var X3 = q.y.add(q.z); | ||
| 237 | t4 = t4.mul(X3); | ||
| 238 | X3 = t1.add(t2); | ||
| 239 | t4 = t4.sub(X3); | ||
| 240 | X3 = p.x.add(p.z); | ||
| 241 | var Y3 = q.x.add(q.z); | ||
| 242 | X3 = X3.mul(Y3); | ||
| 243 | Y3 = t0.add(t2); | ||
| 244 | Y3 = X3.sub(Y3); | ||
| 245 | var Z3 = B.mul(t2); | ||
| 246 | X3 = Y3.sub(Z3); | ||
| 247 | Z3 = X3.dbl(); | ||
| 248 | X3 = X3.add(Z3); | ||
| 249 | Z3 = t1.sub(X3); | ||
| 250 | X3 = t1.add(X3); | ||
| 251 | Y3 = B.mul(Y3); | ||
| 252 | t1 = t2.dbl(); | ||
| 253 | t2 = t1.add(t2); | ||
| 254 | Y3 = Y3.sub(t2); | ||
| 255 | Y3 = Y3.sub(t0); | ||
| 256 | t1 = Y3.dbl(); | ||
| 257 | Y3 = t1.add(Y3); | ||
| 258 | t1 = t0.dbl(); | ||
| 259 | t0 = t1.add(t0); | ||
| 260 | t0 = t0.sub(t2); | ||
| 261 | t1 = t4.mul(Y3); | ||
| 262 | t2 = t0.mul(Y3); | ||
| 263 | Y3 = X3.mul(Z3); | ||
| 264 | Y3 = Y3.add(t2); | ||
| 265 | X3 = t3.mul(X3); | ||
| 266 | X3 = X3.sub(t1); | ||
| 267 | Z3 = t4.mul(Z3); | ||
| 268 | t1 = t3.mul(t0); | ||
| 269 | Z3 = Z3.add(t1); | ||
| 270 | return .{ | ||
| 271 | .x = X3, | ||
| 272 | .y = Y3, | ||
| 273 | .z = Z3, | ||
| 274 | }; | ||
| 275 | } | ||
| 276 | |||
| 277 | // Subtract P256 points. | ||
| 278 | pub fn sub(p: P256, q: P256) P256 { | ||
| 279 | return p.add(q.neg()); | ||
| 280 | } | ||
| 281 | |||
| 282 | /// Return affine coordinates. | ||
| 283 | pub fn affineCoordinates(p: P256) struct { x: Fe, y: Fe } { | ||
| 284 | const zinv = p.z.invert(); | ||
| 285 | const ret = .{ | ||
| 286 | .x = p.x.mul(zinv), | ||
| 287 | .y = p.y.mul(zinv), | ||
| 288 | }; | ||
| 289 | return ret; | ||
| 290 | } | ||
| 291 | |||
| 292 | /// Return true if both coordinate sets represent the same point. | ||
| 293 | pub fn equivalent(a: P256, b: P256) bool { | ||
| 294 | if (a.sub(b).rejectIdentity()) { | ||
| 295 | return false; | ||
| 296 | } else |_| { | ||
| 297 | return true; | ||
| 298 | } | ||
| 299 | } | ||
| 300 | |||
| 301 | fn cMov(p: *P256, a: P256, c: u1) void { | ||
| 302 | p.x.cMov(a.x, c); | ||
| 303 | p.y.cMov(a.y, c); | ||
| 304 | p.z.cMov(a.z, c); | ||
| 305 | } | ||
| 306 | |||
| 307 | fn pcSelect(comptime n: usize, pc: [n]P256, b: u8) P256 { | ||
| 308 | var t = P256.identityElement; | ||
| 309 | comptime var i: u8 = 1; | ||
| 310 | inline while (i < pc.len) : (i += 1) { | ||
| 311 | t.cMov(pc[i], @truncate(u1, (@as(usize, b ^ i) -% 1) >> 8)); | ||
| 312 | } | ||
| 313 | return t; | ||
| 314 | } | ||
| 315 | |||
| 316 | fn slide(s: [32]u8) [2 * 32 + 1]i8 { | ||
| 317 | var e: [2 * 32 + 1]i8 = undefined; | ||
| 318 | for (s) |x, i| { | ||
| 319 | e[i * 2 + 0] = @as(i8, @truncate(u4, x)); | ||
| 320 | e[i * 2 + 1] = @as(i8, @truncate(u4, x >> 4)); | ||
| 321 | } | ||
| 322 | // Now, e[0..63] is between 0 and 15, e[63] is between 0 and 7 | ||
| 323 | var carry: i8 = 0; | ||
| 324 | for (e[0..64]) |*x| { | ||
| 325 | x.* += carry; | ||
| 326 | carry = (x.* + 8) >> 4; | ||
| 327 | x.* -= carry * 16; | ||
| 328 | std.debug.assert(x.* >= -8 and x.* <= 8); | ||
| 329 | } | ||
| 330 | e[64] = carry; | ||
| 331 | // Now, e[*] is between -8 and 8, including e[64] | ||
| 332 | std.debug.assert(carry >= -8 and carry <= 8); | ||
| 333 | return e; | ||
| 334 | } | ||
| 335 | |||
| 336 | fn pcMul(pc: [9]P256, s: [32]u8, comptime vartime: bool) IdentityElementError!P256 { | ||
| 337 | std.debug.assert(vartime); | ||
| 338 | const e = slide(s); | ||
| 339 | var q = P256.identityElement; | ||
| 340 | var pos = e.len - 1; | ||
| 341 | while (true) : (pos -= 1) { | ||
| 342 | const slot = e[pos]; | ||
| 343 | if (slot > 0) { | ||
| 344 | q = q.add(pc[@intCast(usize, slot)]); | ||
| 345 | } else if (slot < 0) { | ||
| 346 | q = q.sub(pc[@intCast(usize, -slot)]); | ||
| 347 | } | ||
| 348 | if (pos == 0) break; | ||
| 349 | q = q.dbl().dbl().dbl().dbl(); | ||
| 350 | } | ||
| 351 | try q.rejectIdentity(); | ||
| 352 | return q; | ||
| 353 | } | ||
| 354 | |||
| 355 | fn pcMul16(pc: [16]P256, s: [32]u8, comptime vartime: bool) IdentityElementError!P256 { | ||
| 356 | var q = P256.identityElement; | ||
| 357 | var pos: usize = 252; | ||
| 358 | while (true) : (pos -= 4) { | ||
| 359 | const slot = @truncate(u4, (s[pos >> 3] >> @truncate(u3, pos))); | ||
| 360 | if (vartime) { | ||
| 361 | if (slot != 0) { | ||
| 362 | q = q.add(pc[slot]); | ||
| 363 | } | ||
| 364 | } else { | ||
| 365 | q = q.add(pcSelect(16, pc, slot)); | ||
| 366 | } | ||
| 367 | if (pos == 0) break; | ||
| 368 | q = q.dbl().dbl().dbl().dbl(); | ||
| 369 | } | ||
| 370 | try q.rejectIdentity(); | ||
| 371 | return q; | ||
| 372 | } | ||
| 373 | |||
| 374 | fn precompute(p: P256, comptime count: usize) [1 + count]P256 { | ||
| 375 | var pc: [1 + count]P256 = undefined; | ||
| 376 | pc[0] = P256.identityElement; | ||
| 377 | pc[1] = p; | ||
| 378 | var i: usize = 2; | ||
| 379 | while (i <= count) : (i += 1) { | ||
| 380 | pc[i] = if (i % 2 == 0) pc[i / 2].dbl() else pc[i - 1].add(p); | ||
| 381 | } | ||
| 382 | return pc; | ||
| 383 | } | ||
| 384 | |||
| 385 | /// Multiply an elliptic curve point by a scalar. | ||
| 386 | /// Return error.IdentityElement if the result is the identity element. | ||
| 387 | pub fn mul(p: P256, s_: [32]u8, endian: builtin.Endian) IdentityElementError!P256 { | ||
| 388 | const s = if (endian == .Little) s_ else Fe.orderSwap(s_); | ||
| 389 | const pc = if (p.is_base) precompute(P256.basePoint, 15) else pc: { | ||
| 390 | try p.rejectIdentity(); | ||
| 391 | const xpc = precompute(p, 15); | ||
| 392 | break :pc xpc; | ||
| 393 | }; | ||
| 394 | return pcMul16(pc, s, false); | ||
| 395 | } | ||
| 396 | |||
| 397 | /// Multiply an elliptic curve point by a *PUBLIC* scalar *IN VARIABLE TIME* | ||
| 398 | /// This can be used for signature verification. | ||
| 399 | pub fn mulPublic(p: P256, s_: [32]u8, endian: builtin.Endian) IdentityElementError!P256 { | ||
| 400 | const s = if (endian == .Little) s_ else Fe.orderSwap(s_); | ||
| 401 | const pc = if (p.is_base) precompute(P256.basePoint, 8) else pc: { | ||
| 402 | try p.rejectIdentity(); | ||
| 403 | const xpc = precompute(p, 8); | ||
| 404 | break :pc xpc; | ||
| 405 | }; | ||
| 406 | return pcMul(pc, s, true); | ||
| 407 | } | ||
| 408 | }; | ||
| 409 | |||
| 410 | test "p256" { | ||
| 411 | _ = @import("tests.zig"); | ||
| 412 | } | ||
lib/std/crypto/pcurves/p256/field.zig created+18| ... | @@ -0,0 +1,18 @@ | ||
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2021 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 6 | |||
| 7 | const std = @import("std"); | ||
| 8 | const common = @import("../common.zig"); | ||
| 9 | |||
| 10 | const Field = common.Field; | ||
| 11 | |||
| 12 | pub const Fe = Field(.{ | ||
| 13 | .fiat = @import("p256_64.zig"), | ||
| 14 | .field_order = 115792089210356248762697446949407573530086143415290314195533631308867097853951, | ||
| 15 | .field_bits = 256, | ||
| 16 | .saturated_bits = 255, | ||
| 17 | .encoded_length = 32, | ||
| 18 | }); | ||
lib/std/crypto/pcurves/p256/p256_64.zig created+1812| ... | @@ -0,0 +1,1812 @@ | ||
| 1 | // Autogenerated: 'src/ExtractionOCaml/word_by_word_montgomery' --lang Zig --internal-static --public-function-case camelCase --private-function-case camelCase --no-prefix-fiat --package-name p256 '' 64 '2^256 - 2^224 + 2^192 + 2^96 - 1' mul square add sub opp from_montgomery to_montgomery nonzero selectznz to_bytes from_bytes one msat divstep divstep_precomp | ||
| 2 | // curve description (via package name): p256 | ||
| 3 | // machine_wordsize = 64 (from "64") | ||
| 4 | // requested operations: mul, square, add, sub, opp, from_montgomery, to_montgomery, nonzero, selectznz, to_bytes, from_bytes, one, msat, divstep, divstep_precomp | ||
| 5 | // m = 0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff (from "2^256 - 2^224 + 2^192 + 2^96 - 1") | ||
| 6 | // | ||
| 7 | // NOTE: In addition to the bounds specified above each function, all | ||
| 8 | // functions synthesized for this Montgomery arithmetic require the | ||
| 9 | // input to be strictly less than the prime modulus (m), and also | ||
| 10 | // require the input to be in the unique saturated representation. | ||
| 11 | // All functions also ensure that these two properties are true of | ||
| 12 | // return values. | ||
| 13 | // | ||
| 14 | // Computed values: | ||
| 15 | // eval z = z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) | ||
| 16 | // bytes_eval z = z[0] + (z[1] << 8) + (z[2] << 16) + (z[3] << 24) + (z[4] << 32) + (z[5] << 40) + (z[6] << 48) + (z[7] << 56) + (z[8] << 64) + (z[9] << 72) + (z[10] << 80) + (z[11] << 88) + (z[12] << 96) + (z[13] << 104) + (z[14] << 112) + (z[15] << 120) + (z[16] << 128) + (z[17] << 136) + (z[18] << 144) + (z[19] << 152) + (z[20] << 160) + (z[21] << 168) + (z[22] << 176) + (z[23] << 184) + (z[24] << 192) + (z[25] << 200) + (z[26] << 208) + (z[27] << 216) + (z[28] << 224) + (z[29] << 232) + (z[30] << 240) + (z[31] << 248) | ||
| 17 | // twos_complement_eval z = let x1 := z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) in | ||
| 18 | // if x1 & (2^256-1) < 2^255 then x1 & (2^256-1) else (x1 & (2^256-1)) - 2^256 | ||
| 19 | |||
| 20 | const std = @import("std"); | ||
| 21 | const cast = std.meta.cast; | ||
| 22 | const mode = std.builtin.mode; // Checked arithmetic is disabled in non-debug modes to avoid side channels | ||
| 23 | |||
| 24 | pub const Limbs = [4]u64; | ||
| 25 | |||
| 26 | /// The function addcarryxU64 is an addition with carry. | ||
| 27 | /// Postconditions: | ||
| 28 | /// out1 = (arg1 + arg2 + arg3) mod 2^64 | ||
| 29 | /// out2 = ⌊(arg1 + arg2 + arg3) / 2^64⌋ | ||
| 30 | /// | ||
| 31 | /// Input Bounds: | ||
| 32 | /// arg1: [0x0 ~> 0x1] | ||
| 33 | /// arg2: [0x0 ~> 0xffffffffffffffff] | ||
| 34 | /// arg3: [0x0 ~> 0xffffffffffffffff] | ||
| 35 | /// Output Bounds: | ||
| 36 | /// out1: [0x0 ~> 0xffffffffffffffff] | ||
| 37 | /// out2: [0x0 ~> 0x1] | ||
| 38 | fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) callconv(.Inline) void { | ||
| 39 | @setRuntimeSafety(mode == .Debug); | ||
| 40 | |||
| 41 | var t: u64 = undefined; | ||
| 42 | const carry1 = @addWithOverflow(u64, arg2, arg3, &t); | ||
| 43 | const carry2 = @addWithOverflow(u64, t, arg1, out1); | ||
| 44 | out2.* = @boolToInt(carry1) | @boolToInt(carry2); | ||
| 45 | } | ||
| 46 | |||
| 47 | /// The function subborrowxU64 is a subtraction with borrow. | ||
| 48 | /// Postconditions: | ||
| 49 | /// out1 = (-arg1 + arg2 + -arg3) mod 2^64 | ||
| 50 | /// out2 = -⌊(-arg1 + arg2 + -arg3) / 2^64⌋ | ||
| 51 | /// | ||
| 52 | /// Input Bounds: | ||
| 53 | /// arg1: [0x0 ~> 0x1] | ||
| 54 | /// arg2: [0x0 ~> 0xffffffffffffffff] | ||
| 55 | /// arg3: [0x0 ~> 0xffffffffffffffff] | ||
| 56 | /// Output Bounds: | ||
| 57 | /// out1: [0x0 ~> 0xffffffffffffffff] | ||
| 58 | /// out2: [0x0 ~> 0x1] | ||
| 59 | fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) callconv(.Inline) void { | ||
| 60 | @setRuntimeSafety(mode == .Debug); | ||
| 61 | |||
| 62 | var t: u64 = undefined; | ||
| 63 | const carry1 = @subWithOverflow(u64, arg2, arg3, &t); | ||
| 64 | const carry2 = @subWithOverflow(u64, t, arg1, out1); | ||
| 65 | out2.* = @boolToInt(carry1) | @boolToInt(carry2); | ||
| 66 | } | ||
| 67 | |||
| 68 | /// The function mulxU64 is a multiplication, returning the full double-width result. | ||
| 69 | /// Postconditions: | ||
| 70 | /// out1 = (arg1 * arg2) mod 2^64 | ||
| 71 | /// out2 = ⌊arg1 * arg2 / 2^64⌋ | ||
| 72 | /// | ||
| 73 | /// Input Bounds: | ||
| 74 | /// arg1: [0x0 ~> 0xffffffffffffffff] | ||
| 75 | /// arg2: [0x0 ~> 0xffffffffffffffff] | ||
| 76 | /// Output Bounds: | ||
| 77 | /// out1: [0x0 ~> 0xffffffffffffffff] | ||
| 78 | /// out2: [0x0 ~> 0xffffffffffffffff] | ||
| 79 | fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) callconv(.Inline) void { | ||
| 80 | @setRuntimeSafety(mode == .Debug); | ||
| 81 | |||
| 82 | const x = @as(u128, arg1) * @as(u128, arg2); | ||
| 83 | out1.* = @truncate(u64, x); | ||
| 84 | out2.* = @truncate(u64, x >> 64); | ||
| 85 | } | ||
| 86 | |||
| 87 | /// The function cmovznzU64 is a single-word conditional move. | ||
| 88 | /// Postconditions: | ||
| 89 | /// out1 = (if arg1 = 0 then arg2 else arg3) | ||
| 90 | /// | ||
| 91 | /// Input Bounds: | ||
| 92 | /// arg1: [0x0 ~> 0x1] | ||
| 93 | /// arg2: [0x0 ~> 0xffffffffffffffff] | ||
| 94 | /// arg3: [0x0 ~> 0xffffffffffffffff] | ||
| 95 | /// Output Bounds: | ||
| 96 | /// out1: [0x0 ~> 0xffffffffffffffff] | ||
| 97 | fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) callconv(.Inline) void { | ||
| 98 | @setRuntimeSafety(mode == .Debug); | ||
| 99 | |||
| 100 | const mask = 0 -% @as(u64, arg1); | ||
| 101 | out1.* = (mask & arg3) | ((~mask) & arg2); | ||
| 102 | } | ||
| 103 | |||
| 104 | /// The function mul multiplies two field elements in the Montgomery domain. | ||
| 105 | /// Preconditions: | ||
| 106 | /// 0 ≤ eval arg1 < m | ||
| 107 | /// 0 ≤ eval arg2 < m | ||
| 108 | /// Postconditions: | ||
| 109 | /// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) * eval (from_montgomery arg2)) mod m | ||
| 110 | /// 0 ≤ eval out1 < m | ||
| 111 | /// | ||
| 112 | /// Input Bounds: | ||
| 113 | /// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 114 | /// arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 115 | /// Output Bounds: | ||
| 116 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 117 | pub fn mul(out1: *[4]u64, arg1: [4]u64, arg2: [4]u64) void { | ||
| 118 | @setRuntimeSafety(mode == .Debug); | ||
| 119 | |||
| 120 | const x1 = (arg1[1]); | ||
| 121 | const x2 = (arg1[2]); | ||
| 122 | const x3 = (arg1[3]); | ||
| 123 | const x4 = (arg1[0]); | ||
| 124 | var x5: u64 = undefined; | ||
| 125 | var x6: u64 = undefined; | ||
| 126 | mulxU64(&x5, &x6, x4, (arg2[3])); | ||
| 127 | var x7: u64 = undefined; | ||
| 128 | var x8: u64 = undefined; | ||
| 129 | mulxU64(&x7, &x8, x4, (arg2[2])); | ||
| 130 | var x9: u64 = undefined; | ||
| 131 | var x10: u64 = undefined; | ||
| 132 | mulxU64(&x9, &x10, x4, (arg2[1])); | ||
| 133 | var x11: u64 = undefined; | ||
| 134 | var x12: u64 = undefined; | ||
| 135 | mulxU64(&x11, &x12, x4, (arg2[0])); | ||
| 136 | var x13: u64 = undefined; | ||
| 137 | var x14: u1 = undefined; | ||
| 138 | addcarryxU64(&x13, &x14, 0x0, x12, x9); | ||
| 139 | var x15: u64 = undefined; | ||
| 140 | var x16: u1 = undefined; | ||
| 141 | addcarryxU64(&x15, &x16, x14, x10, x7); | ||
| 142 | var x17: u64 = undefined; | ||
| 143 | var x18: u1 = undefined; | ||
| 144 | addcarryxU64(&x17, &x18, x16, x8, x5); | ||
| 145 | const x19 = (cast(u64, x18) + x6); | ||
| 146 | var x20: u64 = undefined; | ||
| 147 | var x21: u64 = undefined; | ||
| 148 | mulxU64(&x20, &x21, x11, 0xffffffff00000001); | ||
| 149 | var x22: u64 = undefined; | ||
| 150 | var x23: u64 = undefined; | ||
| 151 | mulxU64(&x22, &x23, x11, 0xffffffff); | ||
| 152 | var x24: u64 = undefined; | ||
| 153 | var x25: u64 = undefined; | ||
| 154 | mulxU64(&x24, &x25, x11, 0xffffffffffffffff); | ||
| 155 | var x26: u64 = undefined; | ||
| 156 | var x27: u1 = undefined; | ||
| 157 | addcarryxU64(&x26, &x27, 0x0, x25, x22); | ||
| 158 | const x28 = (cast(u64, x27) + x23); | ||
| 159 | var x29: u64 = undefined; | ||
| 160 | var x30: u1 = undefined; | ||
| 161 | addcarryxU64(&x29, &x30, 0x0, x11, x24); | ||
| 162 | var x31: u64 = undefined; | ||
| 163 | var x32: u1 = undefined; | ||
| 164 | addcarryxU64(&x31, &x32, x30, x13, x26); | ||
| 165 | var x33: u64 = undefined; | ||
| 166 | var x34: u1 = undefined; | ||
| 167 | addcarryxU64(&x33, &x34, x32, x15, x28); | ||
| 168 | var x35: u64 = undefined; | ||
| 169 | var x36: u1 = undefined; | ||
| 170 | addcarryxU64(&x35, &x36, x34, x17, x20); | ||
| 171 | var x37: u64 = undefined; | ||
| 172 | var x38: u1 = undefined; | ||
| 173 | addcarryxU64(&x37, &x38, x36, x19, x21); | ||
| 174 | var x39: u64 = undefined; | ||
| 175 | var x40: u64 = undefined; | ||
| 176 | mulxU64(&x39, &x40, x1, (arg2[3])); | ||
| 177 | var x41: u64 = undefined; | ||
| 178 | var x42: u64 = undefined; | ||
| 179 | mulxU64(&x41, &x42, x1, (arg2[2])); | ||
| 180 | var x43: u64 = undefined; | ||
| 181 | var x44: u64 = undefined; | ||
| 182 | mulxU64(&x43, &x44, x1, (arg2[1])); | ||
| 183 | var x45: u64 = undefined; | ||
| 184 | var x46: u64 = undefined; | ||
| 185 | mulxU64(&x45, &x46, x1, (arg2[0])); | ||
| 186 | var x47: u64 = undefined; | ||
| 187 | var x48: u1 = undefined; | ||
| 188 | addcarryxU64(&x47, &x48, 0x0, x46, x43); | ||
| 189 | var x49: u64 = undefined; | ||
| 190 | var x50: u1 = undefined; | ||
| 191 | addcarryxU64(&x49, &x50, x48, x44, x41); | ||
| 192 | var x51: u64 = undefined; | ||
| 193 | var x52: u1 = undefined; | ||
| 194 | addcarryxU64(&x51, &x52, x50, x42, x39); | ||
| 195 | const x53 = (cast(u64, x52) + x40); | ||
| 196 | var x54: u64 = undefined; | ||
| 197 | var x55: u1 = undefined; | ||
| 198 | addcarryxU64(&x54, &x55, 0x0, x31, x45); | ||
| 199 | var x56: u64 = undefined; | ||
| 200 | var x57: u1 = undefined; | ||
| 201 | addcarryxU64(&x56, &x57, x55, x33, x47); | ||
| 202 | var x58: u64 = undefined; | ||
| 203 | var x59: u1 = undefined; | ||
| 204 | addcarryxU64(&x58, &x59, x57, x35, x49); | ||
| 205 | var x60: u64 = undefined; | ||
| 206 | var x61: u1 = undefined; | ||
| 207 | addcarryxU64(&x60, &x61, x59, x37, x51); | ||
| 208 | var x62: u64 = undefined; | ||
| 209 | var x63: u1 = undefined; | ||
| 210 | addcarryxU64(&x62, &x63, x61, cast(u64, x38), x53); | ||
| 211 | var x64: u64 = undefined; | ||
| 212 | var x65: u64 = undefined; | ||
| 213 | mulxU64(&x64, &x65, x54, 0xffffffff00000001); | ||
| 214 | var x66: u64 = undefined; | ||
| 215 | var x67: u64 = undefined; | ||
| 216 | mulxU64(&x66, &x67, x54, 0xffffffff); | ||
| 217 | var x68: u64 = undefined; | ||
| 218 | var x69: u64 = undefined; | ||
| 219 | mulxU64(&x68, &x69, x54, 0xffffffffffffffff); | ||
| 220 | var x70: u64 = undefined; | ||
| 221 | var x71: u1 = undefined; | ||
| 222 | addcarryxU64(&x70, &x71, 0x0, x69, x66); | ||
| 223 | const x72 = (cast(u64, x71) + x67); | ||
| 224 | var x73: u64 = undefined; | ||
| 225 | var x74: u1 = undefined; | ||
| 226 | addcarryxU64(&x73, &x74, 0x0, x54, x68); | ||
| 227 | var x75: u64 = undefined; | ||
| 228 | var x76: u1 = undefined; | ||
| 229 | addcarryxU64(&x75, &x76, x74, x56, x70); | ||
| 230 | var x77: u64 = undefined; | ||
| 231 | var x78: u1 = undefined; | ||
| 232 | addcarryxU64(&x77, &x78, x76, x58, x72); | ||
| 233 | var x79: u64 = undefined; | ||
| 234 | var x80: u1 = undefined; | ||
| 235 | addcarryxU64(&x79, &x80, x78, x60, x64); | ||
| 236 | var x81: u64 = undefined; | ||
| 237 | var x82: u1 = undefined; | ||
| 238 | addcarryxU64(&x81, &x82, x80, x62, x65); | ||
| 239 | const x83 = (cast(u64, x82) + cast(u64, x63)); | ||
| 240 | var x84: u64 = undefined; | ||
| 241 | var x85: u64 = undefined; | ||
| 242 | mulxU64(&x84, &x85, x2, (arg2[3])); | ||
| 243 | var x86: u64 = undefined; | ||
| 244 | var x87: u64 = undefined; | ||
| 245 | mulxU64(&x86, &x87, x2, (arg2[2])); | ||
| 246 | var x88: u64 = undefined; | ||
| 247 | var x89: u64 = undefined; | ||
| 248 | mulxU64(&x88, &x89, x2, (arg2[1])); | ||
| 249 | var x90: u64 = undefined; | ||
| 250 | var x91: u64 = undefined; | ||
| 251 | mulxU64(&x90, &x91, x2, (arg2[0])); | ||
| 252 | var x92: u64 = undefined; | ||
| 253 | var x93: u1 = undefined; | ||
| 254 | addcarryxU64(&x92, &x93, 0x0, x91, x88); | ||
| 255 | var x94: u64 = undefined; | ||
| 256 | var x95: u1 = undefined; | ||
| 257 | addcarryxU64(&x94, &x95, x93, x89, x86); | ||
| 258 | var x96: u64 = undefined; | ||
| 259 | var x97: u1 = undefined; | ||
| 260 | addcarryxU64(&x96, &x97, x95, x87, x84); | ||
| 261 | const x98 = (cast(u64, x97) + x85); | ||
| 262 | var x99: u64 = undefined; | ||
| 263 | var x100: u1 = undefined; | ||
| 264 | addcarryxU64(&x99, &x100, 0x0, x75, x90); | ||
| 265 | var x101: u64 = undefined; | ||
| 266 | var x102: u1 = undefined; | ||
| 267 | addcarryxU64(&x101, &x102, x100, x77, x92); | ||
| 268 | var x103: u64 = undefined; | ||
| 269 | var x104: u1 = undefined; | ||
| 270 | addcarryxU64(&x103, &x104, x102, x79, x94); | ||
| 271 | var x105: u64 = undefined; | ||
| 272 | var x106: u1 = undefined; | ||
| 273 | addcarryxU64(&x105, &x106, x104, x81, x96); | ||
| 274 | var x107: u64 = undefined; | ||
| 275 | var x108: u1 = undefined; | ||
| 276 | addcarryxU64(&x107, &x108, x106, x83, x98); | ||
| 277 | var x109: u64 = undefined; | ||
| 278 | var x110: u64 = undefined; | ||
| 279 | mulxU64(&x109, &x110, x99, 0xffffffff00000001); | ||
| 280 | var x111: u64 = undefined; | ||
| 281 | var x112: u64 = undefined; | ||
| 282 | mulxU64(&x111, &x112, x99, 0xffffffff); | ||
| 283 | var x113: u64 = undefined; | ||
| 284 | var x114: u64 = undefined; | ||
| 285 | mulxU64(&x113, &x114, x99, 0xffffffffffffffff); | ||
| 286 | var x115: u64 = undefined; | ||
| 287 | var x116: u1 = undefined; | ||
| 288 | addcarryxU64(&x115, &x116, 0x0, x114, x111); | ||
| 289 | const x117 = (cast(u64, x116) + x112); | ||
| 290 | var x118: u64 = undefined; | ||
| 291 | var x119: u1 = undefined; | ||
| 292 | addcarryxU64(&x118, &x119, 0x0, x99, x113); | ||
| 293 | var x120: u64 = undefined; | ||
| 294 | var x121: u1 = undefined; | ||
| 295 | addcarryxU64(&x120, &x121, x119, x101, x115); | ||
| 296 | var x122: u64 = undefined; | ||
| 297 | var x123: u1 = undefined; | ||
| 298 | addcarryxU64(&x122, &x123, x121, x103, x117); | ||
| 299 | var x124: u64 = undefined; | ||
| 300 | var x125: u1 = undefined; | ||
| 301 | addcarryxU64(&x124, &x125, x123, x105, x109); | ||
| 302 | var x126: u64 = undefined; | ||
| 303 | var x127: u1 = undefined; | ||
| 304 | addcarryxU64(&x126, &x127, x125, x107, x110); | ||
| 305 | const x128 = (cast(u64, x127) + cast(u64, x108)); | ||
| 306 | var x129: u64 = undefined; | ||
| 307 | var x130: u64 = undefined; | ||
| 308 | mulxU64(&x129, &x130, x3, (arg2[3])); | ||
| 309 | var x131: u64 = undefined; | ||
| 310 | var x132: u64 = undefined; | ||
| 311 | mulxU64(&x131, &x132, x3, (arg2[2])); | ||
| 312 | var x133: u64 = undefined; | ||
| 313 | var x134: u64 = undefined; | ||
| 314 | mulxU64(&x133, &x134, x3, (arg2[1])); | ||
| 315 | var x135: u64 = undefined; | ||
| 316 | var x136: u64 = undefined; | ||
| 317 | mulxU64(&x135, &x136, x3, (arg2[0])); | ||
| 318 | var x137: u64 = undefined; | ||
| 319 | var x138: u1 = undefined; | ||
| 320 | addcarryxU64(&x137, &x138, 0x0, x136, x133); | ||
| 321 | var x139: u64 = undefined; | ||
| 322 | var x140: u1 = undefined; | ||
| 323 | addcarryxU64(&x139, &x140, x138, x134, x131); | ||
| 324 | var x141: u64 = undefined; | ||
| 325 | var x142: u1 = undefined; | ||
| 326 | addcarryxU64(&x141, &x142, x140, x132, x129); | ||
| 327 | const x143 = (cast(u64, x142) + x130); | ||
| 328 | var x144: u64 = undefined; | ||
| 329 | var x145: u1 = undefined; | ||
| 330 | addcarryxU64(&x144, &x145, 0x0, x120, x135); | ||
| 331 | var x146: u64 = undefined; | ||
| 332 | var x147: u1 = undefined; | ||
| 333 | addcarryxU64(&x146, &x147, x145, x122, x137); | ||
| 334 | var x148: u64 = undefined; | ||
| 335 | var x149: u1 = undefined; | ||
| 336 | addcarryxU64(&x148, &x149, x147, x124, x139); | ||
| 337 | var x150: u64 = undefined; | ||
| 338 | var x151: u1 = undefined; | ||
| 339 | addcarryxU64(&x150, &x151, x149, x126, x141); | ||
| 340 | var x152: u64 = undefined; | ||
| 341 | var x153: u1 = undefined; | ||
| 342 | addcarryxU64(&x152, &x153, x151, x128, x143); | ||
| 343 | var x154: u64 = undefined; | ||
| 344 | var x155: u64 = undefined; | ||
| 345 | mulxU64(&x154, &x155, x144, 0xffffffff00000001); | ||
| 346 | var x156: u64 = undefined; | ||
| 347 | var x157: u64 = undefined; | ||
| 348 | mulxU64(&x156, &x157, x144, 0xffffffff); | ||
| 349 | var x158: u64 = undefined; | ||
| 350 | var x159: u64 = undefined; | ||
| 351 | mulxU64(&x158, &x159, x144, 0xffffffffffffffff); | ||
| 352 | var x160: u64 = undefined; | ||
| 353 | var x161: u1 = undefined; | ||
| 354 | addcarryxU64(&x160, &x161, 0x0, x159, x156); | ||
| 355 | const x162 = (cast(u64, x161) + x157); | ||
| 356 | var x163: u64 = undefined; | ||
| 357 | var x164: u1 = undefined; | ||
| 358 | addcarryxU64(&x163, &x164, 0x0, x144, x158); | ||
| 359 | var x165: u64 = undefined; | ||
| 360 | var x166: u1 = undefined; | ||
| 361 | addcarryxU64(&x165, &x166, x164, x146, x160); | ||
| 362 | var x167: u64 = undefined; | ||
| 363 | var x168: u1 = undefined; | ||
| 364 | addcarryxU64(&x167, &x168, x166, x148, x162); | ||
| 365 | var x169: u64 = undefined; | ||
| 366 | var x170: u1 = undefined; | ||
| 367 | addcarryxU64(&x169, &x170, x168, x150, x154); | ||
| 368 | var x171: u64 = undefined; | ||
| 369 | var x172: u1 = undefined; | ||
| 370 | addcarryxU64(&x171, &x172, x170, x152, x155); | ||
| 371 | const x173 = (cast(u64, x172) + cast(u64, x153)); | ||
| 372 | var x174: u64 = undefined; | ||
| 373 | var x175: u1 = undefined; | ||
| 374 | subborrowxU64(&x174, &x175, 0x0, x165, 0xffffffffffffffff); | ||
| 375 | var x176: u64 = undefined; | ||
| 376 | var x177: u1 = undefined; | ||
| 377 | subborrowxU64(&x176, &x177, x175, x167, 0xffffffff); | ||
| 378 | var x178: u64 = undefined; | ||
| 379 | var x179: u1 = undefined; | ||
| 380 | subborrowxU64(&x178, &x179, x177, x169, cast(u64, 0x0)); | ||
| 381 | var x180: u64 = undefined; | ||
| 382 | var x181: u1 = undefined; | ||
| 383 | subborrowxU64(&x180, &x181, x179, x171, 0xffffffff00000001); | ||
| 384 | var x182: u64 = undefined; | ||
| 385 | var x183: u1 = undefined; | ||
| 386 | subborrowxU64(&x182, &x183, x181, x173, cast(u64, 0x0)); | ||
| 387 | var x184: u64 = undefined; | ||
| 388 | cmovznzU64(&x184, x183, x174, x165); | ||
| 389 | var x185: u64 = undefined; | ||
| 390 | cmovznzU64(&x185, x183, x176, x167); | ||
| 391 | var x186: u64 = undefined; | ||
| 392 | cmovznzU64(&x186, x183, x178, x169); | ||
| 393 | var x187: u64 = undefined; | ||
| 394 | cmovznzU64(&x187, x183, x180, x171); | ||
| 395 | out1[0] = x184; | ||
| 396 | out1[1] = x185; | ||
| 397 | out1[2] = x186; | ||
| 398 | out1[3] = x187; | ||
| 399 | } | ||
| 400 | |||
| 401 | /// The function square squares a field element in the Montgomery domain. | ||
| 402 | /// Preconditions: | ||
| 403 | /// 0 ≤ eval arg1 < m | ||
| 404 | /// Postconditions: | ||
| 405 | /// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) * eval (from_montgomery arg1)) mod m | ||
| 406 | /// 0 ≤ eval out1 < m | ||
| 407 | /// | ||
| 408 | /// Input Bounds: | ||
| 409 | /// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 410 | /// Output Bounds: | ||
| 411 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 412 | pub fn square(out1: *[4]u64, arg1: [4]u64) void { | ||
| 413 | @setRuntimeSafety(mode == .Debug); | ||
| 414 | |||
| 415 | const x1 = (arg1[1]); | ||
| 416 | const x2 = (arg1[2]); | ||
| 417 | const x3 = (arg1[3]); | ||
| 418 | const x4 = (arg1[0]); | ||
| 419 | var x5: u64 = undefined; | ||
| 420 | var x6: u64 = undefined; | ||
| 421 | mulxU64(&x5, &x6, x4, (arg1[3])); | ||
| 422 | var x7: u64 = undefined; | ||
| 423 | var x8: u64 = undefined; | ||
| 424 | mulxU64(&x7, &x8, x4, (arg1[2])); | ||
| 425 | var x9: u64 = undefined; | ||
| 426 | var x10: u64 = undefined; | ||
| 427 | mulxU64(&x9, &x10, x4, (arg1[1])); | ||
| 428 | var x11: u64 = undefined; | ||
| 429 | var x12: u64 = undefined; | ||
| 430 | mulxU64(&x11, &x12, x4, (arg1[0])); | ||
| 431 | var x13: u64 = undefined; | ||
| 432 | var x14: u1 = undefined; | ||
| 433 | addcarryxU64(&x13, &x14, 0x0, x12, x9); | ||
| 434 | var x15: u64 = undefined; | ||
| 435 | var x16: u1 = undefined; | ||
| 436 | addcarryxU64(&x15, &x16, x14, x10, x7); | ||
| 437 | var x17: u64 = undefined; | ||
| 438 | var x18: u1 = undefined; | ||
| 439 | addcarryxU64(&x17, &x18, x16, x8, x5); | ||
| 440 | const x19 = (cast(u64, x18) + x6); | ||
| 441 | var x20: u64 = undefined; | ||
| 442 | var x21: u64 = undefined; | ||
| 443 | mulxU64(&x20, &x21, x11, 0xffffffff00000001); | ||
| 444 | var x22: u64 = undefined; | ||
| 445 | var x23: u64 = undefined; | ||
| 446 | mulxU64(&x22, &x23, x11, 0xffffffff); | ||
| 447 | var x24: u64 = undefined; | ||
| 448 | var x25: u64 = undefined; | ||
| 449 | mulxU64(&x24, &x25, x11, 0xffffffffffffffff); | ||
| 450 | var x26: u64 = undefined; | ||
| 451 | var x27: u1 = undefined; | ||
| 452 | addcarryxU64(&x26, &x27, 0x0, x25, x22); | ||
| 453 | const x28 = (cast(u64, x27) + x23); | ||
| 454 | var x29: u64 = undefined; | ||
| 455 | var x30: u1 = undefined; | ||
| 456 | addcarryxU64(&x29, &x30, 0x0, x11, x24); | ||
| 457 | var x31: u64 = undefined; | ||
| 458 | var x32: u1 = undefined; | ||
| 459 | addcarryxU64(&x31, &x32, x30, x13, x26); | ||
| 460 | var x33: u64 = undefined; | ||
| 461 | var x34: u1 = undefined; | ||
| 462 | addcarryxU64(&x33, &x34, x32, x15, x28); | ||
| 463 | var x35: u64 = undefined; | ||
| 464 | var x36: u1 = undefined; | ||
| 465 | addcarryxU64(&x35, &x36, x34, x17, x20); | ||
| 466 | var x37: u64 = undefined; | ||
| 467 | var x38: u1 = undefined; | ||
| 468 | addcarryxU64(&x37, &x38, x36, x19, x21); | ||
| 469 | var x39: u64 = undefined; | ||
| 470 | var x40: u64 = undefined; | ||
| 471 | mulxU64(&x39, &x40, x1, (arg1[3])); | ||
| 472 | var x41: u64 = undefined; | ||
| 473 | var x42: u64 = undefined; | ||
| 474 | mulxU64(&x41, &x42, x1, (arg1[2])); | ||
| 475 | var x43: u64 = undefined; | ||
| 476 | var x44: u64 = undefined; | ||
| 477 | mulxU64(&x43, &x44, x1, (arg1[1])); | ||
| 478 | var x45: u64 = undefined; | ||
| 479 | var x46: u64 = undefined; | ||
| 480 | mulxU64(&x45, &x46, x1, (arg1[0])); | ||
| 481 | var x47: u64 = undefined; | ||
| 482 | var x48: u1 = undefined; | ||
| 483 | addcarryxU64(&x47, &x48, 0x0, x46, x43); | ||
| 484 | var x49: u64 = undefined; | ||
| 485 | var x50: u1 = undefined; | ||
| 486 | addcarryxU64(&x49, &x50, x48, x44, x41); | ||
| 487 | var x51: u64 = undefined; | ||
| 488 | var x52: u1 = undefined; | ||
| 489 | addcarryxU64(&x51, &x52, x50, x42, x39); | ||
| 490 | const x53 = (cast(u64, x52) + x40); | ||
| 491 | var x54: u64 = undefined; | ||
| 492 | var x55: u1 = undefined; | ||
| 493 | addcarryxU64(&x54, &x55, 0x0, x31, x45); | ||
| 494 | var x56: u64 = undefined; | ||
| 495 | var x57: u1 = undefined; | ||
| 496 | addcarryxU64(&x56, &x57, x55, x33, x47); | ||
| 497 | var x58: u64 = undefined; | ||
| 498 | var x59: u1 = undefined; | ||
| 499 | addcarryxU64(&x58, &x59, x57, x35, x49); | ||
| 500 | var x60: u64 = undefined; | ||
| 501 | var x61: u1 = undefined; | ||
| 502 | addcarryxU64(&x60, &x61, x59, x37, x51); | ||
| 503 | var x62: u64 = undefined; | ||
| 504 | var x63: u1 = undefined; | ||
| 505 | addcarryxU64(&x62, &x63, x61, cast(u64, x38), x53); | ||
| 506 | var x64: u64 = undefined; | ||
| 507 | var x65: u64 = undefined; | ||
| 508 | mulxU64(&x64, &x65, x54, 0xffffffff00000001); | ||
| 509 | var x66: u64 = undefined; | ||
| 510 | var x67: u64 = undefined; | ||
| 511 | mulxU64(&x66, &x67, x54, 0xffffffff); | ||
| 512 | var x68: u64 = undefined; | ||
| 513 | var x69: u64 = undefined; | ||
| 514 | mulxU64(&x68, &x69, x54, 0xffffffffffffffff); | ||
| 515 | var x70: u64 = undefined; | ||
| 516 | var x71: u1 = undefined; | ||
| 517 | addcarryxU64(&x70, &x71, 0x0, x69, x66); | ||
| 518 | const x72 = (cast(u64, x71) + x67); | ||
| 519 | var x73: u64 = undefined; | ||
| 520 | var x74: u1 = undefined; | ||
| 521 | addcarryxU64(&x73, &x74, 0x0, x54, x68); | ||
| 522 | var x75: u64 = undefined; | ||
| 523 | var x76: u1 = undefined; | ||
| 524 | addcarryxU64(&x75, &x76, x74, x56, x70); | ||
| 525 | var x77: u64 = undefined; | ||
| 526 | var x78: u1 = undefined; | ||
| 527 | addcarryxU64(&x77, &x78, x76, x58, x72); | ||
| 528 | var x79: u64 = undefined; | ||
| 529 | var x80: u1 = undefined; | ||
| 530 | addcarryxU64(&x79, &x80, x78, x60, x64); | ||
| 531 | var x81: u64 = undefined; | ||
| 532 | var x82: u1 = undefined; | ||
| 533 | addcarryxU64(&x81, &x82, x80, x62, x65); | ||
| 534 | const x83 = (cast(u64, x82) + cast(u64, x63)); | ||
| 535 | var x84: u64 = undefined; | ||
| 536 | var x85: u64 = undefined; | ||
| 537 | mulxU64(&x84, &x85, x2, (arg1[3])); | ||
| 538 | var x86: u64 = undefined; | ||
| 539 | var x87: u64 = undefined; | ||
| 540 | mulxU64(&x86, &x87, x2, (arg1[2])); | ||
| 541 | var x88: u64 = undefined; | ||
| 542 | var x89: u64 = undefined; | ||
| 543 | mulxU64(&x88, &x89, x2, (arg1[1])); | ||
| 544 | var x90: u64 = undefined; | ||
| 545 | var x91: u64 = undefined; | ||
| 546 | mulxU64(&x90, &x91, x2, (arg1[0])); | ||
| 547 | var x92: u64 = undefined; | ||
| 548 | var x93: u1 = undefined; | ||
| 549 | addcarryxU64(&x92, &x93, 0x0, x91, x88); | ||
| 550 | var x94: u64 = undefined; | ||
| 551 | var x95: u1 = undefined; | ||
| 552 | addcarryxU64(&x94, &x95, x93, x89, x86); | ||
| 553 | var x96: u64 = undefined; | ||
| 554 | var x97: u1 = undefined; | ||
| 555 | addcarryxU64(&x96, &x97, x95, x87, x84); | ||
| 556 | const x98 = (cast(u64, x97) + x85); | ||
| 557 | var x99: u64 = undefined; | ||
| 558 | var x100: u1 = undefined; | ||
| 559 | addcarryxU64(&x99, &x100, 0x0, x75, x90); | ||
| 560 | var x101: u64 = undefined; | ||
| 561 | var x102: u1 = undefined; | ||
| 562 | addcarryxU64(&x101, &x102, x100, x77, x92); | ||
| 563 | var x103: u64 = undefined; | ||
| 564 | var x104: u1 = undefined; | ||
| 565 | addcarryxU64(&x103, &x104, x102, x79, x94); | ||
| 566 | var x105: u64 = undefined; | ||
| 567 | var x106: u1 = undefined; | ||
| 568 | addcarryxU64(&x105, &x106, x104, x81, x96); | ||
| 569 | var x107: u64 = undefined; | ||
| 570 | var x108: u1 = undefined; | ||
| 571 | addcarryxU64(&x107, &x108, x106, x83, x98); | ||
| 572 | var x109: u64 = undefined; | ||
| 573 | var x110: u64 = undefined; | ||
| 574 | mulxU64(&x109, &x110, x99, 0xffffffff00000001); | ||
| 575 | var x111: u64 = undefined; | ||
| 576 | var x112: u64 = undefined; | ||
| 577 | mulxU64(&x111, &x112, x99, 0xffffffff); | ||
| 578 | var x113: u64 = undefined; | ||
| 579 | var x114: u64 = undefined; | ||
| 580 | mulxU64(&x113, &x114, x99, 0xffffffffffffffff); | ||
| 581 | var x115: u64 = undefined; | ||
| 582 | var x116: u1 = undefined; | ||
| 583 | addcarryxU64(&x115, &x116, 0x0, x114, x111); | ||
| 584 | const x117 = (cast(u64, x116) + x112); | ||
| 585 | var x118: u64 = undefined; | ||
| 586 | var x119: u1 = undefined; | ||
| 587 | addcarryxU64(&x118, &x119, 0x0, x99, x113); | ||
| 588 | var x120: u64 = undefined; | ||
| 589 | var x121: u1 = undefined; | ||
| 590 | addcarryxU64(&x120, &x121, x119, x101, x115); | ||
| 591 | var x122: u64 = undefined; | ||
| 592 | var x123: u1 = undefined; | ||
| 593 | addcarryxU64(&x122, &x123, x121, x103, x117); | ||
| 594 | var x124: u64 = undefined; | ||
| 595 | var x125: u1 = undefined; | ||
| 596 | addcarryxU64(&x124, &x125, x123, x105, x109); | ||
| 597 | var x126: u64 = undefined; | ||
| 598 | var x127: u1 = undefined; | ||
| 599 | addcarryxU64(&x126, &x127, x125, x107, x110); | ||
| 600 | const x128 = (cast(u64, x127) + cast(u64, x108)); | ||
| 601 | var x129: u64 = undefined; | ||
| 602 | var x130: u64 = undefined; | ||
| 603 | mulxU64(&x129, &x130, x3, (arg1[3])); | ||
| 604 | var x131: u64 = undefined; | ||
| 605 | var x132: u64 = undefined; | ||
| 606 | mulxU64(&x131, &x132, x3, (arg1[2])); | ||
| 607 | var x133: u64 = undefined; | ||
| 608 | var x134: u64 = undefined; | ||
| 609 | mulxU64(&x133, &x134, x3, (arg1[1])); | ||
| 610 | var x135: u64 = undefined; | ||
| 611 | var x136: u64 = undefined; | ||
| 612 | mulxU64(&x135, &x136, x3, (arg1[0])); | ||
| 613 | var x137: u64 = undefined; | ||
| 614 | var x138: u1 = undefined; | ||
| 615 | addcarryxU64(&x137, &x138, 0x0, x136, x133); | ||
| 616 | var x139: u64 = undefined; | ||
| 617 | var x140: u1 = undefined; | ||
| 618 | addcarryxU64(&x139, &x140, x138, x134, x131); | ||
| 619 | var x141: u64 = undefined; | ||
| 620 | var x142: u1 = undefined; | ||
| 621 | addcarryxU64(&x141, &x142, x140, x132, x129); | ||
| 622 | const x143 = (cast(u64, x142) + x130); | ||
| 623 | var x144: u64 = undefined; | ||
| 624 | var x145: u1 = undefined; | ||
| 625 | addcarryxU64(&x144, &x145, 0x0, x120, x135); | ||
| 626 | var x146: u64 = undefined; | ||
| 627 | var x147: u1 = undefined; | ||
| 628 | addcarryxU64(&x146, &x147, x145, x122, x137); | ||
| 629 | var x148: u64 = undefined; | ||
| 630 | var x149: u1 = undefined; | ||
| 631 | addcarryxU64(&x148, &x149, x147, x124, x139); | ||
| 632 | var x150: u64 = undefined; | ||
| 633 | var x151: u1 = undefined; | ||
| 634 | addcarryxU64(&x150, &x151, x149, x126, x141); | ||
| 635 | var x152: u64 = undefined; | ||
| 636 | var x153: u1 = undefined; | ||
| 637 | addcarryxU64(&x152, &x153, x151, x128, x143); | ||
| 638 | var x154: u64 = undefined; | ||
| 639 | var x155: u64 = undefined; | ||
| 640 | mulxU64(&x154, &x155, x144, 0xffffffff00000001); | ||
| 641 | var x156: u64 = undefined; | ||
| 642 | var x157: u64 = undefined; | ||
| 643 | mulxU64(&x156, &x157, x144, 0xffffffff); | ||
| 644 | var x158: u64 = undefined; | ||
| 645 | var x159: u64 = undefined; | ||
| 646 | mulxU64(&x158, &x159, x144, 0xffffffffffffffff); | ||
| 647 | var x160: u64 = undefined; | ||
| 648 | var x161: u1 = undefined; | ||
| 649 | addcarryxU64(&x160, &x161, 0x0, x159, x156); | ||
| 650 | const x162 = (cast(u64, x161) + x157); | ||
| 651 | var x163: u64 = undefined; | ||
| 652 | var x164: u1 = undefined; | ||
| 653 | addcarryxU64(&x163, &x164, 0x0, x144, x158); | ||
| 654 | var x165: u64 = undefined; | ||
| 655 | var x166: u1 = undefined; | ||
| 656 | addcarryxU64(&x165, &x166, x164, x146, x160); | ||
| 657 | var x167: u64 = undefined; | ||
| 658 | var x168: u1 = undefined; | ||
| 659 | addcarryxU64(&x167, &x168, x166, x148, x162); | ||
| 660 | var x169: u64 = undefined; | ||
| 661 | var x170: u1 = undefined; | ||
| 662 | addcarryxU64(&x169, &x170, x168, x150, x154); | ||
| 663 | var x171: u64 = undefined; | ||
| 664 | var x172: u1 = undefined; | ||
| 665 | addcarryxU64(&x171, &x172, x170, x152, x155); | ||
| 666 | const x173 = (cast(u64, x172) + cast(u64, x153)); | ||
| 667 | var x174: u64 = undefined; | ||
| 668 | var x175: u1 = undefined; | ||
| 669 | subborrowxU64(&x174, &x175, 0x0, x165, 0xffffffffffffffff); | ||
| 670 | var x176: u64 = undefined; | ||
| 671 | var x177: u1 = undefined; | ||
| 672 | subborrowxU64(&x176, &x177, x175, x167, 0xffffffff); | ||
| 673 | var x178: u64 = undefined; | ||
| 674 | var x179: u1 = undefined; | ||
| 675 | subborrowxU64(&x178, &x179, x177, x169, cast(u64, 0x0)); | ||
| 676 | var x180: u64 = undefined; | ||
| 677 | var x181: u1 = undefined; | ||
| 678 | subborrowxU64(&x180, &x181, x179, x171, 0xffffffff00000001); | ||
| 679 | var x182: u64 = undefined; | ||
| 680 | var x183: u1 = undefined; | ||
| 681 | subborrowxU64(&x182, &x183, x181, x173, cast(u64, 0x0)); | ||
| 682 | var x184: u64 = undefined; | ||
| 683 | cmovznzU64(&x184, x183, x174, x165); | ||
| 684 | var x185: u64 = undefined; | ||
| 685 | cmovznzU64(&x185, x183, x176, x167); | ||
| 686 | var x186: u64 = undefined; | ||
| 687 | cmovznzU64(&x186, x183, x178, x169); | ||
| 688 | var x187: u64 = undefined; | ||
| 689 | cmovznzU64(&x187, x183, x180, x171); | ||
| 690 | out1[0] = x184; | ||
| 691 | out1[1] = x185; | ||
| 692 | out1[2] = x186; | ||
| 693 | out1[3] = x187; | ||
| 694 | } | ||
| 695 | |||
| 696 | /// The function add adds two field elements in the Montgomery domain. | ||
| 697 | /// Preconditions: | ||
| 698 | /// 0 ≤ eval arg1 < m | ||
| 699 | /// 0 ≤ eval arg2 < m | ||
| 700 | /// Postconditions: | ||
| 701 | /// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) + eval (from_montgomery arg2)) mod m | ||
| 702 | /// 0 ≤ eval out1 < m | ||
| 703 | /// | ||
| 704 | /// Input Bounds: | ||
| 705 | /// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 706 | /// arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 707 | /// Output Bounds: | ||
| 708 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 709 | pub fn add(out1: *[4]u64, arg1: [4]u64, arg2: [4]u64) void { | ||
| 710 | @setRuntimeSafety(mode == .Debug); | ||
| 711 | |||
| 712 | var x1: u64 = undefined; | ||
| 713 | var x2: u1 = undefined; | ||
| 714 | addcarryxU64(&x1, &x2, 0x0, (arg1[0]), (arg2[0])); | ||
| 715 | var x3: u64 = undefined; | ||
| 716 | var x4: u1 = undefined; | ||
| 717 | addcarryxU64(&x3, &x4, x2, (arg1[1]), (arg2[1])); | ||
| 718 | var x5: u64 = undefined; | ||
| 719 | var x6: u1 = undefined; | ||
| 720 | addcarryxU64(&x5, &x6, x4, (arg1[2]), (arg2[2])); | ||
| 721 | var x7: u64 = undefined; | ||
| 722 | var x8: u1 = undefined; | ||
| 723 | addcarryxU64(&x7, &x8, x6, (arg1[3]), (arg2[3])); | ||
| 724 | var x9: u64 = undefined; | ||
| 725 | var x10: u1 = undefined; | ||
| 726 | subborrowxU64(&x9, &x10, 0x0, x1, 0xffffffffffffffff); | ||
| 727 | var x11: u64 = undefined; | ||
| 728 | var x12: u1 = undefined; | ||
| 729 | subborrowxU64(&x11, &x12, x10, x3, 0xffffffff); | ||
| 730 | var x13: u64 = undefined; | ||
| 731 | var x14: u1 = undefined; | ||
| 732 | subborrowxU64(&x13, &x14, x12, x5, cast(u64, 0x0)); | ||
| 733 | var x15: u64 = undefined; | ||
| 734 | var x16: u1 = undefined; | ||
| 735 | subborrowxU64(&x15, &x16, x14, x7, 0xffffffff00000001); | ||
| 736 | var x17: u64 = undefined; | ||
| 737 | var x18: u1 = undefined; | ||
| 738 | subborrowxU64(&x17, &x18, x16, cast(u64, x8), cast(u64, 0x0)); | ||
| 739 | var x19: u64 = undefined; | ||
| 740 | cmovznzU64(&x19, x18, x9, x1); | ||
| 741 | var x20: u64 = undefined; | ||
| 742 | cmovznzU64(&x20, x18, x11, x3); | ||
| 743 | var x21: u64 = undefined; | ||
| 744 | cmovznzU64(&x21, x18, x13, x5); | ||
| 745 | var x22: u64 = undefined; | ||
| 746 | cmovznzU64(&x22, x18, x15, x7); | ||
| 747 | out1[0] = x19; | ||
| 748 | out1[1] = x20; | ||
| 749 | out1[2] = x21; | ||
| 750 | out1[3] = x22; | ||
| 751 | } | ||
| 752 | |||
| 753 | /// The function sub subtracts two field elements in the Montgomery domain. | ||
| 754 | /// Preconditions: | ||
| 755 | /// 0 ≤ eval arg1 < m | ||
| 756 | /// 0 ≤ eval arg2 < m | ||
| 757 | /// Postconditions: | ||
| 758 | /// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) - eval (from_montgomery arg2)) mod m | ||
| 759 | /// 0 ≤ eval out1 < m | ||
| 760 | /// | ||
| 761 | /// Input Bounds: | ||
| 762 | /// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 763 | /// arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 764 | /// Output Bounds: | ||
| 765 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 766 | pub fn sub(out1: *[4]u64, arg1: [4]u64, arg2: [4]u64) void { | ||
| 767 | @setRuntimeSafety(mode == .Debug); | ||
| 768 | |||
| 769 | var x1: u64 = undefined; | ||
| 770 | var x2: u1 = undefined; | ||
| 771 | subborrowxU64(&x1, &x2, 0x0, (arg1[0]), (arg2[0])); | ||
| 772 | var x3: u64 = undefined; | ||
| 773 | var x4: u1 = undefined; | ||
| 774 | subborrowxU64(&x3, &x4, x2, (arg1[1]), (arg2[1])); | ||
| 775 | var x5: u64 = undefined; | ||
| 776 | var x6: u1 = undefined; | ||
| 777 | subborrowxU64(&x5, &x6, x4, (arg1[2]), (arg2[2])); | ||
| 778 | var x7: u64 = undefined; | ||
| 779 | var x8: u1 = undefined; | ||
| 780 | subborrowxU64(&x7, &x8, x6, (arg1[3]), (arg2[3])); | ||
| 781 | var x9: u64 = undefined; | ||
| 782 | cmovznzU64(&x9, x8, cast(u64, 0x0), 0xffffffffffffffff); | ||
| 783 | var x10: u64 = undefined; | ||
| 784 | var x11: u1 = undefined; | ||
| 785 | addcarryxU64(&x10, &x11, 0x0, x1, x9); | ||
| 786 | var x12: u64 = undefined; | ||
| 787 | var x13: u1 = undefined; | ||
| 788 | addcarryxU64(&x12, &x13, x11, x3, (x9 & 0xffffffff)); | ||
| 789 | var x14: u64 = undefined; | ||
| 790 | var x15: u1 = undefined; | ||
| 791 | addcarryxU64(&x14, &x15, x13, x5, cast(u64, 0x0)); | ||
| 792 | var x16: u64 = undefined; | ||
| 793 | var x17: u1 = undefined; | ||
| 794 | addcarryxU64(&x16, &x17, x15, x7, (x9 & 0xffffffff00000001)); | ||
| 795 | out1[0] = x10; | ||
| 796 | out1[1] = x12; | ||
| 797 | out1[2] = x14; | ||
| 798 | out1[3] = x16; | ||
| 799 | } | ||
| 800 | |||
| 801 | /// The function opp negates a field element in the Montgomery domain. | ||
| 802 | /// Preconditions: | ||
| 803 | /// 0 ≤ eval arg1 < m | ||
| 804 | /// Postconditions: | ||
| 805 | /// eval (from_montgomery out1) mod m = -eval (from_montgomery arg1) mod m | ||
| 806 | /// 0 ≤ eval out1 < m | ||
| 807 | /// | ||
| 808 | /// Input Bounds: | ||
| 809 | /// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 810 | /// Output Bounds: | ||
| 811 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 812 | pub fn opp(out1: *[4]u64, arg1: [4]u64) void { | ||
| 813 | @setRuntimeSafety(mode == .Debug); | ||
| 814 | |||
| 815 | var x1: u64 = undefined; | ||
| 816 | var x2: u1 = undefined; | ||
| 817 | subborrowxU64(&x1, &x2, 0x0, cast(u64, 0x0), (arg1[0])); | ||
| 818 | var x3: u64 = undefined; | ||
| 819 | var x4: u1 = undefined; | ||
| 820 | subborrowxU64(&x3, &x4, x2, cast(u64, 0x0), (arg1[1])); | ||
| 821 | var x5: u64 = undefined; | ||
| 822 | var x6: u1 = undefined; | ||
| 823 | subborrowxU64(&x5, &x6, x4, cast(u64, 0x0), (arg1[2])); | ||
| 824 | var x7: u64 = undefined; | ||
| 825 | var x8: u1 = undefined; | ||
| 826 | subborrowxU64(&x7, &x8, x6, cast(u64, 0x0), (arg1[3])); | ||
| 827 | var x9: u64 = undefined; | ||
| 828 | cmovznzU64(&x9, x8, cast(u64, 0x0), 0xffffffffffffffff); | ||
| 829 | var x10: u64 = undefined; | ||
| 830 | var x11: u1 = undefined; | ||
| 831 | addcarryxU64(&x10, &x11, 0x0, x1, x9); | ||
| 832 | var x12: u64 = undefined; | ||
| 833 | var x13: u1 = undefined; | ||
| 834 | addcarryxU64(&x12, &x13, x11, x3, (x9 & 0xffffffff)); | ||
| 835 | var x14: u64 = undefined; | ||
| 836 | var x15: u1 = undefined; | ||
| 837 | addcarryxU64(&x14, &x15, x13, x5, cast(u64, 0x0)); | ||
| 838 | var x16: u64 = undefined; | ||
| 839 | var x17: u1 = undefined; | ||
| 840 | addcarryxU64(&x16, &x17, x15, x7, (x9 & 0xffffffff00000001)); | ||
| 841 | out1[0] = x10; | ||
| 842 | out1[1] = x12; | ||
| 843 | out1[2] = x14; | ||
| 844 | out1[3] = x16; | ||
| 845 | } | ||
| 846 | |||
| 847 | /// The function fromMontgomery translates a field element out of the Montgomery domain. | ||
| 848 | /// Preconditions: | ||
| 849 | /// 0 ≤ eval arg1 < m | ||
| 850 | /// Postconditions: | ||
| 851 | /// eval out1 mod m = (eval arg1 * ((2^64)⁻¹ mod m)^4) mod m | ||
| 852 | /// 0 ≤ eval out1 < m | ||
| 853 | /// | ||
| 854 | /// Input Bounds: | ||
| 855 | /// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 856 | /// Output Bounds: | ||
| 857 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 858 | pub fn fromMontgomery(out1: *[4]u64, arg1: [4]u64) void { | ||
| 859 | @setRuntimeSafety(mode == .Debug); | ||
| 860 | |||
| 861 | const x1 = (arg1[0]); | ||
| 862 | var x2: u64 = undefined; | ||
| 863 | var x3: u64 = undefined; | ||
| 864 | mulxU64(&x2, &x3, x1, 0xffffffff00000001); | ||
| 865 | var x4: u64 = undefined; | ||
| 866 | var x5: u64 = undefined; | ||
| 867 | mulxU64(&x4, &x5, x1, 0xffffffff); | ||
| 868 | var x6: u64 = undefined; | ||
| 869 | var x7: u64 = undefined; | ||
| 870 | mulxU64(&x6, &x7, x1, 0xffffffffffffffff); | ||
| 871 | var x8: u64 = undefined; | ||
| 872 | var x9: u1 = undefined; | ||
| 873 | addcarryxU64(&x8, &x9, 0x0, x7, x4); | ||
| 874 | var x10: u64 = undefined; | ||
| 875 | var x11: u1 = undefined; | ||
| 876 | addcarryxU64(&x10, &x11, 0x0, x1, x6); | ||
| 877 | var x12: u64 = undefined; | ||
| 878 | var x13: u1 = undefined; | ||
| 879 | addcarryxU64(&x12, &x13, x11, cast(u64, 0x0), x8); | ||
| 880 | var x14: u64 = undefined; | ||
| 881 | var x15: u1 = undefined; | ||
| 882 | addcarryxU64(&x14, &x15, 0x0, x12, (arg1[1])); | ||
| 883 | var x16: u64 = undefined; | ||
| 884 | var x17: u64 = undefined; | ||
| 885 | mulxU64(&x16, &x17, x14, 0xffffffff00000001); | ||
| 886 | var x18: u64 = undefined; | ||
| 887 | var x19: u64 = undefined; | ||
| 888 | mulxU64(&x18, &x19, x14, 0xffffffff); | ||
| 889 | var x20: u64 = undefined; | ||
| 890 | var x21: u64 = undefined; | ||
| 891 | mulxU64(&x20, &x21, x14, 0xffffffffffffffff); | ||
| 892 | var x22: u64 = undefined; | ||
| 893 | var x23: u1 = undefined; | ||
| 894 | addcarryxU64(&x22, &x23, 0x0, x21, x18); | ||
| 895 | var x24: u64 = undefined; | ||
| 896 | var x25: u1 = undefined; | ||
| 897 | addcarryxU64(&x24, &x25, 0x0, x14, x20); | ||
| 898 | var x26: u64 = undefined; | ||
| 899 | var x27: u1 = undefined; | ||
| 900 | addcarryxU64(&x26, &x27, x25, (cast(u64, x15) + (cast(u64, x13) + (cast(u64, x9) + x5))), x22); | ||
| 901 | var x28: u64 = undefined; | ||
| 902 | var x29: u1 = undefined; | ||
| 903 | addcarryxU64(&x28, &x29, x27, x2, (cast(u64, x23) + x19)); | ||
| 904 | var x30: u64 = undefined; | ||
| 905 | var x31: u1 = undefined; | ||
| 906 | addcarryxU64(&x30, &x31, x29, x3, x16); | ||
| 907 | var x32: u64 = undefined; | ||
| 908 | var x33: u1 = undefined; | ||
| 909 | addcarryxU64(&x32, &x33, 0x0, x26, (arg1[2])); | ||
| 910 | var x34: u64 = undefined; | ||
| 911 | var x35: u1 = undefined; | ||
| 912 | addcarryxU64(&x34, &x35, x33, x28, cast(u64, 0x0)); | ||
| 913 | var x36: u64 = undefined; | ||
| 914 | var x37: u1 = undefined; | ||
| 915 | addcarryxU64(&x36, &x37, x35, x30, cast(u64, 0x0)); | ||
| 916 | var x38: u64 = undefined; | ||
| 917 | var x39: u64 = undefined; | ||
| 918 | mulxU64(&x38, &x39, x32, 0xffffffff00000001); | ||
| 919 | var x40: u64 = undefined; | ||
| 920 | var x41: u64 = undefined; | ||
| 921 | mulxU64(&x40, &x41, x32, 0xffffffff); | ||
| 922 | var x42: u64 = undefined; | ||
| 923 | var x43: u64 = undefined; | ||
| 924 | mulxU64(&x42, &x43, x32, 0xffffffffffffffff); | ||
| 925 | var x44: u64 = undefined; | ||
| 926 | var x45: u1 = undefined; | ||
| 927 | addcarryxU64(&x44, &x45, 0x0, x43, x40); | ||
| 928 | var x46: u64 = undefined; | ||
| 929 | var x47: u1 = undefined; | ||
| 930 | addcarryxU64(&x46, &x47, 0x0, x32, x42); | ||
| 931 | var x48: u64 = undefined; | ||
| 932 | var x49: u1 = undefined; | ||
| 933 | addcarryxU64(&x48, &x49, x47, x34, x44); | ||
| 934 | var x50: u64 = undefined; | ||
| 935 | var x51: u1 = undefined; | ||
| 936 | addcarryxU64(&x50, &x51, x49, x36, (cast(u64, x45) + x41)); | ||
| 937 | var x52: u64 = undefined; | ||
| 938 | var x53: u1 = undefined; | ||
| 939 | addcarryxU64(&x52, &x53, x51, (cast(u64, x37) + (cast(u64, x31) + x17)), x38); | ||
| 940 | var x54: u64 = undefined; | ||
| 941 | var x55: u1 = undefined; | ||
| 942 | addcarryxU64(&x54, &x55, 0x0, x48, (arg1[3])); | ||
| 943 | var x56: u64 = undefined; | ||
| 944 | var x57: u1 = undefined; | ||
| 945 | addcarryxU64(&x56, &x57, x55, x50, cast(u64, 0x0)); | ||
| 946 | var x58: u64 = undefined; | ||
| 947 | var x59: u1 = undefined; | ||
| 948 | addcarryxU64(&x58, &x59, x57, x52, cast(u64, 0x0)); | ||
| 949 | var x60: u64 = undefined; | ||
| 950 | var x61: u64 = undefined; | ||
| 951 | mulxU64(&x60, &x61, x54, 0xffffffff00000001); | ||
| 952 | var x62: u64 = undefined; | ||
| 953 | var x63: u64 = undefined; | ||
| 954 | mulxU64(&x62, &x63, x54, 0xffffffff); | ||
| 955 | var x64: u64 = undefined; | ||
| 956 | var x65: u64 = undefined; | ||
| 957 | mulxU64(&x64, &x65, x54, 0xffffffffffffffff); | ||
| 958 | var x66: u64 = undefined; | ||
| 959 | var x67: u1 = undefined; | ||
| 960 | addcarryxU64(&x66, &x67, 0x0, x65, x62); | ||
| 961 | var x68: u64 = undefined; | ||
| 962 | var x69: u1 = undefined; | ||
| 963 | addcarryxU64(&x68, &x69, 0x0, x54, x64); | ||
| 964 | var x70: u64 = undefined; | ||
| 965 | var x71: u1 = undefined; | ||
| 966 | addcarryxU64(&x70, &x71, x69, x56, x66); | ||
| 967 | var x72: u64 = undefined; | ||
| 968 | var x73: u1 = undefined; | ||
| 969 | addcarryxU64(&x72, &x73, x71, x58, (cast(u64, x67) + x63)); | ||
| 970 | var x74: u64 = undefined; | ||
| 971 | var x75: u1 = undefined; | ||
| 972 | addcarryxU64(&x74, &x75, x73, (cast(u64, x59) + (cast(u64, x53) + x39)), x60); | ||
| 973 | const x76 = (cast(u64, x75) + x61); | ||
| 974 | var x77: u64 = undefined; | ||
| 975 | var x78: u1 = undefined; | ||
| 976 | subborrowxU64(&x77, &x78, 0x0, x70, 0xffffffffffffffff); | ||
| 977 | var x79: u64 = undefined; | ||
| 978 | var x80: u1 = undefined; | ||
| 979 | subborrowxU64(&x79, &x80, x78, x72, 0xffffffff); | ||
| 980 | var x81: u64 = undefined; | ||
| 981 | var x82: u1 = undefined; | ||
| 982 | subborrowxU64(&x81, &x82, x80, x74, cast(u64, 0x0)); | ||
| 983 | var x83: u64 = undefined; | ||
| 984 | var x84: u1 = undefined; | ||
| 985 | subborrowxU64(&x83, &x84, x82, x76, 0xffffffff00000001); | ||
| 986 | var x85: u64 = undefined; | ||
| 987 | var x86: u1 = undefined; | ||
| 988 | subborrowxU64(&x85, &x86, x84, cast(u64, 0x0), cast(u64, 0x0)); | ||
| 989 | var x87: u64 = undefined; | ||
| 990 | cmovznzU64(&x87, x86, x77, x70); | ||
| 991 | var x88: u64 = undefined; | ||
| 992 | cmovznzU64(&x88, x86, x79, x72); | ||
| 993 | var x89: u64 = undefined; | ||
| 994 | cmovznzU64(&x89, x86, x81, x74); | ||
| 995 | var x90: u64 = undefined; | ||
| 996 | cmovznzU64(&x90, x86, x83, x76); | ||
| 997 | out1[0] = x87; | ||
| 998 | out1[1] = x88; | ||
| 999 | out1[2] = x89; | ||
| 1000 | out1[3] = x90; | ||
| 1001 | } | ||
| 1002 | |||
| 1003 | /// The function toMontgomery translates a field element into the Montgomery domain. | ||
| 1004 | /// Preconditions: | ||
| 1005 | /// 0 ≤ eval arg1 < m | ||
| 1006 | /// Postconditions: | ||
| 1007 | /// eval (from_montgomery out1) mod m = eval arg1 mod m | ||
| 1008 | /// 0 ≤ eval out1 < m | ||
| 1009 | /// | ||
| 1010 | /// Input Bounds: | ||
| 1011 | /// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 1012 | /// Output Bounds: | ||
| 1013 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 1014 | pub fn toMontgomery(out1: *[4]u64, arg1: [4]u64) void { | ||
| 1015 | @setRuntimeSafety(mode == .Debug); | ||
| 1016 | |||
| 1017 | const x1 = (arg1[1]); | ||
| 1018 | const x2 = (arg1[2]); | ||
| 1019 | const x3 = (arg1[3]); | ||
| 1020 | const x4 = (arg1[0]); | ||
| 1021 | var x5: u64 = undefined; | ||
| 1022 | var x6: u64 = undefined; | ||
| 1023 | mulxU64(&x5, &x6, x4, 0x4fffffffd); | ||
| 1024 | var x7: u64 = undefined; | ||
| 1025 | var x8: u64 = undefined; | ||
| 1026 | mulxU64(&x7, &x8, x4, 0xfffffffffffffffe); | ||
| 1027 | var x9: u64 = undefined; | ||
| 1028 | var x10: u64 = undefined; | ||
| 1029 | mulxU64(&x9, &x10, x4, 0xfffffffbffffffff); | ||
| 1030 | var x11: u64 = undefined; | ||
| 1031 | var x12: u64 = undefined; | ||
| 1032 | mulxU64(&x11, &x12, x4, 0x3); | ||
| 1033 | var x13: u64 = undefined; | ||
| 1034 | var x14: u1 = undefined; | ||
| 1035 | addcarryxU64(&x13, &x14, 0x0, x12, x9); | ||
| 1036 | var x15: u64 = undefined; | ||
| 1037 | var x16: u1 = undefined; | ||
| 1038 | addcarryxU64(&x15, &x16, x14, x10, x7); | ||
| 1039 | var x17: u64 = undefined; | ||
| 1040 | var x18: u1 = undefined; | ||
| 1041 | addcarryxU64(&x17, &x18, x16, x8, x5); | ||
| 1042 | var x19: u64 = undefined; | ||
| 1043 | var x20: u64 = undefined; | ||
| 1044 | mulxU64(&x19, &x20, x11, 0xffffffff00000001); | ||
| 1045 | var x21: u64 = undefined; | ||
| 1046 | var x22: u64 = undefined; | ||
| 1047 | mulxU64(&x21, &x22, x11, 0xffffffff); | ||
| 1048 | var x23: u64 = undefined; | ||
| 1049 | var x24: u64 = undefined; | ||
| 1050 | mulxU64(&x23, &x24, x11, 0xffffffffffffffff); | ||
| 1051 | var x25: u64 = undefined; | ||
| 1052 | var x26: u1 = undefined; | ||
| 1053 | addcarryxU64(&x25, &x26, 0x0, x24, x21); | ||
| 1054 | var x27: u64 = undefined; | ||
| 1055 | var x28: u1 = undefined; | ||
| 1056 | addcarryxU64(&x27, &x28, 0x0, x11, x23); | ||
| 1057 | var x29: u64 = undefined; | ||
| 1058 | var x30: u1 = undefined; | ||
| 1059 | addcarryxU64(&x29, &x30, x28, x13, x25); | ||
| 1060 | var x31: u64 = undefined; | ||
| 1061 | var x32: u1 = undefined; | ||
| 1062 | addcarryxU64(&x31, &x32, x30, x15, (cast(u64, x26) + x22)); | ||
| 1063 | var x33: u64 = undefined; | ||
| 1064 | var x34: u1 = undefined; | ||
| 1065 | addcarryxU64(&x33, &x34, x32, x17, x19); | ||
| 1066 | var x35: u64 = undefined; | ||
| 1067 | var x36: u1 = undefined; | ||
| 1068 | addcarryxU64(&x35, &x36, x34, (cast(u64, x18) + x6), x20); | ||
| 1069 | var x37: u64 = undefined; | ||
| 1070 | var x38: u64 = undefined; | ||
| 1071 | mulxU64(&x37, &x38, x1, 0x4fffffffd); | ||
| 1072 | var x39: u64 = undefined; | ||
| 1073 | var x40: u64 = undefined; | ||
| 1074 | mulxU64(&x39, &x40, x1, 0xfffffffffffffffe); | ||
| 1075 | var x41: u64 = undefined; | ||
| 1076 | var x42: u64 = undefined; | ||
| 1077 | mulxU64(&x41, &x42, x1, 0xfffffffbffffffff); | ||
| 1078 | var x43: u64 = undefined; | ||
| 1079 | var x44: u64 = undefined; | ||
| 1080 | mulxU64(&x43, &x44, x1, 0x3); | ||
| 1081 | var x45: u64 = undefined; | ||
| 1082 | var x46: u1 = undefined; | ||
| 1083 | addcarryxU64(&x45, &x46, 0x0, x44, x41); | ||
| 1084 | var x47: u64 = undefined; | ||
| 1085 | var x48: u1 = undefined; | ||
| 1086 | addcarryxU64(&x47, &x48, x46, x42, x39); | ||
| 1087 | var x49: u64 = undefined; | ||
| 1088 | var x50: u1 = undefined; | ||
| 1089 | addcarryxU64(&x49, &x50, x48, x40, x37); | ||
| 1090 | var x51: u64 = undefined; | ||
| 1091 | var x52: u1 = undefined; | ||
| 1092 | addcarryxU64(&x51, &x52, 0x0, x29, x43); | ||
| 1093 | var x53: u64 = undefined; | ||
| 1094 | var x54: u1 = undefined; | ||
| 1095 | addcarryxU64(&x53, &x54, x52, x31, x45); | ||
| 1096 | var x55: u64 = undefined; | ||
| 1097 | var x56: u1 = undefined; | ||
| 1098 | addcarryxU64(&x55, &x56, x54, x33, x47); | ||
| 1099 | var x57: u64 = undefined; | ||
| 1100 | var x58: u1 = undefined; | ||
| 1101 | addcarryxU64(&x57, &x58, x56, x35, x49); | ||
| 1102 | var x59: u64 = undefined; | ||
| 1103 | var x60: u64 = undefined; | ||
| 1104 | mulxU64(&x59, &x60, x51, 0xffffffff00000001); | ||
| 1105 | var x61: u64 = undefined; | ||
| 1106 | var x62: u64 = undefined; | ||
| 1107 | mulxU64(&x61, &x62, x51, 0xffffffff); | ||
| 1108 | var x63: u64 = undefined; | ||
| 1109 | var x64: u64 = undefined; | ||
| 1110 | mulxU64(&x63, &x64, x51, 0xffffffffffffffff); | ||
| 1111 | var x65: u64 = undefined; | ||
| 1112 | var x66: u1 = undefined; | ||
| 1113 | addcarryxU64(&x65, &x66, 0x0, x64, x61); | ||
| 1114 | var x67: u64 = undefined; | ||
| 1115 | var x68: u1 = undefined; | ||
| 1116 | addcarryxU64(&x67, &x68, 0x0, x51, x63); | ||
| 1117 | var x69: u64 = undefined; | ||
| 1118 | var x70: u1 = undefined; | ||
| 1119 | addcarryxU64(&x69, &x70, x68, x53, x65); | ||
| 1120 | var x71: u64 = undefined; | ||
| 1121 | var x72: u1 = undefined; | ||
| 1122 | addcarryxU64(&x71, &x72, x70, x55, (cast(u64, x66) + x62)); | ||
| 1123 | var x73: u64 = undefined; | ||
| 1124 | var x74: u1 = undefined; | ||
| 1125 | addcarryxU64(&x73, &x74, x72, x57, x59); | ||
| 1126 | var x75: u64 = undefined; | ||
| 1127 | var x76: u1 = undefined; | ||
| 1128 | addcarryxU64(&x75, &x76, x74, ((cast(u64, x58) + cast(u64, x36)) + (cast(u64, x50) + x38)), x60); | ||
| 1129 | var x77: u64 = undefined; | ||
| 1130 | var x78: u64 = undefined; | ||
| 1131 | mulxU64(&x77, &x78, x2, 0x4fffffffd); | ||
| 1132 | var x79: u64 = undefined; | ||
| 1133 | var x80: u64 = undefined; | ||
| 1134 | mulxU64(&x79, &x80, x2, 0xfffffffffffffffe); | ||
| 1135 | var x81: u64 = undefined; | ||
| 1136 | var x82: u64 = undefined; | ||
| 1137 | mulxU64(&x81, &x82, x2, 0xfffffffbffffffff); | ||
| 1138 | var x83: u64 = undefined; | ||
| 1139 | var x84: u64 = undefined; | ||
| 1140 | mulxU64(&x83, &x84, x2, 0x3); | ||
| 1141 | var x85: u64 = undefined; | ||
| 1142 | var x86: u1 = undefined; | ||
| 1143 | addcarryxU64(&x85, &x86, 0x0, x84, x81); | ||
| 1144 | var x87: u64 = undefined; | ||
| 1145 | var x88: u1 = undefined; | ||
| 1146 | addcarryxU64(&x87, &x88, x86, x82, x79); | ||
| 1147 | var x89: u64 = undefined; | ||
| 1148 | var x90: u1 = undefined; | ||
| 1149 | addcarryxU64(&x89, &x90, x88, x80, x77); | ||
| 1150 | var x91: u64 = undefined; | ||
| 1151 | var x92: u1 = undefined; | ||
| 1152 | addcarryxU64(&x91, &x92, 0x0, x69, x83); | ||
| 1153 | var x93: u64 = undefined; | ||
| 1154 | var x94: u1 = undefined; | ||
| 1155 | addcarryxU64(&x93, &x94, x92, x71, x85); | ||
| 1156 | var x95: u64 = undefined; | ||
| 1157 | var x96: u1 = undefined; | ||
| 1158 | addcarryxU64(&x95, &x96, x94, x73, x87); | ||
| 1159 | var x97: u64 = undefined; | ||
| 1160 | var x98: u1 = undefined; | ||
| 1161 | addcarryxU64(&x97, &x98, x96, x75, x89); | ||
| 1162 | var x99: u64 = undefined; | ||
| 1163 | var x100: u64 = undefined; | ||
| 1164 | mulxU64(&x99, &x100, x91, 0xffffffff00000001); | ||
| 1165 | var x101: u64 = undefined; | ||
| 1166 | var x102: u64 = undefined; | ||
| 1167 | mulxU64(&x101, &x102, x91, 0xffffffff); | ||
| 1168 | var x103: u64 = undefined; | ||
| 1169 | var x104: u64 = undefined; | ||
| 1170 | mulxU64(&x103, &x104, x91, 0xffffffffffffffff); | ||
| 1171 | var x105: u64 = undefined; | ||
| 1172 | var x106: u1 = undefined; | ||
| 1173 | addcarryxU64(&x105, &x106, 0x0, x104, x101); | ||
| 1174 | var x107: u64 = undefined; | ||
| 1175 | var x108: u1 = undefined; | ||
| 1176 | addcarryxU64(&x107, &x108, 0x0, x91, x103); | ||
| 1177 | var x109: u64 = undefined; | ||
| 1178 | var x110: u1 = undefined; | ||
| 1179 | addcarryxU64(&x109, &x110, x108, x93, x105); | ||
| 1180 | var x111: u64 = undefined; | ||
| 1181 | var x112: u1 = undefined; | ||
| 1182 | addcarryxU64(&x111, &x112, x110, x95, (cast(u64, x106) + x102)); | ||
| 1183 | var x113: u64 = undefined; | ||
| 1184 | var x114: u1 = undefined; | ||
| 1185 | addcarryxU64(&x113, &x114, x112, x97, x99); | ||
| 1186 | var x115: u64 = undefined; | ||
| 1187 | var x116: u1 = undefined; | ||
| 1188 | addcarryxU64(&x115, &x116, x114, ((cast(u64, x98) + cast(u64, x76)) + (cast(u64, x90) + x78)), x100); | ||
| 1189 | var x117: u64 = undefined; | ||
| 1190 | var x118: u64 = undefined; | ||
| 1191 | mulxU64(&x117, &x118, x3, 0x4fffffffd); | ||
| 1192 | var x119: u64 = undefined; | ||
| 1193 | var x120: u64 = undefined; | ||
| 1194 | mulxU64(&x119, &x120, x3, 0xfffffffffffffffe); | ||
| 1195 | var x121: u64 = undefined; | ||
| 1196 | var x122: u64 = undefined; | ||
| 1197 | mulxU64(&x121, &x122, x3, 0xfffffffbffffffff); | ||
| 1198 | var x123: u64 = undefined; | ||
| 1199 | var x124: u64 = undefined; | ||
| 1200 | mulxU64(&x123, &x124, x3, 0x3); | ||
| 1201 | var x125: u64 = undefined; | ||
| 1202 | var x126: u1 = undefined; | ||
| 1203 | addcarryxU64(&x125, &x126, 0x0, x124, x121); | ||
| 1204 | var x127: u64 = undefined; | ||
| 1205 | var x128: u1 = undefined; | ||
| 1206 | addcarryxU64(&x127, &x128, x126, x122, x119); | ||
| 1207 | var x129: u64 = undefined; | ||
| 1208 | var x130: u1 = undefined; | ||
| 1209 | addcarryxU64(&x129, &x130, x128, x120, x117); | ||
| 1210 | var x131: u64 = undefined; | ||
| 1211 | var x132: u1 = undefined; | ||
| 1212 | addcarryxU64(&x131, &x132, 0x0, x109, x123); | ||
| 1213 | var x133: u64 = undefined; | ||
| 1214 | var x134: u1 = undefined; | ||
| 1215 | addcarryxU64(&x133, &x134, x132, x111, x125); | ||
| 1216 | var x135: u64 = undefined; | ||
| 1217 | var x136: u1 = undefined; | ||
| 1218 | addcarryxU64(&x135, &x136, x134, x113, x127); | ||
| 1219 | var x137: u64 = undefined; | ||
| 1220 | var x138: u1 = undefined; | ||
| 1221 | addcarryxU64(&x137, &x138, x136, x115, x129); | ||
| 1222 | var x139: u64 = undefined; | ||
| 1223 | var x140: u64 = undefined; | ||
| 1224 | mulxU64(&x139, &x140, x131, 0xffffffff00000001); | ||
| 1225 | var x141: u64 = undefined; | ||
| 1226 | var x142: u64 = undefined; | ||
| 1227 | mulxU64(&x141, &x142, x131, 0xffffffff); | ||
| 1228 | var x143: u64 = undefined; | ||
| 1229 | var x144: u64 = undefined; | ||
| 1230 | mulxU64(&x143, &x144, x131, 0xffffffffffffffff); | ||
| 1231 | var x145: u64 = undefined; | ||
| 1232 | var x146: u1 = undefined; | ||
| 1233 | addcarryxU64(&x145, &x146, 0x0, x144, x141); | ||
| 1234 | var x147: u64 = undefined; | ||
| 1235 | var x148: u1 = undefined; | ||
| 1236 | addcarryxU64(&x147, &x148, 0x0, x131, x143); | ||
| 1237 | var x149: u64 = undefined; | ||
| 1238 | var x150: u1 = undefined; | ||
| 1239 | addcarryxU64(&x149, &x150, x148, x133, x145); | ||
| 1240 | var x151: u64 = undefined; | ||
| 1241 | var x152: u1 = undefined; | ||
| 1242 | addcarryxU64(&x151, &x152, x150, x135, (cast(u64, x146) + x142)); | ||
| 1243 | var x153: u64 = undefined; | ||
| 1244 | var x154: u1 = undefined; | ||
| 1245 | addcarryxU64(&x153, &x154, x152, x137, x139); | ||
| 1246 | var x155: u64 = undefined; | ||
| 1247 | var x156: u1 = undefined; | ||
| 1248 | addcarryxU64(&x155, &x156, x154, ((cast(u64, x138) + cast(u64, x116)) + (cast(u64, x130) + x118)), x140); | ||
| 1249 | var x157: u64 = undefined; | ||
| 1250 | var x158: u1 = undefined; | ||
| 1251 | subborrowxU64(&x157, &x158, 0x0, x149, 0xffffffffffffffff); | ||
| 1252 | var x159: u64 = undefined; | ||
| 1253 | var x160: u1 = undefined; | ||
| 1254 | subborrowxU64(&x159, &x160, x158, x151, 0xffffffff); | ||
| 1255 | var x161: u64 = undefined; | ||
| 1256 | var x162: u1 = undefined; | ||
| 1257 | subborrowxU64(&x161, &x162, x160, x153, cast(u64, 0x0)); | ||
| 1258 | var x163: u64 = undefined; | ||
| 1259 | var x164: u1 = undefined; | ||
| 1260 | subborrowxU64(&x163, &x164, x162, x155, 0xffffffff00000001); | ||
| 1261 | var x165: u64 = undefined; | ||
| 1262 | var x166: u1 = undefined; | ||
| 1263 | subborrowxU64(&x165, &x166, x164, cast(u64, x156), cast(u64, 0x0)); | ||
| 1264 | var x167: u64 = undefined; | ||
| 1265 | cmovznzU64(&x167, x166, x157, x149); | ||
| 1266 | var x168: u64 = undefined; | ||
| 1267 | cmovznzU64(&x168, x166, x159, x151); | ||
| 1268 | var x169: u64 = undefined; | ||
| 1269 | cmovznzU64(&x169, x166, x161, x153); | ||
| 1270 | var x170: u64 = undefined; | ||
| 1271 | cmovznzU64(&x170, x166, x163, x155); | ||
| 1272 | out1[0] = x167; | ||
| 1273 | out1[1] = x168; | ||
| 1274 | out1[2] = x169; | ||
| 1275 | out1[3] = x170; | ||
| 1276 | } | ||
| 1277 | |||
| 1278 | /// The function nonzero outputs a single non-zero word if the input is non-zero and zero otherwise. | ||
| 1279 | /// Preconditions: | ||
| 1280 | /// 0 ≤ eval arg1 < m | ||
| 1281 | /// Postconditions: | ||
| 1282 | /// out1 = 0 ↔ eval (from_montgomery arg1) mod m = 0 | ||
| 1283 | /// | ||
| 1284 | /// Input Bounds: | ||
| 1285 | /// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 1286 | /// Output Bounds: | ||
| 1287 | /// out1: [0x0 ~> 0xffffffffffffffff] | ||
| 1288 | pub fn nonzero(out1: *u64, arg1: [4]u64) void { | ||
| 1289 | @setRuntimeSafety(mode == .Debug); | ||
| 1290 | |||
| 1291 | const x1 = ((arg1[0]) | ((arg1[1]) | ((arg1[2]) | (arg1[3])))); | ||
| 1292 | out1.* = x1; | ||
| 1293 | } | ||
| 1294 | |||
| 1295 | /// The function selectznz is a multi-limb conditional select. | ||
| 1296 | /// Postconditions: | ||
| 1297 | /// eval out1 = (if arg1 = 0 then eval arg2 else eval arg3) | ||
| 1298 | /// | ||
| 1299 | /// Input Bounds: | ||
| 1300 | /// arg1: [0x0 ~> 0x1] | ||
| 1301 | /// arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 1302 | /// arg3: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 1303 | /// Output Bounds: | ||
| 1304 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 1305 | pub fn selectznz(out1: *[4]u64, arg1: u1, arg2: [4]u64, arg3: [4]u64) void { | ||
| 1306 | @setRuntimeSafety(mode == .Debug); | ||
| 1307 | |||
| 1308 | var x1: u64 = undefined; | ||
| 1309 | cmovznzU64(&x1, arg1, (arg2[0]), (arg3[0])); | ||
| 1310 | var x2: u64 = undefined; | ||
| 1311 | cmovznzU64(&x2, arg1, (arg2[1]), (arg3[1])); | ||
| 1312 | var x3: u64 = undefined; | ||
| 1313 | cmovznzU64(&x3, arg1, (arg2[2]), (arg3[2])); | ||
| 1314 | var x4: u64 = undefined; | ||
| 1315 | cmovznzU64(&x4, arg1, (arg2[3]), (arg3[3])); | ||
| 1316 | out1[0] = x1; | ||
| 1317 | out1[1] = x2; | ||
| 1318 | out1[2] = x3; | ||
| 1319 | out1[3] = x4; | ||
| 1320 | } | ||
| 1321 | |||
| 1322 | /// The function toBytes serializes a field element NOT in the Montgomery domain to bytes in little-endian order. | ||
| 1323 | /// Preconditions: | ||
| 1324 | /// 0 ≤ eval arg1 < m | ||
| 1325 | /// Postconditions: | ||
| 1326 | /// out1 = map (λ x, ⌊((eval arg1 mod m) mod 2^(8 * (x + 1))) / 2^(8 * x)⌋) [0..31] | ||
| 1327 | /// | ||
| 1328 | /// Input Bounds: | ||
| 1329 | /// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 1330 | /// Output Bounds: | ||
| 1331 | /// 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]] | ||
| 1332 | pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void { | ||
| 1333 | @setRuntimeSafety(mode == .Debug); | ||
| 1334 | |||
| 1335 | const x1 = (arg1[3]); | ||
| 1336 | const x2 = (arg1[2]); | ||
| 1337 | const x3 = (arg1[1]); | ||
| 1338 | const x4 = (arg1[0]); | ||
| 1339 | const x5 = cast(u8, (x4 & cast(u64, 0xff))); | ||
| 1340 | const x6 = (x4 >> 8); | ||
| 1341 | const x7 = cast(u8, (x6 & cast(u64, 0xff))); | ||
| 1342 | const x8 = (x6 >> 8); | ||
| 1343 | const x9 = cast(u8, (x8 & cast(u64, 0xff))); | ||
| 1344 | const x10 = (x8 >> 8); | ||
| 1345 | const x11 = cast(u8, (x10 & cast(u64, 0xff))); | ||
| 1346 | const x12 = (x10 >> 8); | ||
| 1347 | const x13 = cast(u8, (x12 & cast(u64, 0xff))); | ||
| 1348 | const x14 = (x12 >> 8); | ||
| 1349 | const x15 = cast(u8, (x14 & cast(u64, 0xff))); | ||
| 1350 | const x16 = (x14 >> 8); | ||
| 1351 | const x17 = cast(u8, (x16 & cast(u64, 0xff))); | ||
| 1352 | const x18 = cast(u8, (x16 >> 8)); | ||
| 1353 | const x19 = cast(u8, (x3 & cast(u64, 0xff))); | ||
| 1354 | const x20 = (x3 >> 8); | ||
| 1355 | const x21 = cast(u8, (x20 & cast(u64, 0xff))); | ||
| 1356 | const x22 = (x20 >> 8); | ||
| 1357 | const x23 = cast(u8, (x22 & cast(u64, 0xff))); | ||
| 1358 | const x24 = (x22 >> 8); | ||
| 1359 | const x25 = cast(u8, (x24 & cast(u64, 0xff))); | ||
| 1360 | const x26 = (x24 >> 8); | ||
| 1361 | const x27 = cast(u8, (x26 & cast(u64, 0xff))); | ||
| 1362 | const x28 = (x26 >> 8); | ||
| 1363 | const x29 = cast(u8, (x28 & cast(u64, 0xff))); | ||
| 1364 | const x30 = (x28 >> 8); | ||
| 1365 | const x31 = cast(u8, (x30 & cast(u64, 0xff))); | ||
| 1366 | const x32 = cast(u8, (x30 >> 8)); | ||
| 1367 | const x33 = cast(u8, (x2 & cast(u64, 0xff))); | ||
| 1368 | const x34 = (x2 >> 8); | ||
| 1369 | const x35 = cast(u8, (x34 & cast(u64, 0xff))); | ||
| 1370 | const x36 = (x34 >> 8); | ||
| 1371 | const x37 = cast(u8, (x36 & cast(u64, 0xff))); | ||
| 1372 | const x38 = (x36 >> 8); | ||
| 1373 | const x39 = cast(u8, (x38 & cast(u64, 0xff))); | ||
| 1374 | const x40 = (x38 >> 8); | ||
| 1375 | const x41 = cast(u8, (x40 & cast(u64, 0xff))); | ||
| 1376 | const x42 = (x40 >> 8); | ||
| 1377 | const x43 = cast(u8, (x42 & cast(u64, 0xff))); | ||
| 1378 | const x44 = (x42 >> 8); | ||
| 1379 | const x45 = cast(u8, (x44 & cast(u64, 0xff))); | ||
| 1380 | const x46 = cast(u8, (x44 >> 8)); | ||
| 1381 | const x47 = cast(u8, (x1 & cast(u64, 0xff))); | ||
| 1382 | const x48 = (x1 >> 8); | ||
| 1383 | const x49 = cast(u8, (x48 & cast(u64, 0xff))); | ||
| 1384 | const x50 = (x48 >> 8); | ||
| 1385 | const x51 = cast(u8, (x50 & cast(u64, 0xff))); | ||
| 1386 | const x52 = (x50 >> 8); | ||
| 1387 | const x53 = cast(u8, (x52 & cast(u64, 0xff))); | ||
| 1388 | const x54 = (x52 >> 8); | ||
| 1389 | const x55 = cast(u8, (x54 & cast(u64, 0xff))); | ||
| 1390 | const x56 = (x54 >> 8); | ||
| 1391 | const x57 = cast(u8, (x56 & cast(u64, 0xff))); | ||
| 1392 | const x58 = (x56 >> 8); | ||
| 1393 | const x59 = cast(u8, (x58 & cast(u64, 0xff))); | ||
| 1394 | const x60 = cast(u8, (x58 >> 8)); | ||
| 1395 | out1[0] = x5; | ||
| 1396 | out1[1] = x7; | ||
| 1397 | out1[2] = x9; | ||
| 1398 | out1[3] = x11; | ||
| 1399 | out1[4] = x13; | ||
| 1400 | out1[5] = x15; | ||
| 1401 | out1[6] = x17; | ||
| 1402 | out1[7] = x18; | ||
| 1403 | out1[8] = x19; | ||
| 1404 | out1[9] = x21; | ||
| 1405 | out1[10] = x23; | ||
| 1406 | out1[11] = x25; | ||
| 1407 | out1[12] = x27; | ||
| 1408 | out1[13] = x29; | ||
| 1409 | out1[14] = x31; | ||
| 1410 | out1[15] = x32; | ||
| 1411 | out1[16] = x33; | ||
| 1412 | out1[17] = x35; | ||
| 1413 | out1[18] = x37; | ||
| 1414 | out1[19] = x39; | ||
| 1415 | out1[20] = x41; | ||
| 1416 | out1[21] = x43; | ||
| 1417 | out1[22] = x45; | ||
| 1418 | out1[23] = x46; | ||
| 1419 | out1[24] = x47; | ||
| 1420 | out1[25] = x49; | ||
| 1421 | out1[26] = x51; | ||
| 1422 | out1[27] = x53; | ||
| 1423 | out1[28] = x55; | ||
| 1424 | out1[29] = x57; | ||
| 1425 | out1[30] = x59; | ||
| 1426 | out1[31] = x60; | ||
| 1427 | } | ||
| 1428 | |||
| 1429 | /// The function fromBytes deserializes a field element NOT in the Montgomery domain from bytes in little-endian order. | ||
| 1430 | /// Preconditions: | ||
| 1431 | /// 0 ≤ bytes_eval arg1 < m | ||
| 1432 | /// Postconditions: | ||
| 1433 | /// eval out1 mod m = bytes_eval arg1 mod m | ||
| 1434 | /// 0 ≤ eval out1 < m | ||
| 1435 | /// | ||
| 1436 | /// Input Bounds: | ||
| 1437 | /// arg1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff]] | ||
| 1438 | /// Output Bounds: | ||
| 1439 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 1440 | pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void { | ||
| 1441 | @setRuntimeSafety(mode == .Debug); | ||
| 1442 | |||
| 1443 | const x1 = (cast(u64, (arg1[31])) << 56); | ||
| 1444 | const x2 = (cast(u64, (arg1[30])) << 48); | ||
| 1445 | const x3 = (cast(u64, (arg1[29])) << 40); | ||
| 1446 | const x4 = (cast(u64, (arg1[28])) << 32); | ||
| 1447 | const x5 = (cast(u64, (arg1[27])) << 24); | ||
| 1448 | const x6 = (cast(u64, (arg1[26])) << 16); | ||
| 1449 | const x7 = (cast(u64, (arg1[25])) << 8); | ||
| 1450 | const x8 = (arg1[24]); | ||
| 1451 | const x9 = (cast(u64, (arg1[23])) << 56); | ||
| 1452 | const x10 = (cast(u64, (arg1[22])) << 48); | ||
| 1453 | const x11 = (cast(u64, (arg1[21])) << 40); | ||
| 1454 | const x12 = (cast(u64, (arg1[20])) << 32); | ||
| 1455 | const x13 = (cast(u64, (arg1[19])) << 24); | ||
| 1456 | const x14 = (cast(u64, (arg1[18])) << 16); | ||
| 1457 | const x15 = (cast(u64, (arg1[17])) << 8); | ||
| 1458 | const x16 = (arg1[16]); | ||
| 1459 | const x17 = (cast(u64, (arg1[15])) << 56); | ||
| 1460 | const x18 = (cast(u64, (arg1[14])) << 48); | ||
| 1461 | const x19 = (cast(u64, (arg1[13])) << 40); | ||
| 1462 | const x20 = (cast(u64, (arg1[12])) << 32); | ||
| 1463 | const x21 = (cast(u64, (arg1[11])) << 24); | ||
| 1464 | const x22 = (cast(u64, (arg1[10])) << 16); | ||
| 1465 | const x23 = (cast(u64, (arg1[9])) << 8); | ||
| 1466 | const x24 = (arg1[8]); | ||
| 1467 | const x25 = (cast(u64, (arg1[7])) << 56); | ||
| 1468 | const x26 = (cast(u64, (arg1[6])) << 48); | ||
| 1469 | const x27 = (cast(u64, (arg1[5])) << 40); | ||
| 1470 | const x28 = (cast(u64, (arg1[4])) << 32); | ||
| 1471 | const x29 = (cast(u64, (arg1[3])) << 24); | ||
| 1472 | const x30 = (cast(u64, (arg1[2])) << 16); | ||
| 1473 | const x31 = (cast(u64, (arg1[1])) << 8); | ||
| 1474 | const x32 = (arg1[0]); | ||
| 1475 | const x33 = (x31 + cast(u64, x32)); | ||
| 1476 | const x34 = (x30 + x33); | ||
| 1477 | const x35 = (x29 + x34); | ||
| 1478 | const x36 = (x28 + x35); | ||
| 1479 | const x37 = (x27 + x36); | ||
| 1480 | const x38 = (x26 + x37); | ||
| 1481 | const x39 = (x25 + x38); | ||
| 1482 | const x40 = (x23 + cast(u64, x24)); | ||
| 1483 | const x41 = (x22 + x40); | ||
| 1484 | const x42 = (x21 + x41); | ||
| 1485 | const x43 = (x20 + x42); | ||
| 1486 | const x44 = (x19 + x43); | ||
| 1487 | const x45 = (x18 + x44); | ||
| 1488 | const x46 = (x17 + x45); | ||
| 1489 | const x47 = (x15 + cast(u64, x16)); | ||
| 1490 | const x48 = (x14 + x47); | ||
| 1491 | const x49 = (x13 + x48); | ||
| 1492 | const x50 = (x12 + x49); | ||
| 1493 | const x51 = (x11 + x50); | ||
| 1494 | const x52 = (x10 + x51); | ||
| 1495 | const x53 = (x9 + x52); | ||
| 1496 | const x54 = (x7 + cast(u64, x8)); | ||
| 1497 | const x55 = (x6 + x54); | ||
| 1498 | const x56 = (x5 + x55); | ||
| 1499 | const x57 = (x4 + x56); | ||
| 1500 | const x58 = (x3 + x57); | ||
| 1501 | const x59 = (x2 + x58); | ||
| 1502 | const x60 = (x1 + x59); | ||
| 1503 | out1[0] = x39; | ||
| 1504 | out1[1] = x46; | ||
| 1505 | out1[2] = x53; | ||
| 1506 | out1[3] = x60; | ||
| 1507 | } | ||
| 1508 | |||
| 1509 | /// The function setOne returns the field element one in the Montgomery domain. | ||
| 1510 | /// Postconditions: | ||
| 1511 | /// eval (from_montgomery out1) mod m = 1 mod m | ||
| 1512 | /// 0 ≤ eval out1 < m | ||
| 1513 | /// | ||
| 1514 | /// Input Bounds: | ||
| 1515 | /// Output Bounds: | ||
| 1516 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 1517 | pub fn setOne(out1: *[4]u64) void { | ||
| 1518 | @setRuntimeSafety(mode == .Debug); | ||
| 1519 | |||
| 1520 | out1[0] = cast(u64, 0x1); | ||
| 1521 | out1[1] = 0xffffffff00000000; | ||
| 1522 | out1[2] = 0xffffffffffffffff; | ||
| 1523 | out1[3] = 0xfffffffe; | ||
| 1524 | } | ||
| 1525 | |||
| 1526 | /// The function msat returns the saturated representation of the prime modulus. | ||
| 1527 | /// Postconditions: | ||
| 1528 | /// twos_complement_eval out1 = m | ||
| 1529 | /// 0 ≤ eval out1 < m | ||
| 1530 | /// | ||
| 1531 | /// Input Bounds: | ||
| 1532 | /// Output Bounds: | ||
| 1533 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 1534 | pub fn msat(out1: *[5]u64) void { | ||
| 1535 | @setRuntimeSafety(mode == .Debug); | ||
| 1536 | |||
| 1537 | out1[0] = 0xffffffffffffffff; | ||
| 1538 | out1[1] = 0xffffffff; | ||
| 1539 | out1[2] = cast(u64, 0x0); | ||
| 1540 | out1[3] = 0xffffffff00000001; | ||
| 1541 | out1[4] = cast(u64, 0x0); | ||
| 1542 | } | ||
| 1543 | |||
| 1544 | /// The function divstep computes a divstep. | ||
| 1545 | /// Preconditions: | ||
| 1546 | /// 0 ≤ eval arg4 < m | ||
| 1547 | /// 0 ≤ eval arg5 < m | ||
| 1548 | /// Postconditions: | ||
| 1549 | /// out1 = (if 0 < arg1 ∧ (twos_complement_eval arg3) is odd then 1 - arg1 else 1 + arg1) | ||
| 1550 | /// twos_complement_eval out2 = (if 0 < arg1 ∧ (twos_complement_eval arg3) is odd then twos_complement_eval arg3 else twos_complement_eval arg2) | ||
| 1551 | /// twos_complement_eval out3 = (if 0 < arg1 ∧ (twos_complement_eval arg3) is odd then ⌊(twos_complement_eval arg3 - twos_complement_eval arg2) / 2⌋ else ⌊(twos_complement_eval arg3 + (twos_complement_eval arg3 mod 2) * twos_complement_eval arg2) / 2⌋) | ||
| 1552 | /// eval (from_montgomery out4) mod m = (if 0 < arg1 ∧ (twos_complement_eval arg3) is odd then (2 * eval (from_montgomery arg5)) mod m else (2 * eval (from_montgomery arg4)) mod m) | ||
| 1553 | /// eval (from_montgomery out5) mod m = (if 0 < arg1 ∧ (twos_complement_eval arg3) is odd then (eval (from_montgomery arg4) - eval (from_montgomery arg4)) mod m else (eval (from_montgomery arg5) + (twos_complement_eval arg3 mod 2) * eval (from_montgomery arg4)) mod m) | ||
| 1554 | /// 0 ≤ eval out5 < m | ||
| 1555 | /// 0 ≤ eval out5 < m | ||
| 1556 | /// 0 ≤ eval out2 < m | ||
| 1557 | /// 0 ≤ eval out3 < m | ||
| 1558 | /// | ||
| 1559 | /// Input Bounds: | ||
| 1560 | /// arg1: [0x0 ~> 0xffffffffffffffff] | ||
| 1561 | /// arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 1562 | /// arg3: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 1563 | /// arg4: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 1564 | /// arg5: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 1565 | /// Output Bounds: | ||
| 1566 | /// out1: [0x0 ~> 0xffffffffffffffff] | ||
| 1567 | /// out2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 1568 | /// out3: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 1569 | /// out4: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 1570 | /// out5: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 1571 | 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 { | ||
| 1572 | @setRuntimeSafety(mode == .Debug); | ||
| 1573 | |||
| 1574 | var x1: u64 = undefined; | ||
| 1575 | var x2: u1 = undefined; | ||
| 1576 | addcarryxU64(&x1, &x2, 0x0, (~arg1), cast(u64, 0x1)); | ||
| 1577 | const x3 = (cast(u1, (x1 >> 63)) & cast(u1, ((arg3[0]) & cast(u64, 0x1)))); | ||
| 1578 | var x4: u64 = undefined; | ||
| 1579 | var x5: u1 = undefined; | ||
| 1580 | addcarryxU64(&x4, &x5, 0x0, (~arg1), cast(u64, 0x1)); | ||
| 1581 | var x6: u64 = undefined; | ||
| 1582 | cmovznzU64(&x6, x3, arg1, x4); | ||
| 1583 | var x7: u64 = undefined; | ||
| 1584 | cmovznzU64(&x7, x3, (arg2[0]), (arg3[0])); | ||
| 1585 | var x8: u64 = undefined; | ||
| 1586 | cmovznzU64(&x8, x3, (arg2[1]), (arg3[1])); | ||
| 1587 | var x9: u64 = undefined; | ||
| 1588 | cmovznzU64(&x9, x3, (arg2[2]), (arg3[2])); | ||
| 1589 | var x10: u64 = undefined; | ||
| 1590 | cmovznzU64(&x10, x3, (arg2[3]), (arg3[3])); | ||
| 1591 | var x11: u64 = undefined; | ||
| 1592 | cmovznzU64(&x11, x3, (arg2[4]), (arg3[4])); | ||
| 1593 | var x12: u64 = undefined; | ||
| 1594 | var x13: u1 = undefined; | ||
| 1595 | addcarryxU64(&x12, &x13, 0x0, cast(u64, 0x1), (~(arg2[0]))); | ||
| 1596 | var x14: u64 = undefined; | ||
| 1597 | var x15: u1 = undefined; | ||
| 1598 | addcarryxU64(&x14, &x15, x13, cast(u64, 0x0), (~(arg2[1]))); | ||
| 1599 | var x16: u64 = undefined; | ||
| 1600 | var x17: u1 = undefined; | ||
| 1601 | addcarryxU64(&x16, &x17, x15, cast(u64, 0x0), (~(arg2[2]))); | ||
| 1602 | var x18: u64 = undefined; | ||
| 1603 | var x19: u1 = undefined; | ||
| 1604 | addcarryxU64(&x18, &x19, x17, cast(u64, 0x0), (~(arg2[3]))); | ||
| 1605 | var x20: u64 = undefined; | ||
| 1606 | var x21: u1 = undefined; | ||
| 1607 | addcarryxU64(&x20, &x21, x19, cast(u64, 0x0), (~(arg2[4]))); | ||
| 1608 | var x22: u64 = undefined; | ||
| 1609 | cmovznzU64(&x22, x3, (arg3[0]), x12); | ||
| 1610 | var x23: u64 = undefined; | ||
| 1611 | cmovznzU64(&x23, x3, (arg3[1]), x14); | ||
| 1612 | var x24: u64 = undefined; | ||
| 1613 | cmovznzU64(&x24, x3, (arg3[2]), x16); | ||
| 1614 | var x25: u64 = undefined; | ||
| 1615 | cmovznzU64(&x25, x3, (arg3[3]), x18); | ||
| 1616 | var x26: u64 = undefined; | ||
| 1617 | cmovznzU64(&x26, x3, (arg3[4]), x20); | ||
| 1618 | var x27: u64 = undefined; | ||
| 1619 | cmovznzU64(&x27, x3, (arg4[0]), (arg5[0])); | ||
| 1620 | var x28: u64 = undefined; | ||
| 1621 | cmovznzU64(&x28, x3, (arg4[1]), (arg5[1])); | ||
| 1622 | var x29: u64 = undefined; | ||
| 1623 | cmovznzU64(&x29, x3, (arg4[2]), (arg5[2])); | ||
| 1624 | var x30: u64 = undefined; | ||
| 1625 | cmovznzU64(&x30, x3, (arg4[3]), (arg5[3])); | ||
| 1626 | var x31: u64 = undefined; | ||
| 1627 | var x32: u1 = undefined; | ||
| 1628 | addcarryxU64(&x31, &x32, 0x0, x27, x27); | ||
| 1629 | var x33: u64 = undefined; | ||
| 1630 | var x34: u1 = undefined; | ||
| 1631 | addcarryxU64(&x33, &x34, x32, x28, x28); | ||
| 1632 | var x35: u64 = undefined; | ||
| 1633 | var x36: u1 = undefined; | ||
| 1634 | addcarryxU64(&x35, &x36, x34, x29, x29); | ||
| 1635 | var x37: u64 = undefined; | ||
| 1636 | var x38: u1 = undefined; | ||
| 1637 | addcarryxU64(&x37, &x38, x36, x30, x30); | ||
| 1638 | var x39: u64 = undefined; | ||
| 1639 | var x40: u1 = undefined; | ||
| 1640 | subborrowxU64(&x39, &x40, 0x0, x31, 0xffffffffffffffff); | ||
| 1641 | var x41: u64 = undefined; | ||
| 1642 | var x42: u1 = undefined; | ||
| 1643 | subborrowxU64(&x41, &x42, x40, x33, 0xffffffff); | ||
| 1644 | var x43: u64 = undefined; | ||
| 1645 | var x44: u1 = undefined; | ||
| 1646 | subborrowxU64(&x43, &x44, x42, x35, cast(u64, 0x0)); | ||
| 1647 | var x45: u64 = undefined; | ||
| 1648 | var x46: u1 = undefined; | ||
| 1649 | subborrowxU64(&x45, &x46, x44, x37, 0xffffffff00000001); | ||
| 1650 | var x47: u64 = undefined; | ||
| 1651 | var x48: u1 = undefined; | ||
| 1652 | subborrowxU64(&x47, &x48, x46, cast(u64, x38), cast(u64, 0x0)); | ||
| 1653 | const x49 = (arg4[3]); | ||
| 1654 | const x50 = (arg4[2]); | ||
| 1655 | const x51 = (arg4[1]); | ||
| 1656 | const x52 = (arg4[0]); | ||
| 1657 | var x53: u64 = undefined; | ||
| 1658 | var x54: u1 = undefined; | ||
| 1659 | subborrowxU64(&x53, &x54, 0x0, cast(u64, 0x0), x52); | ||
| 1660 | var x55: u64 = undefined; | ||
| 1661 | var x56: u1 = undefined; | ||
| 1662 | subborrowxU64(&x55, &x56, x54, cast(u64, 0x0), x51); | ||
| 1663 | var x57: u64 = undefined; | ||
| 1664 | var x58: u1 = undefined; | ||
| 1665 | subborrowxU64(&x57, &x58, x56, cast(u64, 0x0), x50); | ||
| 1666 | var x59: u64 = undefined; | ||
| 1667 | var x60: u1 = undefined; | ||
| 1668 | subborrowxU64(&x59, &x60, x58, cast(u64, 0x0), x49); | ||
| 1669 | var x61: u64 = undefined; | ||
| 1670 | cmovznzU64(&x61, x60, cast(u64, 0x0), 0xffffffffffffffff); | ||
| 1671 | var x62: u64 = undefined; | ||
| 1672 | var x63: u1 = undefined; | ||
| 1673 | addcarryxU64(&x62, &x63, 0x0, x53, x61); | ||
| 1674 | var x64: u64 = undefined; | ||
| 1675 | var x65: u1 = undefined; | ||
| 1676 | addcarryxU64(&x64, &x65, x63, x55, (x61 & 0xffffffff)); | ||
| 1677 | var x66: u64 = undefined; | ||
| 1678 | var x67: u1 = undefined; | ||
| 1679 | addcarryxU64(&x66, &x67, x65, x57, cast(u64, 0x0)); | ||
| 1680 | var x68: u64 = undefined; | ||
| 1681 | var x69: u1 = undefined; | ||
| 1682 | addcarryxU64(&x68, &x69, x67, x59, (x61 & 0xffffffff00000001)); | ||
| 1683 | var x70: u64 = undefined; | ||
| 1684 | cmovznzU64(&x70, x3, (arg5[0]), x62); | ||
| 1685 | var x71: u64 = undefined; | ||
| 1686 | cmovznzU64(&x71, x3, (arg5[1]), x64); | ||
| 1687 | var x72: u64 = undefined; | ||
| 1688 | cmovznzU64(&x72, x3, (arg5[2]), x66); | ||
| 1689 | var x73: u64 = undefined; | ||
| 1690 | cmovznzU64(&x73, x3, (arg5[3]), x68); | ||
| 1691 | const x74 = cast(u1, (x22 & cast(u64, 0x1))); | ||
| 1692 | var x75: u64 = undefined; | ||
| 1693 | cmovznzU64(&x75, x74, cast(u64, 0x0), x7); | ||
| 1694 | var x76: u64 = undefined; | ||
| 1695 | cmovznzU64(&x76, x74, cast(u64, 0x0), x8); | ||
| 1696 | var x77: u64 = undefined; | ||
| 1697 | cmovznzU64(&x77, x74, cast(u64, 0x0), x9); | ||
| 1698 | var x78: u64 = undefined; | ||
| 1699 | cmovznzU64(&x78, x74, cast(u64, 0x0), x10); | ||
| 1700 | var x79: u64 = undefined; | ||
| 1701 | cmovznzU64(&x79, x74, cast(u64, 0x0), x11); | ||
| 1702 | var x80: u64 = undefined; | ||
| 1703 | var x81: u1 = undefined; | ||
| 1704 | addcarryxU64(&x80, &x81, 0x0, x22, x75); | ||
| 1705 | var x82: u64 = undefined; | ||
| 1706 | var x83: u1 = undefined; | ||
| 1707 | addcarryxU64(&x82, &x83, x81, x23, x76); | ||
| 1708 | var x84: u64 = undefined; | ||
| 1709 | var x85: u1 = undefined; | ||
| 1710 | addcarryxU64(&x84, &x85, x83, x24, x77); | ||
| 1711 | var x86: u64 = undefined; | ||
| 1712 | var x87: u1 = undefined; | ||
| 1713 | addcarryxU64(&x86, &x87, x85, x25, x78); | ||
| 1714 | var x88: u64 = undefined; | ||
| 1715 | var x89: u1 = undefined; | ||
| 1716 | addcarryxU64(&x88, &x89, x87, x26, x79); | ||
| 1717 | var x90: u64 = undefined; | ||
| 1718 | cmovznzU64(&x90, x74, cast(u64, 0x0), x27); | ||
| 1719 | var x91: u64 = undefined; | ||
| 1720 | cmovznzU64(&x91, x74, cast(u64, 0x0), x28); | ||
| 1721 | var x92: u64 = undefined; | ||
| 1722 | cmovznzU64(&x92, x74, cast(u64, 0x0), x29); | ||
| 1723 | var x93: u64 = undefined; | ||
| 1724 | cmovznzU64(&x93, x74, cast(u64, 0x0), x30); | ||
| 1725 | var x94: u64 = undefined; | ||
| 1726 | var x95: u1 = undefined; | ||
| 1727 | addcarryxU64(&x94, &x95, 0x0, x70, x90); | ||
| 1728 | var x96: u64 = undefined; | ||
| 1729 | var x97: u1 = undefined; | ||
| 1730 | addcarryxU64(&x96, &x97, x95, x71, x91); | ||
| 1731 | var x98: u64 = undefined; | ||
| 1732 | var x99: u1 = undefined; | ||
| 1733 | addcarryxU64(&x98, &x99, x97, x72, x92); | ||
| 1734 | var x100: u64 = undefined; | ||
| 1735 | var x101: u1 = undefined; | ||
| 1736 | addcarryxU64(&x100, &x101, x99, x73, x93); | ||
| 1737 | var x102: u64 = undefined; | ||
| 1738 | var x103: u1 = undefined; | ||
| 1739 | subborrowxU64(&x102, &x103, 0x0, x94, 0xffffffffffffffff); | ||
| 1740 | var x104: u64 = undefined; | ||
| 1741 | var x105: u1 = undefined; | ||
| 1742 | subborrowxU64(&x104, &x105, x103, x96, 0xffffffff); | ||
| 1743 | var x106: u64 = undefined; | ||
| 1744 | var x107: u1 = undefined; | ||
| 1745 | subborrowxU64(&x106, &x107, x105, x98, cast(u64, 0x0)); | ||
| 1746 | var x108: u64 = undefined; | ||
| 1747 | var x109: u1 = undefined; | ||
| 1748 | subborrowxU64(&x108, &x109, x107, x100, 0xffffffff00000001); | ||
| 1749 | var x110: u64 = undefined; | ||
| 1750 | var x111: u1 = undefined; | ||
| 1751 | subborrowxU64(&x110, &x111, x109, cast(u64, x101), cast(u64, 0x0)); | ||
| 1752 | var x112: u64 = undefined; | ||
| 1753 | var x113: u1 = undefined; | ||
| 1754 | addcarryxU64(&x112, &x113, 0x0, x6, cast(u64, 0x1)); | ||
| 1755 | const x114 = ((x80 >> 1) | ((x82 << 63) & 0xffffffffffffffff)); | ||
| 1756 | const x115 = ((x82 >> 1) | ((x84 << 63) & 0xffffffffffffffff)); | ||
| 1757 | const x116 = ((x84 >> 1) | ((x86 << 63) & 0xffffffffffffffff)); | ||
| 1758 | const x117 = ((x86 >> 1) | ((x88 << 63) & 0xffffffffffffffff)); | ||
| 1759 | const x118 = ((x88 & 0x8000000000000000) | (x88 >> 1)); | ||
| 1760 | var x119: u64 = undefined; | ||
| 1761 | cmovznzU64(&x119, x48, x39, x31); | ||
| 1762 | var x120: u64 = undefined; | ||
| 1763 | cmovznzU64(&x120, x48, x41, x33); | ||
| 1764 | var x121: u64 = undefined; | ||
| 1765 | cmovznzU64(&x121, x48, x43, x35); | ||
| 1766 | var x122: u64 = undefined; | ||
| 1767 | cmovznzU64(&x122, x48, x45, x37); | ||
| 1768 | var x123: u64 = undefined; | ||
| 1769 | cmovznzU64(&x123, x111, x102, x94); | ||
| 1770 | var x124: u64 = undefined; | ||
| 1771 | cmovznzU64(&x124, x111, x104, x96); | ||
| 1772 | var x125: u64 = undefined; | ||
| 1773 | cmovznzU64(&x125, x111, x106, x98); | ||
| 1774 | var x126: u64 = undefined; | ||
| 1775 | cmovznzU64(&x126, x111, x108, x100); | ||
| 1776 | out1.* = x112; | ||
| 1777 | out2[0] = x7; | ||
| 1778 | out2[1] = x8; | ||
| 1779 | out2[2] = x9; | ||
| 1780 | out2[3] = x10; | ||
| 1781 | out2[4] = x11; | ||
| 1782 | out3[0] = x114; | ||
| 1783 | out3[1] = x115; | ||
| 1784 | out3[2] = x116; | ||
| 1785 | out3[3] = x117; | ||
| 1786 | out3[4] = x118; | ||
| 1787 | out4[0] = x119; | ||
| 1788 | out4[1] = x120; | ||
| 1789 | out4[2] = x121; | ||
| 1790 | out4[3] = x122; | ||
| 1791 | out5[0] = x123; | ||
| 1792 | out5[1] = x124; | ||
| 1793 | out5[2] = x125; | ||
| 1794 | out5[3] = x126; | ||
| 1795 | } | ||
| 1796 | |||
| 1797 | /// The function divstepPrecomp returns the precomputed value for Bernstein-Yang-inversion (in montgomery form). | ||
| 1798 | /// Postconditions: | ||
| 1799 | /// eval (from_montgomery out1) = ⌊(m - 1) / 2⌋^(if (log2 m) + 1 < 46 then ⌊(49 * ((log2 m) + 1) + 80) / 17⌋ else ⌊(49 * ((log2 m) + 1) + 57) / 17⌋) | ||
| 1800 | /// 0 ≤ eval out1 < m | ||
| 1801 | /// | ||
| 1802 | /// Input Bounds: | ||
| 1803 | /// Output Bounds: | ||
| 1804 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 1805 | pub fn divstepPrecomp(out1: *[4]u64) void { | ||
| 1806 | @setRuntimeSafety(mode == .Debug); | ||
| 1807 | |||
| 1808 | out1[0] = 0x67ffffffb8000000; | ||
| 1809 | out1[1] = 0xc000000038000000; | ||
| 1810 | out1[2] = 0xd80000007fffffff; | ||
| 1811 | out1[3] = 0x2fffffffffffffff; | ||
| 1812 | } | ||
lib/std/crypto/pcurves/p256/p256_scalar_64.zig created+2016| ... | @@ -0,0 +1,2016 @@ | ||
| 1 | // Autogenerated: './src/ExtractionOCaml/word_by_word_montgomery' --lang Zig --internal-static --public-function-case camelCase --private-function-case camelCase --no-prefix-fiat --package-name p256-scalar '' 64 115792089210356248762697446949407573529996955224135760342422259061068512044369 | ||
| 2 | // curve description (via package name): p256-scalar | ||
| 3 | // machine_wordsize = 64 (from "64") | ||
| 4 | // requested operations: (all) | ||
| 5 | // m = 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551 (from "115792089210356248762697446949407573529996955224135760342422259061068512044369") | ||
| 6 | // | ||
| 7 | // NOTE: In addition to the bounds specified above each function, all | ||
| 8 | // functions synthesized for this Montgomery arithmetic require the | ||
| 9 | // input to be strictly less than the prime modulus (m), and also | ||
| 10 | // require the input to be in the unique saturated representation. | ||
| 11 | // All functions also ensure that these two properties are true of | ||
| 12 | // return values. | ||
| 13 | // | ||
| 14 | // Computed values: | ||
| 15 | // eval z = z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) | ||
| 16 | // bytes_eval z = z[0] + (z[1] << 8) + (z[2] << 16) + (z[3] << 24) + (z[4] << 32) + (z[5] << 40) + (z[6] << 48) + (z[7] << 56) + (z[8] << 64) + (z[9] << 72) + (z[10] << 80) + (z[11] << 88) + (z[12] << 96) + (z[13] << 104) + (z[14] << 112) + (z[15] << 120) + (z[16] << 128) + (z[17] << 136) + (z[18] << 144) + (z[19] << 152) + (z[20] << 160) + (z[21] << 168) + (z[22] << 176) + (z[23] << 184) + (z[24] << 192) + (z[25] << 200) + (z[26] << 208) + (z[27] << 216) + (z[28] << 224) + (z[29] << 232) + (z[30] << 240) + (z[31] << 248) | ||
| 17 | // twos_complement_eval z = let x1 := z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) in | ||
| 18 | // if x1 & (2^256-1) < 2^255 then x1 & (2^256-1) else (x1 & (2^256-1)) - 2^256 | ||
| 19 | |||
| 20 | const std = @import("std"); | ||
| 21 | const cast = std.meta.cast; | ||
| 22 | const mode = std.builtin.mode; // Checked arithmetic is disabled in non-debug modes to avoid side channels | ||
| 23 | |||
| 24 | pub const Limbs = [4]u64; | ||
| 25 | |||
| 26 | /// The function addcarryxU64 is an addition with carry. | ||
| 27 | /// Postconditions: | ||
| 28 | /// out1 = (arg1 + arg2 + arg3) mod 2^64 | ||
| 29 | /// out2 = ⌊(arg1 + arg2 + arg3) / 2^64⌋ | ||
| 30 | /// | ||
| 31 | /// Input Bounds: | ||
| 32 | /// arg1: [0x0 ~> 0x1] | ||
| 33 | /// arg2: [0x0 ~> 0xffffffffffffffff] | ||
| 34 | /// arg3: [0x0 ~> 0xffffffffffffffff] | ||
| 35 | /// Output Bounds: | ||
| 36 | /// out1: [0x0 ~> 0xffffffffffffffff] | ||
| 37 | /// out2: [0x0 ~> 0x1] | ||
| 38 | fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) callconv(.Inline) void { | ||
| 39 | @setRuntimeSafety(mode == .Debug); | ||
| 40 | |||
| 41 | var t: u64 = undefined; | ||
| 42 | const carry1 = @addWithOverflow(u64, arg2, arg3, &t); | ||
| 43 | const carry2 = @addWithOverflow(u64, t, arg1, out1); | ||
| 44 | out2.* = @boolToInt(carry1) | @boolToInt(carry2); | ||
| 45 | } | ||
| 46 | |||
| 47 | /// The function subborrowxU64 is a subtraction with borrow. | ||
| 48 | /// Postconditions: | ||
| 49 | /// out1 = (-arg1 + arg2 + -arg3) mod 2^64 | ||
| 50 | /// out2 = -⌊(-arg1 + arg2 + -arg3) / 2^64⌋ | ||
| 51 | /// | ||
| 52 | /// Input Bounds: | ||
| 53 | /// arg1: [0x0 ~> 0x1] | ||
| 54 | /// arg2: [0x0 ~> 0xffffffffffffffff] | ||
| 55 | /// arg3: [0x0 ~> 0xffffffffffffffff] | ||
| 56 | /// Output Bounds: | ||
| 57 | /// out1: [0x0 ~> 0xffffffffffffffff] | ||
| 58 | /// out2: [0x0 ~> 0x1] | ||
| 59 | fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) callconv(.Inline) void { | ||
| 60 | @setRuntimeSafety(mode == .Debug); | ||
| 61 | |||
| 62 | var t: u64 = undefined; | ||
| 63 | const carry1 = @subWithOverflow(u64, arg2, arg3, &t); | ||
| 64 | const carry2 = @subWithOverflow(u64, t, arg1, out1); | ||
| 65 | out2.* = @boolToInt(carry1) | @boolToInt(carry2); | ||
| 66 | } | ||
| 67 | |||
| 68 | /// The function mulxU64 is a multiplication, returning the full double-width result. | ||
| 69 | /// Postconditions: | ||
| 70 | /// out1 = (arg1 * arg2) mod 2^64 | ||
| 71 | /// out2 = ⌊arg1 * arg2 / 2^64⌋ | ||
| 72 | /// | ||
| 73 | /// Input Bounds: | ||
| 74 | /// arg1: [0x0 ~> 0xffffffffffffffff] | ||
| 75 | /// arg2: [0x0 ~> 0xffffffffffffffff] | ||
| 76 | /// Output Bounds: | ||
| 77 | /// out1: [0x0 ~> 0xffffffffffffffff] | ||
| 78 | /// out2: [0x0 ~> 0xffffffffffffffff] | ||
| 79 | fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) callconv(.Inline) void { | ||
| 80 | @setRuntimeSafety(mode == .Debug); | ||
| 81 | |||
| 82 | const x = @as(u128, arg1) * @as(u128, arg2); | ||
| 83 | out1.* = @truncate(u64, x); | ||
| 84 | out2.* = @truncate(u64, x >> 64); | ||
| 85 | } | ||
| 86 | |||
| 87 | /// The function cmovznzU64 is a single-word conditional move. | ||
| 88 | /// Postconditions: | ||
| 89 | /// out1 = (if arg1 = 0 then arg2 else arg3) | ||
| 90 | /// | ||
| 91 | /// Input Bounds: | ||
| 92 | /// arg1: [0x0 ~> 0x1] | ||
| 93 | /// arg2: [0x0 ~> 0xffffffffffffffff] | ||
| 94 | /// arg3: [0x0 ~> 0xffffffffffffffff] | ||
| 95 | /// Output Bounds: | ||
| 96 | /// out1: [0x0 ~> 0xffffffffffffffff] | ||
| 97 | fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) callconv(.Inline) void { | ||
| 98 | @setRuntimeSafety(mode == .Debug); | ||
| 99 | |||
| 100 | const mask = 0 -% @as(u64, arg1); | ||
| 101 | out1.* = (mask & arg3) | ((~mask) & arg2); | ||
| 102 | } | ||
| 103 | |||
| 104 | /// The function mul multiplies two field elements in the Montgomery domain. | ||
| 105 | /// Preconditions: | ||
| 106 | /// 0 ≤ eval arg1 < m | ||
| 107 | /// 0 ≤ eval arg2 < m | ||
| 108 | /// Postconditions: | ||
| 109 | /// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) * eval (from_montgomery arg2)) mod m | ||
| 110 | /// 0 ≤ eval out1 < m | ||
| 111 | /// | ||
| 112 | /// Input Bounds: | ||
| 113 | /// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 114 | /// arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 115 | /// Output Bounds: | ||
| 116 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 117 | pub fn mul(out1: *[4]u64, arg1: [4]u64, arg2: [4]u64) void { | ||
| 118 | @setRuntimeSafety(mode == .Debug); | ||
| 119 | |||
| 120 | const x1 = (arg1[1]); | ||
| 121 | const x2 = (arg1[2]); | ||
| 122 | const x3 = (arg1[3]); | ||
| 123 | const x4 = (arg1[0]); | ||
| 124 | var x5: u64 = undefined; | ||
| 125 | var x6: u64 = undefined; | ||
| 126 | mulxU64(&x5, &x6, x4, (arg2[3])); | ||
| 127 | var x7: u64 = undefined; | ||
| 128 | var x8: u64 = undefined; | ||
| 129 | mulxU64(&x7, &x8, x4, (arg2[2])); | ||
| 130 | var x9: u64 = undefined; | ||
| 131 | var x10: u64 = undefined; | ||
| 132 | mulxU64(&x9, &x10, x4, (arg2[1])); | ||
| 133 | var x11: u64 = undefined; | ||
| 134 | var x12: u64 = undefined; | ||
| 135 | mulxU64(&x11, &x12, x4, (arg2[0])); | ||
| 136 | var x13: u64 = undefined; | ||
| 137 | var x14: u1 = undefined; | ||
| 138 | addcarryxU64(&x13, &x14, 0x0, x12, x9); | ||
| 139 | var x15: u64 = undefined; | ||
| 140 | var x16: u1 = undefined; | ||
| 141 | addcarryxU64(&x15, &x16, x14, x10, x7); | ||
| 142 | var x17: u64 = undefined; | ||
| 143 | var x18: u1 = undefined; | ||
| 144 | addcarryxU64(&x17, &x18, x16, x8, x5); | ||
| 145 | const x19 = (cast(u64, x18) + x6); | ||
| 146 | var x20: u64 = undefined; | ||
| 147 | var x21: u64 = undefined; | ||
| 148 | mulxU64(&x20, &x21, x11, 0xccd1c8aaee00bc4f); | ||
| 149 | var x22: u64 = undefined; | ||
| 150 | var x23: u64 = undefined; | ||
| 151 | mulxU64(&x22, &x23, x20, 0xffffffff00000000); | ||
| 152 | var x24: u64 = undefined; | ||
| 153 | var x25: u64 = undefined; | ||
| 154 | mulxU64(&x24, &x25, x20, 0xffffffffffffffff); | ||
| 155 | var x26: u64 = undefined; | ||
| 156 | var x27: u64 = undefined; | ||
| 157 | mulxU64(&x26, &x27, x20, 0xbce6faada7179e84); | ||
| 158 | var x28: u64 = undefined; | ||
| 159 | var x29: u64 = undefined; | ||
| 160 | mulxU64(&x28, &x29, x20, 0xf3b9cac2fc632551); | ||
| 161 | var x30: u64 = undefined; | ||
| 162 | var x31: u1 = undefined; | ||
| 163 | addcarryxU64(&x30, &x31, 0x0, x29, x26); | ||
| 164 | var x32: u64 = undefined; | ||
| 165 | var x33: u1 = undefined; | ||
| 166 | addcarryxU64(&x32, &x33, x31, x27, x24); | ||
| 167 | var x34: u64 = undefined; | ||
| 168 | var x35: u1 = undefined; | ||
| 169 | addcarryxU64(&x34, &x35, x33, x25, x22); | ||
| 170 | const x36 = (cast(u64, x35) + x23); | ||
| 171 | var x37: u64 = undefined; | ||
| 172 | var x38: u1 = undefined; | ||
| 173 | addcarryxU64(&x37, &x38, 0x0, x11, x28); | ||
| 174 | var x39: u64 = undefined; | ||
| 175 | var x40: u1 = undefined; | ||
| 176 | addcarryxU64(&x39, &x40, x38, x13, x30); | ||
| 177 | var x41: u64 = undefined; | ||
| 178 | var x42: u1 = undefined; | ||
| 179 | addcarryxU64(&x41, &x42, x40, x15, x32); | ||
| 180 | var x43: u64 = undefined; | ||
| 181 | var x44: u1 = undefined; | ||
| 182 | addcarryxU64(&x43, &x44, x42, x17, x34); | ||
| 183 | var x45: u64 = undefined; | ||
| 184 | var x46: u1 = undefined; | ||
| 185 | addcarryxU64(&x45, &x46, x44, x19, x36); | ||
| 186 | var x47: u64 = undefined; | ||
| 187 | var x48: u64 = undefined; | ||
| 188 | mulxU64(&x47, &x48, x1, (arg2[3])); | ||
| 189 | var x49: u64 = undefined; | ||
| 190 | var x50: u64 = undefined; | ||
| 191 | mulxU64(&x49, &x50, x1, (arg2[2])); | ||
| 192 | var x51: u64 = undefined; | ||
| 193 | var x52: u64 = undefined; | ||
| 194 | mulxU64(&x51, &x52, x1, (arg2[1])); | ||
| 195 | var x53: u64 = undefined; | ||
| 196 | var x54: u64 = undefined; | ||
| 197 | mulxU64(&x53, &x54, x1, (arg2[0])); | ||
| 198 | var x55: u64 = undefined; | ||
| 199 | var x56: u1 = undefined; | ||
| 200 | addcarryxU64(&x55, &x56, 0x0, x54, x51); | ||
| 201 | var x57: u64 = undefined; | ||
| 202 | var x58: u1 = undefined; | ||
| 203 | addcarryxU64(&x57, &x58, x56, x52, x49); | ||
| 204 | var x59: u64 = undefined; | ||
| 205 | var x60: u1 = undefined; | ||
| 206 | addcarryxU64(&x59, &x60, x58, x50, x47); | ||
| 207 | const x61 = (cast(u64, x60) + x48); | ||
| 208 | var x62: u64 = undefined; | ||
| 209 | var x63: u1 = undefined; | ||
| 210 | addcarryxU64(&x62, &x63, 0x0, x39, x53); | ||
| 211 | var x64: u64 = undefined; | ||
| 212 | var x65: u1 = undefined; | ||
| 213 | addcarryxU64(&x64, &x65, x63, x41, x55); | ||
| 214 | var x66: u64 = undefined; | ||
| 215 | var x67: u1 = undefined; | ||
| 216 | addcarryxU64(&x66, &x67, x65, x43, x57); | ||
| 217 | var x68: u64 = undefined; | ||
| 218 | var x69: u1 = undefined; | ||
| 219 | addcarryxU64(&x68, &x69, x67, x45, x59); | ||
| 220 | var x70: u64 = undefined; | ||
| 221 | var x71: u1 = undefined; | ||
| 222 | addcarryxU64(&x70, &x71, x69, cast(u64, x46), x61); | ||
| 223 | var x72: u64 = undefined; | ||
| 224 | var x73: u64 = undefined; | ||
| 225 | mulxU64(&x72, &x73, x62, 0xccd1c8aaee00bc4f); | ||
| 226 | var x74: u64 = undefined; | ||
| 227 | var x75: u64 = undefined; | ||
| 228 | mulxU64(&x74, &x75, x72, 0xffffffff00000000); | ||
| 229 | var x76: u64 = undefined; | ||
| 230 | var x77: u64 = undefined; | ||
| 231 | mulxU64(&x76, &x77, x72, 0xffffffffffffffff); | ||
| 232 | var x78: u64 = undefined; | ||
| 233 | var x79: u64 = undefined; | ||
| 234 | mulxU64(&x78, &x79, x72, 0xbce6faada7179e84); | ||
| 235 | var x80: u64 = undefined; | ||
| 236 | var x81: u64 = undefined; | ||
| 237 | mulxU64(&x80, &x81, x72, 0xf3b9cac2fc632551); | ||
| 238 | var x82: u64 = undefined; | ||
| 239 | var x83: u1 = undefined; | ||
| 240 | addcarryxU64(&x82, &x83, 0x0, x81, x78); | ||
| 241 | var x84: u64 = undefined; | ||
| 242 | var x85: u1 = undefined; | ||
| 243 | addcarryxU64(&x84, &x85, x83, x79, x76); | ||
| 244 | var x86: u64 = undefined; | ||
| 245 | var x87: u1 = undefined; | ||
| 246 | addcarryxU64(&x86, &x87, x85, x77, x74); | ||
| 247 | const x88 = (cast(u64, x87) + x75); | ||
| 248 | var x89: u64 = undefined; | ||
| 249 | var x90: u1 = undefined; | ||
| 250 | addcarryxU64(&x89, &x90, 0x0, x62, x80); | ||
| 251 | var x91: u64 = undefined; | ||
| 252 | var x92: u1 = undefined; | ||
| 253 | addcarryxU64(&x91, &x92, x90, x64, x82); | ||
| 254 | var x93: u64 = undefined; | ||
| 255 | var x94: u1 = undefined; | ||
| 256 | addcarryxU64(&x93, &x94, x92, x66, x84); | ||
| 257 | var x95: u64 = undefined; | ||
| 258 | var x96: u1 = undefined; | ||
| 259 | addcarryxU64(&x95, &x96, x94, x68, x86); | ||
| 260 | var x97: u64 = undefined; | ||
| 261 | var x98: u1 = undefined; | ||
| 262 | addcarryxU64(&x97, &x98, x96, x70, x88); | ||
| 263 | const x99 = (cast(u64, x98) + cast(u64, x71)); | ||
| 264 | var x100: u64 = undefined; | ||
| 265 | var x101: u64 = undefined; | ||
| 266 | mulxU64(&x100, &x101, x2, (arg2[3])); | ||
| 267 | var x102: u64 = undefined; | ||
| 268 | var x103: u64 = undefined; | ||
| 269 | mulxU64(&x102, &x103, x2, (arg2[2])); | ||
| 270 | var x104: u64 = undefined; | ||
| 271 | var x105: u64 = undefined; | ||
| 272 | mulxU64(&x104, &x105, x2, (arg2[1])); | ||
| 273 | var x106: u64 = undefined; | ||
| 274 | var x107: u64 = undefined; | ||
| 275 | mulxU64(&x106, &x107, x2, (arg2[0])); | ||
| 276 | var x108: u64 = undefined; | ||
| 277 | var x109: u1 = undefined; | ||
| 278 | addcarryxU64(&x108, &x109, 0x0, x107, x104); | ||
| 279 | var x110: u64 = undefined; | ||
| 280 | var x111: u1 = undefined; | ||
| 281 | addcarryxU64(&x110, &x111, x109, x105, x102); | ||
| 282 | var x112: u64 = undefined; | ||
| 283 | var x113: u1 = undefined; | ||
| 284 | addcarryxU64(&x112, &x113, x111, x103, x100); | ||
| 285 | const x114 = (cast(u64, x113) + x101); | ||
| 286 | var x115: u64 = undefined; | ||
| 287 | var x116: u1 = undefined; | ||
| 288 | addcarryxU64(&x115, &x116, 0x0, x91, x106); | ||
| 289 | var x117: u64 = undefined; | ||
| 290 | var x118: u1 = undefined; | ||
| 291 | addcarryxU64(&x117, &x118, x116, x93, x108); | ||
| 292 | var x119: u64 = undefined; | ||
| 293 | var x120: u1 = undefined; | ||
| 294 | addcarryxU64(&x119, &x120, x118, x95, x110); | ||
| 295 | var x121: u64 = undefined; | ||
| 296 | var x122: u1 = undefined; | ||
| 297 | addcarryxU64(&x121, &x122, x120, x97, x112); | ||
| 298 | var x123: u64 = undefined; | ||
| 299 | var x124: u1 = undefined; | ||
| 300 | addcarryxU64(&x123, &x124, x122, x99, x114); | ||
| 301 | var x125: u64 = undefined; | ||
| 302 | var x126: u64 = undefined; | ||
| 303 | mulxU64(&x125, &x126, x115, 0xccd1c8aaee00bc4f); | ||
| 304 | var x127: u64 = undefined; | ||
| 305 | var x128: u64 = undefined; | ||
| 306 | mulxU64(&x127, &x128, x125, 0xffffffff00000000); | ||
| 307 | var x129: u64 = undefined; | ||
| 308 | var x130: u64 = undefined; | ||
| 309 | mulxU64(&x129, &x130, x125, 0xffffffffffffffff); | ||
| 310 | var x131: u64 = undefined; | ||
| 311 | var x132: u64 = undefined; | ||
| 312 | mulxU64(&x131, &x132, x125, 0xbce6faada7179e84); | ||
| 313 | var x133: u64 = undefined; | ||
| 314 | var x134: u64 = undefined; | ||
| 315 | mulxU64(&x133, &x134, x125, 0xf3b9cac2fc632551); | ||
| 316 | var x135: u64 = undefined; | ||
| 317 | var x136: u1 = undefined; | ||
| 318 | addcarryxU64(&x135, &x136, 0x0, x134, x131); | ||
| 319 | var x137: u64 = undefined; | ||
| 320 | var x138: u1 = undefined; | ||
| 321 | addcarryxU64(&x137, &x138, x136, x132, x129); | ||
| 322 | var x139: u64 = undefined; | ||
| 323 | var x140: u1 = undefined; | ||
| 324 | addcarryxU64(&x139, &x140, x138, x130, x127); | ||
| 325 | const x141 = (cast(u64, x140) + x128); | ||
| 326 | var x142: u64 = undefined; | ||
| 327 | var x143: u1 = undefined; | ||
| 328 | addcarryxU64(&x142, &x143, 0x0, x115, x133); | ||
| 329 | var x144: u64 = undefined; | ||
| 330 | var x145: u1 = undefined; | ||
| 331 | addcarryxU64(&x144, &x145, x143, x117, x135); | ||
| 332 | var x146: u64 = undefined; | ||
| 333 | var x147: u1 = undefined; | ||
| 334 | addcarryxU64(&x146, &x147, x145, x119, x137); | ||
| 335 | var x148: u64 = undefined; | ||
| 336 | var x149: u1 = undefined; | ||
| 337 | addcarryxU64(&x148, &x149, x147, x121, x139); | ||
| 338 | var x150: u64 = undefined; | ||
| 339 | var x151: u1 = undefined; | ||
| 340 | addcarryxU64(&x150, &x151, x149, x123, x141); | ||
| 341 | const x152 = (cast(u64, x151) + cast(u64, x124)); | ||
| 342 | var x153: u64 = undefined; | ||
| 343 | var x154: u64 = undefined; | ||
| 344 | mulxU64(&x153, &x154, x3, (arg2[3])); | ||
| 345 | var x155: u64 = undefined; | ||
| 346 | var x156: u64 = undefined; | ||
| 347 | mulxU64(&x155, &x156, x3, (arg2[2])); | ||
| 348 | var x157: u64 = undefined; | ||
| 349 | var x158: u64 = undefined; | ||
| 350 | mulxU64(&x157, &x158, x3, (arg2[1])); | ||
| 351 | var x159: u64 = undefined; | ||
| 352 | var x160: u64 = undefined; | ||
| 353 | mulxU64(&x159, &x160, x3, (arg2[0])); | ||
| 354 | var x161: u64 = undefined; | ||
| 355 | var x162: u1 = undefined; | ||
| 356 | addcarryxU64(&x161, &x162, 0x0, x160, x157); | ||
| 357 | var x163: u64 = undefined; | ||
| 358 | var x164: u1 = undefined; | ||
| 359 | addcarryxU64(&x163, &x164, x162, x158, x155); | ||
| 360 | var x165: u64 = undefined; | ||
| 361 | var x166: u1 = undefined; | ||
| 362 | addcarryxU64(&x165, &x166, x164, x156, x153); | ||
| 363 | const x167 = (cast(u64, x166) + x154); | ||
| 364 | var x168: u64 = undefined; | ||
| 365 | var x169: u1 = undefined; | ||
| 366 | addcarryxU64(&x168, &x169, 0x0, x144, x159); | ||
| 367 | var x170: u64 = undefined; | ||
| 368 | var x171: u1 = undefined; | ||
| 369 | addcarryxU64(&x170, &x171, x169, x146, x161); | ||
| 370 | var x172: u64 = undefined; | ||
| 371 | var x173: u1 = undefined; | ||
| 372 | addcarryxU64(&x172, &x173, x171, x148, x163); | ||
| 373 | var x174: u64 = undefined; | ||
| 374 | var x175: u1 = undefined; | ||
| 375 | addcarryxU64(&x174, &x175, x173, x150, x165); | ||
| 376 | var x176: u64 = undefined; | ||
| 377 | var x177: u1 = undefined; | ||
| 378 | addcarryxU64(&x176, &x177, x175, x152, x167); | ||
| 379 | var x178: u64 = undefined; | ||
| 380 | var x179: u64 = undefined; | ||
| 381 | mulxU64(&x178, &x179, x168, 0xccd1c8aaee00bc4f); | ||
| 382 | var x180: u64 = undefined; | ||
| 383 | var x181: u64 = undefined; | ||
| 384 | mulxU64(&x180, &x181, x178, 0xffffffff00000000); | ||
| 385 | var x182: u64 = undefined; | ||
| 386 | var x183: u64 = undefined; | ||
| 387 | mulxU64(&x182, &x183, x178, 0xffffffffffffffff); | ||
| 388 | var x184: u64 = undefined; | ||
| 389 | var x185: u64 = undefined; | ||
| 390 | mulxU64(&x184, &x185, x178, 0xbce6faada7179e84); | ||
| 391 | var x186: u64 = undefined; | ||
| 392 | var x187: u64 = undefined; | ||
| 393 | mulxU64(&x186, &x187, x178, 0xf3b9cac2fc632551); | ||
| 394 | var x188: u64 = undefined; | ||
| 395 | var x189: u1 = undefined; | ||
| 396 | addcarryxU64(&x188, &x189, 0x0, x187, x184); | ||
| 397 | var x190: u64 = undefined; | ||
| 398 | var x191: u1 = undefined; | ||
| 399 | addcarryxU64(&x190, &x191, x189, x185, x182); | ||
| 400 | var x192: u64 = undefined; | ||
| 401 | var x193: u1 = undefined; | ||
| 402 | addcarryxU64(&x192, &x193, x191, x183, x180); | ||
| 403 | const x194 = (cast(u64, x193) + x181); | ||
| 404 | var x195: u64 = undefined; | ||
| 405 | var x196: u1 = undefined; | ||
| 406 | addcarryxU64(&x195, &x196, 0x0, x168, x186); | ||
| 407 | var x197: u64 = undefined; | ||
| 408 | var x198: u1 = undefined; | ||
| 409 | addcarryxU64(&x197, &x198, x196, x170, x188); | ||
| 410 | var x199: u64 = undefined; | ||
| 411 | var x200: u1 = undefined; | ||
| 412 | addcarryxU64(&x199, &x200, x198, x172, x190); | ||
| 413 | var x201: u64 = undefined; | ||
| 414 | var x202: u1 = undefined; | ||
| 415 | addcarryxU64(&x201, &x202, x200, x174, x192); | ||
| 416 | var x203: u64 = undefined; | ||
| 417 | var x204: u1 = undefined; | ||
| 418 | addcarryxU64(&x203, &x204, x202, x176, x194); | ||
| 419 | const x205 = (cast(u64, x204) + cast(u64, x177)); | ||
| 420 | var x206: u64 = undefined; | ||
| 421 | var x207: u1 = undefined; | ||
| 422 | subborrowxU64(&x206, &x207, 0x0, x197, 0xf3b9cac2fc632551); | ||
| 423 | var x208: u64 = undefined; | ||
| 424 | var x209: u1 = undefined; | ||
| 425 | subborrowxU64(&x208, &x209, x207, x199, 0xbce6faada7179e84); | ||
| 426 | var x210: u64 = undefined; | ||
| 427 | var x211: u1 = undefined; | ||
| 428 | subborrowxU64(&x210, &x211, x209, x201, 0xffffffffffffffff); | ||
| 429 | var x212: u64 = undefined; | ||
| 430 | var x213: u1 = undefined; | ||
| 431 | subborrowxU64(&x212, &x213, x211, x203, 0xffffffff00000000); | ||
| 432 | var x214: u64 = undefined; | ||
| 433 | var x215: u1 = undefined; | ||
| 434 | subborrowxU64(&x214, &x215, x213, x205, cast(u64, 0x0)); | ||
| 435 | var x216: u64 = undefined; | ||
| 436 | cmovznzU64(&x216, x215, x206, x197); | ||
| 437 | var x217: u64 = undefined; | ||
| 438 | cmovznzU64(&x217, x215, x208, x199); | ||
| 439 | var x218: u64 = undefined; | ||
| 440 | cmovznzU64(&x218, x215, x210, x201); | ||
| 441 | var x219: u64 = undefined; | ||
| 442 | cmovznzU64(&x219, x215, x212, x203); | ||
| 443 | out1[0] = x216; | ||
| 444 | out1[1] = x217; | ||
| 445 | out1[2] = x218; | ||
| 446 | out1[3] = x219; | ||
| 447 | } | ||
| 448 | |||
| 449 | /// The function square squares a field element in the Montgomery domain. | ||
| 450 | /// Preconditions: | ||
| 451 | /// 0 ≤ eval arg1 < m | ||
| 452 | /// Postconditions: | ||
| 453 | /// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) * eval (from_montgomery arg1)) mod m | ||
| 454 | /// 0 ≤ eval out1 < m | ||
| 455 | /// | ||
| 456 | /// Input Bounds: | ||
| 457 | /// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 458 | /// Output Bounds: | ||
| 459 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 460 | pub fn square(out1: *[4]u64, arg1: [4]u64) void { | ||
| 461 | @setRuntimeSafety(mode == .Debug); | ||
| 462 | |||
| 463 | const x1 = (arg1[1]); | ||
| 464 | const x2 = (arg1[2]); | ||
| 465 | const x3 = (arg1[3]); | ||
| 466 | const x4 = (arg1[0]); | ||
| 467 | var x5: u64 = undefined; | ||
| 468 | var x6: u64 = undefined; | ||
| 469 | mulxU64(&x5, &x6, x4, (arg1[3])); | ||
| 470 | var x7: u64 = undefined; | ||
| 471 | var x8: u64 = undefined; | ||
| 472 | mulxU64(&x7, &x8, x4, (arg1[2])); | ||
| 473 | var x9: u64 = undefined; | ||
| 474 | var x10: u64 = undefined; | ||
| 475 | mulxU64(&x9, &x10, x4, (arg1[1])); | ||
| 476 | var x11: u64 = undefined; | ||
| 477 | var x12: u64 = undefined; | ||
| 478 | mulxU64(&x11, &x12, x4, (arg1[0])); | ||
| 479 | var x13: u64 = undefined; | ||
| 480 | var x14: u1 = undefined; | ||
| 481 | addcarryxU64(&x13, &x14, 0x0, x12, x9); | ||
| 482 | var x15: u64 = undefined; | ||
| 483 | var x16: u1 = undefined; | ||
| 484 | addcarryxU64(&x15, &x16, x14, x10, x7); | ||
| 485 | var x17: u64 = undefined; | ||
| 486 | var x18: u1 = undefined; | ||
| 487 | addcarryxU64(&x17, &x18, x16, x8, x5); | ||
| 488 | const x19 = (cast(u64, x18) + x6); | ||
| 489 | var x20: u64 = undefined; | ||
| 490 | var x21: u64 = undefined; | ||
| 491 | mulxU64(&x20, &x21, x11, 0xccd1c8aaee00bc4f); | ||
| 492 | var x22: u64 = undefined; | ||
| 493 | var x23: u64 = undefined; | ||
| 494 | mulxU64(&x22, &x23, x20, 0xffffffff00000000); | ||
| 495 | var x24: u64 = undefined; | ||
| 496 | var x25: u64 = undefined; | ||
| 497 | mulxU64(&x24, &x25, x20, 0xffffffffffffffff); | ||
| 498 | var x26: u64 = undefined; | ||
| 499 | var x27: u64 = undefined; | ||
| 500 | mulxU64(&x26, &x27, x20, 0xbce6faada7179e84); | ||
| 501 | var x28: u64 = undefined; | ||
| 502 | var x29: u64 = undefined; | ||
| 503 | mulxU64(&x28, &x29, x20, 0xf3b9cac2fc632551); | ||
| 504 | var x30: u64 = undefined; | ||
| 505 | var x31: u1 = undefined; | ||
| 506 | addcarryxU64(&x30, &x31, 0x0, x29, x26); | ||
| 507 | var x32: u64 = undefined; | ||
| 508 | var x33: u1 = undefined; | ||
| 509 | addcarryxU64(&x32, &x33, x31, x27, x24); | ||
| 510 | var x34: u64 = undefined; | ||
| 511 | var x35: u1 = undefined; | ||
| 512 | addcarryxU64(&x34, &x35, x33, x25, x22); | ||
| 513 | const x36 = (cast(u64, x35) + x23); | ||
| 514 | var x37: u64 = undefined; | ||
| 515 | var x38: u1 = undefined; | ||
| 516 | addcarryxU64(&x37, &x38, 0x0, x11, x28); | ||
| 517 | var x39: u64 = undefined; | ||
| 518 | var x40: u1 = undefined; | ||
| 519 | addcarryxU64(&x39, &x40, x38, x13, x30); | ||
| 520 | var x41: u64 = undefined; | ||
| 521 | var x42: u1 = undefined; | ||
| 522 | addcarryxU64(&x41, &x42, x40, x15, x32); | ||
| 523 | var x43: u64 = undefined; | ||
| 524 | var x44: u1 = undefined; | ||
| 525 | addcarryxU64(&x43, &x44, x42, x17, x34); | ||
| 526 | var x45: u64 = undefined; | ||
| 527 | var x46: u1 = undefined; | ||
| 528 | addcarryxU64(&x45, &x46, x44, x19, x36); | ||
| 529 | var x47: u64 = undefined; | ||
| 530 | var x48: u64 = undefined; | ||
| 531 | mulxU64(&x47, &x48, x1, (arg1[3])); | ||
| 532 | var x49: u64 = undefined; | ||
| 533 | var x50: u64 = undefined; | ||
| 534 | mulxU64(&x49, &x50, x1, (arg1[2])); | ||
| 535 | var x51: u64 = undefined; | ||
| 536 | var x52: u64 = undefined; | ||
| 537 | mulxU64(&x51, &x52, x1, (arg1[1])); | ||
| 538 | var x53: u64 = undefined; | ||
| 539 | var x54: u64 = undefined; | ||
| 540 | mulxU64(&x53, &x54, x1, (arg1[0])); | ||
| 541 | var x55: u64 = undefined; | ||
| 542 | var x56: u1 = undefined; | ||
| 543 | addcarryxU64(&x55, &x56, 0x0, x54, x51); | ||
| 544 | var x57: u64 = undefined; | ||
| 545 | var x58: u1 = undefined; | ||
| 546 | addcarryxU64(&x57, &x58, x56, x52, x49); | ||
| 547 | var x59: u64 = undefined; | ||
| 548 | var x60: u1 = undefined; | ||
| 549 | addcarryxU64(&x59, &x60, x58, x50, x47); | ||
| 550 | const x61 = (cast(u64, x60) + x48); | ||
| 551 | var x62: u64 = undefined; | ||
| 552 | var x63: u1 = undefined; | ||
| 553 | addcarryxU64(&x62, &x63, 0x0, x39, x53); | ||
| 554 | var x64: u64 = undefined; | ||
| 555 | var x65: u1 = undefined; | ||
| 556 | addcarryxU64(&x64, &x65, x63, x41, x55); | ||
| 557 | var x66: u64 = undefined; | ||
| 558 | var x67: u1 = undefined; | ||
| 559 | addcarryxU64(&x66, &x67, x65, x43, x57); | ||
| 560 | var x68: u64 = undefined; | ||
| 561 | var x69: u1 = undefined; | ||
| 562 | addcarryxU64(&x68, &x69, x67, x45, x59); | ||
| 563 | var x70: u64 = undefined; | ||
| 564 | var x71: u1 = undefined; | ||
| 565 | addcarryxU64(&x70, &x71, x69, cast(u64, x46), x61); | ||
| 566 | var x72: u64 = undefined; | ||
| 567 | var x73: u64 = undefined; | ||
| 568 | mulxU64(&x72, &x73, x62, 0xccd1c8aaee00bc4f); | ||
| 569 | var x74: u64 = undefined; | ||
| 570 | var x75: u64 = undefined; | ||
| 571 | mulxU64(&x74, &x75, x72, 0xffffffff00000000); | ||
| 572 | var x76: u64 = undefined; | ||
| 573 | var x77: u64 = undefined; | ||
| 574 | mulxU64(&x76, &x77, x72, 0xffffffffffffffff); | ||
| 575 | var x78: u64 = undefined; | ||
| 576 | var x79: u64 = undefined; | ||
| 577 | mulxU64(&x78, &x79, x72, 0xbce6faada7179e84); | ||
| 578 | var x80: u64 = undefined; | ||
| 579 | var x81: u64 = undefined; | ||
| 580 | mulxU64(&x80, &x81, x72, 0xf3b9cac2fc632551); | ||
| 581 | var x82: u64 = undefined; | ||
| 582 | var x83: u1 = undefined; | ||
| 583 | addcarryxU64(&x82, &x83, 0x0, x81, x78); | ||
| 584 | var x84: u64 = undefined; | ||
| 585 | var x85: u1 = undefined; | ||
| 586 | addcarryxU64(&x84, &x85, x83, x79, x76); | ||
| 587 | var x86: u64 = undefined; | ||
| 588 | var x87: u1 = undefined; | ||
| 589 | addcarryxU64(&x86, &x87, x85, x77, x74); | ||
| 590 | const x88 = (cast(u64, x87) + x75); | ||
| 591 | var x89: u64 = undefined; | ||
| 592 | var x90: u1 = undefined; | ||
| 593 | addcarryxU64(&x89, &x90, 0x0, x62, x80); | ||
| 594 | var x91: u64 = undefined; | ||
| 595 | var x92: u1 = undefined; | ||
| 596 | addcarryxU64(&x91, &x92, x90, x64, x82); | ||
| 597 | var x93: u64 = undefined; | ||
| 598 | var x94: u1 = undefined; | ||
| 599 | addcarryxU64(&x93, &x94, x92, x66, x84); | ||
| 600 | var x95: u64 = undefined; | ||
| 601 | var x96: u1 = undefined; | ||
| 602 | addcarryxU64(&x95, &x96, x94, x68, x86); | ||
| 603 | var x97: u64 = undefined; | ||
| 604 | var x98: u1 = undefined; | ||
| 605 | addcarryxU64(&x97, &x98, x96, x70, x88); | ||
| 606 | const x99 = (cast(u64, x98) + cast(u64, x71)); | ||
| 607 | var x100: u64 = undefined; | ||
| 608 | var x101: u64 = undefined; | ||
| 609 | mulxU64(&x100, &x101, x2, (arg1[3])); | ||
| 610 | var x102: u64 = undefined; | ||
| 611 | var x103: u64 = undefined; | ||
| 612 | mulxU64(&x102, &x103, x2, (arg1[2])); | ||
| 613 | var x104: u64 = undefined; | ||
| 614 | var x105: u64 = undefined; | ||
| 615 | mulxU64(&x104, &x105, x2, (arg1[1])); | ||
| 616 | var x106: u64 = undefined; | ||
| 617 | var x107: u64 = undefined; | ||
| 618 | mulxU64(&x106, &x107, x2, (arg1[0])); | ||
| 619 | var x108: u64 = undefined; | ||
| 620 | var x109: u1 = undefined; | ||
| 621 | addcarryxU64(&x108, &x109, 0x0, x107, x104); | ||
| 622 | var x110: u64 = undefined; | ||
| 623 | var x111: u1 = undefined; | ||
| 624 | addcarryxU64(&x110, &x111, x109, x105, x102); | ||
| 625 | var x112: u64 = undefined; | ||
| 626 | var x113: u1 = undefined; | ||
| 627 | addcarryxU64(&x112, &x113, x111, x103, x100); | ||
| 628 | const x114 = (cast(u64, x113) + x101); | ||
| 629 | var x115: u64 = undefined; | ||
| 630 | var x116: u1 = undefined; | ||
| 631 | addcarryxU64(&x115, &x116, 0x0, x91, x106); | ||
| 632 | var x117: u64 = undefined; | ||
| 633 | var x118: u1 = undefined; | ||
| 634 | addcarryxU64(&x117, &x118, x116, x93, x108); | ||
| 635 | var x119: u64 = undefined; | ||
| 636 | var x120: u1 = undefined; | ||
| 637 | addcarryxU64(&x119, &x120, x118, x95, x110); | ||
| 638 | var x121: u64 = undefined; | ||
| 639 | var x122: u1 = undefined; | ||
| 640 | addcarryxU64(&x121, &x122, x120, x97, x112); | ||
| 641 | var x123: u64 = undefined; | ||
| 642 | var x124: u1 = undefined; | ||
| 643 | addcarryxU64(&x123, &x124, x122, x99, x114); | ||
| 644 | var x125: u64 = undefined; | ||
| 645 | var x126: u64 = undefined; | ||
| 646 | mulxU64(&x125, &x126, x115, 0xccd1c8aaee00bc4f); | ||
| 647 | var x127: u64 = undefined; | ||
| 648 | var x128: u64 = undefined; | ||
| 649 | mulxU64(&x127, &x128, x125, 0xffffffff00000000); | ||
| 650 | var x129: u64 = undefined; | ||
| 651 | var x130: u64 = undefined; | ||
| 652 | mulxU64(&x129, &x130, x125, 0xffffffffffffffff); | ||
| 653 | var x131: u64 = undefined; | ||
| 654 | var x132: u64 = undefined; | ||
| 655 | mulxU64(&x131, &x132, x125, 0xbce6faada7179e84); | ||
| 656 | var x133: u64 = undefined; | ||
| 657 | var x134: u64 = undefined; | ||
| 658 | mulxU64(&x133, &x134, x125, 0xf3b9cac2fc632551); | ||
| 659 | var x135: u64 = undefined; | ||
| 660 | var x136: u1 = undefined; | ||
| 661 | addcarryxU64(&x135, &x136, 0x0, x134, x131); | ||
| 662 | var x137: u64 = undefined; | ||
| 663 | var x138: u1 = undefined; | ||
| 664 | addcarryxU64(&x137, &x138, x136, x132, x129); | ||
| 665 | var x139: u64 = undefined; | ||
| 666 | var x140: u1 = undefined; | ||
| 667 | addcarryxU64(&x139, &x140, x138, x130, x127); | ||
| 668 | const x141 = (cast(u64, x140) + x128); | ||
| 669 | var x142: u64 = undefined; | ||
| 670 | var x143: u1 = undefined; | ||
| 671 | addcarryxU64(&x142, &x143, 0x0, x115, x133); | ||
| 672 | var x144: u64 = undefined; | ||
| 673 | var x145: u1 = undefined; | ||
| 674 | addcarryxU64(&x144, &x145, x143, x117, x135); | ||
| 675 | var x146: u64 = undefined; | ||
| 676 | var x147: u1 = undefined; | ||
| 677 | addcarryxU64(&x146, &x147, x145, x119, x137); | ||
| 678 | var x148: u64 = undefined; | ||
| 679 | var x149: u1 = undefined; | ||
| 680 | addcarryxU64(&x148, &x149, x147, x121, x139); | ||
| 681 | var x150: u64 = undefined; | ||
| 682 | var x151: u1 = undefined; | ||
| 683 | addcarryxU64(&x150, &x151, x149, x123, x141); | ||
| 684 | const x152 = (cast(u64, x151) + cast(u64, x124)); | ||
| 685 | var x153: u64 = undefined; | ||
| 686 | var x154: u64 = undefined; | ||
| 687 | mulxU64(&x153, &x154, x3, (arg1[3])); | ||
| 688 | var x155: u64 = undefined; | ||
| 689 | var x156: u64 = undefined; | ||
| 690 | mulxU64(&x155, &x156, x3, (arg1[2])); | ||
| 691 | var x157: u64 = undefined; | ||
| 692 | var x158: u64 = undefined; | ||
| 693 | mulxU64(&x157, &x158, x3, (arg1[1])); | ||
| 694 | var x159: u64 = undefined; | ||
| 695 | var x160: u64 = undefined; | ||
| 696 | mulxU64(&x159, &x160, x3, (arg1[0])); | ||
| 697 | var x161: u64 = undefined; | ||
| 698 | var x162: u1 = undefined; | ||
| 699 | addcarryxU64(&x161, &x162, 0x0, x160, x157); | ||
| 700 | var x163: u64 = undefined; | ||
| 701 | var x164: u1 = undefined; | ||
| 702 | addcarryxU64(&x163, &x164, x162, x158, x155); | ||
| 703 | var x165: u64 = undefined; | ||
| 704 | var x166: u1 = undefined; | ||
| 705 | addcarryxU64(&x165, &x166, x164, x156, x153); | ||
| 706 | const x167 = (cast(u64, x166) + x154); | ||
| 707 | var x168: u64 = undefined; | ||
| 708 | var x169: u1 = undefined; | ||
| 709 | addcarryxU64(&x168, &x169, 0x0, x144, x159); | ||
| 710 | var x170: u64 = undefined; | ||
| 711 | var x171: u1 = undefined; | ||
| 712 | addcarryxU64(&x170, &x171, x169, x146, x161); | ||
| 713 | var x172: u64 = undefined; | ||
| 714 | var x173: u1 = undefined; | ||
| 715 | addcarryxU64(&x172, &x173, x171, x148, x163); | ||
| 716 | var x174: u64 = undefined; | ||
| 717 | var x175: u1 = undefined; | ||
| 718 | addcarryxU64(&x174, &x175, x173, x150, x165); | ||
| 719 | var x176: u64 = undefined; | ||
| 720 | var x177: u1 = undefined; | ||
| 721 | addcarryxU64(&x176, &x177, x175, x152, x167); | ||
| 722 | var x178: u64 = undefined; | ||
| 723 | var x179: u64 = undefined; | ||
| 724 | mulxU64(&x178, &x179, x168, 0xccd1c8aaee00bc4f); | ||
| 725 | var x180: u64 = undefined; | ||
| 726 | var x181: u64 = undefined; | ||
| 727 | mulxU64(&x180, &x181, x178, 0xffffffff00000000); | ||
| 728 | var x182: u64 = undefined; | ||
| 729 | var x183: u64 = undefined; | ||
| 730 | mulxU64(&x182, &x183, x178, 0xffffffffffffffff); | ||
| 731 | var x184: u64 = undefined; | ||
| 732 | var x185: u64 = undefined; | ||
| 733 | mulxU64(&x184, &x185, x178, 0xbce6faada7179e84); | ||
| 734 | var x186: u64 = undefined; | ||
| 735 | var x187: u64 = undefined; | ||
| 736 | mulxU64(&x186, &x187, x178, 0xf3b9cac2fc632551); | ||
| 737 | var x188: u64 = undefined; | ||
| 738 | var x189: u1 = undefined; | ||
| 739 | addcarryxU64(&x188, &x189, 0x0, x187, x184); | ||
| 740 | var x190: u64 = undefined; | ||
| 741 | var x191: u1 = undefined; | ||
| 742 | addcarryxU64(&x190, &x191, x189, x185, x182); | ||
| 743 | var x192: u64 = undefined; | ||
| 744 | var x193: u1 = undefined; | ||
| 745 | addcarryxU64(&x192, &x193, x191, x183, x180); | ||
| 746 | const x194 = (cast(u64, x193) + x181); | ||
| 747 | var x195: u64 = undefined; | ||
| 748 | var x196: u1 = undefined; | ||
| 749 | addcarryxU64(&x195, &x196, 0x0, x168, x186); | ||
| 750 | var x197: u64 = undefined; | ||
| 751 | var x198: u1 = undefined; | ||
| 752 | addcarryxU64(&x197, &x198, x196, x170, x188); | ||
| 753 | var x199: u64 = undefined; | ||
| 754 | var x200: u1 = undefined; | ||
| 755 | addcarryxU64(&x199, &x200, x198, x172, x190); | ||
| 756 | var x201: u64 = undefined; | ||
| 757 | var x202: u1 = undefined; | ||
| 758 | addcarryxU64(&x201, &x202, x200, x174, x192); | ||
| 759 | var x203: u64 = undefined; | ||
| 760 | var x204: u1 = undefined; | ||
| 761 | addcarryxU64(&x203, &x204, x202, x176, x194); | ||
| 762 | const x205 = (cast(u64, x204) + cast(u64, x177)); | ||
| 763 | var x206: u64 = undefined; | ||
| 764 | var x207: u1 = undefined; | ||
| 765 | subborrowxU64(&x206, &x207, 0x0, x197, 0xf3b9cac2fc632551); | ||
| 766 | var x208: u64 = undefined; | ||
| 767 | var x209: u1 = undefined; | ||
| 768 | subborrowxU64(&x208, &x209, x207, x199, 0xbce6faada7179e84); | ||
| 769 | var x210: u64 = undefined; | ||
| 770 | var x211: u1 = undefined; | ||
| 771 | subborrowxU64(&x210, &x211, x209, x201, 0xffffffffffffffff); | ||
| 772 | var x212: u64 = undefined; | ||
| 773 | var x213: u1 = undefined; | ||
| 774 | subborrowxU64(&x212, &x213, x211, x203, 0xffffffff00000000); | ||
| 775 | var x214: u64 = undefined; | ||
| 776 | var x215: u1 = undefined; | ||
| 777 | subborrowxU64(&x214, &x215, x213, x205, cast(u64, 0x0)); | ||
| 778 | var x216: u64 = undefined; | ||
| 779 | cmovznzU64(&x216, x215, x206, x197); | ||
| 780 | var x217: u64 = undefined; | ||
| 781 | cmovznzU64(&x217, x215, x208, x199); | ||
| 782 | var x218: u64 = undefined; | ||
| 783 | cmovznzU64(&x218, x215, x210, x201); | ||
| 784 | var x219: u64 = undefined; | ||
| 785 | cmovznzU64(&x219, x215, x212, x203); | ||
| 786 | out1[0] = x216; | ||
| 787 | out1[1] = x217; | ||
| 788 | out1[2] = x218; | ||
| 789 | out1[3] = x219; | ||
| 790 | } | ||
| 791 | |||
| 792 | /// The function add adds two field elements in the Montgomery domain. | ||
| 793 | /// Preconditions: | ||
| 794 | /// 0 ≤ eval arg1 < m | ||
| 795 | /// 0 ≤ eval arg2 < m | ||
| 796 | /// Postconditions: | ||
| 797 | /// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) + eval (from_montgomery arg2)) mod m | ||
| 798 | /// 0 ≤ eval out1 < m | ||
| 799 | /// | ||
| 800 | /// Input Bounds: | ||
| 801 | /// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 802 | /// arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 803 | /// Output Bounds: | ||
| 804 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 805 | pub fn add(out1: *[4]u64, arg1: [4]u64, arg2: [4]u64) void { | ||
| 806 | @setRuntimeSafety(mode == .Debug); | ||
| 807 | |||
| 808 | var x1: u64 = undefined; | ||
| 809 | var x2: u1 = undefined; | ||
| 810 | addcarryxU64(&x1, &x2, 0x0, (arg1[0]), (arg2[0])); | ||
| 811 | var x3: u64 = undefined; | ||
| 812 | var x4: u1 = undefined; | ||
| 813 | addcarryxU64(&x3, &x4, x2, (arg1[1]), (arg2[1])); | ||
| 814 | var x5: u64 = undefined; | ||
| 815 | var x6: u1 = undefined; | ||
| 816 | addcarryxU64(&x5, &x6, x4, (arg1[2]), (arg2[2])); | ||
| 817 | var x7: u64 = undefined; | ||
| 818 | var x8: u1 = undefined; | ||
| 819 | addcarryxU64(&x7, &x8, x6, (arg1[3]), (arg2[3])); | ||
| 820 | var x9: u64 = undefined; | ||
| 821 | var x10: u1 = undefined; | ||
| 822 | subborrowxU64(&x9, &x10, 0x0, x1, 0xf3b9cac2fc632551); | ||
| 823 | var x11: u64 = undefined; | ||
| 824 | var x12: u1 = undefined; | ||
| 825 | subborrowxU64(&x11, &x12, x10, x3, 0xbce6faada7179e84); | ||
| 826 | var x13: u64 = undefined; | ||
| 827 | var x14: u1 = undefined; | ||
| 828 | subborrowxU64(&x13, &x14, x12, x5, 0xffffffffffffffff); | ||
| 829 | var x15: u64 = undefined; | ||
| 830 | var x16: u1 = undefined; | ||
| 831 | subborrowxU64(&x15, &x16, x14, x7, 0xffffffff00000000); | ||
| 832 | var x17: u64 = undefined; | ||
| 833 | var x18: u1 = undefined; | ||
| 834 | subborrowxU64(&x17, &x18, x16, cast(u64, x8), cast(u64, 0x0)); | ||
| 835 | var x19: u64 = undefined; | ||
| 836 | cmovznzU64(&x19, x18, x9, x1); | ||
| 837 | var x20: u64 = undefined; | ||
| 838 | cmovznzU64(&x20, x18, x11, x3); | ||
| 839 | var x21: u64 = undefined; | ||
| 840 | cmovznzU64(&x21, x18, x13, x5); | ||
| 841 | var x22: u64 = undefined; | ||
| 842 | cmovznzU64(&x22, x18, x15, x7); | ||
| 843 | out1[0] = x19; | ||
| 844 | out1[1] = x20; | ||
| 845 | out1[2] = x21; | ||
| 846 | out1[3] = x22; | ||
| 847 | } | ||
| 848 | |||
| 849 | /// The function sub subtracts two field elements in the Montgomery domain. | ||
| 850 | /// Preconditions: | ||
| 851 | /// 0 ≤ eval arg1 < m | ||
| 852 | /// 0 ≤ eval arg2 < m | ||
| 853 | /// Postconditions: | ||
| 854 | /// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) - eval (from_montgomery arg2)) mod m | ||
| 855 | /// 0 ≤ eval out1 < m | ||
| 856 | /// | ||
| 857 | /// Input Bounds: | ||
| 858 | /// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 859 | /// arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 860 | /// Output Bounds: | ||
| 861 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 862 | pub fn sub(out1: *[4]u64, arg1: [4]u64, arg2: [4]u64) void { | ||
| 863 | @setRuntimeSafety(mode == .Debug); | ||
| 864 | |||
| 865 | var x1: u64 = undefined; | ||
| 866 | var x2: u1 = undefined; | ||
| 867 | subborrowxU64(&x1, &x2, 0x0, (arg1[0]), (arg2[0])); | ||
| 868 | var x3: u64 = undefined; | ||
| 869 | var x4: u1 = undefined; | ||
| 870 | subborrowxU64(&x3, &x4, x2, (arg1[1]), (arg2[1])); | ||
| 871 | var x5: u64 = undefined; | ||
| 872 | var x6: u1 = undefined; | ||
| 873 | subborrowxU64(&x5, &x6, x4, (arg1[2]), (arg2[2])); | ||
| 874 | var x7: u64 = undefined; | ||
| 875 | var x8: u1 = undefined; | ||
| 876 | subborrowxU64(&x7, &x8, x6, (arg1[3]), (arg2[3])); | ||
| 877 | var x9: u64 = undefined; | ||
| 878 | cmovznzU64(&x9, x8, cast(u64, 0x0), 0xffffffffffffffff); | ||
| 879 | var x10: u64 = undefined; | ||
| 880 | var x11: u1 = undefined; | ||
| 881 | addcarryxU64(&x10, &x11, 0x0, x1, (x9 & 0xf3b9cac2fc632551)); | ||
| 882 | var x12: u64 = undefined; | ||
| 883 | var x13: u1 = undefined; | ||
| 884 | addcarryxU64(&x12, &x13, x11, x3, (x9 & 0xbce6faada7179e84)); | ||
| 885 | var x14: u64 = undefined; | ||
| 886 | var x15: u1 = undefined; | ||
| 887 | addcarryxU64(&x14, &x15, x13, x5, x9); | ||
| 888 | var x16: u64 = undefined; | ||
| 889 | var x17: u1 = undefined; | ||
| 890 | addcarryxU64(&x16, &x17, x15, x7, (x9 & 0xffffffff00000000)); | ||
| 891 | out1[0] = x10; | ||
| 892 | out1[1] = x12; | ||
| 893 | out1[2] = x14; | ||
| 894 | out1[3] = x16; | ||
| 895 | } | ||
| 896 | |||
| 897 | /// The function opp negates a field element in the Montgomery domain. | ||
| 898 | /// Preconditions: | ||
| 899 | /// 0 ≤ eval arg1 < m | ||
| 900 | /// Postconditions: | ||
| 901 | /// eval (from_montgomery out1) mod m = -eval (from_montgomery arg1) mod m | ||
| 902 | /// 0 ≤ eval out1 < m | ||
| 903 | /// | ||
| 904 | /// Input Bounds: | ||
| 905 | /// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 906 | /// Output Bounds: | ||
| 907 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 908 | pub fn opp(out1: *[4]u64, arg1: [4]u64) void { | ||
| 909 | @setRuntimeSafety(mode == .Debug); | ||
| 910 | |||
| 911 | var x1: u64 = undefined; | ||
| 912 | var x2: u1 = undefined; | ||
| 913 | subborrowxU64(&x1, &x2, 0x0, cast(u64, 0x0), (arg1[0])); | ||
| 914 | var x3: u64 = undefined; | ||
| 915 | var x4: u1 = undefined; | ||
| 916 | subborrowxU64(&x3, &x4, x2, cast(u64, 0x0), (arg1[1])); | ||
| 917 | var x5: u64 = undefined; | ||
| 918 | var x6: u1 = undefined; | ||
| 919 | subborrowxU64(&x5, &x6, x4, cast(u64, 0x0), (arg1[2])); | ||
| 920 | var x7: u64 = undefined; | ||
| 921 | var x8: u1 = undefined; | ||
| 922 | subborrowxU64(&x7, &x8, x6, cast(u64, 0x0), (arg1[3])); | ||
| 923 | var x9: u64 = undefined; | ||
| 924 | cmovznzU64(&x9, x8, cast(u64, 0x0), 0xffffffffffffffff); | ||
| 925 | var x10: u64 = undefined; | ||
| 926 | var x11: u1 = undefined; | ||
| 927 | addcarryxU64(&x10, &x11, 0x0, x1, (x9 & 0xf3b9cac2fc632551)); | ||
| 928 | var x12: u64 = undefined; | ||
| 929 | var x13: u1 = undefined; | ||
| 930 | addcarryxU64(&x12, &x13, x11, x3, (x9 & 0xbce6faada7179e84)); | ||
| 931 | var x14: u64 = undefined; | ||
| 932 | var x15: u1 = undefined; | ||
| 933 | addcarryxU64(&x14, &x15, x13, x5, x9); | ||
| 934 | var x16: u64 = undefined; | ||
| 935 | var x17: u1 = undefined; | ||
| 936 | addcarryxU64(&x16, &x17, x15, x7, (x9 & 0xffffffff00000000)); | ||
| 937 | out1[0] = x10; | ||
| 938 | out1[1] = x12; | ||
| 939 | out1[2] = x14; | ||
| 940 | out1[3] = x16; | ||
| 941 | } | ||
| 942 | |||
| 943 | /// The function fromMontgomery translates a field element out of the Montgomery domain. | ||
| 944 | /// Preconditions: | ||
| 945 | /// 0 ≤ eval arg1 < m | ||
| 946 | /// Postconditions: | ||
| 947 | /// eval out1 mod m = (eval arg1 * ((2^64)⁻¹ mod m)^4) mod m | ||
| 948 | /// 0 ≤ eval out1 < m | ||
| 949 | /// | ||
| 950 | /// Input Bounds: | ||
| 951 | /// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 952 | /// Output Bounds: | ||
| 953 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 954 | pub fn fromMontgomery(out1: *[4]u64, arg1: [4]u64) void { | ||
| 955 | @setRuntimeSafety(mode == .Debug); | ||
| 956 | |||
| 957 | const x1 = (arg1[0]); | ||
| 958 | var x2: u64 = undefined; | ||
| 959 | var x3: u64 = undefined; | ||
| 960 | mulxU64(&x2, &x3, x1, 0xccd1c8aaee00bc4f); | ||
| 961 | var x4: u64 = undefined; | ||
| 962 | var x5: u64 = undefined; | ||
| 963 | mulxU64(&x4, &x5, x2, 0xffffffff00000000); | ||
| 964 | var x6: u64 = undefined; | ||
| 965 | var x7: u64 = undefined; | ||
| 966 | mulxU64(&x6, &x7, x2, 0xffffffffffffffff); | ||
| 967 | var x8: u64 = undefined; | ||
| 968 | var x9: u64 = undefined; | ||
| 969 | mulxU64(&x8, &x9, x2, 0xbce6faada7179e84); | ||
| 970 | var x10: u64 = undefined; | ||
| 971 | var x11: u64 = undefined; | ||
| 972 | mulxU64(&x10, &x11, x2, 0xf3b9cac2fc632551); | ||
| 973 | var x12: u64 = undefined; | ||
| 974 | var x13: u1 = undefined; | ||
| 975 | addcarryxU64(&x12, &x13, 0x0, x11, x8); | ||
| 976 | var x14: u64 = undefined; | ||
| 977 | var x15: u1 = undefined; | ||
| 978 | addcarryxU64(&x14, &x15, x13, x9, x6); | ||
| 979 | var x16: u64 = undefined; | ||
| 980 | var x17: u1 = undefined; | ||
| 981 | addcarryxU64(&x16, &x17, x15, x7, x4); | ||
| 982 | var x18: u64 = undefined; | ||
| 983 | var x19: u1 = undefined; | ||
| 984 | addcarryxU64(&x18, &x19, 0x0, x1, x10); | ||
| 985 | var x20: u64 = undefined; | ||
| 986 | var x21: u1 = undefined; | ||
| 987 | addcarryxU64(&x20, &x21, x19, cast(u64, 0x0), x12); | ||
| 988 | var x22: u64 = undefined; | ||
| 989 | var x23: u1 = undefined; | ||
| 990 | addcarryxU64(&x22, &x23, x21, cast(u64, 0x0), x14); | ||
| 991 | var x24: u64 = undefined; | ||
| 992 | var x25: u1 = undefined; | ||
| 993 | addcarryxU64(&x24, &x25, x23, cast(u64, 0x0), x16); | ||
| 994 | var x26: u64 = undefined; | ||
| 995 | var x27: u1 = undefined; | ||
| 996 | addcarryxU64(&x26, &x27, 0x0, x20, (arg1[1])); | ||
| 997 | var x28: u64 = undefined; | ||
| 998 | var x29: u1 = undefined; | ||
| 999 | addcarryxU64(&x28, &x29, x27, x22, cast(u64, 0x0)); | ||
| 1000 | var x30: u64 = undefined; | ||
| 1001 | var x31: u1 = undefined; | ||
| 1002 | addcarryxU64(&x30, &x31, x29, x24, cast(u64, 0x0)); | ||
| 1003 | var x32: u64 = undefined; | ||
| 1004 | var x33: u64 = undefined; | ||
| 1005 | mulxU64(&x32, &x33, x26, 0xccd1c8aaee00bc4f); | ||
| 1006 | var x34: u64 = undefined; | ||
| 1007 | var x35: u64 = undefined; | ||
| 1008 | mulxU64(&x34, &x35, x32, 0xffffffff00000000); | ||
| 1009 | var x36: u64 = undefined; | ||
| 1010 | var x37: u64 = undefined; | ||
| 1011 | mulxU64(&x36, &x37, x32, 0xffffffffffffffff); | ||
| 1012 | var x38: u64 = undefined; | ||
| 1013 | var x39: u64 = undefined; | ||
| 1014 | mulxU64(&x38, &x39, x32, 0xbce6faada7179e84); | ||
| 1015 | var x40: u64 = undefined; | ||
| 1016 | var x41: u64 = undefined; | ||
| 1017 | mulxU64(&x40, &x41, x32, 0xf3b9cac2fc632551); | ||
| 1018 | var x42: u64 = undefined; | ||
| 1019 | var x43: u1 = undefined; | ||
| 1020 | addcarryxU64(&x42, &x43, 0x0, x41, x38); | ||
| 1021 | var x44: u64 = undefined; | ||
| 1022 | var x45: u1 = undefined; | ||
| 1023 | addcarryxU64(&x44, &x45, x43, x39, x36); | ||
| 1024 | var x46: u64 = undefined; | ||
| 1025 | var x47: u1 = undefined; | ||
| 1026 | addcarryxU64(&x46, &x47, x45, x37, x34); | ||
| 1027 | var x48: u64 = undefined; | ||
| 1028 | var x49: u1 = undefined; | ||
| 1029 | addcarryxU64(&x48, &x49, 0x0, x26, x40); | ||
| 1030 | var x50: u64 = undefined; | ||
| 1031 | var x51: u1 = undefined; | ||
| 1032 | addcarryxU64(&x50, &x51, x49, x28, x42); | ||
| 1033 | var x52: u64 = undefined; | ||
| 1034 | var x53: u1 = undefined; | ||
| 1035 | addcarryxU64(&x52, &x53, x51, x30, x44); | ||
| 1036 | var x54: u64 = undefined; | ||
| 1037 | var x55: u1 = undefined; | ||
| 1038 | addcarryxU64(&x54, &x55, x53, (cast(u64, x31) + (cast(u64, x25) + (cast(u64, x17) + x5))), x46); | ||
| 1039 | var x56: u64 = undefined; | ||
| 1040 | var x57: u1 = undefined; | ||
| 1041 | addcarryxU64(&x56, &x57, 0x0, x50, (arg1[2])); | ||
| 1042 | var x58: u64 = undefined; | ||
| 1043 | var x59: u1 = undefined; | ||
| 1044 | addcarryxU64(&x58, &x59, x57, x52, cast(u64, 0x0)); | ||
| 1045 | var x60: u64 = undefined; | ||
| 1046 | var x61: u1 = undefined; | ||
| 1047 | addcarryxU64(&x60, &x61, x59, x54, cast(u64, 0x0)); | ||
| 1048 | var x62: u64 = undefined; | ||
| 1049 | var x63: u64 = undefined; | ||
| 1050 | mulxU64(&x62, &x63, x56, 0xccd1c8aaee00bc4f); | ||
| 1051 | var x64: u64 = undefined; | ||
| 1052 | var x65: u64 = undefined; | ||
| 1053 | mulxU64(&x64, &x65, x62, 0xffffffff00000000); | ||
| 1054 | var x66: u64 = undefined; | ||
| 1055 | var x67: u64 = undefined; | ||
| 1056 | mulxU64(&x66, &x67, x62, 0xffffffffffffffff); | ||
| 1057 | var x68: u64 = undefined; | ||
| 1058 | var x69: u64 = undefined; | ||
| 1059 | mulxU64(&x68, &x69, x62, 0xbce6faada7179e84); | ||
| 1060 | var x70: u64 = undefined; | ||
| 1061 | var x71: u64 = undefined; | ||
| 1062 | mulxU64(&x70, &x71, x62, 0xf3b9cac2fc632551); | ||
| 1063 | var x72: u64 = undefined; | ||
| 1064 | var x73: u1 = undefined; | ||
| 1065 | addcarryxU64(&x72, &x73, 0x0, x71, x68); | ||
| 1066 | var x74: u64 = undefined; | ||
| 1067 | var x75: u1 = undefined; | ||
| 1068 | addcarryxU64(&x74, &x75, x73, x69, x66); | ||
| 1069 | var x76: u64 = undefined; | ||
| 1070 | var x77: u1 = undefined; | ||
| 1071 | addcarryxU64(&x76, &x77, x75, x67, x64); | ||
| 1072 | var x78: u64 = undefined; | ||
| 1073 | var x79: u1 = undefined; | ||
| 1074 | addcarryxU64(&x78, &x79, 0x0, x56, x70); | ||
| 1075 | var x80: u64 = undefined; | ||
| 1076 | var x81: u1 = undefined; | ||
| 1077 | addcarryxU64(&x80, &x81, x79, x58, x72); | ||
| 1078 | var x82: u64 = undefined; | ||
| 1079 | var x83: u1 = undefined; | ||
| 1080 | addcarryxU64(&x82, &x83, x81, x60, x74); | ||
| 1081 | var x84: u64 = undefined; | ||
| 1082 | var x85: u1 = undefined; | ||
| 1083 | addcarryxU64(&x84, &x85, x83, (cast(u64, x61) + (cast(u64, x55) + (cast(u64, x47) + x35))), x76); | ||
| 1084 | var x86: u64 = undefined; | ||
| 1085 | var x87: u1 = undefined; | ||
| 1086 | addcarryxU64(&x86, &x87, 0x0, x80, (arg1[3])); | ||
| 1087 | var x88: u64 = undefined; | ||
| 1088 | var x89: u1 = undefined; | ||
| 1089 | addcarryxU64(&x88, &x89, x87, x82, cast(u64, 0x0)); | ||
| 1090 | var x90: u64 = undefined; | ||
| 1091 | var x91: u1 = undefined; | ||
| 1092 | addcarryxU64(&x90, &x91, x89, x84, cast(u64, 0x0)); | ||
| 1093 | var x92: u64 = undefined; | ||
| 1094 | var x93: u64 = undefined; | ||
| 1095 | mulxU64(&x92, &x93, x86, 0xccd1c8aaee00bc4f); | ||
| 1096 | var x94: u64 = undefined; | ||
| 1097 | var x95: u64 = undefined; | ||
| 1098 | mulxU64(&x94, &x95, x92, 0xffffffff00000000); | ||
| 1099 | var x96: u64 = undefined; | ||
| 1100 | var x97: u64 = undefined; | ||
| 1101 | mulxU64(&x96, &x97, x92, 0xffffffffffffffff); | ||
| 1102 | var x98: u64 = undefined; | ||
| 1103 | var x99: u64 = undefined; | ||
| 1104 | mulxU64(&x98, &x99, x92, 0xbce6faada7179e84); | ||
| 1105 | var x100: u64 = undefined; | ||
| 1106 | var x101: u64 = undefined; | ||
| 1107 | mulxU64(&x100, &x101, x92, 0xf3b9cac2fc632551); | ||
| 1108 | var x102: u64 = undefined; | ||
| 1109 | var x103: u1 = undefined; | ||
| 1110 | addcarryxU64(&x102, &x103, 0x0, x101, x98); | ||
| 1111 | var x104: u64 = undefined; | ||
| 1112 | var x105: u1 = undefined; | ||
| 1113 | addcarryxU64(&x104, &x105, x103, x99, x96); | ||
| 1114 | var x106: u64 = undefined; | ||
| 1115 | var x107: u1 = undefined; | ||
| 1116 | addcarryxU64(&x106, &x107, x105, x97, x94); | ||
| 1117 | var x108: u64 = undefined; | ||
| 1118 | var x109: u1 = undefined; | ||
| 1119 | addcarryxU64(&x108, &x109, 0x0, x86, x100); | ||
| 1120 | var x110: u64 = undefined; | ||
| 1121 | var x111: u1 = undefined; | ||
| 1122 | addcarryxU64(&x110, &x111, x109, x88, x102); | ||
| 1123 | var x112: u64 = undefined; | ||
| 1124 | var x113: u1 = undefined; | ||
| 1125 | addcarryxU64(&x112, &x113, x111, x90, x104); | ||
| 1126 | var x114: u64 = undefined; | ||
| 1127 | var x115: u1 = undefined; | ||
| 1128 | addcarryxU64(&x114, &x115, x113, (cast(u64, x91) + (cast(u64, x85) + (cast(u64, x77) + x65))), x106); | ||
| 1129 | const x116 = (cast(u64, x115) + (cast(u64, x107) + x95)); | ||
| 1130 | var x117: u64 = undefined; | ||
| 1131 | var x118: u1 = undefined; | ||
| 1132 | subborrowxU64(&x117, &x118, 0x0, x110, 0xf3b9cac2fc632551); | ||
| 1133 | var x119: u64 = undefined; | ||
| 1134 | var x120: u1 = undefined; | ||
| 1135 | subborrowxU64(&x119, &x120, x118, x112, 0xbce6faada7179e84); | ||
| 1136 | var x121: u64 = undefined; | ||
| 1137 | var x122: u1 = undefined; | ||
| 1138 | subborrowxU64(&x121, &x122, x120, x114, 0xffffffffffffffff); | ||
| 1139 | var x123: u64 = undefined; | ||
| 1140 | var x124: u1 = undefined; | ||
| 1141 | subborrowxU64(&x123, &x124, x122, x116, 0xffffffff00000000); | ||
| 1142 | var x125: u64 = undefined; | ||
| 1143 | var x126: u1 = undefined; | ||
| 1144 | subborrowxU64(&x125, &x126, x124, cast(u64, 0x0), cast(u64, 0x0)); | ||
| 1145 | var x127: u64 = undefined; | ||
| 1146 | cmovznzU64(&x127, x126, x117, x110); | ||
| 1147 | var x128: u64 = undefined; | ||
| 1148 | cmovznzU64(&x128, x126, x119, x112); | ||
| 1149 | var x129: u64 = undefined; | ||
| 1150 | cmovznzU64(&x129, x126, x121, x114); | ||
| 1151 | var x130: u64 = undefined; | ||
| 1152 | cmovznzU64(&x130, x126, x123, x116); | ||
| 1153 | out1[0] = x127; | ||
| 1154 | out1[1] = x128; | ||
| 1155 | out1[2] = x129; | ||
| 1156 | out1[3] = x130; | ||
| 1157 | } | ||
| 1158 | |||
| 1159 | /// The function toMontgomery translates a field element into the Montgomery domain. | ||
| 1160 | /// Preconditions: | ||
| 1161 | /// 0 ≤ eval arg1 < m | ||
| 1162 | /// Postconditions: | ||
| 1163 | /// eval (from_montgomery out1) mod m = eval arg1 mod m | ||
| 1164 | /// 0 ≤ eval out1 < m | ||
| 1165 | /// | ||
| 1166 | /// Input Bounds: | ||
| 1167 | /// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 1168 | /// Output Bounds: | ||
| 1169 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 1170 | pub fn toMontgomery(out1: *[4]u64, arg1: [4]u64) void { | ||
| 1171 | @setRuntimeSafety(mode == .Debug); | ||
| 1172 | |||
| 1173 | const x1 = (arg1[1]); | ||
| 1174 | const x2 = (arg1[2]); | ||
| 1175 | const x3 = (arg1[3]); | ||
| 1176 | const x4 = (arg1[0]); | ||
| 1177 | var x5: u64 = undefined; | ||
| 1178 | var x6: u64 = undefined; | ||
| 1179 | mulxU64(&x5, &x6, x4, 0x66e12d94f3d95620); | ||
| 1180 | var x7: u64 = undefined; | ||
| 1181 | var x8: u64 = undefined; | ||
| 1182 | mulxU64(&x7, &x8, x4, 0x2845b2392b6bec59); | ||
| 1183 | var x9: u64 = undefined; | ||
| 1184 | var x10: u64 = undefined; | ||
| 1185 | mulxU64(&x9, &x10, x4, 0x4699799c49bd6fa6); | ||
| 1186 | var x11: u64 = undefined; | ||
| 1187 | var x12: u64 = undefined; | ||
| 1188 | mulxU64(&x11, &x12, x4, 0x83244c95be79eea2); | ||
| 1189 | var x13: u64 = undefined; | ||
| 1190 | var x14: u1 = undefined; | ||
| 1191 | addcarryxU64(&x13, &x14, 0x0, x12, x9); | ||
| 1192 | var x15: u64 = undefined; | ||
| 1193 | var x16: u1 = undefined; | ||
| 1194 | addcarryxU64(&x15, &x16, x14, x10, x7); | ||
| 1195 | var x17: u64 = undefined; | ||
| 1196 | var x18: u1 = undefined; | ||
| 1197 | addcarryxU64(&x17, &x18, x16, x8, x5); | ||
| 1198 | var x19: u64 = undefined; | ||
| 1199 | var x20: u64 = undefined; | ||
| 1200 | mulxU64(&x19, &x20, x11, 0xccd1c8aaee00bc4f); | ||
| 1201 | var x21: u64 = undefined; | ||
| 1202 | var x22: u64 = undefined; | ||
| 1203 | mulxU64(&x21, &x22, x19, 0xffffffff00000000); | ||
| 1204 | var x23: u64 = undefined; | ||
| 1205 | var x24: u64 = undefined; | ||
| 1206 | mulxU64(&x23, &x24, x19, 0xffffffffffffffff); | ||
| 1207 | var x25: u64 = undefined; | ||
| 1208 | var x26: u64 = undefined; | ||
| 1209 | mulxU64(&x25, &x26, x19, 0xbce6faada7179e84); | ||
| 1210 | var x27: u64 = undefined; | ||
| 1211 | var x28: u64 = undefined; | ||
| 1212 | mulxU64(&x27, &x28, x19, 0xf3b9cac2fc632551); | ||
| 1213 | var x29: u64 = undefined; | ||
| 1214 | var x30: u1 = undefined; | ||
| 1215 | addcarryxU64(&x29, &x30, 0x0, x28, x25); | ||
| 1216 | var x31: u64 = undefined; | ||
| 1217 | var x32: u1 = undefined; | ||
| 1218 | addcarryxU64(&x31, &x32, x30, x26, x23); | ||
| 1219 | var x33: u64 = undefined; | ||
| 1220 | var x34: u1 = undefined; | ||
| 1221 | addcarryxU64(&x33, &x34, x32, x24, x21); | ||
| 1222 | var x35: u64 = undefined; | ||
| 1223 | var x36: u1 = undefined; | ||
| 1224 | addcarryxU64(&x35, &x36, 0x0, x11, x27); | ||
| 1225 | var x37: u64 = undefined; | ||
| 1226 | var x38: u1 = undefined; | ||
| 1227 | addcarryxU64(&x37, &x38, x36, x13, x29); | ||
| 1228 | var x39: u64 = undefined; | ||
| 1229 | var x40: u1 = undefined; | ||
| 1230 | addcarryxU64(&x39, &x40, x38, x15, x31); | ||
| 1231 | var x41: u64 = undefined; | ||
| 1232 | var x42: u1 = undefined; | ||
| 1233 | addcarryxU64(&x41, &x42, x40, x17, x33); | ||
| 1234 | var x43: u64 = undefined; | ||
| 1235 | var x44: u1 = undefined; | ||
| 1236 | addcarryxU64(&x43, &x44, x42, (cast(u64, x18) + x6), (cast(u64, x34) + x22)); | ||
| 1237 | var x45: u64 = undefined; | ||
| 1238 | var x46: u64 = undefined; | ||
| 1239 | mulxU64(&x45, &x46, x1, 0x66e12d94f3d95620); | ||
| 1240 | var x47: u64 = undefined; | ||
| 1241 | var x48: u64 = undefined; | ||
| 1242 | mulxU64(&x47, &x48, x1, 0x2845b2392b6bec59); | ||
| 1243 | var x49: u64 = undefined; | ||
| 1244 | var x50: u64 = undefined; | ||
| 1245 | mulxU64(&x49, &x50, x1, 0x4699799c49bd6fa6); | ||
| 1246 | var x51: u64 = undefined; | ||
| 1247 | var x52: u64 = undefined; | ||
| 1248 | mulxU64(&x51, &x52, x1, 0x83244c95be79eea2); | ||
| 1249 | var x53: u64 = undefined; | ||
| 1250 | var x54: u1 = undefined; | ||
| 1251 | addcarryxU64(&x53, &x54, 0x0, x52, x49); | ||
| 1252 | var x55: u64 = undefined; | ||
| 1253 | var x56: u1 = undefined; | ||
| 1254 | addcarryxU64(&x55, &x56, x54, x50, x47); | ||
| 1255 | var x57: u64 = undefined; | ||
| 1256 | var x58: u1 = undefined; | ||
| 1257 | addcarryxU64(&x57, &x58, x56, x48, x45); | ||
| 1258 | var x59: u64 = undefined; | ||
| 1259 | var x60: u1 = undefined; | ||
| 1260 | addcarryxU64(&x59, &x60, 0x0, x37, x51); | ||
| 1261 | var x61: u64 = undefined; | ||
| 1262 | var x62: u1 = undefined; | ||
| 1263 | addcarryxU64(&x61, &x62, x60, x39, x53); | ||
| 1264 | var x63: u64 = undefined; | ||
| 1265 | var x64: u1 = undefined; | ||
| 1266 | addcarryxU64(&x63, &x64, x62, x41, x55); | ||
| 1267 | var x65: u64 = undefined; | ||
| 1268 | var x66: u1 = undefined; | ||
| 1269 | addcarryxU64(&x65, &x66, x64, x43, x57); | ||
| 1270 | var x67: u64 = undefined; | ||
| 1271 | var x68: u64 = undefined; | ||
| 1272 | mulxU64(&x67, &x68, x59, 0xccd1c8aaee00bc4f); | ||
| 1273 | var x69: u64 = undefined; | ||
| 1274 | var x70: u64 = undefined; | ||
| 1275 | mulxU64(&x69, &x70, x67, 0xffffffff00000000); | ||
| 1276 | var x71: u64 = undefined; | ||
| 1277 | var x72: u64 = undefined; | ||
| 1278 | mulxU64(&x71, &x72, x67, 0xffffffffffffffff); | ||
| 1279 | var x73: u64 = undefined; | ||
| 1280 | var x74: u64 = undefined; | ||
| 1281 | mulxU64(&x73, &x74, x67, 0xbce6faada7179e84); | ||
| 1282 | var x75: u64 = undefined; | ||
| 1283 | var x76: u64 = undefined; | ||
| 1284 | mulxU64(&x75, &x76, x67, 0xf3b9cac2fc632551); | ||
| 1285 | var x77: u64 = undefined; | ||
| 1286 | var x78: u1 = undefined; | ||
| 1287 | addcarryxU64(&x77, &x78, 0x0, x76, x73); | ||
| 1288 | var x79: u64 = undefined; | ||
| 1289 | var x80: u1 = undefined; | ||
| 1290 | addcarryxU64(&x79, &x80, x78, x74, x71); | ||
| 1291 | var x81: u64 = undefined; | ||
| 1292 | var x82: u1 = undefined; | ||
| 1293 | addcarryxU64(&x81, &x82, x80, x72, x69); | ||
| 1294 | var x83: u64 = undefined; | ||
| 1295 | var x84: u1 = undefined; | ||
| 1296 | addcarryxU64(&x83, &x84, 0x0, x59, x75); | ||
| 1297 | var x85: u64 = undefined; | ||
| 1298 | var x86: u1 = undefined; | ||
| 1299 | addcarryxU64(&x85, &x86, x84, x61, x77); | ||
| 1300 | var x87: u64 = undefined; | ||
| 1301 | var x88: u1 = undefined; | ||
| 1302 | addcarryxU64(&x87, &x88, x86, x63, x79); | ||
| 1303 | var x89: u64 = undefined; | ||
| 1304 | var x90: u1 = undefined; | ||
| 1305 | addcarryxU64(&x89, &x90, x88, x65, x81); | ||
| 1306 | var x91: u64 = undefined; | ||
| 1307 | var x92: u1 = undefined; | ||
| 1308 | addcarryxU64(&x91, &x92, x90, ((cast(u64, x66) + cast(u64, x44)) + (cast(u64, x58) + x46)), (cast(u64, x82) + x70)); | ||
| 1309 | var x93: u64 = undefined; | ||
| 1310 | var x94: u64 = undefined; | ||
| 1311 | mulxU64(&x93, &x94, x2, 0x66e12d94f3d95620); | ||
| 1312 | var x95: u64 = undefined; | ||
| 1313 | var x96: u64 = undefined; | ||
| 1314 | mulxU64(&x95, &x96, x2, 0x2845b2392b6bec59); | ||
| 1315 | var x97: u64 = undefined; | ||
| 1316 | var x98: u64 = undefined; | ||
| 1317 | mulxU64(&x97, &x98, x2, 0x4699799c49bd6fa6); | ||
| 1318 | var x99: u64 = undefined; | ||
| 1319 | var x100: u64 = undefined; | ||
| 1320 | mulxU64(&x99, &x100, x2, 0x83244c95be79eea2); | ||
| 1321 | var x101: u64 = undefined; | ||
| 1322 | var x102: u1 = undefined; | ||
| 1323 | addcarryxU64(&x101, &x102, 0x0, x100, x97); | ||
| 1324 | var x103: u64 = undefined; | ||
| 1325 | var x104: u1 = undefined; | ||
| 1326 | addcarryxU64(&x103, &x104, x102, x98, x95); | ||
| 1327 | var x105: u64 = undefined; | ||
| 1328 | var x106: u1 = undefined; | ||
| 1329 | addcarryxU64(&x105, &x106, x104, x96, x93); | ||
| 1330 | var x107: u64 = undefined; | ||
| 1331 | var x108: u1 = undefined; | ||
| 1332 | addcarryxU64(&x107, &x108, 0x0, x85, x99); | ||
| 1333 | var x109: u64 = undefined; | ||
| 1334 | var x110: u1 = undefined; | ||
| 1335 | addcarryxU64(&x109, &x110, x108, x87, x101); | ||
| 1336 | var x111: u64 = undefined; | ||
| 1337 | var x112: u1 = undefined; | ||
| 1338 | addcarryxU64(&x111, &x112, x110, x89, x103); | ||
| 1339 | var x113: u64 = undefined; | ||
| 1340 | var x114: u1 = undefined; | ||
| 1341 | addcarryxU64(&x113, &x114, x112, x91, x105); | ||
| 1342 | var x115: u64 = undefined; | ||
| 1343 | var x116: u64 = undefined; | ||
| 1344 | mulxU64(&x115, &x116, x107, 0xccd1c8aaee00bc4f); | ||
| 1345 | var x117: u64 = undefined; | ||
| 1346 | var x118: u64 = undefined; | ||
| 1347 | mulxU64(&x117, &x118, x115, 0xffffffff00000000); | ||
| 1348 | var x119: u64 = undefined; | ||
| 1349 | var x120: u64 = undefined; | ||
| 1350 | mulxU64(&x119, &x120, x115, 0xffffffffffffffff); | ||
| 1351 | var x121: u64 = undefined; | ||
| 1352 | var x122: u64 = undefined; | ||
| 1353 | mulxU64(&x121, &x122, x115, 0xbce6faada7179e84); | ||
| 1354 | var x123: u64 = undefined; | ||
| 1355 | var x124: u64 = undefined; | ||
| 1356 | mulxU64(&x123, &x124, x115, 0xf3b9cac2fc632551); | ||
| 1357 | var x125: u64 = undefined; | ||
| 1358 | var x126: u1 = undefined; | ||
| 1359 | addcarryxU64(&x125, &x126, 0x0, x124, x121); | ||
| 1360 | var x127: u64 = undefined; | ||
| 1361 | var x128: u1 = undefined; | ||
| 1362 | addcarryxU64(&x127, &x128, x126, x122, x119); | ||
| 1363 | var x129: u64 = undefined; | ||
| 1364 | var x130: u1 = undefined; | ||
| 1365 | addcarryxU64(&x129, &x130, x128, x120, x117); | ||
| 1366 | var x131: u64 = undefined; | ||
| 1367 | var x132: u1 = undefined; | ||
| 1368 | addcarryxU64(&x131, &x132, 0x0, x107, x123); | ||
| 1369 | var x133: u64 = undefined; | ||
| 1370 | var x134: u1 = undefined; | ||
| 1371 | addcarryxU64(&x133, &x134, x132, x109, x125); | ||
| 1372 | var x135: u64 = undefined; | ||
| 1373 | var x136: u1 = undefined; | ||
| 1374 | addcarryxU64(&x135, &x136, x134, x111, x127); | ||
| 1375 | var x137: u64 = undefined; | ||
| 1376 | var x138: u1 = undefined; | ||
| 1377 | addcarryxU64(&x137, &x138, x136, x113, x129); | ||
| 1378 | var x139: u64 = undefined; | ||
| 1379 | var x140: u1 = undefined; | ||
| 1380 | addcarryxU64(&x139, &x140, x138, ((cast(u64, x114) + cast(u64, x92)) + (cast(u64, x106) + x94)), (cast(u64, x130) + x118)); | ||
| 1381 | var x141: u64 = undefined; | ||
| 1382 | var x142: u64 = undefined; | ||
| 1383 | mulxU64(&x141, &x142, x3, 0x66e12d94f3d95620); | ||
| 1384 | var x143: u64 = undefined; | ||
| 1385 | var x144: u64 = undefined; | ||
| 1386 | mulxU64(&x143, &x144, x3, 0x2845b2392b6bec59); | ||
| 1387 | var x145: u64 = undefined; | ||
| 1388 | var x146: u64 = undefined; | ||
| 1389 | mulxU64(&x145, &x146, x3, 0x4699799c49bd6fa6); | ||
| 1390 | var x147: u64 = undefined; | ||
| 1391 | var x148: u64 = undefined; | ||
| 1392 | mulxU64(&x147, &x148, x3, 0x83244c95be79eea2); | ||
| 1393 | var x149: u64 = undefined; | ||
| 1394 | var x150: u1 = undefined; | ||
| 1395 | addcarryxU64(&x149, &x150, 0x0, x148, x145); | ||
| 1396 | var x151: u64 = undefined; | ||
| 1397 | var x152: u1 = undefined; | ||
| 1398 | addcarryxU64(&x151, &x152, x150, x146, x143); | ||
| 1399 | var x153: u64 = undefined; | ||
| 1400 | var x154: u1 = undefined; | ||
| 1401 | addcarryxU64(&x153, &x154, x152, x144, x141); | ||
| 1402 | var x155: u64 = undefined; | ||
| 1403 | var x156: u1 = undefined; | ||
| 1404 | addcarryxU64(&x155, &x156, 0x0, x133, x147); | ||
| 1405 | var x157: u64 = undefined; | ||
| 1406 | var x158: u1 = undefined; | ||
| 1407 | addcarryxU64(&x157, &x158, x156, x135, x149); | ||
| 1408 | var x159: u64 = undefined; | ||
| 1409 | var x160: u1 = undefined; | ||
| 1410 | addcarryxU64(&x159, &x160, x158, x137, x151); | ||
| 1411 | var x161: u64 = undefined; | ||
| 1412 | var x162: u1 = undefined; | ||
| 1413 | addcarryxU64(&x161, &x162, x160, x139, x153); | ||
| 1414 | var x163: u64 = undefined; | ||
| 1415 | var x164: u64 = undefined; | ||
| 1416 | mulxU64(&x163, &x164, x155, 0xccd1c8aaee00bc4f); | ||
| 1417 | var x165: u64 = undefined; | ||
| 1418 | var x166: u64 = undefined; | ||
| 1419 | mulxU64(&x165, &x166, x163, 0xffffffff00000000); | ||
| 1420 | var x167: u64 = undefined; | ||
| 1421 | var x168: u64 = undefined; | ||
| 1422 | mulxU64(&x167, &x168, x163, 0xffffffffffffffff); | ||
| 1423 | var x169: u64 = undefined; | ||
| 1424 | var x170: u64 = undefined; | ||
| 1425 | mulxU64(&x169, &x170, x163, 0xbce6faada7179e84); | ||
| 1426 | var x171: u64 = undefined; | ||
| 1427 | var x172: u64 = undefined; | ||
| 1428 | mulxU64(&x171, &x172, x163, 0xf3b9cac2fc632551); | ||
| 1429 | var x173: u64 = undefined; | ||
| 1430 | var x174: u1 = undefined; | ||
| 1431 | addcarryxU64(&x173, &x174, 0x0, x172, x169); | ||
| 1432 | var x175: u64 = undefined; | ||
| 1433 | var x176: u1 = undefined; | ||
| 1434 | addcarryxU64(&x175, &x176, x174, x170, x167); | ||
| 1435 | var x177: u64 = undefined; | ||
| 1436 | var x178: u1 = undefined; | ||
| 1437 | addcarryxU64(&x177, &x178, x176, x168, x165); | ||
| 1438 | var x179: u64 = undefined; | ||
| 1439 | var x180: u1 = undefined; | ||
| 1440 | addcarryxU64(&x179, &x180, 0x0, x155, x171); | ||
| 1441 | var x181: u64 = undefined; | ||
| 1442 | var x182: u1 = undefined; | ||
| 1443 | addcarryxU64(&x181, &x182, x180, x157, x173); | ||
| 1444 | var x183: u64 = undefined; | ||
| 1445 | var x184: u1 = undefined; | ||
| 1446 | addcarryxU64(&x183, &x184, x182, x159, x175); | ||
| 1447 | var x185: u64 = undefined; | ||
| 1448 | var x186: u1 = undefined; | ||
| 1449 | addcarryxU64(&x185, &x186, x184, x161, x177); | ||
| 1450 | var x187: u64 = undefined; | ||
| 1451 | var x188: u1 = undefined; | ||
| 1452 | addcarryxU64(&x187, &x188, x186, ((cast(u64, x162) + cast(u64, x140)) + (cast(u64, x154) + x142)), (cast(u64, x178) + x166)); | ||
| 1453 | var x189: u64 = undefined; | ||
| 1454 | var x190: u1 = undefined; | ||
| 1455 | subborrowxU64(&x189, &x190, 0x0, x181, 0xf3b9cac2fc632551); | ||
| 1456 | var x191: u64 = undefined; | ||
| 1457 | var x192: u1 = undefined; | ||
| 1458 | subborrowxU64(&x191, &x192, x190, x183, 0xbce6faada7179e84); | ||
| 1459 | var x193: u64 = undefined; | ||
| 1460 | var x194: u1 = undefined; | ||
| 1461 | subborrowxU64(&x193, &x194, x192, x185, 0xffffffffffffffff); | ||
| 1462 | var x195: u64 = undefined; | ||
| 1463 | var x196: u1 = undefined; | ||
| 1464 | subborrowxU64(&x195, &x196, x194, x187, 0xffffffff00000000); | ||
| 1465 | var x197: u64 = undefined; | ||
| 1466 | var x198: u1 = undefined; | ||
| 1467 | subborrowxU64(&x197, &x198, x196, cast(u64, x188), cast(u64, 0x0)); | ||
| 1468 | var x199: u64 = undefined; | ||
| 1469 | cmovznzU64(&x199, x198, x189, x181); | ||
| 1470 | var x200: u64 = undefined; | ||
| 1471 | cmovznzU64(&x200, x198, x191, x183); | ||
| 1472 | var x201: u64 = undefined; | ||
| 1473 | cmovznzU64(&x201, x198, x193, x185); | ||
| 1474 | var x202: u64 = undefined; | ||
| 1475 | cmovznzU64(&x202, x198, x195, x187); | ||
| 1476 | out1[0] = x199; | ||
| 1477 | out1[1] = x200; | ||
| 1478 | out1[2] = x201; | ||
| 1479 | out1[3] = x202; | ||
| 1480 | } | ||
| 1481 | |||
| 1482 | /// The function nonzero outputs a single non-zero word if the input is non-zero and zero otherwise. | ||
| 1483 | /// Preconditions: | ||
| 1484 | /// 0 ≤ eval arg1 < m | ||
| 1485 | /// Postconditions: | ||
| 1486 | /// out1 = 0 ↔ eval (from_montgomery arg1) mod m = 0 | ||
| 1487 | /// | ||
| 1488 | /// Input Bounds: | ||
| 1489 | /// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 1490 | /// Output Bounds: | ||
| 1491 | /// out1: [0x0 ~> 0xffffffffffffffff] | ||
| 1492 | pub fn nonzero(out1: *u64, arg1: [4]u64) void { | ||
| 1493 | @setRuntimeSafety(mode == .Debug); | ||
| 1494 | |||
| 1495 | const x1 = ((arg1[0]) | ((arg1[1]) | ((arg1[2]) | (arg1[3])))); | ||
| 1496 | out1.* = x1; | ||
| 1497 | } | ||
| 1498 | |||
| 1499 | /// The function selectznz is a multi-limb conditional select. | ||
| 1500 | /// Postconditions: | ||
| 1501 | /// eval out1 = (if arg1 = 0 then eval arg2 else eval arg3) | ||
| 1502 | /// | ||
| 1503 | /// Input Bounds: | ||
| 1504 | /// arg1: [0x0 ~> 0x1] | ||
| 1505 | /// arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 1506 | /// arg3: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 1507 | /// Output Bounds: | ||
| 1508 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 1509 | pub fn selectznz(out1: *[4]u64, arg1: u1, arg2: [4]u64, arg3: [4]u64) void { | ||
| 1510 | @setRuntimeSafety(mode == .Debug); | ||
| 1511 | |||
| 1512 | var x1: u64 = undefined; | ||
| 1513 | cmovznzU64(&x1, arg1, (arg2[0]), (arg3[0])); | ||
| 1514 | var x2: u64 = undefined; | ||
| 1515 | cmovznzU64(&x2, arg1, (arg2[1]), (arg3[1])); | ||
| 1516 | var x3: u64 = undefined; | ||
| 1517 | cmovznzU64(&x3, arg1, (arg2[2]), (arg3[2])); | ||
| 1518 | var x4: u64 = undefined; | ||
| 1519 | cmovznzU64(&x4, arg1, (arg2[3]), (arg3[3])); | ||
| 1520 | out1[0] = x1; | ||
| 1521 | out1[1] = x2; | ||
| 1522 | out1[2] = x3; | ||
| 1523 | out1[3] = x4; | ||
| 1524 | } | ||
| 1525 | |||
| 1526 | /// The function toBytes serializes a field element NOT in the Montgomery domain to bytes in little-endian order. | ||
| 1527 | /// Preconditions: | ||
| 1528 | /// 0 ≤ eval arg1 < m | ||
| 1529 | /// Postconditions: | ||
| 1530 | /// out1 = map (λ x, ⌊((eval arg1 mod m) mod 2^(8 * (x + 1))) / 2^(8 * x)⌋) [0..31] | ||
| 1531 | /// | ||
| 1532 | /// Input Bounds: | ||
| 1533 | /// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 1534 | /// Output Bounds: | ||
| 1535 | /// 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]] | ||
| 1536 | pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void { | ||
| 1537 | @setRuntimeSafety(mode == .Debug); | ||
| 1538 | |||
| 1539 | const x1 = (arg1[3]); | ||
| 1540 | const x2 = (arg1[2]); | ||
| 1541 | const x3 = (arg1[1]); | ||
| 1542 | const x4 = (arg1[0]); | ||
| 1543 | const x5 = cast(u8, (x4 & cast(u64, 0xff))); | ||
| 1544 | const x6 = (x4 >> 8); | ||
| 1545 | const x7 = cast(u8, (x6 & cast(u64, 0xff))); | ||
| 1546 | const x8 = (x6 >> 8); | ||
| 1547 | const x9 = cast(u8, (x8 & cast(u64, 0xff))); | ||
| 1548 | const x10 = (x8 >> 8); | ||
| 1549 | const x11 = cast(u8, (x10 & cast(u64, 0xff))); | ||
| 1550 | const x12 = (x10 >> 8); | ||
| 1551 | const x13 = cast(u8, (x12 & cast(u64, 0xff))); | ||
| 1552 | const x14 = (x12 >> 8); | ||
| 1553 | const x15 = cast(u8, (x14 & cast(u64, 0xff))); | ||
| 1554 | const x16 = (x14 >> 8); | ||
| 1555 | const x17 = cast(u8, (x16 & cast(u64, 0xff))); | ||
| 1556 | const x18 = cast(u8, (x16 >> 8)); | ||
| 1557 | const x19 = cast(u8, (x3 & cast(u64, 0xff))); | ||
| 1558 | const x20 = (x3 >> 8); | ||
| 1559 | const x21 = cast(u8, (x20 & cast(u64, 0xff))); | ||
| 1560 | const x22 = (x20 >> 8); | ||
| 1561 | const x23 = cast(u8, (x22 & cast(u64, 0xff))); | ||
| 1562 | const x24 = (x22 >> 8); | ||
| 1563 | const x25 = cast(u8, (x24 & cast(u64, 0xff))); | ||
| 1564 | const x26 = (x24 >> 8); | ||
| 1565 | const x27 = cast(u8, (x26 & cast(u64, 0xff))); | ||
| 1566 | const x28 = (x26 >> 8); | ||
| 1567 | const x29 = cast(u8, (x28 & cast(u64, 0xff))); | ||
| 1568 | const x30 = (x28 >> 8); | ||
| 1569 | const x31 = cast(u8, (x30 & cast(u64, 0xff))); | ||
| 1570 | const x32 = cast(u8, (x30 >> 8)); | ||
| 1571 | const x33 = cast(u8, (x2 & cast(u64, 0xff))); | ||
| 1572 | const x34 = (x2 >> 8); | ||
| 1573 | const x35 = cast(u8, (x34 & cast(u64, 0xff))); | ||
| 1574 | const x36 = (x34 >> 8); | ||
| 1575 | const x37 = cast(u8, (x36 & cast(u64, 0xff))); | ||
| 1576 | const x38 = (x36 >> 8); | ||
| 1577 | const x39 = cast(u8, (x38 & cast(u64, 0xff))); | ||
| 1578 | const x40 = (x38 >> 8); | ||
| 1579 | const x41 = cast(u8, (x40 & cast(u64, 0xff))); | ||
| 1580 | const x42 = (x40 >> 8); | ||
| 1581 | const x43 = cast(u8, (x42 & cast(u64, 0xff))); | ||
| 1582 | const x44 = (x42 >> 8); | ||
| 1583 | const x45 = cast(u8, (x44 & cast(u64, 0xff))); | ||
| 1584 | const x46 = cast(u8, (x44 >> 8)); | ||
| 1585 | const x47 = cast(u8, (x1 & cast(u64, 0xff))); | ||
| 1586 | const x48 = (x1 >> 8); | ||
| 1587 | const x49 = cast(u8, (x48 & cast(u64, 0xff))); | ||
| 1588 | const x50 = (x48 >> 8); | ||
| 1589 | const x51 = cast(u8, (x50 & cast(u64, 0xff))); | ||
| 1590 | const x52 = (x50 >> 8); | ||
| 1591 | const x53 = cast(u8, (x52 & cast(u64, 0xff))); | ||
| 1592 | const x54 = (x52 >> 8); | ||
| 1593 | const x55 = cast(u8, (x54 & cast(u64, 0xff))); | ||
| 1594 | const x56 = (x54 >> 8); | ||
| 1595 | const x57 = cast(u8, (x56 & cast(u64, 0xff))); | ||
| 1596 | const x58 = (x56 >> 8); | ||
| 1597 | const x59 = cast(u8, (x58 & cast(u64, 0xff))); | ||
| 1598 | const x60 = cast(u8, (x58 >> 8)); | ||
| 1599 | out1[0] = x5; | ||
| 1600 | out1[1] = x7; | ||
| 1601 | out1[2] = x9; | ||
| 1602 | out1[3] = x11; | ||
| 1603 | out1[4] = x13; | ||
| 1604 | out1[5] = x15; | ||
| 1605 | out1[6] = x17; | ||
| 1606 | out1[7] = x18; | ||
| 1607 | out1[8] = x19; | ||
| 1608 | out1[9] = x21; | ||
| 1609 | out1[10] = x23; | ||
| 1610 | out1[11] = x25; | ||
| 1611 | out1[12] = x27; | ||
| 1612 | out1[13] = x29; | ||
| 1613 | out1[14] = x31; | ||
| 1614 | out1[15] = x32; | ||
| 1615 | out1[16] = x33; | ||
| 1616 | out1[17] = x35; | ||
| 1617 | out1[18] = x37; | ||
| 1618 | out1[19] = x39; | ||
| 1619 | out1[20] = x41; | ||
| 1620 | out1[21] = x43; | ||
| 1621 | out1[22] = x45; | ||
| 1622 | out1[23] = x46; | ||
| 1623 | out1[24] = x47; | ||
| 1624 | out1[25] = x49; | ||
| 1625 | out1[26] = x51; | ||
| 1626 | out1[27] = x53; | ||
| 1627 | out1[28] = x55; | ||
| 1628 | out1[29] = x57; | ||
| 1629 | out1[30] = x59; | ||
| 1630 | out1[31] = x60; | ||
| 1631 | } | ||
| 1632 | |||
| 1633 | /// The function fromBytes deserializes a field element NOT in the Montgomery domain from bytes in little-endian order. | ||
| 1634 | /// Preconditions: | ||
| 1635 | /// 0 ≤ bytes_eval arg1 < m | ||
| 1636 | /// Postconditions: | ||
| 1637 | /// eval out1 mod m = bytes_eval arg1 mod m | ||
| 1638 | /// 0 ≤ eval out1 < m | ||
| 1639 | /// | ||
| 1640 | /// Input Bounds: | ||
| 1641 | /// arg1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff]] | ||
| 1642 | /// Output Bounds: | ||
| 1643 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 1644 | pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void { | ||
| 1645 | @setRuntimeSafety(mode == .Debug); | ||
| 1646 | |||
| 1647 | const x1 = (cast(u64, (arg1[31])) << 56); | ||
| 1648 | const x2 = (cast(u64, (arg1[30])) << 48); | ||
| 1649 | const x3 = (cast(u64, (arg1[29])) << 40); | ||
| 1650 | const x4 = (cast(u64, (arg1[28])) << 32); | ||
| 1651 | const x5 = (cast(u64, (arg1[27])) << 24); | ||
| 1652 | const x6 = (cast(u64, (arg1[26])) << 16); | ||
| 1653 | const x7 = (cast(u64, (arg1[25])) << 8); | ||
| 1654 | const x8 = (arg1[24]); | ||
| 1655 | const x9 = (cast(u64, (arg1[23])) << 56); | ||
| 1656 | const x10 = (cast(u64, (arg1[22])) << 48); | ||
| 1657 | const x11 = (cast(u64, (arg1[21])) << 40); | ||
| 1658 | const x12 = (cast(u64, (arg1[20])) << 32); | ||
| 1659 | const x13 = (cast(u64, (arg1[19])) << 24); | ||
| 1660 | const x14 = (cast(u64, (arg1[18])) << 16); | ||
| 1661 | const x15 = (cast(u64, (arg1[17])) << 8); | ||
| 1662 | const x16 = (arg1[16]); | ||
| 1663 | const x17 = (cast(u64, (arg1[15])) << 56); | ||
| 1664 | const x18 = (cast(u64, (arg1[14])) << 48); | ||
| 1665 | const x19 = (cast(u64, (arg1[13])) << 40); | ||
| 1666 | const x20 = (cast(u64, (arg1[12])) << 32); | ||
| 1667 | const x21 = (cast(u64, (arg1[11])) << 24); | ||
| 1668 | const x22 = (cast(u64, (arg1[10])) << 16); | ||
| 1669 | const x23 = (cast(u64, (arg1[9])) << 8); | ||
| 1670 | const x24 = (arg1[8]); | ||
| 1671 | const x25 = (cast(u64, (arg1[7])) << 56); | ||
| 1672 | const x26 = (cast(u64, (arg1[6])) << 48); | ||
| 1673 | const x27 = (cast(u64, (arg1[5])) << 40); | ||
| 1674 | const x28 = (cast(u64, (arg1[4])) << 32); | ||
| 1675 | const x29 = (cast(u64, (arg1[3])) << 24); | ||
| 1676 | const x30 = (cast(u64, (arg1[2])) << 16); | ||
| 1677 | const x31 = (cast(u64, (arg1[1])) << 8); | ||
| 1678 | const x32 = (arg1[0]); | ||
| 1679 | const x33 = (x31 + cast(u64, x32)); | ||
| 1680 | const x34 = (x30 + x33); | ||
| 1681 | const x35 = (x29 + x34); | ||
| 1682 | const x36 = (x28 + x35); | ||
| 1683 | const x37 = (x27 + x36); | ||
| 1684 | const x38 = (x26 + x37); | ||
| 1685 | const x39 = (x25 + x38); | ||
| 1686 | const x40 = (x23 + cast(u64, x24)); | ||
| 1687 | const x41 = (x22 + x40); | ||
| 1688 | const x42 = (x21 + x41); | ||
| 1689 | const x43 = (x20 + x42); | ||
| 1690 | const x44 = (x19 + x43); | ||
| 1691 | const x45 = (x18 + x44); | ||
| 1692 | const x46 = (x17 + x45); | ||
| 1693 | const x47 = (x15 + cast(u64, x16)); | ||
| 1694 | const x48 = (x14 + x47); | ||
| 1695 | const x49 = (x13 + x48); | ||
| 1696 | const x50 = (x12 + x49); | ||
| 1697 | const x51 = (x11 + x50); | ||
| 1698 | const x52 = (x10 + x51); | ||
| 1699 | const x53 = (x9 + x52); | ||
| 1700 | const x54 = (x7 + cast(u64, x8)); | ||
| 1701 | const x55 = (x6 + x54); | ||
| 1702 | const x56 = (x5 + x55); | ||
| 1703 | const x57 = (x4 + x56); | ||
| 1704 | const x58 = (x3 + x57); | ||
| 1705 | const x59 = (x2 + x58); | ||
| 1706 | const x60 = (x1 + x59); | ||
| 1707 | out1[0] = x39; | ||
| 1708 | out1[1] = x46; | ||
| 1709 | out1[2] = x53; | ||
| 1710 | out1[3] = x60; | ||
| 1711 | } | ||
| 1712 | |||
| 1713 | /// The function setOne returns the field element one in the Montgomery domain. | ||
| 1714 | /// Postconditions: | ||
| 1715 | /// eval (from_montgomery out1) mod m = 1 mod m | ||
| 1716 | /// 0 ≤ eval out1 < m | ||
| 1717 | /// | ||
| 1718 | /// Input Bounds: | ||
| 1719 | /// Output Bounds: | ||
| 1720 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 1721 | pub fn setOne(out1: *[4]u64) void { | ||
| 1722 | @setRuntimeSafety(mode == .Debug); | ||
| 1723 | |||
| 1724 | out1[0] = 0xc46353d039cdaaf; | ||
| 1725 | out1[1] = 0x4319055258e8617b; | ||
| 1726 | out1[2] = cast(u64, 0x0); | ||
| 1727 | out1[3] = 0xffffffff; | ||
| 1728 | } | ||
| 1729 | |||
| 1730 | /// The function msat returns the saturated representation of the prime modulus. | ||
| 1731 | /// Postconditions: | ||
| 1732 | /// twos_complement_eval out1 = m | ||
| 1733 | /// 0 ≤ eval out1 < m | ||
| 1734 | /// | ||
| 1735 | /// Input Bounds: | ||
| 1736 | /// Output Bounds: | ||
| 1737 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 1738 | pub fn msat(out1: *[5]u64) void { | ||
| 1739 | @setRuntimeSafety(mode == .Debug); | ||
| 1740 | |||
| 1741 | out1[0] = 0xf3b9cac2fc632551; | ||
| 1742 | out1[1] = 0xbce6faada7179e84; | ||
| 1743 | out1[2] = 0xffffffffffffffff; | ||
| 1744 | out1[3] = 0xffffffff00000000; | ||
| 1745 | out1[4] = cast(u64, 0x0); | ||
| 1746 | } | ||
| 1747 | |||
| 1748 | /// The function divstepPrecomp returns the precomputed value for Bernstein-Yang-inversion (in montgomery form). | ||
| 1749 | /// Postconditions: | ||
| 1750 | /// eval (from_montgomery out1) = ⌊(m - 1) / 2⌋^(if (log2 m) + 1 < 46 then ⌊(49 * ((log2 m) + 1) + 80) / 17⌋ else ⌊(49 * ((log2 m) + 1) + 57) / 17⌋) | ||
| 1751 | /// 0 ≤ eval out1 < m | ||
| 1752 | /// | ||
| 1753 | /// Input Bounds: | ||
| 1754 | /// Output Bounds: | ||
| 1755 | /// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 1756 | pub fn divstepPrecomp(out1: *[4]u64) void { | ||
| 1757 | @setRuntimeSafety(mode == .Debug); | ||
| 1758 | |||
| 1759 | out1[0] = 0xd739262fb7fcfbb5; | ||
| 1760 | out1[1] = 0x8ac6f75d20074414; | ||
| 1761 | out1[2] = 0xc67428bfb5e3c256; | ||
| 1762 | out1[3] = 0x444962f2eda7aedf; | ||
| 1763 | } | ||
| 1764 | |||
| 1765 | /// The function divstep computes a divstep. | ||
| 1766 | /// Preconditions: | ||
| 1767 | /// 0 ≤ eval arg4 < m | ||
| 1768 | /// 0 ≤ eval arg5 < m | ||
| 1769 | /// Postconditions: | ||
| 1770 | /// out1 = (if 0 < arg1 ∧ (twos_complement_eval arg3) is odd then 1 - arg1 else 1 + arg1) | ||
| 1771 | /// twos_complement_eval out2 = (if 0 < arg1 ∧ (twos_complement_eval arg3) is odd then twos_complement_eval arg3 else twos_complement_eval arg2) | ||
| 1772 | /// twos_complement_eval out3 = (if 0 < arg1 ∧ (twos_complement_eval arg3) is odd then ⌊(twos_complement_eval arg3 - twos_complement_eval arg2) / 2⌋ else ⌊(twos_complement_eval arg3 + (twos_complement_eval arg3 mod 2) * twos_complement_eval arg2) / 2⌋) | ||
| 1773 | /// eval (from_montgomery out4) mod m = (if 0 < arg1 ∧ (twos_complement_eval arg3) is odd then (2 * eval (from_montgomery arg5)) mod m else (2 * eval (from_montgomery arg4)) mod m) | ||
| 1774 | /// eval (from_montgomery out5) mod m = (if 0 < arg1 ∧ (twos_complement_eval arg3) is odd then (eval (from_montgomery arg4) - eval (from_montgomery arg4)) mod m else (eval (from_montgomery arg5) + (twos_complement_eval arg3 mod 2) * eval (from_montgomery arg4)) mod m) | ||
| 1775 | /// 0 ≤ eval out5 < m | ||
| 1776 | /// 0 ≤ eval out5 < m | ||
| 1777 | /// 0 ≤ eval out2 < m | ||
| 1778 | /// 0 ≤ eval out3 < m | ||
| 1779 | /// | ||
| 1780 | /// Input Bounds: | ||
| 1781 | /// arg1: [0x0 ~> 0xffffffffffffffff] | ||
| 1782 | /// arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 1783 | /// arg3: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 1784 | /// arg4: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 1785 | /// arg5: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 1786 | /// Output Bounds: | ||
| 1787 | /// out1: [0x0 ~> 0xffffffffffffffff] | ||
| 1788 | /// out2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 1789 | /// out3: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 1790 | /// out4: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 1791 | /// out5: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]] | ||
| 1792 | 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 { | ||
| 1793 | @setRuntimeSafety(mode == .Debug); | ||
| 1794 | |||
| 1795 | var x1: u64 = undefined; | ||
| 1796 | var x2: u1 = undefined; | ||
| 1797 | addcarryxU64(&x1, &x2, 0x0, (~arg1), cast(u64, 0x1)); | ||
| 1798 | const x3 = (cast(u1, (x1 >> 63)) & cast(u1, ((arg3[0]) & cast(u64, 0x1)))); | ||
| 1799 | var x4: u64 = undefined; | ||
| 1800 | var x5: u1 = undefined; | ||
| 1801 | addcarryxU64(&x4, &x5, 0x0, (~arg1), cast(u64, 0x1)); | ||
| 1802 | var x6: u64 = undefined; | ||
| 1803 | cmovznzU64(&x6, x3, arg1, x4); | ||
| 1804 | var x7: u64 = undefined; | ||
| 1805 | cmovznzU64(&x7, x3, (arg2[0]), (arg3[0])); | ||
| 1806 | var x8: u64 = undefined; | ||
| 1807 | cmovznzU64(&x8, x3, (arg2[1]), (arg3[1])); | ||
| 1808 | var x9: u64 = undefined; | ||
| 1809 | cmovznzU64(&x9, x3, (arg2[2]), (arg3[2])); | ||
| 1810 | var x10: u64 = undefined; | ||
| 1811 | cmovznzU64(&x10, x3, (arg2[3]), (arg3[3])); | ||
| 1812 | var x11: u64 = undefined; | ||
| 1813 | cmovznzU64(&x11, x3, (arg2[4]), (arg3[4])); | ||
| 1814 | var x12: u64 = undefined; | ||
| 1815 | var x13: u1 = undefined; | ||
| 1816 | addcarryxU64(&x12, &x13, 0x0, cast(u64, 0x1), (~(arg2[0]))); | ||
| 1817 | var x14: u64 = undefined; | ||
| 1818 | var x15: u1 = undefined; | ||
| 1819 | addcarryxU64(&x14, &x15, x13, cast(u64, 0x0), (~(arg2[1]))); | ||
| 1820 | var x16: u64 = undefined; | ||
| 1821 | var x17: u1 = undefined; | ||
| 1822 | addcarryxU64(&x16, &x17, x15, cast(u64, 0x0), (~(arg2[2]))); | ||
| 1823 | var x18: u64 = undefined; | ||
| 1824 | var x19: u1 = undefined; | ||
| 1825 | addcarryxU64(&x18, &x19, x17, cast(u64, 0x0), (~(arg2[3]))); | ||
| 1826 | var x20: u64 = undefined; | ||
| 1827 | var x21: u1 = undefined; | ||
| 1828 | addcarryxU64(&x20, &x21, x19, cast(u64, 0x0), (~(arg2[4]))); | ||
| 1829 | var x22: u64 = undefined; | ||
| 1830 | cmovznzU64(&x22, x3, (arg3[0]), x12); | ||
| 1831 | var x23: u64 = undefined; | ||
| 1832 | cmovznzU64(&x23, x3, (arg3[1]), x14); | ||
| 1833 | var x24: u64 = undefined; | ||
| 1834 | cmovznzU64(&x24, x3, (arg3[2]), x16); | ||
| 1835 | var x25: u64 = undefined; | ||
| 1836 | cmovznzU64(&x25, x3, (arg3[3]), x18); | ||
| 1837 | var x26: u64 = undefined; | ||
| 1838 | cmovznzU64(&x26, x3, (arg3[4]), x20); | ||
| 1839 | var x27: u64 = undefined; | ||
| 1840 | cmovznzU64(&x27, x3, (arg4[0]), (arg5[0])); | ||
| 1841 | var x28: u64 = undefined; | ||
| 1842 | cmovznzU64(&x28, x3, (arg4[1]), (arg5[1])); | ||
| 1843 | var x29: u64 = undefined; | ||
| 1844 | cmovznzU64(&x29, x3, (arg4[2]), (arg5[2])); | ||
| 1845 | var x30: u64 = undefined; | ||
| 1846 | cmovznzU64(&x30, x3, (arg4[3]), (arg5[3])); | ||
| 1847 | var x31: u64 = undefined; | ||
| 1848 | var x32: u1 = undefined; | ||
| 1849 | addcarryxU64(&x31, &x32, 0x0, x27, x27); | ||
| 1850 | var x33: u64 = undefined; | ||
| 1851 | var x34: u1 = undefined; | ||
| 1852 | addcarryxU64(&x33, &x34, x32, x28, x28); | ||
| 1853 | var x35: u64 = undefined; | ||
| 1854 | var x36: u1 = undefined; | ||
| 1855 | addcarryxU64(&x35, &x36, x34, x29, x29); | ||
| 1856 | var x37: u64 = undefined; | ||
| 1857 | var x38: u1 = undefined; | ||
| 1858 | addcarryxU64(&x37, &x38, x36, x30, x30); | ||
| 1859 | var x39: u64 = undefined; | ||
| 1860 | var x40: u1 = undefined; | ||
| 1861 | subborrowxU64(&x39, &x40, 0x0, x31, 0xf3b9cac2fc632551); | ||
| 1862 | var x41: u64 = undefined; | ||
| 1863 | var x42: u1 = undefined; | ||
| 1864 | subborrowxU64(&x41, &x42, x40, x33, 0xbce6faada7179e84); | ||
| 1865 | var x43: u64 = undefined; | ||
| 1866 | var x44: u1 = undefined; | ||
| 1867 | subborrowxU64(&x43, &x44, x42, x35, 0xffffffffffffffff); | ||
| 1868 | var x45: u64 = undefined; | ||
| 1869 | var x46: u1 = undefined; | ||
| 1870 | subborrowxU64(&x45, &x46, x44, x37, 0xffffffff00000000); | ||
| 1871 | var x47: u64 = undefined; | ||
| 1872 | var x48: u1 = undefined; | ||
| 1873 | subborrowxU64(&x47, &x48, x46, cast(u64, x38), cast(u64, 0x0)); | ||
| 1874 | const x49 = (arg4[3]); | ||
| 1875 | const x50 = (arg4[2]); | ||
| 1876 | const x51 = (arg4[1]); | ||
| 1877 | const x52 = (arg4[0]); | ||
| 1878 | var x53: u64 = undefined; | ||
| 1879 | var x54: u1 = undefined; | ||
| 1880 | subborrowxU64(&x53, &x54, 0x0, cast(u64, 0x0), x52); | ||
| 1881 | var x55: u64 = undefined; | ||
| 1882 | var x56: u1 = undefined; | ||
| 1883 | subborrowxU64(&x55, &x56, x54, cast(u64, 0x0), x51); | ||
| 1884 | var x57: u64 = undefined; | ||
| 1885 | var x58: u1 = undefined; | ||
| 1886 | subborrowxU64(&x57, &x58, x56, cast(u64, 0x0), x50); | ||
| 1887 | var x59: u64 = undefined; | ||
| 1888 | var x60: u1 = undefined; | ||
| 1889 | subborrowxU64(&x59, &x60, x58, cast(u64, 0x0), x49); | ||
| 1890 | var x61: u64 = undefined; | ||
| 1891 | cmovznzU64(&x61, x60, cast(u64, 0x0), 0xffffffffffffffff); | ||
| 1892 | var x62: u64 = undefined; | ||
| 1893 | var x63: u1 = undefined; | ||
| 1894 | addcarryxU64(&x62, &x63, 0x0, x53, (x61 & 0xf3b9cac2fc632551)); | ||
| 1895 | var x64: u64 = undefined; | ||
| 1896 | var x65: u1 = undefined; | ||
| 1897 | addcarryxU64(&x64, &x65, x63, x55, (x61 & 0xbce6faada7179e84)); | ||
| 1898 | var x66: u64 = undefined; | ||
| 1899 | var x67: u1 = undefined; | ||
| 1900 | addcarryxU64(&x66, &x67, x65, x57, x61); | ||
| 1901 | var x68: u64 = undefined; | ||
| 1902 | var x69: u1 = undefined; | ||
| 1903 | addcarryxU64(&x68, &x69, x67, x59, (x61 & 0xffffffff00000000)); | ||
| 1904 | var x70: u64 = undefined; | ||
| 1905 | cmovznzU64(&x70, x3, (arg5[0]), x62); | ||
| 1906 | var x71: u64 = undefined; | ||
| 1907 | cmovznzU64(&x71, x3, (arg5[1]), x64); | ||
| 1908 | var x72: u64 = undefined; | ||
| 1909 | cmovznzU64(&x72, x3, (arg5[2]), x66); | ||
| 1910 | var x73: u64 = undefined; | ||
| 1911 | cmovznzU64(&x73, x3, (arg5[3]), x68); | ||
| 1912 | const x74 = cast(u1, (x22 & cast(u64, 0x1))); | ||
| 1913 | var x75: u64 = undefined; | ||
| 1914 | cmovznzU64(&x75, x74, cast(u64, 0x0), x7); | ||
| 1915 | var x76: u64 = undefined; | ||
| 1916 | cmovznzU64(&x76, x74, cast(u64, 0x0), x8); | ||
| 1917 | var x77: u64 = undefined; | ||
| 1918 | cmovznzU64(&x77, x74, cast(u64, 0x0), x9); | ||
| 1919 | var x78: u64 = undefined; | ||
| 1920 | cmovznzU64(&x78, x74, cast(u64, 0x0), x10); | ||
| 1921 | var x79: u64 = undefined; | ||
| 1922 | cmovznzU64(&x79, x74, cast(u64, 0x0), x11); | ||
| 1923 | var x80: u64 = undefined; | ||
| 1924 | var x81: u1 = undefined; | ||
| 1925 | addcarryxU64(&x80, &x81, 0x0, x22, x75); | ||
| 1926 | var x82: u64 = undefined; | ||
| 1927 | var x83: u1 = undefined; | ||
| 1928 | addcarryxU64(&x82, &x83, x81, x23, x76); | ||
| 1929 | var x84: u64 = undefined; | ||
| 1930 | var x85: u1 = undefined; | ||
| 1931 | addcarryxU64(&x84, &x85, x83, x24, x77); | ||
| 1932 | var x86: u64 = undefined; | ||
| 1933 | var x87: u1 = undefined; | ||
| 1934 | addcarryxU64(&x86, &x87, x85, x25, x78); | ||
| 1935 | var x88: u64 = undefined; | ||
| 1936 | var x89: u1 = undefined; | ||
| 1937 | addcarryxU64(&x88, &x89, x87, x26, x79); | ||
| 1938 | var x90: u64 = undefined; | ||
| 1939 | cmovznzU64(&x90, x74, cast(u64, 0x0), x27); | ||
| 1940 | var x91: u64 = undefined; | ||
| 1941 | cmovznzU64(&x91, x74, cast(u64, 0x0), x28); | ||
| 1942 | var x92: u64 = undefined; | ||
| 1943 | cmovznzU64(&x92, x74, cast(u64, 0x0), x29); | ||
| 1944 | var x93: u64 = undefined; | ||
| 1945 | cmovznzU64(&x93, x74, cast(u64, 0x0), x30); | ||
| 1946 | var x94: u64 = undefined; | ||
| 1947 | var x95: u1 = undefined; | ||
| 1948 | addcarryxU64(&x94, &x95, 0x0, x70, x90); | ||
| 1949 | var x96: u64 = undefined; | ||
| 1950 | var x97: u1 = undefined; | ||
| 1951 | addcarryxU64(&x96, &x97, x95, x71, x91); | ||
| 1952 | var x98: u64 = undefined; | ||
| 1953 | var x99: u1 = undefined; | ||
| 1954 | addcarryxU64(&x98, &x99, x97, x72, x92); | ||
| 1955 | var x100: u64 = undefined; | ||
| 1956 | var x101: u1 = undefined; | ||
| 1957 | addcarryxU64(&x100, &x101, x99, x73, x93); | ||
| 1958 | var x102: u64 = undefined; | ||
| 1959 | var x103: u1 = undefined; | ||
| 1960 | subborrowxU64(&x102, &x103, 0x0, x94, 0xf3b9cac2fc632551); | ||
| 1961 | var x104: u64 = undefined; | ||
| 1962 | var x105: u1 = undefined; | ||
| 1963 | subborrowxU64(&x104, &x105, x103, x96, 0xbce6faada7179e84); | ||
| 1964 | var x106: u64 = undefined; | ||
| 1965 | var x107: u1 = undefined; | ||
| 1966 | subborrowxU64(&x106, &x107, x105, x98, 0xffffffffffffffff); | ||
| 1967 | var x108: u64 = undefined; | ||
| 1968 | var x109: u1 = undefined; | ||
| 1969 | subborrowxU64(&x108, &x109, x107, x100, 0xffffffff00000000); | ||
| 1970 | var x110: u64 = undefined; | ||
| 1971 | var x111: u1 = undefined; | ||
| 1972 | subborrowxU64(&x110, &x111, x109, cast(u64, x101), cast(u64, 0x0)); | ||
| 1973 | var x112: u64 = undefined; | ||
| 1974 | var x113: u1 = undefined; | ||
| 1975 | addcarryxU64(&x112, &x113, 0x0, x6, cast(u64, 0x1)); | ||
| 1976 | const x114 = ((x80 >> 1) | ((x82 << 63) & 0xffffffffffffffff)); | ||
| 1977 | const x115 = ((x82 >> 1) | ((x84 << 63) & 0xffffffffffffffff)); | ||
| 1978 | const x116 = ((x84 >> 1) | ((x86 << 63) & 0xffffffffffffffff)); | ||
| 1979 | const x117 = ((x86 >> 1) | ((x88 << 63) & 0xffffffffffffffff)); | ||
| 1980 | const x118 = ((x88 & 0x8000000000000000) | (x88 >> 1)); | ||
| 1981 | var x119: u64 = undefined; | ||
| 1982 | cmovznzU64(&x119, x48, x39, x31); | ||
| 1983 | var x120: u64 = undefined; | ||
| 1984 | cmovznzU64(&x120, x48, x41, x33); | ||
| 1985 | var x121: u64 = undefined; | ||
| 1986 | cmovznzU64(&x121, x48, x43, x35); | ||
| 1987 | var x122: u64 = undefined; | ||
| 1988 | cmovznzU64(&x122, x48, x45, x37); | ||
| 1989 | var x123: u64 = undefined; | ||
| 1990 | cmovznzU64(&x123, x111, x102, x94); | ||
| 1991 | var x124: u64 = undefined; | ||
| 1992 | cmovznzU64(&x124, x111, x104, x96); | ||
| 1993 | var x125: u64 = undefined; | ||
| 1994 | cmovznzU64(&x125, x111, x106, x98); | ||
| 1995 | var x126: u64 = undefined; | ||
| 1996 | cmovznzU64(&x126, x111, x108, x100); | ||
| 1997 | out1.* = x112; | ||
| 1998 | out2[0] = x7; | ||
| 1999 | out2[1] = x8; | ||
| 2000 | out2[2] = x9; | ||
| 2001 | out2[3] = x10; | ||
| 2002 | out2[4] = x11; | ||
| 2003 | out3[0] = x114; | ||
| 2004 | out3[1] = x115; | ||
| 2005 | out3[2] = x116; | ||
| 2006 | out3[3] = x117; | ||
| 2007 | out3[4] = x118; | ||
| 2008 | out4[0] = x119; | ||
| 2009 | out4[1] = x120; | ||
| 2010 | out4[2] = x121; | ||
| 2011 | out4[3] = x122; | ||
| 2012 | out5[0] = x123; | ||
| 2013 | out5[1] = x124; | ||
| 2014 | out5[2] = x125; | ||
| 2015 | out5[3] = x126; | ||
| 2016 | } | ||
lib/std/crypto/pcurves/p256/scalar.zig created+231| ... | @@ -0,0 +1,231 @@ | ||
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2021 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 6 | |||
| 7 | const std = @import("std"); | ||
| 8 | const builtin = std.builtin; | ||
| 9 | const common = @import("../common.zig"); | ||
| 10 | const crypto = std.crypto; | ||
| 11 | const debug = std.debug; | ||
| 12 | const math = std.math; | ||
| 13 | const mem = std.mem; | ||
| 14 | |||
| 15 | const Field = common.Field; | ||
| 16 | |||
| 17 | const NonCanonicalError = std.crypto.errors.NonCanonicalError; | ||
| 18 | const NotSquareError = std.crypto.errors.NotSquareError; | ||
| 19 | |||
| 20 | /// Number of bytes required to encode a scalar. | ||
| 21 | pub const encoded_length = 32; | ||
| 22 | |||
| 23 | /// A compressed scalar, in canonical form. | ||
| 24 | pub const CompressedScalar = [encoded_length]u8; | ||
| 25 | |||
| 26 | const Fe = Field(.{ | ||
| 27 | .fiat = @import("p256_scalar_64.zig"), | ||
| 28 | .field_order = 115792089210356248762697446949407573529996955224135760342422259061068512044369, | ||
| 29 | .field_bits = 256, | ||
| 30 | .saturated_bits = 255, | ||
| 31 | .encoded_length = encoded_length, | ||
| 32 | }); | ||
| 33 | |||
| 34 | /// Reject a scalar whose encoding is not canonical. | ||
| 35 | pub fn rejectNonCanonical(s: CompressedScalar, endian: builtin.Endian) NonCanonicalError!void { | ||
| 36 | return Fe.rejectNonCanonical(s, endian); | ||
| 37 | } | ||
| 38 | |||
| 39 | /// Reduce a 48-bytes scalar to the field size. | ||
| 40 | pub fn reduce48(s: [48]u8, endian: builtin.Endian) CompressedScalar { | ||
| 41 | return Scalar.fromBytes48(s, endian).toBytes(endian); | ||
| 42 | } | ||
| 43 | |||
| 44 | /// Reduce a 64-bytes scalar to the field size. | ||
| 45 | pub fn reduce64(s: [64]u8, endian: builtin.Endian) CompressedScalar { | ||
| 46 | return ScalarDouble.fromBytes64(s, endian).toBytes(endian); | ||
| 47 | } | ||
| 48 | |||
| 49 | /// Return a*b (mod L) | ||
| 50 | pub fn mul(a: CompressedScalar, b: CompressedScalar, endian: builtin.Endian) NonCanonicalError!CompressedScalar { | ||
| 51 | return (try Scalar.fromBytes(a, endian)).mul(try Scalar.fromBytes(b, endian)).toBytes(endian); | ||
| 52 | } | ||
| 53 | |||
| 54 | /// Return a*b+c (mod L) | ||
| 55 | pub fn mulAdd(a: CompressedScalar, b: CompressedScalar, c: CompressedScalar, endian: builtin.Endian) NonCanonicalError!CompressedScalar { | ||
| 56 | return (try Scalar.fromBytes(a, endian)).mul(try Scalar.fromBytes(b, endian)).add(try Scalar.fromBytes(c, endian)).toBytes(endian); | ||
| 57 | } | ||
| 58 | |||
| 59 | /// Return a+b (mod L) | ||
| 60 | pub fn add(a: CompressedScalar, b: CompressedScalar, endian: builtin.Endian) NonCanonicalError!CompressedScalar { | ||
| 61 | return (try Scalar.fromBytes(a, endian)).add(try Scalar.fromBytes(b, endian)).toBytes(endian); | ||
| 62 | } | ||
| 63 | |||
| 64 | /// Return -s (mod L) | ||
| 65 | pub fn neg(s: CompressedScalar, endian: builtin.Endian) NonCanonicalError!CompressedScalar { | ||
| 66 | return (try Scalar.fromBytes(a, endian)).neg().toBytes(endian); | ||
| 67 | } | ||
| 68 | |||
| 69 | /// Return (a-b) (mod L) | ||
| 70 | pub fn sub(a: CompressedScalar, b: CompressedScalar, endian: builtin.Endian) NonCanonicalError!CompressedScalar { | ||
| 71 | return (try Scalar.fromBytes(a, endian)).sub(try Scalar.fromBytes(b.endian)).toBytes(endian); | ||
| 72 | } | ||
| 73 | |||
| 74 | /// Return a random scalar | ||
| 75 | pub fn random(endian: builtin.Endian) CompressedScalar { | ||
| 76 | return Scalar.random().toBytes(endian); | ||
| 77 | } | ||
| 78 | |||
| 79 | /// A scalar in unpacked representation. | ||
| 80 | pub const Scalar = struct { | ||
| 81 | fe: Fe, | ||
| 82 | |||
| 83 | /// Zero. | ||
| 84 | pub const zero = Scalar{ .fe = Fe.zero }; | ||
| 85 | |||
| 86 | /// One. | ||
| 87 | pub const one = Scalar{ .fe = Fe.one }; | ||
| 88 | |||
| 89 | /// Unpack a serialized representation of a scalar. | ||
| 90 | pub fn fromBytes(s: CompressedScalar, endian: builtin.Endian) NonCanonicalError!Scalar { | ||
| 91 | return Scalar{ .fe = try Fe.fromBytes(s, endian) }; | ||
| 92 | } | ||
| 93 | |||
| 94 | /// Reduce a 384 bit input to the field size. | ||
| 95 | pub fn fromBytes48(s: [48]u8, endian: builtin.Endian) Scalar { | ||
| 96 | const t = ScalarDouble.fromBytes(384, s, endian); | ||
| 97 | return t.reduce(384); | ||
| 98 | } | ||
| 99 | |||
| 100 | /// Reduce a 512 bit input to the field size. | ||
| 101 | pub fn fromBytes64(s: [64]u8, endian: builtin.Endian) Scalar { | ||
| 102 | const t = ScalarDouble.fromBytes(512, s, endian); | ||
| 103 | return t.reduce(512); | ||
| 104 | } | ||
| 105 | |||
| 106 | /// Pack a scalar into bytes. | ||
| 107 | pub fn toBytes(n: Scalar, endian: builtin.Endian) CompressedScalar { | ||
| 108 | return n.fe.toBytes(endian); | ||
| 109 | } | ||
| 110 | |||
| 111 | /// Return true if the scalar is zero.. | ||
| 112 | pub fn isZero(n: Scalar) bool { | ||
| 113 | return n.fe.isZero(); | ||
| 114 | } | ||
| 115 | |||
| 116 | /// Return true if a and b are equivalent. | ||
| 117 | pub fn equivalent(a: Scalar, b: Scalar) bool { | ||
| 118 | return a.fe.equivalent(b.fe); | ||
| 119 | } | ||
| 120 | |||
| 121 | /// Compute x+y (mod L) | ||
| 122 | pub fn add(x: Scalar, y: Scalar) Scalar { | ||
| 123 | return Scalar{ .fe = x.fe().add(y.fe) }; | ||
| 124 | } | ||
| 125 | |||
| 126 | /// Compute x-y (mod L) | ||
| 127 | pub fn sub(x: Scalar, y: Scalar) Scalar { | ||
| 128 | return Scalar{ .fe = x.fe().sub(y.fe) }; | ||
| 129 | } | ||
| 130 | |||
| 131 | /// Compute 2n (mod L) | ||
| 132 | pub fn dbl(n: Scalar) Scalar { | ||
| 133 | return Scalar{ .fe = n.fe.dbl() }; | ||
| 134 | } | ||
| 135 | |||
| 136 | /// Compute x*y (mod L) | ||
| 137 | pub fn mul(x: Scalar, y: Scalar) Scalar { | ||
| 138 | return Scalar{ .fe = x.fe().mul(y.fe) }; | ||
| 139 | } | ||
| 140 | |||
| 141 | /// Compute x^2 (mod L) | ||
| 142 | pub fn sq(n: Scalar) Scalar { | ||
| 143 | return Scalar{ .fe = n.fe.sq() }; | ||
| 144 | } | ||
| 145 | |||
| 146 | /// Compute x^n (mod L) | ||
| 147 | pub fn pow(a: Scalar, comptime T: type, comptime n: T) Scalar { | ||
| 148 | return Scalar{ .fe = a.fe.pow(n) }; | ||
| 149 | } | ||
| 150 | |||
| 151 | /// Compute -x (mod L) | ||
| 152 | pub fn neg(n: Scalar) Scalar { | ||
| 153 | return Scalar{ .fe = n.fe.neg() }; | ||
| 154 | } | ||
| 155 | |||
| 156 | /// Compute x^-1 (mod L) | ||
| 157 | pub fn invert(n: Scalar) Scalar { | ||
| 158 | return Scalar{ .fe = n.fe.invert() }; | ||
| 159 | } | ||
| 160 | |||
| 161 | /// Return true if n is a quadratic residue mod L. | ||
| 162 | pub fn isSquare(n: Scalar) Scalar { | ||
| 163 | return n.fe.isSquare(); | ||
| 164 | } | ||
| 165 | |||
| 166 | /// Return the square root of L, or NotSquare if there isn't any solutions. | ||
| 167 | pub fn sqrt(n: Scalar) NotSquareError!Scalar { | ||
| 168 | return Scalar{ .fe = try n.fe.sqrt() }; | ||
| 169 | } | ||
| 170 | |||
| 171 | /// Return a random scalar < L. | ||
| 172 | pub fn random() Scalar { | ||
| 173 | var s: [48]u8 = undefined; | ||
| 174 | while (true) { | ||
| 175 | crypto.random.bytes(&s); | ||
| 176 | const n = Scalar.fromBytes48(s, .Little); | ||
| 177 | if (!n.isZero()) { | ||
| 178 | return n; | ||
| 179 | } | ||
| 180 | } | ||
| 181 | } | ||
| 182 | }; | ||
| 183 | |||
| 184 | const ScalarDouble = struct { | ||
| 185 | x1: Fe, | ||
| 186 | x2: Fe, | ||
| 187 | x3: Fe, | ||
| 188 | |||
| 189 | fn fromBytes(comptime bits: usize, s_: [bits / 8]u8, endian: builtin.Endian) ScalarDouble { | ||
| 190 | debug.assert(bits > 0 and bits <= 512 and bits >= Fe.saturated_bits and bits <= Fe.saturated_bits * 3); | ||
| 191 | |||
| 192 | var s = s_; | ||
| 193 | if (endian == .Big) { | ||
| 194 | for (s_) |x, i| s[s.len - 1 - i] = x; | ||
| 195 | } | ||
| 196 | var t = ScalarDouble{ .x1 = undefined, .x2 = Fe.zero, .x3 = Fe.zero }; | ||
| 197 | { | ||
| 198 | var b = [_]u8{0} ** encoded_length; | ||
| 199 | const len = math.min(s.len, 24); | ||
| 200 | mem.copy(u8, b[0..len], s[0..len]); | ||
| 201 | t.x1 = Fe.fromBytes(b, .Little) catch unreachable; | ||
| 202 | } | ||
| 203 | if (s_.len >= 24) { | ||
| 204 | var b = [_]u8{0} ** encoded_length; | ||
| 205 | const len = math.min(s.len - 24, 24); | ||
| 206 | mem.copy(u8, b[0..len], s[24..][0..len]); | ||
| 207 | t.x2 = Fe.fromBytes(b, .Little) catch unreachable; | ||
| 208 | } | ||
| 209 | if (s_.len >= 48) { | ||
| 210 | var b = [_]u8{0} ** encoded_length; | ||
| 211 | const len = s.len - 48; | ||
| 212 | mem.copy(u8, b[0..len], s[48..][0..len]); | ||
| 213 | t.x3 = Fe.fromBytes(b, .Little) catch unreachable; | ||
| 214 | } | ||
| 215 | return t; | ||
| 216 | } | ||
| 217 | |||
| 218 | fn reduce(expanded: ScalarDouble, comptime bits: usize) Scalar { | ||
| 219 | debug.assert(bits > 0 and bits <= Fe.saturated_bits * 3 and bits <= 512); | ||
| 220 | var fe = expanded.x1; | ||
| 221 | if (bits >= 192) { | ||
| 222 | const st1 = Fe.fromInt(1 << 192) catch unreachable; | ||
| 223 | fe = fe.add(expanded.x2.mul(st1)); | ||
| 224 | if (bits >= 384) { | ||
| 225 | const st2 = st1.sq(); | ||
| 226 | fe = fe.add(expanded.x3.mul(st2)); | ||
| 227 | } | ||
| 228 | } | ||
| 229 | return Scalar{ .fe = fe }; | ||
| 230 | } | ||
| 231 | }; | ||
lib/std/crypto/pcurves/tests.zig created+103| ... | @@ -0,0 +1,103 @@ | ||
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2021 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 6 | |||
| 7 | const std = @import("std"); | ||
| 8 | const fmt = std.fmt; | ||
| 9 | const testing = std.testing; | ||
| 10 | |||
| 11 | const P256 = @import("p256.zig").P256; | ||
| 12 | |||
| 13 | test "p256 ECDH key exchange" { | ||
| 14 | const dha = P256.scalar.random(.Little); | ||
| 15 | const dhb = P256.scalar.random(.Little); | ||
| 16 | const dhA = try P256.basePoint.mul(dha, .Little); | ||
| 17 | const dhB = try P256.basePoint.mul(dhb, .Little); | ||
| 18 | const shareda = try dhA.mul(dhb, .Little); | ||
| 19 | const sharedb = try dhB.mul(dha, .Little); | ||
| 20 | testing.expect(shareda.equivalent(sharedb)); | ||
| 21 | } | ||
| 22 | |||
| 23 | test "p256 point from affine coordinates" { | ||
| 24 | const xh = "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296"; | ||
| 25 | const yh = "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5"; | ||
| 26 | var xs: [32]u8 = undefined; | ||
| 27 | _ = try fmt.hexToBytes(&xs, xh); | ||
| 28 | var ys: [32]u8 = undefined; | ||
| 29 | _ = try fmt.hexToBytes(&ys, yh); | ||
| 30 | var p = try P256.fromSerializedAffineCoordinates(xs, ys, .Big); | ||
| 31 | testing.expect(p.equivalent(P256.basePoint)); | ||
| 32 | } | ||
| 33 | |||
| 34 | test "p256 test vectors" { | ||
| 35 | const expected = [_][]const u8{ | ||
| 36 | "0000000000000000000000000000000000000000000000000000000000000000", | ||
| 37 | "6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", | ||
| 38 | "7cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978", | ||
| 39 | "5ecbe4d1a6330a44c8f7ef951d4bf165e6c6b721efada985fb41661bc6e7fd6c", | ||
| 40 | "e2534a3532d08fbba02dde659ee62bd0031fe2db785596ef509302446b030852", | ||
| 41 | "51590b7a515140d2d784c85608668fdfef8c82fd1f5be52421554a0dc3d033ed", | ||
| 42 | "b01a172a76a4602c92d3242cb897dde3024c740debb215b4c6b0aae93c2291a9", | ||
| 43 | "8e533b6fa0bf7b4625bb30667c01fb607ef9f8b8a80fef5b300628703187b2a3", | ||
| 44 | "62d9779dbee9b0534042742d3ab54cadc1d238980fce97dbb4dd9dc1db6fb393", | ||
| 45 | "ea68d7b6fedf0b71878938d51d71f8729e0acb8c2c6df8b3d79e8a4b90949ee0", | ||
| 46 | }; | ||
| 47 | var p = P256.identityElement; | ||
| 48 | for (expected) |xh| { | ||
| 49 | const x = p.affineCoordinates().x; | ||
| 50 | p = p.add(P256.basePoint); | ||
| 51 | var xs: [32]u8 = undefined; | ||
| 52 | _ = try fmt.hexToBytes(&xs, xh); | ||
| 53 | testing.expectEqualSlices(u8, &x.toBytes(.Big), &xs); | ||
| 54 | } | ||
| 55 | } | ||
| 56 | |||
| 57 | test "p256 test vectors - doubling" { | ||
| 58 | const expected = [_][]const u8{ | ||
| 59 | "6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296", | ||
| 60 | "7cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978", | ||
| 61 | "e2534a3532d08fbba02dde659ee62bd0031fe2db785596ef509302446b030852", | ||
| 62 | "62d9779dbee9b0534042742d3ab54cadc1d238980fce97dbb4dd9dc1db6fb393", | ||
| 63 | }; | ||
| 64 | var p = P256.basePoint; | ||
| 65 | for (expected) |xh| { | ||
| 66 | const x = p.affineCoordinates().x; | ||
| 67 | p = p.dbl(); | ||
| 68 | var xs: [32]u8 = undefined; | ||
| 69 | _ = try fmt.hexToBytes(&xs, xh); | ||
| 70 | testing.expectEqualSlices(u8, &x.toBytes(.Big), &xs); | ||
| 71 | } | ||
| 72 | } | ||
| 73 | |||
| 74 | test "p256 compressed sec1 encoding/decoding" { | ||
| 75 | const p = P256.random(); | ||
| 76 | const s = p.toCompressedSec1(); | ||
| 77 | const q = try P256.fromSec1(&s); | ||
| 78 | testing.expect(p.equivalent(q)); | ||
| 79 | } | ||
| 80 | |||
| 81 | test "p256 uncompressed sec1 encoding/decoding" { | ||
| 82 | const p = P256.random(); | ||
| 83 | const s = p.toUncompressedSec1(); | ||
| 84 | const q = try P256.fromSec1(&s); | ||
| 85 | testing.expect(p.equivalent(q)); | ||
| 86 | } | ||
| 87 | |||
| 88 | test "p256 public key is the neutral element" { | ||
| 89 | const n = P256.scalar.Scalar.zero.toBytes(.Little); | ||
| 90 | const p = P256.random(); | ||
| 91 | testing.expectError(error.IdentityElement, p.mul(n, .Little)); | ||
| 92 | } | ||
| 93 | |||
| 94 | test "p256 public key is the neutral element (public verification)" { | ||
| 95 | const n = P256.scalar.Scalar.zero.toBytes(.Little); | ||
| 96 | const p = P256.random(); | ||
| 97 | testing.expectError(error.IdentityElement, p.mulPublic(n, .Little)); | ||
| 98 | } | ||
| 99 | |||
| 100 | test "p256 field element non-canonical encoding" { | ||
| 101 | const s = [_]u8{0xff} ** 32; | ||
| 102 | testing.expectError(error.NonCanonical, P256.Fe.fromBytes(s, .Little)); | ||
| 103 | } | ||
lib/std/fmt.zig+159| ... | @@ -696,6 +696,11 @@ fn formatFloatValue( | ... | @@ -696,6 +696,11 @@ fn formatFloatValue( |
| 696 | error.NoSpaceLeft => unreachable, | 696 | error.NoSpaceLeft => unreachable, |
| 697 | else => |e| return e, | 697 | else => |e| return e, |
| 698 | }; | 698 | }; |
| 699 | } else if (comptime std.mem.eql(u8, fmt, "x")) { | ||
| 700 | formatFloatHexadecimal(value, options, buf_stream.writer()) catch |err| switch (err) { | ||
| 701 | error.NoSpaceLeft => unreachable, | ||
| 702 | else => |e| return e, | ||
| 703 | }; | ||
| 699 | } else { | 704 | } else { |
| 700 | @compileError("Unsupported format string '" ++ fmt ++ "' for type '" ++ @typeName(@TypeOf(value)) ++ "'"); | 705 | @compileError("Unsupported format string '" ++ fmt ++ "' for type '" ++ @typeName(@TypeOf(value)) ++ "'"); |
| 701 | } | 706 | } |
| ... | @@ -1023,6 +1028,112 @@ pub fn formatFloatScientific( | ... | @@ -1023,6 +1028,112 @@ pub fn formatFloatScientific( |
| 1023 | } | 1028 | } |
| 1024 | } | 1029 | } |
| 1025 | 1030 | ||
| 1031 | pub fn formatFloatHexadecimal( | ||
| 1032 | value: anytype, | ||
| 1033 | options: FormatOptions, | ||
| 1034 | writer: anytype, | ||
| 1035 | ) !void { | ||
| 1036 | if (math.signbit(value)) { | ||
| 1037 | try writer.writeByte('-'); | ||
| 1038 | } | ||
| 1039 | if (math.isNan(value)) { | ||
| 1040 | return writer.writeAll("nan"); | ||
| 1041 | } | ||
| 1042 | if (math.isInf(value)) { | ||
| 1043 | return writer.writeAll("inf"); | ||
| 1044 | } | ||
| 1045 | |||
| 1046 | const T = @TypeOf(value); | ||
| 1047 | const TU = std.meta.Int(.unsigned, std.meta.bitCount(T)); | ||
| 1048 | |||
| 1049 | const mantissa_bits = math.floatMantissaBits(T); | ||
| 1050 | const exponent_bits = math.floatExponentBits(T); | ||
| 1051 | const mantissa_mask = (1 << mantissa_bits) - 1; | ||
| 1052 | const exponent_mask = (1 << exponent_bits) - 1; | ||
| 1053 | const exponent_bias = (1 << (exponent_bits - 1)) - 1; | ||
| 1054 | |||
| 1055 | const as_bits = @bitCast(TU, value); | ||
| 1056 | var mantissa = as_bits & mantissa_mask; | ||
| 1057 | var exponent: i32 = @truncate(u16, (as_bits >> mantissa_bits) & exponent_mask); | ||
| 1058 | |||
| 1059 | const is_denormal = exponent == 0 and mantissa != 0; | ||
| 1060 | const is_zero = exponent == 0 and mantissa == 0; | ||
| 1061 | |||
| 1062 | if (is_zero) { | ||
| 1063 | // Handle this case here to simplify the logic below. | ||
| 1064 | try writer.writeAll("0x0"); | ||
| 1065 | if (options.precision) |precision| { | ||
| 1066 | if (precision > 0) { | ||
| 1067 | try writer.writeAll("."); | ||
| 1068 | try writer.writeByteNTimes('0', precision); | ||
| 1069 | } | ||
| 1070 | } else { | ||
| 1071 | try writer.writeAll(".0"); | ||
| 1072 | } | ||
| 1073 | try writer.writeAll("p0"); | ||
| 1074 | return; | ||
| 1075 | } | ||
| 1076 | |||
| 1077 | if (is_denormal) { | ||
| 1078 | // Adjust the exponent for printing. | ||
| 1079 | exponent += 1; | ||
| 1080 | } else { | ||
| 1081 | // Add the implicit 1. | ||
| 1082 | mantissa |= 1 << mantissa_bits; | ||
| 1083 | } | ||
| 1084 | |||
| 1085 | // Fill in zeroes to round the mantissa width to a multiple of 4. | ||
| 1086 | if (T == f16) mantissa <<= 2 else if (T == f32) mantissa <<= 1; | ||
| 1087 | |||
| 1088 | const mantissa_digits = (mantissa_bits + 3) / 4; | ||
| 1089 | |||
| 1090 | if (options.precision) |precision| { | ||
| 1091 | // Round if needed. | ||
| 1092 | if (precision < mantissa_digits) { | ||
| 1093 | // We always have at least 4 extra bits. | ||
| 1094 | var extra_bits = (mantissa_digits - precision) * 4; | ||
| 1095 | // The result LSB is the Guard bit, we need two more (Round and | ||
| 1096 | // Sticky) to round the value. | ||
| 1097 | while (extra_bits > 2) { | ||
| 1098 | mantissa = (mantissa >> 1) | (mantissa & 1); | ||
| 1099 | extra_bits -= 1; | ||
| 1100 | } | ||
| 1101 | // Round to nearest, tie to even. | ||
| 1102 | mantissa |= @boolToInt(mantissa & 0b100 != 0); | ||
| 1103 | mantissa += 1; | ||
| 1104 | // Drop the excess bits. | ||
| 1105 | mantissa >>= 2; | ||
| 1106 | // Restore the alignment. | ||
| 1107 | mantissa <<= @intCast(math.Log2Int(TU), (mantissa_digits - precision) * 4); | ||
| 1108 | |||
| 1109 | const overflow = mantissa & (1 << 1 + mantissa_digits * 4) != 0; | ||
| 1110 | // Prefer a normalized result in case of overflow. | ||
| 1111 | if (overflow) { | ||
| 1112 | mantissa >>= 1; | ||
| 1113 | exponent += 1; | ||
| 1114 | } | ||
| 1115 | } | ||
| 1116 | } | ||
| 1117 | |||
| 1118 | // +1 for the decimal part. | ||
| 1119 | var buf: [1 + mantissa_digits]u8 = undefined; | ||
| 1120 | const N = formatIntBuf(&buf, mantissa, 16, false, .{ .fill = '0', .width = 1 + mantissa_digits }); | ||
| 1121 | |||
| 1122 | try writer.writeAll("0x"); | ||
| 1123 | try writer.writeByte(buf[0]); | ||
| 1124 | if (options.precision != @as(usize, 0)) | ||
| 1125 | try writer.writeAll("."); | ||
| 1126 | const trimmed = mem.trimRight(u8, buf[1..], "0"); | ||
| 1127 | try writer.writeAll(trimmed); | ||
| 1128 | // Add trailing zeros if explicitly requested. | ||
| 1129 | if (options.precision) |precision| if (precision > 0) { | ||
| 1130 | if (precision > trimmed.len) | ||
| 1131 | try writer.writeByteNTimes('0', precision - trimmed.len); | ||
| 1132 | }; | ||
| 1133 | try writer.writeAll("p"); | ||
| 1134 | try formatInt(exponent - exponent_bias, 10, false, .{}, writer); | ||
| 1135 | } | ||
| 1136 | |||
| 1026 | /// Print a float of the format x.yyyyy where the number of y is specified by the precision argument. | 1137 | /// Print a float of the format x.yyyyy where the number of y is specified by the precision argument. |
| 1027 | /// By default floats are printed at full precision (no rounding). | 1138 | /// By default floats are printed at full precision (no rounding). |
| 1028 | pub fn formatFloatDecimal( | 1139 | pub fn formatFloatDecimal( |
| ... | @@ -1917,6 +2028,54 @@ test "float.special" { | ... | @@ -1917,6 +2028,54 @@ test "float.special" { |
| 1917 | try expectFmt("f64: -inf", "f64: {}", .{-math.inf_f64}); | 2028 | try expectFmt("f64: -inf", "f64: {}", .{-math.inf_f64}); |
| 1918 | } | 2029 | } |
| 1919 | 2030 | ||
| 2031 | test "float.hexadecimal.special" { | ||
| 2032 | try expectFmt("f64: nan", "f64: {x}", .{math.nan_f64}); | ||
| 2033 | // negative nan is not defined by IEE 754, | ||
| 2034 | // and ARM thus normalizes it to positive nan | ||
| 2035 | if (builtin.arch != builtin.Arch.arm) { | ||
| 2036 | try expectFmt("f64: -nan", "f64: {x}", .{-math.nan_f64}); | ||
| 2037 | } | ||
| 2038 | try expectFmt("f64: inf", "f64: {x}", .{math.inf_f64}); | ||
| 2039 | try expectFmt("f64: -inf", "f64: {x}", .{-math.inf_f64}); | ||
| 2040 | |||
| 2041 | try expectFmt("f64: 0x0.0p0", "f64: {x}", .{@as(f64, 0)}); | ||
| 2042 | try expectFmt("f64: -0x0.0p0", "f64: {x}", .{-@as(f64, 0)}); | ||
| 2043 | } | ||
| 2044 | |||
| 2045 | test "float.hexadecimal" { | ||
| 2046 | try expectFmt("f16: 0x1.554p-2", "f16: {x}", .{@as(f16, 1.0 / 3.0)}); | ||
| 2047 | try expectFmt("f32: 0x1.555556p-2", "f32: {x}", .{@as(f32, 1.0 / 3.0)}); | ||
| 2048 | try expectFmt("f64: 0x1.5555555555555p-2", "f64: {x}", .{@as(f64, 1.0 / 3.0)}); | ||
| 2049 | try expectFmt("f128: 0x1.5555555555555555555555555555p-2", "f128: {x}", .{@as(f128, 1.0 / 3.0)}); | ||
| 2050 | |||
| 2051 | try expectFmt("f16: 0x1.p-14", "f16: {x}", .{@as(f16, math.f16_min)}); | ||
| 2052 | try expectFmt("f32: 0x1.p-126", "f32: {x}", .{@as(f32, math.f32_min)}); | ||
| 2053 | try expectFmt("f64: 0x1.p-1022", "f64: {x}", .{@as(f64, math.f64_min)}); | ||
| 2054 | try expectFmt("f128: 0x1.p-16382", "f128: {x}", .{@as(f128, math.f128_min)}); | ||
| 2055 | |||
| 2056 | try expectFmt("f16: 0x0.004p-14", "f16: {x}", .{@as(f16, math.f16_true_min)}); | ||
| 2057 | try expectFmt("f32: 0x0.000002p-126", "f32: {x}", .{@as(f32, math.f32_true_min)}); | ||
| 2058 | try expectFmt("f64: 0x0.0000000000001p-1022", "f64: {x}", .{@as(f64, math.f64_true_min)}); | ||
| 2059 | try expectFmt("f128: 0x0.0000000000000000000000000001p-16382", "f128: {x}", .{@as(f128, math.f128_true_min)}); | ||
| 2060 | |||
| 2061 | try expectFmt("f16: 0x1.ffcp15", "f16: {x}", .{@as(f16, math.f16_max)}); | ||
| 2062 | try expectFmt("f32: 0x1.fffffep127", "f32: {x}", .{@as(f32, math.f32_max)}); | ||
| 2063 | try expectFmt("f64: 0x1.fffffffffffffp1023", "f64: {x}", .{@as(f64, math.f64_max)}); | ||
| 2064 | try expectFmt("f128: 0x1.ffffffffffffffffffffffffffffp16383", "f128: {x}", .{@as(f128, math.f128_max)}); | ||
| 2065 | } | ||
| 2066 | |||
| 2067 | test "float.hexadecimal.precision" { | ||
| 2068 | try expectFmt("f16: 0x1.5p-2", "f16: {x:.1}", .{@as(f16, 1.0 / 3.0)}); | ||
| 2069 | try expectFmt("f32: 0x1.555p-2", "f32: {x:.3}", .{@as(f32, 1.0 / 3.0)}); | ||
| 2070 | try expectFmt("f64: 0x1.55555p-2", "f64: {x:.5}", .{@as(f64, 1.0 / 3.0)}); | ||
| 2071 | try expectFmt("f128: 0x1.5555555p-2", "f128: {x:.7}", .{@as(f128, 1.0 / 3.0)}); | ||
| 2072 | |||
| 2073 | try expectFmt("f16: 0x1.00000p0", "f16: {x:.5}", .{@as(f16, 1.0)}); | ||
| 2074 | try expectFmt("f32: 0x1.00000p0", "f32: {x:.5}", .{@as(f32, 1.0)}); | ||
| 2075 | try expectFmt("f64: 0x1.00000p0", "f64: {x:.5}", .{@as(f64, 1.0)}); | ||
| 2076 | try expectFmt("f128: 0x1.00000p0", "f128: {x:.5}", .{@as(f128, 1.0)}); | ||
| 2077 | } | ||
| 2078 | |||
| 1920 | test "float.decimal" { | 2079 | test "float.decimal" { |
| 1921 | try expectFmt("f64: 152314000000000000000000000000", "f64: {d}", .{@as(f64, 1.52314e+29)}); | 2080 | try expectFmt("f64: 152314000000000000000000000000", "f64: {d}", .{@as(f64, 1.52314e+29)}); |
| 1922 | try expectFmt("f32: 0", "f32: {d}", .{@as(f32, 0.0)}); | 2081 | try expectFmt("f32: 0", "f32: {d}", .{@as(f32, 0.0)}); |
lib/std/math/copysign.zig+18| ... | @@ -20,6 +20,7 @@ pub fn copysign(comptime T: type, x: T, y: T) T { | ... | @@ -20,6 +20,7 @@ pub fn copysign(comptime T: type, x: T, y: T) T { |
| 20 | f16 => copysign16(x, y), | 20 | f16 => copysign16(x, y), |
| 21 | f32 => copysign32(x, y), | 21 | f32 => copysign32(x, y), |
| 22 | f64 => copysign64(x, y), | 22 | f64 => copysign64(x, y), |
| 23 | f128 => copysign128(x, y), | ||
| 23 | else => @compileError("copysign not implemented for " ++ @typeName(T)), | 24 | else => @compileError("copysign not implemented for " ++ @typeName(T)), |
| 24 | }; | 25 | }; |
| 25 | } | 26 | } |
| ... | @@ -51,10 +52,20 @@ fn copysign64(x: f64, y: f64) f64 { | ... | @@ -51,10 +52,20 @@ fn copysign64(x: f64, y: f64) f64 { |
| 51 | return @bitCast(f64, h1 | h2); | 52 | return @bitCast(f64, h1 | h2); |
| 52 | } | 53 | } |
| 53 | 54 | ||
| 55 | fn copysign128(x: f128, y: f128) f128 { | ||
| 56 | const ux = @bitCast(u128, x); | ||
| 57 | const uy = @bitCast(u128, y); | ||
| 58 | |||
| 59 | const h1 = ux & (maxInt(u128) / 2); | ||
| 60 | const h2 = uy & (@as(u128, 1) << 127); | ||
| 61 | return @bitCast(f128, h1 | h2); | ||
| 62 | } | ||
| 63 | |||
| 54 | test "math.copysign" { | 64 | test "math.copysign" { |
| 55 | expect(copysign(f16, 1.0, 1.0) == copysign16(1.0, 1.0)); | 65 | expect(copysign(f16, 1.0, 1.0) == copysign16(1.0, 1.0)); |
| 56 | expect(copysign(f32, 1.0, 1.0) == copysign32(1.0, 1.0)); | 66 | expect(copysign(f32, 1.0, 1.0) == copysign32(1.0, 1.0)); |
| 57 | expect(copysign(f64, 1.0, 1.0) == copysign64(1.0, 1.0)); | 67 | expect(copysign(f64, 1.0, 1.0) == copysign64(1.0, 1.0)); |
| 68 | expect(copysign(f128, 1.0, 1.0) == copysign128(1.0, 1.0)); | ||
| 58 | } | 69 | } |
| 59 | 70 | ||
| 60 | test "math.copysign16" { | 71 | test "math.copysign16" { |
| ... | @@ -77,3 +88,10 @@ test "math.copysign64" { | ... | @@ -77,3 +88,10 @@ test "math.copysign64" { |
| 77 | expect(copysign64(-5.0, -1.0) == -5.0); | 88 | expect(copysign64(-5.0, -1.0) == -5.0); |
| 78 | expect(copysign64(-5.0, 1.0) == 5.0); | 89 | expect(copysign64(-5.0, 1.0) == 5.0); |
| 79 | } | 90 | } |
| 91 | |||
| 92 | test "math.copysign128" { | ||
| 93 | expect(copysign128(5.0, 1.0) == 5.0); | ||
| 94 | expect(copysign128(5.0, -1.0) == -5.0); | ||
| 95 | expect(copysign128(-5.0, -1.0) == -5.0); | ||
| 96 | expect(copysign128(-5.0, 1.0) == 5.0); | ||
| 97 | } |
lib/std/math/isfinite.zig+18| ... | @@ -24,6 +24,10 @@ pub fn isFinite(x: anytype) bool { | ... | @@ -24,6 +24,10 @@ pub fn isFinite(x: anytype) bool { |
| 24 | const bits = @bitCast(u64, x); | 24 | const bits = @bitCast(u64, x); |
| 25 | return bits & (maxInt(u64) >> 1) < (0x7FF << 52); | 25 | return bits & (maxInt(u64) >> 1) < (0x7FF << 52); |
| 26 | }, | 26 | }, |
| 27 | f128 => { | ||
| 28 | const bits = @bitCast(u128, x); | ||
| 29 | return bits & (maxInt(u128) >> 1) < (0x7FFF << 112); | ||
| 30 | }, | ||
| 27 | else => { | 31 | else => { |
| 28 | @compileError("isFinite not implemented for " ++ @typeName(T)); | 32 | @compileError("isFinite not implemented for " ++ @typeName(T)); |
| 29 | }, | 33 | }, |
| ... | @@ -37,10 +41,24 @@ test "math.isFinite" { | ... | @@ -37,10 +41,24 @@ test "math.isFinite" { |
| 37 | expect(isFinite(@as(f32, -0.0))); | 41 | expect(isFinite(@as(f32, -0.0))); |
| 38 | expect(isFinite(@as(f64, 0.0))); | 42 | expect(isFinite(@as(f64, 0.0))); |
| 39 | expect(isFinite(@as(f64, -0.0))); | 43 | expect(isFinite(@as(f64, -0.0))); |
| 44 | expect(isFinite(@as(f128, 0.0))); | ||
| 45 | expect(isFinite(@as(f128, -0.0))); | ||
| 46 | |||
| 40 | expect(!isFinite(math.inf(f16))); | 47 | expect(!isFinite(math.inf(f16))); |
| 41 | expect(!isFinite(-math.inf(f16))); | 48 | expect(!isFinite(-math.inf(f16))); |
| 42 | expect(!isFinite(math.inf(f32))); | 49 | expect(!isFinite(math.inf(f32))); |
| 43 | expect(!isFinite(-math.inf(f32))); | 50 | expect(!isFinite(-math.inf(f32))); |
| 44 | expect(!isFinite(math.inf(f64))); | 51 | expect(!isFinite(math.inf(f64))); |
| 45 | expect(!isFinite(-math.inf(f64))); | 52 | expect(!isFinite(-math.inf(f64))); |
| 53 | expect(!isFinite(math.inf(f128))); | ||
| 54 | expect(!isFinite(-math.inf(f128))); | ||
| 55 | |||
| 56 | expect(!isFinite(math.nan(f16))); | ||
| 57 | expect(!isFinite(-math.nan(f16))); | ||
| 58 | expect(!isFinite(math.nan(f32))); | ||
| 59 | expect(!isFinite(-math.nan(f32))); | ||
| 60 | expect(!isFinite(math.nan(f64))); | ||
| 61 | expect(!isFinite(-math.nan(f64))); | ||
| 62 | expect(!isFinite(math.nan(f128))); | ||
| 63 | expect(!isFinite(-math.nan(f128))); | ||
| 46 | } | 64 | } |
lib/std/math/signbit.zig+12| ... | @@ -14,6 +14,7 @@ pub fn signbit(x: anytype) bool { | ... | @@ -14,6 +14,7 @@ pub fn signbit(x: anytype) bool { |
| 14 | f16 => signbit16(x), | 14 | f16 => signbit16(x), |
| 15 | f32 => signbit32(x), | 15 | f32 => signbit32(x), |
| 16 | f64 => signbit64(x), | 16 | f64 => signbit64(x), |
| 17 | f128 => signbit128(x), | ||
| 17 | else => @compileError("signbit not implemented for " ++ @typeName(T)), | 18 | else => @compileError("signbit not implemented for " ++ @typeName(T)), |
| 18 | }; | 19 | }; |
| 19 | } | 20 | } |
| ... | @@ -33,10 +34,16 @@ fn signbit64(x: f64) bool { | ... | @@ -33,10 +34,16 @@ fn signbit64(x: f64) bool { |
| 33 | return bits >> 63 != 0; | 34 | return bits >> 63 != 0; |
| 34 | } | 35 | } |
| 35 | 36 | ||
| 37 | fn signbit128(x: f128) bool { | ||
| 38 | const bits = @bitCast(u128, x); | ||
| 39 | return bits >> 127 != 0; | ||
| 40 | } | ||
| 41 | |||
| 36 | test "math.signbit" { | 42 | test "math.signbit" { |
| 37 | expect(signbit(@as(f16, 4.0)) == signbit16(4.0)); | 43 | expect(signbit(@as(f16, 4.0)) == signbit16(4.0)); |
| 38 | expect(signbit(@as(f32, 4.0)) == signbit32(4.0)); | 44 | expect(signbit(@as(f32, 4.0)) == signbit32(4.0)); |
| 39 | expect(signbit(@as(f64, 4.0)) == signbit64(4.0)); | 45 | expect(signbit(@as(f64, 4.0)) == signbit64(4.0)); |
| 46 | expect(signbit(@as(f128, 4.0)) == signbit128(4.0)); | ||
| 40 | } | 47 | } |
| 41 | 48 | ||
| 42 | test "math.signbit16" { | 49 | test "math.signbit16" { |
| ... | @@ -53,3 +60,8 @@ test "math.signbit64" { | ... | @@ -53,3 +60,8 @@ test "math.signbit64" { |
| 53 | expect(!signbit64(4.0)); | 60 | expect(!signbit64(4.0)); |
| 54 | expect(signbit64(-3.0)); | 61 | expect(signbit64(-3.0)); |
| 55 | } | 62 | } |
| 63 | |||
| 64 | test "math.signbit128" { | ||
| 65 | expect(!signbit128(4.0)); | ||
| 66 | expect(signbit128(-3.0)); | ||
| 67 | } |
lib/std/os/bits/darwin.zig+7| ... | @@ -832,6 +832,13 @@ pub const SO_RCVTIMEO = 0x1006; | ... | @@ -832,6 +832,13 @@ pub const SO_RCVTIMEO = 0x1006; |
| 832 | pub const SO_ERROR = 0x1007; | 832 | pub const SO_ERROR = 0x1007; |
| 833 | pub const SO_TYPE = 0x1008; | 833 | pub const SO_TYPE = 0x1008; |
| 834 | 834 | ||
| 835 | pub const SO_NREAD = 0x1020; | ||
| 836 | pub const SO_NKE = 0x1021; | ||
| 837 | pub const SO_NOSIGPIPE = 0x1022; | ||
| 838 | pub const SO_NOADDRERR = 0x1023; | ||
| 839 | pub const SO_NWRITE = 0x1024; | ||
| 840 | pub const SO_REUSESHAREUID = 0x1025; | ||
| 841 | |||
| 835 | fn wstatus(x: u32) u32 { | 842 | fn wstatus(x: u32) u32 { |
| 836 | return x & 0o177; | 843 | return x & 0o177; |
| 837 | } | 844 | } |
lib/std/os/bits/linux.zig+109-39| ... | @@ -5,11 +5,12 @@ | ... | @@ -5,11 +5,12 @@ |
| 5 | // and substantial portions of the software. | 5 | // and substantial portions of the software. |
| 6 | const std = @import("../../std.zig"); | 6 | const std = @import("../../std.zig"); |
| 7 | const maxInt = std.math.maxInt; | 7 | const maxInt = std.math.maxInt; |
| 8 | const arch = std.Target.current.cpu.arch; | 8 | const arch = @import("builtin").target.cpu.arch; |
| 9 | usingnamespace @import("../bits.zig"); | 9 | usingnamespace @import("../bits.zig"); |
| 10 | 10 | ||
| 11 | pub usingnamespace switch (arch) { | 11 | pub usingnamespace switch (arch) { |
| 12 | .mips, .mipsel => @import("linux/errno-mips.zig"), | 12 | .mips, .mipsel => @import("linux/errno-mips.zig"), |
| 13 | .sparc, .sparcel, .sparcv9 => @import("linux/errno-sparc.zig"), | ||
| 13 | else => @import("linux/errno-generic.zig"), | 14 | else => @import("linux/errno-generic.zig"), |
| 14 | }; | 15 | }; |
| 15 | 16 | ||
| ... | @@ -31,6 +32,7 @@ pub usingnamespace @import("linux/prctl.zig"); | ... | @@ -31,6 +32,7 @@ pub usingnamespace @import("linux/prctl.zig"); |
| 31 | pub usingnamespace @import("linux/securebits.zig"); | 32 | pub usingnamespace @import("linux/securebits.zig"); |
| 32 | 33 | ||
| 33 | const is_mips = arch.isMIPS(); | 34 | const is_mips = arch.isMIPS(); |
| 35 | const is_ppc = arch.isPPC(); | ||
| 34 | const is_ppc64 = arch.isPPC64(); | 36 | const is_ppc64 = arch.isPPC64(); |
| 35 | const is_sparc = arch.isSPARC(); | 37 | const is_sparc = arch.isSPARC(); |
| 36 | 38 | ||
| ... | @@ -247,40 +249,78 @@ else | ... | @@ -247,40 +249,78 @@ else |
| 247 | pub const SIG_SETMASK = 2; | 249 | pub const SIG_SETMASK = 2; |
| 248 | }; | 250 | }; |
| 249 | 251 | ||
| 250 | pub const SIGHUP = 1; | 252 | pub usingnamespace if (is_sparc) struct { |
| 251 | pub const SIGINT = 2; | 253 | pub const SIGHUP = 1; |
| 252 | pub const SIGQUIT = 3; | 254 | pub const SIGINT = 2; |
| 253 | pub const SIGILL = 4; | 255 | pub const SIGQUIT = 3; |
| 254 | pub const SIGTRAP = 5; | 256 | pub const SIGILL = 4; |
| 255 | pub const SIGABRT = 6; | 257 | pub const SIGTRAP = 5; |
| 256 | pub const SIGIOT = SIGABRT; | 258 | pub const SIGABRT = 6; |
| 257 | pub const SIGBUS = 7; | 259 | pub const SIGEMT = 7; |
| 258 | pub const SIGFPE = 8; | 260 | pub const SIGFPE = 8; |
| 259 | pub const SIGKILL = 9; | 261 | pub const SIGKILL = 9; |
| 260 | pub const SIGUSR1 = 10; | 262 | pub const SIGBUS = 10; |
| 261 | pub const SIGSEGV = 11; | 263 | pub const SIGSEGV = 11; |
| 262 | pub const SIGUSR2 = 12; | 264 | pub const SIGSYS = 12; |
| 263 | pub const SIGPIPE = 13; | 265 | pub const SIGPIPE = 13; |
| 264 | pub const SIGALRM = 14; | 266 | pub const SIGALRM = 14; |
| 265 | pub const SIGTERM = 15; | 267 | pub const SIGTERM = 15; |
| 266 | pub const SIGSTKFLT = 16; | 268 | pub const SIGURG = 16; |
| 267 | pub const SIGCHLD = 17; | 269 | pub const SIGSTOP = 17; |
| 268 | pub const SIGCONT = 18; | 270 | pub const SIGTSTP = 18; |
| 269 | pub const SIGSTOP = 19; | 271 | pub const SIGCONT = 19; |
| 270 | pub const SIGTSTP = 20; | 272 | pub const SIGCHLD = 20; |
| 271 | pub const SIGTTIN = 21; | 273 | pub const SIGTTIN = 21; |
| 272 | pub const SIGTTOU = 22; | 274 | pub const SIGTTOU = 22; |
| 273 | pub const SIGURG = 23; | 275 | pub const SIGPOLL = 23; |
| 274 | pub const SIGXCPU = 24; | 276 | pub const SIGXCPU = 24; |
| 275 | pub const SIGXFSZ = 25; | 277 | pub const SIGXFSZ = 25; |
| 276 | pub const SIGVTALRM = 26; | 278 | pub const SIGVTALRM = 26; |
| 277 | pub const SIGPROF = 27; | 279 | pub const SIGPROF = 27; |
| 278 | pub const SIGWINCH = 28; | 280 | pub const SIGWINCH = 28; |
| 279 | pub const SIGIO = 29; | 281 | pub const SIGLOST = 29; |
| 280 | pub const SIGPOLL = 29; | 282 | pub const SIGUSR1 = 30; |
| 281 | pub const SIGPWR = 30; | 283 | pub const SIGUSR2 = 31; |
| 282 | pub const SIGSYS = 31; | 284 | pub const SIGIOT = SIGABRT; |
| 283 | pub const SIGUNUSED = SIGSYS; | 285 | pub const SIGCLD = SIGCHLD; |
| 286 | pub const SIGPWR = SIGLOST; | ||
| 287 | pub const SIGIO = SIGPOLL; | ||
| 288 | } else struct { | ||
| 289 | pub const SIGHUP = 1; | ||
| 290 | pub const SIGINT = 2; | ||
| 291 | pub const SIGQUIT = 3; | ||
| 292 | pub const SIGILL = 4; | ||
| 293 | pub const SIGTRAP = 5; | ||
| 294 | pub const SIGABRT = 6; | ||
| 295 | pub const SIGIOT = SIGABRT; | ||
| 296 | pub const SIGBUS = 7; | ||
| 297 | pub const SIGFPE = 8; | ||
| 298 | pub const SIGKILL = 9; | ||
| 299 | pub const SIGUSR1 = 10; | ||
| 300 | pub const SIGSEGV = 11; | ||
| 301 | pub const SIGUSR2 = 12; | ||
| 302 | pub const SIGPIPE = 13; | ||
| 303 | pub const SIGALRM = 14; | ||
| 304 | pub const SIGTERM = 15; | ||
| 305 | pub const SIGSTKFLT = 16; | ||
| 306 | pub const SIGCHLD = 17; | ||
| 307 | pub const SIGCONT = 18; | ||
| 308 | pub const SIGSTOP = 19; | ||
| 309 | pub const SIGTSTP = 20; | ||
| 310 | pub const SIGTTIN = 21; | ||
| 311 | pub const SIGTTOU = 22; | ||
| 312 | pub const SIGURG = 23; | ||
| 313 | pub const SIGXCPU = 24; | ||
| 314 | pub const SIGXFSZ = 25; | ||
| 315 | pub const SIGVTALRM = 26; | ||
| 316 | pub const SIGPROF = 27; | ||
| 317 | pub const SIGWINCH = 28; | ||
| 318 | pub const SIGIO = 29; | ||
| 319 | pub const SIGPOLL = 29; | ||
| 320 | pub const SIGPWR = 30; | ||
| 321 | pub const SIGSYS = 31; | ||
| 322 | pub const SIGUNUSED = SIGSYS; | ||
| 323 | }; | ||
| 284 | 324 | ||
| 285 | pub const O_RDONLY = 0o0; | 325 | pub const O_RDONLY = 0o0; |
| 286 | pub const O_WRONLY = 0o1; | 326 | pub const O_WRONLY = 0o1; |
| ... | @@ -419,7 +459,39 @@ pub const AF_QIPCRTR = PF_QIPCRTR; | ... | @@ -419,7 +459,39 @@ pub const AF_QIPCRTR = PF_QIPCRTR; |
| 419 | pub const AF_SMC = PF_SMC; | 459 | pub const AF_SMC = PF_SMC; |
| 420 | pub const AF_MAX = PF_MAX; | 460 | pub const AF_MAX = PF_MAX; |
| 421 | 461 | ||
| 422 | pub usingnamespace if (!is_mips) | 462 | pub usingnamespace if (is_mips) |
| 463 | struct {} | ||
| 464 | else if (is_ppc or is_ppc64) | ||
| 465 | struct { | ||
| 466 | pub const SO_DEBUG = 1; | ||
| 467 | pub const SO_REUSEADDR = 2; | ||
| 468 | pub const SO_TYPE = 3; | ||
| 469 | pub const SO_ERROR = 4; | ||
| 470 | pub const SO_DONTROUTE = 5; | ||
| 471 | pub const SO_BROADCAST = 6; | ||
| 472 | pub const SO_SNDBUF = 7; | ||
| 473 | pub const SO_RCVBUF = 8; | ||
| 474 | pub const SO_KEEPALIVE = 9; | ||
| 475 | pub const SO_OOBINLINE = 10; | ||
| 476 | pub const SO_NO_CHECK = 11; | ||
| 477 | pub const SO_PRIORITY = 12; | ||
| 478 | pub const SO_LINGER = 13; | ||
| 479 | pub const SO_BSDCOMPAT = 14; | ||
| 480 | pub const SO_REUSEPORT = 15; | ||
| 481 | pub const SO_RCVLOWAT = 16; | ||
| 482 | pub const SO_SNDLOWAT = 17; | ||
| 483 | pub const SO_RCVTIMEO = 18; | ||
| 484 | pub const SO_SNDTIMEO = 19; | ||
| 485 | pub const SO_PASSCRED = 20; | ||
| 486 | pub const SO_PEERCRED = 21; | ||
| 487 | pub const SO_ACCEPTCONN = 30; | ||
| 488 | pub const SO_PEERSEC = 31; | ||
| 489 | pub const SO_SNDBUFFORCE = 32; | ||
| 490 | pub const SO_RCVBUFFORCE = 33; | ||
| 491 | pub const SO_PROTOCOL = 38; | ||
| 492 | pub const SO_DOMAIN = 39; | ||
| 493 | } | ||
| 494 | else | ||
| 423 | struct { | 495 | struct { |
| 424 | pub const SO_DEBUG = 1; | 496 | pub const SO_DEBUG = 1; |
| 425 | pub const SO_REUSEADDR = 2; | 497 | pub const SO_REUSEADDR = 2; |
| ... | @@ -448,9 +520,7 @@ pub usingnamespace if (!is_mips) | ... | @@ -448,9 +520,7 @@ pub usingnamespace if (!is_mips) |
| 448 | pub const SO_RCVBUFFORCE = 33; | 520 | pub const SO_RCVBUFFORCE = 33; |
| 449 | pub const SO_PROTOCOL = 38; | 521 | pub const SO_PROTOCOL = 38; |
| 450 | pub const SO_DOMAIN = 39; | 522 | pub const SO_DOMAIN = 39; |
| 451 | } | 523 | }; |
| 452 | else | ||
| 453 | struct {}; | ||
| 454 | 524 | ||
| 455 | pub const SO_SECURITY_AUTHENTICATION = 22; | 525 | pub const SO_SECURITY_AUTHENTICATION = 22; |
| 456 | pub const SO_SECURITY_ENCRYPTION_TRANSPORT = 23; | 526 | pub const SO_SECURITY_ENCRYPTION_TRANSPORT = 23; |
lib/std/os/bits/linux/arm64.zig+1| ... | @@ -9,6 +9,7 @@ | ... | @@ -9,6 +9,7 @@ |
| 9 | const std = @import("../../../std.zig"); | 9 | const std = @import("../../../std.zig"); |
| 10 | const linux = std.os.linux; | 10 | const linux = std.os.linux; |
| 11 | const socklen_t = linux.socklen_t; | 11 | const socklen_t = linux.socklen_t; |
| 12 | const sockaddr = linux.sockaddr; | ||
| 12 | const iovec = linux.iovec; | 13 | const iovec = linux.iovec; |
| 13 | const iovec_const = linux.iovec_const; | 14 | const iovec_const = linux.iovec_const; |
| 14 | const uid_t = linux.uid_t; | 15 | const uid_t = linux.uid_t; |
lib/std/os/bits/linux/errno-mips.zig+4| ... | @@ -3,6 +3,9 @@ | ... | @@ -3,6 +3,9 @@ |
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. |
| 4 | // The MIT license requires this copyright notice to be included in all copies | 4 | // The MIT license requires this copyright notice to be included in all copies |
| 5 | // and substantial portions of the software. | 5 | // and substantial portions of the software. |
| 6 | |||
| 7 | // These are MIPS ABI compatible. | ||
| 8 | |||
| 6 | pub const EPERM = 1; | 9 | pub const EPERM = 1; |
| 7 | pub const ENOENT = 2; | 10 | pub const ENOENT = 2; |
| 8 | pub const ESRCH = 3; | 11 | pub const ESRCH = 3; |
| ... | @@ -37,6 +40,7 @@ pub const EMLINK = 31; | ... | @@ -37,6 +40,7 @@ pub const EMLINK = 31; |
| 37 | pub const EPIPE = 32; | 40 | pub const EPIPE = 32; |
| 38 | pub const EDOM = 33; | 41 | pub const EDOM = 33; |
| 39 | pub const ERANGE = 34; | 42 | pub const ERANGE = 34; |
| 43 | |||
| 40 | pub const ENOMSG = 35; | 44 | pub const ENOMSG = 35; |
| 41 | pub const EIDRM = 36; | 45 | pub const EIDRM = 36; |
| 42 | pub const ECHRNG = 37; | 46 | pub const ECHRNG = 37; |
lib/std/os/bits/linux/errno-sparc.zig created+144| ... | @@ -0,0 +1,144 @@ | ||
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2021 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 6 | |||
| 7 | // These match the SunOS error numbering scheme. | ||
| 8 | |||
| 9 | pub const EPERM = 1; | ||
| 10 | pub const ENOENT = 2; | ||
| 11 | pub const ESRCH = 3; | ||
| 12 | pub const EINTR = 4; | ||
| 13 | pub const EIO = 5; | ||
| 14 | pub const ENXIO = 6; | ||
| 15 | pub const E2BIG = 7; | ||
| 16 | pub const ENOEXEC = 8; | ||
| 17 | pub const EBADF = 9; | ||
| 18 | pub const ECHILD = 10; | ||
| 19 | pub const EAGAIN = 11; | ||
| 20 | pub const ENOMEM = 12; | ||
| 21 | pub const EACCES = 13; | ||
| 22 | pub const EFAULT = 14; | ||
| 23 | pub const ENOTBLK = 15; | ||
| 24 | pub const EBUSY = 16; | ||
| 25 | pub const EEXIST = 17; | ||
| 26 | pub const EXDEV = 18; | ||
| 27 | pub const ENODEV = 19; | ||
| 28 | pub const ENOTDIR = 20; | ||
| 29 | pub const EISDIR = 21; | ||
| 30 | pub const EINVAL = 22; | ||
| 31 | pub const ENFILE = 23; | ||
| 32 | pub const EMFILE = 24; | ||
| 33 | pub const ENOTTY = 25; | ||
| 34 | pub const ETXTBSY = 26; | ||
| 35 | pub const EFBIG = 27; | ||
| 36 | pub const ENOSPC = 28; | ||
| 37 | pub const ESPIPE = 29; | ||
| 38 | pub const EROFS = 30; | ||
| 39 | pub const EMLINK = 31; | ||
| 40 | pub const EPIPE = 32; | ||
| 41 | pub const EDOM = 33; | ||
| 42 | pub const ERANGE = 34; | ||
| 43 | |||
| 44 | pub const EWOULDBLOCK = EAGAIN; | ||
| 45 | pub const EINPROGRESS = 36; | ||
| 46 | pub const EALREADY = 37; | ||
| 47 | pub const ENOTSOCK = 38; | ||
| 48 | pub const EDESTADDRREQ = 39; | ||
| 49 | pub const EMSGSIZE = 40; | ||
| 50 | pub const EPROTOTYPE = 41; | ||
| 51 | pub const ENOPROTOOPT = 42; | ||
| 52 | pub const EPROTONOSUPPORT = 43; | ||
| 53 | pub const ESOCKTNOSUPPORT = 44; | ||
| 54 | pub const EOPNOTSUPP = 45; | ||
| 55 | pub const EPFNOSUPPORT = 46; | ||
| 56 | pub const EAFNOSUPPORT = 47; | ||
| 57 | pub const EADDRINUSE = 48; | ||
| 58 | pub const EADDRNOTAVAIL = 49; | ||
| 59 | pub const ENETDOWN = 50; | ||
| 60 | pub const ENETUNREACH = 51; | ||
| 61 | pub const ENETRESET = 52; | ||
| 62 | pub const ECONNABORTED = 53; | ||
| 63 | pub const ECONNRESET = 54; | ||
| 64 | pub const ENOBUFS = 55; | ||
| 65 | pub const EISCONN = 56; | ||
| 66 | pub const ENOTCONN = 57; | ||
| 67 | pub const ESHUTDOWN = 58; | ||
| 68 | pub const ETOOMANYREFS = 59; | ||
| 69 | pub const ETIMEDOUT = 60; | ||
| 70 | pub const ECONNREFUSED = 61; | ||
| 71 | pub const ELOOP = 62; | ||
| 72 | pub const ENAMETOOLONG = 63; | ||
| 73 | pub const EHOSTDOWN = 64; | ||
| 74 | pub const EHOSTUNREACH = 65; | ||
| 75 | pub const ENOTEMPTY = 66; | ||
| 76 | pub const EPROCLIM = 67; | ||
| 77 | pub const EUSERS = 68; | ||
| 78 | pub const EDQUOT = 69; | ||
| 79 | pub const ESTALE = 70; | ||
| 80 | pub const EREMOTE = 71; | ||
| 81 | pub const ENOSTR = 72; | ||
| 82 | pub const ETIME = 73; | ||
| 83 | pub const ENOSR = 74; | ||
| 84 | pub const ENOMSG = 75; | ||
| 85 | pub const EBADMSG = 76; | ||
| 86 | pub const EIDRM = 77; | ||
| 87 | pub const EDEADLK = 78; | ||
| 88 | pub const ENOLCK = 79; | ||
| 89 | pub const ENONET = 80; | ||
| 90 | pub const ERREMOTE = 81; | ||
| 91 | pub const ENOLINK = 82; | ||
| 92 | pub const EADV = 83; | ||
| 93 | pub const ESRMNT = 84; | ||
| 94 | pub const ECOMM = 85; | ||
| 95 | pub const EPROTO = 86; | ||
| 96 | pub const EMULTIHOP = 87; | ||
| 97 | pub const EDOTDOT = 88; | ||
| 98 | pub const EREMCHG = 89; | ||
| 99 | pub const ENOSYS = 90; | ||
| 100 | pub const ESTRPIPE = 91; | ||
| 101 | pub const EOVERFLOW = 92; | ||
| 102 | pub const EBADFD = 93; | ||
| 103 | pub const ECHRNG = 94; | ||
| 104 | pub const EL2NSYNC = 95; | ||
| 105 | pub const EL3HLT = 96; | ||
| 106 | pub const EL3RST = 97; | ||
| 107 | pub const ELNRNG = 98; | ||
| 108 | pub const EUNATCH = 99; | ||
| 109 | pub const ENOCSI = 100; | ||
| 110 | pub const EL2HLT = 101; | ||
| 111 | pub const EBADE = 102; | ||
| 112 | pub const EBADR = 103; | ||
| 113 | pub const EXFULL = 104; | ||
| 114 | pub const ENOANO = 105; | ||
| 115 | pub const EBADRQC = 106; | ||
| 116 | pub const EBADSLT = 107; | ||
| 117 | pub const EDEADLOCK = 108; | ||
| 118 | pub const EBFONT = 109; | ||
| 119 | pub const ELIBEXEC = 110; | ||
| 120 | pub const ENODATA = 111; | ||
| 121 | pub const ELIBBAD = 112; | ||
| 122 | pub const ENOPKG = 113; | ||
| 123 | pub const ELIBACC = 114; | ||
| 124 | pub const ENOTUNIQ = 115; | ||
| 125 | pub const ERESTART = 116; | ||
| 126 | pub const EUCLEAN = 117; | ||
| 127 | pub const ENOTNAM = 118; | ||
| 128 | pub const ENAVAIL = 119; | ||
| 129 | pub const EISNAM = 120; | ||
| 130 | pub const EREMOTEIO = 121; | ||
| 131 | pub const EILSEQ = 122; | ||
| 132 | pub const ELIBMAX = 123; | ||
| 133 | pub const ELIBSCN = 124; | ||
| 134 | pub const ENOMEDIUM = 125; | ||
| 135 | pub const EMEDIUMTYPE = 126; | ||
| 136 | pub const ECANCELED = 127; | ||
| 137 | pub const ENOKEY = 128; | ||
| 138 | pub const EKEYEXPIRED = 129; | ||
| 139 | pub const EKEYREVOKED = 130; | ||
| 140 | pub const EKEYREJECTED = 131; | ||
| 141 | pub const EOWNERDEAD = 132; | ||
| 142 | pub const ENOTRECOVERABLE = 133; | ||
| 143 | pub const ERFKILL = 134; | ||
| 144 | pub const EHWPOISON = 135; | ||
lib/std/os/bits/linux/riscv64.zig+5| ... | @@ -376,6 +376,11 @@ pub const timespec = extern struct { | ... | @@ -376,6 +376,11 @@ pub const timespec = extern struct { |
| 376 | tv_nsec: isize, | 376 | tv_nsec: isize, |
| 377 | }; | 377 | }; |
| 378 | 378 | ||
| 379 | pub const timeval = extern struct { | ||
| 380 | tv_sec: time_t, | ||
| 381 | tv_usec: i64, | ||
| 382 | }; | ||
| 383 | |||
| 379 | pub const Flock = extern struct { | 384 | pub const Flock = extern struct { |
| 380 | l_type: i16, | 385 | l_type: i16, |
| 381 | l_whence: i16, | 386 | l_whence: i16, |
lib/std/os/bits/windows.zig+5| ... | @@ -22,6 +22,11 @@ pub const timespec = extern struct { | ... | @@ -22,6 +22,11 @@ pub const timespec = extern struct { |
| 22 | tv_nsec: c_long, | 22 | tv_nsec: c_long, |
| 23 | }; | 23 | }; |
| 24 | 24 | ||
| 25 | pub const timeval = extern struct { | ||
| 26 | tv_sec: c_long, | ||
| 27 | tv_usec: c_long, | ||
| 28 | }; | ||
| 29 | |||
| 25 | pub const sig_atomic_t = c_int; | 30 | pub const sig_atomic_t = c_int; |
| 26 | 31 | ||
| 27 | /// maximum signal number + 1 | 32 | /// maximum signal number + 1 |
lib/std/os/linux.zig+9-5| ... | @@ -387,7 +387,7 @@ pub fn symlinkat(existing: [*:0]const u8, newfd: i32, newpath: [*:0]const u8) us | ... | @@ -387,7 +387,7 @@ pub fn symlinkat(existing: [*:0]const u8, newfd: i32, newpath: [*:0]const u8) us |
| 387 | } | 387 | } |
| 388 | 388 | ||
| 389 | pub fn pread(fd: i32, buf: [*]u8, count: usize, offset: u64) usize { | 389 | pub fn pread(fd: i32, buf: [*]u8, count: usize, offset: u64) usize { |
| 390 | if (@hasField(SYS, "pread64")) { | 390 | if (@hasField(SYS, "pread64") and usize_bits < 64) { |
| 391 | const offset_halves = splitValue64(offset); | 391 | const offset_halves = splitValue64(offset); |
| 392 | if (require_aligned_register_pair) { | 392 | if (require_aligned_register_pair) { |
| 393 | return syscall6( | 393 | return syscall6( |
| ... | @@ -410,8 +410,10 @@ pub fn pread(fd: i32, buf: [*]u8, count: usize, offset: u64) usize { | ... | @@ -410,8 +410,10 @@ pub fn pread(fd: i32, buf: [*]u8, count: usize, offset: u64) usize { |
| 410 | ); | 410 | ); |
| 411 | } | 411 | } |
| 412 | } else { | 412 | } else { |
| 413 | // Some architectures (eg. 64bit SPARC) pread is called pread64. | ||
| 414 | const S = if (!@hasField(SYS, "pread") and @hasField(SYS, "pread64")) .pread64 else .pread; | ||
| 413 | return syscall4( | 415 | return syscall4( |
| 414 | .pread, | 416 | S, |
| 415 | @bitCast(usize, @as(isize, fd)), | 417 | @bitCast(usize, @as(isize, fd)), |
| 416 | @ptrToInt(buf), | 418 | @ptrToInt(buf), |
| 417 | count, | 419 | count, |
| ... | @@ -451,7 +453,7 @@ pub fn write(fd: i32, buf: [*]const u8, count: usize) usize { | ... | @@ -451,7 +453,7 @@ pub fn write(fd: i32, buf: [*]const u8, count: usize) usize { |
| 451 | } | 453 | } |
| 452 | 454 | ||
| 453 | pub fn ftruncate(fd: i32, length: u64) usize { | 455 | pub fn ftruncate(fd: i32, length: u64) usize { |
| 454 | if (@hasField(SYS, "ftruncate64")) { | 456 | if (@hasField(SYS, "ftruncate64") and usize_bits < 64) { |
| 455 | const length_halves = splitValue64(length); | 457 | const length_halves = splitValue64(length); |
| 456 | if (require_aligned_register_pair) { | 458 | if (require_aligned_register_pair) { |
| 457 | return syscall4( | 459 | return syscall4( |
| ... | @@ -479,7 +481,7 @@ pub fn ftruncate(fd: i32, length: u64) usize { | ... | @@ -479,7 +481,7 @@ pub fn ftruncate(fd: i32, length: u64) usize { |
| 479 | } | 481 | } |
| 480 | 482 | ||
| 481 | pub fn pwrite(fd: i32, buf: [*]const u8, count: usize, offset: u64) usize { | 483 | pub fn pwrite(fd: i32, buf: [*]const u8, count: usize, offset: u64) usize { |
| 482 | if (@hasField(SYS, "pwrite64")) { | 484 | if (@hasField(SYS, "pwrite64") and usize_bits < 64) { |
| 483 | const offset_halves = splitValue64(offset); | 485 | const offset_halves = splitValue64(offset); |
| 484 | 486 | ||
| 485 | if (require_aligned_register_pair) { | 487 | if (require_aligned_register_pair) { |
| ... | @@ -503,8 +505,10 @@ pub fn pwrite(fd: i32, buf: [*]const u8, count: usize, offset: u64) usize { | ... | @@ -503,8 +505,10 @@ pub fn pwrite(fd: i32, buf: [*]const u8, count: usize, offset: u64) usize { |
| 503 | ); | 505 | ); |
| 504 | } | 506 | } |
| 505 | } else { | 507 | } else { |
| 508 | // Some architectures (eg. 64bit SPARC) pwrite is called pwrite64. | ||
| 509 | const S = if (!@hasField(SYS, "pwrite") and @hasField(SYS, "pwrite64")) .pwrite64 else .pwrite; | ||
| 506 | return syscall4( | 510 | return syscall4( |
| 507 | .pwrite, | 511 | S, |
| 508 | @bitCast(usize, @as(isize, fd)), | 512 | @bitCast(usize, @as(isize, fd)), |
| 509 | @ptrToInt(buf), | 513 | @ptrToInt(buf), |
| 510 | count, | 514 | count, |
lib/std/special/c.zig+7-6| ... | @@ -617,23 +617,24 @@ fn clone() callconv(.Naked) void { | ... | @@ -617,23 +617,24 @@ fn clone() callconv(.Naked) void { |
| 617 | \\ # Shuffle the arguments | 617 | \\ # Shuffle the arguments |
| 618 | \\ mov 217, %%g1 | 618 | \\ mov 217, %%g1 |
| 619 | \\ mov %%i2, %%o0 | 619 | \\ mov %%i2, %%o0 |
| 620 | \\ sub %%i1, 2047, %%o1 | 620 | \\ # Add some extra space for the initial frame |
| 621 | \\ sub %%i1, 176 + 2047, %%o1 | ||
| 621 | \\ mov %%i4, %%o2 | 622 | \\ mov %%i4, %%o2 |
| 622 | \\ mov %%i5, %%o3 | 623 | \\ mov %%i5, %%o3 |
| 623 | \\ ldx [%%fp + 192 - 2*8 + 2047], %%o4 | 624 | \\ ldx [%%fp + 0x8af], %%o4 |
| 624 | \\ t 0x6d | 625 | \\ t 0x6d |
| 625 | \\ bcs,pn %%xcc, 2f | 626 | \\ bcs,pn %%xcc, 2f |
| 626 | \\ nop | 627 | \\ nop |
| 627 | \\ # sparc64 returns the child pid in o0 and a flag telling | 628 | \\ # The child pid is returned in o0 while o1 tells if this |
| 628 | \\ # whether the process is the child in o1 | 629 | \\ # process is # the child (=1) or the parent (=0). |
| 629 | \\ brnz %%o1, 1f | 630 | \\ brnz %%o1, 1f |
| 630 | \\ nop | 631 | \\ nop |
| 631 | \\ # This is the parent process, return the child pid | 632 | \\ # Parent process, return the child pid |
| 632 | \\ mov %%o0, %%i0 | 633 | \\ mov %%o0, %%i0 |
| 633 | \\ ret | 634 | \\ ret |
| 634 | \\ restore | 635 | \\ restore |
| 635 | \\1: | 636 | \\1: |
| 636 | \\ # This is the child process | 637 | \\ # Child process, call func(arg) |
| 637 | \\ mov %%g0, %%fp | 638 | \\ mov %%g0, %%fp |
| 638 | \\ call %%g2 | 639 | \\ call %%g2 |
| 639 | \\ mov %%g3, %%o0 | 640 | \\ mov %%g3, %%o0 |
lib/std/target/aarch64.zig+18| ... | @@ -1621,6 +1621,16 @@ pub const cpu = struct { | ... | @@ -1621,6 +1621,16 @@ pub const cpu = struct { |
| 1621 | .apple_a7, | 1621 | .apple_a7, |
| 1622 | }), | 1622 | }), |
| 1623 | }; | 1623 | }; |
| 1624 | pub const emag = CpuModel{ | ||
| 1625 | .name = "emag", | ||
| 1626 | .llvm_name = null, | ||
| 1627 | .features = featureSet(&[_]Feature{ | ||
| 1628 | .crc, | ||
| 1629 | .crypto, | ||
| 1630 | .perfmon, | ||
| 1631 | .v8a, | ||
| 1632 | }), | ||
| 1633 | }; | ||
| 1624 | pub const exynos_m1 = CpuModel{ | 1634 | pub const exynos_m1 = CpuModel{ |
| 1625 | .name = "exynos_m1", | 1635 | .name = "exynos_m1", |
| 1626 | .llvm_name = null, | 1636 | .llvm_name = null, |
| ... | @@ -1867,4 +1877,12 @@ pub const cpu = struct { | ... | @@ -1867,4 +1877,12 @@ pub const cpu = struct { |
| 1867 | .v8_2a, | 1877 | .v8_2a, |
| 1868 | }), | 1878 | }), |
| 1869 | }; | 1879 | }; |
| 1880 | pub const xgene1 = CpuModel{ | ||
| 1881 | .name = "xgene1", | ||
| 1882 | .llvm_name = null, | ||
| 1883 | .features = featureSet(&[_]Feature{ | ||
| 1884 | .perfmon, | ||
| 1885 | .v8a, | ||
| 1886 | }), | ||
| 1887 | }; | ||
| 1870 | }; | 1888 | }; |
lib/std/x.zig+23-1| ... | @@ -1 +1,23 @@ | ... | @@ -1 +1,23 @@ |
| 1 | pub const os = @import("x/os/os.zig"); | 1 | // SPDX-License-Identifier: MIT |
| 2 | // Copyright (c) 2015-2021 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 6 | |||
| 7 | const std = @import("std.zig"); | ||
| 8 | |||
| 9 | pub const os = struct { | ||
| 10 | pub const Socket = @import("x/os/Socket.zig"); | ||
| 11 | pub usingnamespace @import("x/os/net.zig"); | ||
| 12 | }; | ||
| 13 | |||
| 14 | pub const net = struct { | ||
| 15 | pub const ip = @import("x/net/ip.zig"); | ||
| 16 | pub const tcp = @import("x/net/tcp.zig"); | ||
| 17 | }; | ||
| 18 | |||
| 19 | test { | ||
| 20 | inline for (.{ os, net }) |module| { | ||
| 21 | std.testing.refAllDecls(module); | ||
| 22 | } | ||
| 23 | } |
lib/std/x/net/ip.zig created+61| ... | @@ -0,0 +1,61 @@ | ||
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2021 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 6 | |||
| 7 | const std = @import("../../std.zig"); | ||
| 8 | |||
| 9 | const fmt = std.fmt; | ||
| 10 | |||
| 11 | const IPv4 = std.x.os.IPv4; | ||
| 12 | const IPv6 = std.x.os.IPv6; | ||
| 13 | const Socket = std.x.os.Socket; | ||
| 14 | |||
| 15 | /// A generic IP abstraction. | ||
| 16 | const ip = @This(); | ||
| 17 | |||
| 18 | /// A union of all eligible types of IP addresses. | ||
| 19 | pub const Address = union(enum) { | ||
| 20 | ipv4: IPv4.Address, | ||
| 21 | ipv6: IPv6.Address, | ||
| 22 | |||
| 23 | /// Instantiate a new address with a IPv4 host and port. | ||
| 24 | pub fn initIPv4(host: IPv4, port: u16) Address { | ||
| 25 | return .{ .ipv4 = .{ .host = host, .port = port } }; | ||
| 26 | } | ||
| 27 | |||
| 28 | /// Instantiate a new address with a IPv6 host and port. | ||
| 29 | pub fn initIPv6(host: IPv6, port: u16) Address { | ||
| 30 | return .{ .ipv6 = .{ .host = host, .port = port } }; | ||
| 31 | } | ||
| 32 | |||
| 33 | /// Re-interpret a generic socket address into an IP address. | ||
| 34 | pub fn from(address: Socket.Address) ip.Address { | ||
| 35 | return switch (address) { | ||
| 36 | .ipv4 => |ipv4_address| .{ .ipv4 = ipv4_address }, | ||
| 37 | .ipv6 => |ipv6_address| .{ .ipv6 = ipv6_address }, | ||
| 38 | }; | ||
| 39 | } | ||
| 40 | |||
| 41 | /// Re-interpret an IP address into a generic socket address. | ||
| 42 | pub fn into(self: ip.Address) Socket.Address { | ||
| 43 | return switch (self) { | ||
| 44 | .ipv4 => |ipv4_address| .{ .ipv4 = ipv4_address }, | ||
| 45 | .ipv6 => |ipv6_address| .{ .ipv6 = ipv6_address }, | ||
| 46 | }; | ||
| 47 | } | ||
| 48 | |||
| 49 | /// Implements the `std.fmt.format` API. | ||
| 50 | pub fn format( | ||
| 51 | self: ip.Address, | ||
| 52 | comptime layout: []const u8, | ||
| 53 | opts: fmt.FormatOptions, | ||
| 54 | writer: anytype, | ||
| 55 | ) !void { | ||
| 56 | switch (self) { | ||
| 57 | .ipv4 => |address| try fmt.format(writer, "{}:{}", .{ address.host, address.port }), | ||
| 58 | .ipv6 => |address| try fmt.format(writer, "{}:{}", .{ address.host, address.port }), | ||
| 59 | } | ||
| 60 | } | ||
| 61 | }; | ||
lib/std/x/net/tcp.zig created+352| ... | @@ -0,0 +1,352 @@ | ||
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2021 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 6 | |||
| 7 | const std = @import("../../std.zig"); | ||
| 8 | |||
| 9 | const os = std.os; | ||
| 10 | const ip = std.x.net.ip; | ||
| 11 | |||
| 12 | const fmt = std.fmt; | ||
| 13 | const mem = std.mem; | ||
| 14 | const builtin = std.builtin; | ||
| 15 | const testing = std.testing; | ||
| 16 | |||
| 17 | const IPv4 = std.x.os.IPv4; | ||
| 18 | const IPv6 = std.x.os.IPv6; | ||
| 19 | const Socket = std.x.os.Socket; | ||
| 20 | |||
| 21 | /// A generic TCP socket abstraction. | ||
| 22 | const tcp = @This(); | ||
| 23 | |||
| 24 | /// A TCP client-address pair. | ||
| 25 | pub const Connection = struct { | ||
| 26 | client: tcp.Client, | ||
| 27 | address: ip.Address, | ||
| 28 | |||
| 29 | /// Enclose a TCP client and address into a client-address pair. | ||
| 30 | pub fn from(conn: Socket.Connection) tcp.Connection { | ||
| 31 | return .{ | ||
| 32 | .client = tcp.Client.from(conn.socket), | ||
| 33 | .address = ip.Address.from(conn.address), | ||
| 34 | }; | ||
| 35 | } | ||
| 36 | |||
| 37 | /// Unravel a TCP client-address pair into a socket-address pair. | ||
| 38 | pub fn into(self: tcp.Connection) Socket.Connection { | ||
| 39 | return .{ | ||
| 40 | .socket = self.client.socket, | ||
| 41 | .address = self.address.into(), | ||
| 42 | }; | ||
| 43 | } | ||
| 44 | |||
| 45 | /// Closes the underlying client of the connection. | ||
| 46 | pub fn deinit(self: tcp.Connection) void { | ||
| 47 | self.client.deinit(); | ||
| 48 | } | ||
| 49 | }; | ||
| 50 | |||
| 51 | /// Possible domains that a TCP client/listener may operate over. | ||
| 52 | pub const Domain = extern enum(u16) { | ||
| 53 | ip = os.AF_INET, | ||
| 54 | ipv6 = os.AF_INET6, | ||
| 55 | }; | ||
| 56 | |||
| 57 | /// A TCP client. | ||
| 58 | pub const Client = struct { | ||
| 59 | socket: Socket, | ||
| 60 | |||
| 61 | /// Opens a new client. | ||
| 62 | pub fn init(domain: tcp.Domain, flags: u32) !Client { | ||
| 63 | return Client{ | ||
| 64 | .socket = try Socket.init( | ||
| 65 | @enumToInt(domain), | ||
| 66 | os.SOCK_STREAM | flags, | ||
| 67 | os.IPPROTO_TCP, | ||
| 68 | ), | ||
| 69 | }; | ||
| 70 | } | ||
| 71 | |||
| 72 | /// Enclose a TCP client over an existing socket. | ||
| 73 | pub fn from(socket: Socket) Client { | ||
| 74 | return Client{ .socket = socket }; | ||
| 75 | } | ||
| 76 | |||
| 77 | /// Closes the client. | ||
| 78 | pub fn deinit(self: Client) void { | ||
| 79 | self.socket.deinit(); | ||
| 80 | } | ||
| 81 | |||
| 82 | /// Shutdown either the read side, write side, or all sides of the client's underlying socket. | ||
| 83 | pub fn shutdown(self: Client, how: os.ShutdownHow) !void { | ||
| 84 | return self.socket.shutdown(how); | ||
| 85 | } | ||
| 86 | |||
| 87 | /// Have the client attempt to the connect to an address. | ||
| 88 | pub fn connect(self: Client, address: ip.Address) !void { | ||
| 89 | return self.socket.connect(address.into()); | ||
| 90 | } | ||
| 91 | |||
| 92 | /// Read data from the socket into the buffer provided. It returns the | ||
| 93 | /// number of bytes read into the buffer provided. | ||
| 94 | pub fn read(self: Client, buf: []u8) !usize { | ||
| 95 | return self.socket.read(buf); | ||
| 96 | } | ||
| 97 | |||
| 98 | /// Read data from the socket into the buffer provided with a set of flags | ||
| 99 | /// specified. It returns the number of bytes read into the buffer provided. | ||
| 100 | pub fn recv(self: Client, buf: []u8, flags: u32) !usize { | ||
| 101 | return self.socket.recv(buf, flags); | ||
| 102 | } | ||
| 103 | |||
| 104 | /// Write a buffer of data provided to the socket. It returns the number | ||
| 105 | /// of bytes that are written to the socket. | ||
| 106 | pub fn write(self: Client, buf: []const u8) !usize { | ||
| 107 | return self.socket.write(buf); | ||
| 108 | } | ||
| 109 | |||
| 110 | /// Writes multiple I/O vectors to the socket. It returns the number | ||
| 111 | /// of bytes that are written to the socket. | ||
| 112 | pub fn writev(self: Client, buffers: []const os.iovec_const) !usize { | ||
| 113 | return self.socket.writev(buffers); | ||
| 114 | } | ||
| 115 | |||
| 116 | /// Write a buffer of data provided to the socket with a set of flags specified. | ||
| 117 | /// It returns the number of bytes that are written to the socket. | ||
| 118 | pub fn send(self: Client, buf: []const u8, flags: u32) !usize { | ||
| 119 | return self.socket.send(buf, flags); | ||
| 120 | } | ||
| 121 | |||
| 122 | /// Writes multiple I/O vectors with a prepended message header to the socket | ||
| 123 | /// with a set of flags specified. It returns the number of bytes that are | ||
| 124 | /// written to the socket. | ||
| 125 | pub fn sendmsg(self: Client, msg: os.msghdr_const, flags: u32) !usize { | ||
| 126 | return self.socket.sendmsg(msg, flags); | ||
| 127 | } | ||
| 128 | |||
| 129 | /// Query and return the latest cached error on the client's underlying socket. | ||
| 130 | pub fn getError(self: Client) !void { | ||
| 131 | return self.socket.getError(); | ||
| 132 | } | ||
| 133 | |||
| 134 | /// Query the read buffer size of the client's underlying socket. | ||
| 135 | pub fn getReadBufferSize(self: Client) !u32 { | ||
| 136 | return self.socket.getReadBufferSize(); | ||
| 137 | } | ||
| 138 | |||
| 139 | /// Query the write buffer size of the client's underlying socket. | ||
| 140 | pub fn getWriteBufferSize(self: Client) !u32 { | ||
| 141 | return self.socket.getWriteBufferSize(); | ||
| 142 | } | ||
| 143 | |||
| 144 | /// Query the address that the client's socket is locally bounded to. | ||
| 145 | pub fn getLocalAddress(self: Client) !ip.Address { | ||
| 146 | return ip.Address.from(try self.socket.getLocalAddress()); | ||
| 147 | } | ||
| 148 | |||
| 149 | /// Disable Nagle's algorithm on a TCP socket. It returns `error.UnsupportedSocketOption` if | ||
| 150 | /// the host does not support sockets disabling Nagle's algorithm. | ||
| 151 | pub fn setNoDelay(self: Client, enabled: bool) !void { | ||
| 152 | if (comptime @hasDecl(os, "TCP_NODELAY")) { | ||
| 153 | const bytes = mem.asBytes(&@as(usize, @boolToInt(enabled))); | ||
| 154 | return os.setsockopt(self.socket.fd, os.IPPROTO_TCP, os.TCP_NODELAY, bytes); | ||
| 155 | } | ||
| 156 | return error.UnsupportedSocketOption; | ||
| 157 | } | ||
| 158 | |||
| 159 | /// Set the write buffer size of the socket. | ||
| 160 | pub fn setWriteBufferSize(self: Client, size: u32) !void { | ||
| 161 | return self.socket.setWriteBufferSize(size); | ||
| 162 | } | ||
| 163 | |||
| 164 | /// Set the read buffer size of the socket. | ||
| 165 | pub fn setReadBufferSize(self: Client, size: u32) !void { | ||
| 166 | return self.socket.setReadBufferSize(size); | ||
| 167 | } | ||
| 168 | |||
| 169 | /// Set a timeout on the socket that is to occur if no messages are successfully written | ||
| 170 | /// to its bound destination after a specified number of milliseconds. A subsequent write | ||
| 171 | /// to the socket will thereafter return `error.WouldBlock` should the timeout be exceeded. | ||
| 172 | pub fn setWriteTimeout(self: Client, milliseconds: usize) !void { | ||
| 173 | return self.socket.setWriteTimeout(milliseconds); | ||
| 174 | } | ||
| 175 | |||
| 176 | /// Set a timeout on the socket that is to occur if no messages are successfully read | ||
| 177 | /// from its bound destination after a specified number of milliseconds. A subsequent | ||
| 178 | /// read from the socket will thereafter return `error.WouldBlock` should the timeout be | ||
| 179 | /// exceeded. | ||
| 180 | pub fn setReadTimeout(self: Client, milliseconds: usize) !void { | ||
| 181 | return self.socket.setReadTimeout(milliseconds); | ||
| 182 | } | ||
| 183 | }; | ||
| 184 | |||
| 185 | /// A TCP listener. | ||
| 186 | pub const Listener = struct { | ||
| 187 | socket: Socket, | ||
| 188 | |||
| 189 | /// Opens a new listener. | ||
| 190 | pub fn init(domain: tcp.Domain, flags: u32) !Listener { | ||
| 191 | return Listener{ | ||
| 192 | .socket = try Socket.init( | ||
| 193 | @enumToInt(domain), | ||
| 194 | os.SOCK_STREAM | flags, | ||
| 195 | os.IPPROTO_TCP, | ||
| 196 | ), | ||
| 197 | }; | ||
| 198 | } | ||
| 199 | |||
| 200 | /// Closes the listener. | ||
| 201 | pub fn deinit(self: Listener) void { | ||
| 202 | self.socket.deinit(); | ||
| 203 | } | ||
| 204 | |||
| 205 | /// Shuts down the underlying listener's socket. The next subsequent call, or | ||
| 206 | /// a current pending call to accept() after shutdown is called will return | ||
| 207 | /// an error. | ||
| 208 | pub fn shutdown(self: Listener) !void { | ||
| 209 | return self.socket.shutdown(.recv); | ||
| 210 | } | ||
| 211 | |||
| 212 | /// Binds the listener's socket to an address. | ||
| 213 | pub fn bind(self: Listener, address: ip.Address) !void { | ||
| 214 | return self.socket.bind(address.into()); | ||
| 215 | } | ||
| 216 | |||
| 217 | /// Start listening for incoming connections. | ||
| 218 | pub fn listen(self: Listener, max_backlog_size: u31) !void { | ||
| 219 | return self.socket.listen(max_backlog_size); | ||
| 220 | } | ||
| 221 | |||
| 222 | /// Accept a pending incoming connection queued to the kernel backlog | ||
| 223 | /// of the listener's socket. | ||
| 224 | pub fn accept(self: Listener, flags: u32) !tcp.Connection { | ||
| 225 | return tcp.Connection.from(try self.socket.accept(flags)); | ||
| 226 | } | ||
| 227 | |||
| 228 | /// Query and return the latest cached error on the listener's underlying socket. | ||
| 229 | pub fn getError(self: Client) !void { | ||
| 230 | return self.socket.getError(); | ||
| 231 | } | ||
| 232 | |||
| 233 | /// Query the address that the listener's socket is locally bounded to. | ||
| 234 | pub fn getLocalAddress(self: Listener) !ip.Address { | ||
| 235 | return ip.Address.from(try self.socket.getLocalAddress()); | ||
| 236 | } | ||
| 237 | |||
| 238 | /// Allow multiple sockets on the same host to listen on the same address. It returns `error.UnsupportedSocketOption` if | ||
| 239 | /// the host does not support sockets listening the same address. | ||
| 240 | pub fn setReuseAddress(self: Listener, enabled: bool) !void { | ||
| 241 | return self.socket.setReuseAddress(enabled); | ||
| 242 | } | ||
| 243 | |||
| 244 | /// Allow multiple sockets on the same host to listen on the same port. It returns `error.UnsupportedSocketOption` if | ||
| 245 | /// the host does not supports sockets listening on the same port. | ||
| 246 | pub fn setReusePort(self: Listener, enabled: bool) !void { | ||
| 247 | return self.socket.setReusePort(enabled); | ||
| 248 | } | ||
| 249 | |||
| 250 | /// Enables TCP Fast Open (RFC 7413) on a TCP socket. It returns `error.UnsupportedSocketOption` if the host does not | ||
| 251 | /// support TCP Fast Open. | ||
| 252 | pub fn setFastOpen(self: Listener, enabled: bool) !void { | ||
| 253 | if (comptime @hasDecl(os, "TCP_FASTOPEN")) { | ||
| 254 | return os.setsockopt(self.socket.fd, os.IPPROTO_TCP, os.TCP_FASTOPEN, mem.asBytes(&@as(usize, @boolToInt(enabled)))); | ||
| 255 | } | ||
| 256 | return error.UnsupportedSocketOption; | ||
| 257 | } | ||
| 258 | |||
| 259 | /// Enables TCP Quick ACK on a TCP socket to immediately send rather than delay ACKs when necessary. It returns | ||
| 260 | /// `error.UnsupportedSocketOption` if the host does not support TCP Quick ACK. | ||
| 261 | pub fn setQuickACK(self: Listener, enabled: bool) !void { | ||
| 262 | if (comptime @hasDecl(os, "TCP_QUICKACK")) { | ||
| 263 | return os.setsockopt(self.socket.fd, os.IPPROTO_TCP, os.TCP_QUICKACK, mem.asBytes(&@as(usize, @boolToInt(enabled)))); | ||
| 264 | } | ||
| 265 | return error.UnsupportedSocketOption; | ||
| 266 | } | ||
| 267 | |||
| 268 | /// Set a timeout on the listener that is to occur if no new incoming connections come in | ||
| 269 | /// after a specified number of milliseconds. A subsequent accept call to the listener | ||
| 270 | /// will thereafter return `error.WouldBlock` should the timeout be exceeded. | ||
| 271 | pub fn setAcceptTimeout(self: Listener, milliseconds: usize) !void { | ||
| 272 | return self.socket.setReadTimeout(milliseconds); | ||
| 273 | } | ||
| 274 | }; | ||
| 275 | |||
| 276 | test "tcp: create client/listener pair" { | ||
| 277 | if (builtin.os.tag == .wasi) return error.SkipZigTest; | ||
| 278 | |||
| 279 | const listener = try tcp.Listener.init(.ip, os.SOCK_CLOEXEC); | ||
| 280 | defer listener.deinit(); | ||
| 281 | |||
| 282 | try listener.bind(ip.Address.initIPv4(IPv4.unspecified, 0)); | ||
| 283 | try listener.listen(128); | ||
| 284 | |||
| 285 | var binded_address = try listener.getLocalAddress(); | ||
| 286 | switch (binded_address) { | ||
| 287 | .ipv4 => |*ipv4| ipv4.host = IPv4.localhost, | ||
| 288 | .ipv6 => |*ipv6| ipv6.host = IPv6.localhost, | ||
| 289 | } | ||
| 290 | |||
| 291 | const client = try tcp.Client.init(.ip, os.SOCK_CLOEXEC); | ||
| 292 | defer client.deinit(); | ||
| 293 | |||
| 294 | try client.connect(binded_address); | ||
| 295 | |||
| 296 | const conn = try listener.accept(os.SOCK_CLOEXEC); | ||
| 297 | defer conn.deinit(); | ||
| 298 | } | ||
| 299 | |||
| 300 | test "tcp/client: set read timeout of 1 millisecond on blocking client" { | ||
| 301 | if (builtin.os.tag == .wasi) return error.SkipZigTest; | ||
| 302 | |||
| 303 | const listener = try tcp.Listener.init(.ip, os.SOCK_CLOEXEC); | ||
| 304 | defer listener.deinit(); | ||
| 305 | |||
| 306 | try listener.bind(ip.Address.initIPv4(IPv4.unspecified, 0)); | ||
| 307 | try listener.listen(128); | ||
| 308 | |||
| 309 | var binded_address = try listener.getLocalAddress(); | ||
| 310 | switch (binded_address) { | ||
| 311 | .ipv4 => |*ipv4| ipv4.host = IPv4.localhost, | ||
| 312 | .ipv6 => |*ipv6| ipv6.host = IPv6.localhost, | ||
| 313 | } | ||
| 314 | |||
| 315 | const client = try tcp.Client.init(.ip, os.SOCK_CLOEXEC); | ||
| 316 | defer client.deinit(); | ||
| 317 | |||
| 318 | try client.connect(binded_address); | ||
| 319 | try client.setReadTimeout(1); | ||
| 320 | |||
| 321 | const conn = try listener.accept(os.SOCK_CLOEXEC); | ||
| 322 | defer conn.deinit(); | ||
| 323 | |||
| 324 | var buf: [1]u8 = undefined; | ||
| 325 | testing.expectError(error.WouldBlock, client.read(&buf)); | ||
| 326 | } | ||
| 327 | |||
| 328 | test "tcp/listener: bind to unspecified ipv4 address" { | ||
| 329 | if (builtin.os.tag == .wasi) return error.SkipZigTest; | ||
| 330 | |||
| 331 | const listener = try tcp.Listener.init(.ip, os.SOCK_CLOEXEC); | ||
| 332 | defer listener.deinit(); | ||
| 333 | |||
| 334 | try listener.bind(ip.Address.initIPv4(IPv4.unspecified, 0)); | ||
| 335 | try listener.listen(128); | ||
| 336 | |||
| 337 | const address = try listener.getLocalAddress(); | ||
| 338 | testing.expect(address == .ipv4); | ||
| 339 | } | ||
| 340 | |||
| 341 | test "tcp/listener: bind to unspecified ipv6 address" { | ||
| 342 | if (builtin.os.tag == .wasi) return error.SkipZigTest; | ||
| 343 | |||
| 344 | const listener = try tcp.Listener.init(.ipv6, os.SOCK_CLOEXEC); | ||
| 345 | defer listener.deinit(); | ||
| 346 | |||
| 347 | try listener.bind(ip.Address.initIPv6(IPv6.unspecified, 0)); | ||
| 348 | try listener.listen(128); | ||
| 349 | |||
| 350 | const address = try listener.getLocalAddress(); | ||
| 351 | testing.expect(address == .ipv6); | ||
| 352 | } | ||
lib/std/x/os/Socket.zig+115-96| ... | @@ -1,18 +1,110 @@ | ... | @@ -1,18 +1,110 @@ |
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2021 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 6 | |||
| 1 | const std = @import("../../std.zig"); | 7 | const std = @import("../../std.zig"); |
| 8 | const net = @import("net.zig"); | ||
| 2 | 9 | ||
| 3 | const os = std.os; | 10 | const os = std.os; |
| 11 | const fmt = std.fmt; | ||
| 4 | const mem = std.mem; | 12 | const mem = std.mem; |
| 5 | const net = std.net; | ||
| 6 | const time = std.time; | 13 | const time = std.time; |
| 7 | const builtin = std.builtin; | ||
| 8 | const testing = std.testing; | ||
| 9 | 14 | ||
| 15 | /// A generic socket abstraction. | ||
| 10 | const Socket = @This(); | 16 | const Socket = @This(); |
| 11 | 17 | ||
| 12 | /// A socket-address pair. | 18 | /// A socket-address pair. |
| 13 | pub const Connection = struct { | 19 | pub const Connection = struct { |
| 14 | socket: Socket, | 20 | socket: Socket, |
| 15 | address: net.Address, | 21 | address: Socket.Address, |
| 22 | |||
| 23 | /// Enclose a socket and address into a socket-address pair. | ||
| 24 | pub fn from(socket: Socket, address: Socket.Address) Socket.Connection { | ||
| 25 | return .{ .socket = socket, .address = address }; | ||
| 26 | } | ||
| 27 | }; | ||
| 28 | |||
| 29 | /// A generic socket address abstraction. It is safe to directly access and modify | ||
| 30 | /// the fields of a `Socket.Address`. | ||
| 31 | pub const Address = union(enum) { | ||
| 32 | ipv4: net.IPv4.Address, | ||
| 33 | ipv6: net.IPv6.Address, | ||
| 34 | |||
| 35 | /// Instantiate a new address with a IPv4 host and port. | ||
| 36 | pub fn initIPv4(host: net.IPv4, port: u16) Socket.Address { | ||
| 37 | return .{ .ipv4 = .{ .host = host, .port = port } }; | ||
| 38 | } | ||
| 39 | |||
| 40 | /// Instantiate a new address with a IPv6 host and port. | ||
| 41 | pub fn initIPv6(host: net.IPv6, port: u16) Socket.Address { | ||
| 42 | return .{ .ipv6 = .{ .host = host, .port = port } }; | ||
| 43 | } | ||
| 44 | |||
| 45 | /// Parses a `sockaddr` into a generic socket address. | ||
| 46 | pub fn fromNative(address: *align(4) const os.sockaddr) Socket.Address { | ||
| 47 | switch (address.family) { | ||
| 48 | os.AF_INET => { | ||
| 49 | const info = @ptrCast(*const os.sockaddr_in, address); | ||
| 50 | const host = net.IPv4{ .octets = @bitCast([4]u8, info.addr) }; | ||
| 51 | const port = mem.bigToNative(u16, info.port); | ||
| 52 | return Socket.Address.initIPv4(host, port); | ||
| 53 | }, | ||
| 54 | os.AF_INET6 => { | ||
| 55 | const info = @ptrCast(*const os.sockaddr_in6, address); | ||
| 56 | const host = net.IPv6{ .octets = info.addr, .scope_id = info.scope_id }; | ||
| 57 | const port = mem.bigToNative(u16, info.port); | ||
| 58 | return Socket.Address.initIPv6(host, port); | ||
| 59 | }, | ||
| 60 | else => unreachable, | ||
| 61 | } | ||
| 62 | } | ||
| 63 | |||
| 64 | /// Encodes a generic socket address into an extern union that may be reliably | ||
| 65 | /// casted into a `sockaddr` which may be passed into socket syscalls. | ||
| 66 | pub fn toNative(self: Socket.Address) extern union { | ||
| 67 | ipv4: os.sockaddr_in, | ||
| 68 | ipv6: os.sockaddr_in6, | ||
| 69 | } { | ||
| 70 | return switch (self) { | ||
| 71 | .ipv4 => |address| .{ | ||
| 72 | .ipv4 = .{ | ||
| 73 | .addr = @bitCast(u32, address.host.octets), | ||
| 74 | .port = mem.nativeToBig(u16, address.port), | ||
| 75 | }, | ||
| 76 | }, | ||
| 77 | .ipv6 => |address| .{ | ||
| 78 | .ipv6 = .{ | ||
| 79 | .addr = address.host.octets, | ||
| 80 | .port = mem.nativeToBig(u16, address.port), | ||
| 81 | .scope_id = address.host.scope_id, | ||
| 82 | .flowinfo = 0, | ||
| 83 | }, | ||
| 84 | }, | ||
| 85 | }; | ||
| 86 | } | ||
| 87 | |||
| 88 | /// Returns the number of bytes that make up the `sockaddr` equivalent to the address. | ||
| 89 | pub fn getNativeSize(self: Socket.Address) u32 { | ||
| 90 | return switch (self) { | ||
| 91 | .ipv4 => @sizeOf(os.sockaddr_in), | ||
| 92 | .ipv6 => @sizeOf(os.sockaddr_in6), | ||
| 93 | }; | ||
| 94 | } | ||
| 95 | |||
| 96 | /// Implements the `std.fmt.format` API. | ||
| 97 | pub fn format( | ||
| 98 | self: Socket.Address, | ||
| 99 | comptime layout: []const u8, | ||
| 100 | opts: fmt.FormatOptions, | ||
| 101 | writer: anytype, | ||
| 102 | ) !void { | ||
| 103 | switch (self) { | ||
| 104 | .ipv4 => |address| try fmt.format(writer, "{}:{}", .{ address.host, address.port }), | ||
| 105 | .ipv6 => |address| try fmt.format(writer, "{}:{}", .{ address.host, address.port }), | ||
| 106 | } | ||
| 107 | } | ||
| 16 | }; | 108 | }; |
| 17 | 109 | ||
| 18 | /// The underlying handle of a socket. | 110 | /// The underlying handle of a socket. |
| ... | @@ -23,19 +115,24 @@ pub fn init(domain: u32, socket_type: u32, protocol: u32) !Socket { | ... | @@ -23,19 +115,24 @@ pub fn init(domain: u32, socket_type: u32, protocol: u32) !Socket { |
| 23 | return Socket{ .fd = try os.socket(domain, socket_type, protocol) }; | 115 | return Socket{ .fd = try os.socket(domain, socket_type, protocol) }; |
| 24 | } | 116 | } |
| 25 | 117 | ||
| 118 | /// Enclose a socket abstraction over an existing socket file descriptor. | ||
| 119 | pub fn from(fd: os.socket_t) Socket { | ||
| 120 | return Socket{ .fd = fd }; | ||
| 121 | } | ||
| 122 | |||
| 26 | /// Closes the socket. | 123 | /// Closes the socket. |
| 27 | pub fn deinit(self: Socket) void { | 124 | pub fn deinit(self: Socket) void { |
| 28 | os.closeSocket(self.fd); | 125 | os.closeSocket(self.fd); |
| 29 | } | 126 | } |
| 30 | 127 | ||
| 31 | /// Shutdown either the read side, or write side, or the entirety of a socket. | 128 | /// Shutdown either the read side, write side, or all side of the socket. |
| 32 | pub fn shutdown(self: Socket, how: os.ShutdownHow) !void { | 129 | pub fn shutdown(self: Socket, how: os.ShutdownHow) !void { |
| 33 | return os.shutdown(self.fd, how); | 130 | return os.shutdown(self.fd, how); |
| 34 | } | 131 | } |
| 35 | 132 | ||
| 36 | /// Binds the socket to an address. | 133 | /// Binds the socket to an address. |
| 37 | pub fn bind(self: Socket, address: net.Address) !void { | 134 | pub fn bind(self: Socket, address: Socket.Address) !void { |
| 38 | return os.bind(self.fd, &address.any, address.getOsSockLen()); | 135 | return os.bind(self.fd, @ptrCast(*const os.sockaddr, &address.toNative()), address.getNativeSize()); |
| 39 | } | 136 | } |
| 40 | 137 | ||
| 41 | /// Start listening for incoming connections on the socket. | 138 | /// Start listening for incoming connections on the socket. |
| ... | @@ -44,8 +141,8 @@ pub fn listen(self: Socket, max_backlog_size: u31) !void { | ... | @@ -44,8 +141,8 @@ pub fn listen(self: Socket, max_backlog_size: u31) !void { |
| 44 | } | 141 | } |
| 45 | 142 | ||
| 46 | /// Have the socket attempt to the connect to an address. | 143 | /// Have the socket attempt to the connect to an address. |
| 47 | pub fn connect(self: Socket, address: net.Address) !void { | 144 | pub fn connect(self: Socket, address: Socket.Address) !void { |
| 48 | return os.connect(self.fd, &address.any, address.getOsSockLen()); | 145 | return os.connect(self.fd, @ptrCast(*const os.sockaddr, &address.toNative()), address.getNativeSize()); |
| 49 | } | 146 | } |
| 50 | 147 | ||
| 51 | /// Accept a pending incoming connection queued to the kernel backlog | 148 | /// Accept a pending incoming connection queued to the kernel backlog |
| ... | @@ -54,12 +151,10 @@ pub fn accept(self: Socket, flags: u32) !Socket.Connection { | ... | @@ -54,12 +151,10 @@ pub fn accept(self: Socket, flags: u32) !Socket.Connection { |
| 54 | var address: os.sockaddr = undefined; | 151 | var address: os.sockaddr = undefined; |
| 55 | var address_len: u32 = @sizeOf(os.sockaddr); | 152 | var address_len: u32 = @sizeOf(os.sockaddr); |
| 56 | 153 | ||
| 57 | const fd = try os.accept(self.fd, &address, &address_len, flags); | 154 | const socket = Socket{ .fd = try os.accept(self.fd, &address, &address_len, flags) }; |
| 155 | const socket_address = Socket.Address.fromNative(@alignCast(4, &address)); | ||
| 58 | 156 | ||
| 59 | return Connection{ | 157 | return Socket.Connection.from(socket, socket_address); |
| 60 | .socket = Socket{ .fd = fd }, | ||
| 61 | .address = net.Address.initPosix(@alignCast(4, &address)), | ||
| 62 | }; | ||
| 63 | } | 158 | } |
| 64 | 159 | ||
| 65 | /// Read data from the socket into the buffer provided. It returns the | 160 | /// Read data from the socket into the buffer provided. It returns the |
| ... | @@ -100,11 +195,11 @@ pub fn sendmsg(self: Socket, msg: os.msghdr_const, flags: u32) !usize { | ... | @@ -100,11 +195,11 @@ pub fn sendmsg(self: Socket, msg: os.msghdr_const, flags: u32) !usize { |
| 100 | } | 195 | } |
| 101 | 196 | ||
| 102 | /// Query the address that the socket is locally bounded to. | 197 | /// Query the address that the socket is locally bounded to. |
| 103 | pub fn getLocalAddress(self: Socket) !net.Address { | 198 | pub fn getLocalAddress(self: Socket) !Socket.Address { |
| 104 | var address: os.sockaddr = undefined; | 199 | var address: os.sockaddr = undefined; |
| 105 | var address_len: u32 = @sizeOf(os.sockaddr); | 200 | var address_len: u32 = @sizeOf(os.sockaddr); |
| 106 | try os.getsockname(self.fd, &address, &address_len); | 201 | try os.getsockname(self.fd, &address, &address_len); |
| 107 | return net.Address.initPosix(@alignCast(4, &address)); | 202 | return Socket.Address.fromNative(@alignCast(4, &address)); |
| 108 | } | 203 | } |
| 109 | 204 | ||
| 110 | /// Query and return the latest cached error on the socket. | 205 | /// Query and return the latest cached error on the socket. |
| ... | @@ -164,33 +259,6 @@ pub fn setReusePort(self: Socket, enabled: bool) !void { | ... | @@ -164,33 +259,6 @@ pub fn setReusePort(self: Socket, enabled: bool) !void { |
| 164 | return error.UnsupportedSocketOption; | 259 | return error.UnsupportedSocketOption; |
| 165 | } | 260 | } |
| 166 | 261 | ||
| 167 | /// Disable Nagle's algorithm on a TCP socket. It returns `error.UnsupportedSocketOption` if the host does not support | ||
| 168 | /// sockets disabling Nagle's algorithm. | ||
| 169 | pub fn setNoDelay(self: Socket, enabled: bool) !void { | ||
| 170 | if (comptime @hasDecl(os, "TCP_NODELAY")) { | ||
| 171 | return os.setsockopt(self.fd, os.IPPROTO_TCP, os.TCP_NODELAY, mem.asBytes(&@as(usize, @boolToInt(enabled)))); | ||
| 172 | } | ||
| 173 | return error.UnsupportedSocketOption; | ||
| 174 | } | ||
| 175 | |||
| 176 | /// Enables TCP Fast Open (RFC 7413) on a TCP socket. It returns `error.UnsupportedSocketOption` if the host does not | ||
| 177 | /// support TCP Fast Open. | ||
| 178 | pub fn setFastOpen(self: Socket, enabled: bool) !void { | ||
| 179 | if (comptime @hasDecl(os, "TCP_FASTOPEN")) { | ||
| 180 | return os.setsockopt(self.fd, os.IPPROTO_TCP, os.TCP_FASTOPEN, mem.asBytes(&@as(usize, @boolToInt(enabled)))); | ||
| 181 | } | ||
| 182 | return error.UnsupportedSocketOption; | ||
| 183 | } | ||
| 184 | |||
| 185 | /// Enables TCP Quick ACK on a TCP socket to immediately send rather than delay ACKs when necessary. It returns | ||
| 186 | /// `error.UnsupportedSocketOption` if the host does not support TCP Quick ACK. | ||
| 187 | pub fn setQuickACK(self: Socket, enabled: bool) !void { | ||
| 188 | if (comptime @hasDecl(os, "TCP_QUICKACK")) { | ||
| 189 | return os.setsockopt(self.fd, os.IPPROTO_TCP, os.TCP_QUICKACK, mem.asBytes(&@as(usize, @boolToInt(enabled)))); | ||
| 190 | } | ||
| 191 | return error.UnsupportedSocketOption; | ||
| 192 | } | ||
| 193 | |||
| 194 | /// Set the write buffer size of the socket. | 262 | /// Set the write buffer size of the socket. |
| 195 | pub fn setWriteBufferSize(self: Socket, size: u32) !void { | 263 | pub fn setWriteBufferSize(self: Socket, size: u32) !void { |
| 196 | return os.setsockopt(self.fd, os.SOL_SOCKET, os.SO_SNDBUF, mem.asBytes(&size)); | 264 | return os.setsockopt(self.fd, os.SOL_SOCKET, os.SO_SNDBUF, mem.asBytes(&size)); |
| ... | @@ -206,8 +274,8 @@ pub fn setReadBufferSize(self: Socket, size: u32) !void { | ... | @@ -206,8 +274,8 @@ pub fn setReadBufferSize(self: Socket, size: u32) !void { |
| 206 | /// to the socket will thereafter return `error.WouldBlock` should the timeout be exceeded. | 274 | /// to the socket will thereafter return `error.WouldBlock` should the timeout be exceeded. |
| 207 | pub fn setWriteTimeout(self: Socket, milliseconds: usize) !void { | 275 | pub fn setWriteTimeout(self: Socket, milliseconds: usize) !void { |
| 208 | const timeout = os.timeval{ | 276 | const timeout = os.timeval{ |
| 209 | .tv_sec = @intCast(isize, milliseconds / time.ms_per_s), | 277 | .tv_sec = @intCast(i32, milliseconds / time.ms_per_s), |
| 210 | .tv_usec = @intCast(isize, (milliseconds % time.ms_per_s) * time.us_per_ms), | 278 | .tv_usec = @intCast(i32, (milliseconds % time.ms_per_s) * time.us_per_ms), |
| 211 | }; | 279 | }; |
| 212 | 280 | ||
| 213 | return os.setsockopt(self.fd, os.SOL_SOCKET, os.SO_SNDTIMEO, mem.asBytes(&timeout)); | 281 | return os.setsockopt(self.fd, os.SOL_SOCKET, os.SO_SNDTIMEO, mem.asBytes(&timeout)); |
| ... | @@ -219,58 +287,9 @@ pub fn setWriteTimeout(self: Socket, milliseconds: usize) !void { | ... | @@ -219,58 +287,9 @@ pub fn setWriteTimeout(self: Socket, milliseconds: usize) !void { |
| 219 | /// exceeded. | 287 | /// exceeded. |
| 220 | pub fn setReadTimeout(self: Socket, milliseconds: usize) !void { | 288 | pub fn setReadTimeout(self: Socket, milliseconds: usize) !void { |
| 221 | const timeout = os.timeval{ | 289 | const timeout = os.timeval{ |
| 222 | .tv_sec = @intCast(isize, milliseconds / time.ms_per_s), | 290 | .tv_sec = @intCast(i32, milliseconds / time.ms_per_s), |
| 223 | .tv_usec = @intCast(isize, (milliseconds % time.ms_per_s) * time.us_per_ms), | 291 | .tv_usec = @intCast(i32, (milliseconds % time.ms_per_s) * time.us_per_ms), |
| 224 | }; | 292 | }; |
| 225 | 293 | ||
| 226 | return os.setsockopt(self.fd, os.SOL_SOCKET, os.SO_RCVTIMEO, mem.asBytes(&timeout)); | 294 | return os.setsockopt(self.fd, os.SOL_SOCKET, os.SO_RCVTIMEO, mem.asBytes(&timeout)); |
| 227 | } | 295 | } |
| 228 | |||
| 229 | test { | ||
| 230 | testing.refAllDecls(@This()); | ||
| 231 | } | ||
| 232 | |||
| 233 | test "socket/linux: set read timeout of 1 millisecond on blocking socket" { | ||
| 234 | if (builtin.os.tag != .linux) return error.SkipZigTest; | ||
| 235 | |||
| 236 | const a = try Socket.init(os.AF_INET, os.SOCK_STREAM | os.SOCK_CLOEXEC, os.IPPROTO_TCP); | ||
| 237 | defer a.deinit(); | ||
| 238 | |||
| 239 | try a.bind(net.Address.initIp4([_]u8{ 0, 0, 0, 0 }, 0)); | ||
| 240 | try a.listen(128); | ||
| 241 | |||
| 242 | const binded_address = try a.getLocalAddress(); | ||
| 243 | |||
| 244 | const b = try Socket.init(os.AF_INET, os.SOCK_STREAM | os.SOCK_CLOEXEC, os.IPPROTO_TCP); | ||
| 245 | defer b.deinit(); | ||
| 246 | |||
| 247 | try b.connect(binded_address); | ||
| 248 | try b.setReadTimeout(1); | ||
| 249 | |||
| 250 | const ab = try a.accept(os.SOCK_CLOEXEC); | ||
| 251 | defer ab.socket.deinit(); | ||
| 252 | |||
| 253 | var buf: [1]u8 = undefined; | ||
| 254 | testing.expectError(error.WouldBlock, b.read(&buf)); | ||
| 255 | } | ||
| 256 | |||
| 257 | test "socket/linux: create non-blocking socket pair" { | ||
| 258 | if (builtin.os.tag != .linux) return error.SkipZigTest; | ||
| 259 | |||
| 260 | const a = try Socket.init(os.AF_INET, os.SOCK_STREAM | os.SOCK_NONBLOCK | os.SOCK_CLOEXEC, os.IPPROTO_TCP); | ||
| 261 | defer a.deinit(); | ||
| 262 | |||
| 263 | try a.bind(net.Address.initIp4([_]u8{ 0, 0, 0, 0 }, 0)); | ||
| 264 | try a.listen(128); | ||
| 265 | |||
| 266 | const binded_address = try a.getLocalAddress(); | ||
| 267 | |||
| 268 | const b = try Socket.init(os.AF_INET, os.SOCK_STREAM | os.SOCK_NONBLOCK | os.SOCK_CLOEXEC, os.IPPROTO_TCP); | ||
| 269 | defer b.deinit(); | ||
| 270 | |||
| 271 | testing.expectError(error.WouldBlock, b.connect(binded_address)); | ||
| 272 | try b.getError(); | ||
| 273 | |||
| 274 | const ab = try a.accept(os.SOCK_NONBLOCK | os.SOCK_CLOEXEC); | ||
| 275 | defer ab.socket.deinit(); | ||
| 276 | } |
lib/std/x/os/net.zig created+567| ... | @@ -0,0 +1,567 @@ | ||
| 1 | // SPDX-License-Identifier: MIT | ||
| 2 | // Copyright (c) 2015-2021 Zig Contributors | ||
| 3 | // This file is part of [zig](https://ziglang.org/), which is MIT licensed. | ||
| 4 | // The MIT license requires this copyright notice to be included in all copies | ||
| 5 | // and substantial portions of the software. | ||
| 6 | |||
| 7 | const std = @import("../../std.zig"); | ||
| 8 | |||
| 9 | const os = std.os; | ||
| 10 | const fmt = std.fmt; | ||
| 11 | const mem = std.mem; | ||
| 12 | const math = std.math; | ||
| 13 | const builtin = std.builtin; | ||
| 14 | const testing = std.testing; | ||
| 15 | |||
| 16 | /// Resolves a network interface name into a scope/zone ID. It returns | ||
| 17 | /// an error if either resolution fails, or if the interface name is | ||
| 18 | /// too long. | ||
| 19 | pub fn resolveScopeID(name: []const u8) !u32 { | ||
| 20 | if (comptime @hasDecl(os, "IFNAMESIZE")) { | ||
| 21 | if (name.len >= os.IFNAMESIZE - 1) return error.NameTooLong; | ||
| 22 | |||
| 23 | const fd = try os.socket(os.AF_UNIX, os.SOCK_DGRAM, 0); | ||
| 24 | defer os.closeSocket(fd); | ||
| 25 | |||
| 26 | var f: os.ifreq = undefined; | ||
| 27 | mem.copy(u8, &f.ifrn.name, name); | ||
| 28 | f.ifrn.name[name.len] = 0; | ||
| 29 | |||
| 30 | try os.ioctl_SIOCGIFINDEX(fd, &f); | ||
| 31 | |||
| 32 | return @bitCast(u32, f.ifru.ivalue); | ||
| 33 | } | ||
| 34 | return error.Unsupported; | ||
| 35 | } | ||
| 36 | |||
| 37 | /// An IPv4 address comprised of 4 bytes. | ||
| 38 | pub const IPv4 = extern struct { | ||
| 39 | /// A IPv4 host-port pair. | ||
| 40 | pub const Address = extern struct { | ||
| 41 | host: IPv4, | ||
| 42 | port: u16, | ||
| 43 | }; | ||
| 44 | |||
| 45 | /// Octets of a IPv4 address designating the local host. | ||
| 46 | pub const localhost_octets = [_]u8{ 127, 0, 0, 1 }; | ||
| 47 | |||
| 48 | /// The IPv4 address of the local host. | ||
| 49 | pub const localhost: IPv4 = .{ .octets = localhost_octets }; | ||
| 50 | |||
| 51 | /// Octets of an unspecified IPv4 address. | ||
| 52 | pub const unspecified_octets = [_]u8{0} ** 4; | ||
| 53 | |||
| 54 | /// An unspecified IPv4 address. | ||
| 55 | pub const unspecified: IPv4 = .{ .octets = unspecified_octets }; | ||
| 56 | |||
| 57 | /// Octets of a broadcast IPv4 address. | ||
| 58 | pub const broadcast_octets = [_]u8{255} ** 4; | ||
| 59 | |||
| 60 | /// An IPv4 broadcast address. | ||
| 61 | pub const broadcast: IPv4 = .{ .octets = broadcast_octets }; | ||
| 62 | |||
| 63 | /// The prefix octet pattern of a link-local IPv4 address. | ||
| 64 | pub const link_local_prefix = [_]u8{ 169, 254 }; | ||
| 65 | |||
| 66 | /// The prefix octet patterns of IPv4 addresses intended for | ||
| 67 | /// documentation. | ||
| 68 | pub const documentation_prefixes = [_][]const u8{ | ||
| 69 | &[_]u8{ 192, 0, 2 }, | ||
| 70 | &[_]u8{ 198, 51, 100 }, | ||
| 71 | &[_]u8{ 203, 0, 113 }, | ||
| 72 | }; | ||
| 73 | |||
| 74 | octets: [4]u8, | ||
| 75 | |||
| 76 | /// Returns whether or not the two addresses are equal to, less than, or | ||
| 77 | /// greater than each other. | ||
| 78 | pub fn cmp(self: IPv4, other: IPv4) math.Order { | ||
| 79 | return mem.order(u8, &self.octets, &other.octets); | ||
| 80 | } | ||
| 81 | |||
| 82 | /// Returns true if both addresses are semantically equivalent. | ||
| 83 | pub fn eql(self: IPv4, other: IPv4) bool { | ||
| 84 | return mem.eql(u8, &self.octets, &other.octets); | ||
| 85 | } | ||
| 86 | |||
| 87 | /// Returns true if the address is a loopback address. | ||
| 88 | pub fn isLoopback(self: IPv4) bool { | ||
| 89 | return self.octets[0] == 127; | ||
| 90 | } | ||
| 91 | |||
| 92 | /// Returns true if the address is an unspecified IPv4 address. | ||
| 93 | pub fn isUnspecified(self: IPv4) bool { | ||
| 94 | return mem.eql(u8, &self.octets, &unspecified_octets); | ||
| 95 | } | ||
| 96 | |||
| 97 | /// Returns true if the address is a private IPv4 address. | ||
| 98 | pub fn isPrivate(self: IPv4) bool { | ||
| 99 | return self.octets[0] == 10 or | ||
| 100 | (self.octets[0] == 172 and self.octets[1] >= 16 and self.octets[1] <= 31) or | ||
| 101 | (self.octets[0] == 192 and self.octets[1] == 168); | ||
| 102 | } | ||
| 103 | |||
| 104 | /// Returns true if the address is a link-local IPv4 address. | ||
| 105 | pub fn isLinkLocal(self: IPv4) bool { | ||
| 106 | return mem.startsWith(u8, &self.octets, &link_local_prefix); | ||
| 107 | } | ||
| 108 | |||
| 109 | /// Returns true if the address is a multicast IPv4 address. | ||
| 110 | pub fn isMulticast(self: IPv4) bool { | ||
| 111 | return self.octets[0] >= 224 and self.octets[0] <= 239; | ||
| 112 | } | ||
| 113 | |||
| 114 | /// Returns true if the address is a IPv4 broadcast address. | ||
| 115 | pub fn isBroadcast(self: IPv4) bool { | ||
| 116 | return mem.eql(u8, &self.octets, &broadcast_octets); | ||
| 117 | } | ||
| 118 | |||
| 119 | /// Returns true if the address is in a range designated for documentation. Refer | ||
| 120 | /// to IETF RFC 5737 for more details. | ||
| 121 | pub fn isDocumentation(self: IPv4) bool { | ||
| 122 | inline for (documentation_prefixes) |prefix| { | ||
| 123 | if (mem.startsWith(u8, &self.octets, prefix)) { | ||
| 124 | return true; | ||
| 125 | } | ||
| 126 | } | ||
| 127 | return false; | ||
| 128 | } | ||
| 129 | |||
| 130 | /// Implements the `std.fmt.format` API. | ||
| 131 | pub fn format( | ||
| 132 | self: IPv4, | ||
| 133 | comptime layout: []const u8, | ||
| 134 | opts: fmt.FormatOptions, | ||
| 135 | writer: anytype, | ||
| 136 | ) !void { | ||
| 137 | if (comptime layout.len != 0 and layout[0] != 's') { | ||
| 138 | @compileError("Unsupported format specifier for IPv4 type '" ++ layout ++ "'."); | ||
| 139 | } | ||
| 140 | |||
| 141 | try fmt.format(writer, "{}.{}.{}.{}", .{ | ||
| 142 | self.octets[0], | ||
| 143 | self.octets[1], | ||
| 144 | self.octets[2], | ||
| 145 | self.octets[3], | ||
| 146 | }); | ||
| 147 | } | ||
| 148 | |||
| 149 | /// Set of possible errors that may encountered when parsing an IPv4 | ||
| 150 | /// address. | ||
| 151 | pub const ParseError = error{ | ||
| 152 | UnexpectedEndOfOctet, | ||
| 153 | TooManyOctets, | ||
| 154 | OctetOverflow, | ||
| 155 | UnexpectedToken, | ||
| 156 | IncompleteAddress, | ||
| 157 | }; | ||
| 158 | |||
| 159 | /// Parses an arbitrary IPv4 address. | ||
| 160 | pub fn parse(buf: []const u8) ParseError!IPv4 { | ||
| 161 | var octets: [4]u8 = undefined; | ||
| 162 | var octet: u8 = 0; | ||
| 163 | |||
| 164 | var index: u8 = 0; | ||
| 165 | var saw_any_digits: bool = false; | ||
| 166 | |||
| 167 | for (buf) |c| { | ||
| 168 | switch (c) { | ||
| 169 | '.' => { | ||
| 170 | if (!saw_any_digits) return error.UnexpectedEndOfOctet; | ||
| 171 | if (index == 3) return error.TooManyOctets; | ||
| 172 | octets[index] = octet; | ||
| 173 | index += 1; | ||
| 174 | octet = 0; | ||
| 175 | saw_any_digits = false; | ||
| 176 | }, | ||
| 177 | '0'...'9' => { | ||
| 178 | saw_any_digits = true; | ||
| 179 | octet = math.mul(u8, octet, 10) catch return error.OctetOverflow; | ||
| 180 | octet = math.add(u8, octet, c - '0') catch return error.OctetOverflow; | ||
| 181 | }, | ||
| 182 | else => return error.UnexpectedToken, | ||
| 183 | } | ||
| 184 | } | ||
| 185 | |||
| 186 | if (index == 3 and saw_any_digits) { | ||
| 187 | octets[index] = octet; | ||
| 188 | return IPv4{ .octets = octets }; | ||
| 189 | } | ||
| 190 | |||
| 191 | return error.IncompleteAddress; | ||
| 192 | } | ||
| 193 | |||
| 194 | /// Maps the address to its IPv6 equivalent. In most cases, you would | ||
| 195 | /// want to map the address to its IPv6 equivalent rather than directly | ||
| 196 | /// re-interpreting the address. | ||
| 197 | pub fn mapToIPv6(self: IPv4) IPv6 { | ||
| 198 | var octets: [16]u8 = undefined; | ||
| 199 | mem.copy(u8, octets[0..12], &IPv6.v4_mapped_prefix); | ||
| 200 | mem.copy(u8, octets[12..], &self.octets); | ||
| 201 | return IPv6{ .octets = octets, .scope_id = IPv6.no_scope_id }; | ||
| 202 | } | ||
| 203 | |||
| 204 | /// Directly re-interprets the address to its IPv6 equivalent. In most | ||
| 205 | /// cases, you would want to map the address to its IPv6 equivalent rather | ||
| 206 | /// than directly re-interpreting the address. | ||
| 207 | pub fn toIPv6(self: IPv4) IPv6 { | ||
| 208 | var octets: [16]u8 = undefined; | ||
| 209 | mem.set(u8, octets[0..12], 0); | ||
| 210 | mem.copy(u8, octets[12..], &self.octets); | ||
| 211 | return IPv6{ .octets = octets, .scope_id = IPv6.no_scope_id }; | ||
| 212 | } | ||
| 213 | }; | ||
| 214 | |||
| 215 | /// An IPv6 address comprised of 16 bytes for an address, and 4 bytes | ||
| 216 | /// for a scope ID; cumulatively summing to 20 bytes in total. | ||
| 217 | pub const IPv6 = extern struct { | ||
| 218 | /// A IPv6 host-port pair. | ||
| 219 | pub const Address = extern struct { | ||
| 220 | host: IPv6, | ||
| 221 | port: u16, | ||
| 222 | }; | ||
| 223 | |||
| 224 | /// Octets of a IPv6 address designating the local host. | ||
| 225 | pub const localhost_octets = [_]u8{0} ** 15 ++ [_]u8{0x01}; | ||
| 226 | |||
| 227 | /// The IPv6 address of the local host. | ||
| 228 | pub const localhost: IPv6 = .{ | ||
| 229 | .octets = localhost_octets, | ||
| 230 | .scope_id = no_scope_id, | ||
| 231 | }; | ||
| 232 | |||
| 233 | /// Octets of an unspecified IPv6 address. | ||
| 234 | pub const unspecified_octets = [_]u8{0} ** 16; | ||
| 235 | |||
| 236 | /// An unspecified IPv6 address. | ||
| 237 | pub const unspecified: IPv6 = .{ | ||
| 238 | .octets = unspecified_octets, | ||
| 239 | .scope_id = no_scope_id, | ||
| 240 | }; | ||
| 241 | |||
| 242 | /// The prefix of a IPv6 address that is mapped to a IPv4 address. | ||
| 243 | pub const v4_mapped_prefix = [_]u8{0} ** 10 ++ [_]u8{0xFF} ** 2; | ||
| 244 | |||
| 245 | /// A marker value used to designate an IPv6 address with no | ||
| 246 | /// associated scope ID. | ||
| 247 | pub const no_scope_id = math.maxInt(u32); | ||
| 248 | |||
| 249 | octets: [16]u8, | ||
| 250 | scope_id: u32, | ||
| 251 | |||
| 252 | /// Returns whether or not the two addresses are equal to, less than, or | ||
| 253 | /// greater than each other. | ||
| 254 | pub fn cmp(self: IPv6, other: IPv6) math.Order { | ||
| 255 | return switch (mem.order(u8, self.octets, other.octets)) { | ||
| 256 | .eq => math.order(self.scope_id, other.scope_id), | ||
| 257 | else => |order| order, | ||
| 258 | }; | ||
| 259 | } | ||
| 260 | |||
| 261 | /// Returns true if both addresses are semantically equivalent. | ||
| 262 | pub fn eql(self: IPv6, other: IPv6) bool { | ||
| 263 | return self.scope_id == other.scope_id and mem.eql(u8, &self.octets, &other.octets); | ||
| 264 | } | ||
| 265 | |||
| 266 | /// Returns true if the address is an unspecified IPv6 address. | ||
| 267 | pub fn isUnspecified(self: IPv6) bool { | ||
| 268 | return mem.eql(u8, &self.octets, &unspecified_octets); | ||
| 269 | } | ||
| 270 | |||
| 271 | /// Returns true if the address is a loopback address. | ||
| 272 | pub fn isLoopback(self: IPv6) bool { | ||
| 273 | return mem.eql(u8, self.octets[0..3], &[_]u8{ 0, 0, 0 }) and | ||
| 274 | mem.eql(u8, self.octets[12..], &[_]u8{ 0, 0, 0, 1 }); | ||
| 275 | } | ||
| 276 | |||
| 277 | /// Returns true if the address maps to an IPv4 address. | ||
| 278 | pub fn mapsToIPv4(self: IPv6) bool { | ||
| 279 | return mem.startsWith(u8, &self.octets, &v4_mapped_prefix); | ||
| 280 | } | ||
| 281 | |||
| 282 | /// Returns an IPv4 address representative of the address should | ||
| 283 | /// it the address be mapped to an IPv4 address. It returns null | ||
| 284 | /// otherwise. | ||
| 285 | pub fn toIPv4(self: IPv6) ?IPv4 { | ||
| 286 | if (!self.mapsToIPv4()) return null; | ||
| 287 | return IPv4{ .octets = self.octets[12..][0..4].* }; | ||
| 288 | } | ||
| 289 | |||
| 290 | /// Returns true if the address is a multicast IPv6 address. | ||
| 291 | pub fn isMulticast(self: IPv6) bool { | ||
| 292 | return self.octets[0] == 0xFF; | ||
| 293 | } | ||
| 294 | |||
| 295 | /// Returns true if the address is a unicast link local IPv6 address. | ||
| 296 | pub fn isLinkLocal(self: IPv6) bool { | ||
| 297 | return self.octets[0] == 0xFE and self.octets[1] & 0xC0 == 0x80; | ||
| 298 | } | ||
| 299 | |||
| 300 | /// Returns true if the address is a deprecated unicast site local | ||
| 301 | /// IPv6 address. Refer to IETF RFC 3879 for more details as to | ||
| 302 | /// why they are deprecated. | ||
| 303 | pub fn isSiteLocal(self: IPv6) bool { | ||
| 304 | return self.octets[0] == 0xFE and self.octets[1] & 0xC0 == 0xC0; | ||
| 305 | } | ||
| 306 | |||
| 307 | /// IPv6 multicast address scopes. | ||
| 308 | pub const Scope = enum(u8) { | ||
| 309 | interface = 1, | ||
| 310 | link = 2, | ||
| 311 | realm = 3, | ||
| 312 | admin = 4, | ||
| 313 | site = 5, | ||
| 314 | organization = 8, | ||
| 315 | global = 14, | ||
| 316 | unknown = 0xFF, | ||
| 317 | }; | ||
| 318 | |||
| 319 | /// Returns the multicast scope of the address. | ||
| 320 | pub fn scope(self: IPv6) Scope { | ||
| 321 | if (!self.isMulticast()) return .unknown; | ||
| 322 | |||
| 323 | return switch (self.octets[0] & 0x0F) { | ||
| 324 | 1 => .interface, | ||
| 325 | 2 => .link, | ||
| 326 | 3 => .realm, | ||
| 327 | 4 => .admin, | ||
| 328 | 5 => .site, | ||
| 329 | 8 => .organization, | ||
| 330 | 14 => .global, | ||
| 331 | else => .unknown, | ||
| 332 | }; | ||
| 333 | } | ||
| 334 | |||
| 335 | /// Implements the `std.fmt.format` API. Specifying 'x' or 's' formats the | ||
| 336 | /// address lower-cased octets, while specifying 'X' or 'S' formats the | ||
| 337 | /// address using upper-cased ASCII octets. | ||
| 338 | /// | ||
| 339 | /// The default specifier is 'x'. | ||
| 340 | pub fn format( | ||
| 341 | self: IPv6, | ||
| 342 | comptime layout: []const u8, | ||
| 343 | opts: fmt.FormatOptions, | ||
| 344 | writer: anytype, | ||
| 345 | ) !void { | ||
| 346 | comptime const specifier = &[_]u8{if (layout.len == 0) 'x' else switch (layout[0]) { | ||
| 347 | 'x', 'X' => |specifier| specifier, | ||
| 348 | 's' => 'x', | ||
| 349 | 'S' => 'X', | ||
| 350 | else => @compileError("Unsupported format specifier for IPv6 type '" ++ layout ++ "'."), | ||
| 351 | }}; | ||
| 352 | |||
| 353 | if (mem.startsWith(u8, &self.octets, &v4_mapped_prefix)) { | ||
| 354 | return fmt.format(writer, "::{" ++ specifier ++ "}{" ++ specifier ++ "}:{}.{}.{}.{}", .{ | ||
| 355 | 0xFF, | ||
| 356 | 0xFF, | ||
| 357 | self.octets[12], | ||
| 358 | self.octets[13], | ||
| 359 | self.octets[14], | ||
| 360 | self.octets[15], | ||
| 361 | }); | ||
| 362 | } | ||
| 363 | |||
| 364 | const zero_span = span: { | ||
| 365 | var i: usize = 0; | ||
| 366 | while (i < self.octets.len) : (i += 2) { | ||
| 367 | if (self.octets[i] == 0 and self.octets[i + 1] == 0) break; | ||
| 368 | } else break :span .{ .from = 0, .to = 0 }; | ||
| 369 | |||
| 370 | const from = i; | ||
| 371 | |||
| 372 | while (i < self.octets.len) : (i += 2) { | ||
| 373 | if (self.octets[i] != 0 or self.octets[i + 1] != 0) break; | ||
| 374 | } | ||
| 375 | |||
| 376 | break :span .{ .from = from, .to = i }; | ||
| 377 | }; | ||
| 378 | |||
| 379 | var i: usize = 0; | ||
| 380 | while (i != 16) : (i += 2) { | ||
| 381 | if (zero_span.from != zero_span.to and i == zero_span.from) { | ||
| 382 | try writer.writeAll("::"); | ||
| 383 | } else if (i >= zero_span.from and i < zero_span.to) {} else { | ||
| 384 | if (i != 0 and i != zero_span.to) try writer.writeAll(":"); | ||
| 385 | |||
| 386 | const val = @as(u16, self.octets[i]) << 8 | self.octets[i + 1]; | ||
| 387 | try fmt.formatIntValue(val, specifier, .{}, writer); | ||
| 388 | } | ||
| 389 | } | ||
| 390 | |||
| 391 | if (self.scope_id != no_scope_id and self.scope_id != 0) { | ||
| 392 | try fmt.format(writer, "%{d}", .{self.scope_id}); | ||
| 393 | } | ||
| 394 | } | ||
| 395 | |||
| 396 | /// Set of possible errors that may encountered when parsing an IPv6 | ||
| 397 | /// address. | ||
| 398 | pub const ParseError = error{ | ||
| 399 | MalformedV4Mapping, | ||
| 400 | BadScopeID, | ||
| 401 | } || IPv4.ParseError; | ||
| 402 | |||
| 403 | /// Parses an arbitrary IPv6 address, including link-local addresses. | ||
| 404 | pub fn parse(buf: []const u8) ParseError!IPv6 { | ||
| 405 | if (mem.lastIndexOfScalar(u8, buf, '%')) |index| { | ||
| 406 | const ip_slice = buf[0..index]; | ||
| 407 | const scope_id_slice = buf[index + 1 ..]; | ||
| 408 | |||
| 409 | if (scope_id_slice.len == 0) return error.BadScopeID; | ||
| 410 | |||
| 411 | const scope_id: u32 = switch (scope_id_slice[0]) { | ||
| 412 | '0'...'9' => fmt.parseInt(u32, scope_id_slice, 10), | ||
| 413 | else => resolveScopeID(scope_id_slice), | ||
| 414 | } catch return error.BadScopeID; | ||
| 415 | |||
| 416 | return parseWithScopeID(ip_slice, scope_id); | ||
| 417 | } | ||
| 418 | |||
| 419 | return parseWithScopeID(buf, no_scope_id); | ||
| 420 | } | ||
| 421 | |||
| 422 | /// Parses an IPv6 address with a pre-specified scope ID. Presumes | ||
| 423 | /// that the address is not a link-local address. | ||
| 424 | pub fn parseWithScopeID(buf: []const u8, scope_id: u32) ParseError!IPv6 { | ||
| 425 | var octets: [16]u8 = undefined; | ||
| 426 | var octet: u16 = 0; | ||
| 427 | var tail: [16]u8 = undefined; | ||
| 428 | |||
| 429 | var out: []u8 = &octets; | ||
| 430 | var index: u8 = 0; | ||
| 431 | |||
| 432 | var saw_any_digits: bool = false; | ||
| 433 | var abbrv: bool = false; | ||
| 434 | |||
| 435 | for (buf) |c, i| { | ||
| 436 | switch (c) { | ||
| 437 | ':' => { | ||
| 438 | if (!saw_any_digits) { | ||
| 439 | if (abbrv) return error.UnexpectedToken; | ||
| 440 | if (i != 0) abbrv = true; | ||
| 441 | mem.set(u8, out[index..], 0); | ||
| 442 | out = &tail; | ||
| 443 | index = 0; | ||
| 444 | continue; | ||
| 445 | } | ||
| 446 | if (index == 14) return error.TooManyOctets; | ||
| 447 | |||
| 448 | out[index] = @truncate(u8, octet >> 8); | ||
| 449 | index += 1; | ||
| 450 | out[index] = @truncate(u8, octet); | ||
| 451 | index += 1; | ||
| 452 | |||
| 453 | octet = 0; | ||
| 454 | saw_any_digits = false; | ||
| 455 | }, | ||
| 456 | '.' => { | ||
| 457 | if (!abbrv or out[0] != 0xFF and out[1] != 0xFF) { | ||
| 458 | return error.MalformedV4Mapping; | ||
| 459 | } | ||
| 460 | const start_index = mem.lastIndexOfScalar(u8, buf[0..i], ':').? + 1; | ||
| 461 | const v4 = try IPv4.parse(buf[start_index..]); | ||
| 462 | octets[10] = 0xFF; | ||
| 463 | octets[11] = 0xFF; | ||
| 464 | mem.copy(u8, octets[12..], &v4.octets); | ||
| 465 | |||
| 466 | return IPv6{ .octets = octets, .scope_id = scope_id }; | ||
| 467 | }, | ||
| 468 | else => { | ||
| 469 | saw_any_digits = true; | ||
| 470 | const digit = fmt.charToDigit(c, 16) catch return error.UnexpectedToken; | ||
| 471 | octet = math.mul(u16, octet, 16) catch return error.OctetOverflow; | ||
| 472 | octet = math.add(u16, octet, digit) catch return error.OctetOverflow; | ||
| 473 | }, | ||
| 474 | } | ||
| 475 | } | ||
| 476 | |||
| 477 | if (!saw_any_digits and !abbrv) { | ||
| 478 | return error.IncompleteAddress; | ||
| 479 | } | ||
| 480 | |||
| 481 | if (index == 14) { | ||
| 482 | out[14] = @truncate(u8, octet >> 8); | ||
| 483 | out[15] = @truncate(u8, octet); | ||
| 484 | } else { | ||
| 485 | out[index] = @truncate(u8, octet >> 8); | ||
| 486 | index += 1; | ||
| 487 | out[index] = @truncate(u8, octet); | ||
| 488 | index += 1; | ||
| 489 | mem.copy(u8, octets[16 - index ..], out[0..index]); | ||
| 490 | } | ||
| 491 | |||
| 492 | return IPv6{ .octets = octets, .scope_id = scope_id }; | ||
| 493 | } | ||
| 494 | }; | ||
| 495 | |||
| 496 | test { | ||
| 497 | testing.refAllDecls(@This()); | ||
| 498 | } | ||
| 499 | |||
| 500 | test "ip: convert to and from ipv6" { | ||
| 501 | try testing.expectFmt("::7f00:1", "{}", .{IPv4.localhost.toIPv6()}); | ||
| 502 | testing.expect(!IPv4.localhost.toIPv6().mapsToIPv4()); | ||
| 503 | |||
| 504 | try testing.expectFmt("::ffff:127.0.0.1", "{}", .{IPv4.localhost.mapToIPv6()}); | ||
| 505 | testing.expect(IPv4.localhost.mapToIPv6().mapsToIPv4()); | ||
| 506 | |||
| 507 | testing.expect(IPv4.localhost.toIPv6().toIPv4() == null); | ||
| 508 | try testing.expectFmt("127.0.0.1", "{}", .{IPv4.localhost.mapToIPv6().toIPv4()}); | ||
| 509 | } | ||
| 510 | |||
| 511 | test "ipv4: parse & format" { | ||
| 512 | const cases = [_][]const u8{ | ||
| 513 | "0.0.0.0", | ||
| 514 | "255.255.255.255", | ||
| 515 | "1.2.3.4", | ||
| 516 | "123.255.0.91", | ||
| 517 | "127.0.0.1", | ||
| 518 | }; | ||
| 519 | |||
| 520 | for (cases) |case| { | ||
| 521 | try testing.expectFmt(case, "{}", .{try IPv4.parse(case)}); | ||
| 522 | } | ||
| 523 | } | ||
| 524 | |||
| 525 | test "ipv6: parse & format" { | ||
| 526 | const inputs = [_][]const u8{ | ||
| 527 | "FF01:0:0:0:0:0:0:FB", | ||
| 528 | "FF01::Fb", | ||
| 529 | "::1", | ||
| 530 | "::", | ||
| 531 | "2001:db8::", | ||
| 532 | "::1234:5678", | ||
| 533 | "2001:db8::1234:5678", | ||
| 534 | "::ffff:123.5.123.5", | ||
| 535 | }; | ||
| 536 | |||
| 537 | const outputs = [_][]const u8{ | ||
| 538 | "ff01::fb", | ||
| 539 | "ff01::fb", | ||
| 540 | "::1", | ||
| 541 | "::", | ||
| 542 | "2001:db8::", | ||
| 543 | "::1234:5678", | ||
| 544 | "2001:db8::1234:5678", | ||
| 545 | "::ffff:123.5.123.5", | ||
| 546 | }; | ||
| 547 | |||
| 548 | for (inputs) |input, i| { | ||
| 549 | try testing.expectFmt(outputs[i], "{}", .{try IPv6.parse(input)}); | ||
| 550 | } | ||
| 551 | } | ||
| 552 | |||
| 553 | test "ipv6: parse & format addresses with scope ids" { | ||
| 554 | if (!@hasDecl(os, "IFNAMESIZE")) return error.SkipZigTest; | ||
| 555 | |||
| 556 | const inputs = [_][]const u8{ | ||
| 557 | "FF01::FB%lo", | ||
| 558 | }; | ||
| 559 | |||
| 560 | const outputs = [_][]const u8{ | ||
| 561 | "ff01::fb%1", | ||
| 562 | }; | ||
| 563 | |||
| 564 | for (inputs) |input, i| { | ||
| 565 | try testing.expectFmt(outputs[i], "{}", .{try IPv6.parse(input)}); | ||
| 566 | } | ||
| 567 | } | ||
lib/std/x/os/os.zig deleted-9| ... | @@ -1,9 +0,0 @@ | ||
| 1 | const std = @import("../../std.zig"); | ||
| 2 | |||
| 3 | const testing = std.testing; | ||
| 4 | |||
| 5 | pub const Socket = @import("Socket.zig"); | ||
| 6 | |||
| 7 | test { | ||
| 8 | testing.refAllDecls(@This()); | ||
| 9 | } | ||
lib/std/zig/ast.zig+13-7| ... | @@ -1979,20 +1979,26 @@ pub const Tree = struct { | ... | @@ -1979,20 +1979,26 @@ pub const Tree = struct { |
| 1979 | // asm ("foo" :: [_] "" (y) : "a", "b"); | 1979 | // asm ("foo" :: [_] "" (y) : "a", "b"); |
| 1980 | const last_input = result.inputs[result.inputs.len - 1]; | 1980 | const last_input = result.inputs[result.inputs.len - 1]; |
| 1981 | const rparen = tree.lastToken(last_input); | 1981 | const rparen = tree.lastToken(last_input); |
| 1982 | if (token_tags[rparen + 1] == .colon and | 1982 | var i = rparen + 1; |
| 1983 | token_tags[rparen + 2] == .string_literal) | 1983 | // Allow a (useless) comma right after the closing parenthesis. |
| 1984 | if (token_tags[i] == .comma) i += 1; | ||
| 1985 | if (token_tags[i] == .colon and | ||
| 1986 | token_tags[i + 1] == .string_literal) | ||
| 1984 | { | 1987 | { |
| 1985 | result.first_clobber = rparen + 2; | 1988 | result.first_clobber = i + 1; |
| 1986 | } | 1989 | } |
| 1987 | } else { | 1990 | } else { |
| 1988 | // asm ("foo" : [_] "" (x) :: "a", "b"); | 1991 | // asm ("foo" : [_] "" (x) :: "a", "b"); |
| 1989 | const last_output = result.outputs[result.outputs.len - 1]; | 1992 | const last_output = result.outputs[result.outputs.len - 1]; |
| 1990 | const rparen = tree.lastToken(last_output); | 1993 | const rparen = tree.lastToken(last_output); |
| 1991 | if (token_tags[rparen + 1] == .colon and | 1994 | var i = rparen + 1; |
| 1992 | token_tags[rparen + 2] == .colon and | 1995 | // Allow a (useless) comma right after the closing parenthesis. |
| 1993 | token_tags[rparen + 3] == .string_literal) | 1996 | if (token_tags[i] == .comma) i += 1; |
| 1997 | if (token_tags[i] == .colon and | ||
| 1998 | token_tags[i + 1] == .colon and | ||
| 1999 | token_tags[i + 2] == .string_literal) | ||
| 1994 | { | 2000 | { |
| 1995 | result.first_clobber = rparen + 3; | 2001 | result.first_clobber = i + 2; |
| 1996 | } | 2002 | } |
| 1997 | } | 2003 | } |
| 1998 | 2004 |
lib/std/zig/parser_test.zig+32| ... | @@ -4,6 +4,38 @@ | ... | @@ -4,6 +4,38 @@ |
| 4 | // The MIT license requires this copyright notice to be included in all copies | 4 | // The MIT license requires this copyright notice to be included in all copies |
| 5 | // and substantial portions of the software. | 5 | // and substantial portions of the software. |
| 6 | 6 | ||
| 7 | test "zig fmt: preserves clobbers in inline asm with stray comma" { | ||
| 8 | try testTransform( | ||
| 9 | \\fn foo() void { | ||
| 10 | \\ asm volatile ("" | ||
| 11 | \\ : [_] "" (-> type), | ||
| 12 | \\ : | ||
| 13 | \\ : "clobber" | ||
| 14 | \\ ); | ||
| 15 | \\ asm volatile ("" | ||
| 16 | \\ : | ||
| 17 | \\ : [_] "" (type), | ||
| 18 | \\ : "clobber" | ||
| 19 | \\ ); | ||
| 20 | \\} | ||
| 21 | \\ | ||
| 22 | , | ||
| 23 | \\fn foo() void { | ||
| 24 | \\ asm volatile ("" | ||
| 25 | \\ : [_] "" (-> type) | ||
| 26 | \\ : | ||
| 27 | \\ : "clobber" | ||
| 28 | \\ ); | ||
| 29 | \\ asm volatile ("" | ||
| 30 | \\ : | ||
| 31 | \\ : [_] "" (type) | ||
| 32 | \\ : "clobber" | ||
| 33 | \\ ); | ||
| 34 | \\} | ||
| 35 | \\ | ||
| 36 | ); | ||
| 37 | } | ||
| 38 | |||
| 7 | test "zig fmt: respect line breaks in struct field value declaration" { | 39 | test "zig fmt: respect line breaks in struct field value declaration" { |
| 8 | try testCanonical( | 40 | try testCanonical( |
| 9 | \\const Foo = struct { | 41 | \\const Foo = struct { |
lib/std/zig/system/linux.zig+276-7| ... | @@ -53,7 +53,7 @@ const SparcCpuinfoImpl = struct { | ... | @@ -53,7 +53,7 @@ const SparcCpuinfoImpl = struct { |
| 53 | // At the moment we only support 64bit SPARC systems. | 53 | // At the moment we only support 64bit SPARC systems. |
| 54 | assert(self.is_64bit); | 54 | assert(self.is_64bit); |
| 55 | 55 | ||
| 56 | const model = self.model orelse Target.Cpu.Model.generic(arch); | 56 | const model = self.model orelse return null; |
| 57 | return Target.Cpu{ | 57 | return Target.Cpu{ |
| 58 | .arch = arch, | 58 | .arch = arch, |
| 59 | .model = model, | 59 | .model = model, |
| ... | @@ -65,7 +65,7 @@ const SparcCpuinfoImpl = struct { | ... | @@ -65,7 +65,7 @@ const SparcCpuinfoImpl = struct { |
| 65 | const SparcCpuinfoParser = CpuinfoParser(SparcCpuinfoImpl); | 65 | const SparcCpuinfoParser = CpuinfoParser(SparcCpuinfoImpl); |
| 66 | 66 | ||
| 67 | test "cpuinfo: SPARC" { | 67 | test "cpuinfo: SPARC" { |
| 68 | try testParser(SparcCpuinfoParser, &Target.sparc.cpu.niagara2, | 68 | try testParser(SparcCpuinfoParser, .sparcv9, &Target.sparc.cpu.niagara2, |
| 69 | \\cpu : UltraSparc T2 (Niagara2) | 69 | \\cpu : UltraSparc T2 (Niagara2) |
| 70 | \\fpu : UltraSparc T2 integrated FPU | 70 | \\fpu : UltraSparc T2 integrated FPU |
| 71 | \\pmu : niagara2 | 71 | \\pmu : niagara2 |
| ... | @@ -119,7 +119,7 @@ const PowerpcCpuinfoImpl = struct { | ... | @@ -119,7 +119,7 @@ const PowerpcCpuinfoImpl = struct { |
| 119 | } | 119 | } |
| 120 | 120 | ||
| 121 | fn finalize(self: *const PowerpcCpuinfoImpl, arch: Target.Cpu.Arch) ?Target.Cpu { | 121 | fn finalize(self: *const PowerpcCpuinfoImpl, arch: Target.Cpu.Arch) ?Target.Cpu { |
| 122 | const model = self.model orelse Target.Cpu.Model.generic(arch); | 122 | const model = self.model orelse return null; |
| 123 | return Target.Cpu{ | 123 | return Target.Cpu{ |
| 124 | .arch = arch, | 124 | .arch = arch, |
| 125 | .model = model, | 125 | .model = model, |
| ... | @@ -131,13 +131,13 @@ const PowerpcCpuinfoImpl = struct { | ... | @@ -131,13 +131,13 @@ const PowerpcCpuinfoImpl = struct { |
| 131 | const PowerpcCpuinfoParser = CpuinfoParser(PowerpcCpuinfoImpl); | 131 | const PowerpcCpuinfoParser = CpuinfoParser(PowerpcCpuinfoImpl); |
| 132 | 132 | ||
| 133 | test "cpuinfo: PowerPC" { | 133 | test "cpuinfo: PowerPC" { |
| 134 | try testParser(PowerpcCpuinfoParser, &Target.powerpc.cpu.@"970", | 134 | try testParser(PowerpcCpuinfoParser, .powerpc, &Target.powerpc.cpu.@"970", |
| 135 | \\processor	: 0 | 135 | \\processor	: 0 |
| 136 | \\cpu		: PPC970MP, altivec supported | 136 | \\cpu		: PPC970MP, altivec supported |
| 137 | \\clock		: 1250.000000MHz | 137 | \\clock		: 1250.000000MHz |
| 138 | \\revision	: 1.1 (pvr 0044 0101) | 138 | \\revision	: 1.1 (pvr 0044 0101) |
| 139 | ); | 139 | ); |
| 140 | try testParser(PowerpcCpuinfoParser, &Target.powerpc.cpu.pwr8, | 140 | try testParser(PowerpcCpuinfoParser, .powerpc64le, &Target.powerpc.cpu.pwr8, |
| 141 | \\processor	: 0 | 141 | \\processor	: 0 |
| 142 | \\cpu		: POWER8 (raw), altivec supported | 142 | \\cpu		: POWER8 (raw), altivec supported |
| 143 | \\clock		: 2926.000000MHz | 143 | \\clock		: 2926.000000MHz |
| ... | @@ -145,9 +145,275 @@ test "cpuinfo: PowerPC" { | ... | @@ -145,9 +145,275 @@ test "cpuinfo: PowerPC" { |
| 145 | ); | 145 | ); |
| 146 | } | 146 | } |
| 147 | 147 | ||
| 148 | fn testParser(parser: anytype, expected_model: *const Target.Cpu.Model, input: []const u8) !void { | 148 | const ArmCpuinfoImpl = struct { |
| 149 | cores: [4]CoreInfo = undefined, | ||
| 150 | core_no: usize = 0, | ||
| 151 | have_fields: usize = 0, | ||
| 152 | |||
| 153 | const CoreInfo = struct { | ||
| 154 | architecture: u8 = 0, | ||
| 155 | implementer: u8 = 0, | ||
| 156 | variant: u8 = 0, | ||
| 157 | part: u16 = 0, | ||
| 158 | is_really_v6: bool = false, | ||
| 159 | }; | ||
| 160 | |||
| 161 | const cpu_models = struct { | ||
| 162 | // Shorthands to simplify the tables below. | ||
| 163 | const A32 = Target.arm.cpu; | ||
| 164 | const A64 = Target.aarch64.cpu; | ||
| 165 | |||
| 166 | const E = struct { | ||
| 167 | part: u16, | ||
| 168 | variant: ?u8 = null, // null if matches any variant | ||
| 169 | m32: ?*const Target.Cpu.Model = null, | ||
| 170 | m64: ?*const Target.Cpu.Model = null, | ||
| 171 | }; | ||
| 172 | |||
| 173 | // implementer = 0x41 | ||
| 174 | const ARM = [_]E{ | ||
| 175 | E{ .part = 0x926, .m32 = &A32.arm926ej_s, .m64 = null }, | ||
| 176 | E{ .part = 0xb02, .m32 = &A32.mpcore, .m64 = null }, | ||
| 177 | E{ .part = 0xb36, .m32 = &A32.arm1136j_s, .m64 = null }, | ||
| 178 | E{ .part = 0xb56, .m32 = &A32.arm1156t2_s, .m64 = null }, | ||
| 179 | E{ .part = 0xb76, .m32 = &A32.arm1176jz_s, .m64 = null }, | ||
| 180 | E{ .part = 0xc05, .m32 = &A32.cortex_a5, .m64 = null }, | ||
| 181 | E{ .part = 0xc07, .m32 = &A32.cortex_a7, .m64 = null }, | ||
| 182 | E{ .part = 0xc08, .m32 = &A32.cortex_a8, .m64 = null }, | ||
| 183 | E{ .part = 0xc09, .m32 = &A32.cortex_a9, .m64 = null }, | ||
| 184 | E{ .part = 0xc0d, .m32 = &A32.cortex_a17, .m64 = null }, | ||
| 185 | E{ .part = 0xc0f, .m32 = &A32.cortex_a15, .m64 = null }, | ||
| 186 | E{ .part = 0xc0e, .m32 = &A32.cortex_a17, .m64 = null }, | ||
| 187 | E{ .part = 0xc14, .m32 = &A32.cortex_r4, .m64 = null }, | ||
| 188 | E{ .part = 0xc15, .m32 = &A32.cortex_r5, .m64 = null }, | ||
| 189 | E{ .part = 0xc17, .m32 = &A32.cortex_r7, .m64 = null }, | ||
| 190 | E{ .part = 0xc18, .m32 = &A32.cortex_r8, .m64 = null }, | ||
| 191 | E{ .part = 0xc20, .m32 = &A32.cortex_m0, .m64 = null }, | ||
| 192 | E{ .part = 0xc21, .m32 = &A32.cortex_m1, .m64 = null }, | ||
| 193 | E{ .part = 0xc23, .m32 = &A32.cortex_m3, .m64 = null }, | ||
| 194 | E{ .part = 0xc24, .m32 = &A32.cortex_m4, .m64 = null }, | ||
| 195 | E{ .part = 0xc27, .m32 = &A32.cortex_m7, .m64 = null }, | ||
| 196 | E{ .part = 0xc60, .m32 = &A32.cortex_m0plus, .m64 = null }, | ||
| 197 | E{ .part = 0xd01, .m32 = &A32.cortex_a32, .m64 = null }, | ||
| 198 | E{ .part = 0xd03, .m32 = &A32.cortex_a53, .m64 = &A64.cortex_a53 }, | ||
| 199 | E{ .part = 0xd04, .m32 = &A32.cortex_a35, .m64 = &A64.cortex_a35 }, | ||
| 200 | E{ .part = 0xd05, .m32 = &A32.cortex_a55, .m64 = &A64.cortex_a55 }, | ||
| 201 | E{ .part = 0xd07, .m32 = &A32.cortex_a57, .m64 = &A64.cortex_a57 }, | ||
| 202 | E{ .part = 0xd08, .m32 = &A32.cortex_a72, .m64 = &A64.cortex_a72 }, | ||
| 203 | E{ .part = 0xd09, .m32 = &A32.cortex_a73, .m64 = &A64.cortex_a73 }, | ||
| 204 | E{ .part = 0xd0a, .m32 = &A32.cortex_a75, .m64 = &A64.cortex_a75 }, | ||
| 205 | E{ .part = 0xd0b, .m32 = &A32.cortex_a76, .m64 = &A64.cortex_a76 }, | ||
| 206 | E{ .part = 0xd0c, .m32 = &A32.neoverse_n1, .m64 = null }, | ||
| 207 | E{ .part = 0xd0d, .m32 = &A32.cortex_a77, .m64 = &A64.cortex_a77 }, | ||
| 208 | E{ .part = 0xd13, .m32 = &A32.cortex_r52, .m64 = null }, | ||
| 209 | E{ .part = 0xd20, .m32 = &A32.cortex_m23, .m64 = null }, | ||
| 210 | E{ .part = 0xd21, .m32 = &A32.cortex_m33, .m64 = null }, | ||
| 211 | E{ .part = 0xd41, .m32 = &A32.cortex_a78, .m64 = &A64.cortex_a78 }, | ||
| 212 | E{ .part = 0xd4b, .m32 = &A32.cortex_a78c, .m64 = &A64.cortex_a78c }, | ||
| 213 | E{ .part = 0xd44, .m32 = &A32.cortex_x1, .m64 = &A64.cortex_x1 }, | ||
| 214 | E{ .part = 0xd02, .m64 = &A64.cortex_a34 }, | ||
| 215 | E{ .part = 0xd06, .m64 = &A64.cortex_a65 }, | ||
| 216 | E{ .part = 0xd43, .m64 = &A64.cortex_a65ae }, | ||
| 217 | }; | ||
| 218 | // implementer = 0x42 | ||
| 219 | const Broadcom = [_]E{ | ||
| 220 | E{ .part = 0x516, .m64 = &A64.thunderx2t99 }, | ||
| 221 | }; | ||
| 222 | // implementer = 0x43 | ||
| 223 | const Cavium = [_]E{ | ||
| 224 | E{ .part = 0x0a0, .m64 = &A64.thunderx }, | ||
| 225 | E{ .part = 0x0a2, .m64 = &A64.thunderxt81 }, | ||
| 226 | E{ .part = 0x0a3, .m64 = &A64.thunderxt83 }, | ||
| 227 | E{ .part = 0x0a1, .m64 = &A64.thunderxt88 }, | ||
| 228 | E{ .part = 0x0af, .m64 = &A64.thunderx2t99 }, | ||
| 229 | }; | ||
| 230 | // implementer = 0x46 | ||
| 231 | const Fujitsu = [_]E{ | ||
| 232 | E{ .part = 0x001, .m64 = &A64.a64fx }, | ||
| 233 | }; | ||
| 234 | // implementer = 0x48 | ||
| 235 | const HiSilicon = [_]E{ | ||
| 236 | E{ .part = 0xd01, .m64 = &A64.tsv110 }, | ||
| 237 | }; | ||
| 238 | // implementer = 0x4e | ||
| 239 | const Nvidia = [_]E{ | ||
| 240 | E{ .part = 0x004, .m64 = &A64.carmel }, | ||
| 241 | }; | ||
| 242 | // implementer = 0x50 | ||
| 243 | const Ampere = [_]E{ | ||
| 244 | E{ .part = 0x000, .variant = 3, .m64 = &A64.emag }, | ||
| 245 | E{ .part = 0x000, .m64 = &A64.xgene1 }, | ||
| 246 | }; | ||
| 247 | // implementer = 0x51 | ||
| 248 | const Qualcomm = [_]E{ | ||
| 249 | E{ .part = 0x06f, .m32 = &A32.krait }, | ||
| 250 | E{ .part = 0x201, .m64 = &A64.kryo, .m32 = &A64.kryo }, | ||
| 251 | E{ .part = 0x205, .m64 = &A64.kryo, .m32 = &A64.kryo }, | ||
| 252 | E{ .part = 0x211, .m64 = &A64.kryo, .m32 = &A64.kryo }, | ||
| 253 | E{ .part = 0x800, .m64 = &A64.cortex_a73, .m32 = &A64.cortex_a73 }, | ||
| 254 | E{ .part = 0x801, .m64 = &A64.cortex_a73, .m32 = &A64.cortex_a73 }, | ||
| 255 | E{ .part = 0x802, .m64 = &A64.cortex_a75, .m32 = &A64.cortex_a75 }, | ||
| 256 | E{ .part = 0x803, .m64 = &A64.cortex_a75, .m32 = &A64.cortex_a75 }, | ||
| 257 | E{ .part = 0x804, .m64 = &A64.cortex_a76, .m32 = &A64.cortex_a76 }, | ||
| 258 | E{ .part = 0x805, .m64 = &A64.cortex_a76, .m32 = &A64.cortex_a76 }, | ||
| 259 | E{ .part = 0xc00, .m64 = &A64.falkor }, | ||
| 260 | E{ .part = 0xc01, .m64 = &A64.saphira }, | ||
| 261 | }; | ||
| 262 | |||
| 263 | fn isKnown(core: CoreInfo, is_64bit: bool) ?*const Target.Cpu.Model { | ||
| 264 | const models = switch (core.implementer) { | ||
| 265 | 0x41 => &ARM, | ||
| 266 | 0x42 => &Broadcom, | ||
| 267 | 0x43 => &Cavium, | ||
| 268 | 0x46 => &Fujitsu, | ||
| 269 | 0x48 => &HiSilicon, | ||
| 270 | 0x50 => &Ampere, | ||
| 271 | 0x51 => &Qualcomm, | ||
| 272 | else => return null, | ||
| 273 | }; | ||
| 274 | |||
| 275 | for (models) |model| { | ||
| 276 | if (model.part == core.part and | ||
| 277 | (model.variant == null or model.variant.? == core.variant)) | ||
| 278 | return if (is_64bit) model.m64 else model.m32; | ||
| 279 | } | ||
| 280 | |||
| 281 | return null; | ||
| 282 | } | ||
| 283 | }; | ||
| 284 | |||
| 285 | fn addOne(self: *ArmCpuinfoImpl) void { | ||
| 286 | if (self.have_fields == 4 and self.core_no < self.cores.len) { | ||
| 287 | if (self.core_no > 0) { | ||
| 288 | // Deduplicate the core info. | ||
| 289 | for (self.cores[0..self.core_no]) |it| { | ||
| 290 | if (std.meta.eql(it, self.cores[self.core_no])) | ||
| 291 | return; | ||
| 292 | } | ||
| 293 | } | ||
| 294 | self.core_no += 1; | ||
| 295 | } | ||
| 296 | } | ||
| 297 | |||
| 298 | fn line_hook(self: *ArmCpuinfoImpl, key: []const u8, value: []const u8) !bool { | ||
| 299 | const info = &self.cores[self.core_no]; | ||
| 300 | |||
| 301 | if (mem.eql(u8, key, "processor")) { | ||
| 302 | // Handle both old-style and new-style cpuinfo formats. | ||
| 303 | // The former prints a sequence of "processor: N" lines for each | ||
| 304 | // core and then the info for the core that's executing this code(!) | ||
| 305 | // while the latter prints the infos for each core right after the | ||
| 306 | // "processor" key. | ||
| 307 | self.have_fields = 0; | ||
| 308 | self.cores[self.core_no] = .{}; | ||
| 309 | } else if (mem.eql(u8, key, "CPU implementer")) { | ||
| 310 | info.implementer = try fmt.parseInt(u8, value, 0); | ||
| 311 | self.have_fields += 1; | ||
| 312 | } else if (mem.eql(u8, key, "CPU architecture")) { | ||
| 313 | // "AArch64" on older kernels. | ||
| 314 | info.architecture = if (mem.startsWith(u8, value, "AArch64")) | ||
| 315 | 8 | ||
| 316 | else | ||
| 317 | try fmt.parseInt(u8, value, 0); | ||
| 318 | self.have_fields += 1; | ||
| 319 | } else if (mem.eql(u8, key, "CPU variant")) { | ||
| 320 | info.variant = try fmt.parseInt(u8, value, 0); | ||
| 321 | self.have_fields += 1; | ||
| 322 | } else if (mem.eql(u8, key, "CPU part")) { | ||
| 323 | info.part = try fmt.parseInt(u16, value, 0); | ||
| 324 | self.have_fields += 1; | ||
| 325 | } else if (mem.eql(u8, key, "model name")) { | ||
| 326 | // ARMv6 cores report "CPU architecture" equal to 7. | ||
| 327 | if (mem.indexOf(u8, value, "(v6l)")) |_| { | ||
| 328 | info.is_really_v6 = true; | ||
| 329 | } | ||
| 330 | } else if (mem.eql(u8, key, "CPU revision")) { | ||
| 331 | // This field is always the last one for each CPU section. | ||
| 332 | _ = self.addOne(); | ||
| 333 | } | ||
| 334 | |||
| 335 | return true; | ||
| 336 | } | ||
| 337 | |||
| 338 | fn finalize(self: *ArmCpuinfoImpl, arch: Target.Cpu.Arch) ?Target.Cpu { | ||
| 339 | if (self.core_no == 0) return null; | ||
| 340 | |||
| 341 | const is_64bit = switch (arch) { | ||
| 342 | .aarch64, .aarch64_be, .aarch64_32 => true, | ||
| 343 | else => false, | ||
| 344 | }; | ||
| 345 | |||
| 346 | var known_models: [self.cores.len]?*const Target.Cpu.Model = undefined; | ||
| 347 | for (self.cores[0..self.core_no]) |core, i| { | ||
| 348 | known_models[i] = cpu_models.isKnown(core, is_64bit); | ||
| 349 | } | ||
| 350 | |||
| 351 | // XXX We pick the first core on big.LITTLE systems, hopefully the | ||
| 352 | // LITTLE one. | ||
| 353 | const model = known_models[0] orelse return null; | ||
| 354 | return Target.Cpu{ | ||
| 355 | .arch = arch, | ||
| 356 | .model = model, | ||
| 357 | .features = model.features, | ||
| 358 | }; | ||
| 359 | } | ||
| 360 | }; | ||
| 361 | |||
| 362 | const ArmCpuinfoParser = CpuinfoParser(ArmCpuinfoImpl); | ||
| 363 | |||
| 364 | test "cpuinfo: ARM" { | ||
| 365 | try testParser(ArmCpuinfoParser, .arm, &Target.arm.cpu.arm1176jz_s, | ||
| 366 | \\processor : 0 | ||
| 367 | \\model name : ARMv6-compatible processor rev 7 (v6l) | ||
| 368 | \\BogoMIPS : 997.08 | ||
| 369 | \\Features : half thumb fastmult vfp edsp java tls | ||
| 370 | \\CPU implementer : 0x41 | ||
| 371 | \\CPU architecture: 7 | ||
| 372 | \\CPU variant : 0x0 | ||
| 373 | \\CPU part : 0xb76 | ||
| 374 | \\CPU revision : 7 | ||
| 375 | ); | ||
| 376 | try testParser(ArmCpuinfoParser, .arm, &Target.arm.cpu.cortex_a7, | ||
| 377 | \\processor	: 0 | ||
| 378 | \\model name	: ARMv7 Processor rev 3 (v7l) | ||
| 379 | \\BogoMIPS	: 18.00 | ||
| 380 | \\Features	: half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae | ||
| 381 | \\CPU implementer	: 0x41 | ||
| 382 | \\CPU architecture: 7 | ||
| 383 | \\CPU variant	: 0x0 | ||
| 384 | \\CPU part	: 0xc07 | ||
| 385 | \\CPU revision	: 3 | ||
| 386 | \\ | ||
| 387 | \\processor	: 4 | ||
| 388 | \\model name	: ARMv7 Processor rev 3 (v7l) | ||
| 389 | \\BogoMIPS	: 90.00 | ||
| 390 | \\Features	: half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae | ||
| 391 | \\CPU implementer	: 0x41 | ||
| 392 | \\CPU architecture: 7 | ||
| 393 | \\CPU variant	: 0x2 | ||
| 394 | \\CPU part	: 0xc0f | ||
| 395 | \\CPU revision	: 3 | ||
| 396 | ); | ||
| 397 | try testParser(ArmCpuinfoParser, .aarch64, &Target.aarch64.cpu.cortex_a72, | ||
| 398 | \\processor : 0 | ||
| 399 | \\BogoMIPS : 108.00 | ||
| 400 | \\Features : fp asimd evtstrm crc32 cpuid | ||
| 401 | \\CPU implementer : 0x41 | ||
| 402 | \\CPU architecture: 8 | ||
| 403 | \\CPU variant : 0x0 | ||
| 404 | \\CPU part : 0xd08 | ||
| 405 | \\CPU revision : 3 | ||
| 406 | ); | ||
| 407 | } | ||
| 408 | |||
| 409 | fn testParser( | ||
| 410 | parser: anytype, | ||
| 411 | arch: Target.Cpu.Arch, | ||
| 412 | expected_model: *const Target.Cpu.Model, | ||
| 413 | input: []const u8, | ||
| 414 | ) !void { | ||
| 149 | var fbs = io.fixedBufferStream(input); | 415 | var fbs = io.fixedBufferStream(input); |
| 150 | const result = try parser.parse(.powerpc, fbs.reader()); | 416 | const result = try parser.parse(arch, fbs.reader()); |
| 151 | testing.expectEqual(expected_model, result.?.model); | 417 | testing.expectEqual(expected_model, result.?.model); |
| 152 | testing.expect(expected_model.features.eql(result.?.features)); | 418 | testing.expect(expected_model.features.eql(result.?.features)); |
| 153 | } | 419 | } |
| ... | @@ -186,6 +452,9 @@ pub fn detectNativeCpuAndFeatures() ?Target.Cpu { | ... | @@ -186,6 +452,9 @@ pub fn detectNativeCpuAndFeatures() ?Target.Cpu { |
| 186 | 452 | ||
| 187 | const current_arch = std.Target.current.cpu.arch; | 453 | const current_arch = std.Target.current.cpu.arch; |
| 188 | switch (current_arch) { | 454 | switch (current_arch) { |
| 455 | .arm, .armeb, .thumb, .thumbeb, .aarch64, .aarch64_be, .aarch64_32 => { | ||
| 456 | return ArmCpuinfoParser.parse(current_arch, f.reader()) catch null; | ||
| 457 | }, | ||
| 189 | .sparcv9 => { | 458 | .sparcv9 => { |
| 190 | return SparcCpuinfoParser.parse(current_arch, f.reader()) catch null; | 459 | return SparcCpuinfoParser.parse(current_arch, f.reader()) catch null; |
| 191 | }, | 460 | }, |
src/Compilation.zig-1| ... | @@ -239,7 +239,6 @@ pub const CObject = struct { | ... | @@ -239,7 +239,6 @@ pub const CObject = struct { |
| 239 | pub fn destroy(em: *ErrorMsg, gpa: *Allocator) void { | 239 | pub fn destroy(em: *ErrorMsg, gpa: *Allocator) void { |
| 240 | gpa.free(em.msg); | 240 | gpa.free(em.msg); |
| 241 | gpa.destroy(em); | 241 | gpa.destroy(em); |
| 242 | em.* = undefined; | ||
| 243 | } | 242 | } |
| 244 | }; | 243 | }; |
| 245 | 244 |
src/link/MachO/Object.zig+80-98| ... | @@ -43,17 +43,13 @@ dwarf_debug_str_index: ?u16 = null, | ... | @@ -43,17 +43,13 @@ dwarf_debug_str_index: ?u16 = null, |
| 43 | dwarf_debug_line_index: ?u16 = null, | 43 | dwarf_debug_line_index: ?u16 = null, |
| 44 | dwarf_debug_ranges_index: ?u16 = null, | 44 | dwarf_debug_ranges_index: ?u16 = null, |
| 45 | 45 | ||
| 46 | symtab: std.ArrayListUnmanaged(macho.nlist_64) = .{}, | 46 | symbols: std.ArrayListUnmanaged(*Symbol) = .{}, |
| 47 | strtab: std.ArrayListUnmanaged(u8) = .{}, | 47 | initializers: std.ArrayListUnmanaged(*Symbol) = .{}, |
| 48 | data_in_code_entries: std.ArrayListUnmanaged(macho.data_in_code_entry) = .{}, | ||
| 48 | 49 | ||
| 49 | locals: std.StringArrayHashMapUnmanaged(Symbol) = .{}, | ||
| 50 | stabs: std.ArrayListUnmanaged(Stab) = .{}, | ||
| 51 | tu_path: ?[]const u8 = null, | 50 | tu_path: ?[]const u8 = null, |
| 52 | tu_mtime: ?u64 = null, | 51 | tu_mtime: ?u64 = null, |
| 53 | 52 | ||
| 54 | initializers: std.ArrayListUnmanaged(CppStatic) = .{}, | ||
| 55 | data_in_code_entries: std.ArrayListUnmanaged(macho.data_in_code_entry) = .{}, | ||
| 56 | |||
| 57 | pub const Section = struct { | 53 | pub const Section = struct { |
| 58 | inner: macho.section_64, | 54 | inner: macho.section_64, |
| 59 | code: []u8, | 55 | code: []u8, |
| ... | @@ -71,23 +67,6 @@ pub const Section = struct { | ... | @@ -71,23 +67,6 @@ pub const Section = struct { |
| 71 | } | 67 | } |
| 72 | }; | 68 | }; |
| 73 | 69 | ||
| 74 | const CppStatic = struct { | ||
| 75 | symbol: u32, | ||
| 76 | target_addr: u64, | ||
| 77 | }; | ||
| 78 | |||
| 79 | const Stab = struct { | ||
| 80 | tag: Tag, | ||
| 81 | symbol: u32, | ||
| 82 | size: ?u64 = null, | ||
| 83 | |||
| 84 | const Tag = enum { | ||
| 85 | function, | ||
| 86 | global, | ||
| 87 | static, | ||
| 88 | }; | ||
| 89 | }; | ||
| 90 | |||
| 91 | const DebugInfo = struct { | 70 | const DebugInfo = struct { |
| 92 | inner: dwarf.DwarfInfo, | 71 | inner: dwarf.DwarfInfo, |
| 93 | debug_info: []u8, | 72 | debug_info: []u8, |
| ... | @@ -169,14 +148,12 @@ pub fn deinit(self: *Object) void { | ... | @@ -169,14 +148,12 @@ pub fn deinit(self: *Object) void { |
| 169 | } | 148 | } |
| 170 | self.sections.deinit(self.allocator); | 149 | self.sections.deinit(self.allocator); |
| 171 | 150 | ||
| 172 | for (self.locals.items()) |*entry| { | 151 | for (self.symbols.items) |sym| { |
| 173 | entry.value.deinit(self.allocator); | 152 | sym.deinit(self.allocator); |
| 153 | self.allocator.destroy(sym); | ||
| 174 | } | 154 | } |
| 175 | self.locals.deinit(self.allocator); | 155 | self.symbols.deinit(self.allocator); |
| 176 | 156 | ||
| 177 | self.symtab.deinit(self.allocator); | ||
| 178 | self.strtab.deinit(self.allocator); | ||
| 179 | self.stabs.deinit(self.allocator); | ||
| 180 | self.data_in_code_entries.deinit(self.allocator); | 157 | self.data_in_code_entries.deinit(self.allocator); |
| 181 | self.initializers.deinit(self.allocator); | 158 | self.initializers.deinit(self.allocator); |
| 182 | 159 | ||
| ... | @@ -222,9 +199,9 @@ pub fn parse(self: *Object) !void { | ... | @@ -222,9 +199,9 @@ pub fn parse(self: *Object) !void { |
| 222 | } | 199 | } |
| 223 | 200 | ||
| 224 | try self.readLoadCommands(reader); | 201 | try self.readLoadCommands(reader); |
| 202 | try self.parseSymbols(); | ||
| 225 | try self.parseSections(); | 203 | try self.parseSections(); |
| 226 | if (self.symtab_cmd_index != null) try self.parseSymtab(); | 204 | try self.parseDataInCode(); |
| 227 | if (self.data_in_code_cmd_index != null) try self.readDataInCode(); | ||
| 228 | try self.parseInitializers(); | 205 | try self.parseInitializers(); |
| 229 | try self.parseDebugInfo(); | 206 | try self.parseDebugInfo(); |
| 230 | } | 207 | } |
| ... | @@ -298,9 +275,10 @@ pub fn readLoadCommands(self: *Object, reader: anytype) !void { | ... | @@ -298,9 +275,10 @@ pub fn readLoadCommands(self: *Object, reader: anytype) !void { |
| 298 | } | 275 | } |
| 299 | 276 | ||
| 300 | pub fn parseSections(self: *Object) !void { | 277 | pub fn parseSections(self: *Object) !void { |
| 301 | log.debug("parsing sections in {s}", .{self.name.?}); | ||
| 302 | const seg = self.load_commands.items[self.segment_cmd_index.?].Segment; | 278 | const seg = self.load_commands.items[self.segment_cmd_index.?].Segment; |
| 303 | 279 | ||
| 280 | log.debug("parsing sections in {s}", .{self.name.?}); | ||
| 281 | |||
| 304 | try self.sections.ensureCapacity(self.allocator, seg.sections.items.len); | 282 | try self.sections.ensureCapacity(self.allocator, seg.sections.items.len); |
| 305 | 283 | ||
| 306 | for (seg.sections.items) |sect| { | 284 | for (seg.sections.items) |sect| { |
| ... | @@ -327,6 +305,7 @@ pub fn parseSections(self: *Object) !void { | ... | @@ -327,6 +305,7 @@ pub fn parseSections(self: *Object) !void { |
| 327 | self.arch.?, | 305 | self.arch.?, |
| 328 | section.code, | 306 | section.code, |
| 329 | mem.bytesAsSlice(macho.relocation_info, raw_relocs), | 307 | mem.bytesAsSlice(macho.relocation_info, raw_relocs), |
| 308 | self.symbols.items, | ||
| 330 | ); | 309 | ); |
| 331 | } | 310 | } |
| 332 | 311 | ||
| ... | @@ -344,60 +323,70 @@ pub fn parseInitializers(self: *Object) !void { | ... | @@ -344,60 +323,70 @@ pub fn parseInitializers(self: *Object) !void { |
| 344 | const relocs = section.relocs orelse unreachable; | 323 | const relocs = section.relocs orelse unreachable; |
| 345 | try self.initializers.ensureCapacity(self.allocator, relocs.len); | 324 | try self.initializers.ensureCapacity(self.allocator, relocs.len); |
| 346 | for (relocs) |rel| { | 325 | for (relocs) |rel| { |
| 347 | self.initializers.appendAssumeCapacity(.{ | 326 | self.initializers.appendAssumeCapacity(rel.target.symbol); |
| 348 | .symbol = rel.target.symbol, | ||
| 349 | .target_addr = undefined, | ||
| 350 | }); | ||
| 351 | } | 327 | } |
| 352 | 328 | ||
| 353 | mem.reverse(CppStatic, self.initializers.items); | 329 | mem.reverse(*Symbol, self.initializers.items); |
| 354 | |||
| 355 | for (self.initializers.items) |initializer| { | ||
| 356 | const sym = self.symtab.items[initializer.symbol]; | ||
| 357 | const sym_name = self.getString(sym.n_strx); | ||
| 358 | log.debug(" | {s}", .{sym_name}); | ||
| 359 | } | ||
| 360 | } | 330 | } |
| 361 | 331 | ||
| 362 | pub fn parseSymtab(self: *Object) !void { | 332 | pub fn parseSymbols(self: *Object) !void { |
| 363 | const symtab_cmd = self.load_commands.items[self.symtab_cmd_index.?].Symtab; | 333 | const index = self.symtab_cmd_index orelse return; |
| 334 | const symtab_cmd = self.load_commands.items[index].Symtab; | ||
| 364 | 335 | ||
| 365 | var symtab = try self.allocator.alloc(u8, @sizeOf(macho.nlist_64) * symtab_cmd.nsyms); | 336 | var symtab = try self.allocator.alloc(u8, @sizeOf(macho.nlist_64) * symtab_cmd.nsyms); |
| 366 | defer self.allocator.free(symtab); | 337 | defer self.allocator.free(symtab); |
| 367 | |||
| 368 | _ = try self.file.?.preadAll(symtab, symtab_cmd.symoff); | 338 | _ = try self.file.?.preadAll(symtab, symtab_cmd.symoff); |
| 369 | const slice = @alignCast(@alignOf(macho.nlist_64), mem.bytesAsSlice(macho.nlist_64, symtab)); | 339 | const slice = @alignCast(@alignOf(macho.nlist_64), mem.bytesAsSlice(macho.nlist_64, symtab)); |
| 370 | try self.symtab.appendSlice(self.allocator, slice); | ||
| 371 | 340 | ||
| 372 | var strtab = try self.allocator.alloc(u8, symtab_cmd.strsize); | 341 | var strtab = try self.allocator.alloc(u8, symtab_cmd.strsize); |
| 373 | defer self.allocator.free(strtab); | 342 | defer self.allocator.free(strtab); |
| 374 | |||
| 375 | _ = try self.file.?.preadAll(strtab, symtab_cmd.stroff); | 343 | _ = try self.file.?.preadAll(strtab, symtab_cmd.stroff); |
| 376 | try self.strtab.appendSlice(self.allocator, strtab); | ||
| 377 | 344 | ||
| 378 | for (self.symtab.items) |sym, sym_id| { | 345 | for (slice) |sym| { |
| 379 | if (Symbol.isStab(sym) or Symbol.isUndef(sym)) continue; | 346 | if (Symbol.isStab(sym)) { |
| 347 | log.err("TODO handle stabs embedded within object files", .{}); | ||
| 348 | return error.HandleStabsInObjects; | ||
| 349 | } | ||
| 380 | 350 | ||
| 381 | const sym_name = self.getString(sym.n_strx); | 351 | const sym_name = mem.spanZ(@ptrCast([*:0]const u8, strtab.ptr + sym.n_strx)); |
| 382 | const tag: Symbol.Tag = tag: { | 352 | const name = try self.allocator.dupe(u8, sym_name); |
| 383 | if (Symbol.isLocal(sym)) { | 353 | |
| 384 | if (self.arch.? == .aarch64 and mem.startsWith(u8, sym_name, "l")) continue; | 354 | const symbol: *Symbol = symbol: { |
| 385 | break :tag .local; | 355 | if (Symbol.isSect(sym)) { |
| 386 | } | 356 | const linkage: Symbol.Regular.Linkage = linkage: { |
| 387 | if (Symbol.isWeakDef(sym)) { | 357 | if (!Symbol.isExt(sym)) break :linkage .translation_unit; |
| 388 | break :tag .weak; | 358 | if (Symbol.isWeakDef(sym) or Symbol.isPext(sym)) break :linkage .linkage_unit; |
| 359 | break :linkage .global; | ||
| 360 | }; | ||
| 361 | const regular = try self.allocator.create(Symbol.Regular); | ||
| 362 | errdefer self.allocator.destroy(regular); | ||
| 363 | regular.* = .{ | ||
| 364 | .base = .{ | ||
| 365 | .@"type" = .regular, | ||
| 366 | .name = name, | ||
| 367 | }, | ||
| 368 | .linkage = linkage, | ||
| 369 | .address = sym.n_value, | ||
| 370 | .section = sym.n_sect - 1, | ||
| 371 | .weak_ref = Symbol.isWeakRef(sym), | ||
| 372 | .file = self, | ||
| 373 | }; | ||
| 374 | break :symbol &regular.base; | ||
| 389 | } | 375 | } |
| 390 | break :tag .strong; | 376 | |
| 377 | const undef = try self.allocator.create(Symbol.Unresolved); | ||
| 378 | errdefer self.allocator.destroy(undef); | ||
| 379 | undef.* = .{ | ||
| 380 | .base = .{ | ||
| 381 | .@"type" = .unresolved, | ||
| 382 | .name = name, | ||
| 383 | }, | ||
| 384 | .file = self, | ||
| 385 | }; | ||
| 386 | break :symbol &undef.base; | ||
| 391 | }; | 387 | }; |
| 392 | const name = try self.allocator.dupe(u8, sym_name); | ||
| 393 | 388 | ||
| 394 | try self.locals.putNoClobber(self.allocator, name, .{ | 389 | try self.symbols.append(self.allocator, symbol); |
| 395 | .tag = tag, | ||
| 396 | .name = name, | ||
| 397 | .address = 0, | ||
| 398 | .section = 0, | ||
| 399 | .index = @intCast(u32, sym_id), | ||
| 400 | }); | ||
| 401 | } | 390 | } |
| 402 | } | 391 | } |
| 403 | 392 | ||
| ... | @@ -429,38 +418,31 @@ pub fn parseDebugInfo(self: *Object) !void { | ... | @@ -429,38 +418,31 @@ pub fn parseDebugInfo(self: *Object) !void { |
| 429 | break :mtime @intCast(u64, @divFloor(stat.mtime, 1_000_000_000)); | 418 | break :mtime @intCast(u64, @divFloor(stat.mtime, 1_000_000_000)); |
| 430 | }; | 419 | }; |
| 431 | 420 | ||
| 432 | for (self.locals.items()) |entry, index| { | 421 | for (self.symbols.items) |sym| { |
| 433 | const local = entry.value; | 422 | if (sym.cast(Symbol.Regular)) |reg| { |
| 434 | const source_sym = self.symtab.items[local.index.?]; | 423 | const size: u64 = blk: for (debug_info.inner.func_list.items) |func| { |
| 435 | const size = blk: for (debug_info.inner.func_list.items) |func| { | 424 | if (func.pc_range) |range| { |
| 436 | if (func.pc_range) |range| { | 425 | if (reg.address >= range.start and reg.address < range.end) { |
| 437 | if (source_sym.n_value >= range.start and source_sym.n_value < range.end) { | 426 | break :blk range.end - range.start; |
| 438 | break :blk range.end - range.start; | 427 | } |
| 439 | } | 428 | } |
| 440 | } | 429 | } else 0; |
| 441 | } else null; | 430 | |
| 442 | const tag: Stab.Tag = tag: { | 431 | reg.stab = .{ |
| 443 | if (size != null) break :tag .function; | 432 | .kind = kind: { |
| 444 | switch (local.tag) { | 433 | if (size > 0) break :kind .function; |
| 445 | .weak, .strong => break :tag .global, | 434 | switch (reg.linkage) { |
| 446 | else => break :tag .static, | 435 | .translation_unit => break :kind .static, |
| 447 | } | 436 | else => break :kind .global, |
| 448 | }; | 437 | } |
| 449 | 438 | }, | |
| 450 | try self.stabs.append(self.allocator, .{ | 439 | .size = size, |
| 451 | .tag = tag, | 440 | }; |
| 452 | .size = size, | 441 | } |
| 453 | .symbol = @intCast(u32, index), | ||
| 454 | }); | ||
| 455 | } | 442 | } |
| 456 | } | 443 | } |
| 457 | 444 | ||
| 458 | pub fn getString(self: *const Object, str_off: u32) []const u8 { | 445 | fn readSection(self: Object, allocator: *Allocator, index: u16) ![]u8 { |
| 459 | assert(str_off < self.strtab.items.len); | ||
| 460 | return mem.spanZ(@ptrCast([*:0]const u8, self.strtab.items.ptr + str_off)); | ||
| 461 | } | ||
| 462 | |||
| 463 | pub fn readSection(self: Object, allocator: *Allocator, index: u16) ![]u8 { | ||
| 464 | const seg = self.load_commands.items[self.segment_cmd_index.?].Segment; | 446 | const seg = self.load_commands.items[self.segment_cmd_index.?].Segment; |
| 465 | const sect = seg.sections.items[index]; | 447 | const sect = seg.sections.items[index]; |
| 466 | var buffer = try allocator.alloc(u8, sect.size); | 448 | var buffer = try allocator.alloc(u8, sect.size); |
| ... | @@ -468,7 +450,7 @@ pub fn readSection(self: Object, allocator: *Allocator, index: u16) ![]u8 { | ... | @@ -468,7 +450,7 @@ pub fn readSection(self: Object, allocator: *Allocator, index: u16) ![]u8 { |
| 468 | return buffer; | 450 | return buffer; |
| 469 | } | 451 | } |
| 470 | 452 | ||
| 471 | pub fn readDataInCode(self: *Object) !void { | 453 | pub fn parseDataInCode(self: *Object) !void { |
| 472 | const index = self.data_in_code_cmd_index orelse return; | 454 | const index = self.data_in_code_cmd_index orelse return; |
| 473 | const data_in_code = self.load_commands.items[index].LinkeditData; | 455 | const data_in_code = self.load_commands.items[index].LinkeditData; |
| 474 | 456 |
src/link/MachO/Symbol.zig+101-30| ... | @@ -2,31 +2,113 @@ const Symbol = @This(); | ... | @@ -2,31 +2,113 @@ const Symbol = @This(); |
| 2 | 2 | ||
| 3 | const std = @import("std"); | 3 | const std = @import("std"); |
| 4 | const macho = std.macho; | 4 | const macho = std.macho; |
| 5 | const mem = std.mem; | ||
| 5 | 6 | ||
| 6 | const Allocator = std.mem.Allocator; | 7 | const Allocator = mem.Allocator; |
| 8 | const Object = @import("Object.zig"); | ||
| 7 | 9 | ||
| 8 | pub const Tag = enum { | 10 | pub const Type = enum { |
| 9 | local, | 11 | regular, |
| 10 | weak, | 12 | proxy, |
| 11 | strong, | 13 | unresolved, |
| 12 | import, | ||
| 13 | undef, | ||
| 14 | }; | 14 | }; |
| 15 | 15 | ||
| 16 | tag: Tag, | 16 | /// Symbol type. |
| 17 | @"type": Type, | ||
| 18 | |||
| 19 | /// Symbol name. Owned slice. | ||
| 17 | name: []u8, | 20 | name: []u8, |
| 18 | address: u64, | ||
| 19 | section: u8, | ||
| 20 | 21 | ||
| 21 | /// Index of file where to locate this symbol. | 22 | /// Alias of. |
| 22 | /// Depending on context, this is either an object file, or a dylib. | 23 | alias: ?*Symbol = null, |
| 23 | file: ?u16 = null, | 24 | |
| 25 | /// Index in GOT table for indirection. | ||
| 26 | got_index: ?u32 = null, | ||
| 27 | |||
| 28 | /// Index in stubs table for late binding. | ||
| 29 | stubs_index: ?u32 = null, | ||
| 30 | |||
| 31 | pub const Regular = struct { | ||
| 32 | base: Symbol, | ||
| 33 | |||
| 34 | /// Linkage type. | ||
| 35 | linkage: Linkage, | ||
| 36 | |||
| 37 | /// Symbol address. | ||
| 38 | address: u64, | ||
| 39 | |||
| 40 | /// Section ID where the symbol resides. | ||
| 41 | section: u8, | ||
| 42 | |||
| 43 | /// Whether the symbol is a weak ref. | ||
| 44 | weak_ref: bool, | ||
| 45 | |||
| 46 | /// File where to locate this symbol. | ||
| 47 | file: *Object, | ||
| 48 | |||
| 49 | /// Debug stab if defined. | ||
| 50 | stab: ?struct { | ||
| 51 | /// Stab kind | ||
| 52 | kind: enum { | ||
| 53 | function, | ||
| 54 | global, | ||
| 55 | static, | ||
| 56 | }, | ||
| 57 | |||
| 58 | /// Size of the stab. | ||
| 59 | size: u64, | ||
| 60 | } = null, | ||
| 61 | |||
| 62 | pub const base_type: Symbol.Type = .regular; | ||
| 63 | |||
| 64 | pub const Linkage = enum { | ||
| 65 | translation_unit, | ||
| 66 | linkage_unit, | ||
| 67 | global, | ||
| 68 | }; | ||
| 69 | |||
| 70 | pub fn isTemp(regular: *Regular) bool { | ||
| 71 | if (regular.linkage == .translation_unit) { | ||
| 72 | return mem.startsWith(u8, regular.base.name, "l") or mem.startsWith(u8, regular.base.name, "L"); | ||
| 73 | } | ||
| 74 | return false; | ||
| 75 | } | ||
| 76 | }; | ||
| 77 | |||
| 78 | pub const Proxy = struct { | ||
| 79 | base: Symbol, | ||
| 80 | |||
| 81 | /// Dylib ordinal. | ||
| 82 | dylib: u16, | ||
| 83 | |||
| 84 | pub const base_type: Symbol.Type = .proxy; | ||
| 85 | }; | ||
| 86 | |||
| 87 | pub const Unresolved = struct { | ||
| 88 | base: Symbol, | ||
| 89 | |||
| 90 | /// File where this symbol was referenced. | ||
| 91 | file: *Object, | ||
| 24 | 92 | ||
| 25 | /// Index of this symbol within the file's symbol table. | 93 | pub const base_type: Symbol.Type = .unresolved; |
| 26 | index: ?u32 = null, | 94 | }; |
| 27 | 95 | ||
| 28 | pub fn deinit(self: *Symbol, allocator: *Allocator) void { | 96 | pub fn deinit(base: *Symbol, allocator: *Allocator) void { |
| 29 | allocator.free(self.name); | 97 | allocator.free(base.name); |
| 98 | } | ||
| 99 | |||
| 100 | pub fn cast(base: *Symbol, comptime T: type) ?*T { | ||
| 101 | if (base.@"type" != T.base_type) { | ||
| 102 | return null; | ||
| 103 | } | ||
| 104 | return @fieldParentPtr(T, "base", base); | ||
| 105 | } | ||
| 106 | |||
| 107 | pub fn getTopmostAlias(base: *Symbol) *Symbol { | ||
| 108 | if (base.alias) |alias| { | ||
| 109 | return alias.getTopmostAlias(); | ||
| 110 | } | ||
| 111 | return base; | ||
| 30 | } | 112 | } |
| 31 | 113 | ||
| 32 | pub fn isStab(sym: macho.nlist_64) bool { | 114 | pub fn isStab(sym: macho.nlist_64) bool { |
| ... | @@ -55,17 +137,6 @@ pub fn isWeakDef(sym: macho.nlist_64) bool { | ... | @@ -55,17 +137,6 @@ pub fn isWeakDef(sym: macho.nlist_64) bool { |
| 55 | return (sym.n_desc & macho.N_WEAK_DEF) != 0; | 137 | return (sym.n_desc & macho.N_WEAK_DEF) != 0; |
| 56 | } | 138 | } |
| 57 | 139 | ||
| 58 | /// Symbol is local if it is defined and not an extern. | 140 | pub fn isWeakRef(sym: macho.nlist_64) bool { |
| 59 | pub fn isLocal(sym: macho.nlist_64) bool { | 141 | return (sym.n_desc & macho.N_WEAK_REF) != 0; |
| 60 | return isSect(sym) and !isExt(sym); | ||
| 61 | } | ||
| 62 | |||
| 63 | /// Symbol is global if it is defined and an extern. | ||
| 64 | pub fn isGlobal(sym: macho.nlist_64) bool { | ||
| 65 | return isSect(sym) and isExt(sym); | ||
| 66 | } | ||
| 67 | |||
| 68 | /// Symbol is undefined if it is not defined and an extern. | ||
| 69 | pub fn isUndef(sym: macho.nlist_64) bool { | ||
| 70 | return isUndf(sym) and isExt(sym); | ||
| 71 | } | 142 | } |
src/link/MachO/Zld.zig+423-449| ... | @@ -29,8 +29,8 @@ page_size: ?u16 = null, | ... | @@ -29,8 +29,8 @@ page_size: ?u16 = null, |
| 29 | file: ?fs.File = null, | 29 | file: ?fs.File = null, |
| 30 | out_path: ?[]const u8 = null, | 30 | out_path: ?[]const u8 = null, |
| 31 | 31 | ||
| 32 | objects: std.ArrayListUnmanaged(Object) = .{}, | 32 | objects: std.ArrayListUnmanaged(*Object) = .{}, |
| 33 | archives: std.ArrayListUnmanaged(Archive) = .{}, | 33 | archives: std.ArrayListUnmanaged(*Archive) = .{}, |
| 34 | 34 | ||
| 35 | load_commands: std.ArrayListUnmanaged(LoadCommand) = .{}, | 35 | load_commands: std.ArrayListUnmanaged(LoadCommand) = .{}, |
| 36 | 36 | ||
| ... | @@ -58,6 +58,7 @@ stubs_section_index: ?u16 = null, | ... | @@ -58,6 +58,7 @@ stubs_section_index: ?u16 = null, |
| 58 | stub_helper_section_index: ?u16 = null, | 58 | stub_helper_section_index: ?u16 = null, |
| 59 | text_const_section_index: ?u16 = null, | 59 | text_const_section_index: ?u16 = null, |
| 60 | cstring_section_index: ?u16 = null, | 60 | cstring_section_index: ?u16 = null, |
| 61 | ustring_section_index: ?u16 = null, | ||
| 61 | 62 | ||
| 62 | // __DATA_CONST segment sections | 63 | // __DATA_CONST segment sections |
| 63 | got_section_index: ?u16 = null, | 64 | got_section_index: ?u16 = null, |
| ... | @@ -74,30 +75,23 @@ data_section_index: ?u16 = null, | ... | @@ -74,30 +75,23 @@ data_section_index: ?u16 = null, |
| 74 | bss_section_index: ?u16 = null, | 75 | bss_section_index: ?u16 = null, |
| 75 | common_section_index: ?u16 = null, | 76 | common_section_index: ?u16 = null, |
| 76 | 77 | ||
| 77 | symtab: std.StringArrayHashMapUnmanaged(Symbol) = .{}, | 78 | globals: std.StringArrayHashMapUnmanaged(*Symbol) = .{}, |
| 79 | imports: std.StringArrayHashMapUnmanaged(*Symbol) = .{}, | ||
| 80 | unresolved: std.StringArrayHashMapUnmanaged(*Symbol) = .{}, | ||
| 81 | |||
| 78 | strtab: std.ArrayListUnmanaged(u8) = .{}, | 82 | strtab: std.ArrayListUnmanaged(u8) = .{}, |
| 79 | strtab_dir: std.StringHashMapUnmanaged(u32) = .{}, | 83 | strtab_dir: std.StringHashMapUnmanaged(u32) = .{}, |
| 80 | 84 | ||
| 81 | threadlocal_offsets: std.ArrayListUnmanaged(u64) = .{}, | 85 | threadlocal_offsets: std.ArrayListUnmanaged(u64) = .{}, |
| 82 | local_rebases: std.ArrayListUnmanaged(Pointer) = .{}, | 86 | local_rebases: std.ArrayListUnmanaged(Pointer) = .{}, |
| 83 | stubs: std.StringArrayHashMapUnmanaged(u32) = .{}, | 87 | stubs: std.ArrayListUnmanaged(*Symbol) = .{}, |
| 84 | got_entries: std.StringArrayHashMapUnmanaged(GotEntry) = .{}, | 88 | got_entries: std.ArrayListUnmanaged(*Symbol) = .{}, |
| 85 | 89 | ||
| 86 | stub_helper_stubs_start_off: ?u64 = null, | 90 | stub_helper_stubs_start_off: ?u64 = null, |
| 87 | 91 | ||
| 88 | mappings: std.AutoHashMapUnmanaged(MappingKey, SectionMapping) = .{}, | 92 | mappings: std.AutoHashMapUnmanaged(MappingKey, SectionMapping) = .{}, |
| 89 | unhandled_sections: std.AutoHashMapUnmanaged(MappingKey, u0) = .{}, | 93 | unhandled_sections: std.AutoHashMapUnmanaged(MappingKey, u0) = .{}, |
| 90 | 94 | ||
| 91 | const GotEntry = struct { | ||
| 92 | tag: enum { | ||
| 93 | local, | ||
| 94 | import, | ||
| 95 | }, | ||
| 96 | index: u32, | ||
| 97 | target_addr: u64, | ||
| 98 | file: u16, | ||
| 99 | }; | ||
| 100 | |||
| 101 | const MappingKey = struct { | 95 | const MappingKey = struct { |
| 102 | object_id: u16, | 96 | object_id: u16, |
| 103 | source_sect_id: u16, | 97 | source_sect_id: u16, |
| ... | @@ -124,15 +118,7 @@ pub fn init(allocator: *Allocator) Zld { | ... | @@ -124,15 +118,7 @@ pub fn init(allocator: *Allocator) Zld { |
| 124 | pub fn deinit(self: *Zld) void { | 118 | pub fn deinit(self: *Zld) void { |
| 125 | self.threadlocal_offsets.deinit(self.allocator); | 119 | self.threadlocal_offsets.deinit(self.allocator); |
| 126 | self.local_rebases.deinit(self.allocator); | 120 | self.local_rebases.deinit(self.allocator); |
| 127 | |||
| 128 | for (self.stubs.items()) |entry| { | ||
| 129 | self.allocator.free(entry.key); | ||
| 130 | } | ||
| 131 | self.stubs.deinit(self.allocator); | 121 | self.stubs.deinit(self.allocator); |
| 132 | |||
| 133 | for (self.got_entries.items()) |entry| { | ||
| 134 | self.allocator.free(entry.key); | ||
| 135 | } | ||
| 136 | self.got_entries.deinit(self.allocator); | 122 | self.got_entries.deinit(self.allocator); |
| 137 | 123 | ||
| 138 | for (self.load_commands.items) |*lc| { | 124 | for (self.load_commands.items) |*lc| { |
| ... | @@ -140,23 +126,22 @@ pub fn deinit(self: *Zld) void { | ... | @@ -140,23 +126,22 @@ pub fn deinit(self: *Zld) void { |
| 140 | } | 126 | } |
| 141 | self.load_commands.deinit(self.allocator); | 127 | self.load_commands.deinit(self.allocator); |
| 142 | 128 | ||
| 143 | for (self.objects.items) |*object| { | 129 | for (self.objects.items) |object| { |
| 144 | object.deinit(); | 130 | object.deinit(); |
| 131 | self.allocator.destroy(object); | ||
| 145 | } | 132 | } |
| 146 | self.objects.deinit(self.allocator); | 133 | self.objects.deinit(self.allocator); |
| 147 | 134 | ||
| 148 | for (self.archives.items) |*archive| { | 135 | for (self.archives.items) |archive| { |
| 149 | archive.deinit(); | 136 | archive.deinit(); |
| 137 | self.allocator.destroy(archive); | ||
| 150 | } | 138 | } |
| 151 | self.archives.deinit(self.allocator); | 139 | self.archives.deinit(self.allocator); |
| 152 | 140 | ||
| 153 | self.mappings.deinit(self.allocator); | 141 | self.mappings.deinit(self.allocator); |
| 154 | self.unhandled_sections.deinit(self.allocator); | 142 | self.unhandled_sections.deinit(self.allocator); |
| 155 | 143 | ||
| 156 | for (self.symtab.items()) |*entry| { | 144 | self.globals.deinit(self.allocator); |
| 157 | entry.value.deinit(self.allocator); | ||
| 158 | } | ||
| 159 | self.symtab.deinit(self.allocator); | ||
| 160 | self.strtab.deinit(self.allocator); | 145 | self.strtab.deinit(self.allocator); |
| 161 | 146 | ||
| 162 | { | 147 | { |
| ... | @@ -224,10 +209,6 @@ pub fn link(self: *Zld, files: []const []const u8, out_path: []const u8) !void { | ... | @@ -224,10 +209,6 @@ pub fn link(self: *Zld, files: []const []const u8, out_path: []const u8) !void { |
| 224 | try self.allocateDataSegment(); | 209 | try self.allocateDataSegment(); |
| 225 | self.allocateLinkeditSegment(); | 210 | self.allocateLinkeditSegment(); |
| 226 | try self.allocateSymbols(); | 211 | try self.allocateSymbols(); |
| 227 | try self.allocateStubsAndGotEntries(); | ||
| 228 | try self.allocateCppStatics(); | ||
| 229 | try self.writeStubHelperCommon(); | ||
| 230 | try self.resolveRelocsAndWriteSections(); | ||
| 231 | try self.flush(); | 212 | try self.flush(); |
| 232 | } | 213 | } |
| 233 | 214 | ||
| ... | @@ -291,7 +272,10 @@ fn parseInputFiles(self: *Zld, files: []const []const u8) !void { | ... | @@ -291,7 +272,10 @@ fn parseInputFiles(self: *Zld, files: []const []const u8) !void { |
| 291 | for (classified.items) |input| { | 272 | for (classified.items) |input| { |
| 292 | switch (input.kind) { | 273 | switch (input.kind) { |
| 293 | .object => { | 274 | .object => { |
| 294 | var object = Object.init(self.allocator); | 275 | const object = try self.allocator.create(Object); |
| 276 | errdefer self.allocator.destroy(object); | ||
| 277 | |||
| 278 | object.* = Object.init(self.allocator); | ||
| 295 | object.arch = self.arch.?; | 279 | object.arch = self.arch.?; |
| 296 | object.name = try self.allocator.dupe(u8, input.name); | 280 | object.name = try self.allocator.dupe(u8, input.name); |
| 297 | object.file = input.file; | 281 | object.file = input.file; |
| ... | @@ -299,7 +283,10 @@ fn parseInputFiles(self: *Zld, files: []const []const u8) !void { | ... | @@ -299,7 +283,10 @@ fn parseInputFiles(self: *Zld, files: []const []const u8) !void { |
| 299 | try self.objects.append(self.allocator, object); | 283 | try self.objects.append(self.allocator, object); |
| 300 | }, | 284 | }, |
| 301 | .archive => { | 285 | .archive => { |
| 302 | var archive = Archive.init(self.allocator); | 286 | const archive = try self.allocator.create(Archive); |
| 287 | errdefer self.allocator.destroy(archive); | ||
| 288 | |||
| 289 | archive.* = Archive.init(self.allocator); | ||
| 303 | archive.arch = self.arch.?; | 290 | archive.arch = self.arch.?; |
| 304 | archive.name = try self.allocator.dupe(u8, input.name); | 291 | archive.name = try self.allocator.dupe(u8, input.name); |
| 305 | archive.file = input.file; | 292 | archive.file = input.file; |
| ... | @@ -367,23 +354,43 @@ fn updateMetadata(self: *Zld) !void { | ... | @@ -367,23 +354,43 @@ fn updateMetadata(self: *Zld) !void { |
| 367 | switch (flags) { | 354 | switch (flags) { |
| 368 | macho.S_REGULAR, macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS => { | 355 | macho.S_REGULAR, macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS => { |
| 369 | if (mem.eql(u8, segname, "__TEXT")) { | 356 | if (mem.eql(u8, segname, "__TEXT")) { |
| 370 | if (self.text_const_section_index != null) continue; | 357 | if (mem.eql(u8, sectname, "__ustring")) { |
| 371 | 358 | if (self.ustring_section_index != null) continue; | |
| 372 | self.text_const_section_index = @intCast(u16, text_seg.sections.items.len); | 359 | |
| 373 | try text_seg.addSection(self.allocator, .{ | 360 | self.ustring_section_index = @intCast(u16, text_seg.sections.items.len); |
| 374 | .sectname = makeStaticString("__const"), | 361 | try text_seg.addSection(self.allocator, .{ |
| 375 | .segname = makeStaticString("__TEXT"), | 362 | .sectname = makeStaticString("__ustring"), |
| 376 | .addr = 0, | 363 | .segname = makeStaticString("__TEXT"), |
| 377 | .size = 0, | 364 | .addr = 0, |
| 378 | .offset = 0, | 365 | .size = 0, |
| 379 | .@"align" = 0, | 366 | .offset = 0, |
| 380 | .reloff = 0, | 367 | .@"align" = 0, |
| 381 | .nreloc = 0, | 368 | .reloff = 0, |
| 382 | .flags = macho.S_REGULAR, | 369 | .nreloc = 0, |
| 383 | .reserved1 = 0, | 370 | .flags = macho.S_REGULAR, |
| 384 | .reserved2 = 0, | 371 | .reserved1 = 0, |
| 385 | .reserved3 = 0, | 372 | .reserved2 = 0, |
| 386 | }); | 373 | .reserved3 = 0, |
| 374 | }); | ||
| 375 | } else { | ||
| 376 | if (self.text_const_section_index != null) continue; | ||
| 377 | |||
| 378 | self.text_const_section_index = @intCast(u16, text_seg.sections.items.len); | ||
| 379 | try text_seg.addSection(self.allocator, .{ | ||
| 380 | .sectname = makeStaticString("__const"), | ||
| 381 | .segname = makeStaticString("__TEXT"), | ||
| 382 | .addr = 0, | ||
| 383 | .size = 0, | ||
| 384 | .offset = 0, | ||
| 385 | .@"align" = 0, | ||
| 386 | .reloff = 0, | ||
| 387 | .nreloc = 0, | ||
| 388 | .flags = macho.S_REGULAR, | ||
| 389 | .reserved1 = 0, | ||
| 390 | .reserved2 = 0, | ||
| 391 | .reserved3 = 0, | ||
| 392 | }); | ||
| 393 | } | ||
| 387 | } else if (mem.eql(u8, segname, "__DATA")) { | 394 | } else if (mem.eql(u8, segname, "__DATA")) { |
| 388 | if (!mem.eql(u8, sectname, "__const")) continue; | 395 | if (!mem.eql(u8, sectname, "__const")) continue; |
| 389 | if (self.data_const_section_index != null) continue; | 396 | if (self.data_const_section_index != null) continue; |
| ... | @@ -599,6 +606,50 @@ fn updateMetadata(self: *Zld) !void { | ... | @@ -599,6 +606,50 @@ fn updateMetadata(self: *Zld) !void { |
| 599 | }, 0); | 606 | }, 0); |
| 600 | } | 607 | } |
| 601 | } | 608 | } |
| 609 | |||
| 610 | tlv_align: { | ||
| 611 | const has_tlv = | ||
| 612 | self.tlv_section_index != null or | ||
| 613 | self.tlv_data_section_index != null or | ||
| 614 | self.tlv_bss_section_index != null; | ||
| 615 | |||
| 616 | if (!has_tlv) break :tlv_align; | ||
| 617 | |||
| 618 | const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; | ||
| 619 | |||
| 620 | if (self.tlv_section_index) |index| { | ||
| 621 | const sect = &seg.sections.items[index]; | ||
| 622 | sect.@"align" = 3; // __thread_vars is always 8byte aligned | ||
| 623 | } | ||
| 624 | |||
| 625 | // Apparently __tlv_data and __tlv_bss need to have matching alignment, so fix it up. | ||
| 626 | // <rdar://problem/24221680> All __thread_data and __thread_bss sections must have same alignment | ||
| 627 | // https://github.com/apple-opensource/ld64/blob/e28c028b20af187a16a7161d89e91868a450cadc/src/ld/ld.cpp#L1172 | ||
| 628 | const data_align: u32 = data: { | ||
| 629 | if (self.tlv_data_section_index) |index| { | ||
| 630 | const sect = &seg.sections.items[index]; | ||
| 631 | break :data sect.@"align"; | ||
| 632 | } | ||
| 633 | break :tlv_align; | ||
| 634 | }; | ||
| 635 | const bss_align: u32 = bss: { | ||
| 636 | if (self.tlv_bss_section_index) |index| { | ||
| 637 | const sect = &seg.sections.items[index]; | ||
| 638 | break :bss sect.@"align"; | ||
| 639 | } | ||
| 640 | break :tlv_align; | ||
| 641 | }; | ||
| 642 | const max_align = math.max(data_align, bss_align); | ||
| 643 | |||
| 644 | if (self.tlv_data_section_index) |index| { | ||
| 645 | const sect = &seg.sections.items[index]; | ||
| 646 | sect.@"align" = max_align; | ||
| 647 | } | ||
| 648 | if (self.tlv_bss_section_index) |index| { | ||
| 649 | const sect = &seg.sections.items[index]; | ||
| 650 | sect.@"align" = max_align; | ||
| 651 | } | ||
| 652 | } | ||
| 602 | } | 653 | } |
| 603 | 654 | ||
| 604 | const MatchingSection = struct { | 655 | const MatchingSection = struct { |
| ... | @@ -674,10 +725,17 @@ fn getMatchingSection(self: *Zld, section: macho.section_64) ?MatchingSection { | ... | @@ -674,10 +725,17 @@ fn getMatchingSection(self: *Zld, section: macho.section_64) ?MatchingSection { |
| 674 | }, | 725 | }, |
| 675 | macho.S_REGULAR => { | 726 | macho.S_REGULAR => { |
| 676 | if (mem.eql(u8, segname, "__TEXT")) { | 727 | if (mem.eql(u8, segname, "__TEXT")) { |
| 677 | break :blk .{ | 728 | if (mem.eql(u8, sectname, "__ustring")) { |
| 678 | .seg = self.text_segment_cmd_index.?, | 729 | break :blk .{ |
| 679 | .sect = self.text_const_section_index.?, | 730 | .seg = self.text_segment_cmd_index.?, |
| 680 | }; | 731 | .sect = self.ustring_section_index.?, |
| 732 | }; | ||
| 733 | } else { | ||
| 734 | break :blk .{ | ||
| 735 | .seg = self.text_segment_cmd_index.?, | ||
| 736 | .sect = self.text_const_section_index.?, | ||
| 737 | }; | ||
| 738 | } | ||
| 681 | } else if (mem.eql(u8, segname, "__DATA")) { | 739 | } else if (mem.eql(u8, segname, "__DATA")) { |
| 682 | if (mem.eql(u8, sectname, "__data")) { | 740 | if (mem.eql(u8, sectname, "__data")) { |
| 683 | break :blk .{ | 741 | break :blk .{ |
| ... | @@ -723,6 +781,7 @@ fn sortSections(self: *Zld) !void { | ... | @@ -723,6 +781,7 @@ fn sortSections(self: *Zld) !void { |
| 723 | &self.stub_helper_section_index, | 781 | &self.stub_helper_section_index, |
| 724 | &self.text_const_section_index, | 782 | &self.text_const_section_index, |
| 725 | &self.cstring_section_index, | 783 | &self.cstring_section_index, |
| 784 | &self.ustring_section_index, | ||
| 726 | }; | 785 | }; |
| 727 | for (indices) |maybe_index| { | 786 | for (indices) |maybe_index| { |
| 728 | const new_index: u16 = if (maybe_index.*) |index| blk: { | 787 | const new_index: u16 = if (maybe_index.*) |index| blk: { |
| ... | @@ -805,7 +864,7 @@ fn sortSections(self: *Zld) !void { | ... | @@ -805,7 +864,7 @@ fn sortSections(self: *Zld) !void { |
| 805 | 864 | ||
| 806 | fn allocateTextSegment(self: *Zld) !void { | 865 | fn allocateTextSegment(self: *Zld) !void { |
| 807 | const seg = &self.load_commands.items[self.text_segment_cmd_index.?].Segment; | 866 | const seg = &self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| 808 | const nstubs = @intCast(u32, self.stubs.items().len); | 867 | const nstubs = @intCast(u32, self.stubs.items.len); |
| 809 | 868 | ||
| 810 | const base_vmaddr = self.load_commands.items[self.pagezero_segment_cmd_index.?].Segment.inner.vmsize; | 869 | const base_vmaddr = self.load_commands.items[self.pagezero_segment_cmd_index.?].Segment.inner.vmsize; |
| 811 | seg.inner.fileoff = 0; | 870 | seg.inner.fileoff = 0; |
| ... | @@ -856,7 +915,7 @@ fn allocateTextSegment(self: *Zld) !void { | ... | @@ -856,7 +915,7 @@ fn allocateTextSegment(self: *Zld) !void { |
| 856 | 915 | ||
| 857 | fn allocateDataConstSegment(self: *Zld) !void { | 916 | fn allocateDataConstSegment(self: *Zld) !void { |
| 858 | const seg = &self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; | 917 | const seg = &self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; |
| 859 | const nentries = @intCast(u32, self.got_entries.items().len); | 918 | const nentries = @intCast(u32, self.got_entries.items.len); |
| 860 | 919 | ||
| 861 | const text_seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment; | 920 | const text_seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| 862 | seg.inner.fileoff = text_seg.inner.fileoff + text_seg.inner.filesize; | 921 | seg.inner.fileoff = text_seg.inner.fileoff + text_seg.inner.filesize; |
| ... | @@ -871,7 +930,7 @@ fn allocateDataConstSegment(self: *Zld) !void { | ... | @@ -871,7 +930,7 @@ fn allocateDataConstSegment(self: *Zld) !void { |
| 871 | 930 | ||
| 872 | fn allocateDataSegment(self: *Zld) !void { | 931 | fn allocateDataSegment(self: *Zld) !void { |
| 873 | const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; | 932 | const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| 874 | const nstubs = @intCast(u32, self.stubs.items().len); | 933 | const nstubs = @intCast(u32, self.stubs.items.len); |
| 875 | 934 | ||
| 876 | const data_const_seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; | 935 | const data_const_seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; |
| 877 | seg.inner.fileoff = data_const_seg.inner.fileoff + data_const_seg.inner.filesize; | 936 | seg.inner.fileoff = data_const_seg.inner.fileoff + data_const_seg.inner.filesize; |
| ... | @@ -914,95 +973,46 @@ fn allocateSegment(self: *Zld, index: u16, offset: u64) !void { | ... | @@ -914,95 +973,46 @@ fn allocateSegment(self: *Zld, index: u16, offset: u64) !void { |
| 914 | } | 973 | } |
| 915 | 974 | ||
| 916 | fn allocateSymbols(self: *Zld) !void { | 975 | fn allocateSymbols(self: *Zld) !void { |
| 917 | for (self.objects.items) |*object, object_id| { | 976 | for (self.objects.items) |object, object_id| { |
| 918 | for (object.locals.items()) |*entry| { | 977 | for (object.symbols.items) |sym| { |
| 919 | const source_sym = object.symtab.items[entry.value.index.?]; | 978 | const reg = sym.cast(Symbol.Regular) orelse continue; |
| 920 | const source_sect_id = source_sym.n_sect - 1; | ||
| 921 | 979 | ||
| 922 | // TODO I am more and more convinced we should store the mapping as part of the Object struct. | 980 | // TODO I am more and more convinced we should store the mapping as part of the Object struct. |
| 923 | const target_mapping = self.mappings.get(.{ | 981 | const target_mapping = self.mappings.get(.{ |
| 924 | .object_id = @intCast(u16, object_id), | 982 | .object_id = @intCast(u16, object_id), |
| 925 | .source_sect_id = source_sect_id, | 983 | .source_sect_id = reg.section, |
| 926 | }) orelse { | 984 | }) orelse { |
| 927 | if (self.unhandled_sections.get(.{ | 985 | if (self.unhandled_sections.get(.{ |
| 928 | .object_id = @intCast(u16, object_id), | 986 | .object_id = @intCast(u16, object_id), |
| 929 | .source_sect_id = source_sect_id, | 987 | .source_sect_id = reg.section, |
| 930 | }) != null) continue; | 988 | }) != null) continue; |
| 931 | 989 | ||
| 932 | log.err("section not mapped for symbol '{s}'", .{entry.value.name}); | 990 | log.err("section not mapped for symbol '{s}'", .{sym.name}); |
| 933 | return error.SectionNotMappedForSymbol; | 991 | return error.SectionNotMappedForSymbol; |
| 934 | }; | 992 | }; |
| 935 | 993 | ||
| 936 | const source_seg = object.load_commands.items[object.segment_cmd_index.?].Segment; | 994 | const source_seg = object.load_commands.items[object.segment_cmd_index.?].Segment; |
| 937 | const source_sect = source_seg.sections.items[source_sect_id]; | 995 | const source_sect = source_seg.sections.items[reg.section]; |
| 938 | const target_seg = self.load_commands.items[target_mapping.target_seg_id].Segment; | 996 | const target_seg = self.load_commands.items[target_mapping.target_seg_id].Segment; |
| 939 | const target_sect = target_seg.sections.items[target_mapping.target_sect_id]; | 997 | const target_sect = target_seg.sections.items[target_mapping.target_sect_id]; |
| 940 | const target_addr = target_sect.addr + target_mapping.offset; | 998 | const target_addr = target_sect.addr + target_mapping.offset; |
| 941 | const n_value = source_sym.n_value - source_sect.addr + target_addr; | 999 | const address = reg.address - source_sect.addr + target_addr; |
| 942 | 1000 | ||
| 943 | log.debug("resolving local symbol '{s}' at 0x{x}", .{ entry.value.name, n_value }); | 1001 | log.debug("resolving symbol '{s}' at 0x{x}", .{ sym.name, address }); |
| 944 | 1002 | ||
| 945 | // TODO there might be a more generic way of doing this. | 1003 | // TODO there might be a more generic way of doing this. |
| 946 | var n_sect: u8 = 0; | 1004 | var section: u8 = 0; |
| 947 | for (self.load_commands.items) |cmd, cmd_id| { | 1005 | for (self.load_commands.items) |cmd, cmd_id| { |
| 948 | if (cmd != .Segment) break; | 1006 | if (cmd != .Segment) break; |
| 949 | if (cmd_id == target_mapping.target_seg_id) { | 1007 | if (cmd_id == target_mapping.target_seg_id) { |
| 950 | n_sect += @intCast(u8, target_mapping.target_sect_id) + 1; | 1008 | section += @intCast(u8, target_mapping.target_sect_id) + 1; |
| 951 | break; | 1009 | break; |
| 952 | } | 1010 | } |
| 953 | n_sect += @intCast(u8, cmd.Segment.sections.items.len); | 1011 | section += @intCast(u8, cmd.Segment.sections.items.len); |
| 954 | } | ||
| 955 | |||
| 956 | entry.value.address = n_value; | ||
| 957 | entry.value.section = n_sect; | ||
| 958 | } | ||
| 959 | } | ||
| 960 | |||
| 961 | for (self.symtab.items()) |*entry| { | ||
| 962 | if (entry.value.tag == .import) continue; | ||
| 963 | |||
| 964 | const object_id = entry.value.file orelse unreachable; | ||
| 965 | const object = self.objects.items[object_id]; | ||
| 966 | const local = object.locals.get(entry.key) orelse unreachable; | ||
| 967 | |||
| 968 | log.debug("resolving {} symbol '{s}' at 0x{x}", .{ entry.value.tag, entry.key, local.address }); | ||
| 969 | |||
| 970 | entry.value.address = local.address; | ||
| 971 | entry.value.section = local.section; | ||
| 972 | } | ||
| 973 | } | ||
| 974 | |||
| 975 | fn allocateStubsAndGotEntries(self: *Zld) !void { | ||
| 976 | for (self.got_entries.items()) |*entry| { | ||
| 977 | if (entry.value.tag == .import) continue; | ||
| 978 | |||
| 979 | const object = self.objects.items[entry.value.file]; | ||
| 980 | entry.value.target_addr = target_addr: { | ||
| 981 | if (object.locals.get(entry.key)) |local| { | ||
| 982 | break :target_addr local.address; | ||
| 983 | } | 1012 | } |
| 984 | const global = self.symtab.get(entry.key) orelse unreachable; | ||
| 985 | break :target_addr global.address; | ||
| 986 | }; | ||
| 987 | |||
| 988 | log.debug("resolving GOT entry '{s}' at 0x{x}", .{ | ||
| 989 | entry.key, | ||
| 990 | entry.value.target_addr, | ||
| 991 | }); | ||
| 992 | } | ||
| 993 | } | ||
| 994 | 1013 | ||
| 995 | fn allocateCppStatics(self: *Zld) !void { | 1014 | reg.address = address; |
| 996 | for (self.objects.items) |*object| { | 1015 | reg.section = section; |
| 997 | for (object.initializers.items) |*initializer| { | ||
| 998 | const sym = object.symtab.items[initializer.symbol]; | ||
| 999 | const sym_name = object.getString(sym.n_strx); | ||
| 1000 | initializer.target_addr = object.locals.get(sym_name).?.address; | ||
| 1001 | |||
| 1002 | log.debug("resolving C++ initializer '{s}' at 0x{x}", .{ | ||
| 1003 | sym_name, | ||
| 1004 | initializer.target_addr, | ||
| 1005 | }); | ||
| 1006 | } | 1016 | } |
| 1007 | } | 1017 | } |
| 1008 | } | 1018 | } |
| ... | @@ -1037,8 +1047,8 @@ fn writeStubHelperCommon(self: *Zld) !void { | ... | @@ -1037,8 +1047,8 @@ fn writeStubHelperCommon(self: *Zld) !void { |
| 1037 | code[9] = 0xff; | 1047 | code[9] = 0xff; |
| 1038 | code[10] = 0x25; | 1048 | code[10] = 0x25; |
| 1039 | { | 1049 | { |
| 1040 | const dyld_stub_binder = self.got_entries.get("dyld_stub_binder").?; | 1050 | const dyld_stub_binder = self.imports.get("dyld_stub_binder").?; |
| 1041 | const addr = (got.addr + dyld_stub_binder.index * @sizeOf(u64)); | 1051 | const addr = (got.addr + dyld_stub_binder.got_index.? * @sizeOf(u64)); |
| 1042 | const displacement = try math.cast(u32, addr - stub_helper.addr - code_size); | 1052 | const displacement = try math.cast(u32, addr - stub_helper.addr - code_size); |
| 1043 | mem.writeIntLittle(u32, code[11..], displacement); | 1053 | mem.writeIntLittle(u32, code[11..], displacement); |
| 1044 | } | 1054 | } |
| ... | @@ -1081,9 +1091,9 @@ fn writeStubHelperCommon(self: *Zld) !void { | ... | @@ -1081,9 +1091,9 @@ fn writeStubHelperCommon(self: *Zld) !void { |
| 1081 | code[10] = 0xbf; | 1091 | code[10] = 0xbf; |
| 1082 | code[11] = 0xa9; | 1092 | code[11] = 0xa9; |
| 1083 | binder_blk_outer: { | 1093 | binder_blk_outer: { |
| 1084 | const dyld_stub_binder = self.got_entries.get("dyld_stub_binder").?; | 1094 | const dyld_stub_binder = self.imports.get("dyld_stub_binder").?; |
| 1085 | const this_addr = stub_helper.addr + 3 * @sizeOf(u32); | 1095 | const this_addr = stub_helper.addr + 3 * @sizeOf(u32); |
| 1086 | const target_addr = (got.addr + dyld_stub_binder.index * @sizeOf(u64)); | 1096 | const target_addr = (got.addr + dyld_stub_binder.got_index.? * @sizeOf(u64)); |
| 1087 | binder_blk: { | 1097 | binder_blk: { |
| 1088 | const displacement = math.divExact(u64, target_addr - this_addr, 4) catch |_| break :binder_blk; | 1098 | const displacement = math.divExact(u64, target_addr - this_addr, 4) catch |_| break :binder_blk; |
| 1089 | const literal = math.cast(u18, displacement) catch |_| break :binder_blk; | 1099 | const literal = math.cast(u18, displacement) catch |_| break :binder_blk; |
| ... | @@ -1134,8 +1144,9 @@ fn writeStubHelperCommon(self: *Zld) !void { | ... | @@ -1134,8 +1144,9 @@ fn writeStubHelperCommon(self: *Zld) !void { |
| 1134 | } | 1144 | } |
| 1135 | }; | 1145 | }; |
| 1136 | 1146 | ||
| 1137 | for (self.stubs.items()) |entry| { | 1147 | for (self.stubs.items) |sym| { |
| 1138 | const index = entry.value; | 1148 | // TODO weak bound pointers |
| 1149 | const index = sym.stubs_index orelse unreachable; | ||
| 1139 | try self.writeLazySymbolPointer(index); | 1150 | try self.writeLazySymbolPointer(index); |
| 1140 | try self.writeStub(index); | 1151 | try self.writeStub(index); |
| 1141 | try self.writeStubInStubHelper(index); | 1152 | try self.writeStubInStubHelper(index); |
| ... | @@ -1274,145 +1285,154 @@ fn writeStubInStubHelper(self: *Zld, index: u32) !void { | ... | @@ -1274,145 +1285,154 @@ fn writeStubInStubHelper(self: *Zld, index: u32) !void { |
| 1274 | try self.file.?.pwriteAll(code, stub_off); | 1285 | try self.file.?.pwriteAll(code, stub_off); |
| 1275 | } | 1286 | } |
| 1276 | 1287 | ||
| 1277 | fn resolveSymbolsInObject(self: *Zld, object_id: u16) !void { | 1288 | fn resolveSymbolsInObject(self: *Zld, object: *Object) !void { |
| 1278 | const object = self.objects.items[object_id]; | ||
| 1279 | log.debug("resolving symbols in '{s}'", .{object.name}); | 1289 | log.debug("resolving symbols in '{s}'", .{object.name}); |
| 1280 | 1290 | ||
| 1281 | for (object.symtab.items) |sym, sym_id| { | 1291 | for (object.symbols.items) |sym| { |
| 1282 | if (Symbol.isLocal(sym)) { | 1292 | if (sym.cast(Symbol.Regular)) |reg| { |
| 1283 | // If symbol is local to CU, we don't put it in the global symbol table. | 1293 | if (reg.linkage == .translation_unit) continue; // Symbol local to TU. |
| 1284 | continue; | 1294 | |
| 1285 | } else if (Symbol.isGlobal(sym)) { | 1295 | if (self.unresolved.swapRemove(sym.name)) |entry| { |
| 1286 | const sym_name = object.getString(sym.n_strx); | 1296 | // Create link to the global. |
| 1287 | const is_weak = Symbol.isWeakDef(sym) or Symbol.isPext(sym); | 1297 | entry.value.alias = sym; |
| 1288 | const global = self.symtab.getEntry(sym_name) orelse { | 1298 | } |
| 1299 | const entry = self.globals.getEntry(sym.name) orelse { | ||
| 1289 | // Put new global symbol into the symbol table. | 1300 | // Put new global symbol into the symbol table. |
| 1290 | const name = try self.allocator.dupe(u8, sym_name); | 1301 | try self.globals.putNoClobber(self.allocator, sym.name, sym); |
| 1291 | try self.symtab.putNoClobber(self.allocator, name, .{ | ||
| 1292 | .tag = if (is_weak) .weak else .strong, | ||
| 1293 | .name = name, | ||
| 1294 | .address = 0, | ||
| 1295 | .section = 0, | ||
| 1296 | .file = object_id, | ||
| 1297 | .index = @intCast(u32, sym_id), | ||
| 1298 | }); | ||
| 1299 | continue; | 1302 | continue; |
| 1300 | }; | 1303 | }; |
| 1301 | 1304 | const g_sym = entry.value; | |
| 1302 | switch (global.value.tag) { | 1305 | const g_reg = g_sym.cast(Symbol.Regular) orelse unreachable; |
| 1303 | .weak => { | 1306 | |
| 1304 | if (is_weak) continue; // Nothing to do for weak symbol. | 1307 | switch (g_reg.linkage) { |
| 1308 | .translation_unit => unreachable, | ||
| 1309 | .linkage_unit => { | ||
| 1310 | if (reg.linkage == .linkage_unit) { | ||
| 1311 | // Create link to the first encountered linkage_unit symbol. | ||
| 1312 | sym.alias = g_sym; | ||
| 1313 | continue; | ||
| 1314 | } | ||
| 1305 | }, | 1315 | }, |
| 1306 | .strong => { | 1316 | .global => { |
| 1307 | if (!is_weak) { | 1317 | if (reg.linkage == .global) { |
| 1308 | log.debug("strong symbol '{s}' defined multiple times", .{sym_name}); | 1318 | log.debug("symbol '{s}' defined multiple times", .{reg.base.name}); |
| 1309 | return error.MultipleSymbolDefinitions; | 1319 | return error.MultipleSymbolDefinitions; |
| 1310 | } | 1320 | } |
| 1321 | sym.alias = g_sym; | ||
| 1311 | continue; | 1322 | continue; |
| 1312 | }, | 1323 | }, |
| 1313 | else => {}, | ||
| 1314 | } | 1324 | } |
| 1315 | 1325 | ||
| 1316 | global.value.tag = if (is_weak) .weak else .strong; | 1326 | g_sym.alias = sym; |
| 1317 | global.value.file = object_id; | 1327 | entry.value = sym; |
| 1318 | global.value.index = @intCast(u32, sym_id); | 1328 | } else if (sym.cast(Symbol.Unresolved)) |und| { |
| 1319 | } else if (Symbol.isUndef(sym)) { | 1329 | if (self.globals.get(sym.name)) |g_sym| { |
| 1320 | const sym_name = object.getString(sym.n_strx); | 1330 | sym.alias = g_sym; |
| 1321 | if (self.symtab.contains(sym_name)) continue; // Nothing to do if we already found a definition. | 1331 | continue; |
| 1322 | 1332 | } | |
| 1323 | const name = try self.allocator.dupe(u8, sym_name); | 1333 | if (self.unresolved.get(sym.name)) |u_sym| { |
| 1324 | try self.symtab.putNoClobber(self.allocator, name, .{ | 1334 | sym.alias = u_sym; |
| 1325 | .tag = .undef, | 1335 | continue; |
| 1326 | .name = name, | 1336 | } |
| 1327 | .address = 0, | 1337 | try self.unresolved.putNoClobber(self.allocator, sym.name, sym); |
| 1328 | .section = 0, | ||
| 1329 | }); | ||
| 1330 | } else unreachable; | 1338 | } else unreachable; |
| 1331 | } | 1339 | } |
| 1332 | } | 1340 | } |
| 1333 | 1341 | ||
| 1334 | fn resolveSymbols(self: *Zld) !void { | 1342 | fn resolveSymbols(self: *Zld) !void { |
| 1335 | // First pass, resolve symbols in provided objects. | 1343 | // First pass, resolve symbols in provided objects. |
| 1336 | for (self.objects.items) |object, object_id| { | 1344 | for (self.objects.items) |object| { |
| 1337 | try self.resolveSymbolsInObject(@intCast(u16, object_id)); | 1345 | try self.resolveSymbolsInObject(object); |
| 1338 | } | 1346 | } |
| 1339 | 1347 | ||
| 1340 | // Second pass, resolve symbols in static libraries. | 1348 | // Second pass, resolve symbols in static libraries. |
| 1341 | var next_sym: usize = 0; | 1349 | var next_sym: usize = 0; |
| 1342 | var nsyms: usize = self.symtab.items().len; | 1350 | while (true) { |
| 1343 | while (next_sym < nsyms) : (next_sym += 1) { | 1351 | if (next_sym == self.unresolved.count()) break; |
| 1344 | const sym = self.symtab.items()[next_sym]; | ||
| 1345 | if (sym.value.tag != .undef) continue; | ||
| 1346 | 1352 | ||
| 1347 | const sym_name = sym.value.name; | 1353 | const entry = self.unresolved.items()[next_sym]; |
| 1354 | const sym = entry.value; | ||
| 1355 | |||
| 1356 | var reset: bool = false; | ||
| 1348 | for (self.archives.items) |archive| { | 1357 | for (self.archives.items) |archive| { |
| 1349 | // Check if the entry exists in a static archive. | 1358 | // Check if the entry exists in a static archive. |
| 1350 | const offsets = archive.toc.get(sym_name) orelse { | 1359 | const offsets = archive.toc.get(sym.name) orelse { |
| 1351 | // No hit. | 1360 | // No hit. |
| 1352 | continue; | 1361 | continue; |
| 1353 | }; | 1362 | }; |
| 1354 | assert(offsets.items.len > 0); | 1363 | assert(offsets.items.len > 0); |
| 1355 | 1364 | ||
| 1356 | const object = try archive.parseObject(offsets.items[0]); | 1365 | const object = try self.allocator.create(Object); |
| 1357 | const object_id = @intCast(u16, self.objects.items.len); | 1366 | errdefer self.allocator.destroy(object); |
| 1367 | |||
| 1368 | object.* = try archive.parseObject(offsets.items[0]); | ||
| 1358 | try self.objects.append(self.allocator, object); | 1369 | try self.objects.append(self.allocator, object); |
| 1359 | try self.resolveSymbolsInObject(object_id); | 1370 | try self.resolveSymbolsInObject(object); |
| 1360 | 1371 | ||
| 1361 | nsyms = self.symtab.items().len; | 1372 | reset = true; |
| 1362 | break; | 1373 | break; |
| 1363 | } | 1374 | } |
| 1375 | |||
| 1376 | if (reset) { | ||
| 1377 | next_sym = 0; | ||
| 1378 | } else { | ||
| 1379 | next_sym += 1; | ||
| 1380 | } | ||
| 1364 | } | 1381 | } |
| 1365 | 1382 | ||
| 1366 | // Third pass, resolve symbols in dynamic libraries. | 1383 | // Third pass, resolve symbols in dynamic libraries. |
| 1367 | // TODO Implement libSystem as a hard-coded library, or ship with | 1384 | // TODO Implement libSystem as a hard-coded library, or ship with |
| 1368 | // a libSystem.B.tbd definition file? | 1385 | // a libSystem.B.tbd definition file? |
| 1369 | for (self.symtab.items()) |*entry| { | 1386 | try self.imports.ensureCapacity(self.allocator, self.unresolved.count()); |
| 1370 | if (entry.value.tag != .undef) continue; | 1387 | for (self.unresolved.items()) |entry| { |
| 1388 | const proxy = try self.allocator.create(Symbol.Proxy); | ||
| 1389 | errdefer self.allocator.destroy(proxy); | ||
| 1390 | |||
| 1391 | proxy.* = .{ | ||
| 1392 | .base = .{ | ||
| 1393 | .@"type" = .proxy, | ||
| 1394 | .name = try self.allocator.dupe(u8, entry.key), | ||
| 1395 | }, | ||
| 1396 | .dylib = 0, | ||
| 1397 | }; | ||
| 1371 | 1398 | ||
| 1372 | entry.value.tag = .import; | 1399 | self.imports.putAssumeCapacityNoClobber(proxy.base.name, &proxy.base); |
| 1373 | entry.value.file = 0; | 1400 | entry.value.alias = &proxy.base; |
| 1374 | } | 1401 | } |
| 1402 | self.unresolved.clearAndFree(self.allocator); | ||
| 1375 | 1403 | ||
| 1376 | // If there are any undefs left, flag an error. | 1404 | // If there are any undefs left, flag an error. |
| 1377 | var has_unresolved = false; | 1405 | if (self.unresolved.count() > 0) { |
| 1378 | for (self.symtab.items()) |entry| { | 1406 | for (self.unresolved.items()) |entry| { |
| 1379 | if (entry.value.tag != .undef) continue; | 1407 | log.err("undefined reference to symbol '{s}'", .{entry.key}); |
| 1380 | 1408 | log.err(" | referenced in {s}", .{ | |
| 1381 | has_unresolved = true; | 1409 | entry.value.cast(Symbol.Unresolved).?.file.name.?, |
| 1382 | log.err("undefined reference to symbol '{s}'", .{entry.value.name}); | 1410 | }); |
| 1383 | } | 1411 | } |
| 1384 | if (has_unresolved) { | ||
| 1385 | return error.UndefinedSymbolReference; | 1412 | return error.UndefinedSymbolReference; |
| 1386 | } | 1413 | } |
| 1387 | 1414 | ||
| 1388 | // Finally put dyld_stub_binder as an Import | 1415 | // Finally put dyld_stub_binder as an Import |
| 1389 | var name = try self.allocator.dupe(u8, "dyld_stub_binder"); | 1416 | const dyld_stub_binder = try self.allocator.create(Symbol.Proxy); |
| 1390 | try self.symtab.putNoClobber(self.allocator, name, .{ | 1417 | errdefer self.allocator.destroy(dyld_stub_binder); |
| 1391 | .tag = .import, | ||
| 1392 | .name = name, | ||
| 1393 | .address = 0, | ||
| 1394 | .section = 0, | ||
| 1395 | .file = 0, | ||
| 1396 | }); | ||
| 1397 | 1418 | ||
| 1398 | { | 1419 | dyld_stub_binder.* = .{ |
| 1399 | log.debug("symtab", .{}); | 1420 | .base = .{ |
| 1400 | for (self.symtab.items()) |sym| { | 1421 | .@"type" = .proxy, |
| 1401 | switch (sym.value.tag) { | 1422 | .name = try self.allocator.dupe(u8, "dyld_stub_binder"), |
| 1402 | .weak, .strong => { | 1423 | }, |
| 1403 | log.debug(" | {s} => {s}", .{ sym.key, self.objects.items[sym.value.file.?].name.? }); | 1424 | .dylib = 0, |
| 1404 | }, | 1425 | }; |
| 1405 | .import => { | 1426 | |
| 1406 | log.debug(" | {s} => libSystem.B.dylib", .{sym.key}); | 1427 | try self.imports.putNoClobber( |
| 1407 | }, | 1428 | self.allocator, |
| 1408 | else => unreachable, | 1429 | dyld_stub_binder.base.name, |
| 1409 | } | 1430 | &dyld_stub_binder.base, |
| 1410 | } | 1431 | ); |
| 1411 | } | ||
| 1412 | } | 1432 | } |
| 1413 | 1433 | ||
| 1414 | fn resolveStubsAndGotEntries(self: *Zld) !void { | 1434 | fn resolveStubsAndGotEntries(self: *Zld) !void { |
| 1415 | for (self.objects.items) |object, object_id| { | 1435 | for (self.objects.items) |object| { |
| 1416 | log.debug("resolving stubs and got entries from {s}", .{object.name}); | 1436 | log.debug("resolving stubs and got entries from {s}", .{object.name}); |
| 1417 | 1437 | ||
| 1418 | for (object.sections.items) |sect| { | 1438 | for (object.sections.items) |sect| { |
| ... | @@ -1421,42 +1441,32 @@ fn resolveStubsAndGotEntries(self: *Zld) !void { | ... | @@ -1421,42 +1441,32 @@ fn resolveStubsAndGotEntries(self: *Zld) !void { |
| 1421 | switch (rel.@"type") { | 1441 | switch (rel.@"type") { |
| 1422 | .unsigned => continue, | 1442 | .unsigned => continue, |
| 1423 | .got_page, .got_page_off, .got_load, .got => { | 1443 | .got_page, .got_page_off, .got_load, .got => { |
| 1424 | const sym = object.symtab.items[rel.target.symbol]; | 1444 | const sym = rel.target.symbol.getTopmostAlias(); |
| 1425 | const sym_name = object.getString(sym.n_strx); | 1445 | if (sym.got_index != null) continue; |
| 1426 | |||
| 1427 | if (self.got_entries.contains(sym_name)) continue; | ||
| 1428 | |||
| 1429 | // TODO clean this up | ||
| 1430 | const is_import = self.symtab.get(sym_name).?.tag == .import; | ||
| 1431 | var name = try self.allocator.dupe(u8, sym_name); | ||
| 1432 | const index = @intCast(u32, self.got_entries.items().len); | ||
| 1433 | try self.got_entries.putNoClobber(self.allocator, name, .{ | ||
| 1434 | .tag = if (is_import) .import else .local, | ||
| 1435 | .index = index, | ||
| 1436 | .target_addr = 0, | ||
| 1437 | .file = if (is_import) 0 else @intCast(u16, object_id), | ||
| 1438 | }); | ||
| 1439 | 1446 | ||
| 1440 | log.debug(" | found GOT entry {s}: {}", .{ sym_name, self.got_entries.get(sym_name) }); | 1447 | const index = @intCast(u32, self.got_entries.items.len); |
| 1448 | sym.got_index = index; | ||
| 1449 | try self.got_entries.append(self.allocator, sym); | ||
| 1450 | |||
| 1451 | log.debug(" | found GOT entry {s}: {*}", .{ sym.name, sym }); | ||
| 1441 | }, | 1452 | }, |
| 1442 | else => { | 1453 | else => { |
| 1443 | if (rel.target != .symbol) continue; | 1454 | if (rel.target != .symbol) continue; |
| 1444 | 1455 | ||
| 1445 | const sym = object.symtab.items[rel.target.symbol]; | 1456 | const sym = rel.target.symbol.getTopmostAlias(); |
| 1446 | const sym_name = object.getString(sym.n_strx); | 1457 | assert(sym.@"type" != .unresolved); |
| 1447 | |||
| 1448 | if (!Symbol.isUndef(sym)) continue; | ||
| 1449 | |||
| 1450 | const in_globals = self.symtab.get(sym_name) orelse unreachable; | ||
| 1451 | 1458 | ||
| 1452 | if (in_globals.tag != .import) continue; | 1459 | if (sym.stubs_index != null) continue; |
| 1453 | if (self.stubs.contains(sym_name)) continue; | 1460 | if (sym.@"type" != .proxy) continue; |
| 1461 | // if (sym.cast(Symbol.Regular)) |reg| { | ||
| 1462 | // if (!reg.weak_ref) continue; | ||
| 1463 | // } | ||
| 1454 | 1464 | ||
| 1455 | var name = try self.allocator.dupe(u8, sym_name); | 1465 | const index = @intCast(u32, self.stubs.items.len); |
| 1456 | const index = @intCast(u32, self.stubs.items().len); | 1466 | sym.stubs_index = index; |
| 1457 | try self.stubs.putNoClobber(self.allocator, name, index); | 1467 | try self.stubs.append(self.allocator, sym); |
| 1458 | 1468 | ||
| 1459 | log.debug(" | found stub {s}: {}", .{ sym_name, self.stubs.get(sym_name) }); | 1469 | log.debug(" | found stub {s}: {*}", .{ sym.name, sym }); |
| 1460 | }, | 1470 | }, |
| 1461 | } | 1471 | } |
| 1462 | } | 1472 | } |
| ... | @@ -1464,16 +1474,12 @@ fn resolveStubsAndGotEntries(self: *Zld) !void { | ... | @@ -1464,16 +1474,12 @@ fn resolveStubsAndGotEntries(self: *Zld) !void { |
| 1464 | } | 1474 | } |
| 1465 | 1475 | ||
| 1466 | // Finally, put dyld_stub_binder as the final GOT entry | 1476 | // Finally, put dyld_stub_binder as the final GOT entry |
| 1467 | var name = try self.allocator.dupe(u8, "dyld_stub_binder"); | 1477 | const sym = self.imports.get("dyld_stub_binder") orelse unreachable; |
| 1468 | const index = @intCast(u32, self.got_entries.items().len); | 1478 | const index = @intCast(u32, self.got_entries.items.len); |
| 1469 | try self.got_entries.putNoClobber(self.allocator, name, .{ | 1479 | sym.got_index = index; |
| 1470 | .tag = .import, | 1480 | try self.got_entries.append(self.allocator, sym); |
| 1471 | .index = index, | ||
| 1472 | .target_addr = 0, | ||
| 1473 | .file = 0, | ||
| 1474 | }); | ||
| 1475 | 1481 | ||
| 1476 | log.debug(" | found GOT entry dyld_stub_binder: {}", .{self.got_entries.get("dyld_stub_binder")}); | 1482 | log.debug(" | found GOT entry {s}: {*}", .{ sym.name, sym }); |
| 1477 | } | 1483 | } |
| 1478 | 1484 | ||
| 1479 | fn resolveRelocsAndWriteSections(self: *Zld) !void { | 1485 | fn resolveRelocsAndWriteSections(self: *Zld) !void { |
| ... | @@ -1547,11 +1553,8 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void { | ... | @@ -1547,11 +1553,8 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void { |
| 1547 | // TLV is handled via a separate offset mechanism. | 1553 | // TLV is handled via a separate offset mechanism. |
| 1548 | // Calculate the offset to the initializer. | 1554 | // Calculate the offset to the initializer. |
| 1549 | if (target_sect.flags == macho.S_THREAD_LOCAL_VARIABLES) tlv: { | 1555 | if (target_sect.flags == macho.S_THREAD_LOCAL_VARIABLES) tlv: { |
| 1550 | const sym = object.symtab.items[rel.target.symbol]; | ||
| 1551 | const sym_name = object.getString(sym.n_strx); | ||
| 1552 | |||
| 1553 | // TODO we don't want to save offset to tlv_bootstrap | 1556 | // TODO we don't want to save offset to tlv_bootstrap |
| 1554 | if (mem.eql(u8, sym_name, "__tlv_bootstrap")) break :tlv; | 1557 | if (mem.eql(u8, rel.target.symbol.name, "__tlv_bootstrap")) break :tlv; |
| 1555 | 1558 | ||
| 1556 | const base_addr = blk: { | 1559 | const base_addr = blk: { |
| 1557 | if (self.tlv_data_section_index) |index| { | 1560 | if (self.tlv_data_section_index) |index| { |
| ... | @@ -1570,10 +1573,8 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void { | ... | @@ -1570,10 +1573,8 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void { |
| 1570 | .got_page, .got_page_off, .got_load, .got => { | 1573 | .got_page, .got_page_off, .got_load, .got => { |
| 1571 | const dc_seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; | 1574 | const dc_seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; |
| 1572 | const got = dc_seg.sections.items[self.got_section_index.?]; | 1575 | const got = dc_seg.sections.items[self.got_section_index.?]; |
| 1573 | const sym = object.symtab.items[rel.target.symbol]; | 1576 | const final = rel.target.symbol.getTopmostAlias(); |
| 1574 | const sym_name = object.getString(sym.n_strx); | 1577 | args.target_addr = got.addr + final.got_index.? * @sizeOf(u64); |
| 1575 | const entry = self.got_entries.get(sym_name) orelse unreachable; | ||
| 1576 | args.target_addr = got.addr + entry.index * @sizeOf(u64); | ||
| 1577 | }, | 1578 | }, |
| 1578 | else => |tt| { | 1579 | else => |tt| { |
| 1579 | if (tt == .signed and rel.target == .section) { | 1580 | if (tt == .signed and rel.target == .section) { |
| ... | @@ -1620,58 +1621,27 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void { | ... | @@ -1620,58 +1621,27 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void { |
| 1620 | } | 1621 | } |
| 1621 | 1622 | ||
| 1622 | fn relocTargetAddr(self: *Zld, object_id: u16, target: reloc.Relocation.Target) !u64 { | 1623 | fn relocTargetAddr(self: *Zld, object_id: u16, target: reloc.Relocation.Target) !u64 { |
| 1623 | const object = self.objects.items[object_id]; | ||
| 1624 | const target_addr = blk: { | 1624 | const target_addr = blk: { |
| 1625 | switch (target) { | 1625 | switch (target) { |
| 1626 | .symbol => |sym_id| { | 1626 | .symbol => |sym| { |
| 1627 | const sym = object.symtab.items[sym_id]; | 1627 | const final = sym.getTopmostAlias(); |
| 1628 | const sym_name = object.getString(sym.n_strx); | 1628 | if (final.cast(Symbol.Regular)) |reg| { |
| 1629 | 1629 | log.debug(" | regular '{s}'", .{sym.name}); | |
| 1630 | if (Symbol.isSect(sym)) { | 1630 | break :blk reg.address; |
| 1631 | log.debug(" | local symbol '{s}'", .{sym_name}); | 1631 | } else if (final.cast(Symbol.Proxy)) |proxy| { |
| 1632 | if (object.locals.get(sym_name)) |local| { | 1632 | if (mem.eql(u8, sym.name, "__tlv_bootstrap")) { |
| 1633 | break :blk local.address; | 1633 | log.debug(" | symbol '__tlv_bootstrap'", .{}); |
| 1634 | } | 1634 | const segment = self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| 1635 | // For temp locals, i.e., symbols prefixed with l... we relocate | 1635 | const tlv = segment.sections.items[self.tlv_section_index.?]; |
| 1636 | // based on section addressing. | 1636 | break :blk tlv.addr; |
| 1637 | const source_sect_id = sym.n_sect - 1; | ||
| 1638 | const target_mapping = self.mappings.get(.{ | ||
| 1639 | .object_id = object_id, | ||
| 1640 | .source_sect_id = source_sect_id, | ||
| 1641 | }) orelse unreachable; | ||
| 1642 | |||
| 1643 | const source_seg = object.load_commands.items[object.segment_cmd_index.?].Segment; | ||
| 1644 | const source_sect = source_seg.sections.items[source_sect_id]; | ||
| 1645 | const target_seg = self.load_commands.items[target_mapping.target_seg_id].Segment; | ||
| 1646 | const target_sect = target_seg.sections.items[target_mapping.target_sect_id]; | ||
| 1647 | const target_addr = target_sect.addr + target_mapping.offset; | ||
| 1648 | break :blk sym.n_value - source_sect.addr + target_addr; | ||
| 1649 | } else if (self.symtab.get(sym_name)) |global| { | ||
| 1650 | switch (global.tag) { | ||
| 1651 | .weak, .strong => { | ||
| 1652 | log.debug(" | global symbol '{s}'", .{sym_name}); | ||
| 1653 | break :blk global.address; | ||
| 1654 | }, | ||
| 1655 | .import => { | ||
| 1656 | if (self.stubs.get(sym_name)) |index| { | ||
| 1657 | log.debug(" | symbol stub '{s}'", .{sym_name}); | ||
| 1658 | const segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment; | ||
| 1659 | const stubs = segment.sections.items[self.stubs_section_index.?]; | ||
| 1660 | break :blk stubs.addr + index * stubs.reserved2; | ||
| 1661 | } else if (mem.eql(u8, sym_name, "__tlv_bootstrap")) { | ||
| 1662 | log.debug(" | symbol '__tlv_bootstrap'", .{}); | ||
| 1663 | const segment = self.load_commands.items[self.data_segment_cmd_index.?].Segment; | ||
| 1664 | const tlv = segment.sections.items[self.tlv_section_index.?]; | ||
| 1665 | break :blk tlv.addr; | ||
| 1666 | } else { | ||
| 1667 | log.err("failed to resolve symbol '{s}' as a relocation target", .{sym_name}); | ||
| 1668 | return error.FailedToResolveRelocationTarget; | ||
| 1669 | } | ||
| 1670 | }, | ||
| 1671 | else => unreachable, | ||
| 1672 | } | 1637 | } |
| 1638 | |||
| 1639 | log.debug(" | symbol stub '{s}'", .{sym.name}); | ||
| 1640 | const segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment; | ||
| 1641 | const stubs = segment.sections.items[self.stubs_section_index.?]; | ||
| 1642 | break :blk stubs.addr + proxy.base.stubs_index.? * stubs.reserved2; | ||
| 1673 | } else { | 1643 | } else { |
| 1674 | log.err("failed to resolve symbol '{s}' as a relocation target", .{sym_name}); | 1644 | log.err("failed to resolve symbol '{s}' as a relocation target", .{sym.name}); |
| 1675 | return error.FailedToResolveRelocationTarget; | 1645 | return error.FailedToResolveRelocationTarget; |
| 1676 | } | 1646 | } |
| 1677 | }, | 1647 | }, |
| ... | @@ -2091,6 +2061,9 @@ fn populateMetadata(self: *Zld) !void { | ... | @@ -2091,6 +2061,9 @@ fn populateMetadata(self: *Zld) !void { |
| 2091 | } | 2061 | } |
| 2092 | 2062 | ||
| 2093 | fn flush(self: *Zld) !void { | 2063 | fn flush(self: *Zld) !void { |
| 2064 | try self.writeStubHelperCommon(); | ||
| 2065 | try self.resolveRelocsAndWriteSections(); | ||
| 2066 | |||
| 2094 | if (self.common_section_index) |index| { | 2067 | if (self.common_section_index) |index| { |
| 2095 | const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; | 2068 | const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| 2096 | const sect = &seg.sections.items[index]; | 2069 | const sect = &seg.sections.items[index]; |
| ... | @@ -2136,10 +2109,10 @@ fn flush(self: *Zld) !void { | ... | @@ -2136,10 +2109,10 @@ fn flush(self: *Zld) !void { |
| 2136 | var initializers = std.ArrayList(u64).init(self.allocator); | 2109 | var initializers = std.ArrayList(u64).init(self.allocator); |
| 2137 | defer initializers.deinit(); | 2110 | defer initializers.deinit(); |
| 2138 | 2111 | ||
| 2139 | // TODO sort the initializers globally | ||
| 2140 | for (self.objects.items) |object| { | 2112 | for (self.objects.items) |object| { |
| 2141 | for (object.initializers.items) |initializer| { | 2113 | for (object.initializers.items) |initializer| { |
| 2142 | try initializers.append(initializer.target_addr); | 2114 | const address = initializer.cast(Symbol.Regular).?.address; |
| 2115 | try initializers.append(address); | ||
| 2143 | } | 2116 | } |
| 2144 | } | 2117 | } |
| 2145 | 2118 | ||
| ... | @@ -2193,14 +2166,15 @@ fn writeGotEntries(self: *Zld) !void { | ... | @@ -2193,14 +2166,15 @@ fn writeGotEntries(self: *Zld) !void { |
| 2193 | const seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; | 2166 | const seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; |
| 2194 | const sect = seg.sections.items[self.got_section_index.?]; | 2167 | const sect = seg.sections.items[self.got_section_index.?]; |
| 2195 | 2168 | ||
| 2196 | var buffer = try self.allocator.alloc(u8, self.got_entries.items().len * @sizeOf(u64)); | 2169 | var buffer = try self.allocator.alloc(u8, self.got_entries.items.len * @sizeOf(u64)); |
| 2197 | defer self.allocator.free(buffer); | 2170 | defer self.allocator.free(buffer); |
| 2198 | 2171 | ||
| 2199 | var stream = std.io.fixedBufferStream(buffer); | 2172 | var stream = std.io.fixedBufferStream(buffer); |
| 2200 | var writer = stream.writer(); | 2173 | var writer = stream.writer(); |
| 2201 | 2174 | ||
| 2202 | for (self.got_entries.items()) |entry| { | 2175 | for (self.got_entries.items) |sym| { |
| 2203 | try writer.writeIntLittle(u64, entry.value.target_addr); | 2176 | const address: u64 = if (sym.cast(Symbol.Regular)) |reg| reg.address else 0; |
| 2177 | try writer.writeIntLittle(u64, address); | ||
| 2204 | } | 2178 | } |
| 2205 | 2179 | ||
| 2206 | log.debug("writing GOT pointers at 0x{x} to 0x{x}", .{ sect.offset, sect.offset + buffer.len }); | 2180 | log.debug("writing GOT pointers at 0x{x} to 0x{x}", .{ sect.offset, sect.offset + buffer.len }); |
| ... | @@ -2213,7 +2187,8 @@ fn setEntryPoint(self: *Zld) !void { | ... | @@ -2213,7 +2187,8 @@ fn setEntryPoint(self: *Zld) !void { |
| 2213 | // entrypoint. For now, assume default of `_main`. | 2187 | // entrypoint. For now, assume default of `_main`. |
| 2214 | const seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment; | 2188 | const seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| 2215 | const text = seg.sections.items[self.text_section_index.?]; | 2189 | const text = seg.sections.items[self.text_section_index.?]; |
| 2216 | const entry_sym = self.symtab.get("_main") orelse return error.MissingMainEntrypoint; | 2190 | const sym = self.globals.get("_main") orelse return error.MissingMainEntrypoint; |
| 2191 | const entry_sym = sym.cast(Symbol.Regular) orelse unreachable; | ||
| 2217 | const ec = &self.load_commands.items[self.main_cmd_index.?].Main; | 2192 | const ec = &self.load_commands.items[self.main_cmd_index.?].Main; |
| 2218 | ec.entryoff = @intCast(u32, entry_sym.address - seg.inner.vmaddr); | 2193 | ec.entryoff = @intCast(u32, entry_sym.address - seg.inner.vmaddr); |
| 2219 | } | 2194 | } |
| ... | @@ -2226,24 +2201,21 @@ fn writeRebaseInfoTable(self: *Zld) !void { | ... | @@ -2226,24 +2201,21 @@ fn writeRebaseInfoTable(self: *Zld) !void { |
| 2226 | pointers.appendSliceAssumeCapacity(self.local_rebases.items); | 2201 | pointers.appendSliceAssumeCapacity(self.local_rebases.items); |
| 2227 | 2202 | ||
| 2228 | if (self.got_section_index) |idx| { | 2203 | if (self.got_section_index) |idx| { |
| 2229 | // TODO this should be cleaned up! | ||
| 2230 | const seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; | 2204 | const seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; |
| 2231 | const sect = seg.sections.items[idx]; | 2205 | const sect = seg.sections.items[idx]; |
| 2232 | const base_offset = sect.addr - seg.inner.vmaddr; | 2206 | const base_offset = sect.addr - seg.inner.vmaddr; |
| 2233 | const segment_id = @intCast(u16, self.data_const_segment_cmd_index.?); | 2207 | const segment_id = @intCast(u16, self.data_const_segment_cmd_index.?); |
| 2234 | 2208 | ||
| 2235 | for (self.got_entries.items()) |entry| { | 2209 | for (self.got_entries.items) |sym| { |
| 2236 | if (entry.value.tag == .import) continue; | 2210 | if (sym.@"type" == .proxy) continue; |
| 2237 | |||
| 2238 | try pointers.append(.{ | 2211 | try pointers.append(.{ |
| 2239 | .offset = base_offset + entry.value.index * @sizeOf(u64), | 2212 | .offset = base_offset + sym.got_index.? * @sizeOf(u64), |
| 2240 | .segment_id = segment_id, | 2213 | .segment_id = segment_id, |
| 2241 | }); | 2214 | }); |
| 2242 | } | 2215 | } |
| 2243 | } | 2216 | } |
| 2244 | 2217 | ||
| 2245 | if (self.mod_init_func_section_index) |idx| { | 2218 | if (self.mod_init_func_section_index) |idx| { |
| 2246 | // TODO audit and investigate this. | ||
| 2247 | const seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; | 2219 | const seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; |
| 2248 | const sect = seg.sections.items[idx]; | 2220 | const sect = seg.sections.items[idx]; |
| 2249 | const base_offset = sect.addr - seg.inner.vmaddr; | 2221 | const base_offset = sect.addr - seg.inner.vmaddr; |
| ... | @@ -2267,10 +2239,10 @@ fn writeRebaseInfoTable(self: *Zld) !void { | ... | @@ -2267,10 +2239,10 @@ fn writeRebaseInfoTable(self: *Zld) !void { |
| 2267 | const base_offset = sect.addr - seg.inner.vmaddr; | 2239 | const base_offset = sect.addr - seg.inner.vmaddr; |
| 2268 | const segment_id = @intCast(u16, self.data_segment_cmd_index.?); | 2240 | const segment_id = @intCast(u16, self.data_segment_cmd_index.?); |
| 2269 | 2241 | ||
| 2270 | try pointers.ensureCapacity(pointers.items.len + self.stubs.items().len); | 2242 | try pointers.ensureCapacity(pointers.items.len + self.stubs.items.len); |
| 2271 | for (self.stubs.items()) |entry| { | 2243 | for (self.stubs.items) |sym| { |
| 2272 | pointers.appendAssumeCapacity(.{ | 2244 | pointers.appendAssumeCapacity(.{ |
| 2273 | .offset = base_offset + entry.value * @sizeOf(u64), | 2245 | .offset = base_offset + sym.stubs_index.? * @sizeOf(u64), |
| 2274 | .segment_id = segment_id, | 2246 | .segment_id = segment_id, |
| 2275 | }); | 2247 | }); |
| 2276 | } | 2248 | } |
| ... | @@ -2306,21 +2278,16 @@ fn writeBindInfoTable(self: *Zld) !void { | ... | @@ -2306,21 +2278,16 @@ fn writeBindInfoTable(self: *Zld) !void { |
| 2306 | const base_offset = sect.addr - seg.inner.vmaddr; | 2278 | const base_offset = sect.addr - seg.inner.vmaddr; |
| 2307 | const segment_id = @intCast(u16, self.data_const_segment_cmd_index.?); | 2279 | const segment_id = @intCast(u16, self.data_const_segment_cmd_index.?); |
| 2308 | 2280 | ||
| 2309 | for (self.got_entries.items()) |entry| { | 2281 | for (self.got_entries.items) |sym| { |
| 2310 | if (entry.value.tag == .local) continue; | 2282 | if (sym.cast(Symbol.Proxy)) |proxy| { |
| 2311 | 2283 | const dylib_ordinal = proxy.dylib + 1; | |
| 2312 | const dylib_ordinal = dylib_ordinal: { | 2284 | try pointers.append(.{ |
| 2313 | const sym = self.symtab.get(entry.key) orelse continue; // local indirection | 2285 | .offset = base_offset + proxy.base.got_index.? * @sizeOf(u64), |
| 2314 | if (sym.tag != .import) continue; // local indirection | 2286 | .segment_id = segment_id, |
| 2315 | break :dylib_ordinal sym.file.? + 1; | 2287 | .dylib_ordinal = dylib_ordinal, |
| 2316 | }; | 2288 | .name = proxy.base.name, |
| 2317 | 2289 | }); | |
| 2318 | try pointers.append(.{ | 2290 | } |
| 2319 | .offset = base_offset + entry.value.index * @sizeOf(u64), | ||
| 2320 | .segment_id = segment_id, | ||
| 2321 | .dylib_ordinal = dylib_ordinal, | ||
| 2322 | .name = entry.key, | ||
| 2323 | }); | ||
| 2324 | } | 2291 | } |
| 2325 | } | 2292 | } |
| 2326 | 2293 | ||
| ... | @@ -2330,14 +2297,15 @@ fn writeBindInfoTable(self: *Zld) !void { | ... | @@ -2330,14 +2297,15 @@ fn writeBindInfoTable(self: *Zld) !void { |
| 2330 | const base_offset = sect.addr - seg.inner.vmaddr; | 2297 | const base_offset = sect.addr - seg.inner.vmaddr; |
| 2331 | const segment_id = @intCast(u16, self.data_segment_cmd_index.?); | 2298 | const segment_id = @intCast(u16, self.data_segment_cmd_index.?); |
| 2332 | 2299 | ||
| 2333 | const sym = self.symtab.get("__tlv_bootstrap") orelse unreachable; | 2300 | const sym = self.imports.get("__tlv_bootstrap") orelse unreachable; |
| 2334 | const dylib_ordinal = sym.file.? + 1; | 2301 | const proxy = sym.cast(Symbol.Proxy) orelse unreachable; |
| 2302 | const dylib_ordinal = proxy.dylib + 1; | ||
| 2335 | 2303 | ||
| 2336 | try pointers.append(.{ | 2304 | try pointers.append(.{ |
| 2337 | .offset = base_offset, | 2305 | .offset = base_offset, |
| 2338 | .segment_id = segment_id, | 2306 | .segment_id = segment_id, |
| 2339 | .dylib_ordinal = dylib_ordinal, | 2307 | .dylib_ordinal = dylib_ordinal, |
| 2340 | .name = "__tlv_bootstrap", | 2308 | .name = proxy.base.name, |
| 2341 | }); | 2309 | }); |
| 2342 | } | 2310 | } |
| 2343 | 2311 | ||
| ... | @@ -2369,20 +2337,16 @@ fn writeLazyBindInfoTable(self: *Zld) !void { | ... | @@ -2369,20 +2337,16 @@ fn writeLazyBindInfoTable(self: *Zld) !void { |
| 2369 | const base_offset = sect.addr - seg.inner.vmaddr; | 2337 | const base_offset = sect.addr - seg.inner.vmaddr; |
| 2370 | const segment_id = @intCast(u16, self.data_segment_cmd_index.?); | 2338 | const segment_id = @intCast(u16, self.data_segment_cmd_index.?); |
| 2371 | 2339 | ||
| 2372 | try pointers.ensureCapacity(self.stubs.items().len); | 2340 | try pointers.ensureCapacity(self.stubs.items.len); |
| 2373 | |||
| 2374 | for (self.stubs.items()) |entry| { | ||
| 2375 | const dylib_ordinal = dylib_ordinal: { | ||
| 2376 | const sym = self.symtab.get(entry.key) orelse unreachable; | ||
| 2377 | assert(sym.tag == .import); | ||
| 2378 | break :dylib_ordinal sym.file.? + 1; | ||
| 2379 | }; | ||
| 2380 | 2341 | ||
| 2342 | for (self.stubs.items) |sym| { | ||
| 2343 | const proxy = sym.cast(Symbol.Proxy) orelse unreachable; | ||
| 2344 | const dylib_ordinal = proxy.dylib + 1; | ||
| 2381 | pointers.appendAssumeCapacity(.{ | 2345 | pointers.appendAssumeCapacity(.{ |
| 2382 | .offset = base_offset + entry.value * @sizeOf(u64), | 2346 | .offset = base_offset + sym.stubs_index.? * @sizeOf(u64), |
| 2383 | .segment_id = segment_id, | 2347 | .segment_id = segment_id, |
| 2384 | .dylib_ordinal = dylib_ordinal, | 2348 | .dylib_ordinal = dylib_ordinal, |
| 2385 | .name = entry.key, | 2349 | .name = sym.name, |
| 2386 | }); | 2350 | }); |
| 2387 | } | 2351 | } |
| 2388 | } | 2352 | } |
| ... | @@ -2451,7 +2415,7 @@ fn populateLazyBindOffsetsInStubHelper(self: *Zld, buffer: []const u8) !void { | ... | @@ -2451,7 +2415,7 @@ fn populateLazyBindOffsetsInStubHelper(self: *Zld, buffer: []const u8) !void { |
| 2451 | else => {}, | 2415 | else => {}, |
| 2452 | } | 2416 | } |
| 2453 | } | 2417 | } |
| 2454 | assert(self.stubs.items().len <= offsets.items.len); | 2418 | assert(self.stubs.items.len <= offsets.items.len); |
| 2455 | 2419 | ||
| 2456 | const stub_size: u4 = switch (self.arch.?) { | 2420 | const stub_size: u4 = switch (self.arch.?) { |
| 2457 | .x86_64 => 10, | 2421 | .x86_64 => 10, |
| ... | @@ -2464,9 +2428,10 @@ fn populateLazyBindOffsetsInStubHelper(self: *Zld, buffer: []const u8) !void { | ... | @@ -2464,9 +2428,10 @@ fn populateLazyBindOffsetsInStubHelper(self: *Zld, buffer: []const u8) !void { |
| 2464 | else => unreachable, | 2428 | else => unreachable, |
| 2465 | }; | 2429 | }; |
| 2466 | var buf: [@sizeOf(u32)]u8 = undefined; | 2430 | var buf: [@sizeOf(u32)]u8 = undefined; |
| 2467 | for (self.stubs.items()) |entry| { | 2431 | for (self.stubs.items) |sym| { |
| 2468 | const placeholder_off = self.stub_helper_stubs_start_off.? + entry.value * stub_size + off; | 2432 | const index = sym.stubs_index orelse unreachable; |
| 2469 | mem.writeIntLittle(u32, &buf, offsets.items[entry.value]); | 2433 | const placeholder_off = self.stub_helper_stubs_start_off.? + index * stub_size + off; |
| 2434 | mem.writeIntLittle(u32, &buf, offsets.items[index]); | ||
| 2470 | try self.file.?.pwriteAll(&buf, placeholder_off); | 2435 | try self.file.?.pwriteAll(&buf, placeholder_off); |
| 2471 | } | 2436 | } |
| 2472 | } | 2437 | } |
| ... | @@ -2478,12 +2443,13 @@ fn writeExportInfo(self: *Zld) !void { | ... | @@ -2478,12 +2443,13 @@ fn writeExportInfo(self: *Zld) !void { |
| 2478 | const text_segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment; | 2443 | const text_segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| 2479 | 2444 | ||
| 2480 | // TODO export items for dylibs | 2445 | // TODO export items for dylibs |
| 2481 | const sym = self.symtab.get("_main") orelse return error.MissingMainEntrypoint; | 2446 | const sym = self.globals.get("_main") orelse return error.MissingMainEntrypoint; |
| 2482 | assert(sym.address >= text_segment.inner.vmaddr); | 2447 | const reg = sym.cast(Symbol.Regular) orelse unreachable; |
| 2448 | assert(reg.address >= text_segment.inner.vmaddr); | ||
| 2483 | 2449 | ||
| 2484 | try trie.put(.{ | 2450 | try trie.put(.{ |
| 2485 | .name = "_main", | 2451 | .name = sym.name, |
| 2486 | .vmaddr_offset = sym.address - text_segment.inner.vmaddr, | 2452 | .vmaddr_offset = reg.address - text_segment.inner.vmaddr, |
| 2487 | .export_flags = macho.EXPORT_SYMBOL_FLAGS_KIND_REGULAR, | 2453 | .export_flags = macho.EXPORT_SYMBOL_FLAGS_KIND_REGULAR, |
| 2488 | }); | 2454 | }); |
| 2489 | 2455 | ||
| ... | @@ -2511,7 +2477,7 @@ fn writeDebugInfo(self: *Zld) !void { | ... | @@ -2511,7 +2477,7 @@ fn writeDebugInfo(self: *Zld) !void { |
| 2511 | var stabs = std.ArrayList(macho.nlist_64).init(self.allocator); | 2477 | var stabs = std.ArrayList(macho.nlist_64).init(self.allocator); |
| 2512 | defer stabs.deinit(); | 2478 | defer stabs.deinit(); |
| 2513 | 2479 | ||
| 2514 | for (self.objects.items) |object, object_id| { | 2480 | for (self.objects.items) |object| { |
| 2515 | const tu_path = object.tu_path orelse continue; | 2481 | const tu_path = object.tu_path orelse continue; |
| 2516 | const tu_mtime = object.tu_mtime orelse continue; | 2482 | const tu_mtime = object.tu_mtime orelse continue; |
| 2517 | const dirname = std.fs.path.dirname(tu_path) orelse "./"; | 2483 | const dirname = std.fs.path.dirname(tu_path) orelse "./"; |
| ... | @@ -2540,39 +2506,42 @@ fn writeDebugInfo(self: *Zld) !void { | ... | @@ -2540,39 +2506,42 @@ fn writeDebugInfo(self: *Zld) !void { |
| 2540 | .n_value = 0, //tu_mtime, TODO figure out why precalculated mtime value doesn't work | 2506 | .n_value = 0, //tu_mtime, TODO figure out why precalculated mtime value doesn't work |
| 2541 | }); | 2507 | }); |
| 2542 | 2508 | ||
| 2543 | for (object.stabs.items) |stab| { | 2509 | for (object.symbols.items) |sym| { |
| 2544 | const entry = object.locals.items()[stab.symbol]; | 2510 | if (sym.@"type" != .regular) continue; |
| 2545 | const sym = entry.value; | 2511 | const reg = sym.cast(Symbol.Regular) orelse unreachable; |
| 2546 | 2512 | ||
| 2547 | switch (stab.tag) { | 2513 | if (reg.isTemp() or reg.stab == null) continue; |
| 2514 | const stab = reg.stab orelse unreachable; | ||
| 2515 | |||
| 2516 | switch (stab.kind) { | ||
| 2548 | .function => { | 2517 | .function => { |
| 2549 | try stabs.append(.{ | 2518 | try stabs.append(.{ |
| 2550 | .n_strx = 0, | 2519 | .n_strx = 0, |
| 2551 | .n_type = macho.N_BNSYM, | 2520 | .n_type = macho.N_BNSYM, |
| 2552 | .n_sect = sym.section, | 2521 | .n_sect = reg.section, |
| 2553 | .n_desc = 0, | 2522 | .n_desc = 0, |
| 2554 | .n_value = sym.address, | 2523 | .n_value = reg.address, |
| 2555 | }); | 2524 | }); |
| 2556 | try stabs.append(.{ | 2525 | try stabs.append(.{ |
| 2557 | .n_strx = try self.makeString(sym.name), | 2526 | .n_strx = try self.makeString(sym.name), |
| 2558 | .n_type = macho.N_FUN, | 2527 | .n_type = macho.N_FUN, |
| 2559 | .n_sect = sym.section, | 2528 | .n_sect = reg.section, |
| 2560 | .n_desc = 0, | 2529 | .n_desc = 0, |
| 2561 | .n_value = sym.address, | 2530 | .n_value = reg.address, |
| 2562 | }); | 2531 | }); |
| 2563 | try stabs.append(.{ | 2532 | try stabs.append(.{ |
| 2564 | .n_strx = 0, | 2533 | .n_strx = 0, |
| 2565 | .n_type = macho.N_FUN, | 2534 | .n_type = macho.N_FUN, |
| 2566 | .n_sect = 0, | 2535 | .n_sect = 0, |
| 2567 | .n_desc = 0, | 2536 | .n_desc = 0, |
| 2568 | .n_value = stab.size.?, | 2537 | .n_value = stab.size, |
| 2569 | }); | 2538 | }); |
| 2570 | try stabs.append(.{ | 2539 | try stabs.append(.{ |
| 2571 | .n_strx = 0, | 2540 | .n_strx = 0, |
| 2572 | .n_type = macho.N_ENSYM, | 2541 | .n_type = macho.N_ENSYM, |
| 2573 | .n_sect = sym.section, | 2542 | .n_sect = reg.section, |
| 2574 | .n_desc = 0, | 2543 | .n_desc = 0, |
| 2575 | .n_value = stab.size.?, | 2544 | .n_value = stab.size, |
| 2576 | }); | 2545 | }); |
| 2577 | }, | 2546 | }, |
| 2578 | .global => { | 2547 | .global => { |
| ... | @@ -2588,9 +2557,9 @@ fn writeDebugInfo(self: *Zld) !void { | ... | @@ -2588,9 +2557,9 @@ fn writeDebugInfo(self: *Zld) !void { |
| 2588 | try stabs.append(.{ | 2557 | try stabs.append(.{ |
| 2589 | .n_strx = try self.makeString(sym.name), | 2558 | .n_strx = try self.makeString(sym.name), |
| 2590 | .n_type = macho.N_STSYM, | 2559 | .n_type = macho.N_STSYM, |
| 2591 | .n_sect = sym.section, | 2560 | .n_sect = reg.section, |
| 2592 | .n_desc = 0, | 2561 | .n_desc = 0, |
| 2593 | .n_value = sym.address, | 2562 | .n_value = reg.address, |
| 2594 | }); | 2563 | }); |
| 2595 | }, | 2564 | }, |
| 2596 | } | 2565 | } |
| ... | @@ -2626,27 +2595,6 @@ fn writeDebugInfo(self: *Zld) !void { | ... | @@ -2626,27 +2595,6 @@ fn writeDebugInfo(self: *Zld) !void { |
| 2626 | dysymtab.nlocalsym = symtab.nsyms; | 2595 | dysymtab.nlocalsym = symtab.nsyms; |
| 2627 | } | 2596 | } |
| 2628 | 2597 | ||
| 2629 | fn populateStringTable(self: *Zld) !void { | ||
| 2630 | for (self.objects.items) |*object| { | ||
| 2631 | for (object.symtab.items) |*sym| { | ||
| 2632 | switch (sym.tag) { | ||
| 2633 | .undef, .import => continue, | ||
| 2634 | else => {}, | ||
| 2635 | } | ||
| 2636 | const sym_name = object.getString(sym.inner.n_strx); | ||
| 2637 | const n_strx = try self.makeString(sym_name); | ||
| 2638 | sym.inner.n_strx = n_strx; | ||
| 2639 | } | ||
| 2640 | } | ||
| 2641 | |||
| 2642 | for (self.symtab.items()) |*entry| { | ||
| 2643 | if (entry.value.tag != .import) continue; | ||
| 2644 | |||
| 2645 | const n_strx = try self.makeString(entry.key); | ||
| 2646 | entry.value.inner.n_strx = n_strx; | ||
| 2647 | } | ||
| 2648 | } | ||
| 2649 | |||
| 2650 | fn writeSymbolTable(self: *Zld) !void { | 2598 | fn writeSymbolTable(self: *Zld) !void { |
| 2651 | const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; | 2599 | const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; |
| 2652 | const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab; | 2600 | const symtab = &self.load_commands.items[self.symtab_cmd_index.?].Symtab; |
| ... | @@ -2654,56 +2602,52 @@ fn writeSymbolTable(self: *Zld) !void { | ... | @@ -2654,56 +2602,52 @@ fn writeSymbolTable(self: *Zld) !void { |
| 2654 | var locals = std.ArrayList(macho.nlist_64).init(self.allocator); | 2602 | var locals = std.ArrayList(macho.nlist_64).init(self.allocator); |
| 2655 | defer locals.deinit(); | 2603 | defer locals.deinit(); |
| 2656 | 2604 | ||
| 2605 | var exports = std.ArrayList(macho.nlist_64).init(self.allocator); | ||
| 2606 | defer exports.deinit(); | ||
| 2607 | |||
| 2657 | for (self.objects.items) |object| { | 2608 | for (self.objects.items) |object| { |
| 2658 | for (object.locals.items()) |entry| { | 2609 | for (object.symbols.items) |sym| { |
| 2659 | const sym = entry.value; | 2610 | const final = sym.getTopmostAlias(); |
| 2660 | if (sym.tag != .local) continue; | 2611 | if (final.@"type" != .regular) continue; |
| 2661 | 2612 | ||
| 2662 | try locals.append(.{ | 2613 | const reg = final.cast(Symbol.Regular) orelse unreachable; |
| 2663 | .n_strx = try self.makeString(sym.name), | 2614 | if (reg.isTemp()) continue; |
| 2664 | .n_type = macho.N_SECT, | 2615 | |
| 2665 | .n_sect = sym.section, | 2616 | switch (reg.linkage) { |
| 2666 | .n_desc = 0, | 2617 | .translation_unit => { |
| 2667 | .n_value = sym.address, | 2618 | try locals.append(.{ |
| 2668 | }); | 2619 | .n_strx = try self.makeString(sym.name), |
| 2620 | .n_type = macho.N_SECT, | ||
| 2621 | .n_sect = reg.section, | ||
| 2622 | .n_desc = 0, | ||
| 2623 | .n_value = reg.address, | ||
| 2624 | }); | ||
| 2625 | }, | ||
| 2626 | else => { | ||
| 2627 | try exports.append(.{ | ||
| 2628 | .n_strx = try self.makeString(sym.name), | ||
| 2629 | .n_type = macho.N_SECT | macho.N_EXT, | ||
| 2630 | .n_sect = reg.section, | ||
| 2631 | .n_desc = 0, | ||
| 2632 | .n_value = reg.address, | ||
| 2633 | }); | ||
| 2634 | }, | ||
| 2635 | } | ||
| 2669 | } | 2636 | } |
| 2670 | } | 2637 | } |
| 2671 | 2638 | ||
| 2672 | var exports = std.ArrayList(macho.nlist_64).init(self.allocator); | ||
| 2673 | defer exports.deinit(); | ||
| 2674 | |||
| 2675 | var undefs = std.ArrayList(macho.nlist_64).init(self.allocator); | 2639 | var undefs = std.ArrayList(macho.nlist_64).init(self.allocator); |
| 2676 | defer undefs.deinit(); | 2640 | defer undefs.deinit(); |
| 2677 | 2641 | ||
| 2678 | var undefs_ids = std.StringHashMap(u32).init(self.allocator); | 2642 | for (self.imports.items()) |entry| { |
| 2679 | defer undefs_ids.deinit(); | ||
| 2680 | |||
| 2681 | var undef_id: u32 = 0; | ||
| 2682 | for (self.symtab.items()) |entry| { | ||
| 2683 | const sym = entry.value; | 2643 | const sym = entry.value; |
| 2684 | switch (sym.tag) { | 2644 | try undefs.append(.{ |
| 2685 | .weak, .strong => { | 2645 | .n_strx = try self.makeString(sym.name), |
| 2686 | try exports.append(.{ | 2646 | .n_type = macho.N_UNDF | macho.N_EXT, |
| 2687 | .n_strx = try self.makeString(sym.name), | 2647 | .n_sect = 0, |
| 2688 | .n_type = macho.N_SECT | macho.N_EXT, | 2648 | .n_desc = macho.N_SYMBOL_RESOLVER | macho.REFERENCE_FLAG_UNDEFINED_NON_LAZY, |
| 2689 | .n_sect = sym.section, | 2649 | .n_value = 0, |
| 2690 | .n_desc = 0, | 2650 | }); |
| 2691 | .n_value = sym.address, | ||
| 2692 | }); | ||
| 2693 | }, | ||
| 2694 | .import => { | ||
| 2695 | try undefs.append(.{ | ||
| 2696 | .n_strx = try self.makeString(sym.name), | ||
| 2697 | .n_type = macho.N_UNDF | macho.N_EXT, | ||
| 2698 | .n_sect = 0, | ||
| 2699 | .n_desc = macho.N_SYMBOL_RESOLVER | macho.REFERENCE_FLAG_UNDEFINED_NON_LAZY, | ||
| 2700 | .n_value = 0, | ||
| 2701 | }); | ||
| 2702 | try undefs_ids.putNoClobber(sym.name, undef_id); | ||
| 2703 | undef_id += 1; | ||
| 2704 | }, | ||
| 2705 | else => unreachable, | ||
| 2706 | } | ||
| 2707 | } | 2651 | } |
| 2708 | 2652 | ||
| 2709 | const nlocals = locals.items.len; | 2653 | const nlocals = locals.items.len; |
| ... | @@ -2743,8 +2687,8 @@ fn writeSymbolTable(self: *Zld) !void { | ... | @@ -2743,8 +2687,8 @@ fn writeSymbolTable(self: *Zld) !void { |
| 2743 | const data_segment = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; | 2687 | const data_segment = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| 2744 | const la_symbol_ptr = &data_segment.sections.items[self.la_symbol_ptr_section_index.?]; | 2688 | const la_symbol_ptr = &data_segment.sections.items[self.la_symbol_ptr_section_index.?]; |
| 2745 | 2689 | ||
| 2746 | const nstubs = @intCast(u32, self.stubs.items().len); | 2690 | const nstubs = @intCast(u32, self.stubs.items.len); |
| 2747 | const ngot_entries = @intCast(u32, self.got_entries.items().len); | 2691 | const ngot_entries = @intCast(u32, self.got_entries.items.len); |
| 2748 | 2692 | ||
| 2749 | dysymtab.indirectsymoff = @intCast(u32, seg.inner.fileoff + seg.inner.filesize); | 2693 | dysymtab.indirectsymoff = @intCast(u32, seg.inner.fileoff + seg.inner.filesize); |
| 2750 | dysymtab.nindirectsyms = nstubs * 2 + ngot_entries; | 2694 | dysymtab.nindirectsyms = nstubs * 2 + ngot_entries; |
| ... | @@ -2764,25 +2708,25 @@ fn writeSymbolTable(self: *Zld) !void { | ... | @@ -2764,25 +2708,25 @@ fn writeSymbolTable(self: *Zld) !void { |
| 2764 | var writer = stream.writer(); | 2708 | var writer = stream.writer(); |
| 2765 | 2709 | ||
| 2766 | stubs.reserved1 = 0; | 2710 | stubs.reserved1 = 0; |
| 2767 | for (self.stubs.items()) |entry| { | 2711 | for (self.stubs.items) |sym| { |
| 2768 | const id = undefs_ids.get(entry.key) orelse unreachable; | 2712 | const id = self.imports.getIndex(sym.name) orelse unreachable; |
| 2769 | try writer.writeIntLittle(u32, dysymtab.iundefsym + id); | 2713 | try writer.writeIntLittle(u32, dysymtab.iundefsym + @intCast(u32, id)); |
| 2770 | } | 2714 | } |
| 2771 | 2715 | ||
| 2772 | got.reserved1 = nstubs; | 2716 | got.reserved1 = nstubs; |
| 2773 | for (self.got_entries.items()) |entry| { | 2717 | for (self.got_entries.items) |sym| { |
| 2774 | if (entry.value.tag == .import) { | 2718 | if (sym.@"type" == .proxy) { |
| 2775 | const id = undefs_ids.get(entry.key) orelse unreachable; | 2719 | const id = self.imports.getIndex(sym.name) orelse unreachable; |
| 2776 | try writer.writeIntLittle(u32, dysymtab.iundefsym + id); | 2720 | try writer.writeIntLittle(u32, dysymtab.iundefsym + @intCast(u32, id)); |
| 2777 | } else { | 2721 | } else { |
| 2778 | try writer.writeIntLittle(u32, macho.INDIRECT_SYMBOL_LOCAL); | 2722 | try writer.writeIntLittle(u32, macho.INDIRECT_SYMBOL_LOCAL); |
| 2779 | } | 2723 | } |
| 2780 | } | 2724 | } |
| 2781 | 2725 | ||
| 2782 | la_symbol_ptr.reserved1 = got.reserved1 + ngot_entries; | 2726 | la_symbol_ptr.reserved1 = got.reserved1 + ngot_entries; |
| 2783 | for (self.stubs.items()) |entry| { | 2727 | for (self.stubs.items) |sym| { |
| 2784 | const id = undefs_ids.get(entry.key) orelse unreachable; | 2728 | const id = self.imports.getIndex(sym.name) orelse unreachable; |
| 2785 | try writer.writeIntLittle(u32, dysymtab.iundefsym + id); | 2729 | try writer.writeIntLittle(u32, dysymtab.iundefsym + @intCast(u32, id)); |
| 2786 | } | 2730 | } |
| 2787 | 2731 | ||
| 2788 | try self.file.?.pwriteAll(buf, dysymtab.indirectsymoff); | 2732 | try self.file.?.pwriteAll(buf, dysymtab.indirectsymoff); |
| ... | @@ -2979,3 +2923,33 @@ pub fn parseName(name: *const [16]u8) []const u8 { | ... | @@ -2979,3 +2923,33 @@ pub fn parseName(name: *const [16]u8) []const u8 { |
| 2979 | const len = mem.indexOfScalar(u8, name, @as(u8, 0)) orelse name.len; | 2923 | const len = mem.indexOfScalar(u8, name, @as(u8, 0)) orelse name.len; |
| 2980 | return name[0..len]; | 2924 | return name[0..len]; |
| 2981 | } | 2925 | } |
| 2926 | |||
| 2927 | fn printSymbols(self: *Zld) void { | ||
| 2928 | log.debug("globals", .{}); | ||
| 2929 | for (self.globals.items()) |entry| { | ||
| 2930 | const sym = entry.value.cast(Symbol.Regular) orelse unreachable; | ||
| 2931 | log.debug(" | {s} @ {*}", .{ sym.base.name, entry.value }); | ||
| 2932 | log.debug(" => alias of {*}", .{sym.base.alias}); | ||
| 2933 | log.debug(" => linkage {s}", .{sym.linkage}); | ||
| 2934 | log.debug(" => defined in {s}", .{sym.file.name.?}); | ||
| 2935 | } | ||
| 2936 | for (self.objects.items) |object| { | ||
| 2937 | log.debug("locals in {s}", .{object.name.?}); | ||
| 2938 | for (object.symbols.items) |sym| { | ||
| 2939 | log.debug(" | {s} @ {*}", .{ sym.name, sym }); | ||
| 2940 | log.debug(" => alias of {*}", .{sym.alias}); | ||
| 2941 | if (sym.cast(Symbol.Regular)) |reg| { | ||
| 2942 | log.debug(" => linkage {s}", .{reg.linkage}); | ||
| 2943 | } else { | ||
| 2944 | log.debug(" => unresolved", .{}); | ||
| 2945 | } | ||
| 2946 | } | ||
| 2947 | } | ||
| 2948 | log.debug("proxies", .{}); | ||
| 2949 | for (self.imports.items()) |entry| { | ||
| 2950 | const sym = entry.value.cast(Symbol.Proxy) orelse unreachable; | ||
| 2951 | log.debug(" | {s} @ {*}", .{ sym.base.name, entry.value }); | ||
| 2952 | log.debug(" => alias of {*}", .{sym.base.alias}); | ||
| 2953 | log.debug(" => defined in libSystem.B.dylib", .{}); | ||
| 2954 | } | ||
| 2955 | } |
src/link/MachO/reloc.zig+7-3| ... | @@ -10,6 +10,7 @@ const aarch64 = @import("reloc/aarch64.zig"); | ... | @@ -10,6 +10,7 @@ const aarch64 = @import("reloc/aarch64.zig"); |
| 10 | const x86_64 = @import("reloc/x86_64.zig"); | 10 | const x86_64 = @import("reloc/x86_64.zig"); |
| 11 | 11 | ||
| 12 | const Allocator = mem.Allocator; | 12 | const Allocator = mem.Allocator; |
| 13 | const Symbol = @import("Symbol.zig"); | ||
| 13 | 14 | ||
| 14 | pub const Relocation = struct { | 15 | pub const Relocation = struct { |
| 15 | @"type": Type, | 16 | @"type": Type, |
| ... | @@ -75,12 +76,12 @@ pub const Relocation = struct { | ... | @@ -75,12 +76,12 @@ pub const Relocation = struct { |
| 75 | }; | 76 | }; |
| 76 | 77 | ||
| 77 | pub const Target = union(enum) { | 78 | pub const Target = union(enum) { |
| 78 | symbol: u32, | 79 | symbol: *Symbol, |
| 79 | section: u16, | 80 | section: u16, |
| 80 | 81 | ||
| 81 | pub fn from_reloc(reloc: macho.relocation_info) Target { | 82 | pub fn from_reloc(reloc: macho.relocation_info, symbols: []*Symbol) Target { |
| 82 | return if (reloc.r_extern == 1) .{ | 83 | return if (reloc.r_extern == 1) .{ |
| 83 | .symbol = reloc.r_symbolnum, | 84 | .symbol = symbols[reloc.r_symbolnum], |
| 84 | } else .{ | 85 | } else .{ |
| 85 | .section = @intCast(u16, reloc.r_symbolnum - 1), | 86 | .section = @intCast(u16, reloc.r_symbolnum - 1), |
| 86 | }; | 87 | }; |
| ... | @@ -136,6 +137,7 @@ pub fn parse( | ... | @@ -136,6 +137,7 @@ pub fn parse( |
| 136 | arch: std.Target.Cpu.Arch, | 137 | arch: std.Target.Cpu.Arch, |
| 137 | code: []u8, | 138 | code: []u8, |
| 138 | relocs: []const macho.relocation_info, | 139 | relocs: []const macho.relocation_info, |
| 140 | symbols: []*Symbol, | ||
| 139 | ) ![]*Relocation { | 141 | ) ![]*Relocation { |
| 140 | var it = RelocIterator{ | 142 | var it = RelocIterator{ |
| 141 | .buffer = relocs, | 143 | .buffer = relocs, |
| ... | @@ -148,6 +150,7 @@ pub fn parse( | ... | @@ -148,6 +150,7 @@ pub fn parse( |
| 148 | .it = &it, | 150 | .it = &it, |
| 149 | .code = code, | 151 | .code = code, |
| 150 | .parsed = std.ArrayList(*Relocation).init(allocator), | 152 | .parsed = std.ArrayList(*Relocation).init(allocator), |
| 153 | .symbols = symbols, | ||
| 151 | }; | 154 | }; |
| 152 | defer parser.deinit(); | 155 | defer parser.deinit(); |
| 153 | try parser.parse(); | 156 | try parser.parse(); |
| ... | @@ -160,6 +163,7 @@ pub fn parse( | ... | @@ -160,6 +163,7 @@ pub fn parse( |
| 160 | .it = &it, | 163 | .it = &it, |
| 161 | .code = code, | 164 | .code = code, |
| 162 | .parsed = std.ArrayList(*Relocation).init(allocator), | 165 | .parsed = std.ArrayList(*Relocation).init(allocator), |
| 166 | .symbols = symbols, | ||
| 163 | }; | 167 | }; |
| 164 | defer parser.deinit(); | 168 | defer parser.deinit(); |
| 165 | try parser.parse(); | 169 | try parser.parse(); |
src/link/MachO/reloc/aarch64.zig+9-7| ... | @@ -10,6 +10,7 @@ const reloc = @import("../reloc.zig"); | ... | @@ -10,6 +10,7 @@ const reloc = @import("../reloc.zig"); |
| 10 | 10 | ||
| 11 | const Allocator = mem.Allocator; | 11 | const Allocator = mem.Allocator; |
| 12 | const Relocation = reloc.Relocation; | 12 | const Relocation = reloc.Relocation; |
| 13 | const Symbol = @import("../Symbol.zig"); | ||
| 13 | 14 | ||
| 14 | pub const Branch = struct { | 15 | pub const Branch = struct { |
| 15 | base: Relocation, | 16 | base: Relocation, |
| ... | @@ -188,6 +189,7 @@ pub const Parser = struct { | ... | @@ -188,6 +189,7 @@ pub const Parser = struct { |
| 188 | it: *reloc.RelocIterator, | 189 | it: *reloc.RelocIterator, |
| 189 | code: []u8, | 190 | code: []u8, |
| 190 | parsed: std.ArrayList(*Relocation), | 191 | parsed: std.ArrayList(*Relocation), |
| 192 | symbols: []*Symbol, | ||
| 191 | addend: ?u32 = null, | 193 | addend: ?u32 = null, |
| 192 | subtractor: ?Relocation.Target = null, | 194 | subtractor: ?Relocation.Target = null, |
| 193 | 195 | ||
| ... | @@ -273,7 +275,7 @@ pub const Parser = struct { | ... | @@ -273,7 +275,7 @@ pub const Parser = struct { |
| 273 | var branch = try parser.allocator.create(Branch); | 275 | var branch = try parser.allocator.create(Branch); |
| 274 | errdefer parser.allocator.destroy(branch); | 276 | errdefer parser.allocator.destroy(branch); |
| 275 | 277 | ||
| 276 | const target = Relocation.Target.from_reloc(rel); | 278 | const target = Relocation.Target.from_reloc(rel, parser.symbols); |
| 277 | 279 | ||
| 278 | branch.* = .{ | 280 | branch.* = .{ |
| 279 | .base = .{ | 281 | .base = .{ |
| ... | @@ -294,7 +296,7 @@ pub const Parser = struct { | ... | @@ -294,7 +296,7 @@ pub const Parser = struct { |
| 294 | assert(rel.r_length == 2); | 296 | assert(rel.r_length == 2); |
| 295 | 297 | ||
| 296 | const rel_type = @intToEnum(macho.reloc_type_arm64, rel.r_type); | 298 | const rel_type = @intToEnum(macho.reloc_type_arm64, rel.r_type); |
| 297 | const target = Relocation.Target.from_reloc(rel); | 299 | const target = Relocation.Target.from_reloc(rel, parser.symbols); |
| 298 | 300 | ||
| 299 | const offset = @intCast(u32, rel.r_address); | 301 | const offset = @intCast(u32, rel.r_address); |
| 300 | const inst = parser.code[offset..][0..4]; | 302 | const inst = parser.code[offset..][0..4]; |
| ... | @@ -400,7 +402,7 @@ pub const Parser = struct { | ... | @@ -400,7 +402,7 @@ pub const Parser = struct { |
| 400 | aarch64.Instruction.load_store_register, | 402 | aarch64.Instruction.load_store_register, |
| 401 | ), inst) }; | 403 | ), inst) }; |
| 402 | } | 404 | } |
| 403 | const target = Relocation.Target.from_reloc(rel); | 405 | const target = Relocation.Target.from_reloc(rel, parser.symbols); |
| 404 | 406 | ||
| 405 | var page_off = try parser.allocator.create(PageOff); | 407 | var page_off = try parser.allocator.create(PageOff); |
| 406 | errdefer parser.allocator.destroy(page_off); | 408 | errdefer parser.allocator.destroy(page_off); |
| ... | @@ -437,7 +439,7 @@ pub const Parser = struct { | ... | @@ -437,7 +439,7 @@ pub const Parser = struct { |
| 437 | ), inst); | 439 | ), inst); |
| 438 | assert(parsed_inst.size == 3); | 440 | assert(parsed_inst.size == 3); |
| 439 | 441 | ||
| 440 | const target = Relocation.Target.from_reloc(rel); | 442 | const target = Relocation.Target.from_reloc(rel, parser.symbols); |
| 441 | 443 | ||
| 442 | var page_off = try parser.allocator.create(GotPageOff); | 444 | var page_off = try parser.allocator.create(GotPageOff); |
| 443 | errdefer parser.allocator.destroy(page_off); | 445 | errdefer parser.allocator.destroy(page_off); |
| ... | @@ -496,7 +498,7 @@ pub const Parser = struct { | ... | @@ -496,7 +498,7 @@ pub const Parser = struct { |
| 496 | } | 498 | } |
| 497 | }; | 499 | }; |
| 498 | 500 | ||
| 499 | const target = Relocation.Target.from_reloc(rel); | 501 | const target = Relocation.Target.from_reloc(rel, parser.symbols); |
| 500 | 502 | ||
| 501 | var page_off = try parser.allocator.create(TlvpPageOff); | 503 | var page_off = try parser.allocator.create(TlvpPageOff); |
| 502 | errdefer parser.allocator.destroy(page_off); | 504 | errdefer parser.allocator.destroy(page_off); |
| ... | @@ -531,7 +533,7 @@ pub const Parser = struct { | ... | @@ -531,7 +533,7 @@ pub const Parser = struct { |
| 531 | assert(rel.r_pcrel == 0); | 533 | assert(rel.r_pcrel == 0); |
| 532 | assert(parser.subtractor == null); | 534 | assert(parser.subtractor == null); |
| 533 | 535 | ||
| 534 | parser.subtractor = Relocation.Target.from_reloc(rel); | 536 | parser.subtractor = Relocation.Target.from_reloc(rel, parser.symbols); |
| 535 | 537 | ||
| 536 | // Verify SUBTRACTOR is followed by UNSIGNED. | 538 | // Verify SUBTRACTOR is followed by UNSIGNED. |
| 537 | const next = @intToEnum(macho.reloc_type_arm64, parser.it.peek().r_type); | 539 | const next = @intToEnum(macho.reloc_type_arm64, parser.it.peek().r_type); |
| ... | @@ -554,7 +556,7 @@ pub const Parser = struct { | ... | @@ -554,7 +556,7 @@ pub const Parser = struct { |
| 554 | var unsigned = try parser.allocator.create(reloc.Unsigned); | 556 | var unsigned = try parser.allocator.create(reloc.Unsigned); |
| 555 | errdefer parser.allocator.destroy(unsigned); | 557 | errdefer parser.allocator.destroy(unsigned); |
| 556 | 558 | ||
| 557 | const target = Relocation.Target.from_reloc(rel); | 559 | const target = Relocation.Target.from_reloc(rel, parser.symbols); |
| 558 | const is_64bit: bool = switch (rel.r_length) { | 560 | const is_64bit: bool = switch (rel.r_length) { |
| 559 | 3 => true, | 561 | 3 => true, |
| 560 | 2 => false, | 562 | 2 => false, |
src/link/MachO/reloc/x86_64.zig+9-7| ... | @@ -9,6 +9,7 @@ const reloc = @import("../reloc.zig"); | ... | @@ -9,6 +9,7 @@ const reloc = @import("../reloc.zig"); |
| 9 | 9 | ||
| 10 | const Allocator = mem.Allocator; | 10 | const Allocator = mem.Allocator; |
| 11 | const Relocation = reloc.Relocation; | 11 | const Relocation = reloc.Relocation; |
| 12 | const Symbol = @import("../Symbol.zig"); | ||
| 12 | 13 | ||
| 13 | pub const Branch = struct { | 14 | pub const Branch = struct { |
| 14 | base: Relocation, | 15 | base: Relocation, |
| ... | @@ -95,6 +96,7 @@ pub const Parser = struct { | ... | @@ -95,6 +96,7 @@ pub const Parser = struct { |
| 95 | it: *reloc.RelocIterator, | 96 | it: *reloc.RelocIterator, |
| 96 | code: []u8, | 97 | code: []u8, |
| 97 | parsed: std.ArrayList(*Relocation), | 98 | parsed: std.ArrayList(*Relocation), |
| 99 | symbols: []*Symbol, | ||
| 98 | subtractor: ?Relocation.Target = null, | 100 | subtractor: ?Relocation.Target = null, |
| 99 | 101 | ||
| 100 | pub fn deinit(parser: *Parser) void { | 102 | pub fn deinit(parser: *Parser) void { |
| ... | @@ -145,7 +147,7 @@ pub const Parser = struct { | ... | @@ -145,7 +147,7 @@ pub const Parser = struct { |
| 145 | var branch = try parser.allocator.create(Branch); | 147 | var branch = try parser.allocator.create(Branch); |
| 146 | errdefer parser.allocator.destroy(branch); | 148 | errdefer parser.allocator.destroy(branch); |
| 147 | 149 | ||
| 148 | const target = Relocation.Target.from_reloc(rel); | 150 | const target = Relocation.Target.from_reloc(rel, parser.symbols); |
| 149 | 151 | ||
| 150 | branch.* = .{ | 152 | branch.* = .{ |
| 151 | .base = .{ | 153 | .base = .{ |
| ... | @@ -165,7 +167,7 @@ pub const Parser = struct { | ... | @@ -165,7 +167,7 @@ pub const Parser = struct { |
| 165 | assert(rel.r_length == 2); | 167 | assert(rel.r_length == 2); |
| 166 | 168 | ||
| 167 | const rel_type = @intToEnum(macho.reloc_type_x86_64, rel.r_type); | 169 | const rel_type = @intToEnum(macho.reloc_type_x86_64, rel.r_type); |
| 168 | const target = Relocation.Target.from_reloc(rel); | 170 | const target = Relocation.Target.from_reloc(rel, parser.symbols); |
| 169 | const is_extern = rel.r_extern == 1; | 171 | const is_extern = rel.r_extern == 1; |
| 170 | 172 | ||
| 171 | const offset = @intCast(u32, rel.r_address); | 173 | const offset = @intCast(u32, rel.r_address); |
| ... | @@ -211,7 +213,7 @@ pub const Parser = struct { | ... | @@ -211,7 +213,7 @@ pub const Parser = struct { |
| 211 | 213 | ||
| 212 | const offset = @intCast(u32, rel.r_address); | 214 | const offset = @intCast(u32, rel.r_address); |
| 213 | const inst = parser.code[offset..][0..4]; | 215 | const inst = parser.code[offset..][0..4]; |
| 214 | const target = Relocation.Target.from_reloc(rel); | 216 | const target = Relocation.Target.from_reloc(rel, parser.symbols); |
| 215 | 217 | ||
| 216 | var got_load = try parser.allocator.create(GotLoad); | 218 | var got_load = try parser.allocator.create(GotLoad); |
| 217 | errdefer parser.allocator.destroy(got_load); | 219 | errdefer parser.allocator.destroy(got_load); |
| ... | @@ -237,7 +239,7 @@ pub const Parser = struct { | ... | @@ -237,7 +239,7 @@ pub const Parser = struct { |
| 237 | 239 | ||
| 238 | const offset = @intCast(u32, rel.r_address); | 240 | const offset = @intCast(u32, rel.r_address); |
| 239 | const inst = parser.code[offset..][0..4]; | 241 | const inst = parser.code[offset..][0..4]; |
| 240 | const target = Relocation.Target.from_reloc(rel); | 242 | const target = Relocation.Target.from_reloc(rel, parser.symbols); |
| 241 | 243 | ||
| 242 | var got = try parser.allocator.create(Got); | 244 | var got = try parser.allocator.create(Got); |
| 243 | errdefer parser.allocator.destroy(got); | 245 | errdefer parser.allocator.destroy(got); |
| ... | @@ -263,7 +265,7 @@ pub const Parser = struct { | ... | @@ -263,7 +265,7 @@ pub const Parser = struct { |
| 263 | 265 | ||
| 264 | const offset = @intCast(u32, rel.r_address); | 266 | const offset = @intCast(u32, rel.r_address); |
| 265 | const inst = parser.code[offset..][0..4]; | 267 | const inst = parser.code[offset..][0..4]; |
| 266 | const target = Relocation.Target.from_reloc(rel); | 268 | const target = Relocation.Target.from_reloc(rel, parser.symbols); |
| 267 | 269 | ||
| 268 | var tlv = try parser.allocator.create(Tlv); | 270 | var tlv = try parser.allocator.create(Tlv); |
| 269 | errdefer parser.allocator.destroy(tlv); | 271 | errdefer parser.allocator.destroy(tlv); |
| ... | @@ -288,7 +290,7 @@ pub const Parser = struct { | ... | @@ -288,7 +290,7 @@ pub const Parser = struct { |
| 288 | assert(rel.r_pcrel == 0); | 290 | assert(rel.r_pcrel == 0); |
| 289 | assert(parser.subtractor == null); | 291 | assert(parser.subtractor == null); |
| 290 | 292 | ||
| 291 | parser.subtractor = Relocation.Target.from_reloc(rel); | 293 | parser.subtractor = Relocation.Target.from_reloc(rel, parser.symbols); |
| 292 | 294 | ||
| 293 | // Verify SUBTRACTOR is followed by UNSIGNED. | 295 | // Verify SUBTRACTOR is followed by UNSIGNED. |
| 294 | const next = @intToEnum(macho.reloc_type_x86_64, parser.it.peek().r_type); | 296 | const next = @intToEnum(macho.reloc_type_x86_64, parser.it.peek().r_type); |
| ... | @@ -311,7 +313,7 @@ pub const Parser = struct { | ... | @@ -311,7 +313,7 @@ pub const Parser = struct { |
| 311 | var unsigned = try parser.allocator.create(reloc.Unsigned); | 313 | var unsigned = try parser.allocator.create(reloc.Unsigned); |
| 312 | errdefer parser.allocator.destroy(unsigned); | 314 | errdefer parser.allocator.destroy(unsigned); |
| 313 | 315 | ||
| 314 | const target = Relocation.Target.from_reloc(rel); | 316 | const target = Relocation.Target.from_reloc(rel, parser.symbols); |
| 315 | const is_64bit: bool = switch (rel.r_length) { | 317 | const is_64bit: bool = switch (rel.r_length) { |
| 316 | 3 => true, | 318 | 3 => true, |
| 317 | 2 => false, | 319 | 2 => false, |
src/stage1/stage1.h+4-1| ... | @@ -56,7 +56,7 @@ enum TargetSubsystem { | ... | @@ -56,7 +56,7 @@ enum TargetSubsystem { |
| 56 | 56 | ||
| 57 | 57 | ||
| 58 | // ABI warning | 58 | // ABI warning |
| 59 | // Synchronize with target.cpp::os_list | 59 | // Synchronize with std.Target.Os.Tag and target.cpp::os_list |
| 60 | enum Os { | 60 | enum Os { |
| 61 | OsFreestanding, | 61 | OsFreestanding, |
| 62 | OsAnanas, | 62 | OsAnanas, |
| ... | @@ -94,6 +94,9 @@ enum Os { | ... | @@ -94,6 +94,9 @@ enum Os { |
| 94 | OsWASI, | 94 | OsWASI, |
| 95 | OsEmscripten, | 95 | OsEmscripten, |
| 96 | OsUefi, | 96 | OsUefi, |
| 97 | OsOpenCL, | ||
| 98 | OsGLSL450, | ||
| 99 | OsVulkan, | ||
| 97 | OsOther, | 100 | OsOther, |
| 98 | }; | 101 | }; |
| 99 | 102 |
src/stage1/target.cpp+16| ... | @@ -122,6 +122,9 @@ static const Os os_list[] = { | ... | @@ -122,6 +122,9 @@ static const Os os_list[] = { |
| 122 | OsWASI, | 122 | OsWASI, |
| 123 | OsEmscripten, | 123 | OsEmscripten, |
| 124 | OsUefi, | 124 | OsUefi, |
| 125 | OsOpenCL, | ||
| 126 | OsGLSL450, | ||
| 127 | OsVulkan, | ||
| 125 | OsOther, | 128 | OsOther, |
| 126 | }; | 129 | }; |
| 127 | 130 | ||
| ... | @@ -213,6 +216,9 @@ Os target_os_enum(size_t index) { | ... | @@ -213,6 +216,9 @@ Os target_os_enum(size_t index) { |
| 213 | ZigLLVM_OSType get_llvm_os_type(Os os_type) { | 216 | ZigLLVM_OSType get_llvm_os_type(Os os_type) { |
| 214 | switch (os_type) { | 217 | switch (os_type) { |
| 215 | case OsFreestanding: | 218 | case OsFreestanding: |
| 219 | case OsOpenCL: | ||
| 220 | case OsGLSL450: | ||
| 221 | case OsVulkan: | ||
| 216 | case OsOther: | 222 | case OsOther: |
| 217 | return ZigLLVM_UnknownOS; | 223 | return ZigLLVM_UnknownOS; |
| 218 | case OsAnanas: | 224 | case OsAnanas: |
| ... | @@ -330,6 +336,9 @@ const char *target_os_name(Os os_type) { | ... | @@ -330,6 +336,9 @@ const char *target_os_name(Os os_type) { |
| 330 | case OsHurd: | 336 | case OsHurd: |
| 331 | case OsWASI: | 337 | case OsWASI: |
| 332 | case OsEmscripten: | 338 | case OsEmscripten: |
| 339 | case OsOpenCL: | ||
| 340 | case OsGLSL450: | ||
| 341 | case OsVulkan: | ||
| 333 | return ZigLLVMGetOSTypeName(get_llvm_os_type(os_type)); | 342 | return ZigLLVMGetOSTypeName(get_llvm_os_type(os_type)); |
| 334 | } | 343 | } |
| 335 | zig_unreachable(); | 344 | zig_unreachable(); |
| ... | @@ -733,6 +742,9 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) { | ... | @@ -733,6 +742,9 @@ uint32_t target_c_type_size_in_bits(const ZigTarget *target, CIntType id) { |
| 733 | case OsAMDPAL: | 742 | case OsAMDPAL: |
| 734 | case OsHermitCore: | 743 | case OsHermitCore: |
| 735 | case OsHurd: | 744 | case OsHurd: |
| 745 | case OsOpenCL: | ||
| 746 | case OsGLSL450: | ||
| 747 | case OsVulkan: | ||
| 736 | zig_panic("TODO c type size in bits for this target"); | 748 | zig_panic("TODO c type size in bits for this target"); |
| 737 | } | 749 | } |
| 738 | zig_unreachable(); | 750 | zig_unreachable(); |
| ... | @@ -999,6 +1011,10 @@ ZigLLVM_EnvironmentType target_default_abi(ZigLLVM_ArchType arch, Os os) { | ... | @@ -999,6 +1011,10 @@ ZigLLVM_EnvironmentType target_default_abi(ZigLLVM_ArchType arch, Os os) { |
| 999 | case OsWASI: | 1011 | case OsWASI: |
| 1000 | case OsEmscripten: | 1012 | case OsEmscripten: |
| 1001 | return ZigLLVM_Musl; | 1013 | return ZigLLVM_Musl; |
| 1014 | case OsOpenCL: | ||
| 1015 | case OsGLSL450: | ||
| 1016 | case OsVulkan: | ||
| 1017 | return ZigLLVM_UnknownEnvironment; | ||
| 1002 | } | 1018 | } |
| 1003 | zig_unreachable(); | 1019 | zig_unreachable(); |
| 1004 | } | 1020 | } |
tools/update_cpu_features.zig+22| ... | @@ -239,6 +239,28 @@ const llvm_targets = [_]LlvmTarget{ | ... | @@ -239,6 +239,28 @@ const llvm_targets = [_]LlvmTarget{ |
| 239 | "zcz_fp", | 239 | "zcz_fp", |
| 240 | }, | 240 | }, |
| 241 | }, | 241 | }, |
| 242 | .{ | ||
| 243 | .llvm_name = null, | ||
| 244 | .zig_name = "xgene1", | ||
| 245 | .features = &.{ | ||
| 246 | "fp_armv8", | ||
| 247 | "neon", | ||
| 248 | "perfmon", | ||
| 249 | "v8a", | ||
| 250 | }, | ||
| 251 | }, | ||
| 252 | .{ | ||
| 253 | .llvm_name = null, | ||
| 254 | .zig_name = "emag", | ||
| 255 | .features = &.{ | ||
| 256 | "crc", | ||
| 257 | "crypto", | ||
| 258 | "fp_armv8", | ||
| 259 | "neon", | ||
| 260 | "perfmon", | ||
| 261 | "v8a", | ||
| 262 | }, | ||
| 263 | }, | ||
| 242 | }, | 264 | }, |
| 243 | }, | 265 | }, |
| 244 | .{ | 266 | .{ |