diff --git a/README.md b/README.md index 2b334805f2..a6f3f0745a 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ is more portable across Linux distributions. | `aarch64-linux-gnu` | OK | | `aarch64-linux-musl` | OK | | `aarch64-windows-gnu` | not tested | -| `aarch64-macos-gnu` | [#44](https://github.com/ziglang/zig-bootstrap/issues/44) | +| `aarch64-macos-gnu` | OK | | `armeb-linux-gnueabi` | not tested | | `armeb-linux-gnueabihf` | not tested | | `armeb-linux-musleabi` | not tested | diff --git a/build b/build index dfc5573128..f933d6383d 100755 --- a/build +++ b/build @@ -7,7 +7,7 @@ TARGET="$2" # Example: riscv64-linux-gnu MCPU="$3" # Examples: `baseline`, `native`, `generic+v7a`, or `arm1176jzf_s` ROOTDIR="$(pwd)" -ZIG_VERSION="0.8.0-dev.1939+5a3ea9bec" +ZIG_VERSION="0.8.0-dev.1813+88d40fc00" TARGET_OS_AND_ABI=${TARGET#*-} # Example: linux-gnu diff --git a/zig/.gitattributes b/zig/.gitattributes index 8bf5843425..6cf47bc9ad 100644 --- a/zig/.gitattributes +++ b/zig/.gitattributes @@ -3,9 +3,9 @@ langref.html.in text eol=lf deps/SoftFloat-3e/*.txt text eol=crlf -deps/* linguist-vendored -lib/include/* linguist-vendored -lib/libc/* linguist-vendored -lib/libcxx/* linguist-vendored -lib/libcxxabi/* linguist-vendored -lib/libunwind/* linguist-vendored +deps/** linguist-vendored +lib/include/** linguist-vendored +lib/libc/** linguist-vendored +lib/libcxx/** linguist-vendored +lib/libcxxabi/** linguist-vendored +lib/libunwind/** linguist-vendored diff --git a/zig/.github/FUNDING.yml b/zig/.github/FUNDING.yml new file mode 100644 index 0000000000..02ba7f0d31 --- /dev/null +++ b/zig/.github/FUNDING.yml @@ -0,0 +1 @@ +github: [ziglang] diff --git a/zig/build.zig b/zig/build.zig index 92e03603c5..a0bc6a89c3 100644 --- a/zig/build.zig +++ b/zig/build.zig @@ -36,7 +36,7 @@ pub fn build(b: *Builder) !void { const docs_step = b.step("docs", "Build documentation"); docs_step.dependOn(&docgen_cmd.step); - const test_step = b.step("test", "Run all the tests"); + const toolchain_step = b.step("test-toolchain", "Run the tests for the toolchain"); var test_stage2 = b.addTest("src/test.zig"); test_stage2.setBuildMode(mode); @@ -44,6 +44,7 @@ pub fn build(b: *Builder) !void { const fmt_build_zig = b.addFmt(&[_][]const u8{"build.zig"}); + const skip_debug = b.option(bool, "skip-debug", "Main test suite skips debug builds") orelse false; const skip_release = b.option(bool, "skip-release", "Main test suite skips release builds") orelse false; const skip_release_small = b.option(bool, "skip-release-small", "Main test suite skips release-small builds") orelse skip_release; const skip_release_fast = b.option(bool, "skip-release-fast", "Main test suite skips release-fast builds") orelse skip_release; @@ -51,9 +52,12 @@ pub fn build(b: *Builder) !void { const skip_non_native = b.option(bool, "skip-non-native", "Main test suite skips non-native builds") orelse false; const skip_libc = b.option(bool, "skip-libc", "Main test suite skips tests that link libc") orelse false; const skip_compile_errors = b.option(bool, "skip-compile-errors", "Main test suite skips compile error tests") orelse false; + const skip_run_translated_c = b.option(bool, "skip-run-translated-c", "Main test suite skips run-translated-c tests") orelse false; + const skip_stage2_tests = b.option(bool, "skip-stage2-tests", "Main test suite skips self-hosted compiler tests") orelse false; const only_install_lib_files = b.option(bool, "lib-files-only", "Only install library files") orelse false; const is_stage1 = b.option(bool, "stage1", "Build the stage1 compiler, put stage2 behind a feature flag") orelse false; + const omit_stage2 = b.option(bool, "omit-stage2", "Do not include stage2 behind a feature flag inside stage1") orelse false; const static_llvm = b.option(bool, "static-llvm", "Disable integration with system-installed LLVM, Clang, LLD, and libc++") orelse false; const enable_llvm = b.option(bool, "enable-llvm", "Build self-hosted compiler with LLVM backend enabled") orelse (is_stage1 or static_llvm); const config_h_path_option = b.option([]const u8, "config_h", "Path to the generated config.h"); @@ -86,7 +90,7 @@ pub fn build(b: *Builder) !void { exe.install(); exe.setBuildMode(mode); exe.setTarget(target); - test_step.dependOn(&exe.step); + toolchain_step.dependOn(&exe.step); b.default_step.dependOn(&exe.step); exe.addBuildOption(bool, "skip_non_native", skip_non_native); @@ -195,7 +199,7 @@ pub fn build(b: *Builder) !void { exe.addBuildOption(bool, "enable_logging", enable_logging); exe.addBuildOption(bool, "enable_tracy", tracy != null); exe.addBuildOption(bool, "is_stage1", is_stage1); - exe.addBuildOption(bool, "omit_stage2", false); + exe.addBuildOption(bool, "omit_stage2", omit_stage2); if (tracy) |tracy_path| { const client_cpp = fs.path.join( b.allocator, @@ -218,7 +222,7 @@ pub fn build(b: *Builder) !void { test_stage2.addBuildOption(bool, "skip_non_native", skip_non_native); test_stage2.addBuildOption(bool, "is_stage1", is_stage1); - test_stage2.addBuildOption(bool, "omit_stage2", false); + test_stage2.addBuildOption(bool, "omit_stage2", omit_stage2); test_stage2.addBuildOption(bool, "have_llvm", enable_llvm); test_stage2.addBuildOption(bool, "enable_qemu", is_qemu_enabled); test_stage2.addBuildOption(bool, "enable_wine", is_wine_enabled); @@ -228,12 +232,16 @@ pub fn build(b: *Builder) !void { const test_stage2_step = b.step("test-stage2", "Run the stage2 compiler tests"); test_stage2_step.dependOn(&test_stage2.step); - test_step.dependOn(test_stage2_step); + if (!skip_stage2_tests) { + toolchain_step.dependOn(test_stage2_step); + } var chosen_modes: [4]builtin.Mode = undefined; var chosen_mode_index: usize = 0; - chosen_modes[chosen_mode_index] = builtin.Mode.Debug; - chosen_mode_index += 1; + if (!skip_debug) { + chosen_modes[chosen_mode_index] = builtin.Mode.Debug; + chosen_mode_index += 1; + } if (!skip_release_safe) { chosen_modes[chosen_mode_index] = builtin.Mode.ReleaseSafe; chosen_mode_index += 1; @@ -249,30 +257,37 @@ pub fn build(b: *Builder) !void { const modes = chosen_modes[0..chosen_mode_index]; // run stage1 `zig fmt` on this build.zig file just to make sure it works - test_step.dependOn(&fmt_build_zig.step); + toolchain_step.dependOn(&fmt_build_zig.step); const fmt_step = b.step("test-fmt", "Run zig fmt against build.zig to make sure it works"); fmt_step.dependOn(&fmt_build_zig.step); // TODO for the moment, skip wasm32-wasi until bugs are sorted out. - test_step.dependOn(tests.addPkgTests(b, test_filter, "test/stage1/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)); - - 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)); - - 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)); - - test_step.dependOn(tests.addCompareOutputTests(b, test_filter, modes)); - test_step.dependOn(tests.addStandaloneTests(b, test_filter, modes)); - test_step.dependOn(tests.addStackTraceTests(b, test_filter, modes)); - test_step.dependOn(tests.addCliTests(b, test_filter, modes)); - test_step.dependOn(tests.addAssembleAndLinkTests(b, test_filter, modes)); - test_step.dependOn(tests.addRuntimeSafetyTests(b, test_filter, modes)); - test_step.dependOn(tests.addTranslateCTests(b, test_filter)); - test_step.dependOn(tests.addRunTranslatedCTests(b, test_filter, target)); + toolchain_step.dependOn(tests.addPkgTests(b, test_filter, "test/stage1/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)); + + 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)); + 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)); + + toolchain_step.dependOn(tests.addCompareOutputTests(b, test_filter, modes)); + toolchain_step.dependOn(tests.addStandaloneTests(b, test_filter, modes)); + toolchain_step.dependOn(tests.addStackTraceTests(b, test_filter, modes)); + toolchain_step.dependOn(tests.addCliTests(b, test_filter, modes)); + toolchain_step.dependOn(tests.addAssembleAndLinkTests(b, test_filter, modes)); + toolchain_step.dependOn(tests.addRuntimeSafetyTests(b, test_filter, modes)); + toolchain_step.dependOn(tests.addTranslateCTests(b, test_filter)); + if (!skip_run_translated_c) { + toolchain_step.dependOn(tests.addRunTranslatedCTests(b, test_filter, target)); + } // tests for this feature are disabled until we have the self-hosted compiler available - // test_step.dependOn(tests.addGenHTests(b, test_filter)); + // toolchain_step.dependOn(tests.addGenHTests(b, test_filter)); if (!skip_compile_errors) { - test_step.dependOn(tests.addCompileErrorTests(b, test_filter, modes)); + toolchain_step.dependOn(tests.addCompileErrorTests(b, test_filter, modes)); } + + 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); + + const test_step = b.step("test", "Run all the tests"); + test_step.dependOn(toolchain_step); + test_step.dependOn(std_step); test_step.dependOn(docs_step); } @@ -739,80 +754,60 @@ const lld_libs = [_][]const u8{ }; // This list can be re-generated with `llvm-config --libfiles` and then // reformatting using your favorite text editor. Note we do not execute -// `llvm-config` here because we are cross compiling. +// `llvm-config` here because we are cross compiling. Also omit LLVMTableGen +// from these libs. const llvm_libs = [_][]const u8{ - "LLVMXRay", "LLVMWindowsManifest", - "LLVMSymbolize", - "LLVMDebugInfoPDB", - "LLVMOrcJIT", - "LLVMOrcError", - "LLVMJITLink", - "LLVMObjectYAML", - "LLVMMCA", - "LLVMLTO", - "LLVMPasses", - "LLVMCoroutines", - "LLVMObjCARCOpts", - "LLVMExtensions", - "LLVMLineEditor", + "LLVMXRay", "LLVMLibDriver", - "LLVMInterpreter", - "LLVMFuzzMutate", - "LLVMMCJIT", - "LLVMExecutionEngine", - "LLVMRuntimeDyld", - "LLVMDWARFLinker", "LLVMDlltoolDriver", - "LLVMOption", - "LLVMDebugInfoGSYM", "LLVMCoverage", + "LLVMLineEditor", "LLVMXCoreDisassembler", "LLVMXCoreCodeGen", "LLVMXCoreDesc", "LLVMXCoreInfo", "LLVMX86Disassembler", - "LLVMX86CodeGen", "LLVMX86AsmParser", + "LLVMX86CodeGen", "LLVMX86Desc", "LLVMX86Info", "LLVMWebAssemblyDisassembler", + "LLVMWebAssemblyAsmParser", "LLVMWebAssemblyCodeGen", "LLVMWebAssemblyDesc", - "LLVMWebAssemblyAsmParser", "LLVMWebAssemblyInfo", "LLVMSystemZDisassembler", - "LLVMSystemZCodeGen", "LLVMSystemZAsmParser", + "LLVMSystemZCodeGen", "LLVMSystemZDesc", "LLVMSystemZInfo", "LLVMSparcDisassembler", - "LLVMSparcCodeGen", "LLVMSparcAsmParser", + "LLVMSparcCodeGen", "LLVMSparcDesc", "LLVMSparcInfo", "LLVMRISCVDisassembler", - "LLVMRISCVCodeGen", "LLVMRISCVAsmParser", + "LLVMRISCVCodeGen", "LLVMRISCVDesc", - "LLVMRISCVUtils", "LLVMRISCVInfo", "LLVMPowerPCDisassembler", - "LLVMPowerPCCodeGen", "LLVMPowerPCAsmParser", + "LLVMPowerPCCodeGen", "LLVMPowerPCDesc", "LLVMPowerPCInfo", "LLVMNVPTXCodeGen", "LLVMNVPTXDesc", "LLVMNVPTXInfo", "LLVMMSP430Disassembler", - "LLVMMSP430CodeGen", "LLVMMSP430AsmParser", + "LLVMMSP430CodeGen", "LLVMMSP430Desc", "LLVMMSP430Info", "LLVMMipsDisassembler", - "LLVMMipsCodeGen", "LLVMMipsAsmParser", + "LLVMMipsCodeGen", "LLVMMipsDesc", "LLVMMipsInfo", "LLVMLanaiDisassembler", @@ -826,44 +821,73 @@ const llvm_libs = [_][]const u8{ "LLVMHexagonDesc", "LLVMHexagonInfo", "LLVMBPFDisassembler", - "LLVMBPFCodeGen", "LLVMBPFAsmParser", + "LLVMBPFCodeGen", "LLVMBPFDesc", "LLVMBPFInfo", "LLVMAVRDisassembler", - "LLVMAVRCodeGen", "LLVMAVRAsmParser", + "LLVMAVRCodeGen", "LLVMAVRDesc", "LLVMAVRInfo", "LLVMARMDisassembler", - "LLVMARMCodeGen", "LLVMARMAsmParser", + "LLVMARMCodeGen", "LLVMARMDesc", "LLVMARMUtils", "LLVMARMInfo", "LLVMAMDGPUDisassembler", - "LLVMAMDGPUCodeGen", - "LLVMMIRParser", - "LLVMipo", - "LLVMInstrumentation", - "LLVMVectorize", - "LLVMLinker", - "LLVMIRReader", - "LLVMAsmParser", - "LLVMFrontendOpenMP", "LLVMAMDGPUAsmParser", + "LLVMAMDGPUCodeGen", "LLVMAMDGPUDesc", "LLVMAMDGPUUtils", "LLVMAMDGPUInfo", "LLVMAArch64Disassembler", - "LLVMMCDisassembler", + "LLVMAArch64AsmParser", "LLVMAArch64CodeGen", + "LLVMAArch64Desc", + "LLVMAArch64Utils", + "LLVMAArch64Info", + "LLVMOrcJIT", + "LLVMMCJIT", + "LLVMJITLink", + "LLVMOrcTargetProcess", + "LLVMOrcShared", + "LLVMInterpreter", + "LLVMExecutionEngine", + "LLVMRuntimeDyld", + "LLVMSymbolize", + "LLVMDebugInfoPDB", + "LLVMDebugInfoGSYM", + "LLVMOption", + "LLVMObjectYAML", + "LLVMMCA", + "LLVMMCDisassembler", + "LLVMLTO", + "LLVMPasses", "LLVMCFGuard", + "LLVMCoroutines", + "LLVMObjCARCOpts", + "LLVMHelloNew", + "LLVMipo", + "LLVMVectorize", + "LLVMLinker", + "LLVMInstrumentation", + "LLVMFrontendOpenMP", + "LLVMFrontendOpenACC", + "LLVMExtensions", + "LLVMDWARFLinker", "LLVMGlobalISel", - "LLVMSelectionDAG", + "LLVMMIRParser", "LLVMAsmPrinter", "LLVMDebugInfoDWARF", + "LLVMSelectionDAG", "LLVMCodeGen", + "LLVMIRReader", + "LLVMAsmParser", + "LLVMInterfaceStub", + "LLVMFileCheck", + "LLVMFuzzMutate", "LLVMTarget", "LLVMScalarOpts", "LLVMInstCombine", @@ -874,19 +898,15 @@ const llvm_libs = [_][]const u8{ "LLVMProfileData", "LLVMObject", "LLVMTextAPI", - "LLVMBitReader", - "LLVMCore", - "LLVMRemarks", - "LLVMBitstreamReader", - "LLVMAArch64AsmParser", "LLVMMCParser", - "LLVMAArch64Desc", "LLVMMC", "LLVMDebugInfoCodeView", "LLVMDebugInfoMSF", + "LLVMBitReader", + "LLVMCore", + "LLVMRemarks", + "LLVMBitstreamReader", "LLVMBinaryFormat", - "LLVMAArch64Utils", - "LLVMAArch64Info", "LLVMSupport", "LLVMDemangle", }; diff --git a/zig/ci/azure/linux_script b/zig/ci/azure/linux_script index e96a16b41b..912a2518bb 100755 --- a/zig/ci/azure/linux_script +++ b/zig/ci/azure/linux_script @@ -9,7 +9,7 @@ sudo apt-get install -y cmake s3cmd tidy ZIGDIR="$(pwd)" ARCH="$(uname -m)" TARGET="$ARCH-linux-musl" -CACHE_BASENAME="zig+llvm+lld+clang-$TARGET-0.8.0-dev.859+f1ef0a80f" +CACHE_BASENAME="zig+llvm+lld+clang-$TARGET-0.8.0-dev.1939+5a3ea9bec" PREFIX="$HOME/$CACHE_BASENAME" MCPU="baseline" JOBS="-j$(nproc)" @@ -65,7 +65,9 @@ make $JOBS install cmake .. -DZIG_EXECUTABLE="$(pwd)/release/bin/zig" make $JOBS install -release/bin/zig build test -Denable-qemu -Denable-wasmtime +for step in test-toolchain test-std docs; do + release/bin/zig build $step -Denable-qemu -Denable-wasmtime +done # Look for HTML errors. tidy -qe ../zig-cache/langref.html diff --git a/zig/ci/azure/macos_arm64_script b/zig/ci/azure/macos_arm64_script index e7aa45b281..54d0380fa4 100755 --- a/zig/ci/azure/macos_arm64_script +++ b/zig/ci/azure/macos_arm64_script @@ -8,8 +8,8 @@ brew update && brew install s3cmd ninja gnu-tar ZIGDIR="$(pwd)" ARCH="aarch64" # {product}-{os}{sdk_version}-{arch}-{llvm_version}-{cmake_build_type} -CACHE_HOST_BASENAME="llvm-macos10.15-x86_64-11.0.1-release" -CACHE_ARM64_BASENAME="llvm-macos11.0-arm64-11.0.1-release" +CACHE_HOST_BASENAME="ci-llvm-macos10.15-x86_64-12.0.0.1-release" +CACHE_ARM64_BASENAME="ci-llvm-macos11.0-arm64-12.0.0.1-release" PREFIX_HOST="$HOME/$CACHE_HOST_BASENAME" PREFIX_ARM64="$HOME/$CACHE_ARM64_BASENAME" JOBS="-j2" diff --git a/zig/ci/azure/macos_script b/zig/ci/azure/macos_script index d47575acc0..d6d32612cc 100755 --- a/zig/ci/azure/macos_script +++ b/zig/ci/azure/macos_script @@ -7,7 +7,7 @@ brew update && brew install s3cmd ZIGDIR="$(pwd)" ARCH="x86_64" -CACHE_BASENAME="zig+llvm+lld+clang-$ARCH-macos-gnu-0.6.0+1c9ef63a" +CACHE_BASENAME="zig+llvm+lld+clang-$ARCH-macos-gnu-0.8.0-dev.1939+5a3ea9bec" PREFIX="$HOME/$CACHE_BASENAME" JOBS="-j2" @@ -18,7 +18,7 @@ tar xf "$CACHE_BASENAME.tar.xz" ZIG="$PREFIX/bin/zig" NATIVE_LIBC_TXT="$HOME/native_libc.txt" -$ZIG libc > "$NATIVE_LIBC_TXT" +$ZIG libc >"$NATIVE_LIBC_TXT" export ZIG_LIBC="$NATIVE_LIBC_TXT" export CC="$ZIG cc" export CXX="$ZIG c++" @@ -52,10 +52,12 @@ make $JOBS install # Here we rebuild zig but this time using the Zig binary we just now produced to # build zig1.o rather than relying on the one built with stage0. See # https://github.com/ziglang/zig/issues/6830 for more details. -cmake .. -DZIG_EXECUTABLE="$(pwd)/release/bin/zig" +cmake .. -DZIG_EXECUTABLE="$(pwd)/release/bin/zig" -DZIG_TARGET_MCPU="x86_64_v2" make $JOBS install -release/bin/zig build test +for step in test-toolchain test-std docs; do + release/bin/zig build $step +done if [ "${BUILD_REASON}" != "PullRequest" ]; then mv ../LICENSE release/ diff --git a/zig/ci/azure/windows_msvc_install b/zig/ci/azure/windows_msvc_install index 7df1aa6461..bdc4bd0bf1 100644 --- a/zig/ci/azure/windows_msvc_install +++ b/zig/ci/azure/windows_msvc_install @@ -7,5 +7,5 @@ pacman -Suy --needed --noconfirm pacman -S --needed --noconfirm wget p7zip python3-pip tar xz pip install s3cmd -wget -nv "https://ziglang.org/deps/llvm%2bclang%2blld-11.0.0-x86_64-windows-msvc-release-mt.tar.xz" -tar xf llvm+clang+lld-11.0.0-x86_64-windows-msvc-release-mt.tar.xz +wget -nv "https://ziglang.org/deps/llvm%2bclang%2blld-12.0.0-x86_64-windows-msvc-release-mt.tar.xz" +tar xf llvm+clang+lld-12.0.0-x86_64-windows-msvc-release-mt.tar.xz diff --git a/zig/ci/azure/windows_msvc_script.bat b/zig/ci/azure/windows_msvc_script.bat index 9d28eccd0b..fc17c80ea2 100644 --- a/zig/ci/azure/windows_msvc_script.bat +++ b/zig/ci/azure/windows_msvc_script.bat @@ -11,7 +11,7 @@ SET "MSYSTEM=%PREVMSYSTEM%" SET "ZIGBUILDDIR=%SRCROOT%\build" SET "ZIGINSTALLDIR=%ZIGBUILDDIR%\dist" -SET "ZIGPREFIXPATH=%SRCROOT%\llvm+clang+lld-11.0.0-x86_64-windows-msvc-release-mt" +SET "ZIGPREFIXPATH=%SRCROOT%\llvm+clang+lld-12.0.0-x86_64-windows-msvc-release-mt" call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 @@ -26,20 +26,8 @@ cd %ZIGBUILDDIR% 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 msbuild /maxcpucount /p:Configuration=Release INSTALL.vcxproj || exit /b -"%ZIGINSTALLDIR%\bin\zig.exe" build test-behavior -Dskip-non-native || exit /b -REM Disabled to prevent OOM -REM "%ZIGINSTALLDIR%\bin\zig.exe" build test-stage2 -Dskip-non-native || exit /b -"%ZIGINSTALLDIR%\bin\zig.exe" build test-fmt -Dskip-non-native || exit /b +"%ZIGINSTALLDIR%\bin\zig.exe" build test-toolchain -Dskip-non-native -Dskip-stage2-tests || exit /b "%ZIGINSTALLDIR%\bin\zig.exe" build test-std -Dskip-non-native || exit /b -"%ZIGINSTALLDIR%\bin\zig.exe" build test-compiler-rt -Dskip-non-native || exit /b -"%ZIGINSTALLDIR%\bin\zig.exe" build test-compare-output -Dskip-non-native || exit /b -"%ZIGINSTALLDIR%\bin\zig.exe" build test-standalone -Dskip-non-native || exit /b -"%ZIGINSTALLDIR%\bin\zig.exe" build test-stack-traces -Dskip-non-native || exit /b -"%ZIGINSTALLDIR%\bin\zig.exe" build test-cli -Dskip-non-native || exit /b -"%ZIGINSTALLDIR%\bin\zig.exe" build test-asm-link -Dskip-non-native || exit /b -"%ZIGINSTALLDIR%\bin\zig.exe" build test-runtime-safety -Dskip-non-native || exit /b -"%ZIGINSTALLDIR%\bin\zig.exe" build test-translate-c -Dskip-non-native || exit /b -"%ZIGINSTALLDIR%\bin\zig.exe" build test-run-translated-c -Dskip-non-native || exit /b "%ZIGINSTALLDIR%\bin\zig.exe" build docs || exit /b set "PATH=%CD:~0,2%\msys64\usr\bin;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem" diff --git a/zig/ci/drone/drone.yml b/zig/ci/drone/drone.yml index 02df735b6b..f0c4ab66d4 100644 --- a/zig/ci/drone/drone.yml +++ b/zig/ci/drone/drone.yml @@ -6,8 +6,39 @@ platform: arch: arm64 steps: -- name: build-and-test - image: ziglang/static-base:llvm11-aarch64-1 +- name: build + image: ziglang/static-base:llvm12-aarch64-1 + commands: + - ./ci/drone/linux_script_build + +- name: test-1 + depends_on: + - build + image: ziglang/static-base:llvm12-aarch64-1 + commands: + - ./ci/drone/linux_script_test 1 + +- name: test-2 + depends_on: + - build + image: ziglang/static-base:llvm12-aarch64-1 + commands: + - ./ci/drone/linux_script_test 2 + +- name: test-3 + depends_on: + - build + image: ziglang/static-base:llvm12-aarch64-1 + commands: + - ./ci/drone/linux_script_test 3 + +- name: finalize + depends_on: + - build + - test-1 + - test-2 + - test-3 + image: ziglang/static-base:llvm12-aarch64-1 environment: SRHT_OAUTH_TOKEN: from_secret: SRHT_OAUTH_TOKEN @@ -16,4 +47,4 @@ steps: AWS_SECRET_ACCESS_KEY: from_secret: AWS_SECRET_ACCESS_KEY commands: - - ./ci/drone/linux_script + - ./ci/drone/linux_script_finalize diff --git a/zig/ci/drone/linux_script b/zig/ci/drone/linux_script deleted file mode 100755 index dbe13f6f19..0000000000 --- a/zig/ci/drone/linux_script +++ /dev/null @@ -1,60 +0,0 @@ -#!/bin/sh - -set -x -set -e - -TRIPLEARCH="$(uname -m)" -BUILDDIR="$(pwd)" -DISTDIR="$(pwd)/dist" - -apk update -apk add py3-pip xz perl-utils jq curl samurai -pip3 install s3cmd - -# Make the `zig version` number consistent. -# This will affect the cmake command below. -git config core.abbrev 9 -git fetch --unshallow || true -git fetch --tags - -mkdir build -cd build -cmake .. -DCMAKE_BUILD_TYPE=Release "-DCMAKE_INSTALL_PREFIX=$DISTDIR" -DZIG_STATIC=ON -DCMAKE_PREFIX_PATH=/deps/local -GNinja - -samu install -./zig build test -Dskip-release -Dskip-non-native -Dskip-compile-errors - -if [ -z "$DRONE_PULL_REQUEST" ]; then - mv ../LICENSE "$DISTDIR/" - mv ../zig-cache/langref.html "$DISTDIR/" - mv "$DISTDIR/bin/zig" "$DISTDIR/" - rmdir "$DISTDIR/bin" - - GITBRANCH="$DRONE_BRANCH" - VERSION="$("$DISTDIR/zig" version)" - DIRNAME="zig-linux-$TRIPLEARCH-$VERSION" - TARBALL="$DIRNAME.tar.xz" - mv "$DISTDIR" "$DIRNAME" - tar cfJ "$TARBALL" "$DIRNAME" - - s3cmd put -P --add-header="cache-control: public, max-age=31536000, immutable" "$TARBALL" s3://ziglang.org/builds/ - - SHASUM=$(shasum -a 256 $TARBALL | cut '-d ' -f1) - BYTESIZE=$(wc -c < $TARBALL) - - JSONFILE="$TRIPLEARCH-linux-$GITBRANCH.json" - touch $JSONFILE - echo "{\"tarball\": \"$TARBALL\"," >>$JSONFILE - echo "\"shasum\": \"$SHASUM\"," >>$JSONFILE - echo "\"size\": \"$BYTESIZE\"}" >>$JSONFILE - - s3cmd put -P --add-header="Cache-Control: max-age=0, must-revalidate" "$JSONFILE" "s3://ziglang.org/builds/$JSONFILE" - s3cmd put -P "$JSONFILE" "s3://ziglang.org/builds/$TRIPLEARCH-linux-$VERSION.json" - if [ "$GITBRANCH" = "master" ]; then - # avoid leaking oauth token - set +x - - cd "$BUILDDIR" - ./ci/srht/on_master_success "$VERSION" "$SRHT_OAUTH_TOKEN" - fi -fi diff --git a/zig/ci/drone/linux_script_base b/zig/ci/drone/linux_script_base new file mode 100755 index 0000000000..2788eb2df6 --- /dev/null +++ b/zig/ci/drone/linux_script_base @@ -0,0 +1,22 @@ +#!/bin/sh + +# https://docs.drone.io/pipeline/docker/syntax/workspace/ +# +# Drone automatically creates a temporary volume, known as your workspace, +# where it clones your repository. The workspace is the current working +# directory for each step in your pipeline. +# +# Because the workspace is a volume, filesystem changes are persisted between +# pipeline steps. In other words, individual steps can communicate and share +# state using the filesystem. +# +# Workspace volumes are ephemeral. They are created when the pipeline starts +# and destroyed after the pipeline completes. + +set -x +set -e + +TRIPLEARCH="$(uname -m)" +DISTDIR="$DRONE_WORKSPACE/dist" + +export ZIG_GLOBAL_CACHE_DIR="$DRONE_WORKSPACE/zig-cache" diff --git a/zig/ci/drone/linux_script_build b/zig/ci/drone/linux_script_build new file mode 100755 index 0000000000..3aedafbb89 --- /dev/null +++ b/zig/ci/drone/linux_script_build @@ -0,0 +1,18 @@ +#!/bin/sh + +. ./ci/drone/linux_script_base + +apk update +apk add samurai + +# Make the `zig version` number consistent. +# This will affect the cmake command below. +git config core.abbrev 9 +git fetch --unshallow || true +git fetch --tags + +mkdir build +cd build +cmake .. -DCMAKE_BUILD_TYPE=Release "-DCMAKE_INSTALL_PREFIX=$DISTDIR" -DZIG_STATIC=ON -DCMAKE_PREFIX_PATH=/deps/local -GNinja + +samu install diff --git a/zig/ci/drone/linux_script_finalize b/zig/ci/drone/linux_script_finalize new file mode 100755 index 0000000000..da754a6b54 --- /dev/null +++ b/zig/ci/drone/linux_script_finalize @@ -0,0 +1,46 @@ +#!/bin/sh + +. ./ci/drone/linux_script_base + +if [ -n "$DRONE_PULL_REQUEST" ]; then + exit 0 +fi + +apk update +apk add py3-pip xz perl-utils jq curl samurai +pip3 install s3cmd + +cd build + +mv ../LICENSE "$DISTDIR/" +# docs are disabled due to: https://github.com/ziglang/zig/issues/8597 +#mv ../zig-cache/langref.html "$DISTDIR/" +mv "$DISTDIR/bin/zig" "$DISTDIR/" +rmdir "$DISTDIR/bin" + +GITBRANCH="$DRONE_BRANCH" +VERSION="$("$DISTDIR/zig" version)" +DIRNAME="zig-linux-$TRIPLEARCH-$VERSION" +TARBALL="$DIRNAME.tar.xz" +mv "$DISTDIR" "$DIRNAME" +tar cfJ "$TARBALL" "$DIRNAME" + +s3cmd put -P --add-header="cache-control: public, max-age=31536000, immutable" "$TARBALL" s3://ziglang.org/builds/ + +SHASUM=$(shasum -a 256 $TARBALL | cut '-d ' -f1) +BYTESIZE=$(wc -c < $TARBALL) + +JSONFILE="tarball.json" +touch $JSONFILE +echo "{\"tarball\": \"$TARBALL\"," >>$JSONFILE +echo "\"shasum\": \"$SHASUM\"," >>$JSONFILE +echo "\"size\": \"$BYTESIZE\"}" >>$JSONFILE + +s3cmd put -P "$JSONFILE" "s3://ziglang.org/builds/$TRIPLEARCH-linux-$VERSION.json" +if [ "$GITBRANCH" = "master" ]; then + # avoid leaking oauth token + set +x + + cd "$DRONE_WORKSPACE" + ./ci/srht/on_master_success "$VERSION" "$SRHT_OAUTH_TOKEN" +fi diff --git a/zig/ci/drone/linux_script_test b/zig/ci/drone/linux_script_test new file mode 100755 index 0000000000..a8e497a619 --- /dev/null +++ b/zig/ci/drone/linux_script_test @@ -0,0 +1,46 @@ +#!/bin/sh + +. ./ci/drone/linux_script_base + +# only release-fast builds of test suite due to: https://github.com/ziglang/zig/issues/8597 +# +# Some test suite components will be missing because they do not support +# forcing -OReleaseFast +# +# see `zig build --help` for the full list of test-* components +case "$1" in + 1) + steps="\ + test-stage2 \ + test-fmt \ + test-behavior" + ;; + 2) + steps="test-std" + ;; + 3) + steps="\ + test-compiler-rt \ + test-minilibc \ + test-compare-output \ + test-translate-c \ + test-run-translated-c" + ;; + '') + echo "error: expecting test group argument" + exit 1 + ;; + *) + echo "error: unknown test group: $1" + exit 1 + ;; +esac + +# only release-fast builds of test suite due to: https://github.com/ziglang/zig/issues/8597 +./build/zig build \ + -Drelease \ + -Dskip-debug \ + -Dskip-release-small \ + -Dskip-release-safe \ + -Dskip-non-native \ + $steps diff --git a/zig/ci/srht/freebsd_script b/zig/ci/srht/freebsd_script index 337d715b7c..4999ad7634 100755 --- a/zig/ci/srht/freebsd_script +++ b/zig/ci/srht/freebsd_script @@ -4,12 +4,11 @@ set -x set -e sudo pkg update -fq -sudo pkg install -y cmake py37-s3cmd wget curl jq +sudo pkg install -y cmake py38-s3cmd wget curl jq samurai ZIGDIR="$(pwd)" -CACHE_BASENAME="llvm+clang+lld-11.0.0-x86_64-freebsd-release" +CACHE_BASENAME="zig+llvm+lld+clang-x86_64-freebsd-gnu-0.8.0-dev.1939+5a3ea9bec" PREFIX="$HOME/$CACHE_BASENAME" -JOBS="-j$(sysctl -n hw.ncpu)" cd $HOME wget -nv "https://ziglang.org/deps/$CACHE_BASENAME.tar.xz" @@ -30,8 +29,14 @@ export TERM=dumb mkdir build cd build -cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH=$PREFIX "-DCMAKE_INSTALL_PREFIX=$(pwd)/release" -DZIG_STATIC=ON -make $JOBS install +cmake .. \ + -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_PREFIX_PATH=$PREFIX \ + "-DCMAKE_INSTALL_PREFIX=$(pwd)/release" \ + -DZIG_STATIC=ON \ + -DZIG_TARGET_TRIPLE=x86_64-freebsd-gnu \ + -GNinja +samu install # Here we skip some tests to save time. release/bin/zig build test -Dskip-compile-errors -Dskip-non-native diff --git a/zig/doc/langref.html.in b/zig/doc/langref.html.in index 63e4c946b6..744d33f85c 100644 --- a/zig/doc/langref.html.in +++ b/zig/doc/langref.html.in @@ -2861,6 +2861,37 @@ fn dump(args: anytype) void { expect(args.b); expect(args.s[0] == 'h'); expect(args.s[1] == 'i'); +} + {#code_end#} +
+ Anonymous structs can be created without specifying field names, and are referred to as "tuples". +
++ The fields are implicitly named using numbers starting from 0. Because their names are integers, + the {#syntax#}@"0"{#endsyntax#} syntax must be used to access them. Names inside {#syntax#}@""{#endsyntax#} are always recognised as identifiers. +
++ Like arrays, tuples have a .len field, can be indexed and work with the ++ and ** operators. They can also be iterated over with {#link|inline for#}. +
+ {#code_begin|test|tuple#} +const std = @import("std"); +const expect = std.testing.expect; + +test "tuple" { + const values = .{ + @as(u32, 1234), + @as(f64, 12.34), + true, + "hi", + } ++ .{false} ** 2; + expect(values[0] == 1234); + expect(values[4] == false); + inline for (values) |v, i| { + if (i != 2) continue; + expect(v); + } + expect(values.len == 6); + expect(values.@"3"[0] == 'h'); } {#code_end#} {#header_close#} @@ -6528,7 +6559,7 @@ test "suspend with no resume" { fn func() void { x += 1; - suspend; + suspend {} // This line is never reached because the suspend has no matching resume. x += 1; } @@ -6593,7 +6624,7 @@ fn testResumeFromSuspend(my_result: *i32) void { resume @frame(); } my_result.* += 1; - suspend; + suspend {} my_result.* += 1; } {#code_end#} @@ -6632,7 +6663,7 @@ fn amain() void { } fn func() void { - suspend; + suspend {} } {#code_end#}@@ -6934,7 +6965,7 @@ test "async fn pointer in a struct field" { fn func(y: *i32) void { defer y.* += 2; y.* += 1; - suspend; + suspend {} } {#code_end#} {#header_close#} @@ -7517,13 +7548,13 @@ test "main" { {#header_close#} {#header_open|@export#} -
{#syntax#}@export(target: anytype, comptime options: std.builtin.ExportOptions) void{#endsyntax#}
+ {#syntax#}@export(identifier, comptime options: std.builtin.ExportOptions) void{#endsyntax#}
Creates a symbol in the output object file.
This function can be called from a {#link|comptime#} block to conditionally export symbols. - When {#syntax#}target{#endsyntax#} is a function with the C calling convention and + When {#syntax#}identifier{#endsyntax#} is a function with the C calling convention and {#syntax#}options.linkage{#endsyntax#} is {#syntax#}Strong{#endsyntax#}, this is equivalent to the {#syntax#}export{#endsyntax#} keyword used on a function:
@@ -7550,6 +7581,14 @@ export fn @"A function name that is a complete sentence."() void {} {#see_also|Exporting a C Library#} {#header_close#} + {#header_open|@extern#} +{#syntax#}@extern(T: type, comptime options: std.builtin.ExternOptions) *T{#endsyntax#}
+ + Creates a reference to an external symbol in the output object file. +
+ {#see_also|@export#} + {#header_close#} + {#header_open|@fence#}{#syntax#}@fence(order: AtomicOrder){#endsyntax#}
@@ -7659,7 +7698,7 @@ test "heap allocated frame" { } fn func() void { - suspend; + suspend {} } {#code_end#} {#header_close#} @@ -10008,7 +10047,7 @@ pub fn build(b: *Builder) void { {#code_end#}
terminal
$ zig build
-$ ./zig-cache/bin/test
+$ ./zig-out/bin/test
all your base are belong to us
{#see_also|Targets|Zig Build System#}
{#header_close#}
diff --git a/zig/lib/std/Thread.zig b/zig/lib/std/Thread.zig
index 7e8a6226e6..a85219a458 100644
--- a/zig/lib/std/Thread.zig
+++ b/zig/lib/std/Thread.zig
@@ -68,11 +68,30 @@ else switch (std.Target.current.os.tag) {
};
/// Signals the processor that it is inside a busy-wait spin-loop ("spin lock").
-pub fn spinLoopHint() void {
+pub fn spinLoopHint() callconv(.Inline) void {
switch (std.Target.current.cpu.arch) {
- .i386, .x86_64 => asm volatile ("pause" ::: "memory"),
- .arm, .aarch64 => asm volatile ("yield" ::: "memory"),
- else => {},
+ .i386, .x86_64 => {
+ asm volatile ("pause" ::: "memory");
+ },
+ .arm, .armeb, .thumb, .thumbeb => {
+ // `yield` was introduced in v6k but are also available on v6m.
+ const can_yield = comptime std.Target.arm.featureSetHasAny(std.Target.current.cpu.features, .{ .has_v6k, .has_v6m });
+ if (can_yield) asm volatile ("yield" ::: "memory")
+ // Fallback.
+ else asm volatile ("" ::: "memory");
+ },
+ .aarch64, .aarch64_be, .aarch64_32 => {
+ asm volatile ("isb" ::: "memory");
+ },
+ .powerpc64, .powerpc64le => {
+ // No-op that serves as `yield` hint.
+ asm volatile ("or 27, 27, 27" ::: "memory");
+ },
+ else => {
+ // Do nothing but prevent the compiler from optimizing away the
+ // spinning loop.
+ asm volatile ("" ::: "memory");
+ },
}
}
@@ -199,7 +218,8 @@ pub fn spawn(comptime startFn: anytype, context: SpawnContextType(@TypeOf(startF
inner: Context,
};
fn threadMain(raw_arg: windows.LPVOID) callconv(.C) windows.DWORD {
- const arg = if (@sizeOf(Context) == 0) {} else @ptrCast(*Context, @alignCast(@alignOf(Context), raw_arg)).*;
+ const arg = if (@sizeOf(Context) == 0) undefined //
+ else @ptrCast(*Context, @alignCast(@alignOf(Context), raw_arg)).*;
switch (@typeInfo(@typeInfo(@TypeOf(startFn)).Fn.return_type.?)) {
.NoReturn => {
@@ -260,7 +280,8 @@ pub fn spawn(comptime startFn: anytype, context: SpawnContextType(@TypeOf(startF
const MainFuncs = struct {
fn linuxThreadMain(ctx_addr: usize) callconv(.C) u8 {
- const arg = if (@sizeOf(Context) == 0) {} else @intToPtr(*const Context, ctx_addr).*;
+ const arg = if (@sizeOf(Context) == 0) undefined //
+ else @intToPtr(*Context, ctx_addr).*;
switch (@typeInfo(@typeInfo(@TypeOf(startFn)).Fn.return_type.?)) {
.NoReturn => {
@@ -292,7 +313,8 @@ pub fn spawn(comptime startFn: anytype, context: SpawnContextType(@TypeOf(startF
}
}
fn posixThreadMain(ctx: ?*c_void) callconv(.C) ?*c_void {
- const arg = if (@sizeOf(Context) == 0) {} else @ptrCast(*Context, @alignCast(@alignOf(Context), ctx)).*;
+ const arg = if (@sizeOf(Context) == 0) undefined //
+ else @ptrCast(*Context, @alignCast(@alignOf(Context), ctx)).*;
switch (@typeInfo(@typeInfo(@TypeOf(startFn)).Fn.return_type.?)) {
.NoReturn => {
diff --git a/zig/lib/std/array_list.zig b/zig/lib/std/array_list.zig
index f30a86d8f7..7825d36ac3 100644
--- a/zig/lib/std/array_list.zig
+++ b/zig/lib/std/array_list.zig
@@ -50,7 +50,6 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
allocator: *Allocator,
pub const Slice = if (alignment) |a| ([]align(a) T) else []T;
- pub const SliceConst = if (alignment) |a| ([]align(a) const T) else []const T;
/// Deinitialize with `deinit` or use `toOwnedSlice`.
pub fn init(allocator: *Allocator) Self {
@@ -141,7 +140,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
/// Insert slice `items` at index `i` by moving `list[i .. list.len]` to make room.
/// This operation is O(N).
- pub fn insertSlice(self: *Self, i: usize, items: SliceConst) !void {
+ pub fn insertSlice(self: *Self, i: usize, items: []const T) !void {
try self.ensureCapacity(self.items.len + items.len);
self.items.len += items.len;
@@ -153,7 +152,7 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
/// Grows list if `len < new_items.len`.
/// Shrinks list if `len > new_items.len`.
/// Invalidates pointers if this ArrayList is resized.
- pub fn replaceRange(self: *Self, start: usize, len: usize, new_items: SliceConst) !void {
+ pub fn replaceRange(self: *Self, start: usize, len: usize, new_items: []const T) !void {
const after_range = start + len;
const range = self.items[start..after_range];
@@ -220,14 +219,14 @@ pub fn ArrayListAligned(comptime T: type, comptime alignment: ?u29) type {
/// Append the slice of items to the list. Allocates more
/// memory as necessary.
- pub fn appendSlice(self: *Self, items: SliceConst) !void {
+ pub fn appendSlice(self: *Self, items: []const T) !void {
try self.ensureCapacity(self.items.len + items.len);
self.appendSliceAssumeCapacity(items);
}
/// Append the slice of items to the list, asserting the capacity is already
/// enough to store the new items. **Does not** invalidate pointers.
- pub fn appendSliceAssumeCapacity(self: *Self, items: SliceConst) void {
+ pub fn appendSliceAssumeCapacity(self: *Self, items: []const T) void {
const oldlen = self.items.len;
const newlen = self.items.len + items.len;
self.items.len = newlen;
@@ -429,7 +428,6 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
capacity: usize = 0,
pub const Slice = if (alignment) |a| ([]align(a) T) else []T;
- pub const SliceConst = if (alignment) |a| ([]align(a) const T) else []const T;
/// Initialize with capacity to hold at least num elements.
/// Deinitialize with `deinit` or use `toOwnedSlice`.
@@ -483,7 +481,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
/// Insert slice `items` at index `i`. Moves `list[i .. list.len]` to
/// higher indicices make room.
/// This operation is O(N).
- pub fn insertSlice(self: *Self, allocator: *Allocator, i: usize, items: SliceConst) !void {
+ pub fn insertSlice(self: *Self, allocator: *Allocator, i: usize, items: []const T) !void {
try self.ensureCapacity(allocator, self.items.len + items.len);
self.items.len += items.len;
@@ -495,7 +493,7 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
/// Grows list if `len < new_items.len`.
/// Shrinks list if `len > new_items.len`
/// Invalidates pointers if this ArrayList is resized.
- pub fn replaceRange(self: *Self, allocator: *Allocator, start: usize, len: usize, new_items: SliceConst) !void {
+ pub fn replaceRange(self: *Self, allocator: *Allocator, start: usize, len: usize, new_items: []const T) !void {
var managed = self.toManaged(allocator);
try managed.replaceRange(start, len, new_items);
self.* = managed.toUnmanaged();
@@ -543,14 +541,14 @@ pub fn ArrayListAlignedUnmanaged(comptime T: type, comptime alignment: ?u29) typ
/// Append the slice of items to the list. Allocates more
/// memory as necessary.
- pub fn appendSlice(self: *Self, allocator: *Allocator, items: SliceConst) !void {
+ pub fn appendSlice(self: *Self, allocator: *Allocator, items: []const T) !void {
try self.ensureCapacity(allocator, self.items.len + items.len);
self.appendSliceAssumeCapacity(items);
}
/// Append the slice of items to the list, asserting the capacity is enough
/// to store the new items.
- pub fn appendSliceAssumeCapacity(self: *Self, items: SliceConst) void {
+ pub fn appendSliceAssumeCapacity(self: *Self, items: []const T) void {
const oldlen = self.items.len;
const newlen = self.items.len + items.len;
@@ -1128,15 +1126,31 @@ test "std.ArrayList/ArrayListUnmanaged: ArrayList(T) of struct T" {
}
}
-test "std.ArrayList(u8) implements writer" {
- var buffer = ArrayList(u8).init(std.testing.allocator);
- defer buffer.deinit();
+test "std.ArrayList(u8)/ArrayListAligned implements writer" {
+ const a = testing.allocator;
+
+ {
+ var buffer = ArrayList(u8).init(a);
+ defer buffer.deinit();
+
+ const x: i32 = 42;
+ const y: i32 = 1234;
+ try buffer.writer().print("x: {}\ny: {}\n", .{ x, y });
- const x: i32 = 42;
- const y: i32 = 1234;
- try buffer.writer().print("x: {}\ny: {}\n", .{ x, y });
+ testing.expectEqualSlices(u8, "x: 42\ny: 1234\n", buffer.items);
+ }
+ {
+ var list = ArrayListAligned(u8, 2).init(a);
+ defer list.deinit();
- testing.expectEqualSlices(u8, "x: 42\ny: 1234\n", buffer.items);
+ const writer = list.writer();
+ try writer.writeAll("a");
+ try writer.writeAll("bc");
+ try writer.writeAll("d");
+ try writer.writeAll("efg");
+
+ testing.expectEqualSlices(u8, list.items, "abcdefg");
+ }
}
test "std.ArrayList/ArrayListUnmanaged.shrink still sets length on error.OutOfMemory" {
@@ -1167,18 +1181,6 @@ test "std.ArrayList/ArrayListUnmanaged.shrink still sets length on error.OutOfMe
}
}
-test "std.ArrayList.writer" {
- var list = ArrayList(u8).init(std.testing.allocator);
- defer list.deinit();
-
- const writer = list.writer();
- try writer.writeAll("a");
- try writer.writeAll("bc");
- try writer.writeAll("d");
- try writer.writeAll("efg");
- testing.expectEqualSlices(u8, list.items, "abcdefg");
-}
-
test "std.ArrayList/ArrayListUnmanaged.addManyAsArray" {
const a = std.testing.allocator;
{
@@ -1226,3 +1228,27 @@ test "std.ArrayList/ArrayListUnmanaged.toOwnedSliceSentinel" {
testing.expectEqualStrings(result, mem.spanZ(result.ptr));
}
}
+
+test "ArrayListAligned/ArrayListAlignedUnmanaged accepts unaligned slices" {
+ const a = testing.allocator;
+ {
+ var list = std.ArrayListAligned(u8, 8).init(a);
+ defer list.deinit();
+
+ try list.appendSlice(&.{ 0, 1, 2, 3 });
+ try list.insertSlice(2, &.{ 4, 5, 6, 7 });
+ try list.replaceRange(1, 3, &.{ 8, 9 });
+
+ testing.expectEqualSlices(u8, list.items, &.{ 0, 8, 9, 6, 7, 2, 3 });
+ }
+ {
+ var list = std.ArrayListAlignedUnmanaged(u8, 8){};
+ defer list.deinit(a);
+
+ try list.appendSlice(a, &.{ 0, 1, 2, 3 });
+ try list.insertSlice(a, 2, &.{ 4, 5, 6, 7 });
+ try list.replaceRange(a, 1, 3, &.{ 8, 9 });
+
+ testing.expectEqualSlices(u8, list.items, &.{ 0, 8, 9, 6, 7, 2, 3 });
+ }
+}
diff --git a/zig/lib/std/atomic/bool.zig b/zig/lib/std/atomic/bool.zig
index c968b862b9..0cffb99d38 100644
--- a/zig/lib/std/atomic/bool.zig
+++ b/zig/lib/std/atomic/bool.zig
@@ -28,7 +28,7 @@ pub const Bool = extern struct {
return @atomicRmw(bool, &self.unprotected_value, .Xchg, operand, ordering);
}
- pub fn load(self: *Self, comptime ordering: std.builtin.AtomicOrder) bool {
+ pub fn load(self: *const Self, comptime ordering: std.builtin.AtomicOrder) bool {
switch (ordering) {
.Unordered, .Monotonic, .Acquire, .SeqCst => {},
else => @compileError("Invalid ordering '" ++ @tagName(ordering) ++ "' for a load operation"),
diff --git a/zig/lib/std/atomic/int.zig b/zig/lib/std/atomic/int.zig
index 1a3bead2df..2d1c5f80e9 100644
--- a/zig/lib/std/atomic/int.zig
+++ b/zig/lib/std/atomic/int.zig
@@ -31,7 +31,7 @@ pub fn Int(comptime T: type) type {
return @atomicRmw(T, &self.unprotected_value, op, operand, ordering);
}
- pub fn load(self: *Self, comptime ordering: builtin.AtomicOrder) T {
+ pub fn load(self: *const Self, comptime ordering: builtin.AtomicOrder) T {
switch (ordering) {
.Unordered, .Monotonic, .Acquire, .SeqCst => {},
else => @compileError("Invalid ordering '" ++ @tagName(ordering) ++ "' for a load operation"),
@@ -59,7 +59,7 @@ pub fn Int(comptime T: type) type {
return self.rmw(.Sub, 1, .SeqCst);
}
- pub fn get(self: *Self) T {
+ pub fn get(self: *const Self) T {
return self.load(.SeqCst);
}
diff --git a/zig/lib/std/build.zig b/zig/lib/std/build.zig
index a652de9c12..1811073279 100644
--- a/zig/lib/std/build.zig
+++ b/zig/lib/std/build.zig
@@ -195,7 +195,8 @@ pub const Builder = struct {
self.install_prefix = install_prefix orelse "/usr";
self.install_path = fs.path.join(self.allocator, &[_][]const u8{ dest_dir, self.install_prefix }) catch unreachable;
} else {
- self.install_prefix = install_prefix orelse self.cache_root;
+ self.install_prefix = install_prefix orelse
+ (fs.path.join(self.allocator, &[_][]const u8{ self.build_root, "zig-out" }) catch unreachable);
self.install_path = self.install_prefix;
}
self.lib_dir = fs.path.join(self.allocator, &[_][]const u8{ self.install_path, "lib" }) catch unreachable;
@@ -675,17 +676,19 @@ pub const Builder = struct {
/// Exposes standard `zig build` options for choosing a target.
pub fn standardTargetOptions(self: *Builder, args: StandardTargetOptionsArgs) CrossTarget {
- const triple = self.option(
+ const maybe_triple = self.option(
[]const u8,
"target",
"The CPU architecture, OS, and ABI to build for",
- ) orelse return args.default_target;
+ );
+ const mcpu = self.option([]const u8, "cpu", "Target CPU");
- // TODO add cpu and features as part of the target triple
+ const triple = maybe_triple orelse return args.default_target;
var diags: CrossTarget.ParseOptions.Diagnostics = .{};
const selected_target = CrossTarget.parse(.{
.arch_os_abi = triple,
+ .cpu_features = mcpu,
.diagnostics = &diags,
}) catch |err| switch (err) {
error.UnknownCpuModel => {
@@ -1384,6 +1387,8 @@ pub const LibExeObjStep = struct {
/// safely garbage-collected during the linking phase.
link_function_sections: bool = false,
+ linker_allow_shlib_undefined: ?bool = null,
+
/// Uses system Wine installation to run cross compiled Windows build artifacts.
enable_wine: bool = false,
@@ -2336,6 +2341,9 @@ pub const LibExeObjStep = struct {
if (self.link_function_sections) {
try zig_args.append("-ffunction-sections");
}
+ if (self.linker_allow_shlib_undefined) |x| {
+ try zig_args.append(if (x) "-fallow-shlib-undefined" else "-fno-allow-shlib-undefined");
+ }
if (self.single_threaded) {
try zig_args.append("--single-threaded");
}
diff --git a/zig/lib/std/build/run.zig b/zig/lib/std/build/run.zig
index ca39b0216e..1e16813cb8 100644
--- a/zig/lib/std/build/run.zig
+++ b/zig/lib/std/build/run.zig
@@ -191,6 +191,13 @@ pub const RunStep = struct {
child.stdout_behavior = stdIoActionToBehavior(self.stdout_action);
child.stderr_behavior = stdIoActionToBehavior(self.stderr_action);
+ if (self.builder.verbose) {
+ for (argv) |arg| {
+ warn("{s} ", .{arg});
+ }
+ warn("\n", .{});
+ }
+
child.spawn() catch |err| {
warn("Unable to spawn {s}: {s}\n", .{ argv[0], @errorName(err) });
return err;
diff --git a/zig/lib/std/builtin.zig b/zig/lib/std/builtin.zig
index 93de8ae3b9..53c27f0bf5 100644
--- a/zig/lib/std/builtin.zig
+++ b/zig/lib/std/builtin.zig
@@ -165,6 +165,7 @@ pub const CallingConvention = enum {
APCS,
AAPCS,
AAPCSVFP,
+ SysV,
};
/// This data structure is used by the Zig language code generation and
diff --git a/zig/lib/std/c.zig b/zig/lib/std/c.zig
index 01247ffc00..f66376f812 100644
--- a/zig/lib/std/c.zig
+++ b/zig/lib/std/c.zig
@@ -10,8 +10,6 @@ const page_size = std.mem.page_size;
pub const tokenizer = @import("c/tokenizer.zig");
pub const Token = tokenizer.Token;
pub const Tokenizer = tokenizer.Tokenizer;
-pub const parse = @import("c/parse.zig").parse;
-pub const ast = @import("c/ast.zig");
pub const builtins = @import("c/builtins.zig");
test {
diff --git a/zig/lib/std/c/ast.zig b/zig/lib/std/c/ast.zig
deleted file mode 100644
index 71455c0ea3..0000000000
--- a/zig/lib/std/c/ast.zig
+++ /dev/null
@@ -1,681 +0,0 @@
-// SPDX-License-Identifier: MIT
-// Copyright (c) 2015-2021 Zig Contributors
-// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
-// The MIT license requires this copyright notice to be included in all copies
-// and substantial portions of the software.
-const std = @import("std");
-const ArrayList = std.ArrayList;
-const Token = std.c.Token;
-const Source = std.c.tokenizer.Source;
-
-pub const TokenIndex = usize;
-
-pub const Tree = struct {
- tokens: []Token,
- sources: []Source,
- root_node: *Node.Root,
- arena_state: std.heap.ArenaAllocator.State,
- gpa: *mem.Allocator,
- msgs: []Msg,
-
- pub fn deinit(self: *Tree) void {
- self.arena_state.promote(self.gpa).deinit();
- }
-
- pub fn tokenSlice(tree: *Tree, token: TokenIndex) []const u8 {
- return tree.tokens.at(token).slice();
- }
-
- pub fn tokenEql(tree: *Tree, a: TokenIndex, b: TokenIndex) bool {
- const atok = tree.tokens.at(a);
- const btok = tree.tokens.at(b);
- return atok.eql(btok.*);
- }
-};
-
-pub const Msg = struct {
- kind: enum {
- Error,
- Warning,
- Note,
- },
- inner: Error,
-};
-
-pub const Error = union(enum) {
- InvalidToken: SingleTokenError("invalid token '{}'"),
- ExpectedToken: ExpectedToken,
- ExpectedExpr: SingleTokenError("expected expression, found '{}'"),
- ExpectedTypeName: SingleTokenError("expected type name, found '{}'"),
- ExpectedFnBody: SingleTokenError("expected function body, found '{}'"),
- ExpectedDeclarator: SingleTokenError("expected declarator, found '{}'"),
- ExpectedInitializer: SingleTokenError("expected initializer, found '{}'"),
- ExpectedEnumField: SingleTokenError("expected enum field, found '{}'"),
- ExpectedType: SingleTokenError("expected enum field, found '{}'"),
- InvalidTypeSpecifier: InvalidTypeSpecifier,
- InvalidStorageClass: SingleTokenError("invalid storage class, found '{}'"),
- InvalidDeclarator: SimpleError("invalid declarator"),
- DuplicateQualifier: SingleTokenError("duplicate type qualifier '{}'"),
- DuplicateSpecifier: SingleTokenError("duplicate declaration specifier '{}'"),
- MustUseKwToRefer: MustUseKwToRefer,
- FnSpecOnNonFn: SingleTokenError("function specifier '{}' on non function"),
- NothingDeclared: SimpleError("declaration doesn't declare anything"),
- QualifierIgnored: SingleTokenError("qualifier '{}' ignored"),
-
- pub fn render(self: *const Error, tree: *Tree, stream: anytype) !void {
- switch (self.*) {
- .InvalidToken => |*x| return x.render(tree, stream),
- .ExpectedToken => |*x| return x.render(tree, stream),
- .ExpectedExpr => |*x| return x.render(tree, stream),
- .ExpectedTypeName => |*x| return x.render(tree, stream),
- .ExpectedDeclarator => |*x| return x.render(tree, stream),
- .ExpectedFnBody => |*x| return x.render(tree, stream),
- .ExpectedInitializer => |*x| return x.render(tree, stream),
- .ExpectedEnumField => |*x| return x.render(tree, stream),
- .ExpectedType => |*x| return x.render(tree, stream),
- .InvalidTypeSpecifier => |*x| return x.render(tree, stream),
- .InvalidStorageClass => |*x| return x.render(tree, stream),
- .InvalidDeclarator => |*x| return x.render(tree, stream),
- .DuplicateQualifier => |*x| return x.render(tree, stream),
- .DuplicateSpecifier => |*x| return x.render(tree, stream),
- .MustUseKwToRefer => |*x| return x.render(tree, stream),
- .FnSpecOnNonFn => |*x| return x.render(tree, stream),
- .NothingDeclared => |*x| return x.render(tree, stream),
- .QualifierIgnored => |*x| return x.render(tree, stream),
- }
- }
-
- pub fn loc(self: *const Error) TokenIndex {
- switch (self.*) {
- .InvalidToken => |x| return x.token,
- .ExpectedToken => |x| return x.token,
- .ExpectedExpr => |x| return x.token,
- .ExpectedTypeName => |x| return x.token,
- .ExpectedDeclarator => |x| return x.token,
- .ExpectedFnBody => |x| return x.token,
- .ExpectedInitializer => |x| return x.token,
- .ExpectedEnumField => |x| return x.token,
- .ExpectedType => |*x| return x.token,
- .InvalidTypeSpecifier => |x| return x.token,
- .InvalidStorageClass => |x| return x.token,
- .InvalidDeclarator => |x| return x.token,
- .DuplicateQualifier => |x| return x.token,
- .DuplicateSpecifier => |x| return x.token,
- .MustUseKwToRefer => |*x| return x.name,
- .FnSpecOnNonFn => |*x| return x.name,
- .NothingDeclared => |*x| return x.name,
- .QualifierIgnored => |*x| return x.name,
- }
- }
-
- pub const ExpectedToken = struct {
- token: TokenIndex,
- expected_id: std.meta.Tag(Token.Id),
-
- pub fn render(self: *const ExpectedToken, tree: *Tree, stream: anytype) !void {
- const found_token = tree.tokens.at(self.token);
- if (found_token.id == .Invalid) {
- return stream.print("expected '{s}', found invalid bytes", .{self.expected_id.symbol()});
- } else {
- const token_name = found_token.id.symbol();
- return stream.print("expected '{s}', found '{s}'", .{ self.expected_id.symbol(), token_name });
- }
- }
- };
-
- pub const InvalidTypeSpecifier = struct {
- token: TokenIndex,
- type_spec: *Node.TypeSpec,
-
- pub fn render(self: *const ExpectedToken, tree: *Tree, stream: anytype) !void {
- try stream.write("invalid type specifier '");
- try type_spec.spec.print(tree, stream);
- const token_name = tree.tokens.at(self.token).id.symbol();
- return stream.print("{s}'", .{token_name});
- }
- };
-
- pub const MustUseKwToRefer = struct {
- kw: TokenIndex,
- name: TokenIndex,
-
- pub fn render(self: *const ExpectedToken, tree: *Tree, stream: anytype) !void {
- return stream.print("must use '{s}' tag to refer to type '{s}'", .{ tree.slice(kw), tree.slice(name) });
- }
- };
-
- fn SingleTokenError(comptime msg: []const u8) type {
- return struct {
- token: TokenIndex,
-
- pub fn render(self: *const @This(), tree: *Tree, stream: anytype) !void {
- const actual_token = tree.tokens.at(self.token);
- return stream.print(msg, .{actual_token.id.symbol()});
- }
- };
- }
-
- fn SimpleError(comptime msg: []const u8) type {
- return struct {
- const ThisError = @This();
-
- token: TokenIndex,
-
- pub fn render(self: *const ThisError, tokens: *Tree.TokenList, stream: anytype) !void {
- return stream.write(msg);
- }
- };
- }
-};
-
-pub const Type = struct {
- pub const TypeList = ArrayList(*Type);
-
- @"const": bool = false,
- atomic: bool = false,
- @"volatile": bool = false,
- restrict: bool = false,
-
- id: union(enum) {
- Int: struct {
- id: Id,
- is_signed: bool,
-
- pub const Id = enum {
- Char,
- Short,
- Int,
- Long,
- LongLong,
- };
- },
- Float: struct {
- id: Id,
-
- pub const Id = enum {
- Float,
- Double,
- LongDouble,
- };
- },
- Pointer: *Type,
- Function: struct {
- return_type: *Type,
- param_types: TypeList,
- },
- Typedef: *Type,
- Record: *Node.RecordType,
- Enum: *Node.EnumType,
-
- /// Special case for macro parameters that can be any type.
- /// Only present if `retain_macros == true`.
- Macro,
- },
-};
-
-pub const Node = struct {
- id: Id,
-
- pub const Id = enum {
- Root,
- EnumField,
- RecordField,
- RecordDeclarator,
- JumpStmt,
- ExprStmt,
- LabeledStmt,
- CompoundStmt,
- IfStmt,
- SwitchStmt,
- WhileStmt,
- DoStmt,
- ForStmt,
- StaticAssert,
- Declarator,
- Pointer,
- FnDecl,
- Typedef,
- VarDecl,
- };
-
- pub const Root = struct {
- base: Node = Node{ .id = .Root },
- decls: DeclList,
- eof: TokenIndex,
-
- pub const DeclList = ArrayList(*Node);
- };
-
- pub const DeclSpec = struct {
- storage_class: union(enum) {
- Auto: TokenIndex,
- Extern: TokenIndex,
- Register: TokenIndex,
- Static: TokenIndex,
- Typedef: TokenIndex,
- None,
- } = .None,
- thread_local: ?TokenIndex = null,
- type_spec: TypeSpec = TypeSpec{},
- fn_spec: union(enum) {
- Inline: TokenIndex,
- Noreturn: TokenIndex,
- None,
- } = .None,
- align_spec: ?struct {
- alignas: TokenIndex,
- expr: *Node,
- rparen: TokenIndex,
- } = null,
- };
-
- pub const TypeSpec = struct {
- qual: TypeQual = TypeQual{},
- spec: union(enum) {
- /// error or default to int
- None,
- Void: TokenIndex,
- Char: struct {
- sign: ?TokenIndex = null,
- char: TokenIndex,
- },
- Short: struct {
- sign: ?TokenIndex = null,
- short: TokenIndex = null,
- int: ?TokenIndex = null,
- },
- Int: struct {
- sign: ?TokenIndex = null,
- int: ?TokenIndex = null,
- },
- Long: struct {
- sign: ?TokenIndex = null,
- long: TokenIndex,
- longlong: ?TokenIndex = null,
- int: ?TokenIndex = null,
- },
- Float: struct {
- float: TokenIndex,
- complex: ?TokenIndex = null,
- },
- Double: struct {
- long: ?TokenIndex = null,
- double: ?TokenIndex,
- complex: ?TokenIndex = null,
- },
- Bool: TokenIndex,
- Atomic: struct {
- atomic: TokenIndex,
- typename: *Node,
- rparen: TokenIndex,
- },
- Enum: *EnumType,
- Record: *RecordType,
- Typedef: struct {
- sym: TokenIndex,
- sym_type: *Type,
- },
-
- pub fn print(self: *@This(), self: *const @This(), tree: *Tree, stream: anytype) !void {
- switch (self.spec) {
- .None => unreachable,
- .Void => |index| try stream.write(tree.slice(index)),
- .Char => |char| {
- if (char.sign) |s| {
- try stream.write(tree.slice(s));
- try stream.writeByte(' ');
- }
- try stream.write(tree.slice(char.char));
- },
- .Short => |short| {
- if (short.sign) |s| {
- try stream.write(tree.slice(s));
- try stream.writeByte(' ');
- }
- try stream.write(tree.slice(short.short));
- if (short.int) |i| {
- try stream.writeByte(' ');
- try stream.write(tree.slice(i));
- }
- },
- .Int => |int| {
- if (int.sign) |s| {
- try stream.write(tree.slice(s));
- try stream.writeByte(' ');
- }
- if (int.int) |i| {
- try stream.writeByte(' ');
- try stream.write(tree.slice(i));
- }
- },
- .Long => |long| {
- if (long.sign) |s| {
- try stream.write(tree.slice(s));
- try stream.writeByte(' ');
- }
- try stream.write(tree.slice(long.long));
- if (long.longlong) |l| {
- try stream.writeByte(' ');
- try stream.write(tree.slice(l));
- }
- if (long.int) |i| {
- try stream.writeByte(' ');
- try stream.write(tree.slice(i));
- }
- },
- .Float => |float| {
- try stream.write(tree.slice(float.float));
- if (float.complex) |c| {
- try stream.writeByte(' ');
- try stream.write(tree.slice(c));
- }
- },
- .Double => |double| {
- if (double.long) |l| {
- try stream.write(tree.slice(l));
- try stream.writeByte(' ');
- }
- try stream.write(tree.slice(double.double));
- if (double.complex) |c| {
- try stream.writeByte(' ');
- try stream.write(tree.slice(c));
- }
- },
- .Bool => |index| try stream.write(tree.slice(index)),
- .Typedef => |typedef| try stream.write(tree.slice(typedef.sym)),
- else => try stream.print("TODO print {}", self.spec),
- }
- }
- } = .None,
- };
-
- pub const EnumType = struct {
- tok: TokenIndex,
- name: ?TokenIndex,
- body: ?struct {
- lbrace: TokenIndex,
-
- /// always EnumField
- fields: FieldList,
- rbrace: TokenIndex,
- },
-
- pub const FieldList = Root.DeclList;
- };
-
- pub const EnumField = struct {
- base: Node = Node{ .id = .EnumField },
- name: TokenIndex,
- value: ?*Node,
- };
-
- pub const RecordType = struct {
- tok: TokenIndex,
- kind: enum {
- Struct,
- Union,
- },
- name: ?TokenIndex,
- body: ?struct {
- lbrace: TokenIndex,
-
- /// RecordField or StaticAssert
- fields: FieldList,
- rbrace: TokenIndex,
- },
-
- pub const FieldList = Root.DeclList;
- };
-
- pub const RecordField = struct {
- base: Node = Node{ .id = .RecordField },
- type_spec: TypeSpec,
- declarators: DeclaratorList,
- semicolon: TokenIndex,
-
- pub const DeclaratorList = Root.DeclList;
- };
-
- pub const RecordDeclarator = struct {
- base: Node = Node{ .id = .RecordDeclarator },
- declarator: ?*Declarator,
- bit_field_expr: ?*Expr,
- };
-
- pub const TypeQual = struct {
- @"const": ?TokenIndex = null,
- atomic: ?TokenIndex = null,
- @"volatile": ?TokenIndex = null,
- restrict: ?TokenIndex = null,
- };
-
- pub const JumpStmt = struct {
- base: Node = Node{ .id = .JumpStmt },
- ltoken: TokenIndex,
- kind: union(enum) {
- Break,
- Continue,
- Return: ?*Node,
- Goto: TokenIndex,
- },
- semicolon: TokenIndex,
- };
-
- pub const ExprStmt = struct {
- base: Node = Node{ .id = .ExprStmt },
- expr: ?*Expr,
- semicolon: TokenIndex,
- };
-
- pub const LabeledStmt = struct {
- base: Node = Node{ .id = .LabeledStmt },
- kind: union(enum) {
- Label: TokenIndex,
- Case: TokenIndex,
- Default: TokenIndex,
- },
- stmt: *Node,
- };
-
- pub const CompoundStmt = struct {
- base: Node = Node{ .id = .CompoundStmt },
- lbrace: TokenIndex,
- statements: StmtList,
- rbrace: TokenIndex,
-
- pub const StmtList = Root.DeclList;
- };
-
- pub const IfStmt = struct {
- base: Node = Node{ .id = .IfStmt },
- @"if": TokenIndex,
- cond: *Node,
- body: *Node,
- @"else": ?struct {
- tok: TokenIndex,
- body: *Node,
- },
- };
-
- pub const SwitchStmt = struct {
- base: Node = Node{ .id = .SwitchStmt },
- @"switch": TokenIndex,
- expr: *Expr,
- rparen: TokenIndex,
- stmt: *Node,
- };
-
- pub const WhileStmt = struct {
- base: Node = Node{ .id = .WhileStmt },
- @"while": TokenIndex,
- cond: *Expr,
- rparen: TokenIndex,
- body: *Node,
- };
-
- pub const DoStmt = struct {
- base: Node = Node{ .id = .DoStmt },
- do: TokenIndex,
- body: *Node,
- @"while": TokenIndex,
- cond: *Expr,
- semicolon: TokenIndex,
- };
-
- pub const ForStmt = struct {
- base: Node = Node{ .id = .ForStmt },
- @"for": TokenIndex,
- init: ?*Node,
- cond: ?*Expr,
- semicolon: TokenIndex,
- incr: ?*Expr,
- rparen: TokenIndex,
- body: *Node,
- };
-
- pub const StaticAssert = struct {
- base: Node = Node{ .id = .StaticAssert },
- assert: TokenIndex,
- expr: *Node,
- semicolon: TokenIndex,
- };
-
- pub const Declarator = struct {
- base: Node = Node{ .id = .Declarator },
- pointer: ?*Pointer,
- prefix: union(enum) {
- None,
- Identifer: TokenIndex,
- Complex: struct {
- lparen: TokenIndex,
- inner: *Node,
- rparen: TokenIndex,
- },
- },
- suffix: union(enum) {
- None,
- Fn: struct {
- lparen: TokenIndex,
- params: Params,
- rparen: TokenIndex,
- },
- Array: Arrays,
- },
-
- pub const Arrays = ArrayList(*Array);
- pub const Params = ArrayList(*Param);
- };
-
- pub const Array = struct {
- lbracket: TokenIndex,
- inner: union(enum) {
- Inferred,
- Unspecified: TokenIndex,
- Variable: struct {
- asterisk: ?TokenIndex,
- static: ?TokenIndex,
- qual: TypeQual,
- expr: *Expr,
- },
- },
- rbracket: TokenIndex,
- };
-
- pub const Pointer = struct {
- base: Node = Node{ .id = .Pointer },
- asterisk: TokenIndex,
- qual: TypeQual,
- pointer: ?*Pointer,
- };
-
- pub const Param = struct {
- kind: union(enum) {
- Variable,
- Old: TokenIndex,
- Normal: struct {
- decl_spec: *DeclSpec,
- declarator: *Node,
- },
- },
- };
-
- pub const FnDecl = struct {
- base: Node = Node{ .id = .FnDecl },
- decl_spec: DeclSpec,
- declarator: *Declarator,
- old_decls: OldDeclList,
- body: ?*CompoundStmt,
-
- pub const OldDeclList = ArrayList(*Node);
- };
-
- pub const Typedef = struct {
- base: Node = Node{ .id = .Typedef },
- decl_spec: DeclSpec,
- declarators: DeclaratorList,
- semicolon: TokenIndex,
-
- pub const DeclaratorList = Root.DeclList;
- };
-
- pub const VarDecl = struct {
- base: Node = Node{ .id = .VarDecl },
- decl_spec: DeclSpec,
- initializers: Initializers,
- semicolon: TokenIndex,
-
- pub const Initializers = Root.DeclList;
- };
-
- pub const Initialized = struct {
- base: Node = Node{ .id = Initialized },
- declarator: *Declarator,
- eq: TokenIndex,
- init: Initializer,
- };
-
- pub const Initializer = union(enum) {
- list: struct {
- initializers: List,
- rbrace: TokenIndex,
- },
- expr: *Expr,
-
- pub const List = ArrayList(*Initializer);
- };
-
- pub const Macro = struct {
- base: Node = Node{ .id = Macro },
- kind: union(enum) {
- Undef: []const u8,
- Fn: struct {
- params: []const []const u8,
- expr: *Expr,
- },
- Expr: *Expr,
- },
- };
-};
-
-pub const Expr = struct {
- id: Id,
- ty: *Type,
- value: union(enum) {
- None,
- },
-
- pub const Id = enum {
- Infix,
- Literal,
- };
-
- pub const Infix = struct {
- base: Expr = Expr{ .id = .Infix },
- lhs: *Expr,
- op_token: TokenIndex,
- op: Op,
- rhs: *Expr,
-
- pub const Op = enum {};
- };
-};
diff --git a/zig/lib/std/c/haiku.zig b/zig/lib/std/c/haiku.zig
index e361a7520e..1aa3ac31e2 100644
--- a/zig/lib/std/c/haiku.zig
+++ b/zig/lib/std/c/haiku.zig
@@ -69,3 +69,51 @@ pub const pthread_rwlock_t = extern struct {
writer_count: i32 = 0,
waiters: [2]?*c_void = [_]?*c_void{ null, null },
};
+
+pub const EAI = extern enum(c_int) {
+ /// address family for hostname not supported
+ ADDRFAMILY = 1,
+
+ /// name could not be resolved at this time
+ AGAIN = 2,
+
+ /// flags parameter had an invalid value
+ BADFLAGS = 3,
+
+ /// non-recoverable failure in name resolution
+ FAIL = 4,
+
+ /// address family not recognized
+ FAMILY = 5,
+
+ /// memory allocation failure
+ MEMORY = 6,
+
+ /// no address associated with hostname
+ NODATA = 7,
+
+ /// name does not resolve
+ NONAME = 8,
+
+ /// service not recognized for socket type
+ SERVICE = 9,
+
+ /// intended socket type was not recognized
+ SOCKTYPE = 10,
+
+ /// system error returned in errno
+ SYSTEM = 11,
+
+ /// invalid value for hints
+ BADHINTS = 12,
+
+ /// resolved protocol is unknown
+ PROTOCOL = 13,
+
+ /// argument buffer overflow
+ OVERFLOW = 14,
+
+ _,
+};
+
+pub const EAI_MAX = 15;
diff --git a/zig/lib/std/c/parse.zig b/zig/lib/std/c/parse.zig
deleted file mode 100644
index 29d4ba2fe1..0000000000
--- a/zig/lib/std/c/parse.zig
+++ /dev/null
@@ -1,1434 +0,0 @@
-// SPDX-License-Identifier: MIT
-// Copyright (c) 2015-2021 Zig Contributors
-// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
-// The MIT license requires this copyright notice to be included in all copies
-// and substantial portions of the software.
-const std = @import("std");
-const mem = std.mem;
-const assert = std.debug.assert;
-const Allocator = std.mem.Allocator;
-const ast = std.c.ast;
-const Node = ast.Node;
-const Type = ast.Type;
-const Tree = ast.Tree;
-const TokenIndex = ast.TokenIndex;
-const Token = std.c.Token;
-const TokenIterator = ast.Tree.TokenList.Iterator;
-
-pub const Error = error{ParseError} || Allocator.Error;
-
-pub const Options = struct {
- // /// Keep simple macros unexpanded and add the definitions to the ast
- // retain_macros: bool = false,
- /// Warning or error
- warn_as_err: union(enum) {
- /// All warnings are warnings
- None,
-
- /// Some warnings are errors
- Some: []std.meta.Tag(ast.Error),
-
- /// All warnings are errors
- All,
- } = .All,
-};
-
-/// Result should be freed with tree.deinit() when there are
-/// no more references to any of the tokens or nodes.
-pub fn parse(allocator: *Allocator, source: []const u8, options: Options) !*Tree {
- const tree = blk: {
- // This block looks unnecessary, but is a "foot-shield" to prevent the SegmentedLists
- // from being initialized with a pointer to this `arena`, which is created on
- // the stack. Following code should instead refer to `&tree.arena_allocator`, a
- // pointer to data which lives safely on the heap and will outlive `parse`.
- var arena = std.heap.ArenaAllocator.init(allocator);
- errdefer arena.deinit();
- const tree = try arena.allocator.create(ast.Tree);
- tree.* = .{
- .root_node = undefined,
- .arena_allocator = arena,
- .tokens = undefined,
- .sources = undefined,
- };
- break :blk tree;
- };
- errdefer tree.deinit();
- const arena = &tree.arena_allocator.allocator;
-
- tree.tokens = ast.Tree.TokenList.init(arena);
- tree.sources = ast.Tree.SourceList.init(arena);
-
- var tokenizer = std.zig.Tokenizer.init(source);
- while (true) {
- const tree_token = try tree.tokens.addOne();
- tree_token.* = tokenizer.next();
- if (tree_token.id == .Eof) break;
- }
- // TODO preprocess here
- var it = tree.tokens.iterator(0);
-
- while (true) {
- const tok = it.peek().?.id;
- switch (id) {
- .LineComment,
- .MultiLineComment,
- => {
- _ = it.next();
- },
- else => break,
- }
- }
-
- var parse_arena = std.heap.ArenaAllocator.init(allocator);
- defer parse_arena.deinit();
-
- var parser = Parser{
- .scopes = Parser.SymbolList.init(allocator),
- .arena = &parse_arena.allocator,
- .it = &it,
- .tree = tree,
- .options = options,
- };
- defer parser.symbols.deinit();
-
- tree.root_node = try parser.root();
- return tree;
-}
-
-const Parser = struct {
- arena: *Allocator,
- it: *TokenIterator,
- tree: *Tree,
-
- arena: *Allocator,
- scopes: ScopeList,
- options: Options,
-
- const ScopeList = std.SegmentedLists(Scope);
- const SymbolList = std.SegmentedLists(Symbol);
-
- const Scope = struct {
- kind: ScopeKind,
- syms: SymbolList,
- };
-
- const Symbol = struct {
- name: []const u8,
- ty: *Type,
- };
-
- const ScopeKind = enum {
- Block,
- Loop,
- Root,
- Switch,
- };
-
- fn pushScope(parser: *Parser, kind: ScopeKind) !void {
- const new = try parser.scopes.addOne();
- new.* = .{
- .kind = kind,
- .syms = SymbolList.init(parser.arena),
- };
- }
-
- fn popScope(parser: *Parser, len: usize) void {
- _ = parser.scopes.pop();
- }
-
- fn getSymbol(parser: *Parser, tok: TokenIndex) ?*Symbol {
- const name = parser.tree.tokenSlice(tok);
- var scope_it = parser.scopes.iterator(parser.scopes.len);
- while (scope_it.prev()) |scope| {
- var sym_it = scope.syms.iterator(scope.syms.len);
- while (sym_it.prev()) |sym| {
- if (mem.eql(u8, sym.name, name)) {
- return sym;
- }
- }
- }
- return null;
- }
-
- fn declareSymbol(parser: *Parser, type_spec: Node.TypeSpec, dr: *Node.Declarator) Error!void {
- return; // TODO
- }
-
- /// Root <- ExternalDeclaration* eof
- fn root(parser: *Parser) Allocator.Error!*Node.Root {
- try parser.pushScope(.Root);
- defer parser.popScope();
- const node = try parser.arena.create(Node.Root);
- node.* = .{
- .decls = Node.Root.DeclList.init(parser.arena),
- .eof = undefined,
- };
- while (parser.externalDeclarations() catch |e| switch (e) {
- error.OutOfMemory => return error.OutOfMemory,
- error.ParseError => return node,
- }) |decl| {
- try node.decls.push(decl);
- }
- node.eof = parser.eatToken(.Eof) orelse return node;
- return node;
- }
-
- /// ExternalDeclaration
- /// <- DeclSpec Declarator OldStyleDecl* CompoundStmt
- /// / Declaration
- /// OldStyleDecl <- DeclSpec Declarator (COMMA Declarator)* SEMICOLON
- fn externalDeclarations(parser: *Parser) !?*Node {
- return parser.declarationExtra(false);
- }
-
- /// Declaration
- /// <- DeclSpec DeclInit SEMICOLON
- /// / StaticAssert
- /// DeclInit <- Declarator (EQUAL Initializer)? (COMMA Declarator (EQUAL Initializer)?)*
- fn declaration(parser: *Parser) !?*Node {
- return parser.declarationExtra(true);
- }
-
- fn declarationExtra(parser: *Parser, local: bool) !?*Node {
- if (try parser.staticAssert()) |decl| return decl;
- const begin = parser.it.index + 1;
- var ds = Node.DeclSpec{};
- const got_ds = try parser.declSpec(&ds);
- if (local and !got_ds) {
- // not a declaration
- return null;
- }
- switch (ds.storage_class) {
- .Auto, .Register => |tok| return parser.err(.{
- .InvalidStorageClass = .{ .token = tok },
- }),
- .Typedef => {
- const node = try parser.arena.create(Node.Typedef);
- node.* = .{
- .decl_spec = ds,
- .declarators = Node.Typedef.DeclaratorList.init(parser.arena),
- .semicolon = undefined,
- };
- while (true) {
- const dr = @fieldParentPtr(Node.Declarator, "base", (try parser.declarator(.Must)) orelse return parser.err(.{
- .ExpectedDeclarator = .{ .token = parser.it.index },
- }));
- try parser.declareSymbol(ds.type_spec, dr);
- try node.declarators.push(&dr.base);
- if (parser.eatToken(.Comma)) |_| {} else break;
- }
- return &node.base;
- },
- else => {},
- }
- var first_dr = try parser.declarator(.Must);
- if (first_dr != null and declaratorIsFunction(first_dr.?)) {
- // TODO typedeffed fn proto-only
- const dr = @fieldParentPtr(Node.Declarator, "base", first_dr.?);
- try parser.declareSymbol(ds.type_spec, dr);
- var old_decls = Node.FnDecl.OldDeclList.init(parser.arena);
- const body = if (parser.eatToken(.Semicolon)) |_|
- null
- else blk: {
- if (local) {
- // TODO nested function warning
- }
- // TODO first_dr.is_old
- // while (true) {
- // var old_ds = Node.DeclSpec{};
- // if (!(try parser.declSpec(&old_ds))) {
- // // not old decl
- // break;
- // }
- // var old_dr = (try parser.declarator(.Must));
- // // if (old_dr == null)
- // // try parser.err(.{
- // // .NoParamName = .{ .token = parser.it.index },
- // // });
- // // try old_decls.push(decl);
- // }
- const body_node = (try parser.compoundStmt()) orelse return parser.err(.{
- .ExpectedFnBody = .{ .token = parser.it.index },
- });
- break :blk @fieldParentPtr(Node.CompoundStmt, "base", body_node);
- };
-
- const node = try parser.arena.create(Node.FnDecl);
- node.* = .{
- .decl_spec = ds,
- .declarator = dr,
- .old_decls = old_decls,
- .body = body,
- };
- return &node.base;
- } else {
- switch (ds.fn_spec) {
- .Inline, .Noreturn => |tok| return parser.err(.{
- .FnSpecOnNonFn = .{ .token = tok },
- }),
- else => {},
- }
- // TODO threadlocal without static or extern on local variable
- const node = try parser.arena.create(Node.VarDecl);
- node.* = .{
- .decl_spec = ds,
- .initializers = Node.VarDecl.Initializers.init(parser.arena),
- .semicolon = undefined,
- };
- if (first_dr == null) {
- node.semicolon = try parser.expectToken(.Semicolon);
- const ok = switch (ds.type_spec.spec) {
- .Enum => |e| e.name != null,
- .Record => |r| r.name != null,
- else => false,
- };
- const q = ds.type_spec.qual;
- if (!ok)
- try parser.warn(.{
- .NothingDeclared = .{ .token = begin },
- })
- else if (q.@"const" orelse q.atomic orelse q.@"volatile" orelse q.restrict) |tok|
- try parser.warn(.{
- .QualifierIgnored = .{ .token = tok },
- });
- return &node.base;
- }
- var dr = @fieldParentPtr(Node.Declarator, "base", first_dr.?);
- while (true) {
- try parser.declareSymbol(ds.type_spec, dr);
- if (parser.eatToken(.Equal)) |tok| {
- try node.initializers.push((try parser.initializer(dr)) orelse return parser.err(.{
- .ExpectedInitializer = .{ .token = parser.it.index },
- }));
- } else try node.initializers.push(&dr.base);
- if (parser.eatToken(.Comma) != null) break;
- dr = @fieldParentPtr(Node.Declarator, "base", (try parser.declarator(.Must)) orelse return parser.err(.{
- .ExpectedDeclarator = .{ .token = parser.it.index },
- }));
- }
- node.semicolon = try parser.expectToken(.Semicolon);
- return &node.base;
- }
- }
-
- fn declaratorIsFunction(node: *Node) bool {
- if (node.id != .Declarator) return false;
- assert(node.id == .Declarator);
- const dr = @fieldParentPtr(Node.Declarator, "base", node);
- if (dr.suffix != .Fn) return false;
- switch (dr.prefix) {
- .None, .Identifer => return true,
- .Complex => |inner| {
- var inner_node = inner.inner;
- while (true) {
- if (inner_node.id != .Declarator) return false;
- assert(inner_node.id == .Declarator);
- const inner_dr = @fieldParentPtr(Node.Declarator, "base", inner_node);
- if (inner_dr.pointer != null) return false;
- switch (inner_dr.prefix) {
- .None, .Identifer => return true,
- .Complex => |c| inner_node = c.inner,
- }
- }
- },
- }
- }
-
- /// StaticAssert <- Keyword_static_assert LPAREN ConstExpr COMMA STRINGLITERAL RPAREN SEMICOLON
- fn staticAssert(parser: *Parser) !?*Node {
- const tok = parser.eatToken(.Keyword_static_assert) orelse return null;
- _ = try parser.expectToken(.LParen);
- const const_expr = (try parser.constExpr()) orelse parser.err(.{
- .ExpectedExpr = .{ .token = parser.it.index },
- });
- _ = try parser.expectToken(.Comma);
- const str = try parser.expectToken(.StringLiteral);
- _ = try parser.expectToken(.RParen);
- const node = try parser.arena.create(Node.StaticAssert);
- node.* = .{
- .assert = tok,
- .expr = const_expr,
- .semicolon = try parser.expectToken(.Semicolon),
- };
- return &node.base;
- }
-
- /// DeclSpec <- (StorageClassSpec / TypeSpec / FnSpec / AlignSpec)*
- /// returns true if any tokens were consumed
- fn declSpec(parser: *Parser, ds: *Node.DeclSpec) !bool {
- var got = false;
- while ((try parser.storageClassSpec(ds)) or (try parser.typeSpec(&ds.type_spec)) or (try parser.fnSpec(ds)) or (try parser.alignSpec(ds))) {
- got = true;
- }
- return got;
- }
-
- /// StorageClassSpec
- /// <- Keyword_typedef / Keyword_extern / Keyword_static / Keyword_thread_local / Keyword_auto / Keyword_register
- fn storageClassSpec(parser: *Parser, ds: *Node.DeclSpec) !bool {
- blk: {
- if (parser.eatToken(.Keyword_typedef)) |tok| {
- if (ds.storage_class != .None or ds.thread_local != null)
- break :blk;
- ds.storage_class = .{ .Typedef = tok };
- } else if (parser.eatToken(.Keyword_extern)) |tok| {
- if (ds.storage_class != .None)
- break :blk;
- ds.storage_class = .{ .Extern = tok };
- } else if (parser.eatToken(.Keyword_static)) |tok| {
- if (ds.storage_class != .None)
- break :blk;
- ds.storage_class = .{ .Static = tok };
- } else if (parser.eatToken(.Keyword_thread_local)) |tok| {
- switch (ds.storage_class) {
- .None, .Extern, .Static => {},
- else => break :blk,
- }
- ds.thread_local = tok;
- } else if (parser.eatToken(.Keyword_auto)) |tok| {
- if (ds.storage_class != .None or ds.thread_local != null)
- break :blk;
- ds.storage_class = .{ .Auto = tok };
- } else if (parser.eatToken(.Keyword_register)) |tok| {
- if (ds.storage_class != .None or ds.thread_local != null)
- break :blk;
- ds.storage_class = .{ .Register = tok };
- } else return false;
- return true;
- }
- try parser.warn(.{
- .DuplicateSpecifier = .{ .token = parser.it.index },
- });
- return true;
- }
-
- /// TypeSpec
- /// <- Keyword_void / Keyword_char / Keyword_short / Keyword_int / Keyword_long / Keyword_float / Keyword_double
- /// / Keyword_signed / Keyword_unsigned / Keyword_bool / Keyword_complex / Keyword_imaginary /
- /// / Keyword_atomic LPAREN TypeName RPAREN
- /// / EnumSpec
- /// / RecordSpec
- /// / IDENTIFIER // typedef name
- /// / TypeQual
- fn typeSpec(parser: *Parser, type_spec: *Node.TypeSpec) !bool {
- blk: {
- if (parser.eatToken(.Keyword_void)) |tok| {
- if (type_spec.spec != .None)
- break :blk;
- type_spec.spec = .{ .Void = tok };
- } else if (parser.eatToken(.Keyword_char)) |tok| {
- switch (type_spec.spec) {
- .None => {
- type_spec.spec = .{
- .Char = .{
- .char = tok,
- },
- };
- },
- .Int => |int| {
- if (int.int != null)
- break :blk;
- type_spec.spec = .{
- .Char = .{
- .char = tok,
- .sign = int.sign,
- },
- };
- },
- else => break :blk,
- }
- } else if (parser.eatToken(.Keyword_short)) |tok| {
- switch (type_spec.spec) {
- .None => {
- type_spec.spec = .{
- .Short = .{
- .short = tok,
- },
- };
- },
- .Int => |int| {
- if (int.int != null)
- break :blk;
- type_spec.spec = .{
- .Short = .{
- .short = tok,
- .sign = int.sign,
- },
- };
- },
- else => break :blk,
- }
- } else if (parser.eatToken(.Keyword_long)) |tok| {
- switch (type_spec.spec) {
- .None => {
- type_spec.spec = .{
- .Long = .{
- .long = tok,
- },
- };
- },
- .Int => |int| {
- type_spec.spec = .{
- .Long = .{
- .long = tok,
- .sign = int.sign,
- .int = int.int,
- },
- };
- },
- .Long => |*long| {
- if (long.longlong != null)
- break :blk;
- long.longlong = tok;
- },
- .Double => |*double| {
- if (double.long != null)
- break :blk;
- double.long = tok;
- },
- else => break :blk,
- }
- } else if (parser.eatToken(.Keyword_int)) |tok| {
- switch (type_spec.spec) {
- .None => {
- type_spec.spec = .{
- .Int = .{
- .int = tok,
- },
- };
- },
- .Short => |*short| {
- if (short.int != null)
- break :blk;
- short.int = tok;
- },
- .Int => |*int| {
- if (int.int != null)
- break :blk;
- int.int = tok;
- },
- .Long => |*long| {
- if (long.int != null)
- break :blk;
- long.int = tok;
- },
- else => break :blk,
- }
- } else if (parser.eatToken(.Keyword_signed) orelse parser.eatToken(.Keyword_unsigned)) |tok| {
- switch (type_spec.spec) {
- .None => {
- type_spec.spec = .{
- .Int = .{
- .sign = tok,
- },
- };
- },
- .Char => |*char| {
- if (char.sign != null)
- break :blk;
- char.sign = tok;
- },
- .Short => |*short| {
- if (short.sign != null)
- break :blk;
- short.sign = tok;
- },
- .Int => |*int| {
- if (int.sign != null)
- break :blk;
- int.sign = tok;
- },
- .Long => |*long| {
- if (long.sign != null)
- break :blk;
- long.sign = tok;
- },
- else => break :blk,
- }
- } else if (parser.eatToken(.Keyword_float)) |tok| {
- if (type_spec.spec != .None)
- break :blk;
- type_spec.spec = .{
- .Float = .{
- .float = tok,
- },
- };
- } else if (parser.eatToken(.Keyword_double)) |tok| {
- if (type_spec.spec != .None)
- break :blk;
- type_spec.spec = .{
- .Double = .{
- .double = tok,
- },
- };
- } else if (parser.eatToken(.Keyword_complex)) |tok| {
- switch (type_spec.spec) {
- .None => {
- type_spec.spec = .{
- .Double = .{
- .complex = tok,
- .double = null,
- },
- };
- },
- .Float => |*float| {
- if (float.complex != null)
- break :blk;
- float.complex = tok;
- },
- .Double => |*double| {
- if (double.complex != null)
- break :blk;
- double.complex = tok;
- },
- else => break :blk,
- }
- } else if (parser.eatToken(.Keyword_bool)) |tok| {
- if (type_spec.spec != .None)
- break :blk;
- type_spec.spec = .{ .Bool = tok };
- } else if (parser.eatToken(.Keyword_atomic)) |tok| {
- // might be _Atomic qualifier
- if (parser.eatToken(.LParen)) |_| {
- if (type_spec.spec != .None)
- break :blk;
- const name = (try parser.typeName()) orelse return parser.err(.{
- .ExpectedTypeName = .{ .token = parser.it.index },
- });
- type_spec.spec.Atomic = .{
- .atomic = tok,
- .typename = name,
- .rparen = try parser.expectToken(.RParen),
- };
- } else {
- parser.putBackToken(tok);
- }
- } else if (parser.eatToken(.Keyword_enum)) |tok| {
- if (type_spec.spec != .None)
- break :blk;
- type_spec.spec.Enum = try parser.enumSpec(tok);
- } else if (parser.eatToken(.Keyword_union) orelse parser.eatToken(.Keyword_struct)) |tok| {
- if (type_spec.spec != .None)
- break :blk;
- type_spec.spec.Record = try parser.recordSpec(tok);
- } else if (parser.eatToken(.Identifier)) |tok| {
- const ty = parser.getSymbol(tok) orelse {
- parser.putBackToken(tok);
- return false;
- };
- switch (ty.id) {
- .Enum => |e| blk: {
- if (e.name) |some|
- if (!parser.tree.tokenEql(some, tok))
- break :blk;
- return parser.err(.{
- .MustUseKwToRefer = .{ .kw = e.tok, .name = tok },
- });
- },
- .Record => |r| blk: {
- if (r.name) |some|
- if (!parser.tree.tokenEql(some, tok))
- break :blk;
- return parser.err(.{
- .MustUseKwToRefer = .{
- .kw = r.tok,
- .name = tok,
- },
- });
- },
- .Typedef => {
- type_spec.spec = .{
- .Typedef = .{
- .sym = tok,
- .sym_type = ty,
- },
- };
- return true;
- },
- else => {},
- }
- parser.putBackToken(tok);
- return false;
- }
- return parser.typeQual(&type_spec.qual);
- }
- return parser.err(.{
- .InvalidTypeSpecifier = .{
- .token = parser.it.index,
- .type_spec = type_spec,
- },
- });
- }
-
- /// TypeQual <- Keyword_const / Keyword_restrict / Keyword_volatile / Keyword_atomic
- fn typeQual(parser: *Parser, qual: *Node.TypeQual) !bool {
- blk: {
- if (parser.eatToken(.Keyword_const)) |tok| {
- if (qual.@"const" != null)
- break :blk;
- qual.@"const" = tok;
- } else if (parser.eatToken(.Keyword_restrict)) |tok| {
- if (qual.atomic != null)
- break :blk;
- qual.atomic = tok;
- } else if (parser.eatToken(.Keyword_volatile)) |tok| {
- if (qual.@"volatile" != null)
- break :blk;
- qual.@"volatile" = tok;
- } else if (parser.eatToken(.Keyword_atomic)) |tok| {
- if (qual.atomic != null)
- break :blk;
- qual.atomic = tok;
- } else return false;
- return true;
- }
- try parser.warn(.{
- .DuplicateQualifier = .{ .token = parser.it.index },
- });
- return true;
- }
-
- /// FnSpec <- Keyword_inline / Keyword_noreturn
- fn fnSpec(parser: *Parser, ds: *Node.DeclSpec) !bool {
- blk: {
- if (parser.eatToken(.Keyword_inline)) |tok| {
- if (ds.fn_spec != .None)
- break :blk;
- ds.fn_spec = .{ .Inline = tok };
- } else if (parser.eatToken(.Keyword_noreturn)) |tok| {
- if (ds.fn_spec != .None)
- break :blk;
- ds.fn_spec = .{ .Noreturn = tok };
- } else return false;
- return true;
- }
- try parser.warn(.{
- .DuplicateSpecifier = .{ .token = parser.it.index },
- });
- return true;
- }
-
- /// AlignSpec <- Keyword_alignas LPAREN (TypeName / ConstExpr) RPAREN
- fn alignSpec(parser: *Parser, ds: *Node.DeclSpec) !bool {
- if (parser.eatToken(.Keyword_alignas)) |tok| {
- _ = try parser.expectToken(.LParen);
- const node = (try parser.typeName()) orelse (try parser.constExpr()) orelse parser.err(.{
- .ExpectedExpr = .{ .token = parser.it.index },
- });
- if (ds.align_spec != null) {
- try parser.warn(.{
- .DuplicateSpecifier = .{ .token = parser.it.index },
- });
- }
- ds.align_spec = .{
- .alignas = tok,
- .expr = node,
- .rparen = try parser.expectToken(.RParen),
- };
- return true;
- }
- return false;
- }
-
- /// EnumSpec <- Keyword_enum IDENTIFIER? (LBRACE EnumField RBRACE)?
- fn enumSpec(parser: *Parser, tok: TokenIndex) !*Node.EnumType {
- const node = try parser.arena.create(Node.EnumType);
- const name = parser.eatToken(.Identifier);
- node.* = .{
- .tok = tok,
- .name = name,
- .body = null,
- };
- const ty = try parser.arena.create(Type);
- ty.* = .{
- .id = .{
- .Enum = node,
- },
- };
- if (name) |some|
- try parser.symbols.append(.{
- .name = parser.tree.tokenSlice(some),
- .ty = ty,
- });
- if (parser.eatToken(.LBrace)) |lbrace| {
- var fields = Node.EnumType.FieldList.init(parser.arena);
- try fields.push((try parser.enumField()) orelse return parser.err(.{
- .ExpectedEnumField = .{ .token = parser.it.index },
- }));
- while (parser.eatToken(.Comma)) |_| {
- try fields.push((try parser.enumField()) orelse break);
- }
- node.body = .{
- .lbrace = lbrace,
- .fields = fields,
- .rbrace = try parser.expectToken(.RBrace),
- };
- }
- return node;
- }
-
- /// EnumField <- IDENTIFIER (EQUAL ConstExpr)? (COMMA EnumField) COMMA?
- fn enumField(parser: *Parser) !?*Node {
- const name = parser.eatToken(.Identifier) orelse return null;
- const node = try parser.arena.create(Node.EnumField);
- node.* = .{
- .name = name,
- .value = null,
- };
- if (parser.eatToken(.Equal)) |eq| {
- node.value = (try parser.constExpr()) orelse parser.err(.{
- .ExpectedExpr = .{ .token = parser.it.index },
- });
- }
- return &node.base;
- }
-
- /// RecordSpec <- (Keyword_struct / Keyword_union) IDENTIFIER? (LBRACE RecordField+ RBRACE)?
- fn recordSpec(parser: *Parser, tok: TokenIndex) !*Node.RecordType {
- const node = try parser.arena.create(Node.RecordType);
- const name = parser.eatToken(.Identifier);
- const is_struct = parser.tree.tokenSlice(tok)[0] == 's';
- node.* = .{
- .tok = tok,
- .kind = if (is_struct) .Struct else .Union,
- .name = name,
- .body = null,
- };
- const ty = try parser.arena.create(Type);
- ty.* = .{
- .id = .{
- .Record = node,
- },
- };
- if (name) |some|
- try parser.symbols.append(.{
- .name = parser.tree.tokenSlice(some),
- .ty = ty,
- });
- if (parser.eatToken(.LBrace)) |lbrace| {
- try parser.pushScope(.Block);
- defer parser.popScope();
- var fields = Node.RecordType.FieldList.init(parser.arena);
- while (true) {
- if (parser.eatToken(.RBrace)) |rbrace| {
- node.body = .{
- .lbrace = lbrace,
- .fields = fields,
- .rbrace = rbrace,
- };
- break;
- }
- try fields.push(try parser.recordField());
- }
- }
- return node;
- }
-
- /// RecordField
- /// <- TypeSpec* (RecordDeclarator (COMMA RecordDeclarator))? SEMICOLON
- /// \ StaticAssert
- fn recordField(parser: *Parser) Error!*Node {
- if (try parser.staticAssert()) |decl| return decl;
- var got = false;
- var type_spec = Node.TypeSpec{};
- while (try parser.typeSpec(&type_spec)) got = true;
- if (!got)
- return parser.err(.{
- .ExpectedType = .{ .token = parser.it.index },
- });
- const node = try parser.arena.create(Node.RecordField);
- node.* = .{
- .type_spec = type_spec,
- .declarators = Node.RecordField.DeclaratorList.init(parser.arena),
- .semicolon = undefined,
- };
- while (true) {
- const rdr = try parser.recordDeclarator();
- try parser.declareSymbol(type_spec, rdr.declarator);
- try node.declarators.push(&rdr.base);
- if (parser.eatToken(.Comma)) |_| {} else break;
- }
-
- node.semicolon = try parser.expectToken(.Semicolon);
- return &node.base;
- }
-
- /// TypeName <- TypeSpec* AbstractDeclarator?
- fn typeName(parser: *Parser) Error!?*Node {
- @panic("TODO");
- }
-
- /// RecordDeclarator <- Declarator? (COLON ConstExpr)?
- fn recordDeclarator(parser: *Parser) Error!*Node.RecordDeclarator {
- @panic("TODO");
- }
-
- /// Pointer <- ASTERISK TypeQual* Pointer?
- fn pointer(parser: *Parser) Error!?*Node.Pointer {
- const asterisk = parser.eatToken(.Asterisk) orelse return null;
- const node = try parser.arena.create(Node.Pointer);
- node.* = .{
- .asterisk = asterisk,
- .qual = .{},
- .pointer = null,
- };
- while (try parser.typeQual(&node.qual)) {}
- node.pointer = try parser.pointer();
- return node;
- }
-
- const Named = enum {
- Must,
- Allowed,
- Forbidden,
- };
-
- /// Declarator <- Pointer? DeclaratorSuffix
- /// DeclaratorPrefix
- /// <- IDENTIFIER // if named != .Forbidden
- /// / LPAREN Declarator RPAREN
- /// / (none) // if named != .Must
- /// DeclaratorSuffix
- /// <- DeclaratorPrefix (LBRACKET ArrayDeclarator? RBRACKET)*
- /// / DeclaratorPrefix LPAREN (ParamDecl (COMMA ParamDecl)* (COMMA ELLIPSIS)?)? RPAREN
- fn declarator(parser: *Parser, named: Named) Error!?*Node {
- const ptr = try parser.pointer();
- var node: *Node.Declarator = undefined;
- var inner_fn = false;
-
- // TODO sizof(int (int))
- // prefix
- if (parser.eatToken(.LParen)) |lparen| {
- const inner = (try parser.declarator(named)) orelse return parser.err(.{
- .ExpectedDeclarator = .{ .token = lparen + 1 },
- });
- inner_fn = declaratorIsFunction(inner);
- node = try parser.arena.create(Node.Declarator);
- node.* = .{
- .pointer = ptr,
- .prefix = .{
- .Complex = .{
- .lparen = lparen,
- .inner = inner,
- .rparen = try parser.expectToken(.RParen),
- },
- },
- .suffix = .None,
- };
- } else if (named != .Forbidden) {
- if (parser.eatToken(.Identifier)) |tok| {
- node = try parser.arena.create(Node.Declarator);
- node.* = .{
- .pointer = ptr,
- .prefix = .{ .Identifer = tok },
- .suffix = .None,
- };
- } else if (named == .Must) {
- return parser.err(.{
- .ExpectedToken = .{ .token = parser.it.index, .expected_id = .Identifier },
- });
- } else {
- if (ptr) |some|
- return &some.base;
- return null;
- }
- } else {
- node = try parser.arena.create(Node.Declarator);
- node.* = .{
- .pointer = ptr,
- .prefix = .None,
- .suffix = .None,
- };
- }
- // suffix
- if (parser.eatToken(.LParen)) |lparen| {
- if (inner_fn)
- return parser.err(.{
- .InvalidDeclarator = .{ .token = lparen },
- });
- node.suffix = .{
- .Fn = .{
- .lparen = lparen,
- .params = Node.Declarator.Params.init(parser.arena),
- .rparen = undefined,
- },
- };
- try parser.paramDecl(node);
- node.suffix.Fn.rparen = try parser.expectToken(.RParen);
- } else if (parser.eatToken(.LBracket)) |tok| {
- if (inner_fn)
- return parser.err(.{
- .InvalidDeclarator = .{ .token = tok },
- });
- node.suffix = .{ .Array = Node.Declarator.Arrays.init(parser.arena) };
- var lbrace = tok;
- while (true) {
- try node.suffix.Array.push(try parser.arrayDeclarator(lbrace));
- if (parser.eatToken(.LBracket)) |t| lbrace = t else break;
- }
- }
- if (parser.eatToken(.LParen) orelse parser.eatToken(.LBracket)) |tok|
- return parser.err(.{
- .InvalidDeclarator = .{ .token = tok },
- });
- return &node.base;
- }
-
- /// ArrayDeclarator
- /// <- ASTERISK
- /// / Keyword_static TypeQual* AssignmentExpr
- /// / TypeQual+ (ASTERISK / Keyword_static AssignmentExpr)
- /// / TypeQual+ AssignmentExpr?
- /// / AssignmentExpr
- fn arrayDeclarator(parser: *Parser, lbracket: TokenIndex) !*Node.Array {
- const arr = try parser.arena.create(Node.Array);
- arr.* = .{
- .lbracket = lbracket,
- .inner = .Inferred,
- .rbracket = undefined,
- };
- if (parser.eatToken(.Asterisk)) |tok| {
- arr.inner = .{ .Unspecified = tok };
- } else {
- // TODO
- }
- arr.rbracket = try parser.expectToken(.RBracket);
- return arr;
- }
-
- /// Params <- ParamDecl (COMMA ParamDecl)* (COMMA ELLIPSIS)?
- /// ParamDecl <- DeclSpec (Declarator / AbstractDeclarator)
- fn paramDecl(parser: *Parser, dr: *Node.Declarator) !void {
- var old_style = false;
- while (true) {
- var ds = Node.DeclSpec{};
- if (try parser.declSpec(&ds)) {
- //TODO
- // TODO try parser.declareSymbol(ds.type_spec, dr);
- } else if (parser.eatToken(.Identifier)) |tok| {
- old_style = true;
- } else if (parser.eatToken(.Ellipsis)) |tok| {
- // TODO
- }
- }
- }
-
- /// Expr <- AssignmentExpr (COMMA Expr)*
- fn expr(parser: *Parser) Error!?*Expr {
- @panic("TODO");
- }
-
- /// AssignmentExpr
- /// <- ConditionalExpr // TODO recursive?
- /// / UnaryExpr (EQUAL / ASTERISKEQUAL / SLASHEQUAL / PERCENTEQUAL / PLUSEQUAL / MINUSEQUA /
- /// / ANGLEBRACKETANGLEBRACKETLEFTEQUAL / ANGLEBRACKETANGLEBRACKETRIGHTEQUAL /
- /// / AMPERSANDEQUAL / CARETEQUAL / PIPEEQUAL) AssignmentExpr
- fn assignmentExpr(parser: *Parser) !?*Expr {
- @panic("TODO");
- }
-
- /// ConstExpr <- ConditionalExpr
- fn constExpr(parser: *Parser) Error!?*Expr {
- const start = parser.it.index;
- const expression = try parser.conditionalExpr();
- if (expression != null and expression.?.value == .None)
- return parser.err(.{
- .ConsExpr = start,
- });
- return expression;
- }
-
- /// ConditionalExpr <- LogicalOrExpr (QUESTIONMARK Expr COLON ConditionalExpr)?
- fn conditionalExpr(parser: *Parser) Error!?*Expr {
- @panic("TODO");
- }
-
- /// LogicalOrExpr <- LogicalAndExpr (PIPEPIPE LogicalOrExpr)*
- fn logicalOrExpr(parser: *Parser) !*Node {
- const lhs = (try parser.logicalAndExpr()) orelse return null;
- }
-
- /// LogicalAndExpr <- BinOrExpr (AMPERSANDAMPERSAND LogicalAndExpr)*
- fn logicalAndExpr(parser: *Parser) !*Node {
- @panic("TODO");
- }
-
- /// BinOrExpr <- BinXorExpr (PIPE BinOrExpr)*
- fn binOrExpr(parser: *Parser) !*Node {
- @panic("TODO");
- }
-
- /// BinXorExpr <- BinAndExpr (CARET BinXorExpr)*
- fn binXorExpr(parser: *Parser) !*Node {
- @panic("TODO");
- }
-
- /// BinAndExpr <- EqualityExpr (AMPERSAND BinAndExpr)*
- fn binAndExpr(parser: *Parser) !*Node {
- @panic("TODO");
- }
-
- /// EqualityExpr <- ComparisionExpr ((EQUALEQUAL / BANGEQUAL) EqualityExpr)*
- fn equalityExpr(parser: *Parser) !*Node {
- @panic("TODO");
- }
-
- /// ComparisionExpr <- ShiftExpr (ANGLEBRACKETLEFT / ANGLEBRACKETLEFTEQUAL /ANGLEBRACKETRIGHT / ANGLEBRACKETRIGHTEQUAL) ComparisionExpr)*
- fn comparisionExpr(parser: *Parser) !*Node {
- @panic("TODO");
- }
-
- /// ShiftExpr <- AdditiveExpr (ANGLEBRACKETANGLEBRACKETLEFT / ANGLEBRACKETANGLEBRACKETRIGHT) ShiftExpr)*
- fn shiftExpr(parser: *Parser) !*Node {
- @panic("TODO");
- }
-
- /// AdditiveExpr <- MultiplicativeExpr (PLUS / MINUS) AdditiveExpr)*
- fn additiveExpr(parser: *Parser) !*Node {
- @panic("TODO");
- }
-
- /// MultiplicativeExpr <- UnaryExpr (ASTERISK / SLASH / PERCENT) MultiplicativeExpr)*
- fn multiplicativeExpr(parser: *Parser) !*Node {
- @panic("TODO");
- }
-
- /// UnaryExpr
- /// <- LPAREN TypeName RPAREN UnaryExpr
- /// / Keyword_sizeof LAPERN TypeName RPAREN
- /// / Keyword_sizeof UnaryExpr
- /// / Keyword_alignof LAPERN TypeName RPAREN
- /// / (AMPERSAND / ASTERISK / PLUS / PLUSPLUS / MINUS / MINUSMINUS / TILDE / BANG) UnaryExpr
- /// / PrimaryExpr PostFixExpr*
- fn unaryExpr(parser: *Parser) !*Node {
- @panic("TODO");
- }
-
- /// PrimaryExpr
- /// <- IDENTIFIER
- /// / INTEGERLITERAL / FLOATLITERAL / STRINGLITERAL / CHARLITERAL
- /// / LPAREN Expr RPAREN
- /// / Keyword_generic LPAREN AssignmentExpr (COMMA Generic)+ RPAREN
- fn primaryExpr(parser: *Parser) !*Node {
- @panic("TODO");
- }
-
- /// Generic
- /// <- TypeName COLON AssignmentExpr
- /// / Keyword_default COLON AssignmentExpr
- fn generic(parser: *Parser) !*Node {
- @panic("TODO");
- }
-
- /// PostFixExpr
- /// <- LPAREN TypeName RPAREN LBRACE Initializers RBRACE
- /// / LBRACKET Expr RBRACKET
- /// / LPAREN (AssignmentExpr (COMMA AssignmentExpr)*)? RPAREN
- /// / (PERIOD / ARROW) IDENTIFIER
- /// / (PLUSPLUS / MINUSMINUS)
- fn postFixExpr(parser: *Parser) !*Node {
- @panic("TODO");
- }
-
- /// Initializers <- ((Designator+ EQUAL)? Initializer COMMA)* (Designator+ EQUAL)? Initializer COMMA?
- fn initializers(parser: *Parser) !*Node {
- @panic("TODO");
- }
-
- /// Initializer
- /// <- LBRACE Initializers RBRACE
- /// / AssignmentExpr
- fn initializer(parser: *Parser, dr: *Node.Declarator) Error!?*Node {
- @panic("TODO");
- }
-
- /// Designator
- /// <- LBRACKET ConstExpr RBRACKET
- /// / PERIOD IDENTIFIER
- fn designator(parser: *Parser) !*Node {
- @panic("TODO");
- }
-
- /// CompoundStmt <- LBRACE (Declaration / Stmt)* RBRACE
- fn compoundStmt(parser: *Parser) Error!?*Node {
- const lbrace = parser.eatToken(.LBrace) orelse return null;
- try parser.pushScope(.Block);
- defer parser.popScope();
- const body_node = try parser.arena.create(Node.CompoundStmt);
- body_node.* = .{
- .lbrace = lbrace,
- .statements = Node.CompoundStmt.StmtList.init(parser.arena),
- .rbrace = undefined,
- };
- while (true) {
- if (parser.eatToken(.RBRACE)) |rbrace| {
- body_node.rbrace = rbrace;
- break;
- }
- try body_node.statements.push((try parser.declaration()) orelse (try parser.stmt()));
- }
- return &body_node.base;
- }
-
- /// Stmt
- /// <- CompoundStmt
- /// / Keyword_if LPAREN Expr RPAREN Stmt (Keyword_ELSE Stmt)?
- /// / Keyword_switch LPAREN Expr RPAREN Stmt
- /// / Keyword_while LPAREN Expr RPAREN Stmt
- /// / Keyword_do statement Keyword_while LPAREN Expr RPAREN SEMICOLON
- /// / Keyword_for LPAREN (Declaration / ExprStmt) ExprStmt Expr? RPAREN Stmt
- /// / Keyword_default COLON Stmt
- /// / Keyword_case ConstExpr COLON Stmt
- /// / Keyword_goto IDENTIFIER SEMICOLON
- /// / Keyword_continue SEMICOLON
- /// / Keyword_break SEMICOLON
- /// / Keyword_return Expr? SEMICOLON
- /// / IDENTIFIER COLON Stmt
- /// / ExprStmt
- fn stmt(parser: *Parser) Error!*Node {
- if (try parser.compoundStmt()) |node| return node;
- if (parser.eatToken(.Keyword_if)) |tok| {
- const node = try parser.arena.create(Node.IfStmt);
- _ = try parser.expectToken(.LParen);
- node.* = .{
- .@"if" = tok,
- .cond = (try parser.expr()) orelse return parser.err(.{
- .ExpectedExpr = .{ .token = parser.it.index },
- }),
- .body = undefined,
- .@"else" = null,
- };
- _ = try parser.expectToken(.RParen);
- node.body = try parser.stmt();
- if (parser.eatToken(.Keyword_else)) |else_tok| {
- node.@"else" = .{
- .tok = else_tok,
- .body = try parser.stmt(),
- };
- }
- return &node.base;
- }
- if (parser.eatToken(.Keyword_while)) |tok| {
- try parser.pushScope(.Loop);
- defer parser.popScope();
- _ = try parser.expectToken(.LParen);
- const cond = (try parser.expr()) orelse return parser.err(.{
- .ExpectedExpr = .{ .token = parser.it.index },
- });
- const rparen = try parser.expectToken(.RParen);
- const node = try parser.arena.create(Node.WhileStmt);
- node.* = .{
- .@"while" = tok,
- .cond = cond,
- .rparen = rparen,
- .body = try parser.stmt(),
- .semicolon = try parser.expectToken(.Semicolon),
- };
- return &node.base;
- }
- if (parser.eatToken(.Keyword_do)) |tok| {
- try parser.pushScope(.Loop);
- defer parser.popScope();
- const body = try parser.stmt();
- _ = try parser.expectToken(.LParen);
- const cond = (try parser.expr()) orelse return parser.err(.{
- .ExpectedExpr = .{ .token = parser.it.index },
- });
- _ = try parser.expectToken(.RParen);
- const node = try parser.arena.create(Node.DoStmt);
- node.* = .{
- .do = tok,
- .body = body,
- .cond = cond,
- .@"while" = @"while",
- .semicolon = try parser.expectToken(.Semicolon),
- };
- return &node.base;
- }
- if (parser.eatToken(.Keyword_for)) |tok| {
- try parser.pushScope(.Loop);
- defer parser.popScope();
- _ = try parser.expectToken(.LParen);
- const init = if (try parser.declaration()) |decl| blk: {
- // TODO disallow storage class other than auto and register
- break :blk decl;
- } else try parser.exprStmt();
- const cond = try parser.expr();
- const semicolon = try parser.expectToken(.Semicolon);
- const incr = try parser.expr();
- const rparen = try parser.expectToken(.RParen);
- const node = try parser.arena.create(Node.ForStmt);
- node.* = .{
- .@"for" = tok,
- .init = init,
- .cond = cond,
- .semicolon = semicolon,
- .incr = incr,
- .rparen = rparen,
- .body = try parser.stmt(),
- };
- return &node.base;
- }
- if (parser.eatToken(.Keyword_switch)) |tok| {
- try parser.pushScope(.Switch);
- defer parser.popScope();
- _ = try parser.expectToken(.LParen);
- const switch_expr = try parser.exprStmt();
- const rparen = try parser.expectToken(.RParen);
- const node = try parser.arena.create(Node.SwitchStmt);
- node.* = .{
- .@"switch" = tok,
- .expr = switch_expr,
- .rparen = rparen,
- .body = try parser.stmt(),
- };
- return &node.base;
- }
- if (parser.eatToken(.Keyword_default)) |tok| {
- _ = try parser.expectToken(.Colon);
- const node = try parser.arena.create(Node.LabeledStmt);
- node.* = .{
- .kind = .{ .Default = tok },
- .stmt = try parser.stmt(),
- };
- return &node.base;
- }
- if (parser.eatToken(.Keyword_case)) |tok| {
- _ = try parser.expectToken(.Colon);
- const node = try parser.arena.create(Node.LabeledStmt);
- node.* = .{
- .kind = .{ .Case = tok },
- .stmt = try parser.stmt(),
- };
- return &node.base;
- }
- if (parser.eatToken(.Keyword_goto)) |tok| {
- const node = try parser.arena.create(Node.JumpStmt);
- node.* = .{
- .ltoken = tok,
- .kind = .{ .Goto = tok },
- .semicolon = try parser.expectToken(.Semicolon),
- };
- return &node.base;
- }
- if (parser.eatToken(.Keyword_continue)) |tok| {
- const node = try parser.arena.create(Node.JumpStmt);
- node.* = .{
- .ltoken = tok,
- .kind = .Continue,
- .semicolon = try parser.expectToken(.Semicolon),
- };
- return &node.base;
- }
- if (parser.eatToken(.Keyword_break)) |tok| {
- const node = try parser.arena.create(Node.JumpStmt);
- node.* = .{
- .ltoken = tok,
- .kind = .Break,
- .semicolon = try parser.expectToken(.Semicolon),
- };
- return &node.base;
- }
- if (parser.eatToken(.Keyword_return)) |tok| {
- const node = try parser.arena.create(Node.JumpStmt);
- node.* = .{
- .ltoken = tok,
- .kind = .{ .Return = try parser.expr() },
- .semicolon = try parser.expectToken(.Semicolon),
- };
- return &node.base;
- }
- if (parser.eatToken(.Identifier)) |tok| {
- if (parser.eatToken(.Colon)) |_| {
- const node = try parser.arena.create(Node.LabeledStmt);
- node.* = .{
- .kind = .{ .Label = tok },
- .stmt = try parser.stmt(),
- };
- return &node.base;
- }
- parser.putBackToken(tok);
- }
- return parser.exprStmt();
- }
-
- /// ExprStmt <- Expr? SEMICOLON
- fn exprStmt(parser: *Parser) !*Node {
- const node = try parser.arena.create(Node.ExprStmt);
- node.* = .{
- .expr = try parser.expr(),
- .semicolon = try parser.expectToken(.Semicolon),
- };
- return &node.base;
- }
-
- fn eatToken(parser: *Parser, id: std.meta.Tag(Token.Id)) ?TokenIndex {
- while (true) {
- switch ((parser.it.next() orelse return null).id) {
- .LineComment, .MultiLineComment, .Nl => continue,
- else => |next_id| if (next_id == id) {
- return parser.it.index;
- } else {
- _ = parser.it.prev();
- return null;
- },
- }
- }
- }
-
- fn expectToken(parser: *Parser, id: std.meta.Tag(Token.Id)) Error!TokenIndex {
- while (true) {
- switch ((parser.it.next() orelse return error.ParseError).id) {
- .LineComment, .MultiLineComment, .Nl => continue,
- else => |next_id| if (next_id != id) {
- return parser.err(.{
- .ExpectedToken = .{ .token = parser.it.index, .expected_id = id },
- });
- } else {
- return parser.it.index;
- },
- }
- }
- }
-
- fn putBackToken(parser: *Parser, putting_back: TokenIndex) void {
- while (true) {
- const prev_tok = parser.it.next() orelse return;
- switch (prev_tok.id) {
- .LineComment, .MultiLineComment, .Nl => continue,
- else => {
- assert(parser.it.list.at(putting_back) == prev_tok);
- return;
- },
- }
- }
- }
-
- fn err(parser: *Parser, msg: ast.Error) Error {
- try parser.tree.msgs.push(.{
- .kind = .Error,
- .inner = msg,
- });
- return error.ParseError;
- }
-
- fn warn(parser: *Parser, msg: ast.Error) Error!void {
- const is_warning = switch (parser.options.warn_as_err) {
- .None => true,
- .Some => |list| for (list) |item| (if (item == msg) break false) else true,
- .All => false,
- };
- try parser.tree.msgs.push(.{
- .kind = if (is_warning) .Warning else .Error,
- .inner = msg,
- });
- if (!is_warning) return error.ParseError;
- }
-
- fn note(parser: *Parser, msg: ast.Error) Error!void {
- try parser.tree.msgs.push(.{
- .kind = .Note,
- .inner = msg,
- });
- }
-};
diff --git a/zig/lib/std/child_process.zig b/zig/lib/std/child_process.zig
index d37dd9fdf5..01db179bbe 100644
--- a/zig/lib/std/child_process.zig
+++ b/zig/lib/std/child_process.zig
@@ -264,7 +264,7 @@ pub const ChildProcess = struct {
// TODO collect output in a deadlock-avoiding way on Windows.
// https://github.com/ziglang/zig/issues/6343
- if (builtin.os.tag == .windows) {
+ if (builtin.os.tag == .windows or builtin.os.tag == .haiku) {
const stdout_in = child.stdout.?.reader();
const stderr_in = child.stderr.?.reader();
diff --git a/zig/lib/std/compress/deflate.zig b/zig/lib/std/compress/deflate.zig
index e680dc9e6f..88b9ec8672 100644
--- a/zig/lib/std/compress/deflate.zig
+++ b/zig/lib/std/compress/deflate.zig
@@ -384,6 +384,8 @@ pub fn InflateStream(comptime ReaderType: type) type {
const last_length = lengths[i - 1];
const repeat = 3 + (try self.readBits(2));
const last_index = i + repeat;
+ if (last_index > lengths.len)
+ return error.InvalidLength;
while (i < last_index) : (i += 1) {
lengths[i] = last_length;
}
@@ -655,3 +657,17 @@ pub fn InflateStream(comptime ReaderType: type) type {
pub fn inflateStream(reader: anytype, window_slice: []u8) InflateStream(@TypeOf(reader)) {
return InflateStream(@TypeOf(reader)).init(reader, window_slice);
}
+
+test "lengths overflow" {
+ // malformed final dynamic block, tries to write 321 code lengths (MAXCODES is 316)
+ // f dy hlit hdist hclen 16 17 18 0 (18) x138 (18) x138 (18) x39 (16) x6
+ // 1 10 11101 11101 0000 010 010 010 010 (11) 1111111 (11) 1111111 (11) 0011100 (01) 11
+ const stream = [_]u8{ 0b11101101, 0b00011101, 0b00100100, 0b11101001, 0b11111111, 0b11111111, 0b00111001, 0b00001110 };
+
+ const reader = std.io.fixedBufferStream(&stream).reader();
+ var window: [0x8000]u8 = undefined;
+ var inflate = inflateStream(reader, &window);
+
+ var buf: [1]u8 = undefined;
+ std.testing.expectError(error.InvalidLength, inflate.read(&buf));
+}
diff --git a/zig/lib/std/crypto.zig b/zig/lib/std/crypto.zig
index 457b9130d9..af23af9460 100644
--- a/zig/lib/std/crypto.zig
+++ b/zig/lib/std/crypto.zig
@@ -67,6 +67,7 @@ pub const dh = struct {
pub const ecc = struct {
pub const Curve25519 = @import("crypto/25519/curve25519.zig").Curve25519;
pub const Edwards25519 = @import("crypto/25519/edwards25519.zig").Edwards25519;
+ pub const P256 = @import("crypto/pcurves/p256.zig").P256;
pub const Ristretto255 = @import("crypto/25519/ristretto255.zig").Ristretto255;
};
@@ -154,7 +155,7 @@ pub const random = &@import("crypto/tlcsprng.zig").interface;
const std = @import("std.zig");
-pub const Error = @import("crypto/error.zig").Error;
+pub const errors = @import("crypto/errors.zig");
test "crypto" {
const please_windows_dont_oom = std.Target.current.os.tag == .windows;
diff --git a/zig/lib/std/crypto/25519/curve25519.zig b/zig/lib/std/crypto/25519/curve25519.zig
index d3e51ad0e0..90b0e10c4f 100644
--- a/zig/lib/std/crypto/25519/curve25519.zig
+++ b/zig/lib/std/crypto/25519/curve25519.zig
@@ -4,7 +4,11 @@
// The MIT license requires this copyright notice to be included in all copies
// and substantial portions of the software.
const std = @import("std");
-const Error = std.crypto.Error;
+const crypto = std.crypto;
+
+const IdentityElementError = crypto.errors.IdentityElementError;
+const NonCanonicalError = crypto.errors.NonCanonicalError;
+const WeakPublicKeyError = crypto.errors.WeakPublicKeyError;
/// Group operations over Curve25519.
pub const Curve25519 = struct {
@@ -29,12 +33,12 @@ pub const Curve25519 = struct {
pub const basePoint = Curve25519{ .x = Fe.curve25519BasePoint };
/// Check that the encoding of a Curve25519 point is canonical.
- pub fn rejectNonCanonical(s: [32]u8) Error!void {
+ pub fn rejectNonCanonical(s: [32]u8) NonCanonicalError!void {
return Fe.rejectNonCanonical(s, false);
}
/// Reject the neutral element.
- pub fn rejectIdentity(p: Curve25519) Error!void {
+ pub fn rejectIdentity(p: Curve25519) IdentityElementError!void {
if (p.x.isZero()) {
return error.IdentityElement;
}
@@ -45,7 +49,7 @@ pub const Curve25519 = struct {
return p.dbl().dbl().dbl();
}
- fn ladder(p: Curve25519, s: [32]u8, comptime bits: usize) Error!Curve25519 {
+ fn ladder(p: Curve25519, s: [32]u8, comptime bits: usize) IdentityElementError!Curve25519 {
var x1 = p.x;
var x2 = Fe.one;
var z2 = Fe.zero;
@@ -86,7 +90,7 @@ pub const Curve25519 = struct {
/// way to use Curve25519 for a DH operation.
/// Return error.IdentityElement if the resulting point is
/// the identity element.
- pub fn clampedMul(p: Curve25519, s: [32]u8) Error!Curve25519 {
+ pub fn clampedMul(p: Curve25519, s: [32]u8) IdentityElementError!Curve25519 {
var t: [32]u8 = s;
scalar.clamp(&t);
return try ladder(p, t, 255);
@@ -96,16 +100,16 @@ pub const Curve25519 = struct {
/// Return error.IdentityElement if the resulting point is
/// the identity element or error.WeakPublicKey if the public
/// key is a low-order point.
- pub fn mul(p: Curve25519, s: [32]u8) Error!Curve25519 {
+ pub fn mul(p: Curve25519, s: [32]u8) (IdentityElementError || WeakPublicKeyError)!Curve25519 {
const cofactor = [_]u8{8} ++ [_]u8{0} ** 31;
_ = ladder(p, cofactor, 4) catch |_| return error.WeakPublicKey;
return try ladder(p, s, 256);
}
/// Compute the Curve25519 equivalent to an Edwards25519 point.
- pub fn fromEdwards25519(p: std.crypto.ecc.Edwards25519) Error!Curve25519 {
+ pub fn fromEdwards25519(p: crypto.ecc.Edwards25519) IdentityElementError!Curve25519 {
try p.clearCofactor().rejectIdentity();
- const one = std.crypto.ecc.Edwards25519.Fe.one;
+ const one = crypto.ecc.Edwards25519.Fe.one;
const x = one.add(p.y).mul(one.sub(p.y).invert()); // xMont=(1+yEd)/(1-yEd)
return Curve25519{ .x = x };
}
diff --git a/zig/lib/std/crypto/25519/ed25519.zig b/zig/lib/std/crypto/25519/ed25519.zig
index e385e34f12..b48cc24b4b 100644
--- a/zig/lib/std/crypto/25519/ed25519.zig
+++ b/zig/lib/std/crypto/25519/ed25519.zig
@@ -8,8 +8,15 @@ const crypto = std.crypto;
const debug = std.debug;
const fmt = std.fmt;
const mem = std.mem;
+
const Sha512 = crypto.hash.sha2.Sha512;
-const Error = crypto.Error;
+
+const EncodingError = crypto.errors.EncodingError;
+const IdentityElementError = crypto.errors.IdentityElementError;
+const NonCanonicalError = crypto.errors.NonCanonicalError;
+const SignatureVerificationError = crypto.errors.SignatureVerificationError;
+const KeyMismatchError = crypto.errors.KeyMismatchError;
+const WeakPublicKeyError = crypto.errors.WeakPublicKeyError;
/// Ed25519 (EdDSA) signatures.
pub const Ed25519 = struct {
@@ -41,7 +48,7 @@ pub const Ed25519 = struct {
///
/// For this reason, an EdDSA secret key is commonly called a seed,
/// from which the actual secret is derived.
- pub fn create(seed: ?[seed_length]u8) Error!KeyPair {
+ pub fn create(seed: ?[seed_length]u8) IdentityElementError!KeyPair {
const ss = seed orelse ss: {
var random_seed: [seed_length]u8 = undefined;
crypto.random.bytes(&random_seed);
@@ -51,7 +58,7 @@ pub const Ed25519 = struct {
var h = Sha512.init(.{});
h.update(&ss);
h.final(&az);
- const p = try Curve.basePoint.clampedMul(az[0..32].*);
+ const p = Curve.basePoint.clampedMul(az[0..32].*) catch return error.IdentityElement;
var sk: [secret_length]u8 = undefined;
mem.copy(u8, &sk, &ss);
const pk = p.toBytes();
@@ -72,7 +79,7 @@ pub const Ed25519 = struct {
/// Sign a message using a key pair, and optional random noise.
/// Having noise creates non-standard, non-deterministic signatures,
/// but has been proven to increase resilience against fault attacks.
- pub fn sign(msg: []const u8, key_pair: KeyPair, noise: ?[noise_length]u8) Error![signature_length]u8 {
+ pub fn sign(msg: []const u8, key_pair: KeyPair, noise: ?[noise_length]u8) (IdentityElementError || WeakPublicKeyError || KeyMismatchError)![signature_length]u8 {
const seed = key_pair.secret_key[0..seed_length];
const public_key = key_pair.secret_key[seed_length..];
if (!mem.eql(u8, public_key, &key_pair.public_key)) {
@@ -113,7 +120,7 @@ pub const Ed25519 = struct {
/// Verify an Ed25519 signature given a message and a public key.
/// Returns error.SignatureVerificationFailed is the signature verification failed.
- pub fn verify(sig: [signature_length]u8, msg: []const u8, public_key: [public_length]u8) Error!void {
+ pub fn verify(sig: [signature_length]u8, msg: []const u8, public_key: [public_length]u8) (SignatureVerificationError || WeakPublicKeyError || EncodingError || NonCanonicalError || IdentityElementError)!void {
const r = sig[0..32];
const s = sig[32..64];
try Curve.scalar.rejectNonCanonical(s.*);
@@ -122,6 +129,7 @@ pub const Ed25519 = struct {
try a.rejectIdentity();
try Curve.rejectNonCanonical(r.*);
const expected_r = try Curve.fromBytes(r.*);
+ try expected_r.rejectIdentity();
var h = Sha512.init(.{});
h.update(r);
@@ -131,8 +139,7 @@ pub const Ed25519 = struct {
h.final(&hram64);
const hram = Curve.scalar.reduce64(hram64);
- const ah = try a.neg().mulPublic(hram);
- const sb_ah = (try Curve.basePoint.mulPublic(s.*)).add(ah);
+ const sb_ah = try Curve.basePoint.mulDoubleBasePublic(s.*, a.neg(), hram);
if (expected_r.sub(sb_ah).clearCofactor().rejectIdentity()) |_| {
return error.SignatureVerificationFailed;
} else |_| {}
@@ -146,7 +153,7 @@ pub const Ed25519 = struct {
};
/// Verify several signatures in a single operation, much faster than verifying signatures one-by-one
- pub fn verifyBatch(comptime count: usize, signature_batch: [count]BatchElement) Error!void {
+ pub fn verifyBatch(comptime count: usize, signature_batch: [count]BatchElement) (SignatureVerificationError || IdentityElementError || WeakPublicKeyError || EncodingError || NonCanonicalError)!void {
var r_batch: [count][32]u8 = undefined;
var s_batch: [count][32]u8 = undefined;
var a_batch: [count]Curve = undefined;
@@ -161,6 +168,7 @@ pub const Ed25519 = struct {
try a.rejectIdentity();
try Curve.rejectNonCanonical(r.*);
const expected_r = try Curve.fromBytes(r.*);
+ try expected_r.rejectIdentity();
expected_r_batch[i] = expected_r;
r_batch[i] = r.*;
s_batch[i] = s.*;
@@ -180,7 +188,7 @@ pub const Ed25519 = struct {
var z_batch: [count]Curve.scalar.CompressedScalar = undefined;
for (z_batch) |*z| {
- std.crypto.random.bytes(z[0..16]);
+ crypto.random.bytes(z[0..16]);
mem.set(u8, z[16..], 0);
}
@@ -233,8 +241,8 @@ test "ed25519 batch verification" {
const key_pair = try Ed25519.KeyPair.create(null);
var msg1: [32]u8 = undefined;
var msg2: [32]u8 = undefined;
- std.crypto.random.bytes(&msg1);
- std.crypto.random.bytes(&msg2);
+ crypto.random.bytes(&msg1);
+ crypto.random.bytes(&msg2);
const sig1 = try Ed25519.sign(&msg1, key_pair, null);
const sig2 = try Ed25519.sign(&msg2, key_pair, null);
var signature_batch = [_]Ed25519.BatchElement{
@@ -317,13 +325,13 @@ test "ed25519 test vectors" {
.msg_hex = "9bedc267423725d473888631ebf45988bad3db83851ee85c85e241a07d148b41",
.public_key_hex = "f7badec5b8abeaf699583992219b7b223f1df3fbbea919844e3f7c554a43dd43",
.sig_hex = "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff03be9678ac102edcd92b0210bb34d7428d12ffc5df5f37e359941266a4e35f0f",
- .expected = error.SignatureVerificationFailed, // 8 - non-canonical R
+ .expected = error.IdentityElement, // 8 - non-canonical R
},
Vec{
.msg_hex = "9bedc267423725d473888631ebf45988bad3db83851ee85c85e241a07d148b41",
.public_key_hex = "f7badec5b8abeaf699583992219b7b223f1df3fbbea919844e3f7c554a43dd43",
.sig_hex = "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffca8c5b64cd208982aa38d4936621a4775aa233aa0505711d8fdcfdaa943d4908",
- .expected = null, // 9 - non-canonical R
+ .expected = error.IdentityElement, // 9 - non-canonical R
},
Vec{
.msg_hex = "e96b7021eb39c1a163b6da4e3093dcd3f21387da4cc4572be588fafae23c155b",
diff --git a/zig/lib/std/crypto/25519/edwards25519.zig b/zig/lib/std/crypto/25519/edwards25519.zig
index 89b7b9b9f3..4e3d156007 100644
--- a/zig/lib/std/crypto/25519/edwards25519.zig
+++ b/zig/lib/std/crypto/25519/edwards25519.zig
@@ -4,10 +4,16 @@
// The MIT license requires this copyright notice to be included in all copies
// and substantial portions of the software.
const std = @import("std");
+const crypto = std.crypto;
const debug = std.debug;
const fmt = std.fmt;
const mem = std.mem;
-const Error = std.crypto.Error;
+
+const EncodingError = crypto.errors.EncodingError;
+const IdentityElementError = crypto.errors.IdentityElementError;
+const NonCanonicalError = crypto.errors.NonCanonicalError;
+const NotSquareError = crypto.errors.NotSquareError;
+const WeakPublicKeyError = crypto.errors.WeakPublicKeyError;
/// Group operations over Edwards25519.
pub const Edwards25519 = struct {
@@ -26,7 +32,7 @@ pub const Edwards25519 = struct {
is_base: bool = false,
/// Decode an Edwards25519 point from its compressed (Y+sign) coordinates.
- pub fn fromBytes(s: [encoded_length]u8) Error!Edwards25519 {
+ pub fn fromBytes(s: [encoded_length]u8) EncodingError!Edwards25519 {
const z = Fe.one;
const y = Fe.fromBytes(s);
var u = y.sq();
@@ -56,7 +62,7 @@ pub const Edwards25519 = struct {
}
/// Check that the encoding of a point is canonical.
- pub fn rejectNonCanonical(s: [32]u8) Error!void {
+ pub fn rejectNonCanonical(s: [32]u8) NonCanonicalError!void {
return Fe.rejectNonCanonical(s, true);
}
@@ -69,19 +75,11 @@ pub const Edwards25519 = struct {
.is_base = true,
};
- /// The edwards25519 neutral element.
- pub const neutralElement = Edwards25519{
- .x = Fe{ .limbs = .{ 2251799813685229, 2251799813685247, 2251799813685247, 2251799813685247, 2251799813685247 } },
- .y = Fe{ .limbs = .{ 1507481815385608, 2223447444246085, 1083941587175919, 2059929906842505, 1581435440146976 } },
- .z = Fe{ .limbs = .{ 1507481815385608, 2223447444246085, 1083941587175919, 2059929906842505, 1581435440146976 } },
- .t = Fe{ .limbs = .{ 2251799813685229, 2251799813685247, 2251799813685247, 2251799813685247, 2251799813685247 } },
- .is_base = false,
- };
-
- const identityElement = Edwards25519{ .x = Fe.zero, .y = Fe.one, .z = Fe.one, .t = Fe.zero };
+ pub const neutralElement = @compileError("deprecated: use identityElement instead");
+ pub const identityElement = Edwards25519{ .x = Fe.zero, .y = Fe.one, .z = Fe.one, .t = Fe.zero };
/// Reject the neutral element.
- pub fn rejectIdentity(p: Edwards25519) Error!void {
+ pub fn rejectIdentity(p: Edwards25519) IdentityElementError!void {
if (p.x.isZero()) {
return error.IdentityElement;
}
@@ -154,9 +152,10 @@ pub const Edwards25519 = struct {
return t;
}
- fn nonAdjacentForm(s: [32]u8) [2 * 32]i8 {
+ fn slide(s: [32]u8) [2 * 32]i8 {
+ const reduced = if ((s[s.len - 1] & 0x80) != 0) s else scalar.reduce(s);
var e: [2 * 32]i8 = undefined;
- for (s) |x, i| {
+ for (reduced) |x, i| {
e[i * 2 + 0] = @as(i8, @truncate(u4, x));
e[i * 2 + 1] = @as(i8, @truncate(u4, x >> 4));
}
@@ -177,9 +176,9 @@ pub const Edwards25519 = struct {
// Based on real-world benchmarks, we only use this for multi-scalar multiplication.
// NAF could be useful to half the size of precomputation tables, but we intentionally
// avoid these to keep the standard library lightweight.
- fn pcMul(pc: [9]Edwards25519, s: [32]u8, comptime vartime: bool) Error!Edwards25519 {
+ fn pcMul(pc: [9]Edwards25519, s: [32]u8, comptime vartime: bool) IdentityElementError!Edwards25519 {
std.debug.assert(vartime);
- const e = nonAdjacentForm(s);
+ const e = slide(s);
var q = Edwards25519.identityElement;
var pos: usize = 2 * 32 - 1;
while (true) : (pos -= 1) {
@@ -197,7 +196,7 @@ pub const Edwards25519 = struct {
}
// Scalar multiplication with a 4-bit window and the first 15 multiples.
- fn pcMul16(pc: [16]Edwards25519, s: [32]u8, comptime vartime: bool) Error!Edwards25519 {
+ fn pcMul16(pc: [16]Edwards25519, s: [32]u8, comptime vartime: bool) IdentityElementError!Edwards25519 {
var q = Edwards25519.identityElement;
var pos: usize = 252;
while (true) : (pos -= 4) {
@@ -232,13 +231,18 @@ pub const Edwards25519 = struct {
break :pc precompute(Edwards25519.basePoint, 15);
};
+ const basePointPc8 = comptime pc: {
+ @setEvalBranchQuota(10000);
+ break :pc precompute(Edwards25519.basePoint, 8);
+ };
+
/// Multiply an Edwards25519 point by a scalar without clamping it.
- /// Return error.WeakPublicKey if the resulting point is
- /// the identity element.
- pub fn mul(p: Edwards25519, s: [32]u8) Error!Edwards25519 {
+ /// Return error.WeakPublicKey if the base generates a small-order group,
+ /// and error.IdentityElement if the result is the identity element.
+ pub fn mul(p: Edwards25519, s: [32]u8) (IdentityElementError || WeakPublicKeyError)!Edwards25519 {
const pc = if (p.is_base) basePointPc else pc: {
const xpc = precompute(p, 15);
- xpc[4].rejectIdentity() catch |_| return error.WeakPublicKey;
+ xpc[4].rejectIdentity() catch return error.WeakPublicKey;
break :pc xpc;
};
return pcMul16(pc, s, false);
@@ -246,7 +250,7 @@ pub const Edwards25519 = struct {
/// Multiply an Edwards25519 point by a *PUBLIC* scalar *IN VARIABLE TIME*
/// This can be used for signature verification.
- pub fn mulPublic(p: Edwards25519, s: [32]u8) Error!Edwards25519 {
+ pub fn mulPublic(p: Edwards25519, s: [32]u8) (IdentityElementError || WeakPublicKeyError)!Edwards25519 {
if (p.is_base) {
return pcMul16(basePointPc, s, true);
} else {
@@ -256,14 +260,50 @@ pub const Edwards25519 = struct {
}
}
+ /// Double-base multiplication of public parameters - Compute (p1*s1)+(p2*s2) *IN VARIABLE TIME*
+ /// This can be used for signature verification.
+ pub fn mulDoubleBasePublic(p1: Edwards25519, s1: [32]u8, p2: Edwards25519, s2: [32]u8) (IdentityElementError || WeakPublicKeyError)!Edwards25519 {
+ const pc1 = if (p1.is_base) basePointPc8 else pc: {
+ const xpc = precompute(p1, 8);
+ xpc[4].rejectIdentity() catch return error.WeakPublicKey;
+ break :pc xpc;
+ };
+ const pc2 = if (p2.is_base) basePointPc8 else pc: {
+ const xpc = precompute(p2, 8);
+ xpc[4].rejectIdentity() catch return error.WeakPublicKey;
+ break :pc xpc;
+ };
+ const e1 = slide(s1);
+ const e2 = slide(s2);
+ var q = Edwards25519.identityElement;
+ var pos: usize = 2 * 32 - 1;
+ while (true) : (pos -= 1) {
+ const slot1 = e1[pos];
+ if (slot1 > 0) {
+ q = q.add(pc1[@intCast(usize, slot1)]);
+ } else if (slot1 < 0) {
+ q = q.sub(pc1[@intCast(usize, -slot1)]);
+ }
+ const slot2 = e2[pos];
+ if (slot2 > 0) {
+ q = q.add(pc2[@intCast(usize, slot2)]);
+ } else if (slot2 < 0) {
+ q = q.sub(pc2[@intCast(usize, -slot2)]);
+ }
+ if (pos == 0) break;
+ q = q.dbl().dbl().dbl().dbl();
+ }
+ try q.rejectIdentity();
+ return q;
+ }
+
/// Multiscalar multiplication *IN VARIABLE TIME* for public data
/// Computes ps0*ss0 + ps1*ss1 + ps2*ss2... faster than doing many of these operations individually
- pub fn mulMulti(comptime count: usize, ps: [count]Edwards25519, ss: [count][32]u8) Error!Edwards25519 {
+ pub fn mulMulti(comptime count: usize, ps: [count]Edwards25519, ss: [count][32]u8) (IdentityElementError || WeakPublicKeyError)!Edwards25519 {
var pcs: [count][9]Edwards25519 = undefined;
for (ps) |p, i| {
if (p.is_base) {
- @setEvalBranchQuota(10000);
- pcs[i] = comptime precompute(Edwards25519.basePoint, 8);
+ pcs[i] = basePointPc8;
} else {
pcs[i] = precompute(p, 8);
pcs[i][4].rejectIdentity() catch |_| return error.WeakPublicKey;
@@ -271,7 +311,7 @@ pub const Edwards25519 = struct {
}
var es: [count][2 * 32]i8 = undefined;
for (ss) |s, i| {
- es[i] = nonAdjacentForm(s);
+ es[i] = slide(s);
}
var q = Edwards25519.identityElement;
var pos: usize = 2 * 32 - 1;
@@ -297,14 +337,14 @@ pub const Edwards25519 = struct {
/// This is strongly recommended for DH operations.
/// Return error.WeakPublicKey if the resulting point is
/// the identity element.
- pub fn clampedMul(p: Edwards25519, s: [32]u8) Error!Edwards25519 {
+ pub fn clampedMul(p: Edwards25519, s: [32]u8) (IdentityElementError || WeakPublicKeyError)!Edwards25519 {
var t: [32]u8 = s;
scalar.clamp(&t);
return mul(p, t);
}
// montgomery -- recover y = sqrt(x^3 + A*x^2 + x)
- fn xmontToYmont(x: Fe) Error!Fe {
+ fn xmontToYmont(x: Fe) NotSquareError!Fe {
var x2 = x.sq();
const x3 = x.mul(x2);
x2 = x2.mul32(Fe.edwards25519a_32);
@@ -367,7 +407,7 @@ pub const Edwards25519 = struct {
fn stringToPoints(comptime n: usize, ctx: []const u8, s: []const u8) [n]Edwards25519 {
debug.assert(n <= 2);
- const H = std.crypto.hash.sha2.Sha512;
+ const H = crypto.hash.sha2.Sha512;
const h_l: usize = 48;
var xctx = ctx;
var hctx: [H.digest_length]u8 = undefined;
@@ -485,8 +525,8 @@ test "edwards25519 packing/unpacking" {
test "edwards25519 point addition/substraction" {
var s1: [32]u8 = undefined;
var s2: [32]u8 = undefined;
- std.crypto.random.bytes(&s1);
- std.crypto.random.bytes(&s2);
+ crypto.random.bytes(&s1);
+ crypto.random.bytes(&s2);
const p = try Edwards25519.basePoint.clampedMul(s1);
const q = try Edwards25519.basePoint.clampedMul(s2);
const r = p.add(q).add(q).sub(q).sub(q);
diff --git a/zig/lib/std/crypto/25519/field.zig b/zig/lib/std/crypto/25519/field.zig
index b570e2d06b..3378191451 100644
--- a/zig/lib/std/crypto/25519/field.zig
+++ b/zig/lib/std/crypto/25519/field.zig
@@ -4,9 +4,12 @@
// The MIT license requires this copyright notice to be included in all copies
// and substantial portions of the software.
const std = @import("std");
+const crypto = std.crypto;
const readIntLittle = std.mem.readIntLittle;
const writeIntLittle = std.mem.writeIntLittle;
-const Error = std.crypto.Error;
+
+const NonCanonicalError = crypto.errors.NonCanonicalError;
+const NotSquareError = crypto.errors.NotSquareError;
pub const Fe = struct {
limbs: [5]u64,
@@ -113,7 +116,7 @@ pub const Fe = struct {
}
/// Reject non-canonical encodings of an element, possibly ignoring the top bit
- pub fn rejectNonCanonical(s: [32]u8, comptime ignore_extra_bit: bool) Error!void {
+ pub fn rejectNonCanonical(s: [32]u8, comptime ignore_extra_bit: bool) NonCanonicalError!void {
var c: u16 = (s[31] & 0x7f) ^ 0x7f;
comptime var i = 30;
inline while (i > 0) : (i -= 1) {
@@ -289,7 +292,7 @@ pub const Fe = struct {
return _carry128(&r);
}
- fn _sq(a: Fe, double: comptime bool) callconv(.Inline) Fe {
+ fn _sq(a: Fe, comptime double: bool) callconv(.Inline) Fe {
var ax: [5]u128 = undefined;
var r: [5]u128 = undefined;
comptime var i = 0;
@@ -352,7 +355,7 @@ pub const Fe = struct {
return fe;
}
- /// Compute the inverse of a field element
+ /// Return the inverse of a field element, or 0 if a=0.
pub fn invert(a: Fe) Fe {
var t0 = a.sq();
var t1 = t0.sqn(2).mul(a);
@@ -413,7 +416,7 @@ pub const Fe = struct {
}
/// Compute the square root of `x2`, returning `error.NotSquare` if `x2` was not a square
- pub fn sqrt(x2: Fe) Error!Fe {
+ pub fn sqrt(x2: Fe) NotSquareError!Fe {
var x2_copy = x2;
const x = x2.uncheckedSqrt();
const check = x.sq().sub(x2_copy);
diff --git a/zig/lib/std/crypto/25519/ristretto255.zig b/zig/lib/std/crypto/25519/ristretto255.zig
index 4644b7622e..50f1580a80 100644
--- a/zig/lib/std/crypto/25519/ristretto255.zig
+++ b/zig/lib/std/crypto/25519/ristretto255.zig
@@ -5,7 +5,11 @@
// and substantial portions of the software.
const std = @import("std");
const fmt = std.fmt;
-const Error = std.crypto.Error;
+
+const EncodingError = std.crypto.errors.EncodingError;
+const IdentityElementError = std.crypto.errors.IdentityElementError;
+const NonCanonicalError = std.crypto.errors.NonCanonicalError;
+const WeakPublicKeyError = std.crypto.errors.WeakPublicKeyError;
/// Group operations over Edwards25519.
pub const Ristretto255 = struct {
@@ -35,7 +39,7 @@ pub const Ristretto255 = struct {
return .{ .ratio_is_square = @boolToInt(has_m_root) | @boolToInt(has_p_root), .root = x.abs() };
}
- fn rejectNonCanonical(s: [encoded_length]u8) Error!void {
+ fn rejectNonCanonical(s: [encoded_length]u8) NonCanonicalError!void {
if ((s[0] & 1) != 0) {
return error.NonCanonical;
}
@@ -43,7 +47,7 @@ pub const Ristretto255 = struct {
}
/// Reject the neutral element.
- pub fn rejectIdentity(p: Ristretto255) callconv(.Inline) Error!void {
+ pub fn rejectIdentity(p: Ristretto255) callconv(.Inline) IdentityElementError!void {
return p.p.rejectIdentity();
}
@@ -51,7 +55,7 @@ pub const Ristretto255 = struct {
pub const basePoint = Ristretto255{ .p = Curve.basePoint };
/// Decode a Ristretto255 representative.
- pub fn fromBytes(s: [encoded_length]u8) Error!Ristretto255 {
+ pub fn fromBytes(s: [encoded_length]u8) (NonCanonicalError || EncodingError)!Ristretto255 {
try rejectNonCanonical(s);
const s_ = Fe.fromBytes(s);
const ss = s_.sq(); // s^2
@@ -154,7 +158,7 @@ pub const Ristretto255 = struct {
/// Multiply a Ristretto255 element with a scalar.
/// Return error.WeakPublicKey if the resulting element is
/// the identity element.
- pub fn mul(p: Ristretto255, s: [encoded_length]u8) callconv(.Inline) Error!Ristretto255 {
+ pub fn mul(p: Ristretto255, s: [encoded_length]u8) callconv(.Inline) (IdentityElementError || WeakPublicKeyError)!Ristretto255 {
return Ristretto255{ .p = try p.p.mul(s) };
}
diff --git a/zig/lib/std/crypto/25519/scalar.zig b/zig/lib/std/crypto/25519/scalar.zig
index a4bf5aafcf..e8564ff577 100644
--- a/zig/lib/std/crypto/25519/scalar.zig
+++ b/zig/lib/std/crypto/25519/scalar.zig
@@ -5,7 +5,8 @@
// and substantial portions of the software.
const std = @import("std");
const mem = std.mem;
-const Error = std.crypto.Error;
+
+const NonCanonicalError = std.crypto.errors.NonCanonicalError;
/// 2^252 + 27742317777372353535851937790883648493
pub const field_size = [32]u8{
@@ -19,7 +20,7 @@ pub const CompressedScalar = [32]u8;
pub const zero = [_]u8{0} ** 32;
/// Reject a scalar whose encoding is not canonical.
-pub fn rejectNonCanonical(s: [32]u8) Error!void {
+pub fn rejectNonCanonical(s: [32]u8) NonCanonicalError!void {
var c: u8 = 0;
var n: u8 = 1;
var i: usize = 31;
@@ -97,7 +98,7 @@ pub fn sub(a: [32]u8, b: [32]u8) [32]u8 {
return add(a, neg(b));
}
-/// A scalar in unpacked reprentation
+/// A scalar in unpacked representation
pub const Scalar = struct {
const Limbs = [5]u64;
limbs: Limbs = undefined,
diff --git a/zig/lib/std/crypto/25519/x25519.zig b/zig/lib/std/crypto/25519/x25519.zig
index 2d53124056..07b1dc7a86 100644
--- a/zig/lib/std/crypto/25519/x25519.zig
+++ b/zig/lib/std/crypto/25519/x25519.zig
@@ -9,7 +9,10 @@ const mem = std.mem;
const fmt = std.fmt;
const Sha512 = crypto.hash.sha2.Sha512;
-const Error = crypto.Error;
+
+const EncodingError = crypto.errors.EncodingError;
+const IdentityElementError = crypto.errors.IdentityElementError;
+const WeakPublicKeyError = crypto.errors.WeakPublicKeyError;
/// X25519 DH function.
pub const X25519 = struct {
@@ -32,7 +35,7 @@ pub const X25519 = struct {
secret_key: [secret_length]u8,
/// Create a new key pair using an optional seed.
- pub fn create(seed: ?[seed_length]u8) Error!KeyPair {
+ pub fn create(seed: ?[seed_length]u8) IdentityElementError!KeyPair {
const sk = seed orelse sk: {
var random_seed: [seed_length]u8 = undefined;
crypto.random.bytes(&random_seed);
@@ -45,7 +48,7 @@ pub const X25519 = struct {
}
/// Create a key pair from an Ed25519 key pair
- pub fn fromEd25519(ed25519_key_pair: crypto.sign.Ed25519.KeyPair) Error!KeyPair {
+ pub fn fromEd25519(ed25519_key_pair: crypto.sign.Ed25519.KeyPair) (IdentityElementError || EncodingError)!KeyPair {
const seed = ed25519_key_pair.secret_key[0..32];
var az: [Sha512.digest_length]u8 = undefined;
Sha512.hash(seed, &az, .{});
@@ -60,13 +63,13 @@ pub const X25519 = struct {
};
/// Compute the public key for a given private key.
- pub fn recoverPublicKey(secret_key: [secret_length]u8) Error![public_length]u8 {
+ pub fn recoverPublicKey(secret_key: [secret_length]u8) IdentityElementError![public_length]u8 {
const q = try Curve.basePoint.clampedMul(secret_key);
return q.toBytes();
}
/// Compute the X25519 equivalent to an Ed25519 public eky.
- pub fn publicKeyFromEd25519(ed25519_public_key: [crypto.sign.Ed25519.public_length]u8) Error![public_length]u8 {
+ pub fn publicKeyFromEd25519(ed25519_public_key: [crypto.sign.Ed25519.public_length]u8) (IdentityElementError || EncodingError)![public_length]u8 {
const pk_ed = try crypto.ecc.Edwards25519.fromBytes(ed25519_public_key);
const pk = try Curve.fromEdwards25519(pk_ed);
return pk.toBytes();
@@ -75,7 +78,7 @@ pub const X25519 = struct {
/// Compute the scalar product of a public key and a secret scalar.
/// Note that the output should not be used as a shared secret without
/// hashing it first.
- pub fn scalarmult(secret_key: [secret_length]u8, public_key: [public_length]u8) Error![shared_length]u8 {
+ pub fn scalarmult(secret_key: [secret_length]u8, public_key: [public_length]u8) IdentityElementError![shared_length]u8 {
const q = try Curve.fromBytes(public_key).clampedMul(secret_key);
return q.toBytes();
}
diff --git a/zig/lib/std/crypto/aegis.zig b/zig/lib/std/crypto/aegis.zig
index 3969d59e10..59dcf04dac 100644
--- a/zig/lib/std/crypto/aegis.zig
+++ b/zig/lib/std/crypto/aegis.zig
@@ -8,7 +8,7 @@ const std = @import("std");
const mem = std.mem;
const assert = std.debug.assert;
const AesBlock = std.crypto.core.aes.Block;
-const Error = std.crypto.Error;
+const AuthenticationError = std.crypto.errors.AuthenticationError;
const State128L = struct {
blocks: [8]AesBlock,
@@ -137,7 +137,7 @@ pub const Aegis128L = struct {
/// ad: Associated Data
/// npub: public nonce
/// k: private key
- pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) Error!void {
+ pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) AuthenticationError!void {
assert(c.len == m.len);
var state = State128L.init(key, npub);
var src: [32]u8 align(16) = undefined;
@@ -299,7 +299,7 @@ pub const Aegis256 = struct {
/// ad: Associated Data
/// npub: public nonce
/// k: private key
- pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) Error!void {
+ pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) AuthenticationError!void {
assert(c.len == m.len);
var state = State256.init(key, npub);
var src: [16]u8 align(16) = undefined;
diff --git a/zig/lib/std/crypto/aes_gcm.zig b/zig/lib/std/crypto/aes_gcm.zig
index bcb1b4c5fa..70746af073 100644
--- a/zig/lib/std/crypto/aes_gcm.zig
+++ b/zig/lib/std/crypto/aes_gcm.zig
@@ -12,7 +12,7 @@ const debug = std.debug;
const Ghash = std.crypto.onetimeauth.Ghash;
const mem = std.mem;
const modes = crypto.core.modes;
-const Error = crypto.Error;
+const AuthenticationError = crypto.errors.AuthenticationError;
pub const Aes128Gcm = AesGcm(crypto.core.aes.Aes128);
pub const Aes256Gcm = AesGcm(crypto.core.aes.Aes256);
@@ -60,7 +60,7 @@ fn AesGcm(comptime Aes: anytype) type {
}
}
- pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) Error!void {
+ pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) AuthenticationError!void {
assert(c.len == m.len);
const aes = Aes.initEnc(key);
diff --git a/zig/lib/std/crypto/aes_ocb.zig b/zig/lib/std/crypto/aes_ocb.zig
index 9eb0561d9f..658b3b97ce 100644
--- a/zig/lib/std/crypto/aes_ocb.zig
+++ b/zig/lib/std/crypto/aes_ocb.zig
@@ -10,7 +10,7 @@ const aes = crypto.core.aes;
const assert = std.debug.assert;
const math = std.math;
const mem = std.mem;
-const Error = crypto.Error;
+const AuthenticationError = crypto.errors.AuthenticationError;
pub const Aes128Ocb = AesOcb(aes.Aes128);
pub const Aes256Ocb = AesOcb(aes.Aes256);
@@ -179,7 +179,7 @@ fn AesOcb(comptime Aes: anytype) type {
/// ad: Associated Data
/// npub: public nonce
/// k: secret key
- pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) Error!void {
+ pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) AuthenticationError!void {
assert(c.len == m.len);
const aes_enc_ctx = Aes.initEnc(key);
diff --git a/zig/lib/std/crypto/bcrypt.zig b/zig/lib/std/crypto/bcrypt.zig
index d00108b9c4..51fb144b2f 100644
--- a/zig/lib/std/crypto/bcrypt.zig
+++ b/zig/lib/std/crypto/bcrypt.zig
@@ -12,7 +12,8 @@ const mem = std.mem;
const debug = std.debug;
const testing = std.testing;
const utils = crypto.utils;
-const Error = crypto.Error;
+const EncodingError = crypto.errors.EncodingError;
+const PasswordVerificationError = crypto.errors.PasswordVerificationError;
const salt_length: usize = 16;
const salt_str_length: usize = 22;
@@ -179,7 +180,7 @@ const Codec = struct {
debug.assert(j == b64.len);
}
- fn decode(bin: []u8, b64: []const u8) Error!void {
+ fn decode(bin: []u8, b64: []const u8) EncodingError!void {
var i: usize = 0;
var j: usize = 0;
while (j < bin.len) {
@@ -204,7 +205,7 @@ const Codec = struct {
}
};
-fn strHashInternal(password: []const u8, rounds_log: u6, salt: [salt_length]u8) Error![hash_length]u8 {
+fn strHashInternal(password: []const u8, rounds_log: u6, salt: [salt_length]u8) ![hash_length]u8 {
var state = State{};
var password_buf: [73]u8 = undefined;
const trimmed_len = math.min(password.len, password_buf.len - 1);
@@ -252,14 +253,14 @@ fn strHashInternal(password: []const u8, rounds_log: u6, salt: [salt_length]u8)
/// IMPORTANT: by design, bcrypt silently truncates passwords to 72 bytes.
/// If this is an issue for your application, hash the password first using a function such as SHA-512,
/// and then use the resulting hash as the password parameter for bcrypt.
-pub fn strHash(password: []const u8, rounds_log: u6) Error![hash_length]u8 {
+pub fn strHash(password: []const u8, rounds_log: u6) ![hash_length]u8 {
var salt: [salt_length]u8 = undefined;
crypto.random.bytes(&salt);
return strHashInternal(password, rounds_log, salt);
}
/// Verify that a previously computed hash is valid for a given password.
-pub fn strVerify(h: [hash_length]u8, password: []const u8) Error!void {
+pub fn strVerify(h: [hash_length]u8, password: []const u8) (EncodingError || PasswordVerificationError)!void {
if (!mem.eql(u8, "$2", h[0..2])) return error.InvalidEncoding;
if (h[3] != '$' or h[6] != '$') return error.InvalidEncoding;
const rounds_log_str = h[4..][0..2];
diff --git a/zig/lib/std/crypto/chacha20.zig b/zig/lib/std/crypto/chacha20.zig
index e1fe3e232d..ea9eafd356 100644
--- a/zig/lib/std/crypto/chacha20.zig
+++ b/zig/lib/std/crypto/chacha20.zig
@@ -13,7 +13,7 @@ const testing = std.testing;
const maxInt = math.maxInt;
const Vector = std.meta.Vector;
const Poly1305 = std.crypto.onetimeauth.Poly1305;
-const Error = std.crypto.Error;
+const AuthenticationError = std.crypto.errors.AuthenticationError;
/// IETF-variant of the ChaCha20 stream cipher, as designed for TLS.
pub const ChaCha20IETF = ChaChaIETF(20);
@@ -521,7 +521,7 @@ fn ChaChaPoly1305(comptime rounds_nb: usize) type {
/// npub: public nonce
/// k: private key
/// NOTE: the check of the authentication tag is currently not done in constant time
- pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, k: [key_length]u8) Error!void {
+ pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, k: [key_length]u8) AuthenticationError!void {
assert(c.len == m.len);
var polyKey = [_]u8{0} ** 32;
@@ -583,7 +583,7 @@ fn XChaChaPoly1305(comptime rounds_nb: usize) type {
/// ad: Associated Data
/// npub: public nonce
/// k: private key
- pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, k: [key_length]u8) Error!void {
+ pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, k: [key_length]u8) AuthenticationError!void {
const extended = extend(k, npub, rounds_nb);
return ChaChaPoly1305(rounds_nb).decrypt(m, c, tag, ad, extended.nonce, extended.key);
}
diff --git a/zig/lib/std/crypto/error.zig b/zig/lib/std/crypto/error.zig
deleted file mode 100644
index 4cb12bb8f7..0000000000
--- a/zig/lib/std/crypto/error.zig
+++ /dev/null
@@ -1,34 +0,0 @@
-pub const Error = error{
- /// MAC verification failed - The tag doesn't verify for the given ciphertext and secret key
- AuthenticationFailed,
-
- /// The requested output length is too long for the chosen algorithm
- OutputTooLong,
-
- /// Finite field operation returned the identity element
- IdentityElement,
-
- /// Encoded input cannot be decoded
- InvalidEncoding,
-
- /// The signature does't verify for the given message and public key
- SignatureVerificationFailed,
-
- /// Both a public and secret key have been provided, but they are incompatible
- KeyMismatch,
-
- /// Encoded input is not in canonical form
- NonCanonical,
-
- /// Square root has no solutions
- NotSquare,
-
- /// Verification string doesn't match the provided password and parameters
- PasswordVerificationFailed,
-
- /// Parameters would be insecure to use
- WeakParameters,
-
- /// Public key would be insecure to use
- WeakPublicKey,
-};
diff --git a/zig/lib/std/crypto/errors.zig b/zig/lib/std/crypto/errors.zig
new file mode 100644
index 0000000000..4d79055919
--- /dev/null
+++ b/zig/lib/std/crypto/errors.zig
@@ -0,0 +1,35 @@
+/// MAC verification failed - The tag doesn't verify for the given ciphertext and secret key
+pub const AuthenticationError = error{AuthenticationFailed};
+
+/// The requested output length is too long for the chosen algorithm
+pub const OutputTooLongError = error{OutputTooLong};
+
+/// Finite field operation returned the identity element
+pub const IdentityElementError = error{IdentityElement};
+
+/// Encoded input cannot be decoded
+pub const EncodingError = error{InvalidEncoding};
+
+/// The signature does't verify for the given message and public key
+pub const SignatureVerificationError = error{SignatureVerificationFailed};
+
+/// Both a public and secret key have been provided, but they are incompatible
+pub const KeyMismatchError = error{KeyMismatch};
+
+/// Encoded input is not in canonical form
+pub const NonCanonicalError = error{NonCanonical};
+
+/// Square root has no solutions
+pub const NotSquareError = error{NotSquare};
+
+/// Verification string doesn't match the provided password and parameters
+pub const PasswordVerificationError = error{PasswordVerificationFailed};
+
+/// Parameters would be insecure to use
+pub const WeakParametersError = error{WeakParameters};
+
+/// Public key would be insecure to use
+pub const WeakPublicKeyError = error{WeakPublicKey};
+
+/// Any error related to cryptography operations
+pub const Error = AuthenticationError || OutputTooLongError || IdentityElementError || EncodingError || SignatureVerificationError || KeyMismatchError || NonCanonicalError || NotSquareError || PasswordVerificationError || WeakParametersError || WeakPublicKeyError;
diff --git a/zig/lib/std/crypto/gimli.zig b/zig/lib/std/crypto/gimli.zig
index 111e0c5274..fb67c25343 100644
--- a/zig/lib/std/crypto/gimli.zig
+++ b/zig/lib/std/crypto/gimli.zig
@@ -20,7 +20,7 @@ const assert = std.debug.assert;
const testing = std.testing;
const htest = @import("test.zig");
const Vector = std.meta.Vector;
-const Error = std.crypto.Error;
+const AuthenticationError = std.crypto.errors.AuthenticationError;
pub const State = struct {
pub const BLOCKBYTES = 48;
@@ -393,7 +393,7 @@ pub const Aead = struct {
/// npub: public nonce
/// k: private key
/// NOTE: the check of the authentication tag is currently not done in constant time
- pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, k: [key_length]u8) Error!void {
+ pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, k: [key_length]u8) AuthenticationError!void {
assert(c.len == m.len);
var state = Aead.init(ad, npub, k);
diff --git a/zig/lib/std/crypto/isap.zig b/zig/lib/std/crypto/isap.zig
index 5219742d85..6deb4977bb 100644
--- a/zig/lib/std/crypto/isap.zig
+++ b/zig/lib/std/crypto/isap.zig
@@ -3,7 +3,7 @@ const debug = std.debug;
const mem = std.mem;
const math = std.math;
const testing = std.testing;
-const Error = std.crypto.Error;
+const AuthenticationError = std.crypto.errors.AuthenticationError;
/// ISAPv2 is an authenticated encryption system hardened against side channels and fault attacks.
/// https://csrc.nist.gov/CSRC/media/Projects/lightweight-cryptography/documents/round-2/spec-doc-rnd2/isap-spec-round2.pdf
@@ -218,7 +218,7 @@ pub const IsapA128A = struct {
tag.* = mac(c, ad, npub, key);
}
- pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) Error!void {
+ pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) AuthenticationError!void {
var computed_tag = mac(c, ad, npub, key);
var acc: u8 = 0;
for (computed_tag) |_, j| {
diff --git a/zig/lib/std/crypto/pbkdf2.zig b/zig/lib/std/crypto/pbkdf2.zig
index 575fb83006..f93a5235af 100644
--- a/zig/lib/std/crypto/pbkdf2.zig
+++ b/zig/lib/std/crypto/pbkdf2.zig
@@ -7,7 +7,8 @@
const std = @import("std");
const mem = std.mem;
const maxInt = std.math.maxInt;
-const Error = std.crypto.Error;
+const OutputTooLongError = std.crypto.errors.OutputTooLongError;
+const WeakParametersError = std.crypto.errors.WeakParametersError;
// RFC 2898 Section 5.2
//
@@ -55,7 +56,7 @@ const Error = std.crypto.Error;
/// the dk. It is common to tune this parameter to achieve approximately 100ms.
///
/// Prf: Pseudo-random function to use. A common choice is `std.crypto.auth.hmac.HmacSha256`.
-pub fn pbkdf2(dk: []u8, password: []const u8, salt: []const u8, rounds: u32, comptime Prf: type) Error!void {
+pub fn pbkdf2(dk: []u8, password: []const u8, salt: []const u8, rounds: u32, comptime Prf: type) (WeakParametersError || OutputTooLongError)!void {
if (rounds < 1) return error.WeakParameters;
const dk_len = dk.len;
diff --git a/zig/lib/std/crypto/pcurves/common.zig b/zig/lib/std/crypto/pcurves/common.zig
new file mode 100644
index 0000000000..5a979fe3e5
--- /dev/null
+++ b/zig/lib/std/crypto/pcurves/common.zig
@@ -0,0 +1,284 @@
+const std = @import("std");
+const builtin = std.builtin;
+const crypto = std.crypto;
+const debug = std.debug;
+const mem = std.mem;
+const meta = std.meta;
+
+const NonCanonicalError = crypto.errors.NonCanonicalError;
+const NotSquareError = crypto.errors.NotSquareError;
+
+/// Parameters to create a finite field type.
+pub const FieldParams = struct {
+ fiat: type,
+ field_order: comptime_int,
+ field_bits: comptime_int,
+ saturated_bits: comptime_int,
+ encoded_length: comptime_int,
+};
+
+/// A field element, internally stored in Montgomery domain.
+pub fn Field(comptime params: FieldParams) type {
+ const fiat = params.fiat;
+ const Limbs = fiat.Limbs;
+
+ return struct {
+ const Fe = @This();
+
+ limbs: Limbs,
+
+ /// Field size.
+ pub const field_order = params.field_order;
+
+ /// Number of bits to represent the set of all elements.
+ pub const field_bits = params.field_bits;
+
+ /// Number of bits that can be saturated without overflowing.
+ pub const saturated_bits = params.saturated_bits;
+
+ /// Number of bytes required to encode an element.
+ pub const encoded_length = params.encoded_length;
+
+ /// Zero.
+ pub const zero: Fe = Fe{ .limbs = mem.zeroes(Limbs) };
+
+ /// One.
+ pub const one = comptime one: {
+ var fe: Fe = undefined;
+ fiat.setOne(&fe.limbs);
+ break :one fe;
+ };
+
+ /// Reject non-canonical encodings of an element.
+ pub fn rejectNonCanonical(s_: [encoded_length]u8, endian: builtin.Endian) NonCanonicalError!void {
+ var s = if (endian == .Little) s_ else orderSwap(s_);
+ const field_order_s = comptime fos: {
+ var fos: [encoded_length]u8 = undefined;
+ mem.writeIntLittle(std.meta.Int(.unsigned, encoded_length * 8), &fos, field_order);
+ break :fos fos;
+ };
+ if (crypto.utils.timingSafeCompare(u8, &s, &field_order_s, .Little) != .lt) {
+ return error.NonCanonical;
+ }
+ }
+
+ /// Swap the endianness of an encoded element.
+ pub fn orderSwap(s: [encoded_length]u8) [encoded_length]u8 {
+ var t = s;
+ for (s) |x, i| t[t.len - 1 - i] = x;
+ return t;
+ }
+
+ /// Unpack a field element.
+ pub fn fromBytes(s_: [encoded_length]u8, endian: builtin.Endian) NonCanonicalError!Fe {
+ var s = if (endian == .Little) s_ else orderSwap(s_);
+ try rejectNonCanonical(s, .Little);
+ var limbs_z: Limbs = undefined;
+ fiat.fromBytes(&limbs_z, s);
+ var limbs: Limbs = undefined;
+ fiat.toMontgomery(&limbs, limbs_z);
+ return Fe{ .limbs = limbs };
+ }
+
+ /// Pack a field element.
+ pub fn toBytes(fe: Fe, endian: builtin.Endian) [encoded_length]u8 {
+ var limbs_z: Limbs = undefined;
+ fiat.fromMontgomery(&limbs_z, fe.limbs);
+ var s: [encoded_length]u8 = undefined;
+ fiat.toBytes(&s, limbs_z);
+ return if (endian == .Little) s else orderSwap(s);
+ }
+
+ /// Element as an integer.
+ pub const IntRepr = meta.Int(.unsigned, params.field_bits);
+
+ /// Create a field element from an integer.
+ pub fn fromInt(comptime x: IntRepr) NonCanonicalError!Fe {
+ var s: [encoded_length]u8 = undefined;
+ mem.writeIntLittle(IntRepr, &s, x);
+ return fromBytes(s, .Little);
+ }
+
+ /// Return the field element as an integer.
+ pub fn toInt(fe: Fe) IntRepr {
+ const s = fe.toBytes(.Little);
+ return mem.readIntLittle(IntRepr, &s);
+ }
+
+ /// Return true if the field element is zero.
+ pub fn isZero(fe: Fe) bool {
+ var z: @TypeOf(fe.limbs[0]) = undefined;
+ fiat.nonzero(&z, fe.limbs);
+ return z == 0;
+ }
+
+ /// Return true if both field elements are equivalent.
+ pub fn equivalent(a: Fe, b: Fe) bool {
+ return a.sub(b).isZero();
+ }
+
+ /// Return true if the element is odd.
+ pub fn isOdd(fe: Fe) bool {
+ const s = fe.toBytes(.Little);
+ return @truncate(u1, s[0]) != 0;
+ }
+
+ /// Conditonally replace a field element with `a` if `c` is positive.
+ pub fn cMov(fe: *Fe, a: Fe, c: u1) void {
+ fiat.selectznz(&fe.limbs, c, fe.limbs, a.limbs);
+ }
+
+ /// Add field elements.
+ pub fn add(a: Fe, b: Fe) Fe {
+ var fe: Fe = undefined;
+ fiat.add(&fe.limbs, a.limbs, b.limbs);
+ return fe;
+ }
+
+ /// Subtract field elements.
+ pub fn sub(a: Fe, b: Fe) Fe {
+ var fe: Fe = undefined;
+ fiat.sub(&fe.limbs, a.limbs, b.limbs);
+ return fe;
+ }
+
+ /// Double a field element.
+ pub fn dbl(a: Fe) Fe {
+ var fe: Fe = undefined;
+ fiat.add(&fe.limbs, a.limbs, a.limbs);
+ return fe;
+ }
+
+ /// Multiply field elements.
+ pub fn mul(a: Fe, b: Fe) Fe {
+ var fe: Fe = undefined;
+ fiat.mul(&fe.limbs, a.limbs, b.limbs);
+ return fe;
+ }
+
+ /// Square a field element.
+ pub fn sq(a: Fe) Fe {
+ var fe: Fe = undefined;
+ fiat.square(&fe.limbs, a.limbs);
+ return fe;
+ }
+
+ /// Square a field element n times.
+ fn sqn(a: Fe, comptime n: comptime_int) Fe {
+ var i: usize = 0;
+ var fe = a;
+ while (i < n) : (i += 1) {
+ fe = fe.sq();
+ }
+ return fe;
+ }
+
+ /// Compute a^n.
+ pub fn pow(a: Fe, comptime T: type, comptime n: T) Fe {
+ var fe = one;
+ var x: T = n;
+ var t = a;
+ while (true) {
+ if (@truncate(u1, x) != 0) fe = fe.mul(t);
+ x >>= 1;
+ if (x == 0) break;
+ t = t.sq();
+ }
+ return fe;
+ }
+
+ /// Negate a field element.
+ pub fn neg(a: Fe) Fe {
+ var fe: Fe = undefined;
+ fiat.opp(&fe.limbs, a.limbs);
+ return fe;
+ }
+
+ /// Return the inverse of a field element, or 0 if a=0.
+ // Field inversion from https://eprint.iacr.org/2021/549.pdf
+ pub fn invert(a: Fe) Fe {
+ const iterations = (49 * field_bits + 57) / 17;
+ const Word = @TypeOf(a.limbs[0]);
+ const XLimbs = [a.limbs.len + 1]Word;
+
+ var d: Word = 1;
+ var f: XLimbs = undefined;
+ fiat.msat(&f);
+
+ var g: XLimbs = undefined;
+ fiat.fromMontgomery(g[0..a.limbs.len], a.limbs);
+ g[g.len - 1] = 0;
+
+ var r: Limbs = undefined;
+ fiat.setOne(&r);
+ var v = mem.zeroes(Limbs);
+
+ var precomp: Limbs = undefined;
+ fiat.divstepPrecomp(&precomp);
+
+ var out1: Word = undefined;
+ var out2: XLimbs = undefined;
+ var out3: XLimbs = undefined;
+ var out4: Limbs = undefined;
+ var out5: Limbs = undefined;
+
+ var i: usize = 0;
+ while (i < iterations - iterations % 2) : (i += 2) {
+ fiat.divstep(&out1, &out2, &out3, &out4, &out5, d, f, g, v, r);
+ fiat.divstep(&d, &f, &g, &v, &r, out1, out2, out3, out4, out5);
+ }
+ if (iterations % 2 != 0) {
+ fiat.divstep(&out1, &out2, &out3, &out4, &out5, d, f, g, v, r);
+ mem.copy(Word, &v, &out4);
+ mem.copy(Word, &f, &out2);
+ }
+ var v_opp: Limbs = undefined;
+ fiat.opp(&v_opp, v);
+ fiat.selectznz(&v, @truncate(u1, f[f.len - 1] >> (meta.bitCount(Word) - 1)), v, v_opp);
+ var fe: Fe = undefined;
+ fiat.mul(&fe.limbs, v, precomp);
+ return fe;
+ }
+
+ /// Return true if the field element is a square.
+ pub fn isSquare(x2: Fe) bool {
+ if (field_order == 115792089210356248762697446949407573530086143415290314195533631308867097853951) {
+ const t110 = x2.mul(x2.sq()).sq();
+ const t111 = x2.mul(t110);
+ const t111111 = t111.mul(x2.mul(t110).sqn(3));
+ const x15 = t111111.sqn(6).mul(t111111).sqn(3).mul(t111);
+ const x16 = x15.sq().mul(x2);
+ const x53 = x16.sqn(16).mul(x16).sqn(15);
+ const x47 = x15.mul(x53);
+ const ls = x47.mul(((x53.sqn(17).mul(x2)).sqn(143).mul(x47)).sqn(47)).sq().mul(x2);
+ return ls.equivalent(Fe.one);
+ } else {
+ const ls = x2.pow(std.meta.Int(.unsigned, field_bits), (field_order - 1) / 2); // Legendre symbol
+ return ls.equivalent(Fe.one);
+ }
+ }
+
+ // x=x2^((field_order+1)/4) w/ field order=3 (mod 4).
+ fn uncheckedSqrt(x2: Fe) Fe {
+ comptime debug.assert(field_order % 4 == 3);
+ if (field_order == 115792089210356248762697446949407573530086143415290314195533631308867097853951) {
+ const t11 = x2.mul(x2.sq());
+ const t1111 = t11.mul(t11.sqn(2));
+ const t11111111 = t1111.mul(t1111.sqn(4));
+ const x16 = t11111111.sqn(8).mul(t11111111);
+ return x16.sqn(16).mul(x16).sqn(32).mul(x2).sqn(96).mul(x2).sqn(94);
+ } else {
+ return x2.pow(std.meta.Int(.unsigned, field_bits), (field_order + 1) / 4);
+ }
+ }
+
+ /// Compute the square root of `x2`, returning `error.NotSquare` if `x2` was not a square.
+ pub fn sqrt(x2: Fe) NotSquareError!Fe {
+ const x = x2.uncheckedSqrt();
+ if (x.sq().equivalent(x2)) {
+ return x;
+ }
+ return error.NotSquare;
+ }
+ };
+}
diff --git a/zig/lib/std/crypto/pcurves/p256.zig b/zig/lib/std/crypto/pcurves/p256.zig
new file mode 100644
index 0000000000..0b1c584fa9
--- /dev/null
+++ b/zig/lib/std/crypto/pcurves/p256.zig
@@ -0,0 +1,412 @@
+// SPDX-License-Identifier: MIT
+// Copyright (c) 2015-2021 Zig Contributors
+// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
+// The MIT license requires this copyright notice to be included in all copies
+// and substantial portions of the software.
+
+const std = @import("std");
+const builtin = std.builtin;
+const crypto = std.crypto;
+const mem = std.mem;
+const meta = std.meta;
+
+const EncodingError = crypto.errors.EncodingError;
+const IdentityElementError = crypto.errors.IdentityElementError;
+const NonCanonicalError = crypto.errors.NonCanonicalError;
+const NotSquareError = crypto.errors.NotSquareError;
+
+/// Group operations over P256.
+pub const P256 = struct {
+ /// The underlying prime field.
+ pub const Fe = @import("p256/field.zig").Fe;
+ /// Field arithmetic mod the order of the main subgroup.
+ pub const scalar = @import("p256/scalar.zig");
+
+ x: Fe,
+ y: Fe,
+ z: Fe = Fe.one,
+
+ is_base: bool = false,
+
+ /// The P256 base point.
+ pub const basePoint = P256{
+ .x = try Fe.fromInt(48439561293906451759052585252797914202762949526041747995844080717082404635286),
+ .y = try Fe.fromInt(36134250956749795798585127919587881956611106672985015071877198253568414405109),
+ .z = Fe.one,
+ .is_base = true,
+ };
+
+ /// The P256 neutral element.
+ pub const identityElement = P256{ .x = Fe.zero, .y = Fe.one, .z = Fe.zero };
+
+ pub const B = try Fe.fromInt(41058363725152142129326129780047268409114441015993725554835256314039467401291);
+
+ /// Reject the neutral element.
+ pub fn rejectIdentity(p: P256) IdentityElementError!void {
+ if (p.x.isZero()) {
+ return error.IdentityElement;
+ }
+ }
+
+ /// Create a point from affine coordinates after checking that they match the curve equation.
+ pub fn fromAffineCoordinates(x: Fe, y: Fe) EncodingError!P256 {
+ const x3AxB = x.sq().mul(x).sub(x).sub(x).sub(x).add(B);
+ const yy = y.sq();
+ if (!x3AxB.equivalent(yy)) {
+ return error.InvalidEncoding;
+ }
+ const p: P256 = .{ .x = x, .y = y, .z = Fe.one };
+ return p;
+ }
+
+ /// Create a point from serialized affine coordinates.
+ pub fn fromSerializedAffineCoordinates(xs: [32]u8, ys: [32]u8, endian: builtin.Endian) (NonCanonicalError || EncodingError)!P256 {
+ const x = try Fe.fromBytes(xs, endian);
+ const y = try Fe.fromBytes(ys, endian);
+ return fromAffineCoordinates(x, y);
+ }
+
+ /// Recover the Y coordinate from the X coordinate.
+ pub fn recoverY(x: Fe, is_odd: bool) NotSquareError!Fe {
+ const x3AxB = x.sq().mul(x).sub(x).sub(x).sub(x).add(B);
+ var y = try x3AxB.sqrt();
+ const yn = y.neg();
+ y.cMov(yn, @boolToInt(is_odd) ^ @boolToInt(y.isOdd()));
+ return y;
+ }
+
+ /// Deserialize a SEC1-encoded point.
+ pub fn fromSec1(s: []const u8) (EncodingError || NotSquareError || NonCanonicalError)!P256 {
+ if (s.len < 1) return error.InvalidEncoding;
+ const encoding_type = s[0];
+ const encoded = s[1..];
+ switch (encoding_type) {
+ 0 => {
+ if (encoded.len != 0) return error.InvalidEncoding;
+ return P256.identityElement;
+ },
+ 2, 3 => {
+ if (encoded.len != 32) return error.InvalidEncoding;
+ const x = try Fe.fromBytes(encoded[0..32].*, .Big);
+ const y_is_odd = (encoding_type == 3);
+ const y = try recoverY(x, y_is_odd);
+ return P256{ .x = x, .y = y };
+ },
+ 4 => {
+ if (encoded.len != 64) return error.InvalidEncoding;
+ const x = try Fe.fromBytes(encoded[0..32].*, .Big);
+ const y = try Fe.fromBytes(encoded[32..64].*, .Big);
+ return P256.fromAffineCoordinates(x, y);
+ },
+ else => return error.InvalidEncoding,
+ }
+ }
+
+ /// Serialize a point using the compressed SEC-1 format.
+ pub fn toCompressedSec1(p: P256) [33]u8 {
+ var out: [33]u8 = undefined;
+ const xy = p.affineCoordinates();
+ out[0] = if (xy.y.isOdd()) 3 else 2;
+ mem.copy(u8, out[1..], &xy.x.toBytes(.Big));
+ return out;
+ }
+
+ /// Serialize a point using the uncompressed SEC-1 format.
+ pub fn toUncompressedSec1(p: P256) [65]u8 {
+ var out: [65]u8 = undefined;
+ out[0] = 4;
+ const xy = p.affineCoordinates();
+ mem.copy(u8, out[1..33], &xy.x.toBytes(.Big));
+ mem.copy(u8, out[33..65], &xy.y.toBytes(.Big));
+ return out;
+ }
+
+ /// Return a random point.
+ pub fn random() P256 {
+ const n = scalar.random(.Little);
+ return basePoint.mul(n, .Little) catch unreachable;
+ }
+
+ /// Flip the sign of the X coordinate.
+ pub fn neg(p: P256) P256 {
+ return .{ .x = p.x, .y = p.y.neg(), .z = p.z };
+ }
+
+ /// Double a P256 point.
+ // Algorithm 6 from https://eprint.iacr.org/2015/1060.pdf
+ pub fn dbl(p: P256) P256 {
+ var t0 = p.x.sq();
+ var t1 = p.y.sq();
+ var t2 = p.z.sq();
+ var t3 = p.x.mul(p.y);
+ t3 = t3.dbl();
+ var Z3 = p.x.mul(p.z);
+ Z3 = Z3.add(Z3);
+ var Y3 = B.mul(t2);
+ Y3 = Y3.sub(Z3);
+ var X3 = Y3.dbl();
+ Y3 = X3.add(Y3);
+ X3 = t1.sub(Y3);
+ Y3 = t1.add(Y3);
+ Y3 = X3.mul(Y3);
+ X3 = X3.mul(t3);
+ t3 = t2.dbl();
+ t2 = t2.add(t3);
+ Z3 = B.mul(Z3);
+ Z3 = Z3.sub(t2);
+ Z3 = Z3.sub(t0);
+ t3 = Z3.dbl();
+ Z3 = Z3.add(t3);
+ t3 = t0.dbl();
+ t0 = t3.add(t0);
+ t0 = t0.sub(t2);
+ t0 = t0.mul(Z3);
+ Y3 = Y3.add(t0);
+ t0 = p.y.mul(p.z);
+ t0 = t0.dbl();
+ Z3 = t0.mul(Z3);
+ X3 = X3.sub(Z3);
+ Z3 = t0.mul(t1);
+ Z3 = Z3.dbl().dbl();
+ return .{
+ .x = X3,
+ .y = Y3,
+ .z = Z3,
+ };
+ }
+
+ /// Add P256 points, the second being specified using affine coordinates.
+ // Algorithm 5 from https://eprint.iacr.org/2015/1060.pdf
+ pub fn addMixed(p: P256, q: struct { x: Fe, y: Fe }) P256 {
+ var t0 = p.x.mul(q.x);
+ var t1 = p.y.mul(q.y);
+ var t3 = q.x.add(q.y);
+ var t4 = p.x.add(p.y);
+ t3 = t3.mul(t4);
+ t4 = t0.add(t1);
+ t3 = t3.sub(t4);
+ t4 = q.y.mul(p.z);
+ t4 = t4.add(p.y);
+ var Y3 = q.x.mul(p.z);
+ Y3 = Y3.add(p.x);
+ var Z3 = B.mul(p.z);
+ var X3 = Y3.sub(Z3);
+ Z3 = X3.dbl();
+ X3 = X3.add(Z3);
+ Z3 = t1.sub(X3);
+ X3 = t1.dbl();
+ Y3 = B.mul(Y3);
+ t1 = p.z.add(p.z);
+ var t2 = t1.add(p.z);
+ Y3 = Y3.sub(t2);
+ Y3 = Y3.sub(t0);
+ t1 = Y3.dbl();
+ Y3 = t1.add(Y3);
+ t1 = t0.dbl();
+ t0 = t1.add(t0);
+ t0 = t0.sub(t2);
+ t1 = t4.mul(Y3);
+ t2 = t0.mul(Y3);
+ Y3 = X3.mul(Z3);
+ Y3 = Y3.add(t2);
+ X3 = t3.mul(X3);
+ X3 = X3.sub(t1);
+ Z3 = t4.mul(Z3);
+ t1 = t3.mul(t0);
+ Z3 = Z3.add(t1);
+ return .{
+ .x = X3,
+ .y = Y3,
+ .z = Z3,
+ };
+ }
+
+ // Add P256 points.
+ // Algorithm 4 from https://eprint.iacr.org/2015/1060.pdf
+ pub fn add(p: P256, q: P256) P256 {
+ var t0 = p.x.mul(q.x);
+ var t1 = p.y.mul(q.y);
+ var t2 = p.z.mul(q.z);
+ var t3 = p.x.add(p.y);
+ var t4 = q.x.add(q.y);
+ t3 = t3.mul(t4);
+ t4 = t0.add(t1);
+ t3 = t3.sub(t4);
+ t4 = p.y.add(p.z);
+ var X3 = q.y.add(q.z);
+ t4 = t4.mul(X3);
+ X3 = t1.add(t2);
+ t4 = t4.sub(X3);
+ X3 = p.x.add(p.z);
+ var Y3 = q.x.add(q.z);
+ X3 = X3.mul(Y3);
+ Y3 = t0.add(t2);
+ Y3 = X3.sub(Y3);
+ var Z3 = B.mul(t2);
+ X3 = Y3.sub(Z3);
+ Z3 = X3.dbl();
+ X3 = X3.add(Z3);
+ Z3 = t1.sub(X3);
+ X3 = t1.add(X3);
+ Y3 = B.mul(Y3);
+ t1 = t2.dbl();
+ t2 = t1.add(t2);
+ Y3 = Y3.sub(t2);
+ Y3 = Y3.sub(t0);
+ t1 = Y3.dbl();
+ Y3 = t1.add(Y3);
+ t1 = t0.dbl();
+ t0 = t1.add(t0);
+ t0 = t0.sub(t2);
+ t1 = t4.mul(Y3);
+ t2 = t0.mul(Y3);
+ Y3 = X3.mul(Z3);
+ Y3 = Y3.add(t2);
+ X3 = t3.mul(X3);
+ X3 = X3.sub(t1);
+ Z3 = t4.mul(Z3);
+ t1 = t3.mul(t0);
+ Z3 = Z3.add(t1);
+ return .{
+ .x = X3,
+ .y = Y3,
+ .z = Z3,
+ };
+ }
+
+ // Subtract P256 points.
+ pub fn sub(p: P256, q: P256) P256 {
+ return p.add(q.neg());
+ }
+
+ /// Return affine coordinates.
+ pub fn affineCoordinates(p: P256) struct { x: Fe, y: Fe } {
+ const zinv = p.z.invert();
+ const ret = .{
+ .x = p.x.mul(zinv),
+ .y = p.y.mul(zinv),
+ };
+ return ret;
+ }
+
+ /// Return true if both coordinate sets represent the same point.
+ pub fn equivalent(a: P256, b: P256) bool {
+ if (a.sub(b).rejectIdentity()) {
+ return false;
+ } else |_| {
+ return true;
+ }
+ }
+
+ fn cMov(p: *P256, a: P256, c: u1) void {
+ p.x.cMov(a.x, c);
+ p.y.cMov(a.y, c);
+ p.z.cMov(a.z, c);
+ }
+
+ fn pcSelect(comptime n: usize, pc: [n]P256, b: u8) P256 {
+ var t = P256.identityElement;
+ comptime var i: u8 = 1;
+ inline while (i < pc.len) : (i += 1) {
+ t.cMov(pc[i], @truncate(u1, (@as(usize, b ^ i) -% 1) >> 8));
+ }
+ return t;
+ }
+
+ fn slide(s: [32]u8) [2 * 32 + 1]i8 {
+ var e: [2 * 32 + 1]i8 = undefined;
+ for (s) |x, i| {
+ e[i * 2 + 0] = @as(i8, @truncate(u4, x));
+ e[i * 2 + 1] = @as(i8, @truncate(u4, x >> 4));
+ }
+ // Now, e[0..63] is between 0 and 15, e[63] is between 0 and 7
+ var carry: i8 = 0;
+ for (e[0..64]) |*x| {
+ x.* += carry;
+ carry = (x.* + 8) >> 4;
+ x.* -= carry * 16;
+ std.debug.assert(x.* >= -8 and x.* <= 8);
+ }
+ e[64] = carry;
+ // Now, e[*] is between -8 and 8, including e[64]
+ std.debug.assert(carry >= -8 and carry <= 8);
+ return e;
+ }
+
+ fn pcMul(pc: [9]P256, s: [32]u8, comptime vartime: bool) IdentityElementError!P256 {
+ std.debug.assert(vartime);
+ const e = slide(s);
+ var q = P256.identityElement;
+ var pos = e.len - 1;
+ while (true) : (pos -= 1) {
+ const slot = e[pos];
+ if (slot > 0) {
+ q = q.add(pc[@intCast(usize, slot)]);
+ } else if (slot < 0) {
+ q = q.sub(pc[@intCast(usize, -slot)]);
+ }
+ if (pos == 0) break;
+ q = q.dbl().dbl().dbl().dbl();
+ }
+ try q.rejectIdentity();
+ return q;
+ }
+
+ fn pcMul16(pc: [16]P256, s: [32]u8, comptime vartime: bool) IdentityElementError!P256 {
+ var q = P256.identityElement;
+ var pos: usize = 252;
+ while (true) : (pos -= 4) {
+ const slot = @truncate(u4, (s[pos >> 3] >> @truncate(u3, pos)));
+ if (vartime) {
+ if (slot != 0) {
+ q = q.add(pc[slot]);
+ }
+ } else {
+ q = q.add(pcSelect(16, pc, slot));
+ }
+ if (pos == 0) break;
+ q = q.dbl().dbl().dbl().dbl();
+ }
+ try q.rejectIdentity();
+ return q;
+ }
+
+ fn precompute(p: P256, comptime count: usize) [1 + count]P256 {
+ var pc: [1 + count]P256 = undefined;
+ pc[0] = P256.identityElement;
+ pc[1] = p;
+ var i: usize = 2;
+ while (i <= count) : (i += 1) {
+ pc[i] = if (i % 2 == 0) pc[i / 2].dbl() else pc[i - 1].add(p);
+ }
+ return pc;
+ }
+
+ /// Multiply an elliptic curve point by a scalar.
+ /// Return error.IdentityElement if the result is the identity element.
+ pub fn mul(p: P256, s_: [32]u8, endian: builtin.Endian) IdentityElementError!P256 {
+ const s = if (endian == .Little) s_ else Fe.orderSwap(s_);
+ const pc = if (p.is_base) precompute(P256.basePoint, 15) else pc: {
+ try p.rejectIdentity();
+ const xpc = precompute(p, 15);
+ break :pc xpc;
+ };
+ return pcMul16(pc, s, false);
+ }
+
+ /// Multiply an elliptic curve point by a *PUBLIC* scalar *IN VARIABLE TIME*
+ /// This can be used for signature verification.
+ pub fn mulPublic(p: P256, s_: [32]u8, endian: builtin.Endian) IdentityElementError!P256 {
+ const s = if (endian == .Little) s_ else Fe.orderSwap(s_);
+ const pc = if (p.is_base) precompute(P256.basePoint, 8) else pc: {
+ try p.rejectIdentity();
+ const xpc = precompute(p, 8);
+ break :pc xpc;
+ };
+ return pcMul(pc, s, true);
+ }
+};
+
+test "p256" {
+ _ = @import("tests.zig");
+}
diff --git a/zig/lib/std/crypto/pcurves/p256/field.zig b/zig/lib/std/crypto/pcurves/p256/field.zig
new file mode 100644
index 0000000000..15de1fe43e
--- /dev/null
+++ b/zig/lib/std/crypto/pcurves/p256/field.zig
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: MIT
+// Copyright (c) 2015-2021 Zig Contributors
+// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
+// The MIT license requires this copyright notice to be included in all copies
+// and substantial portions of the software.
+
+const std = @import("std");
+const common = @import("../common.zig");
+
+const Field = common.Field;
+
+pub const Fe = Field(.{
+ .fiat = @import("p256_64.zig"),
+ .field_order = 115792089210356248762697446949407573530086143415290314195533631308867097853951,
+ .field_bits = 256,
+ .saturated_bits = 255,
+ .encoded_length = 32,
+});
diff --git a/zig/lib/std/crypto/pcurves/p256/p256_64.zig b/zig/lib/std/crypto/pcurves/p256/p256_64.zig
new file mode 100644
index 0000000000..ca04ee961d
--- /dev/null
+++ b/zig/lib/std/crypto/pcurves/p256/p256_64.zig
@@ -0,0 +1,1812 @@
+// 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
+// curve description (via package name): p256
+// machine_wordsize = 64 (from "64")
+// requested operations: mul, square, add, sub, opp, from_montgomery, to_montgomery, nonzero, selectznz, to_bytes, from_bytes, one, msat, divstep, divstep_precomp
+// m = 0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff (from "2^256 - 2^224 + 2^192 + 2^96 - 1")
+//
+// NOTE: In addition to the bounds specified above each function, all
+// functions synthesized for this Montgomery arithmetic require the
+// input to be strictly less than the prime modulus (m), and also
+// require the input to be in the unique saturated representation.
+// All functions also ensure that these two properties are true of
+// return values.
+//
+// Computed values:
+// eval z = z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192)
+// 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)
+// twos_complement_eval z = let x1 := z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) in
+// if x1 & (2^256-1) < 2^255 then x1 & (2^256-1) else (x1 & (2^256-1)) - 2^256
+
+const std = @import("std");
+const cast = std.meta.cast;
+const mode = std.builtin.mode; // Checked arithmetic is disabled in non-debug modes to avoid side channels
+
+pub const Limbs = [4]u64;
+
+/// The function addcarryxU64 is an addition with carry.
+/// Postconditions:
+/// out1 = (arg1 + arg2 + arg3) mod 2^64
+/// out2 = ⌊(arg1 + arg2 + arg3) / 2^64⌋
+///
+/// Input Bounds:
+/// arg1: [0x0 ~> 0x1]
+/// arg2: [0x0 ~> 0xffffffffffffffff]
+/// arg3: [0x0 ~> 0xffffffffffffffff]
+/// Output Bounds:
+/// out1: [0x0 ~> 0xffffffffffffffff]
+/// out2: [0x0 ~> 0x1]
+fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) callconv(.Inline) void {
+ @setRuntimeSafety(mode == .Debug);
+
+ var t: u64 = undefined;
+ const carry1 = @addWithOverflow(u64, arg2, arg3, &t);
+ const carry2 = @addWithOverflow(u64, t, arg1, out1);
+ out2.* = @boolToInt(carry1) | @boolToInt(carry2);
+}
+
+/// The function subborrowxU64 is a subtraction with borrow.
+/// Postconditions:
+/// out1 = (-arg1 + arg2 + -arg3) mod 2^64
+/// out2 = -⌊(-arg1 + arg2 + -arg3) / 2^64⌋
+///
+/// Input Bounds:
+/// arg1: [0x0 ~> 0x1]
+/// arg2: [0x0 ~> 0xffffffffffffffff]
+/// arg3: [0x0 ~> 0xffffffffffffffff]
+/// Output Bounds:
+/// out1: [0x0 ~> 0xffffffffffffffff]
+/// out2: [0x0 ~> 0x1]
+fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) callconv(.Inline) void {
+ @setRuntimeSafety(mode == .Debug);
+
+ var t: u64 = undefined;
+ const carry1 = @subWithOverflow(u64, arg2, arg3, &t);
+ const carry2 = @subWithOverflow(u64, t, arg1, out1);
+ out2.* = @boolToInt(carry1) | @boolToInt(carry2);
+}
+
+/// The function mulxU64 is a multiplication, returning the full double-width result.
+/// Postconditions:
+/// out1 = (arg1 * arg2) mod 2^64
+/// out2 = ⌊arg1 * arg2 / 2^64⌋
+///
+/// Input Bounds:
+/// arg1: [0x0 ~> 0xffffffffffffffff]
+/// arg2: [0x0 ~> 0xffffffffffffffff]
+/// Output Bounds:
+/// out1: [0x0 ~> 0xffffffffffffffff]
+/// out2: [0x0 ~> 0xffffffffffffffff]
+fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) callconv(.Inline) void {
+ @setRuntimeSafety(mode == .Debug);
+
+ const x = @as(u128, arg1) * @as(u128, arg2);
+ out1.* = @truncate(u64, x);
+ out2.* = @truncate(u64, x >> 64);
+}
+
+/// The function cmovznzU64 is a single-word conditional move.
+/// Postconditions:
+/// out1 = (if arg1 = 0 then arg2 else arg3)
+///
+/// Input Bounds:
+/// arg1: [0x0 ~> 0x1]
+/// arg2: [0x0 ~> 0xffffffffffffffff]
+/// arg3: [0x0 ~> 0xffffffffffffffff]
+/// Output Bounds:
+/// out1: [0x0 ~> 0xffffffffffffffff]
+fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) callconv(.Inline) void {
+ @setRuntimeSafety(mode == .Debug);
+
+ const mask = 0 -% @as(u64, arg1);
+ out1.* = (mask & arg3) | ((~mask) & arg2);
+}
+
+/// The function mul multiplies two field elements in the Montgomery domain.
+/// Preconditions:
+/// 0 ≤ eval arg1 < m
+/// 0 ≤ eval arg2 < m
+/// Postconditions:
+/// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) * eval (from_montgomery arg2)) mod m
+/// 0 ≤ eval out1 < m
+///
+/// Input Bounds:
+/// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+/// arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+/// Output Bounds:
+/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+pub fn mul(out1: *[4]u64, arg1: [4]u64, arg2: [4]u64) void {
+ @setRuntimeSafety(mode == .Debug);
+
+ const x1 = (arg1[1]);
+ const x2 = (arg1[2]);
+ const x3 = (arg1[3]);
+ const x4 = (arg1[0]);
+ var x5: u64 = undefined;
+ var x6: u64 = undefined;
+ mulxU64(&x5, &x6, x4, (arg2[3]));
+ var x7: u64 = undefined;
+ var x8: u64 = undefined;
+ mulxU64(&x7, &x8, x4, (arg2[2]));
+ var x9: u64 = undefined;
+ var x10: u64 = undefined;
+ mulxU64(&x9, &x10, x4, (arg2[1]));
+ var x11: u64 = undefined;
+ var x12: u64 = undefined;
+ mulxU64(&x11, &x12, x4, (arg2[0]));
+ var x13: u64 = undefined;
+ var x14: u1 = undefined;
+ addcarryxU64(&x13, &x14, 0x0, x12, x9);
+ var x15: u64 = undefined;
+ var x16: u1 = undefined;
+ addcarryxU64(&x15, &x16, x14, x10, x7);
+ var x17: u64 = undefined;
+ var x18: u1 = undefined;
+ addcarryxU64(&x17, &x18, x16, x8, x5);
+ const x19 = (cast(u64, x18) + x6);
+ var x20: u64 = undefined;
+ var x21: u64 = undefined;
+ mulxU64(&x20, &x21, x11, 0xffffffff00000001);
+ var x22: u64 = undefined;
+ var x23: u64 = undefined;
+ mulxU64(&x22, &x23, x11, 0xffffffff);
+ var x24: u64 = undefined;
+ var x25: u64 = undefined;
+ mulxU64(&x24, &x25, x11, 0xffffffffffffffff);
+ var x26: u64 = undefined;
+ var x27: u1 = undefined;
+ addcarryxU64(&x26, &x27, 0x0, x25, x22);
+ const x28 = (cast(u64, x27) + x23);
+ var x29: u64 = undefined;
+ var x30: u1 = undefined;
+ addcarryxU64(&x29, &x30, 0x0, x11, x24);
+ var x31: u64 = undefined;
+ var x32: u1 = undefined;
+ addcarryxU64(&x31, &x32, x30, x13, x26);
+ var x33: u64 = undefined;
+ var x34: u1 = undefined;
+ addcarryxU64(&x33, &x34, x32, x15, x28);
+ var x35: u64 = undefined;
+ var x36: u1 = undefined;
+ addcarryxU64(&x35, &x36, x34, x17, x20);
+ var x37: u64 = undefined;
+ var x38: u1 = undefined;
+ addcarryxU64(&x37, &x38, x36, x19, x21);
+ var x39: u64 = undefined;
+ var x40: u64 = undefined;
+ mulxU64(&x39, &x40, x1, (arg2[3]));
+ var x41: u64 = undefined;
+ var x42: u64 = undefined;
+ mulxU64(&x41, &x42, x1, (arg2[2]));
+ var x43: u64 = undefined;
+ var x44: u64 = undefined;
+ mulxU64(&x43, &x44, x1, (arg2[1]));
+ var x45: u64 = undefined;
+ var x46: u64 = undefined;
+ mulxU64(&x45, &x46, x1, (arg2[0]));
+ var x47: u64 = undefined;
+ var x48: u1 = undefined;
+ addcarryxU64(&x47, &x48, 0x0, x46, x43);
+ var x49: u64 = undefined;
+ var x50: u1 = undefined;
+ addcarryxU64(&x49, &x50, x48, x44, x41);
+ var x51: u64 = undefined;
+ var x52: u1 = undefined;
+ addcarryxU64(&x51, &x52, x50, x42, x39);
+ const x53 = (cast(u64, x52) + x40);
+ var x54: u64 = undefined;
+ var x55: u1 = undefined;
+ addcarryxU64(&x54, &x55, 0x0, x31, x45);
+ var x56: u64 = undefined;
+ var x57: u1 = undefined;
+ addcarryxU64(&x56, &x57, x55, x33, x47);
+ var x58: u64 = undefined;
+ var x59: u1 = undefined;
+ addcarryxU64(&x58, &x59, x57, x35, x49);
+ var x60: u64 = undefined;
+ var x61: u1 = undefined;
+ addcarryxU64(&x60, &x61, x59, x37, x51);
+ var x62: u64 = undefined;
+ var x63: u1 = undefined;
+ addcarryxU64(&x62, &x63, x61, cast(u64, x38), x53);
+ var x64: u64 = undefined;
+ var x65: u64 = undefined;
+ mulxU64(&x64, &x65, x54, 0xffffffff00000001);
+ var x66: u64 = undefined;
+ var x67: u64 = undefined;
+ mulxU64(&x66, &x67, x54, 0xffffffff);
+ var x68: u64 = undefined;
+ var x69: u64 = undefined;
+ mulxU64(&x68, &x69, x54, 0xffffffffffffffff);
+ var x70: u64 = undefined;
+ var x71: u1 = undefined;
+ addcarryxU64(&x70, &x71, 0x0, x69, x66);
+ const x72 = (cast(u64, x71) + x67);
+ var x73: u64 = undefined;
+ var x74: u1 = undefined;
+ addcarryxU64(&x73, &x74, 0x0, x54, x68);
+ var x75: u64 = undefined;
+ var x76: u1 = undefined;
+ addcarryxU64(&x75, &x76, x74, x56, x70);
+ var x77: u64 = undefined;
+ var x78: u1 = undefined;
+ addcarryxU64(&x77, &x78, x76, x58, x72);
+ var x79: u64 = undefined;
+ var x80: u1 = undefined;
+ addcarryxU64(&x79, &x80, x78, x60, x64);
+ var x81: u64 = undefined;
+ var x82: u1 = undefined;
+ addcarryxU64(&x81, &x82, x80, x62, x65);
+ const x83 = (cast(u64, x82) + cast(u64, x63));
+ var x84: u64 = undefined;
+ var x85: u64 = undefined;
+ mulxU64(&x84, &x85, x2, (arg2[3]));
+ var x86: u64 = undefined;
+ var x87: u64 = undefined;
+ mulxU64(&x86, &x87, x2, (arg2[2]));
+ var x88: u64 = undefined;
+ var x89: u64 = undefined;
+ mulxU64(&x88, &x89, x2, (arg2[1]));
+ var x90: u64 = undefined;
+ var x91: u64 = undefined;
+ mulxU64(&x90, &x91, x2, (arg2[0]));
+ var x92: u64 = undefined;
+ var x93: u1 = undefined;
+ addcarryxU64(&x92, &x93, 0x0, x91, x88);
+ var x94: u64 = undefined;
+ var x95: u1 = undefined;
+ addcarryxU64(&x94, &x95, x93, x89, x86);
+ var x96: u64 = undefined;
+ var x97: u1 = undefined;
+ addcarryxU64(&x96, &x97, x95, x87, x84);
+ const x98 = (cast(u64, x97) + x85);
+ var x99: u64 = undefined;
+ var x100: u1 = undefined;
+ addcarryxU64(&x99, &x100, 0x0, x75, x90);
+ var x101: u64 = undefined;
+ var x102: u1 = undefined;
+ addcarryxU64(&x101, &x102, x100, x77, x92);
+ var x103: u64 = undefined;
+ var x104: u1 = undefined;
+ addcarryxU64(&x103, &x104, x102, x79, x94);
+ var x105: u64 = undefined;
+ var x106: u1 = undefined;
+ addcarryxU64(&x105, &x106, x104, x81, x96);
+ var x107: u64 = undefined;
+ var x108: u1 = undefined;
+ addcarryxU64(&x107, &x108, x106, x83, x98);
+ var x109: u64 = undefined;
+ var x110: u64 = undefined;
+ mulxU64(&x109, &x110, x99, 0xffffffff00000001);
+ var x111: u64 = undefined;
+ var x112: u64 = undefined;
+ mulxU64(&x111, &x112, x99, 0xffffffff);
+ var x113: u64 = undefined;
+ var x114: u64 = undefined;
+ mulxU64(&x113, &x114, x99, 0xffffffffffffffff);
+ var x115: u64 = undefined;
+ var x116: u1 = undefined;
+ addcarryxU64(&x115, &x116, 0x0, x114, x111);
+ const x117 = (cast(u64, x116) + x112);
+ var x118: u64 = undefined;
+ var x119: u1 = undefined;
+ addcarryxU64(&x118, &x119, 0x0, x99, x113);
+ var x120: u64 = undefined;
+ var x121: u1 = undefined;
+ addcarryxU64(&x120, &x121, x119, x101, x115);
+ var x122: u64 = undefined;
+ var x123: u1 = undefined;
+ addcarryxU64(&x122, &x123, x121, x103, x117);
+ var x124: u64 = undefined;
+ var x125: u1 = undefined;
+ addcarryxU64(&x124, &x125, x123, x105, x109);
+ var x126: u64 = undefined;
+ var x127: u1 = undefined;
+ addcarryxU64(&x126, &x127, x125, x107, x110);
+ const x128 = (cast(u64, x127) + cast(u64, x108));
+ var x129: u64 = undefined;
+ var x130: u64 = undefined;
+ mulxU64(&x129, &x130, x3, (arg2[3]));
+ var x131: u64 = undefined;
+ var x132: u64 = undefined;
+ mulxU64(&x131, &x132, x3, (arg2[2]));
+ var x133: u64 = undefined;
+ var x134: u64 = undefined;
+ mulxU64(&x133, &x134, x3, (arg2[1]));
+ var x135: u64 = undefined;
+ var x136: u64 = undefined;
+ mulxU64(&x135, &x136, x3, (arg2[0]));
+ var x137: u64 = undefined;
+ var x138: u1 = undefined;
+ addcarryxU64(&x137, &x138, 0x0, x136, x133);
+ var x139: u64 = undefined;
+ var x140: u1 = undefined;
+ addcarryxU64(&x139, &x140, x138, x134, x131);
+ var x141: u64 = undefined;
+ var x142: u1 = undefined;
+ addcarryxU64(&x141, &x142, x140, x132, x129);
+ const x143 = (cast(u64, x142) + x130);
+ var x144: u64 = undefined;
+ var x145: u1 = undefined;
+ addcarryxU64(&x144, &x145, 0x0, x120, x135);
+ var x146: u64 = undefined;
+ var x147: u1 = undefined;
+ addcarryxU64(&x146, &x147, x145, x122, x137);
+ var x148: u64 = undefined;
+ var x149: u1 = undefined;
+ addcarryxU64(&x148, &x149, x147, x124, x139);
+ var x150: u64 = undefined;
+ var x151: u1 = undefined;
+ addcarryxU64(&x150, &x151, x149, x126, x141);
+ var x152: u64 = undefined;
+ var x153: u1 = undefined;
+ addcarryxU64(&x152, &x153, x151, x128, x143);
+ var x154: u64 = undefined;
+ var x155: u64 = undefined;
+ mulxU64(&x154, &x155, x144, 0xffffffff00000001);
+ var x156: u64 = undefined;
+ var x157: u64 = undefined;
+ mulxU64(&x156, &x157, x144, 0xffffffff);
+ var x158: u64 = undefined;
+ var x159: u64 = undefined;
+ mulxU64(&x158, &x159, x144, 0xffffffffffffffff);
+ var x160: u64 = undefined;
+ var x161: u1 = undefined;
+ addcarryxU64(&x160, &x161, 0x0, x159, x156);
+ const x162 = (cast(u64, x161) + x157);
+ var x163: u64 = undefined;
+ var x164: u1 = undefined;
+ addcarryxU64(&x163, &x164, 0x0, x144, x158);
+ var x165: u64 = undefined;
+ var x166: u1 = undefined;
+ addcarryxU64(&x165, &x166, x164, x146, x160);
+ var x167: u64 = undefined;
+ var x168: u1 = undefined;
+ addcarryxU64(&x167, &x168, x166, x148, x162);
+ var x169: u64 = undefined;
+ var x170: u1 = undefined;
+ addcarryxU64(&x169, &x170, x168, x150, x154);
+ var x171: u64 = undefined;
+ var x172: u1 = undefined;
+ addcarryxU64(&x171, &x172, x170, x152, x155);
+ const x173 = (cast(u64, x172) + cast(u64, x153));
+ var x174: u64 = undefined;
+ var x175: u1 = undefined;
+ subborrowxU64(&x174, &x175, 0x0, x165, 0xffffffffffffffff);
+ var x176: u64 = undefined;
+ var x177: u1 = undefined;
+ subborrowxU64(&x176, &x177, x175, x167, 0xffffffff);
+ var x178: u64 = undefined;
+ var x179: u1 = undefined;
+ subborrowxU64(&x178, &x179, x177, x169, cast(u64, 0x0));
+ var x180: u64 = undefined;
+ var x181: u1 = undefined;
+ subborrowxU64(&x180, &x181, x179, x171, 0xffffffff00000001);
+ var x182: u64 = undefined;
+ var x183: u1 = undefined;
+ subborrowxU64(&x182, &x183, x181, x173, cast(u64, 0x0));
+ var x184: u64 = undefined;
+ cmovznzU64(&x184, x183, x174, x165);
+ var x185: u64 = undefined;
+ cmovznzU64(&x185, x183, x176, x167);
+ var x186: u64 = undefined;
+ cmovznzU64(&x186, x183, x178, x169);
+ var x187: u64 = undefined;
+ cmovznzU64(&x187, x183, x180, x171);
+ out1[0] = x184;
+ out1[1] = x185;
+ out1[2] = x186;
+ out1[3] = x187;
+}
+
+/// The function square squares a field element in the Montgomery domain.
+/// Preconditions:
+/// 0 ≤ eval arg1 < m
+/// Postconditions:
+/// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) * eval (from_montgomery arg1)) mod m
+/// 0 ≤ eval out1 < m
+///
+/// Input Bounds:
+/// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+/// Output Bounds:
+/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+pub fn square(out1: *[4]u64, arg1: [4]u64) void {
+ @setRuntimeSafety(mode == .Debug);
+
+ const x1 = (arg1[1]);
+ const x2 = (arg1[2]);
+ const x3 = (arg1[3]);
+ const x4 = (arg1[0]);
+ var x5: u64 = undefined;
+ var x6: u64 = undefined;
+ mulxU64(&x5, &x6, x4, (arg1[3]));
+ var x7: u64 = undefined;
+ var x8: u64 = undefined;
+ mulxU64(&x7, &x8, x4, (arg1[2]));
+ var x9: u64 = undefined;
+ var x10: u64 = undefined;
+ mulxU64(&x9, &x10, x4, (arg1[1]));
+ var x11: u64 = undefined;
+ var x12: u64 = undefined;
+ mulxU64(&x11, &x12, x4, (arg1[0]));
+ var x13: u64 = undefined;
+ var x14: u1 = undefined;
+ addcarryxU64(&x13, &x14, 0x0, x12, x9);
+ var x15: u64 = undefined;
+ var x16: u1 = undefined;
+ addcarryxU64(&x15, &x16, x14, x10, x7);
+ var x17: u64 = undefined;
+ var x18: u1 = undefined;
+ addcarryxU64(&x17, &x18, x16, x8, x5);
+ const x19 = (cast(u64, x18) + x6);
+ var x20: u64 = undefined;
+ var x21: u64 = undefined;
+ mulxU64(&x20, &x21, x11, 0xffffffff00000001);
+ var x22: u64 = undefined;
+ var x23: u64 = undefined;
+ mulxU64(&x22, &x23, x11, 0xffffffff);
+ var x24: u64 = undefined;
+ var x25: u64 = undefined;
+ mulxU64(&x24, &x25, x11, 0xffffffffffffffff);
+ var x26: u64 = undefined;
+ var x27: u1 = undefined;
+ addcarryxU64(&x26, &x27, 0x0, x25, x22);
+ const x28 = (cast(u64, x27) + x23);
+ var x29: u64 = undefined;
+ var x30: u1 = undefined;
+ addcarryxU64(&x29, &x30, 0x0, x11, x24);
+ var x31: u64 = undefined;
+ var x32: u1 = undefined;
+ addcarryxU64(&x31, &x32, x30, x13, x26);
+ var x33: u64 = undefined;
+ var x34: u1 = undefined;
+ addcarryxU64(&x33, &x34, x32, x15, x28);
+ var x35: u64 = undefined;
+ var x36: u1 = undefined;
+ addcarryxU64(&x35, &x36, x34, x17, x20);
+ var x37: u64 = undefined;
+ var x38: u1 = undefined;
+ addcarryxU64(&x37, &x38, x36, x19, x21);
+ var x39: u64 = undefined;
+ var x40: u64 = undefined;
+ mulxU64(&x39, &x40, x1, (arg1[3]));
+ var x41: u64 = undefined;
+ var x42: u64 = undefined;
+ mulxU64(&x41, &x42, x1, (arg1[2]));
+ var x43: u64 = undefined;
+ var x44: u64 = undefined;
+ mulxU64(&x43, &x44, x1, (arg1[1]));
+ var x45: u64 = undefined;
+ var x46: u64 = undefined;
+ mulxU64(&x45, &x46, x1, (arg1[0]));
+ var x47: u64 = undefined;
+ var x48: u1 = undefined;
+ addcarryxU64(&x47, &x48, 0x0, x46, x43);
+ var x49: u64 = undefined;
+ var x50: u1 = undefined;
+ addcarryxU64(&x49, &x50, x48, x44, x41);
+ var x51: u64 = undefined;
+ var x52: u1 = undefined;
+ addcarryxU64(&x51, &x52, x50, x42, x39);
+ const x53 = (cast(u64, x52) + x40);
+ var x54: u64 = undefined;
+ var x55: u1 = undefined;
+ addcarryxU64(&x54, &x55, 0x0, x31, x45);
+ var x56: u64 = undefined;
+ var x57: u1 = undefined;
+ addcarryxU64(&x56, &x57, x55, x33, x47);
+ var x58: u64 = undefined;
+ var x59: u1 = undefined;
+ addcarryxU64(&x58, &x59, x57, x35, x49);
+ var x60: u64 = undefined;
+ var x61: u1 = undefined;
+ addcarryxU64(&x60, &x61, x59, x37, x51);
+ var x62: u64 = undefined;
+ var x63: u1 = undefined;
+ addcarryxU64(&x62, &x63, x61, cast(u64, x38), x53);
+ var x64: u64 = undefined;
+ var x65: u64 = undefined;
+ mulxU64(&x64, &x65, x54, 0xffffffff00000001);
+ var x66: u64 = undefined;
+ var x67: u64 = undefined;
+ mulxU64(&x66, &x67, x54, 0xffffffff);
+ var x68: u64 = undefined;
+ var x69: u64 = undefined;
+ mulxU64(&x68, &x69, x54, 0xffffffffffffffff);
+ var x70: u64 = undefined;
+ var x71: u1 = undefined;
+ addcarryxU64(&x70, &x71, 0x0, x69, x66);
+ const x72 = (cast(u64, x71) + x67);
+ var x73: u64 = undefined;
+ var x74: u1 = undefined;
+ addcarryxU64(&x73, &x74, 0x0, x54, x68);
+ var x75: u64 = undefined;
+ var x76: u1 = undefined;
+ addcarryxU64(&x75, &x76, x74, x56, x70);
+ var x77: u64 = undefined;
+ var x78: u1 = undefined;
+ addcarryxU64(&x77, &x78, x76, x58, x72);
+ var x79: u64 = undefined;
+ var x80: u1 = undefined;
+ addcarryxU64(&x79, &x80, x78, x60, x64);
+ var x81: u64 = undefined;
+ var x82: u1 = undefined;
+ addcarryxU64(&x81, &x82, x80, x62, x65);
+ const x83 = (cast(u64, x82) + cast(u64, x63));
+ var x84: u64 = undefined;
+ var x85: u64 = undefined;
+ mulxU64(&x84, &x85, x2, (arg1[3]));
+ var x86: u64 = undefined;
+ var x87: u64 = undefined;
+ mulxU64(&x86, &x87, x2, (arg1[2]));
+ var x88: u64 = undefined;
+ var x89: u64 = undefined;
+ mulxU64(&x88, &x89, x2, (arg1[1]));
+ var x90: u64 = undefined;
+ var x91: u64 = undefined;
+ mulxU64(&x90, &x91, x2, (arg1[0]));
+ var x92: u64 = undefined;
+ var x93: u1 = undefined;
+ addcarryxU64(&x92, &x93, 0x0, x91, x88);
+ var x94: u64 = undefined;
+ var x95: u1 = undefined;
+ addcarryxU64(&x94, &x95, x93, x89, x86);
+ var x96: u64 = undefined;
+ var x97: u1 = undefined;
+ addcarryxU64(&x96, &x97, x95, x87, x84);
+ const x98 = (cast(u64, x97) + x85);
+ var x99: u64 = undefined;
+ var x100: u1 = undefined;
+ addcarryxU64(&x99, &x100, 0x0, x75, x90);
+ var x101: u64 = undefined;
+ var x102: u1 = undefined;
+ addcarryxU64(&x101, &x102, x100, x77, x92);
+ var x103: u64 = undefined;
+ var x104: u1 = undefined;
+ addcarryxU64(&x103, &x104, x102, x79, x94);
+ var x105: u64 = undefined;
+ var x106: u1 = undefined;
+ addcarryxU64(&x105, &x106, x104, x81, x96);
+ var x107: u64 = undefined;
+ var x108: u1 = undefined;
+ addcarryxU64(&x107, &x108, x106, x83, x98);
+ var x109: u64 = undefined;
+ var x110: u64 = undefined;
+ mulxU64(&x109, &x110, x99, 0xffffffff00000001);
+ var x111: u64 = undefined;
+ var x112: u64 = undefined;
+ mulxU64(&x111, &x112, x99, 0xffffffff);
+ var x113: u64 = undefined;
+ var x114: u64 = undefined;
+ mulxU64(&x113, &x114, x99, 0xffffffffffffffff);
+ var x115: u64 = undefined;
+ var x116: u1 = undefined;
+ addcarryxU64(&x115, &x116, 0x0, x114, x111);
+ const x117 = (cast(u64, x116) + x112);
+ var x118: u64 = undefined;
+ var x119: u1 = undefined;
+ addcarryxU64(&x118, &x119, 0x0, x99, x113);
+ var x120: u64 = undefined;
+ var x121: u1 = undefined;
+ addcarryxU64(&x120, &x121, x119, x101, x115);
+ var x122: u64 = undefined;
+ var x123: u1 = undefined;
+ addcarryxU64(&x122, &x123, x121, x103, x117);
+ var x124: u64 = undefined;
+ var x125: u1 = undefined;
+ addcarryxU64(&x124, &x125, x123, x105, x109);
+ var x126: u64 = undefined;
+ var x127: u1 = undefined;
+ addcarryxU64(&x126, &x127, x125, x107, x110);
+ const x128 = (cast(u64, x127) + cast(u64, x108));
+ var x129: u64 = undefined;
+ var x130: u64 = undefined;
+ mulxU64(&x129, &x130, x3, (arg1[3]));
+ var x131: u64 = undefined;
+ var x132: u64 = undefined;
+ mulxU64(&x131, &x132, x3, (arg1[2]));
+ var x133: u64 = undefined;
+ var x134: u64 = undefined;
+ mulxU64(&x133, &x134, x3, (arg1[1]));
+ var x135: u64 = undefined;
+ var x136: u64 = undefined;
+ mulxU64(&x135, &x136, x3, (arg1[0]));
+ var x137: u64 = undefined;
+ var x138: u1 = undefined;
+ addcarryxU64(&x137, &x138, 0x0, x136, x133);
+ var x139: u64 = undefined;
+ var x140: u1 = undefined;
+ addcarryxU64(&x139, &x140, x138, x134, x131);
+ var x141: u64 = undefined;
+ var x142: u1 = undefined;
+ addcarryxU64(&x141, &x142, x140, x132, x129);
+ const x143 = (cast(u64, x142) + x130);
+ var x144: u64 = undefined;
+ var x145: u1 = undefined;
+ addcarryxU64(&x144, &x145, 0x0, x120, x135);
+ var x146: u64 = undefined;
+ var x147: u1 = undefined;
+ addcarryxU64(&x146, &x147, x145, x122, x137);
+ var x148: u64 = undefined;
+ var x149: u1 = undefined;
+ addcarryxU64(&x148, &x149, x147, x124, x139);
+ var x150: u64 = undefined;
+ var x151: u1 = undefined;
+ addcarryxU64(&x150, &x151, x149, x126, x141);
+ var x152: u64 = undefined;
+ var x153: u1 = undefined;
+ addcarryxU64(&x152, &x153, x151, x128, x143);
+ var x154: u64 = undefined;
+ var x155: u64 = undefined;
+ mulxU64(&x154, &x155, x144, 0xffffffff00000001);
+ var x156: u64 = undefined;
+ var x157: u64 = undefined;
+ mulxU64(&x156, &x157, x144, 0xffffffff);
+ var x158: u64 = undefined;
+ var x159: u64 = undefined;
+ mulxU64(&x158, &x159, x144, 0xffffffffffffffff);
+ var x160: u64 = undefined;
+ var x161: u1 = undefined;
+ addcarryxU64(&x160, &x161, 0x0, x159, x156);
+ const x162 = (cast(u64, x161) + x157);
+ var x163: u64 = undefined;
+ var x164: u1 = undefined;
+ addcarryxU64(&x163, &x164, 0x0, x144, x158);
+ var x165: u64 = undefined;
+ var x166: u1 = undefined;
+ addcarryxU64(&x165, &x166, x164, x146, x160);
+ var x167: u64 = undefined;
+ var x168: u1 = undefined;
+ addcarryxU64(&x167, &x168, x166, x148, x162);
+ var x169: u64 = undefined;
+ var x170: u1 = undefined;
+ addcarryxU64(&x169, &x170, x168, x150, x154);
+ var x171: u64 = undefined;
+ var x172: u1 = undefined;
+ addcarryxU64(&x171, &x172, x170, x152, x155);
+ const x173 = (cast(u64, x172) + cast(u64, x153));
+ var x174: u64 = undefined;
+ var x175: u1 = undefined;
+ subborrowxU64(&x174, &x175, 0x0, x165, 0xffffffffffffffff);
+ var x176: u64 = undefined;
+ var x177: u1 = undefined;
+ subborrowxU64(&x176, &x177, x175, x167, 0xffffffff);
+ var x178: u64 = undefined;
+ var x179: u1 = undefined;
+ subborrowxU64(&x178, &x179, x177, x169, cast(u64, 0x0));
+ var x180: u64 = undefined;
+ var x181: u1 = undefined;
+ subborrowxU64(&x180, &x181, x179, x171, 0xffffffff00000001);
+ var x182: u64 = undefined;
+ var x183: u1 = undefined;
+ subborrowxU64(&x182, &x183, x181, x173, cast(u64, 0x0));
+ var x184: u64 = undefined;
+ cmovznzU64(&x184, x183, x174, x165);
+ var x185: u64 = undefined;
+ cmovznzU64(&x185, x183, x176, x167);
+ var x186: u64 = undefined;
+ cmovznzU64(&x186, x183, x178, x169);
+ var x187: u64 = undefined;
+ cmovznzU64(&x187, x183, x180, x171);
+ out1[0] = x184;
+ out1[1] = x185;
+ out1[2] = x186;
+ out1[3] = x187;
+}
+
+/// The function add adds two field elements in the Montgomery domain.
+/// Preconditions:
+/// 0 ≤ eval arg1 < m
+/// 0 ≤ eval arg2 < m
+/// Postconditions:
+/// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) + eval (from_montgomery arg2)) mod m
+/// 0 ≤ eval out1 < m
+///
+/// Input Bounds:
+/// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+/// arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+/// Output Bounds:
+/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+pub fn add(out1: *[4]u64, arg1: [4]u64, arg2: [4]u64) void {
+ @setRuntimeSafety(mode == .Debug);
+
+ var x1: u64 = undefined;
+ var x2: u1 = undefined;
+ addcarryxU64(&x1, &x2, 0x0, (arg1[0]), (arg2[0]));
+ var x3: u64 = undefined;
+ var x4: u1 = undefined;
+ addcarryxU64(&x3, &x4, x2, (arg1[1]), (arg2[1]));
+ var x5: u64 = undefined;
+ var x6: u1 = undefined;
+ addcarryxU64(&x5, &x6, x4, (arg1[2]), (arg2[2]));
+ var x7: u64 = undefined;
+ var x8: u1 = undefined;
+ addcarryxU64(&x7, &x8, x6, (arg1[3]), (arg2[3]));
+ var x9: u64 = undefined;
+ var x10: u1 = undefined;
+ subborrowxU64(&x9, &x10, 0x0, x1, 0xffffffffffffffff);
+ var x11: u64 = undefined;
+ var x12: u1 = undefined;
+ subborrowxU64(&x11, &x12, x10, x3, 0xffffffff);
+ var x13: u64 = undefined;
+ var x14: u1 = undefined;
+ subborrowxU64(&x13, &x14, x12, x5, cast(u64, 0x0));
+ var x15: u64 = undefined;
+ var x16: u1 = undefined;
+ subborrowxU64(&x15, &x16, x14, x7, 0xffffffff00000001);
+ var x17: u64 = undefined;
+ var x18: u1 = undefined;
+ subborrowxU64(&x17, &x18, x16, cast(u64, x8), cast(u64, 0x0));
+ var x19: u64 = undefined;
+ cmovznzU64(&x19, x18, x9, x1);
+ var x20: u64 = undefined;
+ cmovznzU64(&x20, x18, x11, x3);
+ var x21: u64 = undefined;
+ cmovznzU64(&x21, x18, x13, x5);
+ var x22: u64 = undefined;
+ cmovznzU64(&x22, x18, x15, x7);
+ out1[0] = x19;
+ out1[1] = x20;
+ out1[2] = x21;
+ out1[3] = x22;
+}
+
+/// The function sub subtracts two field elements in the Montgomery domain.
+/// Preconditions:
+/// 0 ≤ eval arg1 < m
+/// 0 ≤ eval arg2 < m
+/// Postconditions:
+/// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) - eval (from_montgomery arg2)) mod m
+/// 0 ≤ eval out1 < m
+///
+/// Input Bounds:
+/// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+/// arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+/// Output Bounds:
+/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+pub fn sub(out1: *[4]u64, arg1: [4]u64, arg2: [4]u64) void {
+ @setRuntimeSafety(mode == .Debug);
+
+ var x1: u64 = undefined;
+ var x2: u1 = undefined;
+ subborrowxU64(&x1, &x2, 0x0, (arg1[0]), (arg2[0]));
+ var x3: u64 = undefined;
+ var x4: u1 = undefined;
+ subborrowxU64(&x3, &x4, x2, (arg1[1]), (arg2[1]));
+ var x5: u64 = undefined;
+ var x6: u1 = undefined;
+ subborrowxU64(&x5, &x6, x4, (arg1[2]), (arg2[2]));
+ var x7: u64 = undefined;
+ var x8: u1 = undefined;
+ subborrowxU64(&x7, &x8, x6, (arg1[3]), (arg2[3]));
+ var x9: u64 = undefined;
+ cmovznzU64(&x9, x8, cast(u64, 0x0), 0xffffffffffffffff);
+ var x10: u64 = undefined;
+ var x11: u1 = undefined;
+ addcarryxU64(&x10, &x11, 0x0, x1, x9);
+ var x12: u64 = undefined;
+ var x13: u1 = undefined;
+ addcarryxU64(&x12, &x13, x11, x3, (x9 & 0xffffffff));
+ var x14: u64 = undefined;
+ var x15: u1 = undefined;
+ addcarryxU64(&x14, &x15, x13, x5, cast(u64, 0x0));
+ var x16: u64 = undefined;
+ var x17: u1 = undefined;
+ addcarryxU64(&x16, &x17, x15, x7, (x9 & 0xffffffff00000001));
+ out1[0] = x10;
+ out1[1] = x12;
+ out1[2] = x14;
+ out1[3] = x16;
+}
+
+/// The function opp negates a field element in the Montgomery domain.
+/// Preconditions:
+/// 0 ≤ eval arg1 < m
+/// Postconditions:
+/// eval (from_montgomery out1) mod m = -eval (from_montgomery arg1) mod m
+/// 0 ≤ eval out1 < m
+///
+/// Input Bounds:
+/// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+/// Output Bounds:
+/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+pub fn opp(out1: *[4]u64, arg1: [4]u64) void {
+ @setRuntimeSafety(mode == .Debug);
+
+ var x1: u64 = undefined;
+ var x2: u1 = undefined;
+ subborrowxU64(&x1, &x2, 0x0, cast(u64, 0x0), (arg1[0]));
+ var x3: u64 = undefined;
+ var x4: u1 = undefined;
+ subborrowxU64(&x3, &x4, x2, cast(u64, 0x0), (arg1[1]));
+ var x5: u64 = undefined;
+ var x6: u1 = undefined;
+ subborrowxU64(&x5, &x6, x4, cast(u64, 0x0), (arg1[2]));
+ var x7: u64 = undefined;
+ var x8: u1 = undefined;
+ subborrowxU64(&x7, &x8, x6, cast(u64, 0x0), (arg1[3]));
+ var x9: u64 = undefined;
+ cmovznzU64(&x9, x8, cast(u64, 0x0), 0xffffffffffffffff);
+ var x10: u64 = undefined;
+ var x11: u1 = undefined;
+ addcarryxU64(&x10, &x11, 0x0, x1, x9);
+ var x12: u64 = undefined;
+ var x13: u1 = undefined;
+ addcarryxU64(&x12, &x13, x11, x3, (x9 & 0xffffffff));
+ var x14: u64 = undefined;
+ var x15: u1 = undefined;
+ addcarryxU64(&x14, &x15, x13, x5, cast(u64, 0x0));
+ var x16: u64 = undefined;
+ var x17: u1 = undefined;
+ addcarryxU64(&x16, &x17, x15, x7, (x9 & 0xffffffff00000001));
+ out1[0] = x10;
+ out1[1] = x12;
+ out1[2] = x14;
+ out1[3] = x16;
+}
+
+/// The function fromMontgomery translates a field element out of the Montgomery domain.
+/// Preconditions:
+/// 0 ≤ eval arg1 < m
+/// Postconditions:
+/// eval out1 mod m = (eval arg1 * ((2^64)⁻¹ mod m)^4) mod m
+/// 0 ≤ eval out1 < m
+///
+/// Input Bounds:
+/// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+/// Output Bounds:
+/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+pub fn fromMontgomery(out1: *[4]u64, arg1: [4]u64) void {
+ @setRuntimeSafety(mode == .Debug);
+
+ const x1 = (arg1[0]);
+ var x2: u64 = undefined;
+ var x3: u64 = undefined;
+ mulxU64(&x2, &x3, x1, 0xffffffff00000001);
+ var x4: u64 = undefined;
+ var x5: u64 = undefined;
+ mulxU64(&x4, &x5, x1, 0xffffffff);
+ var x6: u64 = undefined;
+ var x7: u64 = undefined;
+ mulxU64(&x6, &x7, x1, 0xffffffffffffffff);
+ var x8: u64 = undefined;
+ var x9: u1 = undefined;
+ addcarryxU64(&x8, &x9, 0x0, x7, x4);
+ var x10: u64 = undefined;
+ var x11: u1 = undefined;
+ addcarryxU64(&x10, &x11, 0x0, x1, x6);
+ var x12: u64 = undefined;
+ var x13: u1 = undefined;
+ addcarryxU64(&x12, &x13, x11, cast(u64, 0x0), x8);
+ var x14: u64 = undefined;
+ var x15: u1 = undefined;
+ addcarryxU64(&x14, &x15, 0x0, x12, (arg1[1]));
+ var x16: u64 = undefined;
+ var x17: u64 = undefined;
+ mulxU64(&x16, &x17, x14, 0xffffffff00000001);
+ var x18: u64 = undefined;
+ var x19: u64 = undefined;
+ mulxU64(&x18, &x19, x14, 0xffffffff);
+ var x20: u64 = undefined;
+ var x21: u64 = undefined;
+ mulxU64(&x20, &x21, x14, 0xffffffffffffffff);
+ var x22: u64 = undefined;
+ var x23: u1 = undefined;
+ addcarryxU64(&x22, &x23, 0x0, x21, x18);
+ var x24: u64 = undefined;
+ var x25: u1 = undefined;
+ addcarryxU64(&x24, &x25, 0x0, x14, x20);
+ var x26: u64 = undefined;
+ var x27: u1 = undefined;
+ addcarryxU64(&x26, &x27, x25, (cast(u64, x15) + (cast(u64, x13) + (cast(u64, x9) + x5))), x22);
+ var x28: u64 = undefined;
+ var x29: u1 = undefined;
+ addcarryxU64(&x28, &x29, x27, x2, (cast(u64, x23) + x19));
+ var x30: u64 = undefined;
+ var x31: u1 = undefined;
+ addcarryxU64(&x30, &x31, x29, x3, x16);
+ var x32: u64 = undefined;
+ var x33: u1 = undefined;
+ addcarryxU64(&x32, &x33, 0x0, x26, (arg1[2]));
+ var x34: u64 = undefined;
+ var x35: u1 = undefined;
+ addcarryxU64(&x34, &x35, x33, x28, cast(u64, 0x0));
+ var x36: u64 = undefined;
+ var x37: u1 = undefined;
+ addcarryxU64(&x36, &x37, x35, x30, cast(u64, 0x0));
+ var x38: u64 = undefined;
+ var x39: u64 = undefined;
+ mulxU64(&x38, &x39, x32, 0xffffffff00000001);
+ var x40: u64 = undefined;
+ var x41: u64 = undefined;
+ mulxU64(&x40, &x41, x32, 0xffffffff);
+ var x42: u64 = undefined;
+ var x43: u64 = undefined;
+ mulxU64(&x42, &x43, x32, 0xffffffffffffffff);
+ var x44: u64 = undefined;
+ var x45: u1 = undefined;
+ addcarryxU64(&x44, &x45, 0x0, x43, x40);
+ var x46: u64 = undefined;
+ var x47: u1 = undefined;
+ addcarryxU64(&x46, &x47, 0x0, x32, x42);
+ var x48: u64 = undefined;
+ var x49: u1 = undefined;
+ addcarryxU64(&x48, &x49, x47, x34, x44);
+ var x50: u64 = undefined;
+ var x51: u1 = undefined;
+ addcarryxU64(&x50, &x51, x49, x36, (cast(u64, x45) + x41));
+ var x52: u64 = undefined;
+ var x53: u1 = undefined;
+ addcarryxU64(&x52, &x53, x51, (cast(u64, x37) + (cast(u64, x31) + x17)), x38);
+ var x54: u64 = undefined;
+ var x55: u1 = undefined;
+ addcarryxU64(&x54, &x55, 0x0, x48, (arg1[3]));
+ var x56: u64 = undefined;
+ var x57: u1 = undefined;
+ addcarryxU64(&x56, &x57, x55, x50, cast(u64, 0x0));
+ var x58: u64 = undefined;
+ var x59: u1 = undefined;
+ addcarryxU64(&x58, &x59, x57, x52, cast(u64, 0x0));
+ var x60: u64 = undefined;
+ var x61: u64 = undefined;
+ mulxU64(&x60, &x61, x54, 0xffffffff00000001);
+ var x62: u64 = undefined;
+ var x63: u64 = undefined;
+ mulxU64(&x62, &x63, x54, 0xffffffff);
+ var x64: u64 = undefined;
+ var x65: u64 = undefined;
+ mulxU64(&x64, &x65, x54, 0xffffffffffffffff);
+ var x66: u64 = undefined;
+ var x67: u1 = undefined;
+ addcarryxU64(&x66, &x67, 0x0, x65, x62);
+ var x68: u64 = undefined;
+ var x69: u1 = undefined;
+ addcarryxU64(&x68, &x69, 0x0, x54, x64);
+ var x70: u64 = undefined;
+ var x71: u1 = undefined;
+ addcarryxU64(&x70, &x71, x69, x56, x66);
+ var x72: u64 = undefined;
+ var x73: u1 = undefined;
+ addcarryxU64(&x72, &x73, x71, x58, (cast(u64, x67) + x63));
+ var x74: u64 = undefined;
+ var x75: u1 = undefined;
+ addcarryxU64(&x74, &x75, x73, (cast(u64, x59) + (cast(u64, x53) + x39)), x60);
+ const x76 = (cast(u64, x75) + x61);
+ var x77: u64 = undefined;
+ var x78: u1 = undefined;
+ subborrowxU64(&x77, &x78, 0x0, x70, 0xffffffffffffffff);
+ var x79: u64 = undefined;
+ var x80: u1 = undefined;
+ subborrowxU64(&x79, &x80, x78, x72, 0xffffffff);
+ var x81: u64 = undefined;
+ var x82: u1 = undefined;
+ subborrowxU64(&x81, &x82, x80, x74, cast(u64, 0x0));
+ var x83: u64 = undefined;
+ var x84: u1 = undefined;
+ subborrowxU64(&x83, &x84, x82, x76, 0xffffffff00000001);
+ var x85: u64 = undefined;
+ var x86: u1 = undefined;
+ subborrowxU64(&x85, &x86, x84, cast(u64, 0x0), cast(u64, 0x0));
+ var x87: u64 = undefined;
+ cmovznzU64(&x87, x86, x77, x70);
+ var x88: u64 = undefined;
+ cmovznzU64(&x88, x86, x79, x72);
+ var x89: u64 = undefined;
+ cmovznzU64(&x89, x86, x81, x74);
+ var x90: u64 = undefined;
+ cmovznzU64(&x90, x86, x83, x76);
+ out1[0] = x87;
+ out1[1] = x88;
+ out1[2] = x89;
+ out1[3] = x90;
+}
+
+/// The function toMontgomery translates a field element into the Montgomery domain.
+/// Preconditions:
+/// 0 ≤ eval arg1 < m
+/// Postconditions:
+/// eval (from_montgomery out1) mod m = eval arg1 mod m
+/// 0 ≤ eval out1 < m
+///
+/// Input Bounds:
+/// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+/// Output Bounds:
+/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+pub fn toMontgomery(out1: *[4]u64, arg1: [4]u64) void {
+ @setRuntimeSafety(mode == .Debug);
+
+ const x1 = (arg1[1]);
+ const x2 = (arg1[2]);
+ const x3 = (arg1[3]);
+ const x4 = (arg1[0]);
+ var x5: u64 = undefined;
+ var x6: u64 = undefined;
+ mulxU64(&x5, &x6, x4, 0x4fffffffd);
+ var x7: u64 = undefined;
+ var x8: u64 = undefined;
+ mulxU64(&x7, &x8, x4, 0xfffffffffffffffe);
+ var x9: u64 = undefined;
+ var x10: u64 = undefined;
+ mulxU64(&x9, &x10, x4, 0xfffffffbffffffff);
+ var x11: u64 = undefined;
+ var x12: u64 = undefined;
+ mulxU64(&x11, &x12, x4, 0x3);
+ var x13: u64 = undefined;
+ var x14: u1 = undefined;
+ addcarryxU64(&x13, &x14, 0x0, x12, x9);
+ var x15: u64 = undefined;
+ var x16: u1 = undefined;
+ addcarryxU64(&x15, &x16, x14, x10, x7);
+ var x17: u64 = undefined;
+ var x18: u1 = undefined;
+ addcarryxU64(&x17, &x18, x16, x8, x5);
+ var x19: u64 = undefined;
+ var x20: u64 = undefined;
+ mulxU64(&x19, &x20, x11, 0xffffffff00000001);
+ var x21: u64 = undefined;
+ var x22: u64 = undefined;
+ mulxU64(&x21, &x22, x11, 0xffffffff);
+ var x23: u64 = undefined;
+ var x24: u64 = undefined;
+ mulxU64(&x23, &x24, x11, 0xffffffffffffffff);
+ var x25: u64 = undefined;
+ var x26: u1 = undefined;
+ addcarryxU64(&x25, &x26, 0x0, x24, x21);
+ var x27: u64 = undefined;
+ var x28: u1 = undefined;
+ addcarryxU64(&x27, &x28, 0x0, x11, x23);
+ var x29: u64 = undefined;
+ var x30: u1 = undefined;
+ addcarryxU64(&x29, &x30, x28, x13, x25);
+ var x31: u64 = undefined;
+ var x32: u1 = undefined;
+ addcarryxU64(&x31, &x32, x30, x15, (cast(u64, x26) + x22));
+ var x33: u64 = undefined;
+ var x34: u1 = undefined;
+ addcarryxU64(&x33, &x34, x32, x17, x19);
+ var x35: u64 = undefined;
+ var x36: u1 = undefined;
+ addcarryxU64(&x35, &x36, x34, (cast(u64, x18) + x6), x20);
+ var x37: u64 = undefined;
+ var x38: u64 = undefined;
+ mulxU64(&x37, &x38, x1, 0x4fffffffd);
+ var x39: u64 = undefined;
+ var x40: u64 = undefined;
+ mulxU64(&x39, &x40, x1, 0xfffffffffffffffe);
+ var x41: u64 = undefined;
+ var x42: u64 = undefined;
+ mulxU64(&x41, &x42, x1, 0xfffffffbffffffff);
+ var x43: u64 = undefined;
+ var x44: u64 = undefined;
+ mulxU64(&x43, &x44, x1, 0x3);
+ var x45: u64 = undefined;
+ var x46: u1 = undefined;
+ addcarryxU64(&x45, &x46, 0x0, x44, x41);
+ var x47: u64 = undefined;
+ var x48: u1 = undefined;
+ addcarryxU64(&x47, &x48, x46, x42, x39);
+ var x49: u64 = undefined;
+ var x50: u1 = undefined;
+ addcarryxU64(&x49, &x50, x48, x40, x37);
+ var x51: u64 = undefined;
+ var x52: u1 = undefined;
+ addcarryxU64(&x51, &x52, 0x0, x29, x43);
+ var x53: u64 = undefined;
+ var x54: u1 = undefined;
+ addcarryxU64(&x53, &x54, x52, x31, x45);
+ var x55: u64 = undefined;
+ var x56: u1 = undefined;
+ addcarryxU64(&x55, &x56, x54, x33, x47);
+ var x57: u64 = undefined;
+ var x58: u1 = undefined;
+ addcarryxU64(&x57, &x58, x56, x35, x49);
+ var x59: u64 = undefined;
+ var x60: u64 = undefined;
+ mulxU64(&x59, &x60, x51, 0xffffffff00000001);
+ var x61: u64 = undefined;
+ var x62: u64 = undefined;
+ mulxU64(&x61, &x62, x51, 0xffffffff);
+ var x63: u64 = undefined;
+ var x64: u64 = undefined;
+ mulxU64(&x63, &x64, x51, 0xffffffffffffffff);
+ var x65: u64 = undefined;
+ var x66: u1 = undefined;
+ addcarryxU64(&x65, &x66, 0x0, x64, x61);
+ var x67: u64 = undefined;
+ var x68: u1 = undefined;
+ addcarryxU64(&x67, &x68, 0x0, x51, x63);
+ var x69: u64 = undefined;
+ var x70: u1 = undefined;
+ addcarryxU64(&x69, &x70, x68, x53, x65);
+ var x71: u64 = undefined;
+ var x72: u1 = undefined;
+ addcarryxU64(&x71, &x72, x70, x55, (cast(u64, x66) + x62));
+ var x73: u64 = undefined;
+ var x74: u1 = undefined;
+ addcarryxU64(&x73, &x74, x72, x57, x59);
+ var x75: u64 = undefined;
+ var x76: u1 = undefined;
+ addcarryxU64(&x75, &x76, x74, ((cast(u64, x58) + cast(u64, x36)) + (cast(u64, x50) + x38)), x60);
+ var x77: u64 = undefined;
+ var x78: u64 = undefined;
+ mulxU64(&x77, &x78, x2, 0x4fffffffd);
+ var x79: u64 = undefined;
+ var x80: u64 = undefined;
+ mulxU64(&x79, &x80, x2, 0xfffffffffffffffe);
+ var x81: u64 = undefined;
+ var x82: u64 = undefined;
+ mulxU64(&x81, &x82, x2, 0xfffffffbffffffff);
+ var x83: u64 = undefined;
+ var x84: u64 = undefined;
+ mulxU64(&x83, &x84, x2, 0x3);
+ var x85: u64 = undefined;
+ var x86: u1 = undefined;
+ addcarryxU64(&x85, &x86, 0x0, x84, x81);
+ var x87: u64 = undefined;
+ var x88: u1 = undefined;
+ addcarryxU64(&x87, &x88, x86, x82, x79);
+ var x89: u64 = undefined;
+ var x90: u1 = undefined;
+ addcarryxU64(&x89, &x90, x88, x80, x77);
+ var x91: u64 = undefined;
+ var x92: u1 = undefined;
+ addcarryxU64(&x91, &x92, 0x0, x69, x83);
+ var x93: u64 = undefined;
+ var x94: u1 = undefined;
+ addcarryxU64(&x93, &x94, x92, x71, x85);
+ var x95: u64 = undefined;
+ var x96: u1 = undefined;
+ addcarryxU64(&x95, &x96, x94, x73, x87);
+ var x97: u64 = undefined;
+ var x98: u1 = undefined;
+ addcarryxU64(&x97, &x98, x96, x75, x89);
+ var x99: u64 = undefined;
+ var x100: u64 = undefined;
+ mulxU64(&x99, &x100, x91, 0xffffffff00000001);
+ var x101: u64 = undefined;
+ var x102: u64 = undefined;
+ mulxU64(&x101, &x102, x91, 0xffffffff);
+ var x103: u64 = undefined;
+ var x104: u64 = undefined;
+ mulxU64(&x103, &x104, x91, 0xffffffffffffffff);
+ var x105: u64 = undefined;
+ var x106: u1 = undefined;
+ addcarryxU64(&x105, &x106, 0x0, x104, x101);
+ var x107: u64 = undefined;
+ var x108: u1 = undefined;
+ addcarryxU64(&x107, &x108, 0x0, x91, x103);
+ var x109: u64 = undefined;
+ var x110: u1 = undefined;
+ addcarryxU64(&x109, &x110, x108, x93, x105);
+ var x111: u64 = undefined;
+ var x112: u1 = undefined;
+ addcarryxU64(&x111, &x112, x110, x95, (cast(u64, x106) + x102));
+ var x113: u64 = undefined;
+ var x114: u1 = undefined;
+ addcarryxU64(&x113, &x114, x112, x97, x99);
+ var x115: u64 = undefined;
+ var x116: u1 = undefined;
+ addcarryxU64(&x115, &x116, x114, ((cast(u64, x98) + cast(u64, x76)) + (cast(u64, x90) + x78)), x100);
+ var x117: u64 = undefined;
+ var x118: u64 = undefined;
+ mulxU64(&x117, &x118, x3, 0x4fffffffd);
+ var x119: u64 = undefined;
+ var x120: u64 = undefined;
+ mulxU64(&x119, &x120, x3, 0xfffffffffffffffe);
+ var x121: u64 = undefined;
+ var x122: u64 = undefined;
+ mulxU64(&x121, &x122, x3, 0xfffffffbffffffff);
+ var x123: u64 = undefined;
+ var x124: u64 = undefined;
+ mulxU64(&x123, &x124, x3, 0x3);
+ var x125: u64 = undefined;
+ var x126: u1 = undefined;
+ addcarryxU64(&x125, &x126, 0x0, x124, x121);
+ var x127: u64 = undefined;
+ var x128: u1 = undefined;
+ addcarryxU64(&x127, &x128, x126, x122, x119);
+ var x129: u64 = undefined;
+ var x130: u1 = undefined;
+ addcarryxU64(&x129, &x130, x128, x120, x117);
+ var x131: u64 = undefined;
+ var x132: u1 = undefined;
+ addcarryxU64(&x131, &x132, 0x0, x109, x123);
+ var x133: u64 = undefined;
+ var x134: u1 = undefined;
+ addcarryxU64(&x133, &x134, x132, x111, x125);
+ var x135: u64 = undefined;
+ var x136: u1 = undefined;
+ addcarryxU64(&x135, &x136, x134, x113, x127);
+ var x137: u64 = undefined;
+ var x138: u1 = undefined;
+ addcarryxU64(&x137, &x138, x136, x115, x129);
+ var x139: u64 = undefined;
+ var x140: u64 = undefined;
+ mulxU64(&x139, &x140, x131, 0xffffffff00000001);
+ var x141: u64 = undefined;
+ var x142: u64 = undefined;
+ mulxU64(&x141, &x142, x131, 0xffffffff);
+ var x143: u64 = undefined;
+ var x144: u64 = undefined;
+ mulxU64(&x143, &x144, x131, 0xffffffffffffffff);
+ var x145: u64 = undefined;
+ var x146: u1 = undefined;
+ addcarryxU64(&x145, &x146, 0x0, x144, x141);
+ var x147: u64 = undefined;
+ var x148: u1 = undefined;
+ addcarryxU64(&x147, &x148, 0x0, x131, x143);
+ var x149: u64 = undefined;
+ var x150: u1 = undefined;
+ addcarryxU64(&x149, &x150, x148, x133, x145);
+ var x151: u64 = undefined;
+ var x152: u1 = undefined;
+ addcarryxU64(&x151, &x152, x150, x135, (cast(u64, x146) + x142));
+ var x153: u64 = undefined;
+ var x154: u1 = undefined;
+ addcarryxU64(&x153, &x154, x152, x137, x139);
+ var x155: u64 = undefined;
+ var x156: u1 = undefined;
+ addcarryxU64(&x155, &x156, x154, ((cast(u64, x138) + cast(u64, x116)) + (cast(u64, x130) + x118)), x140);
+ var x157: u64 = undefined;
+ var x158: u1 = undefined;
+ subborrowxU64(&x157, &x158, 0x0, x149, 0xffffffffffffffff);
+ var x159: u64 = undefined;
+ var x160: u1 = undefined;
+ subborrowxU64(&x159, &x160, x158, x151, 0xffffffff);
+ var x161: u64 = undefined;
+ var x162: u1 = undefined;
+ subborrowxU64(&x161, &x162, x160, x153, cast(u64, 0x0));
+ var x163: u64 = undefined;
+ var x164: u1 = undefined;
+ subborrowxU64(&x163, &x164, x162, x155, 0xffffffff00000001);
+ var x165: u64 = undefined;
+ var x166: u1 = undefined;
+ subborrowxU64(&x165, &x166, x164, cast(u64, x156), cast(u64, 0x0));
+ var x167: u64 = undefined;
+ cmovznzU64(&x167, x166, x157, x149);
+ var x168: u64 = undefined;
+ cmovznzU64(&x168, x166, x159, x151);
+ var x169: u64 = undefined;
+ cmovznzU64(&x169, x166, x161, x153);
+ var x170: u64 = undefined;
+ cmovznzU64(&x170, x166, x163, x155);
+ out1[0] = x167;
+ out1[1] = x168;
+ out1[2] = x169;
+ out1[3] = x170;
+}
+
+/// The function nonzero outputs a single non-zero word if the input is non-zero and zero otherwise.
+/// Preconditions:
+/// 0 ≤ eval arg1 < m
+/// Postconditions:
+/// out1 = 0 ↔ eval (from_montgomery arg1) mod m = 0
+///
+/// Input Bounds:
+/// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+/// Output Bounds:
+/// out1: [0x0 ~> 0xffffffffffffffff]
+pub fn nonzero(out1: *u64, arg1: [4]u64) void {
+ @setRuntimeSafety(mode == .Debug);
+
+ const x1 = ((arg1[0]) | ((arg1[1]) | ((arg1[2]) | (arg1[3]))));
+ out1.* = x1;
+}
+
+/// The function selectznz is a multi-limb conditional select.
+/// Postconditions:
+/// eval out1 = (if arg1 = 0 then eval arg2 else eval arg3)
+///
+/// Input Bounds:
+/// arg1: [0x0 ~> 0x1]
+/// arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+/// arg3: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+/// Output Bounds:
+/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+pub fn selectznz(out1: *[4]u64, arg1: u1, arg2: [4]u64, arg3: [4]u64) void {
+ @setRuntimeSafety(mode == .Debug);
+
+ var x1: u64 = undefined;
+ cmovznzU64(&x1, arg1, (arg2[0]), (arg3[0]));
+ var x2: u64 = undefined;
+ cmovznzU64(&x2, arg1, (arg2[1]), (arg3[1]));
+ var x3: u64 = undefined;
+ cmovznzU64(&x3, arg1, (arg2[2]), (arg3[2]));
+ var x4: u64 = undefined;
+ cmovznzU64(&x4, arg1, (arg2[3]), (arg3[3]));
+ out1[0] = x1;
+ out1[1] = x2;
+ out1[2] = x3;
+ out1[3] = x4;
+}
+
+/// The function toBytes serializes a field element NOT in the Montgomery domain to bytes in little-endian order.
+/// Preconditions:
+/// 0 ≤ eval arg1 < m
+/// Postconditions:
+/// out1 = map (λ x, ⌊((eval arg1 mod m) mod 2^(8 * (x + 1))) / 2^(8 * x)⌋) [0..31]
+///
+/// Input Bounds:
+/// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+/// Output Bounds:
+/// out1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff]]
+pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void {
+ @setRuntimeSafety(mode == .Debug);
+
+ const x1 = (arg1[3]);
+ const x2 = (arg1[2]);
+ const x3 = (arg1[1]);
+ const x4 = (arg1[0]);
+ const x5 = cast(u8, (x4 & cast(u64, 0xff)));
+ const x6 = (x4 >> 8);
+ const x7 = cast(u8, (x6 & cast(u64, 0xff)));
+ const x8 = (x6 >> 8);
+ const x9 = cast(u8, (x8 & cast(u64, 0xff)));
+ const x10 = (x8 >> 8);
+ const x11 = cast(u8, (x10 & cast(u64, 0xff)));
+ const x12 = (x10 >> 8);
+ const x13 = cast(u8, (x12 & cast(u64, 0xff)));
+ const x14 = (x12 >> 8);
+ const x15 = cast(u8, (x14 & cast(u64, 0xff)));
+ const x16 = (x14 >> 8);
+ const x17 = cast(u8, (x16 & cast(u64, 0xff)));
+ const x18 = cast(u8, (x16 >> 8));
+ const x19 = cast(u8, (x3 & cast(u64, 0xff)));
+ const x20 = (x3 >> 8);
+ const x21 = cast(u8, (x20 & cast(u64, 0xff)));
+ const x22 = (x20 >> 8);
+ const x23 = cast(u8, (x22 & cast(u64, 0xff)));
+ const x24 = (x22 >> 8);
+ const x25 = cast(u8, (x24 & cast(u64, 0xff)));
+ const x26 = (x24 >> 8);
+ const x27 = cast(u8, (x26 & cast(u64, 0xff)));
+ const x28 = (x26 >> 8);
+ const x29 = cast(u8, (x28 & cast(u64, 0xff)));
+ const x30 = (x28 >> 8);
+ const x31 = cast(u8, (x30 & cast(u64, 0xff)));
+ const x32 = cast(u8, (x30 >> 8));
+ const x33 = cast(u8, (x2 & cast(u64, 0xff)));
+ const x34 = (x2 >> 8);
+ const x35 = cast(u8, (x34 & cast(u64, 0xff)));
+ const x36 = (x34 >> 8);
+ const x37 = cast(u8, (x36 & cast(u64, 0xff)));
+ const x38 = (x36 >> 8);
+ const x39 = cast(u8, (x38 & cast(u64, 0xff)));
+ const x40 = (x38 >> 8);
+ const x41 = cast(u8, (x40 & cast(u64, 0xff)));
+ const x42 = (x40 >> 8);
+ const x43 = cast(u8, (x42 & cast(u64, 0xff)));
+ const x44 = (x42 >> 8);
+ const x45 = cast(u8, (x44 & cast(u64, 0xff)));
+ const x46 = cast(u8, (x44 >> 8));
+ const x47 = cast(u8, (x1 & cast(u64, 0xff)));
+ const x48 = (x1 >> 8);
+ const x49 = cast(u8, (x48 & cast(u64, 0xff)));
+ const x50 = (x48 >> 8);
+ const x51 = cast(u8, (x50 & cast(u64, 0xff)));
+ const x52 = (x50 >> 8);
+ const x53 = cast(u8, (x52 & cast(u64, 0xff)));
+ const x54 = (x52 >> 8);
+ const x55 = cast(u8, (x54 & cast(u64, 0xff)));
+ const x56 = (x54 >> 8);
+ const x57 = cast(u8, (x56 & cast(u64, 0xff)));
+ const x58 = (x56 >> 8);
+ const x59 = cast(u8, (x58 & cast(u64, 0xff)));
+ const x60 = cast(u8, (x58 >> 8));
+ out1[0] = x5;
+ out1[1] = x7;
+ out1[2] = x9;
+ out1[3] = x11;
+ out1[4] = x13;
+ out1[5] = x15;
+ out1[6] = x17;
+ out1[7] = x18;
+ out1[8] = x19;
+ out1[9] = x21;
+ out1[10] = x23;
+ out1[11] = x25;
+ out1[12] = x27;
+ out1[13] = x29;
+ out1[14] = x31;
+ out1[15] = x32;
+ out1[16] = x33;
+ out1[17] = x35;
+ out1[18] = x37;
+ out1[19] = x39;
+ out1[20] = x41;
+ out1[21] = x43;
+ out1[22] = x45;
+ out1[23] = x46;
+ out1[24] = x47;
+ out1[25] = x49;
+ out1[26] = x51;
+ out1[27] = x53;
+ out1[28] = x55;
+ out1[29] = x57;
+ out1[30] = x59;
+ out1[31] = x60;
+}
+
+/// The function fromBytes deserializes a field element NOT in the Montgomery domain from bytes in little-endian order.
+/// Preconditions:
+/// 0 ≤ bytes_eval arg1 < m
+/// Postconditions:
+/// eval out1 mod m = bytes_eval arg1 mod m
+/// 0 ≤ eval out1 < m
+///
+/// Input Bounds:
+/// 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]]
+/// Output Bounds:
+/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void {
+ @setRuntimeSafety(mode == .Debug);
+
+ const x1 = (cast(u64, (arg1[31])) << 56);
+ const x2 = (cast(u64, (arg1[30])) << 48);
+ const x3 = (cast(u64, (arg1[29])) << 40);
+ const x4 = (cast(u64, (arg1[28])) << 32);
+ const x5 = (cast(u64, (arg1[27])) << 24);
+ const x6 = (cast(u64, (arg1[26])) << 16);
+ const x7 = (cast(u64, (arg1[25])) << 8);
+ const x8 = (arg1[24]);
+ const x9 = (cast(u64, (arg1[23])) << 56);
+ const x10 = (cast(u64, (arg1[22])) << 48);
+ const x11 = (cast(u64, (arg1[21])) << 40);
+ const x12 = (cast(u64, (arg1[20])) << 32);
+ const x13 = (cast(u64, (arg1[19])) << 24);
+ const x14 = (cast(u64, (arg1[18])) << 16);
+ const x15 = (cast(u64, (arg1[17])) << 8);
+ const x16 = (arg1[16]);
+ const x17 = (cast(u64, (arg1[15])) << 56);
+ const x18 = (cast(u64, (arg1[14])) << 48);
+ const x19 = (cast(u64, (arg1[13])) << 40);
+ const x20 = (cast(u64, (arg1[12])) << 32);
+ const x21 = (cast(u64, (arg1[11])) << 24);
+ const x22 = (cast(u64, (arg1[10])) << 16);
+ const x23 = (cast(u64, (arg1[9])) << 8);
+ const x24 = (arg1[8]);
+ const x25 = (cast(u64, (arg1[7])) << 56);
+ const x26 = (cast(u64, (arg1[6])) << 48);
+ const x27 = (cast(u64, (arg1[5])) << 40);
+ const x28 = (cast(u64, (arg1[4])) << 32);
+ const x29 = (cast(u64, (arg1[3])) << 24);
+ const x30 = (cast(u64, (arg1[2])) << 16);
+ const x31 = (cast(u64, (arg1[1])) << 8);
+ const x32 = (arg1[0]);
+ const x33 = (x31 + cast(u64, x32));
+ const x34 = (x30 + x33);
+ const x35 = (x29 + x34);
+ const x36 = (x28 + x35);
+ const x37 = (x27 + x36);
+ const x38 = (x26 + x37);
+ const x39 = (x25 + x38);
+ const x40 = (x23 + cast(u64, x24));
+ const x41 = (x22 + x40);
+ const x42 = (x21 + x41);
+ const x43 = (x20 + x42);
+ const x44 = (x19 + x43);
+ const x45 = (x18 + x44);
+ const x46 = (x17 + x45);
+ const x47 = (x15 + cast(u64, x16));
+ const x48 = (x14 + x47);
+ const x49 = (x13 + x48);
+ const x50 = (x12 + x49);
+ const x51 = (x11 + x50);
+ const x52 = (x10 + x51);
+ const x53 = (x9 + x52);
+ const x54 = (x7 + cast(u64, x8));
+ const x55 = (x6 + x54);
+ const x56 = (x5 + x55);
+ const x57 = (x4 + x56);
+ const x58 = (x3 + x57);
+ const x59 = (x2 + x58);
+ const x60 = (x1 + x59);
+ out1[0] = x39;
+ out1[1] = x46;
+ out1[2] = x53;
+ out1[3] = x60;
+}
+
+/// The function setOne returns the field element one in the Montgomery domain.
+/// Postconditions:
+/// eval (from_montgomery out1) mod m = 1 mod m
+/// 0 ≤ eval out1 < m
+///
+/// Input Bounds:
+/// Output Bounds:
+/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+pub fn setOne(out1: *[4]u64) void {
+ @setRuntimeSafety(mode == .Debug);
+
+ out1[0] = cast(u64, 0x1);
+ out1[1] = 0xffffffff00000000;
+ out1[2] = 0xffffffffffffffff;
+ out1[3] = 0xfffffffe;
+}
+
+/// The function msat returns the saturated representation of the prime modulus.
+/// Postconditions:
+/// twos_complement_eval out1 = m
+/// 0 ≤ eval out1 < m
+///
+/// Input Bounds:
+/// Output Bounds:
+/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+pub fn msat(out1: *[5]u64) void {
+ @setRuntimeSafety(mode == .Debug);
+
+ out1[0] = 0xffffffffffffffff;
+ out1[1] = 0xffffffff;
+ out1[2] = cast(u64, 0x0);
+ out1[3] = 0xffffffff00000001;
+ out1[4] = cast(u64, 0x0);
+}
+
+/// The function divstep computes a divstep.
+/// Preconditions:
+/// 0 ≤ eval arg4 < m
+/// 0 ≤ eval arg5 < m
+/// Postconditions:
+/// out1 = (if 0 < arg1 ∧ (twos_complement_eval arg3) is odd then 1 - arg1 else 1 + arg1)
+/// twos_complement_eval out2 = (if 0 < arg1 ∧ (twos_complement_eval arg3) is odd then twos_complement_eval arg3 else twos_complement_eval arg2)
+/// 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⌋)
+/// 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)
+/// 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)
+/// 0 ≤ eval out5 < m
+/// 0 ≤ eval out5 < m
+/// 0 ≤ eval out2 < m
+/// 0 ≤ eval out3 < m
+///
+/// Input Bounds:
+/// arg1: [0x0 ~> 0xffffffffffffffff]
+/// arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+/// arg3: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+/// arg4: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+/// arg5: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+/// Output Bounds:
+/// out1: [0x0 ~> 0xffffffffffffffff]
+/// out2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+/// out3: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+/// out4: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+/// out5: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+pub fn divstep(out1: *u64, out2: *[5]u64, out3: *[5]u64, out4: *[4]u64, out5: *[4]u64, arg1: u64, arg2: [5]u64, arg3: [5]u64, arg4: [4]u64, arg5: [4]u64) void {
+ @setRuntimeSafety(mode == .Debug);
+
+ var x1: u64 = undefined;
+ var x2: u1 = undefined;
+ addcarryxU64(&x1, &x2, 0x0, (~arg1), cast(u64, 0x1));
+ const x3 = (cast(u1, (x1 >> 63)) & cast(u1, ((arg3[0]) & cast(u64, 0x1))));
+ var x4: u64 = undefined;
+ var x5: u1 = undefined;
+ addcarryxU64(&x4, &x5, 0x0, (~arg1), cast(u64, 0x1));
+ var x6: u64 = undefined;
+ cmovznzU64(&x6, x3, arg1, x4);
+ var x7: u64 = undefined;
+ cmovznzU64(&x7, x3, (arg2[0]), (arg3[0]));
+ var x8: u64 = undefined;
+ cmovznzU64(&x8, x3, (arg2[1]), (arg3[1]));
+ var x9: u64 = undefined;
+ cmovznzU64(&x9, x3, (arg2[2]), (arg3[2]));
+ var x10: u64 = undefined;
+ cmovznzU64(&x10, x3, (arg2[3]), (arg3[3]));
+ var x11: u64 = undefined;
+ cmovznzU64(&x11, x3, (arg2[4]), (arg3[4]));
+ var x12: u64 = undefined;
+ var x13: u1 = undefined;
+ addcarryxU64(&x12, &x13, 0x0, cast(u64, 0x1), (~(arg2[0])));
+ var x14: u64 = undefined;
+ var x15: u1 = undefined;
+ addcarryxU64(&x14, &x15, x13, cast(u64, 0x0), (~(arg2[1])));
+ var x16: u64 = undefined;
+ var x17: u1 = undefined;
+ addcarryxU64(&x16, &x17, x15, cast(u64, 0x0), (~(arg2[2])));
+ var x18: u64 = undefined;
+ var x19: u1 = undefined;
+ addcarryxU64(&x18, &x19, x17, cast(u64, 0x0), (~(arg2[3])));
+ var x20: u64 = undefined;
+ var x21: u1 = undefined;
+ addcarryxU64(&x20, &x21, x19, cast(u64, 0x0), (~(arg2[4])));
+ var x22: u64 = undefined;
+ cmovznzU64(&x22, x3, (arg3[0]), x12);
+ var x23: u64 = undefined;
+ cmovznzU64(&x23, x3, (arg3[1]), x14);
+ var x24: u64 = undefined;
+ cmovznzU64(&x24, x3, (arg3[2]), x16);
+ var x25: u64 = undefined;
+ cmovznzU64(&x25, x3, (arg3[3]), x18);
+ var x26: u64 = undefined;
+ cmovznzU64(&x26, x3, (arg3[4]), x20);
+ var x27: u64 = undefined;
+ cmovznzU64(&x27, x3, (arg4[0]), (arg5[0]));
+ var x28: u64 = undefined;
+ cmovznzU64(&x28, x3, (arg4[1]), (arg5[1]));
+ var x29: u64 = undefined;
+ cmovznzU64(&x29, x3, (arg4[2]), (arg5[2]));
+ var x30: u64 = undefined;
+ cmovznzU64(&x30, x3, (arg4[3]), (arg5[3]));
+ var x31: u64 = undefined;
+ var x32: u1 = undefined;
+ addcarryxU64(&x31, &x32, 0x0, x27, x27);
+ var x33: u64 = undefined;
+ var x34: u1 = undefined;
+ addcarryxU64(&x33, &x34, x32, x28, x28);
+ var x35: u64 = undefined;
+ var x36: u1 = undefined;
+ addcarryxU64(&x35, &x36, x34, x29, x29);
+ var x37: u64 = undefined;
+ var x38: u1 = undefined;
+ addcarryxU64(&x37, &x38, x36, x30, x30);
+ var x39: u64 = undefined;
+ var x40: u1 = undefined;
+ subborrowxU64(&x39, &x40, 0x0, x31, 0xffffffffffffffff);
+ var x41: u64 = undefined;
+ var x42: u1 = undefined;
+ subborrowxU64(&x41, &x42, x40, x33, 0xffffffff);
+ var x43: u64 = undefined;
+ var x44: u1 = undefined;
+ subborrowxU64(&x43, &x44, x42, x35, cast(u64, 0x0));
+ var x45: u64 = undefined;
+ var x46: u1 = undefined;
+ subborrowxU64(&x45, &x46, x44, x37, 0xffffffff00000001);
+ var x47: u64 = undefined;
+ var x48: u1 = undefined;
+ subborrowxU64(&x47, &x48, x46, cast(u64, x38), cast(u64, 0x0));
+ const x49 = (arg4[3]);
+ const x50 = (arg4[2]);
+ const x51 = (arg4[1]);
+ const x52 = (arg4[0]);
+ var x53: u64 = undefined;
+ var x54: u1 = undefined;
+ subborrowxU64(&x53, &x54, 0x0, cast(u64, 0x0), x52);
+ var x55: u64 = undefined;
+ var x56: u1 = undefined;
+ subborrowxU64(&x55, &x56, x54, cast(u64, 0x0), x51);
+ var x57: u64 = undefined;
+ var x58: u1 = undefined;
+ subborrowxU64(&x57, &x58, x56, cast(u64, 0x0), x50);
+ var x59: u64 = undefined;
+ var x60: u1 = undefined;
+ subborrowxU64(&x59, &x60, x58, cast(u64, 0x0), x49);
+ var x61: u64 = undefined;
+ cmovznzU64(&x61, x60, cast(u64, 0x0), 0xffffffffffffffff);
+ var x62: u64 = undefined;
+ var x63: u1 = undefined;
+ addcarryxU64(&x62, &x63, 0x0, x53, x61);
+ var x64: u64 = undefined;
+ var x65: u1 = undefined;
+ addcarryxU64(&x64, &x65, x63, x55, (x61 & 0xffffffff));
+ var x66: u64 = undefined;
+ var x67: u1 = undefined;
+ addcarryxU64(&x66, &x67, x65, x57, cast(u64, 0x0));
+ var x68: u64 = undefined;
+ var x69: u1 = undefined;
+ addcarryxU64(&x68, &x69, x67, x59, (x61 & 0xffffffff00000001));
+ var x70: u64 = undefined;
+ cmovznzU64(&x70, x3, (arg5[0]), x62);
+ var x71: u64 = undefined;
+ cmovznzU64(&x71, x3, (arg5[1]), x64);
+ var x72: u64 = undefined;
+ cmovznzU64(&x72, x3, (arg5[2]), x66);
+ var x73: u64 = undefined;
+ cmovznzU64(&x73, x3, (arg5[3]), x68);
+ const x74 = cast(u1, (x22 & cast(u64, 0x1)));
+ var x75: u64 = undefined;
+ cmovznzU64(&x75, x74, cast(u64, 0x0), x7);
+ var x76: u64 = undefined;
+ cmovznzU64(&x76, x74, cast(u64, 0x0), x8);
+ var x77: u64 = undefined;
+ cmovznzU64(&x77, x74, cast(u64, 0x0), x9);
+ var x78: u64 = undefined;
+ cmovznzU64(&x78, x74, cast(u64, 0x0), x10);
+ var x79: u64 = undefined;
+ cmovznzU64(&x79, x74, cast(u64, 0x0), x11);
+ var x80: u64 = undefined;
+ var x81: u1 = undefined;
+ addcarryxU64(&x80, &x81, 0x0, x22, x75);
+ var x82: u64 = undefined;
+ var x83: u1 = undefined;
+ addcarryxU64(&x82, &x83, x81, x23, x76);
+ var x84: u64 = undefined;
+ var x85: u1 = undefined;
+ addcarryxU64(&x84, &x85, x83, x24, x77);
+ var x86: u64 = undefined;
+ var x87: u1 = undefined;
+ addcarryxU64(&x86, &x87, x85, x25, x78);
+ var x88: u64 = undefined;
+ var x89: u1 = undefined;
+ addcarryxU64(&x88, &x89, x87, x26, x79);
+ var x90: u64 = undefined;
+ cmovznzU64(&x90, x74, cast(u64, 0x0), x27);
+ var x91: u64 = undefined;
+ cmovznzU64(&x91, x74, cast(u64, 0x0), x28);
+ var x92: u64 = undefined;
+ cmovznzU64(&x92, x74, cast(u64, 0x0), x29);
+ var x93: u64 = undefined;
+ cmovznzU64(&x93, x74, cast(u64, 0x0), x30);
+ var x94: u64 = undefined;
+ var x95: u1 = undefined;
+ addcarryxU64(&x94, &x95, 0x0, x70, x90);
+ var x96: u64 = undefined;
+ var x97: u1 = undefined;
+ addcarryxU64(&x96, &x97, x95, x71, x91);
+ var x98: u64 = undefined;
+ var x99: u1 = undefined;
+ addcarryxU64(&x98, &x99, x97, x72, x92);
+ var x100: u64 = undefined;
+ var x101: u1 = undefined;
+ addcarryxU64(&x100, &x101, x99, x73, x93);
+ var x102: u64 = undefined;
+ var x103: u1 = undefined;
+ subborrowxU64(&x102, &x103, 0x0, x94, 0xffffffffffffffff);
+ var x104: u64 = undefined;
+ var x105: u1 = undefined;
+ subborrowxU64(&x104, &x105, x103, x96, 0xffffffff);
+ var x106: u64 = undefined;
+ var x107: u1 = undefined;
+ subborrowxU64(&x106, &x107, x105, x98, cast(u64, 0x0));
+ var x108: u64 = undefined;
+ var x109: u1 = undefined;
+ subborrowxU64(&x108, &x109, x107, x100, 0xffffffff00000001);
+ var x110: u64 = undefined;
+ var x111: u1 = undefined;
+ subborrowxU64(&x110, &x111, x109, cast(u64, x101), cast(u64, 0x0));
+ var x112: u64 = undefined;
+ var x113: u1 = undefined;
+ addcarryxU64(&x112, &x113, 0x0, x6, cast(u64, 0x1));
+ const x114 = ((x80 >> 1) | ((x82 << 63) & 0xffffffffffffffff));
+ const x115 = ((x82 >> 1) | ((x84 << 63) & 0xffffffffffffffff));
+ const x116 = ((x84 >> 1) | ((x86 << 63) & 0xffffffffffffffff));
+ const x117 = ((x86 >> 1) | ((x88 << 63) & 0xffffffffffffffff));
+ const x118 = ((x88 & 0x8000000000000000) | (x88 >> 1));
+ var x119: u64 = undefined;
+ cmovznzU64(&x119, x48, x39, x31);
+ var x120: u64 = undefined;
+ cmovznzU64(&x120, x48, x41, x33);
+ var x121: u64 = undefined;
+ cmovznzU64(&x121, x48, x43, x35);
+ var x122: u64 = undefined;
+ cmovznzU64(&x122, x48, x45, x37);
+ var x123: u64 = undefined;
+ cmovznzU64(&x123, x111, x102, x94);
+ var x124: u64 = undefined;
+ cmovznzU64(&x124, x111, x104, x96);
+ var x125: u64 = undefined;
+ cmovznzU64(&x125, x111, x106, x98);
+ var x126: u64 = undefined;
+ cmovznzU64(&x126, x111, x108, x100);
+ out1.* = x112;
+ out2[0] = x7;
+ out2[1] = x8;
+ out2[2] = x9;
+ out2[3] = x10;
+ out2[4] = x11;
+ out3[0] = x114;
+ out3[1] = x115;
+ out3[2] = x116;
+ out3[3] = x117;
+ out3[4] = x118;
+ out4[0] = x119;
+ out4[1] = x120;
+ out4[2] = x121;
+ out4[3] = x122;
+ out5[0] = x123;
+ out5[1] = x124;
+ out5[2] = x125;
+ out5[3] = x126;
+}
+
+/// The function divstepPrecomp returns the precomputed value for Bernstein-Yang-inversion (in montgomery form).
+/// Postconditions:
+/// 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⌋)
+/// 0 ≤ eval out1 < m
+///
+/// Input Bounds:
+/// Output Bounds:
+/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+pub fn divstepPrecomp(out1: *[4]u64) void {
+ @setRuntimeSafety(mode == .Debug);
+
+ out1[0] = 0x67ffffffb8000000;
+ out1[1] = 0xc000000038000000;
+ out1[2] = 0xd80000007fffffff;
+ out1[3] = 0x2fffffffffffffff;
+}
diff --git a/zig/lib/std/crypto/pcurves/p256/p256_scalar_64.zig b/zig/lib/std/crypto/pcurves/p256/p256_scalar_64.zig
new file mode 100644
index 0000000000..7e3cc211f5
--- /dev/null
+++ b/zig/lib/std/crypto/pcurves/p256/p256_scalar_64.zig
@@ -0,0 +1,2016 @@
+// 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
+// curve description (via package name): p256-scalar
+// machine_wordsize = 64 (from "64")
+// requested operations: (all)
+// m = 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551 (from "115792089210356248762697446949407573529996955224135760342422259061068512044369")
+//
+// NOTE: In addition to the bounds specified above each function, all
+// functions synthesized for this Montgomery arithmetic require the
+// input to be strictly less than the prime modulus (m), and also
+// require the input to be in the unique saturated representation.
+// All functions also ensure that these two properties are true of
+// return values.
+//
+// Computed values:
+// eval z = z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192)
+// 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)
+// twos_complement_eval z = let x1 := z[0] + (z[1] << 64) + (z[2] << 128) + (z[3] << 192) in
+// if x1 & (2^256-1) < 2^255 then x1 & (2^256-1) else (x1 & (2^256-1)) - 2^256
+
+const std = @import("std");
+const cast = std.meta.cast;
+const mode = std.builtin.mode; // Checked arithmetic is disabled in non-debug modes to avoid side channels
+
+pub const Limbs = [4]u64;
+
+/// The function addcarryxU64 is an addition with carry.
+/// Postconditions:
+/// out1 = (arg1 + arg2 + arg3) mod 2^64
+/// out2 = ⌊(arg1 + arg2 + arg3) / 2^64⌋
+///
+/// Input Bounds:
+/// arg1: [0x0 ~> 0x1]
+/// arg2: [0x0 ~> 0xffffffffffffffff]
+/// arg3: [0x0 ~> 0xffffffffffffffff]
+/// Output Bounds:
+/// out1: [0x0 ~> 0xffffffffffffffff]
+/// out2: [0x0 ~> 0x1]
+fn addcarryxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) callconv(.Inline) void {
+ @setRuntimeSafety(mode == .Debug);
+
+ var t: u64 = undefined;
+ const carry1 = @addWithOverflow(u64, arg2, arg3, &t);
+ const carry2 = @addWithOverflow(u64, t, arg1, out1);
+ out2.* = @boolToInt(carry1) | @boolToInt(carry2);
+}
+
+/// The function subborrowxU64 is a subtraction with borrow.
+/// Postconditions:
+/// out1 = (-arg1 + arg2 + -arg3) mod 2^64
+/// out2 = -⌊(-arg1 + arg2 + -arg3) / 2^64⌋
+///
+/// Input Bounds:
+/// arg1: [0x0 ~> 0x1]
+/// arg2: [0x0 ~> 0xffffffffffffffff]
+/// arg3: [0x0 ~> 0xffffffffffffffff]
+/// Output Bounds:
+/// out1: [0x0 ~> 0xffffffffffffffff]
+/// out2: [0x0 ~> 0x1]
+fn subborrowxU64(out1: *u64, out2: *u1, arg1: u1, arg2: u64, arg3: u64) callconv(.Inline) void {
+ @setRuntimeSafety(mode == .Debug);
+
+ var t: u64 = undefined;
+ const carry1 = @subWithOverflow(u64, arg2, arg3, &t);
+ const carry2 = @subWithOverflow(u64, t, arg1, out1);
+ out2.* = @boolToInt(carry1) | @boolToInt(carry2);
+}
+
+/// The function mulxU64 is a multiplication, returning the full double-width result.
+/// Postconditions:
+/// out1 = (arg1 * arg2) mod 2^64
+/// out2 = ⌊arg1 * arg2 / 2^64⌋
+///
+/// Input Bounds:
+/// arg1: [0x0 ~> 0xffffffffffffffff]
+/// arg2: [0x0 ~> 0xffffffffffffffff]
+/// Output Bounds:
+/// out1: [0x0 ~> 0xffffffffffffffff]
+/// out2: [0x0 ~> 0xffffffffffffffff]
+fn mulxU64(out1: *u64, out2: *u64, arg1: u64, arg2: u64) callconv(.Inline) void {
+ @setRuntimeSafety(mode == .Debug);
+
+ const x = @as(u128, arg1) * @as(u128, arg2);
+ out1.* = @truncate(u64, x);
+ out2.* = @truncate(u64, x >> 64);
+}
+
+/// The function cmovznzU64 is a single-word conditional move.
+/// Postconditions:
+/// out1 = (if arg1 = 0 then arg2 else arg3)
+///
+/// Input Bounds:
+/// arg1: [0x0 ~> 0x1]
+/// arg2: [0x0 ~> 0xffffffffffffffff]
+/// arg3: [0x0 ~> 0xffffffffffffffff]
+/// Output Bounds:
+/// out1: [0x0 ~> 0xffffffffffffffff]
+fn cmovznzU64(out1: *u64, arg1: u1, arg2: u64, arg3: u64) callconv(.Inline) void {
+ @setRuntimeSafety(mode == .Debug);
+
+ const mask = 0 -% @as(u64, arg1);
+ out1.* = (mask & arg3) | ((~mask) & arg2);
+}
+
+/// The function mul multiplies two field elements in the Montgomery domain.
+/// Preconditions:
+/// 0 ≤ eval arg1 < m
+/// 0 ≤ eval arg2 < m
+/// Postconditions:
+/// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) * eval (from_montgomery arg2)) mod m
+/// 0 ≤ eval out1 < m
+///
+/// Input Bounds:
+/// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+/// arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+/// Output Bounds:
+/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+pub fn mul(out1: *[4]u64, arg1: [4]u64, arg2: [4]u64) void {
+ @setRuntimeSafety(mode == .Debug);
+
+ const x1 = (arg1[1]);
+ const x2 = (arg1[2]);
+ const x3 = (arg1[3]);
+ const x4 = (arg1[0]);
+ var x5: u64 = undefined;
+ var x6: u64 = undefined;
+ mulxU64(&x5, &x6, x4, (arg2[3]));
+ var x7: u64 = undefined;
+ var x8: u64 = undefined;
+ mulxU64(&x7, &x8, x4, (arg2[2]));
+ var x9: u64 = undefined;
+ var x10: u64 = undefined;
+ mulxU64(&x9, &x10, x4, (arg2[1]));
+ var x11: u64 = undefined;
+ var x12: u64 = undefined;
+ mulxU64(&x11, &x12, x4, (arg2[0]));
+ var x13: u64 = undefined;
+ var x14: u1 = undefined;
+ addcarryxU64(&x13, &x14, 0x0, x12, x9);
+ var x15: u64 = undefined;
+ var x16: u1 = undefined;
+ addcarryxU64(&x15, &x16, x14, x10, x7);
+ var x17: u64 = undefined;
+ var x18: u1 = undefined;
+ addcarryxU64(&x17, &x18, x16, x8, x5);
+ const x19 = (cast(u64, x18) + x6);
+ var x20: u64 = undefined;
+ var x21: u64 = undefined;
+ mulxU64(&x20, &x21, x11, 0xccd1c8aaee00bc4f);
+ var x22: u64 = undefined;
+ var x23: u64 = undefined;
+ mulxU64(&x22, &x23, x20, 0xffffffff00000000);
+ var x24: u64 = undefined;
+ var x25: u64 = undefined;
+ mulxU64(&x24, &x25, x20, 0xffffffffffffffff);
+ var x26: u64 = undefined;
+ var x27: u64 = undefined;
+ mulxU64(&x26, &x27, x20, 0xbce6faada7179e84);
+ var x28: u64 = undefined;
+ var x29: u64 = undefined;
+ mulxU64(&x28, &x29, x20, 0xf3b9cac2fc632551);
+ var x30: u64 = undefined;
+ var x31: u1 = undefined;
+ addcarryxU64(&x30, &x31, 0x0, x29, x26);
+ var x32: u64 = undefined;
+ var x33: u1 = undefined;
+ addcarryxU64(&x32, &x33, x31, x27, x24);
+ var x34: u64 = undefined;
+ var x35: u1 = undefined;
+ addcarryxU64(&x34, &x35, x33, x25, x22);
+ const x36 = (cast(u64, x35) + x23);
+ var x37: u64 = undefined;
+ var x38: u1 = undefined;
+ addcarryxU64(&x37, &x38, 0x0, x11, x28);
+ var x39: u64 = undefined;
+ var x40: u1 = undefined;
+ addcarryxU64(&x39, &x40, x38, x13, x30);
+ var x41: u64 = undefined;
+ var x42: u1 = undefined;
+ addcarryxU64(&x41, &x42, x40, x15, x32);
+ var x43: u64 = undefined;
+ var x44: u1 = undefined;
+ addcarryxU64(&x43, &x44, x42, x17, x34);
+ var x45: u64 = undefined;
+ var x46: u1 = undefined;
+ addcarryxU64(&x45, &x46, x44, x19, x36);
+ var x47: u64 = undefined;
+ var x48: u64 = undefined;
+ mulxU64(&x47, &x48, x1, (arg2[3]));
+ var x49: u64 = undefined;
+ var x50: u64 = undefined;
+ mulxU64(&x49, &x50, x1, (arg2[2]));
+ var x51: u64 = undefined;
+ var x52: u64 = undefined;
+ mulxU64(&x51, &x52, x1, (arg2[1]));
+ var x53: u64 = undefined;
+ var x54: u64 = undefined;
+ mulxU64(&x53, &x54, x1, (arg2[0]));
+ var x55: u64 = undefined;
+ var x56: u1 = undefined;
+ addcarryxU64(&x55, &x56, 0x0, x54, x51);
+ var x57: u64 = undefined;
+ var x58: u1 = undefined;
+ addcarryxU64(&x57, &x58, x56, x52, x49);
+ var x59: u64 = undefined;
+ var x60: u1 = undefined;
+ addcarryxU64(&x59, &x60, x58, x50, x47);
+ const x61 = (cast(u64, x60) + x48);
+ var x62: u64 = undefined;
+ var x63: u1 = undefined;
+ addcarryxU64(&x62, &x63, 0x0, x39, x53);
+ var x64: u64 = undefined;
+ var x65: u1 = undefined;
+ addcarryxU64(&x64, &x65, x63, x41, x55);
+ var x66: u64 = undefined;
+ var x67: u1 = undefined;
+ addcarryxU64(&x66, &x67, x65, x43, x57);
+ var x68: u64 = undefined;
+ var x69: u1 = undefined;
+ addcarryxU64(&x68, &x69, x67, x45, x59);
+ var x70: u64 = undefined;
+ var x71: u1 = undefined;
+ addcarryxU64(&x70, &x71, x69, cast(u64, x46), x61);
+ var x72: u64 = undefined;
+ var x73: u64 = undefined;
+ mulxU64(&x72, &x73, x62, 0xccd1c8aaee00bc4f);
+ var x74: u64 = undefined;
+ var x75: u64 = undefined;
+ mulxU64(&x74, &x75, x72, 0xffffffff00000000);
+ var x76: u64 = undefined;
+ var x77: u64 = undefined;
+ mulxU64(&x76, &x77, x72, 0xffffffffffffffff);
+ var x78: u64 = undefined;
+ var x79: u64 = undefined;
+ mulxU64(&x78, &x79, x72, 0xbce6faada7179e84);
+ var x80: u64 = undefined;
+ var x81: u64 = undefined;
+ mulxU64(&x80, &x81, x72, 0xf3b9cac2fc632551);
+ var x82: u64 = undefined;
+ var x83: u1 = undefined;
+ addcarryxU64(&x82, &x83, 0x0, x81, x78);
+ var x84: u64 = undefined;
+ var x85: u1 = undefined;
+ addcarryxU64(&x84, &x85, x83, x79, x76);
+ var x86: u64 = undefined;
+ var x87: u1 = undefined;
+ addcarryxU64(&x86, &x87, x85, x77, x74);
+ const x88 = (cast(u64, x87) + x75);
+ var x89: u64 = undefined;
+ var x90: u1 = undefined;
+ addcarryxU64(&x89, &x90, 0x0, x62, x80);
+ var x91: u64 = undefined;
+ var x92: u1 = undefined;
+ addcarryxU64(&x91, &x92, x90, x64, x82);
+ var x93: u64 = undefined;
+ var x94: u1 = undefined;
+ addcarryxU64(&x93, &x94, x92, x66, x84);
+ var x95: u64 = undefined;
+ var x96: u1 = undefined;
+ addcarryxU64(&x95, &x96, x94, x68, x86);
+ var x97: u64 = undefined;
+ var x98: u1 = undefined;
+ addcarryxU64(&x97, &x98, x96, x70, x88);
+ const x99 = (cast(u64, x98) + cast(u64, x71));
+ var x100: u64 = undefined;
+ var x101: u64 = undefined;
+ mulxU64(&x100, &x101, x2, (arg2[3]));
+ var x102: u64 = undefined;
+ var x103: u64 = undefined;
+ mulxU64(&x102, &x103, x2, (arg2[2]));
+ var x104: u64 = undefined;
+ var x105: u64 = undefined;
+ mulxU64(&x104, &x105, x2, (arg2[1]));
+ var x106: u64 = undefined;
+ var x107: u64 = undefined;
+ mulxU64(&x106, &x107, x2, (arg2[0]));
+ var x108: u64 = undefined;
+ var x109: u1 = undefined;
+ addcarryxU64(&x108, &x109, 0x0, x107, x104);
+ var x110: u64 = undefined;
+ var x111: u1 = undefined;
+ addcarryxU64(&x110, &x111, x109, x105, x102);
+ var x112: u64 = undefined;
+ var x113: u1 = undefined;
+ addcarryxU64(&x112, &x113, x111, x103, x100);
+ const x114 = (cast(u64, x113) + x101);
+ var x115: u64 = undefined;
+ var x116: u1 = undefined;
+ addcarryxU64(&x115, &x116, 0x0, x91, x106);
+ var x117: u64 = undefined;
+ var x118: u1 = undefined;
+ addcarryxU64(&x117, &x118, x116, x93, x108);
+ var x119: u64 = undefined;
+ var x120: u1 = undefined;
+ addcarryxU64(&x119, &x120, x118, x95, x110);
+ var x121: u64 = undefined;
+ var x122: u1 = undefined;
+ addcarryxU64(&x121, &x122, x120, x97, x112);
+ var x123: u64 = undefined;
+ var x124: u1 = undefined;
+ addcarryxU64(&x123, &x124, x122, x99, x114);
+ var x125: u64 = undefined;
+ var x126: u64 = undefined;
+ mulxU64(&x125, &x126, x115, 0xccd1c8aaee00bc4f);
+ var x127: u64 = undefined;
+ var x128: u64 = undefined;
+ mulxU64(&x127, &x128, x125, 0xffffffff00000000);
+ var x129: u64 = undefined;
+ var x130: u64 = undefined;
+ mulxU64(&x129, &x130, x125, 0xffffffffffffffff);
+ var x131: u64 = undefined;
+ var x132: u64 = undefined;
+ mulxU64(&x131, &x132, x125, 0xbce6faada7179e84);
+ var x133: u64 = undefined;
+ var x134: u64 = undefined;
+ mulxU64(&x133, &x134, x125, 0xf3b9cac2fc632551);
+ var x135: u64 = undefined;
+ var x136: u1 = undefined;
+ addcarryxU64(&x135, &x136, 0x0, x134, x131);
+ var x137: u64 = undefined;
+ var x138: u1 = undefined;
+ addcarryxU64(&x137, &x138, x136, x132, x129);
+ var x139: u64 = undefined;
+ var x140: u1 = undefined;
+ addcarryxU64(&x139, &x140, x138, x130, x127);
+ const x141 = (cast(u64, x140) + x128);
+ var x142: u64 = undefined;
+ var x143: u1 = undefined;
+ addcarryxU64(&x142, &x143, 0x0, x115, x133);
+ var x144: u64 = undefined;
+ var x145: u1 = undefined;
+ addcarryxU64(&x144, &x145, x143, x117, x135);
+ var x146: u64 = undefined;
+ var x147: u1 = undefined;
+ addcarryxU64(&x146, &x147, x145, x119, x137);
+ var x148: u64 = undefined;
+ var x149: u1 = undefined;
+ addcarryxU64(&x148, &x149, x147, x121, x139);
+ var x150: u64 = undefined;
+ var x151: u1 = undefined;
+ addcarryxU64(&x150, &x151, x149, x123, x141);
+ const x152 = (cast(u64, x151) + cast(u64, x124));
+ var x153: u64 = undefined;
+ var x154: u64 = undefined;
+ mulxU64(&x153, &x154, x3, (arg2[3]));
+ var x155: u64 = undefined;
+ var x156: u64 = undefined;
+ mulxU64(&x155, &x156, x3, (arg2[2]));
+ var x157: u64 = undefined;
+ var x158: u64 = undefined;
+ mulxU64(&x157, &x158, x3, (arg2[1]));
+ var x159: u64 = undefined;
+ var x160: u64 = undefined;
+ mulxU64(&x159, &x160, x3, (arg2[0]));
+ var x161: u64 = undefined;
+ var x162: u1 = undefined;
+ addcarryxU64(&x161, &x162, 0x0, x160, x157);
+ var x163: u64 = undefined;
+ var x164: u1 = undefined;
+ addcarryxU64(&x163, &x164, x162, x158, x155);
+ var x165: u64 = undefined;
+ var x166: u1 = undefined;
+ addcarryxU64(&x165, &x166, x164, x156, x153);
+ const x167 = (cast(u64, x166) + x154);
+ var x168: u64 = undefined;
+ var x169: u1 = undefined;
+ addcarryxU64(&x168, &x169, 0x0, x144, x159);
+ var x170: u64 = undefined;
+ var x171: u1 = undefined;
+ addcarryxU64(&x170, &x171, x169, x146, x161);
+ var x172: u64 = undefined;
+ var x173: u1 = undefined;
+ addcarryxU64(&x172, &x173, x171, x148, x163);
+ var x174: u64 = undefined;
+ var x175: u1 = undefined;
+ addcarryxU64(&x174, &x175, x173, x150, x165);
+ var x176: u64 = undefined;
+ var x177: u1 = undefined;
+ addcarryxU64(&x176, &x177, x175, x152, x167);
+ var x178: u64 = undefined;
+ var x179: u64 = undefined;
+ mulxU64(&x178, &x179, x168, 0xccd1c8aaee00bc4f);
+ var x180: u64 = undefined;
+ var x181: u64 = undefined;
+ mulxU64(&x180, &x181, x178, 0xffffffff00000000);
+ var x182: u64 = undefined;
+ var x183: u64 = undefined;
+ mulxU64(&x182, &x183, x178, 0xffffffffffffffff);
+ var x184: u64 = undefined;
+ var x185: u64 = undefined;
+ mulxU64(&x184, &x185, x178, 0xbce6faada7179e84);
+ var x186: u64 = undefined;
+ var x187: u64 = undefined;
+ mulxU64(&x186, &x187, x178, 0xf3b9cac2fc632551);
+ var x188: u64 = undefined;
+ var x189: u1 = undefined;
+ addcarryxU64(&x188, &x189, 0x0, x187, x184);
+ var x190: u64 = undefined;
+ var x191: u1 = undefined;
+ addcarryxU64(&x190, &x191, x189, x185, x182);
+ var x192: u64 = undefined;
+ var x193: u1 = undefined;
+ addcarryxU64(&x192, &x193, x191, x183, x180);
+ const x194 = (cast(u64, x193) + x181);
+ var x195: u64 = undefined;
+ var x196: u1 = undefined;
+ addcarryxU64(&x195, &x196, 0x0, x168, x186);
+ var x197: u64 = undefined;
+ var x198: u1 = undefined;
+ addcarryxU64(&x197, &x198, x196, x170, x188);
+ var x199: u64 = undefined;
+ var x200: u1 = undefined;
+ addcarryxU64(&x199, &x200, x198, x172, x190);
+ var x201: u64 = undefined;
+ var x202: u1 = undefined;
+ addcarryxU64(&x201, &x202, x200, x174, x192);
+ var x203: u64 = undefined;
+ var x204: u1 = undefined;
+ addcarryxU64(&x203, &x204, x202, x176, x194);
+ const x205 = (cast(u64, x204) + cast(u64, x177));
+ var x206: u64 = undefined;
+ var x207: u1 = undefined;
+ subborrowxU64(&x206, &x207, 0x0, x197, 0xf3b9cac2fc632551);
+ var x208: u64 = undefined;
+ var x209: u1 = undefined;
+ subborrowxU64(&x208, &x209, x207, x199, 0xbce6faada7179e84);
+ var x210: u64 = undefined;
+ var x211: u1 = undefined;
+ subborrowxU64(&x210, &x211, x209, x201, 0xffffffffffffffff);
+ var x212: u64 = undefined;
+ var x213: u1 = undefined;
+ subborrowxU64(&x212, &x213, x211, x203, 0xffffffff00000000);
+ var x214: u64 = undefined;
+ var x215: u1 = undefined;
+ subborrowxU64(&x214, &x215, x213, x205, cast(u64, 0x0));
+ var x216: u64 = undefined;
+ cmovznzU64(&x216, x215, x206, x197);
+ var x217: u64 = undefined;
+ cmovznzU64(&x217, x215, x208, x199);
+ var x218: u64 = undefined;
+ cmovznzU64(&x218, x215, x210, x201);
+ var x219: u64 = undefined;
+ cmovznzU64(&x219, x215, x212, x203);
+ out1[0] = x216;
+ out1[1] = x217;
+ out1[2] = x218;
+ out1[3] = x219;
+}
+
+/// The function square squares a field element in the Montgomery domain.
+/// Preconditions:
+/// 0 ≤ eval arg1 < m
+/// Postconditions:
+/// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) * eval (from_montgomery arg1)) mod m
+/// 0 ≤ eval out1 < m
+///
+/// Input Bounds:
+/// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+/// Output Bounds:
+/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+pub fn square(out1: *[4]u64, arg1: [4]u64) void {
+ @setRuntimeSafety(mode == .Debug);
+
+ const x1 = (arg1[1]);
+ const x2 = (arg1[2]);
+ const x3 = (arg1[3]);
+ const x4 = (arg1[0]);
+ var x5: u64 = undefined;
+ var x6: u64 = undefined;
+ mulxU64(&x5, &x6, x4, (arg1[3]));
+ var x7: u64 = undefined;
+ var x8: u64 = undefined;
+ mulxU64(&x7, &x8, x4, (arg1[2]));
+ var x9: u64 = undefined;
+ var x10: u64 = undefined;
+ mulxU64(&x9, &x10, x4, (arg1[1]));
+ var x11: u64 = undefined;
+ var x12: u64 = undefined;
+ mulxU64(&x11, &x12, x4, (arg1[0]));
+ var x13: u64 = undefined;
+ var x14: u1 = undefined;
+ addcarryxU64(&x13, &x14, 0x0, x12, x9);
+ var x15: u64 = undefined;
+ var x16: u1 = undefined;
+ addcarryxU64(&x15, &x16, x14, x10, x7);
+ var x17: u64 = undefined;
+ var x18: u1 = undefined;
+ addcarryxU64(&x17, &x18, x16, x8, x5);
+ const x19 = (cast(u64, x18) + x6);
+ var x20: u64 = undefined;
+ var x21: u64 = undefined;
+ mulxU64(&x20, &x21, x11, 0xccd1c8aaee00bc4f);
+ var x22: u64 = undefined;
+ var x23: u64 = undefined;
+ mulxU64(&x22, &x23, x20, 0xffffffff00000000);
+ var x24: u64 = undefined;
+ var x25: u64 = undefined;
+ mulxU64(&x24, &x25, x20, 0xffffffffffffffff);
+ var x26: u64 = undefined;
+ var x27: u64 = undefined;
+ mulxU64(&x26, &x27, x20, 0xbce6faada7179e84);
+ var x28: u64 = undefined;
+ var x29: u64 = undefined;
+ mulxU64(&x28, &x29, x20, 0xf3b9cac2fc632551);
+ var x30: u64 = undefined;
+ var x31: u1 = undefined;
+ addcarryxU64(&x30, &x31, 0x0, x29, x26);
+ var x32: u64 = undefined;
+ var x33: u1 = undefined;
+ addcarryxU64(&x32, &x33, x31, x27, x24);
+ var x34: u64 = undefined;
+ var x35: u1 = undefined;
+ addcarryxU64(&x34, &x35, x33, x25, x22);
+ const x36 = (cast(u64, x35) + x23);
+ var x37: u64 = undefined;
+ var x38: u1 = undefined;
+ addcarryxU64(&x37, &x38, 0x0, x11, x28);
+ var x39: u64 = undefined;
+ var x40: u1 = undefined;
+ addcarryxU64(&x39, &x40, x38, x13, x30);
+ var x41: u64 = undefined;
+ var x42: u1 = undefined;
+ addcarryxU64(&x41, &x42, x40, x15, x32);
+ var x43: u64 = undefined;
+ var x44: u1 = undefined;
+ addcarryxU64(&x43, &x44, x42, x17, x34);
+ var x45: u64 = undefined;
+ var x46: u1 = undefined;
+ addcarryxU64(&x45, &x46, x44, x19, x36);
+ var x47: u64 = undefined;
+ var x48: u64 = undefined;
+ mulxU64(&x47, &x48, x1, (arg1[3]));
+ var x49: u64 = undefined;
+ var x50: u64 = undefined;
+ mulxU64(&x49, &x50, x1, (arg1[2]));
+ var x51: u64 = undefined;
+ var x52: u64 = undefined;
+ mulxU64(&x51, &x52, x1, (arg1[1]));
+ var x53: u64 = undefined;
+ var x54: u64 = undefined;
+ mulxU64(&x53, &x54, x1, (arg1[0]));
+ var x55: u64 = undefined;
+ var x56: u1 = undefined;
+ addcarryxU64(&x55, &x56, 0x0, x54, x51);
+ var x57: u64 = undefined;
+ var x58: u1 = undefined;
+ addcarryxU64(&x57, &x58, x56, x52, x49);
+ var x59: u64 = undefined;
+ var x60: u1 = undefined;
+ addcarryxU64(&x59, &x60, x58, x50, x47);
+ const x61 = (cast(u64, x60) + x48);
+ var x62: u64 = undefined;
+ var x63: u1 = undefined;
+ addcarryxU64(&x62, &x63, 0x0, x39, x53);
+ var x64: u64 = undefined;
+ var x65: u1 = undefined;
+ addcarryxU64(&x64, &x65, x63, x41, x55);
+ var x66: u64 = undefined;
+ var x67: u1 = undefined;
+ addcarryxU64(&x66, &x67, x65, x43, x57);
+ var x68: u64 = undefined;
+ var x69: u1 = undefined;
+ addcarryxU64(&x68, &x69, x67, x45, x59);
+ var x70: u64 = undefined;
+ var x71: u1 = undefined;
+ addcarryxU64(&x70, &x71, x69, cast(u64, x46), x61);
+ var x72: u64 = undefined;
+ var x73: u64 = undefined;
+ mulxU64(&x72, &x73, x62, 0xccd1c8aaee00bc4f);
+ var x74: u64 = undefined;
+ var x75: u64 = undefined;
+ mulxU64(&x74, &x75, x72, 0xffffffff00000000);
+ var x76: u64 = undefined;
+ var x77: u64 = undefined;
+ mulxU64(&x76, &x77, x72, 0xffffffffffffffff);
+ var x78: u64 = undefined;
+ var x79: u64 = undefined;
+ mulxU64(&x78, &x79, x72, 0xbce6faada7179e84);
+ var x80: u64 = undefined;
+ var x81: u64 = undefined;
+ mulxU64(&x80, &x81, x72, 0xf3b9cac2fc632551);
+ var x82: u64 = undefined;
+ var x83: u1 = undefined;
+ addcarryxU64(&x82, &x83, 0x0, x81, x78);
+ var x84: u64 = undefined;
+ var x85: u1 = undefined;
+ addcarryxU64(&x84, &x85, x83, x79, x76);
+ var x86: u64 = undefined;
+ var x87: u1 = undefined;
+ addcarryxU64(&x86, &x87, x85, x77, x74);
+ const x88 = (cast(u64, x87) + x75);
+ var x89: u64 = undefined;
+ var x90: u1 = undefined;
+ addcarryxU64(&x89, &x90, 0x0, x62, x80);
+ var x91: u64 = undefined;
+ var x92: u1 = undefined;
+ addcarryxU64(&x91, &x92, x90, x64, x82);
+ var x93: u64 = undefined;
+ var x94: u1 = undefined;
+ addcarryxU64(&x93, &x94, x92, x66, x84);
+ var x95: u64 = undefined;
+ var x96: u1 = undefined;
+ addcarryxU64(&x95, &x96, x94, x68, x86);
+ var x97: u64 = undefined;
+ var x98: u1 = undefined;
+ addcarryxU64(&x97, &x98, x96, x70, x88);
+ const x99 = (cast(u64, x98) + cast(u64, x71));
+ var x100: u64 = undefined;
+ var x101: u64 = undefined;
+ mulxU64(&x100, &x101, x2, (arg1[3]));
+ var x102: u64 = undefined;
+ var x103: u64 = undefined;
+ mulxU64(&x102, &x103, x2, (arg1[2]));
+ var x104: u64 = undefined;
+ var x105: u64 = undefined;
+ mulxU64(&x104, &x105, x2, (arg1[1]));
+ var x106: u64 = undefined;
+ var x107: u64 = undefined;
+ mulxU64(&x106, &x107, x2, (arg1[0]));
+ var x108: u64 = undefined;
+ var x109: u1 = undefined;
+ addcarryxU64(&x108, &x109, 0x0, x107, x104);
+ var x110: u64 = undefined;
+ var x111: u1 = undefined;
+ addcarryxU64(&x110, &x111, x109, x105, x102);
+ var x112: u64 = undefined;
+ var x113: u1 = undefined;
+ addcarryxU64(&x112, &x113, x111, x103, x100);
+ const x114 = (cast(u64, x113) + x101);
+ var x115: u64 = undefined;
+ var x116: u1 = undefined;
+ addcarryxU64(&x115, &x116, 0x0, x91, x106);
+ var x117: u64 = undefined;
+ var x118: u1 = undefined;
+ addcarryxU64(&x117, &x118, x116, x93, x108);
+ var x119: u64 = undefined;
+ var x120: u1 = undefined;
+ addcarryxU64(&x119, &x120, x118, x95, x110);
+ var x121: u64 = undefined;
+ var x122: u1 = undefined;
+ addcarryxU64(&x121, &x122, x120, x97, x112);
+ var x123: u64 = undefined;
+ var x124: u1 = undefined;
+ addcarryxU64(&x123, &x124, x122, x99, x114);
+ var x125: u64 = undefined;
+ var x126: u64 = undefined;
+ mulxU64(&x125, &x126, x115, 0xccd1c8aaee00bc4f);
+ var x127: u64 = undefined;
+ var x128: u64 = undefined;
+ mulxU64(&x127, &x128, x125, 0xffffffff00000000);
+ var x129: u64 = undefined;
+ var x130: u64 = undefined;
+ mulxU64(&x129, &x130, x125, 0xffffffffffffffff);
+ var x131: u64 = undefined;
+ var x132: u64 = undefined;
+ mulxU64(&x131, &x132, x125, 0xbce6faada7179e84);
+ var x133: u64 = undefined;
+ var x134: u64 = undefined;
+ mulxU64(&x133, &x134, x125, 0xf3b9cac2fc632551);
+ var x135: u64 = undefined;
+ var x136: u1 = undefined;
+ addcarryxU64(&x135, &x136, 0x0, x134, x131);
+ var x137: u64 = undefined;
+ var x138: u1 = undefined;
+ addcarryxU64(&x137, &x138, x136, x132, x129);
+ var x139: u64 = undefined;
+ var x140: u1 = undefined;
+ addcarryxU64(&x139, &x140, x138, x130, x127);
+ const x141 = (cast(u64, x140) + x128);
+ var x142: u64 = undefined;
+ var x143: u1 = undefined;
+ addcarryxU64(&x142, &x143, 0x0, x115, x133);
+ var x144: u64 = undefined;
+ var x145: u1 = undefined;
+ addcarryxU64(&x144, &x145, x143, x117, x135);
+ var x146: u64 = undefined;
+ var x147: u1 = undefined;
+ addcarryxU64(&x146, &x147, x145, x119, x137);
+ var x148: u64 = undefined;
+ var x149: u1 = undefined;
+ addcarryxU64(&x148, &x149, x147, x121, x139);
+ var x150: u64 = undefined;
+ var x151: u1 = undefined;
+ addcarryxU64(&x150, &x151, x149, x123, x141);
+ const x152 = (cast(u64, x151) + cast(u64, x124));
+ var x153: u64 = undefined;
+ var x154: u64 = undefined;
+ mulxU64(&x153, &x154, x3, (arg1[3]));
+ var x155: u64 = undefined;
+ var x156: u64 = undefined;
+ mulxU64(&x155, &x156, x3, (arg1[2]));
+ var x157: u64 = undefined;
+ var x158: u64 = undefined;
+ mulxU64(&x157, &x158, x3, (arg1[1]));
+ var x159: u64 = undefined;
+ var x160: u64 = undefined;
+ mulxU64(&x159, &x160, x3, (arg1[0]));
+ var x161: u64 = undefined;
+ var x162: u1 = undefined;
+ addcarryxU64(&x161, &x162, 0x0, x160, x157);
+ var x163: u64 = undefined;
+ var x164: u1 = undefined;
+ addcarryxU64(&x163, &x164, x162, x158, x155);
+ var x165: u64 = undefined;
+ var x166: u1 = undefined;
+ addcarryxU64(&x165, &x166, x164, x156, x153);
+ const x167 = (cast(u64, x166) + x154);
+ var x168: u64 = undefined;
+ var x169: u1 = undefined;
+ addcarryxU64(&x168, &x169, 0x0, x144, x159);
+ var x170: u64 = undefined;
+ var x171: u1 = undefined;
+ addcarryxU64(&x170, &x171, x169, x146, x161);
+ var x172: u64 = undefined;
+ var x173: u1 = undefined;
+ addcarryxU64(&x172, &x173, x171, x148, x163);
+ var x174: u64 = undefined;
+ var x175: u1 = undefined;
+ addcarryxU64(&x174, &x175, x173, x150, x165);
+ var x176: u64 = undefined;
+ var x177: u1 = undefined;
+ addcarryxU64(&x176, &x177, x175, x152, x167);
+ var x178: u64 = undefined;
+ var x179: u64 = undefined;
+ mulxU64(&x178, &x179, x168, 0xccd1c8aaee00bc4f);
+ var x180: u64 = undefined;
+ var x181: u64 = undefined;
+ mulxU64(&x180, &x181, x178, 0xffffffff00000000);
+ var x182: u64 = undefined;
+ var x183: u64 = undefined;
+ mulxU64(&x182, &x183, x178, 0xffffffffffffffff);
+ var x184: u64 = undefined;
+ var x185: u64 = undefined;
+ mulxU64(&x184, &x185, x178, 0xbce6faada7179e84);
+ var x186: u64 = undefined;
+ var x187: u64 = undefined;
+ mulxU64(&x186, &x187, x178, 0xf3b9cac2fc632551);
+ var x188: u64 = undefined;
+ var x189: u1 = undefined;
+ addcarryxU64(&x188, &x189, 0x0, x187, x184);
+ var x190: u64 = undefined;
+ var x191: u1 = undefined;
+ addcarryxU64(&x190, &x191, x189, x185, x182);
+ var x192: u64 = undefined;
+ var x193: u1 = undefined;
+ addcarryxU64(&x192, &x193, x191, x183, x180);
+ const x194 = (cast(u64, x193) + x181);
+ var x195: u64 = undefined;
+ var x196: u1 = undefined;
+ addcarryxU64(&x195, &x196, 0x0, x168, x186);
+ var x197: u64 = undefined;
+ var x198: u1 = undefined;
+ addcarryxU64(&x197, &x198, x196, x170, x188);
+ var x199: u64 = undefined;
+ var x200: u1 = undefined;
+ addcarryxU64(&x199, &x200, x198, x172, x190);
+ var x201: u64 = undefined;
+ var x202: u1 = undefined;
+ addcarryxU64(&x201, &x202, x200, x174, x192);
+ var x203: u64 = undefined;
+ var x204: u1 = undefined;
+ addcarryxU64(&x203, &x204, x202, x176, x194);
+ const x205 = (cast(u64, x204) + cast(u64, x177));
+ var x206: u64 = undefined;
+ var x207: u1 = undefined;
+ subborrowxU64(&x206, &x207, 0x0, x197, 0xf3b9cac2fc632551);
+ var x208: u64 = undefined;
+ var x209: u1 = undefined;
+ subborrowxU64(&x208, &x209, x207, x199, 0xbce6faada7179e84);
+ var x210: u64 = undefined;
+ var x211: u1 = undefined;
+ subborrowxU64(&x210, &x211, x209, x201, 0xffffffffffffffff);
+ var x212: u64 = undefined;
+ var x213: u1 = undefined;
+ subborrowxU64(&x212, &x213, x211, x203, 0xffffffff00000000);
+ var x214: u64 = undefined;
+ var x215: u1 = undefined;
+ subborrowxU64(&x214, &x215, x213, x205, cast(u64, 0x0));
+ var x216: u64 = undefined;
+ cmovznzU64(&x216, x215, x206, x197);
+ var x217: u64 = undefined;
+ cmovznzU64(&x217, x215, x208, x199);
+ var x218: u64 = undefined;
+ cmovznzU64(&x218, x215, x210, x201);
+ var x219: u64 = undefined;
+ cmovznzU64(&x219, x215, x212, x203);
+ out1[0] = x216;
+ out1[1] = x217;
+ out1[2] = x218;
+ out1[3] = x219;
+}
+
+/// The function add adds two field elements in the Montgomery domain.
+/// Preconditions:
+/// 0 ≤ eval arg1 < m
+/// 0 ≤ eval arg2 < m
+/// Postconditions:
+/// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) + eval (from_montgomery arg2)) mod m
+/// 0 ≤ eval out1 < m
+///
+/// Input Bounds:
+/// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+/// arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+/// Output Bounds:
+/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+pub fn add(out1: *[4]u64, arg1: [4]u64, arg2: [4]u64) void {
+ @setRuntimeSafety(mode == .Debug);
+
+ var x1: u64 = undefined;
+ var x2: u1 = undefined;
+ addcarryxU64(&x1, &x2, 0x0, (arg1[0]), (arg2[0]));
+ var x3: u64 = undefined;
+ var x4: u1 = undefined;
+ addcarryxU64(&x3, &x4, x2, (arg1[1]), (arg2[1]));
+ var x5: u64 = undefined;
+ var x6: u1 = undefined;
+ addcarryxU64(&x5, &x6, x4, (arg1[2]), (arg2[2]));
+ var x7: u64 = undefined;
+ var x8: u1 = undefined;
+ addcarryxU64(&x7, &x8, x6, (arg1[3]), (arg2[3]));
+ var x9: u64 = undefined;
+ var x10: u1 = undefined;
+ subborrowxU64(&x9, &x10, 0x0, x1, 0xf3b9cac2fc632551);
+ var x11: u64 = undefined;
+ var x12: u1 = undefined;
+ subborrowxU64(&x11, &x12, x10, x3, 0xbce6faada7179e84);
+ var x13: u64 = undefined;
+ var x14: u1 = undefined;
+ subborrowxU64(&x13, &x14, x12, x5, 0xffffffffffffffff);
+ var x15: u64 = undefined;
+ var x16: u1 = undefined;
+ subborrowxU64(&x15, &x16, x14, x7, 0xffffffff00000000);
+ var x17: u64 = undefined;
+ var x18: u1 = undefined;
+ subborrowxU64(&x17, &x18, x16, cast(u64, x8), cast(u64, 0x0));
+ var x19: u64 = undefined;
+ cmovznzU64(&x19, x18, x9, x1);
+ var x20: u64 = undefined;
+ cmovznzU64(&x20, x18, x11, x3);
+ var x21: u64 = undefined;
+ cmovznzU64(&x21, x18, x13, x5);
+ var x22: u64 = undefined;
+ cmovznzU64(&x22, x18, x15, x7);
+ out1[0] = x19;
+ out1[1] = x20;
+ out1[2] = x21;
+ out1[3] = x22;
+}
+
+/// The function sub subtracts two field elements in the Montgomery domain.
+/// Preconditions:
+/// 0 ≤ eval arg1 < m
+/// 0 ≤ eval arg2 < m
+/// Postconditions:
+/// eval (from_montgomery out1) mod m = (eval (from_montgomery arg1) - eval (from_montgomery arg2)) mod m
+/// 0 ≤ eval out1 < m
+///
+/// Input Bounds:
+/// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+/// arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+/// Output Bounds:
+/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+pub fn sub(out1: *[4]u64, arg1: [4]u64, arg2: [4]u64) void {
+ @setRuntimeSafety(mode == .Debug);
+
+ var x1: u64 = undefined;
+ var x2: u1 = undefined;
+ subborrowxU64(&x1, &x2, 0x0, (arg1[0]), (arg2[0]));
+ var x3: u64 = undefined;
+ var x4: u1 = undefined;
+ subborrowxU64(&x3, &x4, x2, (arg1[1]), (arg2[1]));
+ var x5: u64 = undefined;
+ var x6: u1 = undefined;
+ subborrowxU64(&x5, &x6, x4, (arg1[2]), (arg2[2]));
+ var x7: u64 = undefined;
+ var x8: u1 = undefined;
+ subborrowxU64(&x7, &x8, x6, (arg1[3]), (arg2[3]));
+ var x9: u64 = undefined;
+ cmovznzU64(&x9, x8, cast(u64, 0x0), 0xffffffffffffffff);
+ var x10: u64 = undefined;
+ var x11: u1 = undefined;
+ addcarryxU64(&x10, &x11, 0x0, x1, (x9 & 0xf3b9cac2fc632551));
+ var x12: u64 = undefined;
+ var x13: u1 = undefined;
+ addcarryxU64(&x12, &x13, x11, x3, (x9 & 0xbce6faada7179e84));
+ var x14: u64 = undefined;
+ var x15: u1 = undefined;
+ addcarryxU64(&x14, &x15, x13, x5, x9);
+ var x16: u64 = undefined;
+ var x17: u1 = undefined;
+ addcarryxU64(&x16, &x17, x15, x7, (x9 & 0xffffffff00000000));
+ out1[0] = x10;
+ out1[1] = x12;
+ out1[2] = x14;
+ out1[3] = x16;
+}
+
+/// The function opp negates a field element in the Montgomery domain.
+/// Preconditions:
+/// 0 ≤ eval arg1 < m
+/// Postconditions:
+/// eval (from_montgomery out1) mod m = -eval (from_montgomery arg1) mod m
+/// 0 ≤ eval out1 < m
+///
+/// Input Bounds:
+/// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+/// Output Bounds:
+/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+pub fn opp(out1: *[4]u64, arg1: [4]u64) void {
+ @setRuntimeSafety(mode == .Debug);
+
+ var x1: u64 = undefined;
+ var x2: u1 = undefined;
+ subborrowxU64(&x1, &x2, 0x0, cast(u64, 0x0), (arg1[0]));
+ var x3: u64 = undefined;
+ var x4: u1 = undefined;
+ subborrowxU64(&x3, &x4, x2, cast(u64, 0x0), (arg1[1]));
+ var x5: u64 = undefined;
+ var x6: u1 = undefined;
+ subborrowxU64(&x5, &x6, x4, cast(u64, 0x0), (arg1[2]));
+ var x7: u64 = undefined;
+ var x8: u1 = undefined;
+ subborrowxU64(&x7, &x8, x6, cast(u64, 0x0), (arg1[3]));
+ var x9: u64 = undefined;
+ cmovznzU64(&x9, x8, cast(u64, 0x0), 0xffffffffffffffff);
+ var x10: u64 = undefined;
+ var x11: u1 = undefined;
+ addcarryxU64(&x10, &x11, 0x0, x1, (x9 & 0xf3b9cac2fc632551));
+ var x12: u64 = undefined;
+ var x13: u1 = undefined;
+ addcarryxU64(&x12, &x13, x11, x3, (x9 & 0xbce6faada7179e84));
+ var x14: u64 = undefined;
+ var x15: u1 = undefined;
+ addcarryxU64(&x14, &x15, x13, x5, x9);
+ var x16: u64 = undefined;
+ var x17: u1 = undefined;
+ addcarryxU64(&x16, &x17, x15, x7, (x9 & 0xffffffff00000000));
+ out1[0] = x10;
+ out1[1] = x12;
+ out1[2] = x14;
+ out1[3] = x16;
+}
+
+/// The function fromMontgomery translates a field element out of the Montgomery domain.
+/// Preconditions:
+/// 0 ≤ eval arg1 < m
+/// Postconditions:
+/// eval out1 mod m = (eval arg1 * ((2^64)⁻¹ mod m)^4) mod m
+/// 0 ≤ eval out1 < m
+///
+/// Input Bounds:
+/// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+/// Output Bounds:
+/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+pub fn fromMontgomery(out1: *[4]u64, arg1: [4]u64) void {
+ @setRuntimeSafety(mode == .Debug);
+
+ const x1 = (arg1[0]);
+ var x2: u64 = undefined;
+ var x3: u64 = undefined;
+ mulxU64(&x2, &x3, x1, 0xccd1c8aaee00bc4f);
+ var x4: u64 = undefined;
+ var x5: u64 = undefined;
+ mulxU64(&x4, &x5, x2, 0xffffffff00000000);
+ var x6: u64 = undefined;
+ var x7: u64 = undefined;
+ mulxU64(&x6, &x7, x2, 0xffffffffffffffff);
+ var x8: u64 = undefined;
+ var x9: u64 = undefined;
+ mulxU64(&x8, &x9, x2, 0xbce6faada7179e84);
+ var x10: u64 = undefined;
+ var x11: u64 = undefined;
+ mulxU64(&x10, &x11, x2, 0xf3b9cac2fc632551);
+ var x12: u64 = undefined;
+ var x13: u1 = undefined;
+ addcarryxU64(&x12, &x13, 0x0, x11, x8);
+ var x14: u64 = undefined;
+ var x15: u1 = undefined;
+ addcarryxU64(&x14, &x15, x13, x9, x6);
+ var x16: u64 = undefined;
+ var x17: u1 = undefined;
+ addcarryxU64(&x16, &x17, x15, x7, x4);
+ var x18: u64 = undefined;
+ var x19: u1 = undefined;
+ addcarryxU64(&x18, &x19, 0x0, x1, x10);
+ var x20: u64 = undefined;
+ var x21: u1 = undefined;
+ addcarryxU64(&x20, &x21, x19, cast(u64, 0x0), x12);
+ var x22: u64 = undefined;
+ var x23: u1 = undefined;
+ addcarryxU64(&x22, &x23, x21, cast(u64, 0x0), x14);
+ var x24: u64 = undefined;
+ var x25: u1 = undefined;
+ addcarryxU64(&x24, &x25, x23, cast(u64, 0x0), x16);
+ var x26: u64 = undefined;
+ var x27: u1 = undefined;
+ addcarryxU64(&x26, &x27, 0x0, x20, (arg1[1]));
+ var x28: u64 = undefined;
+ var x29: u1 = undefined;
+ addcarryxU64(&x28, &x29, x27, x22, cast(u64, 0x0));
+ var x30: u64 = undefined;
+ var x31: u1 = undefined;
+ addcarryxU64(&x30, &x31, x29, x24, cast(u64, 0x0));
+ var x32: u64 = undefined;
+ var x33: u64 = undefined;
+ mulxU64(&x32, &x33, x26, 0xccd1c8aaee00bc4f);
+ var x34: u64 = undefined;
+ var x35: u64 = undefined;
+ mulxU64(&x34, &x35, x32, 0xffffffff00000000);
+ var x36: u64 = undefined;
+ var x37: u64 = undefined;
+ mulxU64(&x36, &x37, x32, 0xffffffffffffffff);
+ var x38: u64 = undefined;
+ var x39: u64 = undefined;
+ mulxU64(&x38, &x39, x32, 0xbce6faada7179e84);
+ var x40: u64 = undefined;
+ var x41: u64 = undefined;
+ mulxU64(&x40, &x41, x32, 0xf3b9cac2fc632551);
+ var x42: u64 = undefined;
+ var x43: u1 = undefined;
+ addcarryxU64(&x42, &x43, 0x0, x41, x38);
+ var x44: u64 = undefined;
+ var x45: u1 = undefined;
+ addcarryxU64(&x44, &x45, x43, x39, x36);
+ var x46: u64 = undefined;
+ var x47: u1 = undefined;
+ addcarryxU64(&x46, &x47, x45, x37, x34);
+ var x48: u64 = undefined;
+ var x49: u1 = undefined;
+ addcarryxU64(&x48, &x49, 0x0, x26, x40);
+ var x50: u64 = undefined;
+ var x51: u1 = undefined;
+ addcarryxU64(&x50, &x51, x49, x28, x42);
+ var x52: u64 = undefined;
+ var x53: u1 = undefined;
+ addcarryxU64(&x52, &x53, x51, x30, x44);
+ var x54: u64 = undefined;
+ var x55: u1 = undefined;
+ addcarryxU64(&x54, &x55, x53, (cast(u64, x31) + (cast(u64, x25) + (cast(u64, x17) + x5))), x46);
+ var x56: u64 = undefined;
+ var x57: u1 = undefined;
+ addcarryxU64(&x56, &x57, 0x0, x50, (arg1[2]));
+ var x58: u64 = undefined;
+ var x59: u1 = undefined;
+ addcarryxU64(&x58, &x59, x57, x52, cast(u64, 0x0));
+ var x60: u64 = undefined;
+ var x61: u1 = undefined;
+ addcarryxU64(&x60, &x61, x59, x54, cast(u64, 0x0));
+ var x62: u64 = undefined;
+ var x63: u64 = undefined;
+ mulxU64(&x62, &x63, x56, 0xccd1c8aaee00bc4f);
+ var x64: u64 = undefined;
+ var x65: u64 = undefined;
+ mulxU64(&x64, &x65, x62, 0xffffffff00000000);
+ var x66: u64 = undefined;
+ var x67: u64 = undefined;
+ mulxU64(&x66, &x67, x62, 0xffffffffffffffff);
+ var x68: u64 = undefined;
+ var x69: u64 = undefined;
+ mulxU64(&x68, &x69, x62, 0xbce6faada7179e84);
+ var x70: u64 = undefined;
+ var x71: u64 = undefined;
+ mulxU64(&x70, &x71, x62, 0xf3b9cac2fc632551);
+ var x72: u64 = undefined;
+ var x73: u1 = undefined;
+ addcarryxU64(&x72, &x73, 0x0, x71, x68);
+ var x74: u64 = undefined;
+ var x75: u1 = undefined;
+ addcarryxU64(&x74, &x75, x73, x69, x66);
+ var x76: u64 = undefined;
+ var x77: u1 = undefined;
+ addcarryxU64(&x76, &x77, x75, x67, x64);
+ var x78: u64 = undefined;
+ var x79: u1 = undefined;
+ addcarryxU64(&x78, &x79, 0x0, x56, x70);
+ var x80: u64 = undefined;
+ var x81: u1 = undefined;
+ addcarryxU64(&x80, &x81, x79, x58, x72);
+ var x82: u64 = undefined;
+ var x83: u1 = undefined;
+ addcarryxU64(&x82, &x83, x81, x60, x74);
+ var x84: u64 = undefined;
+ var x85: u1 = undefined;
+ addcarryxU64(&x84, &x85, x83, (cast(u64, x61) + (cast(u64, x55) + (cast(u64, x47) + x35))), x76);
+ var x86: u64 = undefined;
+ var x87: u1 = undefined;
+ addcarryxU64(&x86, &x87, 0x0, x80, (arg1[3]));
+ var x88: u64 = undefined;
+ var x89: u1 = undefined;
+ addcarryxU64(&x88, &x89, x87, x82, cast(u64, 0x0));
+ var x90: u64 = undefined;
+ var x91: u1 = undefined;
+ addcarryxU64(&x90, &x91, x89, x84, cast(u64, 0x0));
+ var x92: u64 = undefined;
+ var x93: u64 = undefined;
+ mulxU64(&x92, &x93, x86, 0xccd1c8aaee00bc4f);
+ var x94: u64 = undefined;
+ var x95: u64 = undefined;
+ mulxU64(&x94, &x95, x92, 0xffffffff00000000);
+ var x96: u64 = undefined;
+ var x97: u64 = undefined;
+ mulxU64(&x96, &x97, x92, 0xffffffffffffffff);
+ var x98: u64 = undefined;
+ var x99: u64 = undefined;
+ mulxU64(&x98, &x99, x92, 0xbce6faada7179e84);
+ var x100: u64 = undefined;
+ var x101: u64 = undefined;
+ mulxU64(&x100, &x101, x92, 0xf3b9cac2fc632551);
+ var x102: u64 = undefined;
+ var x103: u1 = undefined;
+ addcarryxU64(&x102, &x103, 0x0, x101, x98);
+ var x104: u64 = undefined;
+ var x105: u1 = undefined;
+ addcarryxU64(&x104, &x105, x103, x99, x96);
+ var x106: u64 = undefined;
+ var x107: u1 = undefined;
+ addcarryxU64(&x106, &x107, x105, x97, x94);
+ var x108: u64 = undefined;
+ var x109: u1 = undefined;
+ addcarryxU64(&x108, &x109, 0x0, x86, x100);
+ var x110: u64 = undefined;
+ var x111: u1 = undefined;
+ addcarryxU64(&x110, &x111, x109, x88, x102);
+ var x112: u64 = undefined;
+ var x113: u1 = undefined;
+ addcarryxU64(&x112, &x113, x111, x90, x104);
+ var x114: u64 = undefined;
+ var x115: u1 = undefined;
+ addcarryxU64(&x114, &x115, x113, (cast(u64, x91) + (cast(u64, x85) + (cast(u64, x77) + x65))), x106);
+ const x116 = (cast(u64, x115) + (cast(u64, x107) + x95));
+ var x117: u64 = undefined;
+ var x118: u1 = undefined;
+ subborrowxU64(&x117, &x118, 0x0, x110, 0xf3b9cac2fc632551);
+ var x119: u64 = undefined;
+ var x120: u1 = undefined;
+ subborrowxU64(&x119, &x120, x118, x112, 0xbce6faada7179e84);
+ var x121: u64 = undefined;
+ var x122: u1 = undefined;
+ subborrowxU64(&x121, &x122, x120, x114, 0xffffffffffffffff);
+ var x123: u64 = undefined;
+ var x124: u1 = undefined;
+ subborrowxU64(&x123, &x124, x122, x116, 0xffffffff00000000);
+ var x125: u64 = undefined;
+ var x126: u1 = undefined;
+ subborrowxU64(&x125, &x126, x124, cast(u64, 0x0), cast(u64, 0x0));
+ var x127: u64 = undefined;
+ cmovznzU64(&x127, x126, x117, x110);
+ var x128: u64 = undefined;
+ cmovznzU64(&x128, x126, x119, x112);
+ var x129: u64 = undefined;
+ cmovznzU64(&x129, x126, x121, x114);
+ var x130: u64 = undefined;
+ cmovznzU64(&x130, x126, x123, x116);
+ out1[0] = x127;
+ out1[1] = x128;
+ out1[2] = x129;
+ out1[3] = x130;
+}
+
+/// The function toMontgomery translates a field element into the Montgomery domain.
+/// Preconditions:
+/// 0 ≤ eval arg1 < m
+/// Postconditions:
+/// eval (from_montgomery out1) mod m = eval arg1 mod m
+/// 0 ≤ eval out1 < m
+///
+/// Input Bounds:
+/// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+/// Output Bounds:
+/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+pub fn toMontgomery(out1: *[4]u64, arg1: [4]u64) void {
+ @setRuntimeSafety(mode == .Debug);
+
+ const x1 = (arg1[1]);
+ const x2 = (arg1[2]);
+ const x3 = (arg1[3]);
+ const x4 = (arg1[0]);
+ var x5: u64 = undefined;
+ var x6: u64 = undefined;
+ mulxU64(&x5, &x6, x4, 0x66e12d94f3d95620);
+ var x7: u64 = undefined;
+ var x8: u64 = undefined;
+ mulxU64(&x7, &x8, x4, 0x2845b2392b6bec59);
+ var x9: u64 = undefined;
+ var x10: u64 = undefined;
+ mulxU64(&x9, &x10, x4, 0x4699799c49bd6fa6);
+ var x11: u64 = undefined;
+ var x12: u64 = undefined;
+ mulxU64(&x11, &x12, x4, 0x83244c95be79eea2);
+ var x13: u64 = undefined;
+ var x14: u1 = undefined;
+ addcarryxU64(&x13, &x14, 0x0, x12, x9);
+ var x15: u64 = undefined;
+ var x16: u1 = undefined;
+ addcarryxU64(&x15, &x16, x14, x10, x7);
+ var x17: u64 = undefined;
+ var x18: u1 = undefined;
+ addcarryxU64(&x17, &x18, x16, x8, x5);
+ var x19: u64 = undefined;
+ var x20: u64 = undefined;
+ mulxU64(&x19, &x20, x11, 0xccd1c8aaee00bc4f);
+ var x21: u64 = undefined;
+ var x22: u64 = undefined;
+ mulxU64(&x21, &x22, x19, 0xffffffff00000000);
+ var x23: u64 = undefined;
+ var x24: u64 = undefined;
+ mulxU64(&x23, &x24, x19, 0xffffffffffffffff);
+ var x25: u64 = undefined;
+ var x26: u64 = undefined;
+ mulxU64(&x25, &x26, x19, 0xbce6faada7179e84);
+ var x27: u64 = undefined;
+ var x28: u64 = undefined;
+ mulxU64(&x27, &x28, x19, 0xf3b9cac2fc632551);
+ var x29: u64 = undefined;
+ var x30: u1 = undefined;
+ addcarryxU64(&x29, &x30, 0x0, x28, x25);
+ var x31: u64 = undefined;
+ var x32: u1 = undefined;
+ addcarryxU64(&x31, &x32, x30, x26, x23);
+ var x33: u64 = undefined;
+ var x34: u1 = undefined;
+ addcarryxU64(&x33, &x34, x32, x24, x21);
+ var x35: u64 = undefined;
+ var x36: u1 = undefined;
+ addcarryxU64(&x35, &x36, 0x0, x11, x27);
+ var x37: u64 = undefined;
+ var x38: u1 = undefined;
+ addcarryxU64(&x37, &x38, x36, x13, x29);
+ var x39: u64 = undefined;
+ var x40: u1 = undefined;
+ addcarryxU64(&x39, &x40, x38, x15, x31);
+ var x41: u64 = undefined;
+ var x42: u1 = undefined;
+ addcarryxU64(&x41, &x42, x40, x17, x33);
+ var x43: u64 = undefined;
+ var x44: u1 = undefined;
+ addcarryxU64(&x43, &x44, x42, (cast(u64, x18) + x6), (cast(u64, x34) + x22));
+ var x45: u64 = undefined;
+ var x46: u64 = undefined;
+ mulxU64(&x45, &x46, x1, 0x66e12d94f3d95620);
+ var x47: u64 = undefined;
+ var x48: u64 = undefined;
+ mulxU64(&x47, &x48, x1, 0x2845b2392b6bec59);
+ var x49: u64 = undefined;
+ var x50: u64 = undefined;
+ mulxU64(&x49, &x50, x1, 0x4699799c49bd6fa6);
+ var x51: u64 = undefined;
+ var x52: u64 = undefined;
+ mulxU64(&x51, &x52, x1, 0x83244c95be79eea2);
+ var x53: u64 = undefined;
+ var x54: u1 = undefined;
+ addcarryxU64(&x53, &x54, 0x0, x52, x49);
+ var x55: u64 = undefined;
+ var x56: u1 = undefined;
+ addcarryxU64(&x55, &x56, x54, x50, x47);
+ var x57: u64 = undefined;
+ var x58: u1 = undefined;
+ addcarryxU64(&x57, &x58, x56, x48, x45);
+ var x59: u64 = undefined;
+ var x60: u1 = undefined;
+ addcarryxU64(&x59, &x60, 0x0, x37, x51);
+ var x61: u64 = undefined;
+ var x62: u1 = undefined;
+ addcarryxU64(&x61, &x62, x60, x39, x53);
+ var x63: u64 = undefined;
+ var x64: u1 = undefined;
+ addcarryxU64(&x63, &x64, x62, x41, x55);
+ var x65: u64 = undefined;
+ var x66: u1 = undefined;
+ addcarryxU64(&x65, &x66, x64, x43, x57);
+ var x67: u64 = undefined;
+ var x68: u64 = undefined;
+ mulxU64(&x67, &x68, x59, 0xccd1c8aaee00bc4f);
+ var x69: u64 = undefined;
+ var x70: u64 = undefined;
+ mulxU64(&x69, &x70, x67, 0xffffffff00000000);
+ var x71: u64 = undefined;
+ var x72: u64 = undefined;
+ mulxU64(&x71, &x72, x67, 0xffffffffffffffff);
+ var x73: u64 = undefined;
+ var x74: u64 = undefined;
+ mulxU64(&x73, &x74, x67, 0xbce6faada7179e84);
+ var x75: u64 = undefined;
+ var x76: u64 = undefined;
+ mulxU64(&x75, &x76, x67, 0xf3b9cac2fc632551);
+ var x77: u64 = undefined;
+ var x78: u1 = undefined;
+ addcarryxU64(&x77, &x78, 0x0, x76, x73);
+ var x79: u64 = undefined;
+ var x80: u1 = undefined;
+ addcarryxU64(&x79, &x80, x78, x74, x71);
+ var x81: u64 = undefined;
+ var x82: u1 = undefined;
+ addcarryxU64(&x81, &x82, x80, x72, x69);
+ var x83: u64 = undefined;
+ var x84: u1 = undefined;
+ addcarryxU64(&x83, &x84, 0x0, x59, x75);
+ var x85: u64 = undefined;
+ var x86: u1 = undefined;
+ addcarryxU64(&x85, &x86, x84, x61, x77);
+ var x87: u64 = undefined;
+ var x88: u1 = undefined;
+ addcarryxU64(&x87, &x88, x86, x63, x79);
+ var x89: u64 = undefined;
+ var x90: u1 = undefined;
+ addcarryxU64(&x89, &x90, x88, x65, x81);
+ var x91: u64 = undefined;
+ var x92: u1 = undefined;
+ addcarryxU64(&x91, &x92, x90, ((cast(u64, x66) + cast(u64, x44)) + (cast(u64, x58) + x46)), (cast(u64, x82) + x70));
+ var x93: u64 = undefined;
+ var x94: u64 = undefined;
+ mulxU64(&x93, &x94, x2, 0x66e12d94f3d95620);
+ var x95: u64 = undefined;
+ var x96: u64 = undefined;
+ mulxU64(&x95, &x96, x2, 0x2845b2392b6bec59);
+ var x97: u64 = undefined;
+ var x98: u64 = undefined;
+ mulxU64(&x97, &x98, x2, 0x4699799c49bd6fa6);
+ var x99: u64 = undefined;
+ var x100: u64 = undefined;
+ mulxU64(&x99, &x100, x2, 0x83244c95be79eea2);
+ var x101: u64 = undefined;
+ var x102: u1 = undefined;
+ addcarryxU64(&x101, &x102, 0x0, x100, x97);
+ var x103: u64 = undefined;
+ var x104: u1 = undefined;
+ addcarryxU64(&x103, &x104, x102, x98, x95);
+ var x105: u64 = undefined;
+ var x106: u1 = undefined;
+ addcarryxU64(&x105, &x106, x104, x96, x93);
+ var x107: u64 = undefined;
+ var x108: u1 = undefined;
+ addcarryxU64(&x107, &x108, 0x0, x85, x99);
+ var x109: u64 = undefined;
+ var x110: u1 = undefined;
+ addcarryxU64(&x109, &x110, x108, x87, x101);
+ var x111: u64 = undefined;
+ var x112: u1 = undefined;
+ addcarryxU64(&x111, &x112, x110, x89, x103);
+ var x113: u64 = undefined;
+ var x114: u1 = undefined;
+ addcarryxU64(&x113, &x114, x112, x91, x105);
+ var x115: u64 = undefined;
+ var x116: u64 = undefined;
+ mulxU64(&x115, &x116, x107, 0xccd1c8aaee00bc4f);
+ var x117: u64 = undefined;
+ var x118: u64 = undefined;
+ mulxU64(&x117, &x118, x115, 0xffffffff00000000);
+ var x119: u64 = undefined;
+ var x120: u64 = undefined;
+ mulxU64(&x119, &x120, x115, 0xffffffffffffffff);
+ var x121: u64 = undefined;
+ var x122: u64 = undefined;
+ mulxU64(&x121, &x122, x115, 0xbce6faada7179e84);
+ var x123: u64 = undefined;
+ var x124: u64 = undefined;
+ mulxU64(&x123, &x124, x115, 0xf3b9cac2fc632551);
+ var x125: u64 = undefined;
+ var x126: u1 = undefined;
+ addcarryxU64(&x125, &x126, 0x0, x124, x121);
+ var x127: u64 = undefined;
+ var x128: u1 = undefined;
+ addcarryxU64(&x127, &x128, x126, x122, x119);
+ var x129: u64 = undefined;
+ var x130: u1 = undefined;
+ addcarryxU64(&x129, &x130, x128, x120, x117);
+ var x131: u64 = undefined;
+ var x132: u1 = undefined;
+ addcarryxU64(&x131, &x132, 0x0, x107, x123);
+ var x133: u64 = undefined;
+ var x134: u1 = undefined;
+ addcarryxU64(&x133, &x134, x132, x109, x125);
+ var x135: u64 = undefined;
+ var x136: u1 = undefined;
+ addcarryxU64(&x135, &x136, x134, x111, x127);
+ var x137: u64 = undefined;
+ var x138: u1 = undefined;
+ addcarryxU64(&x137, &x138, x136, x113, x129);
+ var x139: u64 = undefined;
+ var x140: u1 = undefined;
+ addcarryxU64(&x139, &x140, x138, ((cast(u64, x114) + cast(u64, x92)) + (cast(u64, x106) + x94)), (cast(u64, x130) + x118));
+ var x141: u64 = undefined;
+ var x142: u64 = undefined;
+ mulxU64(&x141, &x142, x3, 0x66e12d94f3d95620);
+ var x143: u64 = undefined;
+ var x144: u64 = undefined;
+ mulxU64(&x143, &x144, x3, 0x2845b2392b6bec59);
+ var x145: u64 = undefined;
+ var x146: u64 = undefined;
+ mulxU64(&x145, &x146, x3, 0x4699799c49bd6fa6);
+ var x147: u64 = undefined;
+ var x148: u64 = undefined;
+ mulxU64(&x147, &x148, x3, 0x83244c95be79eea2);
+ var x149: u64 = undefined;
+ var x150: u1 = undefined;
+ addcarryxU64(&x149, &x150, 0x0, x148, x145);
+ var x151: u64 = undefined;
+ var x152: u1 = undefined;
+ addcarryxU64(&x151, &x152, x150, x146, x143);
+ var x153: u64 = undefined;
+ var x154: u1 = undefined;
+ addcarryxU64(&x153, &x154, x152, x144, x141);
+ var x155: u64 = undefined;
+ var x156: u1 = undefined;
+ addcarryxU64(&x155, &x156, 0x0, x133, x147);
+ var x157: u64 = undefined;
+ var x158: u1 = undefined;
+ addcarryxU64(&x157, &x158, x156, x135, x149);
+ var x159: u64 = undefined;
+ var x160: u1 = undefined;
+ addcarryxU64(&x159, &x160, x158, x137, x151);
+ var x161: u64 = undefined;
+ var x162: u1 = undefined;
+ addcarryxU64(&x161, &x162, x160, x139, x153);
+ var x163: u64 = undefined;
+ var x164: u64 = undefined;
+ mulxU64(&x163, &x164, x155, 0xccd1c8aaee00bc4f);
+ var x165: u64 = undefined;
+ var x166: u64 = undefined;
+ mulxU64(&x165, &x166, x163, 0xffffffff00000000);
+ var x167: u64 = undefined;
+ var x168: u64 = undefined;
+ mulxU64(&x167, &x168, x163, 0xffffffffffffffff);
+ var x169: u64 = undefined;
+ var x170: u64 = undefined;
+ mulxU64(&x169, &x170, x163, 0xbce6faada7179e84);
+ var x171: u64 = undefined;
+ var x172: u64 = undefined;
+ mulxU64(&x171, &x172, x163, 0xf3b9cac2fc632551);
+ var x173: u64 = undefined;
+ var x174: u1 = undefined;
+ addcarryxU64(&x173, &x174, 0x0, x172, x169);
+ var x175: u64 = undefined;
+ var x176: u1 = undefined;
+ addcarryxU64(&x175, &x176, x174, x170, x167);
+ var x177: u64 = undefined;
+ var x178: u1 = undefined;
+ addcarryxU64(&x177, &x178, x176, x168, x165);
+ var x179: u64 = undefined;
+ var x180: u1 = undefined;
+ addcarryxU64(&x179, &x180, 0x0, x155, x171);
+ var x181: u64 = undefined;
+ var x182: u1 = undefined;
+ addcarryxU64(&x181, &x182, x180, x157, x173);
+ var x183: u64 = undefined;
+ var x184: u1 = undefined;
+ addcarryxU64(&x183, &x184, x182, x159, x175);
+ var x185: u64 = undefined;
+ var x186: u1 = undefined;
+ addcarryxU64(&x185, &x186, x184, x161, x177);
+ var x187: u64 = undefined;
+ var x188: u1 = undefined;
+ addcarryxU64(&x187, &x188, x186, ((cast(u64, x162) + cast(u64, x140)) + (cast(u64, x154) + x142)), (cast(u64, x178) + x166));
+ var x189: u64 = undefined;
+ var x190: u1 = undefined;
+ subborrowxU64(&x189, &x190, 0x0, x181, 0xf3b9cac2fc632551);
+ var x191: u64 = undefined;
+ var x192: u1 = undefined;
+ subborrowxU64(&x191, &x192, x190, x183, 0xbce6faada7179e84);
+ var x193: u64 = undefined;
+ var x194: u1 = undefined;
+ subborrowxU64(&x193, &x194, x192, x185, 0xffffffffffffffff);
+ var x195: u64 = undefined;
+ var x196: u1 = undefined;
+ subborrowxU64(&x195, &x196, x194, x187, 0xffffffff00000000);
+ var x197: u64 = undefined;
+ var x198: u1 = undefined;
+ subborrowxU64(&x197, &x198, x196, cast(u64, x188), cast(u64, 0x0));
+ var x199: u64 = undefined;
+ cmovznzU64(&x199, x198, x189, x181);
+ var x200: u64 = undefined;
+ cmovznzU64(&x200, x198, x191, x183);
+ var x201: u64 = undefined;
+ cmovznzU64(&x201, x198, x193, x185);
+ var x202: u64 = undefined;
+ cmovznzU64(&x202, x198, x195, x187);
+ out1[0] = x199;
+ out1[1] = x200;
+ out1[2] = x201;
+ out1[3] = x202;
+}
+
+/// The function nonzero outputs a single non-zero word if the input is non-zero and zero otherwise.
+/// Preconditions:
+/// 0 ≤ eval arg1 < m
+/// Postconditions:
+/// out1 = 0 ↔ eval (from_montgomery arg1) mod m = 0
+///
+/// Input Bounds:
+/// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+/// Output Bounds:
+/// out1: [0x0 ~> 0xffffffffffffffff]
+pub fn nonzero(out1: *u64, arg1: [4]u64) void {
+ @setRuntimeSafety(mode == .Debug);
+
+ const x1 = ((arg1[0]) | ((arg1[1]) | ((arg1[2]) | (arg1[3]))));
+ out1.* = x1;
+}
+
+/// The function selectznz is a multi-limb conditional select.
+/// Postconditions:
+/// eval out1 = (if arg1 = 0 then eval arg2 else eval arg3)
+///
+/// Input Bounds:
+/// arg1: [0x0 ~> 0x1]
+/// arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+/// arg3: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+/// Output Bounds:
+/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+pub fn selectznz(out1: *[4]u64, arg1: u1, arg2: [4]u64, arg3: [4]u64) void {
+ @setRuntimeSafety(mode == .Debug);
+
+ var x1: u64 = undefined;
+ cmovznzU64(&x1, arg1, (arg2[0]), (arg3[0]));
+ var x2: u64 = undefined;
+ cmovznzU64(&x2, arg1, (arg2[1]), (arg3[1]));
+ var x3: u64 = undefined;
+ cmovznzU64(&x3, arg1, (arg2[2]), (arg3[2]));
+ var x4: u64 = undefined;
+ cmovznzU64(&x4, arg1, (arg2[3]), (arg3[3]));
+ out1[0] = x1;
+ out1[1] = x2;
+ out1[2] = x3;
+ out1[3] = x4;
+}
+
+/// The function toBytes serializes a field element NOT in the Montgomery domain to bytes in little-endian order.
+/// Preconditions:
+/// 0 ≤ eval arg1 < m
+/// Postconditions:
+/// out1 = map (λ x, ⌊((eval arg1 mod m) mod 2^(8 * (x + 1))) / 2^(8 * x)⌋) [0..31]
+///
+/// Input Bounds:
+/// arg1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+/// Output Bounds:
+/// out1: [[0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff], [0x0 ~> 0xff]]
+pub fn toBytes(out1: *[32]u8, arg1: [4]u64) void {
+ @setRuntimeSafety(mode == .Debug);
+
+ const x1 = (arg1[3]);
+ const x2 = (arg1[2]);
+ const x3 = (arg1[1]);
+ const x4 = (arg1[0]);
+ const x5 = cast(u8, (x4 & cast(u64, 0xff)));
+ const x6 = (x4 >> 8);
+ const x7 = cast(u8, (x6 & cast(u64, 0xff)));
+ const x8 = (x6 >> 8);
+ const x9 = cast(u8, (x8 & cast(u64, 0xff)));
+ const x10 = (x8 >> 8);
+ const x11 = cast(u8, (x10 & cast(u64, 0xff)));
+ const x12 = (x10 >> 8);
+ const x13 = cast(u8, (x12 & cast(u64, 0xff)));
+ const x14 = (x12 >> 8);
+ const x15 = cast(u8, (x14 & cast(u64, 0xff)));
+ const x16 = (x14 >> 8);
+ const x17 = cast(u8, (x16 & cast(u64, 0xff)));
+ const x18 = cast(u8, (x16 >> 8));
+ const x19 = cast(u8, (x3 & cast(u64, 0xff)));
+ const x20 = (x3 >> 8);
+ const x21 = cast(u8, (x20 & cast(u64, 0xff)));
+ const x22 = (x20 >> 8);
+ const x23 = cast(u8, (x22 & cast(u64, 0xff)));
+ const x24 = (x22 >> 8);
+ const x25 = cast(u8, (x24 & cast(u64, 0xff)));
+ const x26 = (x24 >> 8);
+ const x27 = cast(u8, (x26 & cast(u64, 0xff)));
+ const x28 = (x26 >> 8);
+ const x29 = cast(u8, (x28 & cast(u64, 0xff)));
+ const x30 = (x28 >> 8);
+ const x31 = cast(u8, (x30 & cast(u64, 0xff)));
+ const x32 = cast(u8, (x30 >> 8));
+ const x33 = cast(u8, (x2 & cast(u64, 0xff)));
+ const x34 = (x2 >> 8);
+ const x35 = cast(u8, (x34 & cast(u64, 0xff)));
+ const x36 = (x34 >> 8);
+ const x37 = cast(u8, (x36 & cast(u64, 0xff)));
+ const x38 = (x36 >> 8);
+ const x39 = cast(u8, (x38 & cast(u64, 0xff)));
+ const x40 = (x38 >> 8);
+ const x41 = cast(u8, (x40 & cast(u64, 0xff)));
+ const x42 = (x40 >> 8);
+ const x43 = cast(u8, (x42 & cast(u64, 0xff)));
+ const x44 = (x42 >> 8);
+ const x45 = cast(u8, (x44 & cast(u64, 0xff)));
+ const x46 = cast(u8, (x44 >> 8));
+ const x47 = cast(u8, (x1 & cast(u64, 0xff)));
+ const x48 = (x1 >> 8);
+ const x49 = cast(u8, (x48 & cast(u64, 0xff)));
+ const x50 = (x48 >> 8);
+ const x51 = cast(u8, (x50 & cast(u64, 0xff)));
+ const x52 = (x50 >> 8);
+ const x53 = cast(u8, (x52 & cast(u64, 0xff)));
+ const x54 = (x52 >> 8);
+ const x55 = cast(u8, (x54 & cast(u64, 0xff)));
+ const x56 = (x54 >> 8);
+ const x57 = cast(u8, (x56 & cast(u64, 0xff)));
+ const x58 = (x56 >> 8);
+ const x59 = cast(u8, (x58 & cast(u64, 0xff)));
+ const x60 = cast(u8, (x58 >> 8));
+ out1[0] = x5;
+ out1[1] = x7;
+ out1[2] = x9;
+ out1[3] = x11;
+ out1[4] = x13;
+ out1[5] = x15;
+ out1[6] = x17;
+ out1[7] = x18;
+ out1[8] = x19;
+ out1[9] = x21;
+ out1[10] = x23;
+ out1[11] = x25;
+ out1[12] = x27;
+ out1[13] = x29;
+ out1[14] = x31;
+ out1[15] = x32;
+ out1[16] = x33;
+ out1[17] = x35;
+ out1[18] = x37;
+ out1[19] = x39;
+ out1[20] = x41;
+ out1[21] = x43;
+ out1[22] = x45;
+ out1[23] = x46;
+ out1[24] = x47;
+ out1[25] = x49;
+ out1[26] = x51;
+ out1[27] = x53;
+ out1[28] = x55;
+ out1[29] = x57;
+ out1[30] = x59;
+ out1[31] = x60;
+}
+
+/// The function fromBytes deserializes a field element NOT in the Montgomery domain from bytes in little-endian order.
+/// Preconditions:
+/// 0 ≤ bytes_eval arg1 < m
+/// Postconditions:
+/// eval out1 mod m = bytes_eval arg1 mod m
+/// 0 ≤ eval out1 < m
+///
+/// Input Bounds:
+/// 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]]
+/// Output Bounds:
+/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+pub fn fromBytes(out1: *[4]u64, arg1: [32]u8) void {
+ @setRuntimeSafety(mode == .Debug);
+
+ const x1 = (cast(u64, (arg1[31])) << 56);
+ const x2 = (cast(u64, (arg1[30])) << 48);
+ const x3 = (cast(u64, (arg1[29])) << 40);
+ const x4 = (cast(u64, (arg1[28])) << 32);
+ const x5 = (cast(u64, (arg1[27])) << 24);
+ const x6 = (cast(u64, (arg1[26])) << 16);
+ const x7 = (cast(u64, (arg1[25])) << 8);
+ const x8 = (arg1[24]);
+ const x9 = (cast(u64, (arg1[23])) << 56);
+ const x10 = (cast(u64, (arg1[22])) << 48);
+ const x11 = (cast(u64, (arg1[21])) << 40);
+ const x12 = (cast(u64, (arg1[20])) << 32);
+ const x13 = (cast(u64, (arg1[19])) << 24);
+ const x14 = (cast(u64, (arg1[18])) << 16);
+ const x15 = (cast(u64, (arg1[17])) << 8);
+ const x16 = (arg1[16]);
+ const x17 = (cast(u64, (arg1[15])) << 56);
+ const x18 = (cast(u64, (arg1[14])) << 48);
+ const x19 = (cast(u64, (arg1[13])) << 40);
+ const x20 = (cast(u64, (arg1[12])) << 32);
+ const x21 = (cast(u64, (arg1[11])) << 24);
+ const x22 = (cast(u64, (arg1[10])) << 16);
+ const x23 = (cast(u64, (arg1[9])) << 8);
+ const x24 = (arg1[8]);
+ const x25 = (cast(u64, (arg1[7])) << 56);
+ const x26 = (cast(u64, (arg1[6])) << 48);
+ const x27 = (cast(u64, (arg1[5])) << 40);
+ const x28 = (cast(u64, (arg1[4])) << 32);
+ const x29 = (cast(u64, (arg1[3])) << 24);
+ const x30 = (cast(u64, (arg1[2])) << 16);
+ const x31 = (cast(u64, (arg1[1])) << 8);
+ const x32 = (arg1[0]);
+ const x33 = (x31 + cast(u64, x32));
+ const x34 = (x30 + x33);
+ const x35 = (x29 + x34);
+ const x36 = (x28 + x35);
+ const x37 = (x27 + x36);
+ const x38 = (x26 + x37);
+ const x39 = (x25 + x38);
+ const x40 = (x23 + cast(u64, x24));
+ const x41 = (x22 + x40);
+ const x42 = (x21 + x41);
+ const x43 = (x20 + x42);
+ const x44 = (x19 + x43);
+ const x45 = (x18 + x44);
+ const x46 = (x17 + x45);
+ const x47 = (x15 + cast(u64, x16));
+ const x48 = (x14 + x47);
+ const x49 = (x13 + x48);
+ const x50 = (x12 + x49);
+ const x51 = (x11 + x50);
+ const x52 = (x10 + x51);
+ const x53 = (x9 + x52);
+ const x54 = (x7 + cast(u64, x8));
+ const x55 = (x6 + x54);
+ const x56 = (x5 + x55);
+ const x57 = (x4 + x56);
+ const x58 = (x3 + x57);
+ const x59 = (x2 + x58);
+ const x60 = (x1 + x59);
+ out1[0] = x39;
+ out1[1] = x46;
+ out1[2] = x53;
+ out1[3] = x60;
+}
+
+/// The function setOne returns the field element one in the Montgomery domain.
+/// Postconditions:
+/// eval (from_montgomery out1) mod m = 1 mod m
+/// 0 ≤ eval out1 < m
+///
+/// Input Bounds:
+/// Output Bounds:
+/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+pub fn setOne(out1: *[4]u64) void {
+ @setRuntimeSafety(mode == .Debug);
+
+ out1[0] = 0xc46353d039cdaaf;
+ out1[1] = 0x4319055258e8617b;
+ out1[2] = cast(u64, 0x0);
+ out1[3] = 0xffffffff;
+}
+
+/// The function msat returns the saturated representation of the prime modulus.
+/// Postconditions:
+/// twos_complement_eval out1 = m
+/// 0 ≤ eval out1 < m
+///
+/// Input Bounds:
+/// Output Bounds:
+/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+pub fn msat(out1: *[5]u64) void {
+ @setRuntimeSafety(mode == .Debug);
+
+ out1[0] = 0xf3b9cac2fc632551;
+ out1[1] = 0xbce6faada7179e84;
+ out1[2] = 0xffffffffffffffff;
+ out1[3] = 0xffffffff00000000;
+ out1[4] = cast(u64, 0x0);
+}
+
+/// The function divstepPrecomp returns the precomputed value for Bernstein-Yang-inversion (in montgomery form).
+/// Postconditions:
+/// 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⌋)
+/// 0 ≤ eval out1 < m
+///
+/// Input Bounds:
+/// Output Bounds:
+/// out1: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+pub fn divstepPrecomp(out1: *[4]u64) void {
+ @setRuntimeSafety(mode == .Debug);
+
+ out1[0] = 0xd739262fb7fcfbb5;
+ out1[1] = 0x8ac6f75d20074414;
+ out1[2] = 0xc67428bfb5e3c256;
+ out1[3] = 0x444962f2eda7aedf;
+}
+
+/// The function divstep computes a divstep.
+/// Preconditions:
+/// 0 ≤ eval arg4 < m
+/// 0 ≤ eval arg5 < m
+/// Postconditions:
+/// out1 = (if 0 < arg1 ∧ (twos_complement_eval arg3) is odd then 1 - arg1 else 1 + arg1)
+/// twos_complement_eval out2 = (if 0 < arg1 ∧ (twos_complement_eval arg3) is odd then twos_complement_eval arg3 else twos_complement_eval arg2)
+/// 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⌋)
+/// 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)
+/// 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)
+/// 0 ≤ eval out5 < m
+/// 0 ≤ eval out5 < m
+/// 0 ≤ eval out2 < m
+/// 0 ≤ eval out3 < m
+///
+/// Input Bounds:
+/// arg1: [0x0 ~> 0xffffffffffffffff]
+/// arg2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+/// arg3: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+/// arg4: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+/// arg5: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+/// Output Bounds:
+/// out1: [0x0 ~> 0xffffffffffffffff]
+/// out2: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+/// out3: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+/// out4: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+/// out5: [[0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff], [0x0 ~> 0xffffffffffffffff]]
+pub fn divstep(out1: *u64, out2: *[5]u64, out3: *[5]u64, out4: *[4]u64, out5: *[4]u64, arg1: u64, arg2: [5]u64, arg3: [5]u64, arg4: [4]u64, arg5: [4]u64) void {
+ @setRuntimeSafety(mode == .Debug);
+
+ var x1: u64 = undefined;
+ var x2: u1 = undefined;
+ addcarryxU64(&x1, &x2, 0x0, (~arg1), cast(u64, 0x1));
+ const x3 = (cast(u1, (x1 >> 63)) & cast(u1, ((arg3[0]) & cast(u64, 0x1))));
+ var x4: u64 = undefined;
+ var x5: u1 = undefined;
+ addcarryxU64(&x4, &x5, 0x0, (~arg1), cast(u64, 0x1));
+ var x6: u64 = undefined;
+ cmovznzU64(&x6, x3, arg1, x4);
+ var x7: u64 = undefined;
+ cmovznzU64(&x7, x3, (arg2[0]), (arg3[0]));
+ var x8: u64 = undefined;
+ cmovznzU64(&x8, x3, (arg2[1]), (arg3[1]));
+ var x9: u64 = undefined;
+ cmovznzU64(&x9, x3, (arg2[2]), (arg3[2]));
+ var x10: u64 = undefined;
+ cmovznzU64(&x10, x3, (arg2[3]), (arg3[3]));
+ var x11: u64 = undefined;
+ cmovznzU64(&x11, x3, (arg2[4]), (arg3[4]));
+ var x12: u64 = undefined;
+ var x13: u1 = undefined;
+ addcarryxU64(&x12, &x13, 0x0, cast(u64, 0x1), (~(arg2[0])));
+ var x14: u64 = undefined;
+ var x15: u1 = undefined;
+ addcarryxU64(&x14, &x15, x13, cast(u64, 0x0), (~(arg2[1])));
+ var x16: u64 = undefined;
+ var x17: u1 = undefined;
+ addcarryxU64(&x16, &x17, x15, cast(u64, 0x0), (~(arg2[2])));
+ var x18: u64 = undefined;
+ var x19: u1 = undefined;
+ addcarryxU64(&x18, &x19, x17, cast(u64, 0x0), (~(arg2[3])));
+ var x20: u64 = undefined;
+ var x21: u1 = undefined;
+ addcarryxU64(&x20, &x21, x19, cast(u64, 0x0), (~(arg2[4])));
+ var x22: u64 = undefined;
+ cmovznzU64(&x22, x3, (arg3[0]), x12);
+ var x23: u64 = undefined;
+ cmovznzU64(&x23, x3, (arg3[1]), x14);
+ var x24: u64 = undefined;
+ cmovznzU64(&x24, x3, (arg3[2]), x16);
+ var x25: u64 = undefined;
+ cmovznzU64(&x25, x3, (arg3[3]), x18);
+ var x26: u64 = undefined;
+ cmovznzU64(&x26, x3, (arg3[4]), x20);
+ var x27: u64 = undefined;
+ cmovznzU64(&x27, x3, (arg4[0]), (arg5[0]));
+ var x28: u64 = undefined;
+ cmovznzU64(&x28, x3, (arg4[1]), (arg5[1]));
+ var x29: u64 = undefined;
+ cmovznzU64(&x29, x3, (arg4[2]), (arg5[2]));
+ var x30: u64 = undefined;
+ cmovznzU64(&x30, x3, (arg4[3]), (arg5[3]));
+ var x31: u64 = undefined;
+ var x32: u1 = undefined;
+ addcarryxU64(&x31, &x32, 0x0, x27, x27);
+ var x33: u64 = undefined;
+ var x34: u1 = undefined;
+ addcarryxU64(&x33, &x34, x32, x28, x28);
+ var x35: u64 = undefined;
+ var x36: u1 = undefined;
+ addcarryxU64(&x35, &x36, x34, x29, x29);
+ var x37: u64 = undefined;
+ var x38: u1 = undefined;
+ addcarryxU64(&x37, &x38, x36, x30, x30);
+ var x39: u64 = undefined;
+ var x40: u1 = undefined;
+ subborrowxU64(&x39, &x40, 0x0, x31, 0xf3b9cac2fc632551);
+ var x41: u64 = undefined;
+ var x42: u1 = undefined;
+ subborrowxU64(&x41, &x42, x40, x33, 0xbce6faada7179e84);
+ var x43: u64 = undefined;
+ var x44: u1 = undefined;
+ subborrowxU64(&x43, &x44, x42, x35, 0xffffffffffffffff);
+ var x45: u64 = undefined;
+ var x46: u1 = undefined;
+ subborrowxU64(&x45, &x46, x44, x37, 0xffffffff00000000);
+ var x47: u64 = undefined;
+ var x48: u1 = undefined;
+ subborrowxU64(&x47, &x48, x46, cast(u64, x38), cast(u64, 0x0));
+ const x49 = (arg4[3]);
+ const x50 = (arg4[2]);
+ const x51 = (arg4[1]);
+ const x52 = (arg4[0]);
+ var x53: u64 = undefined;
+ var x54: u1 = undefined;
+ subborrowxU64(&x53, &x54, 0x0, cast(u64, 0x0), x52);
+ var x55: u64 = undefined;
+ var x56: u1 = undefined;
+ subborrowxU64(&x55, &x56, x54, cast(u64, 0x0), x51);
+ var x57: u64 = undefined;
+ var x58: u1 = undefined;
+ subborrowxU64(&x57, &x58, x56, cast(u64, 0x0), x50);
+ var x59: u64 = undefined;
+ var x60: u1 = undefined;
+ subborrowxU64(&x59, &x60, x58, cast(u64, 0x0), x49);
+ var x61: u64 = undefined;
+ cmovznzU64(&x61, x60, cast(u64, 0x0), 0xffffffffffffffff);
+ var x62: u64 = undefined;
+ var x63: u1 = undefined;
+ addcarryxU64(&x62, &x63, 0x0, x53, (x61 & 0xf3b9cac2fc632551));
+ var x64: u64 = undefined;
+ var x65: u1 = undefined;
+ addcarryxU64(&x64, &x65, x63, x55, (x61 & 0xbce6faada7179e84));
+ var x66: u64 = undefined;
+ var x67: u1 = undefined;
+ addcarryxU64(&x66, &x67, x65, x57, x61);
+ var x68: u64 = undefined;
+ var x69: u1 = undefined;
+ addcarryxU64(&x68, &x69, x67, x59, (x61 & 0xffffffff00000000));
+ var x70: u64 = undefined;
+ cmovznzU64(&x70, x3, (arg5[0]), x62);
+ var x71: u64 = undefined;
+ cmovznzU64(&x71, x3, (arg5[1]), x64);
+ var x72: u64 = undefined;
+ cmovznzU64(&x72, x3, (arg5[2]), x66);
+ var x73: u64 = undefined;
+ cmovznzU64(&x73, x3, (arg5[3]), x68);
+ const x74 = cast(u1, (x22 & cast(u64, 0x1)));
+ var x75: u64 = undefined;
+ cmovznzU64(&x75, x74, cast(u64, 0x0), x7);
+ var x76: u64 = undefined;
+ cmovznzU64(&x76, x74, cast(u64, 0x0), x8);
+ var x77: u64 = undefined;
+ cmovznzU64(&x77, x74, cast(u64, 0x0), x9);
+ var x78: u64 = undefined;
+ cmovznzU64(&x78, x74, cast(u64, 0x0), x10);
+ var x79: u64 = undefined;
+ cmovznzU64(&x79, x74, cast(u64, 0x0), x11);
+ var x80: u64 = undefined;
+ var x81: u1 = undefined;
+ addcarryxU64(&x80, &x81, 0x0, x22, x75);
+ var x82: u64 = undefined;
+ var x83: u1 = undefined;
+ addcarryxU64(&x82, &x83, x81, x23, x76);
+ var x84: u64 = undefined;
+ var x85: u1 = undefined;
+ addcarryxU64(&x84, &x85, x83, x24, x77);
+ var x86: u64 = undefined;
+ var x87: u1 = undefined;
+ addcarryxU64(&x86, &x87, x85, x25, x78);
+ var x88: u64 = undefined;
+ var x89: u1 = undefined;
+ addcarryxU64(&x88, &x89, x87, x26, x79);
+ var x90: u64 = undefined;
+ cmovznzU64(&x90, x74, cast(u64, 0x0), x27);
+ var x91: u64 = undefined;
+ cmovznzU64(&x91, x74, cast(u64, 0x0), x28);
+ var x92: u64 = undefined;
+ cmovznzU64(&x92, x74, cast(u64, 0x0), x29);
+ var x93: u64 = undefined;
+ cmovznzU64(&x93, x74, cast(u64, 0x0), x30);
+ var x94: u64 = undefined;
+ var x95: u1 = undefined;
+ addcarryxU64(&x94, &x95, 0x0, x70, x90);
+ var x96: u64 = undefined;
+ var x97: u1 = undefined;
+ addcarryxU64(&x96, &x97, x95, x71, x91);
+ var x98: u64 = undefined;
+ var x99: u1 = undefined;
+ addcarryxU64(&x98, &x99, x97, x72, x92);
+ var x100: u64 = undefined;
+ var x101: u1 = undefined;
+ addcarryxU64(&x100, &x101, x99, x73, x93);
+ var x102: u64 = undefined;
+ var x103: u1 = undefined;
+ subborrowxU64(&x102, &x103, 0x0, x94, 0xf3b9cac2fc632551);
+ var x104: u64 = undefined;
+ var x105: u1 = undefined;
+ subborrowxU64(&x104, &x105, x103, x96, 0xbce6faada7179e84);
+ var x106: u64 = undefined;
+ var x107: u1 = undefined;
+ subborrowxU64(&x106, &x107, x105, x98, 0xffffffffffffffff);
+ var x108: u64 = undefined;
+ var x109: u1 = undefined;
+ subborrowxU64(&x108, &x109, x107, x100, 0xffffffff00000000);
+ var x110: u64 = undefined;
+ var x111: u1 = undefined;
+ subborrowxU64(&x110, &x111, x109, cast(u64, x101), cast(u64, 0x0));
+ var x112: u64 = undefined;
+ var x113: u1 = undefined;
+ addcarryxU64(&x112, &x113, 0x0, x6, cast(u64, 0x1));
+ const x114 = ((x80 >> 1) | ((x82 << 63) & 0xffffffffffffffff));
+ const x115 = ((x82 >> 1) | ((x84 << 63) & 0xffffffffffffffff));
+ const x116 = ((x84 >> 1) | ((x86 << 63) & 0xffffffffffffffff));
+ const x117 = ((x86 >> 1) | ((x88 << 63) & 0xffffffffffffffff));
+ const x118 = ((x88 & 0x8000000000000000) | (x88 >> 1));
+ var x119: u64 = undefined;
+ cmovznzU64(&x119, x48, x39, x31);
+ var x120: u64 = undefined;
+ cmovznzU64(&x120, x48, x41, x33);
+ var x121: u64 = undefined;
+ cmovznzU64(&x121, x48, x43, x35);
+ var x122: u64 = undefined;
+ cmovznzU64(&x122, x48, x45, x37);
+ var x123: u64 = undefined;
+ cmovznzU64(&x123, x111, x102, x94);
+ var x124: u64 = undefined;
+ cmovznzU64(&x124, x111, x104, x96);
+ var x125: u64 = undefined;
+ cmovznzU64(&x125, x111, x106, x98);
+ var x126: u64 = undefined;
+ cmovznzU64(&x126, x111, x108, x100);
+ out1.* = x112;
+ out2[0] = x7;
+ out2[1] = x8;
+ out2[2] = x9;
+ out2[3] = x10;
+ out2[4] = x11;
+ out3[0] = x114;
+ out3[1] = x115;
+ out3[2] = x116;
+ out3[3] = x117;
+ out3[4] = x118;
+ out4[0] = x119;
+ out4[1] = x120;
+ out4[2] = x121;
+ out4[3] = x122;
+ out5[0] = x123;
+ out5[1] = x124;
+ out5[2] = x125;
+ out5[3] = x126;
+}
diff --git a/zig/lib/std/crypto/pcurves/p256/scalar.zig b/zig/lib/std/crypto/pcurves/p256/scalar.zig
new file mode 100644
index 0000000000..3cd6689897
--- /dev/null
+++ b/zig/lib/std/crypto/pcurves/p256/scalar.zig
@@ -0,0 +1,231 @@
+// SPDX-License-Identifier: MIT
+// Copyright (c) 2015-2021 Zig Contributors
+// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
+// The MIT license requires this copyright notice to be included in all copies
+// and substantial portions of the software.
+
+const std = @import("std");
+const builtin = std.builtin;
+const common = @import("../common.zig");
+const crypto = std.crypto;
+const debug = std.debug;
+const math = std.math;
+const mem = std.mem;
+
+const Field = common.Field;
+
+const NonCanonicalError = std.crypto.errors.NonCanonicalError;
+const NotSquareError = std.crypto.errors.NotSquareError;
+
+/// Number of bytes required to encode a scalar.
+pub const encoded_length = 32;
+
+/// A compressed scalar, in canonical form.
+pub const CompressedScalar = [encoded_length]u8;
+
+const Fe = Field(.{
+ .fiat = @import("p256_scalar_64.zig"),
+ .field_order = 115792089210356248762697446949407573529996955224135760342422259061068512044369,
+ .field_bits = 256,
+ .saturated_bits = 255,
+ .encoded_length = encoded_length,
+});
+
+/// Reject a scalar whose encoding is not canonical.
+pub fn rejectNonCanonical(s: CompressedScalar, endian: builtin.Endian) NonCanonicalError!void {
+ return Fe.rejectNonCanonical(s, endian);
+}
+
+/// Reduce a 48-bytes scalar to the field size.
+pub fn reduce48(s: [48]u8, endian: builtin.Endian) CompressedScalar {
+ return Scalar.fromBytes48(s, endian).toBytes(endian);
+}
+
+/// Reduce a 64-bytes scalar to the field size.
+pub fn reduce64(s: [64]u8, endian: builtin.Endian) CompressedScalar {
+ return ScalarDouble.fromBytes64(s, endian).toBytes(endian);
+}
+
+/// Return a*b (mod L)
+pub fn mul(a: CompressedScalar, b: CompressedScalar, endian: builtin.Endian) NonCanonicalError!CompressedScalar {
+ return (try Scalar.fromBytes(a, endian)).mul(try Scalar.fromBytes(b, endian)).toBytes(endian);
+}
+
+/// Return a*b+c (mod L)
+pub fn mulAdd(a: CompressedScalar, b: CompressedScalar, c: CompressedScalar, endian: builtin.Endian) NonCanonicalError!CompressedScalar {
+ return (try Scalar.fromBytes(a, endian)).mul(try Scalar.fromBytes(b, endian)).add(try Scalar.fromBytes(c, endian)).toBytes(endian);
+}
+
+/// Return a+b (mod L)
+pub fn add(a: CompressedScalar, b: CompressedScalar, endian: builtin.Endian) NonCanonicalError!CompressedScalar {
+ return (try Scalar.fromBytes(a, endian)).add(try Scalar.fromBytes(b, endian)).toBytes(endian);
+}
+
+/// Return -s (mod L)
+pub fn neg(s: CompressedScalar, endian: builtin.Endian) NonCanonicalError!CompressedScalar {
+ return (try Scalar.fromBytes(a, endian)).neg().toBytes(endian);
+}
+
+/// Return (a-b) (mod L)
+pub fn sub(a: CompressedScalar, b: CompressedScalar, endian: builtin.Endian) NonCanonicalError!CompressedScalar {
+ return (try Scalar.fromBytes(a, endian)).sub(try Scalar.fromBytes(b.endian)).toBytes(endian);
+}
+
+/// Return a random scalar
+pub fn random(endian: builtin.Endian) CompressedScalar {
+ return Scalar.random().toBytes(endian);
+}
+
+/// A scalar in unpacked representation.
+pub const Scalar = struct {
+ fe: Fe,
+
+ /// Zero.
+ pub const zero = Scalar{ .fe = Fe.zero };
+
+ /// One.
+ pub const one = Scalar{ .fe = Fe.one };
+
+ /// Unpack a serialized representation of a scalar.
+ pub fn fromBytes(s: CompressedScalar, endian: builtin.Endian) NonCanonicalError!Scalar {
+ return Scalar{ .fe = try Fe.fromBytes(s, endian) };
+ }
+
+ /// Reduce a 384 bit input to the field size.
+ pub fn fromBytes48(s: [48]u8, endian: builtin.Endian) Scalar {
+ const t = ScalarDouble.fromBytes(384, s, endian);
+ return t.reduce(384);
+ }
+
+ /// Reduce a 512 bit input to the field size.
+ pub fn fromBytes64(s: [64]u8, endian: builtin.Endian) Scalar {
+ const t = ScalarDouble.fromBytes(512, s, endian);
+ return t.reduce(512);
+ }
+
+ /// Pack a scalar into bytes.
+ pub fn toBytes(n: Scalar, endian: builtin.Endian) CompressedScalar {
+ return n.fe.toBytes(endian);
+ }
+
+ /// Return true if the scalar is zero..
+ pub fn isZero(n: Scalar) bool {
+ return n.fe.isZero();
+ }
+
+ /// Return true if a and b are equivalent.
+ pub fn equivalent(a: Scalar, b: Scalar) bool {
+ return a.fe.equivalent(b.fe);
+ }
+
+ /// Compute x+y (mod L)
+ pub fn add(x: Scalar, y: Scalar) Scalar {
+ return Scalar{ .fe = x.fe().add(y.fe) };
+ }
+
+ /// Compute x-y (mod L)
+ pub fn sub(x: Scalar, y: Scalar) Scalar {
+ return Scalar{ .fe = x.fe().sub(y.fe) };
+ }
+
+ /// Compute 2n (mod L)
+ pub fn dbl(n: Scalar) Scalar {
+ return Scalar{ .fe = n.fe.dbl() };
+ }
+
+ /// Compute x*y (mod L)
+ pub fn mul(x: Scalar, y: Scalar) Scalar {
+ return Scalar{ .fe = x.fe().mul(y.fe) };
+ }
+
+ /// Compute x^2 (mod L)
+ pub fn sq(n: Scalar) Scalar {
+ return Scalar{ .fe = n.fe.sq() };
+ }
+
+ /// Compute x^n (mod L)
+ pub fn pow(a: Scalar, comptime T: type, comptime n: T) Scalar {
+ return Scalar{ .fe = a.fe.pow(n) };
+ }
+
+ /// Compute -x (mod L)
+ pub fn neg(n: Scalar) Scalar {
+ return Scalar{ .fe = n.fe.neg() };
+ }
+
+ /// Compute x^-1 (mod L)
+ pub fn invert(n: Scalar) Scalar {
+ return Scalar{ .fe = n.fe.invert() };
+ }
+
+ /// Return true if n is a quadratic residue mod L.
+ pub fn isSquare(n: Scalar) Scalar {
+ return n.fe.isSquare();
+ }
+
+ /// Return the square root of L, or NotSquare if there isn't any solutions.
+ pub fn sqrt(n: Scalar) NotSquareError!Scalar {
+ return Scalar{ .fe = try n.fe.sqrt() };
+ }
+
+ /// Return a random scalar < L.
+ pub fn random() Scalar {
+ var s: [48]u8 = undefined;
+ while (true) {
+ crypto.random.bytes(&s);
+ const n = Scalar.fromBytes48(s, .Little);
+ if (!n.isZero()) {
+ return n;
+ }
+ }
+ }
+};
+
+const ScalarDouble = struct {
+ x1: Fe,
+ x2: Fe,
+ x3: Fe,
+
+ fn fromBytes(comptime bits: usize, s_: [bits / 8]u8, endian: builtin.Endian) ScalarDouble {
+ debug.assert(bits > 0 and bits <= 512 and bits >= Fe.saturated_bits and bits <= Fe.saturated_bits * 3);
+
+ var s = s_;
+ if (endian == .Big) {
+ for (s_) |x, i| s[s.len - 1 - i] = x;
+ }
+ var t = ScalarDouble{ .x1 = undefined, .x2 = Fe.zero, .x3 = Fe.zero };
+ {
+ var b = [_]u8{0} ** encoded_length;
+ const len = math.min(s.len, 24);
+ mem.copy(u8, b[0..len], s[0..len]);
+ t.x1 = Fe.fromBytes(b, .Little) catch unreachable;
+ }
+ if (s_.len >= 24) {
+ var b = [_]u8{0} ** encoded_length;
+ const len = math.min(s.len - 24, 24);
+ mem.copy(u8, b[0..len], s[24..][0..len]);
+ t.x2 = Fe.fromBytes(b, .Little) catch unreachable;
+ }
+ if (s_.len >= 48) {
+ var b = [_]u8{0} ** encoded_length;
+ const len = s.len - 48;
+ mem.copy(u8, b[0..len], s[48..][0..len]);
+ t.x3 = Fe.fromBytes(b, .Little) catch unreachable;
+ }
+ return t;
+ }
+
+ fn reduce(expanded: ScalarDouble, comptime bits: usize) Scalar {
+ debug.assert(bits > 0 and bits <= Fe.saturated_bits * 3 and bits <= 512);
+ var fe = expanded.x1;
+ if (bits >= 192) {
+ const st1 = Fe.fromInt(1 << 192) catch unreachable;
+ fe = fe.add(expanded.x2.mul(st1));
+ if (bits >= 384) {
+ const st2 = st1.sq();
+ fe = fe.add(expanded.x3.mul(st2));
+ }
+ }
+ return Scalar{ .fe = fe };
+ }
+};
diff --git a/zig/lib/std/crypto/pcurves/tests.zig b/zig/lib/std/crypto/pcurves/tests.zig
new file mode 100644
index 0000000000..4e8e08a7fe
--- /dev/null
+++ b/zig/lib/std/crypto/pcurves/tests.zig
@@ -0,0 +1,103 @@
+// SPDX-License-Identifier: MIT
+// Copyright (c) 2015-2021 Zig Contributors
+// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
+// The MIT license requires this copyright notice to be included in all copies
+// and substantial portions of the software.
+
+const std = @import("std");
+const fmt = std.fmt;
+const testing = std.testing;
+
+const P256 = @import("p256.zig").P256;
+
+test "p256 ECDH key exchange" {
+ const dha = P256.scalar.random(.Little);
+ const dhb = P256.scalar.random(.Little);
+ const dhA = try P256.basePoint.mul(dha, .Little);
+ const dhB = try P256.basePoint.mul(dhb, .Little);
+ const shareda = try dhA.mul(dhb, .Little);
+ const sharedb = try dhB.mul(dha, .Little);
+ testing.expect(shareda.equivalent(sharedb));
+}
+
+test "p256 point from affine coordinates" {
+ const xh = "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296";
+ const yh = "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5";
+ var xs: [32]u8 = undefined;
+ _ = try fmt.hexToBytes(&xs, xh);
+ var ys: [32]u8 = undefined;
+ _ = try fmt.hexToBytes(&ys, yh);
+ var p = try P256.fromSerializedAffineCoordinates(xs, ys, .Big);
+ testing.expect(p.equivalent(P256.basePoint));
+}
+
+test "p256 test vectors" {
+ const expected = [_][]const u8{
+ "0000000000000000000000000000000000000000000000000000000000000000",
+ "6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296",
+ "7cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978",
+ "5ecbe4d1a6330a44c8f7ef951d4bf165e6c6b721efada985fb41661bc6e7fd6c",
+ "e2534a3532d08fbba02dde659ee62bd0031fe2db785596ef509302446b030852",
+ "51590b7a515140d2d784c85608668fdfef8c82fd1f5be52421554a0dc3d033ed",
+ "b01a172a76a4602c92d3242cb897dde3024c740debb215b4c6b0aae93c2291a9",
+ "8e533b6fa0bf7b4625bb30667c01fb607ef9f8b8a80fef5b300628703187b2a3",
+ "62d9779dbee9b0534042742d3ab54cadc1d238980fce97dbb4dd9dc1db6fb393",
+ "ea68d7b6fedf0b71878938d51d71f8729e0acb8c2c6df8b3d79e8a4b90949ee0",
+ };
+ var p = P256.identityElement;
+ for (expected) |xh| {
+ const x = p.affineCoordinates().x;
+ p = p.add(P256.basePoint);
+ var xs: [32]u8 = undefined;
+ _ = try fmt.hexToBytes(&xs, xh);
+ testing.expectEqualSlices(u8, &x.toBytes(.Big), &xs);
+ }
+}
+
+test "p256 test vectors - doubling" {
+ const expected = [_][]const u8{
+ "6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296",
+ "7cf27b188d034f7e8a52380304b51ac3c08969e277f21b35a60b48fc47669978",
+ "e2534a3532d08fbba02dde659ee62bd0031fe2db785596ef509302446b030852",
+ "62d9779dbee9b0534042742d3ab54cadc1d238980fce97dbb4dd9dc1db6fb393",
+ };
+ var p = P256.basePoint;
+ for (expected) |xh| {
+ const x = p.affineCoordinates().x;
+ p = p.dbl();
+ var xs: [32]u8 = undefined;
+ _ = try fmt.hexToBytes(&xs, xh);
+ testing.expectEqualSlices(u8, &x.toBytes(.Big), &xs);
+ }
+}
+
+test "p256 compressed sec1 encoding/decoding" {
+ const p = P256.random();
+ const s = p.toCompressedSec1();
+ const q = try P256.fromSec1(&s);
+ testing.expect(p.equivalent(q));
+}
+
+test "p256 uncompressed sec1 encoding/decoding" {
+ const p = P256.random();
+ const s = p.toUncompressedSec1();
+ const q = try P256.fromSec1(&s);
+ testing.expect(p.equivalent(q));
+}
+
+test "p256 public key is the neutral element" {
+ const n = P256.scalar.Scalar.zero.toBytes(.Little);
+ const p = P256.random();
+ testing.expectError(error.IdentityElement, p.mul(n, .Little));
+}
+
+test "p256 public key is the neutral element (public verification)" {
+ const n = P256.scalar.Scalar.zero.toBytes(.Little);
+ const p = P256.random();
+ testing.expectError(error.IdentityElement, p.mulPublic(n, .Little));
+}
+
+test "p256 field element non-canonical encoding" {
+ const s = [_]u8{0xff} ** 32;
+ testing.expectError(error.NonCanonical, P256.Fe.fromBytes(s, .Little));
+}
diff --git a/zig/lib/std/crypto/poly1305.zig b/zig/lib/std/crypto/poly1305.zig
index 739c057178..375cf0a3cb 100644
--- a/zig/lib/std/crypto/poly1305.zig
+++ b/zig/lib/std/crypto/poly1305.zig
@@ -39,7 +39,7 @@ pub const Poly1305 = struct {
};
}
- fn blocks(st: *Poly1305, m: []const u8, last: comptime bool) void {
+ fn blocks(st: *Poly1305, m: []const u8, comptime last: bool) void {
const hibit: u64 = if (last) 0 else 1 << 40;
const r0 = st.r[0];
const r1 = st.r[1];
diff --git a/zig/lib/std/crypto/salsa20.zig b/zig/lib/std/crypto/salsa20.zig
index 006767c93f..2a06944adc 100644
--- a/zig/lib/std/crypto/salsa20.zig
+++ b/zig/lib/std/crypto/salsa20.zig
@@ -15,7 +15,10 @@ const Vector = std.meta.Vector;
const Poly1305 = crypto.onetimeauth.Poly1305;
const Blake2b = crypto.hash.blake2.Blake2b;
const X25519 = crypto.dh.X25519;
-const Error = crypto.Error;
+
+const AuthenticationError = crypto.errors.AuthenticationError;
+const IdentityElementError = crypto.errors.IdentityElementError;
+const WeakPublicKeyError = crypto.errors.WeakPublicKeyError;
const Salsa20VecImpl = struct {
const Lane = Vector(4, u32);
@@ -399,7 +402,7 @@ pub const XSalsa20Poly1305 = struct {
/// ad: Associated Data
/// npub: public nonce
/// k: private key
- pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, k: [key_length]u8) Error!void {
+ pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, k: [key_length]u8) AuthenticationError!void {
debug.assert(c.len == m.len);
const extended = extend(k, npub);
var block0 = [_]u8{0} ** 64;
@@ -447,7 +450,7 @@ pub const SecretBox = struct {
/// Verify and decrypt `c` using a nonce `npub` and a key `k`.
/// `m` must be exactly `tag_length` smaller than `c`, as `c` includes an authentication tag in addition to the encrypted message.
- pub fn open(m: []u8, c: []const u8, npub: [nonce_length]u8, k: [key_length]u8) Error!void {
+ pub fn open(m: []u8, c: []const u8, npub: [nonce_length]u8, k: [key_length]u8) AuthenticationError!void {
if (c.len < tag_length) {
return error.AuthenticationFailed;
}
@@ -482,20 +485,20 @@ pub const Box = struct {
pub const KeyPair = X25519.KeyPair;
/// Compute a secret suitable for `secretbox` given a recipent's public key and a sender's secret key.
- pub fn createSharedSecret(public_key: [public_length]u8, secret_key: [secret_length]u8) Error![shared_length]u8 {
+ pub fn createSharedSecret(public_key: [public_length]u8, secret_key: [secret_length]u8) (IdentityElementError || WeakPublicKeyError)![shared_length]u8 {
const p = try X25519.scalarmult(secret_key, public_key);
const zero = [_]u8{0} ** 16;
return Salsa20Impl.hsalsa20(zero, p);
}
/// Encrypt and authenticate a message using a recipient's public key `public_key` and a sender's `secret_key`.
- pub fn seal(c: []u8, m: []const u8, npub: [nonce_length]u8, public_key: [public_length]u8, secret_key: [secret_length]u8) Error!void {
+ pub fn seal(c: []u8, m: []const u8, npub: [nonce_length]u8, public_key: [public_length]u8, secret_key: [secret_length]u8) (IdentityElementError || WeakPublicKeyError)!void {
const shared_key = try createSharedSecret(public_key, secret_key);
return SecretBox.seal(c, m, npub, shared_key);
}
/// Verify and decrypt a message using a recipient's secret key `public_key` and a sender's `public_key`.
- pub fn open(m: []u8, c: []const u8, npub: [nonce_length]u8, public_key: [public_length]u8, secret_key: [secret_length]u8) Error!void {
+ pub fn open(m: []u8, c: []const u8, npub: [nonce_length]u8, public_key: [public_length]u8, secret_key: [secret_length]u8) (IdentityElementError || WeakPublicKeyError || AuthenticationError)!void {
const shared_key = try createSharedSecret(public_key, secret_key);
return SecretBox.open(m, c, npub, shared_key);
}
@@ -528,7 +531,7 @@ pub const SealedBox = struct {
/// Encrypt a message `m` for a recipient whose public key is `public_key`.
/// `c` must be `seal_length` bytes larger than `m`, so that the required metadata can be added.
- pub fn seal(c: []u8, m: []const u8, public_key: [public_length]u8) Error!void {
+ pub fn seal(c: []u8, m: []const u8, public_key: [public_length]u8) (WeakPublicKeyError || IdentityElementError)!void {
debug.assert(c.len == m.len + seal_length);
var ekp = try KeyPair.create(null);
const nonce = createNonce(ekp.public_key, public_key);
@@ -539,7 +542,7 @@ pub const SealedBox = struct {
/// Decrypt a message using a key pair.
/// `m` must be exactly `seal_length` bytes smaller than `c`, as `c` also includes metadata.
- pub fn open(m: []u8, c: []const u8, keypair: KeyPair) Error!void {
+ pub fn open(m: []u8, c: []const u8, keypair: KeyPair) (IdentityElementError || WeakPublicKeyError || AuthenticationError)!void {
if (c.len < seal_length) {
return error.AuthenticationFailed;
}
diff --git a/zig/lib/std/crypto/utils.zig b/zig/lib/std/crypto/utils.zig
index 08271ac9f4..ca86601bf9 100644
--- a/zig/lib/std/crypto/utils.zig
+++ b/zig/lib/std/crypto/utils.zig
@@ -1,7 +1,11 @@
const std = @import("../std.zig");
+const debug = std.debug;
const mem = std.mem;
const testing = std.testing;
+const Endian = std.builtin.Endian;
+const Order = std.math.Order;
+
/// Compares two arrays in constant time (for a given length) and returns whether they are equal.
/// This function was designed to compare short cryptographic secrets (MACs, signatures).
/// For all other applications, use mem.eql() instead.
@@ -38,6 +42,41 @@ pub fn timingSafeEql(comptime T: type, a: T, b: T) bool {
}
}
+/// Compare two integers serialized as arrays of the same size, in constant time.
+/// Returns .lt if ab and .eq if a=b
+pub fn timingSafeCompare(comptime T: type, a: []const T, b: []const T, endian: Endian) Order {
+ debug.assert(a.len == b.len);
+ const bits = switch (@typeInfo(T)) {
+ .Int => |cinfo| if (cinfo.signedness != .unsigned) @compileError("Elements to be compared must be unsigned") else cinfo.bits,
+ else => @compileError("Elements to be compared must be integers"),
+ };
+ comptime const Cext = std.meta.Int(.unsigned, bits + 1);
+ var gt: T = 0;
+ var eq: T = 1;
+ if (endian == .Little) {
+ var i = a.len;
+ while (i != 0) {
+ i -= 1;
+ const x1 = a[i];
+ const x2 = b[i];
+ gt |= @truncate(T, (@as(Cext, x2) -% @as(Cext, x1)) >> bits) & eq;
+ eq &= @truncate(T, (@as(Cext, (x2 ^ x1)) -% 1) >> bits);
+ }
+ } else {
+ for (a) |x1, i| {
+ const x2 = b[i];
+ gt |= @truncate(T, (@as(Cext, x2) -% @as(Cext, x1)) >> bits) & eq;
+ eq &= @truncate(T, (@as(Cext, (x2 ^ x1)) -% 1) >> bits);
+ }
+ }
+ if (gt != 0) {
+ return Order.gt;
+ } else if (eq != 0) {
+ return Order.eq;
+ }
+ return Order.lt;
+}
+
/// Sets a slice to zeroes.
/// Prevents the store from being optimized out.
pub fn secureZero(comptime T: type, s: []T) void {
@@ -70,6 +109,19 @@ test "crypto.utils.timingSafeEql (vectors)" {
testing.expect(timingSafeEql(std.meta.Vector(100, u8), v1, v3));
}
+test "crypto.utils.timingSafeCompare" {
+ var a = [_]u8{10} ** 32;
+ var b = [_]u8{10} ** 32;
+ testing.expectEqual(timingSafeCompare(u8, &a, &b, .Big), .eq);
+ testing.expectEqual(timingSafeCompare(u8, &a, &b, .Little), .eq);
+ a[31] = 1;
+ testing.expectEqual(timingSafeCompare(u8, &a, &b, .Big), .lt);
+ testing.expectEqual(timingSafeCompare(u8, &a, &b, .Little), .lt);
+ a[0] = 20;
+ testing.expectEqual(timingSafeCompare(u8, &a, &b, .Big), .gt);
+ testing.expectEqual(timingSafeCompare(u8, &a, &b, .Little), .lt);
+}
+
test "crypto.utils.secureZero" {
var a = [_]u8{0xfe} ** 8;
var b = [_]u8{0xfe} ** 8;
diff --git a/zig/lib/std/debug.zig b/zig/lib/std/debug.zig
index c84a0e0f18..6cca67f302 100644
--- a/zig/lib/std/debug.zig
+++ b/zig/lib/std/debug.zig
@@ -336,6 +336,13 @@ pub const StackIterator = struct {
fp: usize,
pub fn init(first_address: ?usize, fp: ?usize) StackIterator {
+ if (builtin.arch == .sparcv9) {
+ // Flush all the register windows on stack.
+ asm volatile (
+ \\ flushw
+ ::: "memory");
+ }
+
return StackIterator{
.first_address = first_address,
.fp = fp orelse @frameAddress(),
@@ -343,18 +350,18 @@ pub const StackIterator = struct {
}
// Offset of the saved BP wrt the frame pointer.
- const fp_offset = if (builtin.arch.isRISCV())
+ const fp_offset = if (comptime builtin.arch.isRISCV())
// On RISC-V the frame pointer points to the top of the saved register
// area, on pretty much every other architecture it points to the stack
// slot where the previous frame pointer is saved.
2 * @sizeOf(usize)
- else if (builtin.arch.isSPARC())
+ else if (comptime builtin.arch.isSPARC())
// On SPARC the previous frame pointer is stored at 14 slots past %fp+BIAS.
14 * @sizeOf(usize)
else
0;
- const fp_bias = if (builtin.arch.isSPARC())
+ const fp_bias = if (comptime builtin.arch.isSPARC())
// On SPARC frame pointers are biased by a constant.
2047
else
@@ -380,7 +387,7 @@ pub const StackIterator = struct {
}
fn next_internal(self: *StackIterator) ?usize {
- const fp = if (builtin.arch.isSPARC())
+ const fp = if (comptime builtin.arch.isSPARC())
// On SPARC the offset is positive. (!)
math.add(usize, self.fp, fp_offset) catch return null
else
diff --git a/zig/lib/std/event/rwlock.zig b/zig/lib/std/event/rwlock.zig
index 750131beda..04b45ee308 100644
--- a/zig/lib/std/event/rwlock.zig
+++ b/zig/lib/std/event/rwlock.zig
@@ -264,7 +264,7 @@ var shared_test_data = [1]i32{0} ** 10;
var shared_test_index: usize = 0;
var shared_count: usize = 0;
fn writeRunner(lock: *RwLock) callconv(.Async) void {
- suspend; // resumed by onNextTick
+ suspend {} // resumed by onNextTick
var i: usize = 0;
while (i < shared_test_data.len) : (i += 1) {
@@ -281,7 +281,7 @@ fn writeRunner(lock: *RwLock) callconv(.Async) void {
}
}
fn readRunner(lock: *RwLock) callconv(.Async) void {
- suspend; // resumed by onNextTick
+ suspend {} // resumed by onNextTick
std.time.sleep(1);
var i: usize = 0;
diff --git a/zig/lib/std/fmt.zig b/zig/lib/std/fmt.zig
index bfe28ef203..878969b88a 100644
--- a/zig/lib/std/fmt.zig
+++ b/zig/lib/std/fmt.zig
@@ -696,6 +696,11 @@ fn formatFloatValue(
error.NoSpaceLeft => unreachable,
else => |e| return e,
};
+ } else if (comptime std.mem.eql(u8, fmt, "x")) {
+ formatFloatHexadecimal(value, options, buf_stream.writer()) catch |err| switch (err) {
+ error.NoSpaceLeft => unreachable,
+ else => |e| return e,
+ };
} else {
@compileError("Unsupported format string '" ++ fmt ++ "' for type '" ++ @typeName(@TypeOf(value)) ++ "'");
}
@@ -1023,6 +1028,112 @@ pub fn formatFloatScientific(
}
}
+pub fn formatFloatHexadecimal(
+ value: anytype,
+ options: FormatOptions,
+ writer: anytype,
+) !void {
+ if (math.signbit(value)) {
+ try writer.writeByte('-');
+ }
+ if (math.isNan(value)) {
+ return writer.writeAll("nan");
+ }
+ if (math.isInf(value)) {
+ return writer.writeAll("inf");
+ }
+
+ const T = @TypeOf(value);
+ const TU = std.meta.Int(.unsigned, std.meta.bitCount(T));
+
+ const mantissa_bits = math.floatMantissaBits(T);
+ const exponent_bits = math.floatExponentBits(T);
+ const mantissa_mask = (1 << mantissa_bits) - 1;
+ const exponent_mask = (1 << exponent_bits) - 1;
+ const exponent_bias = (1 << (exponent_bits - 1)) - 1;
+
+ const as_bits = @bitCast(TU, value);
+ var mantissa = as_bits & mantissa_mask;
+ var exponent: i32 = @truncate(u16, (as_bits >> mantissa_bits) & exponent_mask);
+
+ const is_denormal = exponent == 0 and mantissa != 0;
+ const is_zero = exponent == 0 and mantissa == 0;
+
+ if (is_zero) {
+ // Handle this case here to simplify the logic below.
+ try writer.writeAll("0x0");
+ if (options.precision) |precision| {
+ if (precision > 0) {
+ try writer.writeAll(".");
+ try writer.writeByteNTimes('0', precision);
+ }
+ } else {
+ try writer.writeAll(".0");
+ }
+ try writer.writeAll("p0");
+ return;
+ }
+
+ if (is_denormal) {
+ // Adjust the exponent for printing.
+ exponent += 1;
+ } else {
+ // Add the implicit 1.
+ mantissa |= 1 << mantissa_bits;
+ }
+
+ // Fill in zeroes to round the mantissa width to a multiple of 4.
+ if (T == f16) mantissa <<= 2 else if (T == f32) mantissa <<= 1;
+
+ const mantissa_digits = (mantissa_bits + 3) / 4;
+
+ if (options.precision) |precision| {
+ // Round if needed.
+ if (precision < mantissa_digits) {
+ // We always have at least 4 extra bits.
+ var extra_bits = (mantissa_digits - precision) * 4;
+ // The result LSB is the Guard bit, we need two more (Round and
+ // Sticky) to round the value.
+ while (extra_bits > 2) {
+ mantissa = (mantissa >> 1) | (mantissa & 1);
+ extra_bits -= 1;
+ }
+ // Round to nearest, tie to even.
+ mantissa |= @boolToInt(mantissa & 0b100 != 0);
+ mantissa += 1;
+ // Drop the excess bits.
+ mantissa >>= 2;
+ // Restore the alignment.
+ mantissa <<= @intCast(math.Log2Int(TU), (mantissa_digits - precision) * 4);
+
+ const overflow = mantissa & (1 << 1 + mantissa_digits * 4) != 0;
+ // Prefer a normalized result in case of overflow.
+ if (overflow) {
+ mantissa >>= 1;
+ exponent += 1;
+ }
+ }
+ }
+
+ // +1 for the decimal part.
+ var buf: [1 + mantissa_digits]u8 = undefined;
+ const N = formatIntBuf(&buf, mantissa, 16, false, .{ .fill = '0', .width = 1 + mantissa_digits });
+
+ try writer.writeAll("0x");
+ try writer.writeByte(buf[0]);
+ if (options.precision != @as(usize, 0))
+ try writer.writeAll(".");
+ const trimmed = mem.trimRight(u8, buf[1..], "0");
+ try writer.writeAll(trimmed);
+ // Add trailing zeros if explicitly requested.
+ if (options.precision) |precision| if (precision > 0) {
+ if (precision > trimmed.len)
+ try writer.writeByteNTimes('0', precision - trimmed.len);
+ };
+ try writer.writeAll("p");
+ try formatInt(exponent - exponent_bias, 10, false, .{}, writer);
+}
+
/// Print a float of the format x.yyyyy where the number of y is specified by the precision argument.
/// By default floats are printed at full precision (no rounding).
pub fn formatFloatDecimal(
@@ -1506,9 +1617,11 @@ test "parseUnsigned" {
}
pub const parseFloat = @import("fmt/parse_float.zig").parseFloat;
+pub const parseHexFloat = @import("fmt/parse_hex_float.zig").parseHexFloat;
-test "parseFloat" {
+test {
_ = @import("fmt/parse_float.zig");
+ _ = @import("fmt/parse_hex_float.zig");
}
pub fn charToDigit(c: u8, radix: u8) (error{InvalidCharacter}!u8) {
@@ -1898,6 +2011,54 @@ test "float.special" {
try expectFmt("f64: -inf", "f64: {}", .{-math.inf_f64});
}
+test "float.hexadecimal.special" {
+ try expectFmt("f64: nan", "f64: {x}", .{math.nan_f64});
+ // negative nan is not defined by IEE 754,
+ // and ARM thus normalizes it to positive nan
+ if (builtin.arch != builtin.Arch.arm) {
+ try expectFmt("f64: -nan", "f64: {x}", .{-math.nan_f64});
+ }
+ try expectFmt("f64: inf", "f64: {x}", .{math.inf_f64});
+ try expectFmt("f64: -inf", "f64: {x}", .{-math.inf_f64});
+
+ try expectFmt("f64: 0x0.0p0", "f64: {x}", .{@as(f64, 0)});
+ try expectFmt("f64: -0x0.0p0", "f64: {x}", .{-@as(f64, 0)});
+}
+
+test "float.hexadecimal" {
+ try expectFmt("f16: 0x1.554p-2", "f16: {x}", .{@as(f16, 1.0 / 3.0)});
+ try expectFmt("f32: 0x1.555556p-2", "f32: {x}", .{@as(f32, 1.0 / 3.0)});
+ try expectFmt("f64: 0x1.5555555555555p-2", "f64: {x}", .{@as(f64, 1.0 / 3.0)});
+ try expectFmt("f128: 0x1.5555555555555555555555555555p-2", "f128: {x}", .{@as(f128, 1.0 / 3.0)});
+
+ try expectFmt("f16: 0x1.p-14", "f16: {x}", .{@as(f16, math.f16_min)});
+ try expectFmt("f32: 0x1.p-126", "f32: {x}", .{@as(f32, math.f32_min)});
+ try expectFmt("f64: 0x1.p-1022", "f64: {x}", .{@as(f64, math.f64_min)});
+ try expectFmt("f128: 0x1.p-16382", "f128: {x}", .{@as(f128, math.f128_min)});
+
+ try expectFmt("f16: 0x0.004p-14", "f16: {x}", .{@as(f16, math.f16_true_min)});
+ try expectFmt("f32: 0x0.000002p-126", "f32: {x}", .{@as(f32, math.f32_true_min)});
+ try expectFmt("f64: 0x0.0000000000001p-1022", "f64: {x}", .{@as(f64, math.f64_true_min)});
+ try expectFmt("f128: 0x0.0000000000000000000000000001p-16382", "f128: {x}", .{@as(f128, math.f128_true_min)});
+
+ try expectFmt("f16: 0x1.ffcp15", "f16: {x}", .{@as(f16, math.f16_max)});
+ try expectFmt("f32: 0x1.fffffep127", "f32: {x}", .{@as(f32, math.f32_max)});
+ try expectFmt("f64: 0x1.fffffffffffffp1023", "f64: {x}", .{@as(f64, math.f64_max)});
+ try expectFmt("f128: 0x1.ffffffffffffffffffffffffffffp16383", "f128: {x}", .{@as(f128, math.f128_max)});
+}
+
+test "float.hexadecimal.precision" {
+ try expectFmt("f16: 0x1.5p-2", "f16: {x:.1}", .{@as(f16, 1.0 / 3.0)});
+ try expectFmt("f32: 0x1.555p-2", "f32: {x:.3}", .{@as(f32, 1.0 / 3.0)});
+ try expectFmt("f64: 0x1.55555p-2", "f64: {x:.5}", .{@as(f64, 1.0 / 3.0)});
+ try expectFmt("f128: 0x1.5555555p-2", "f128: {x:.7}", .{@as(f128, 1.0 / 3.0)});
+
+ try expectFmt("f16: 0x1.00000p0", "f16: {x:.5}", .{@as(f16, 1.0)});
+ try expectFmt("f32: 0x1.00000p0", "f32: {x:.5}", .{@as(f32, 1.0)});
+ try expectFmt("f64: 0x1.00000p0", "f64: {x:.5}", .{@as(f64, 1.0)});
+ try expectFmt("f128: 0x1.00000p0", "f128: {x:.5}", .{@as(f128, 1.0)});
+}
+
test "float.decimal" {
try expectFmt("f64: 152314000000000000000000000000", "f64: {d}", .{@as(f64, 1.52314e+29)});
try expectFmt("f32: 0", "f32: {d}", .{@as(f32, 0.0)});
diff --git a/zig/lib/std/fmt/parse_hex_float.zig b/zig/lib/std/fmt/parse_hex_float.zig
new file mode 100644
index 0000000000..4bff267a82
--- /dev/null
+++ b/zig/lib/std/fmt/parse_hex_float.zig
@@ -0,0 +1,352 @@
+// SPDX-License-Identifier: MIT
+// Copyright (c) 2015-2021 Zig Contributors
+// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
+// The MIT license requires this copyright notice to be included in all copies
+// and substantial portions of the software.const std = @import("std");
+//
+// The rounding logic is inspired by LLVM's APFloat and Go's atofHex
+// implementation.
+
+const std = @import("std");
+const ascii = std.ascii;
+const fmt = std.fmt;
+const math = std.math;
+const testing = std.testing;
+
+const assert = std.debug.assert;
+
+pub fn parseHexFloat(comptime T: type, s: []const u8) !T {
+ assert(@typeInfo(T) == .Float);
+
+ const IntT = std.meta.Int(.unsigned, @typeInfo(T).Float.bits);
+
+ const mantissa_bits = math.floatMantissaBits(T);
+ const exponent_bits = math.floatExponentBits(T);
+
+ const sign_shift = mantissa_bits + exponent_bits;
+
+ const exponent_bias = (1 << (exponent_bits - 1)) - 1;
+ const exponent_min = 1 - exponent_bias;
+ const exponent_max = exponent_bias;
+
+ if (s.len == 0)
+ return error.InvalidCharacter;
+
+ if (ascii.eqlIgnoreCase(s, "nan")) {
+ return math.nan(T);
+ } else if (ascii.eqlIgnoreCase(s, "inf") or ascii.eqlIgnoreCase(s, "+inf")) {
+ return math.inf(T);
+ } else if (ascii.eqlIgnoreCase(s, "-inf")) {
+ return -math.inf(T);
+ }
+
+ var negative: bool = false;
+ var exp_negative: bool = false;
+
+ var mantissa: u128 = 0;
+ var exponent: i16 = 0;
+ var frac_scale: i16 = 0;
+
+ const State = enum {
+ MaybeSign,
+ Prefix,
+ LeadingIntegerDigit,
+ IntegerDigit,
+ MaybeDot,
+ LeadingFractionDigit,
+ FractionDigit,
+ ExpPrefix,
+ MaybeExpSign,
+ ExpDigit,
+ };
+
+ var state = State.MaybeSign;
+
+ var i: usize = 0;
+ while (i < s.len) {
+ const c = s[i];
+
+ switch (state) {
+ .MaybeSign => {
+ state = .Prefix;
+
+ if (c == '+') {
+ i += 1;
+ } else if (c == '-') {
+ negative = true;
+ i += 1;
+ }
+ },
+ .Prefix => {
+ state = .LeadingIntegerDigit;
+
+ // Match both 0x and 0X.
+ if (i + 2 > s.len or s[i] != '0' or s[i + 1] | 32 != 'x')
+ return error.InvalidCharacter;
+ i += 2;
+ },
+ .LeadingIntegerDigit => {
+ if (c == '0') {
+ // Skip leading zeros.
+ i += 1;
+ } else if (c == '_') {
+ return error.InvalidCharacter;
+ } else {
+ state = .IntegerDigit;
+ }
+ },
+ .IntegerDigit => {
+ if (ascii.isXDigit(c)) {
+ if (mantissa >= math.maxInt(u128) / 16)
+ return error.Overflow;
+ mantissa *%= 16;
+ mantissa += try fmt.charToDigit(c, 16);
+ i += 1;
+ } else if (c == '_') {
+ i += 1;
+ } else {
+ state = .MaybeDot;
+ }
+ },
+ .MaybeDot => {
+ if (c == '.') {
+ state = .LeadingFractionDigit;
+ i += 1;
+ } else state = .ExpPrefix;
+ },
+ .LeadingFractionDigit => {
+ if (c == '_') {
+ return error.InvalidCharacter;
+ } else state = .FractionDigit;
+ },
+ .FractionDigit => {
+ if (ascii.isXDigit(c)) {
+ if (mantissa < math.maxInt(u128) / 16) {
+ mantissa *%= 16;
+ mantissa +%= try fmt.charToDigit(c, 16);
+ frac_scale += 1;
+ } else if (c != '0') {
+ return error.Overflow;
+ }
+ i += 1;
+ } else if (c == '_') {
+ i += 1;
+ } else {
+ state = .ExpPrefix;
+ }
+ },
+ .ExpPrefix => {
+ state = .MaybeExpSign;
+ // Match both p and P.
+ if (c | 32 != 'p')
+ return error.InvalidCharacter;
+ i += 1;
+ },
+ .MaybeExpSign => {
+ state = .ExpDigit;
+
+ if (c == '+') {
+ i += 1;
+ } else if (c == '-') {
+ exp_negative = true;
+ i += 1;
+ }
+ },
+ .ExpDigit => {
+ if (ascii.isXDigit(c)) {
+ if (exponent >= math.maxInt(i16) / 10)
+ return error.Overflow;
+ exponent *%= 10;
+ exponent +%= try fmt.charToDigit(c, 10);
+ i += 1;
+ } else if (c == '_') {
+ i += 1;
+ } else {
+ return error.InvalidCharacter;
+ }
+ },
+ }
+ }
+
+ if (exp_negative)
+ exponent *= -1;
+
+ // Bring the decimal part to the left side of the decimal dot.
+ exponent -= frac_scale * 4;
+
+ if (mantissa == 0) {
+ // Signed zero.
+ return if (negative) -0.0 else 0.0;
+ }
+
+ // Divide by 2^mantissa_bits to right-align the mantissa in the fractional
+ // part.
+ exponent += mantissa_bits;
+
+ // Keep around two extra bits to correctly round any value that doesn't fit
+ // the available mantissa bits. The result LSB serves as Guard bit, the
+ // following one is the Round bit and the last one is the Sticky bit,
+ // computed by OR-ing all the dropped bits.
+
+ // Normalize by aligning the implicit one bit.
+ while (mantissa >> (mantissa_bits + 2) == 0) {
+ mantissa <<= 1;
+ exponent -= 1;
+ }
+
+ // Normalize again by dropping the excess precision.
+ // Note that the discarded bits are folded into the Sticky bit.
+ while (mantissa >> (mantissa_bits + 2 + 1) != 0) {
+ mantissa = mantissa >> 1 | (mantissa & 1);
+ exponent += 1;
+ }
+
+ // Very small numbers can be possibly represented as denormals, reduce the
+ // exponent as much as possible.
+ while (mantissa != 0 and exponent < exponent_min - 2) {
+ mantissa = mantissa >> 1 | (mantissa & 1);
+ exponent += 1;
+ }
+
+ // There are two cases to handle:
+ // - We've truncated more than 0.5ULP (R=S=1), increase the mantissa.
+ // - We've truncated exactly 0.5ULP (R=1 S=0), increase the mantissa if the
+ // result is odd (G=1).
+ // The two checks can be neatly folded as follows.
+ mantissa |= @boolToInt(mantissa & 0b100 != 0);
+ mantissa += 1;
+
+ mantissa >>= 2;
+ exponent += 2;
+
+ if (mantissa & (1 << (mantissa_bits + 1)) != 0) {
+ // Renormalize, if the exponent overflows we'll catch that below.
+ mantissa >>= 1;
+ exponent += 1;
+ }
+
+ if (mantissa >> mantissa_bits == 0) {
+ // This is a denormal number, the biased exponent is zero.
+ exponent = -exponent_bias;
+ }
+
+ if (exponent > exponent_max) {
+ // Overflow, return +inf.
+ return math.inf(T);
+ }
+
+ // Remove the implicit bit.
+ mantissa &= @as(u128, (1 << mantissa_bits) - 1);
+
+ const raw: IntT =
+ (if (negative) @as(IntT, 1) << sign_shift else 0) |
+ @as(IntT, @bitCast(u16, exponent + exponent_bias)) << mantissa_bits |
+ @truncate(IntT, mantissa);
+
+ return @bitCast(T, raw);
+}
+
+test "special" {
+ testing.expect(math.isNan(try parseHexFloat(f32, "nAn")));
+ testing.expect(math.isPositiveInf(try parseHexFloat(f32, "iNf")));
+ testing.expect(math.isPositiveInf(try parseHexFloat(f32, "+Inf")));
+ testing.expect(math.isNegativeInf(try parseHexFloat(f32, "-iNf")));
+}
+test "zero" {
+ testing.expectEqual(@as(f32, 0.0), try parseHexFloat(f32, "0x0"));
+ testing.expectEqual(@as(f32, 0.0), try parseHexFloat(f32, "-0x0"));
+ testing.expectEqual(@as(f32, 0.0), try parseHexFloat(f32, "0x0p42"));
+ testing.expectEqual(@as(f32, 0.0), try parseHexFloat(f32, "-0x0.00000p42"));
+ testing.expectEqual(@as(f32, 0.0), try parseHexFloat(f32, "0x0.00000p666"));
+}
+
+test "f16" {
+ const Case = struct { s: []const u8, v: f16 };
+ const cases: []const Case = &[_]Case{
+ .{ .s = "0x1p0", .v = 1.0 },
+ .{ .s = "-0x1p-1", .v = -0.5 },
+ .{ .s = "0x10p+10", .v = 16384.0 },
+ .{ .s = "0x10p-10", .v = 0.015625 },
+ // Max normalized value.
+ .{ .s = "0x1.ffcp+15", .v = math.f16_max },
+ .{ .s = "-0x1.ffcp+15", .v = -math.f16_max },
+ // Min normalized value.
+ .{ .s = "0x1p-14", .v = math.f16_min },
+ .{ .s = "-0x1p-14", .v = -math.f16_min },
+ // Min denormal value.
+ .{ .s = "0x1p-24", .v = math.f16_true_min },
+ .{ .s = "-0x1p-24", .v = -math.f16_true_min },
+ };
+
+ for (cases) |case| {
+ testing.expectEqual(case.v, try parseHexFloat(f16, case.s));
+ }
+}
+test "f32" {
+ const Case = struct { s: []const u8, v: f32 };
+ const cases: []const Case = &[_]Case{
+ .{ .s = "0x1p0", .v = 1.0 },
+ .{ .s = "-0x1p-1", .v = -0.5 },
+ .{ .s = "0x10p+10", .v = 16384.0 },
+ .{ .s = "0x10p-10", .v = 0.015625 },
+ .{ .s = "0x0.ffffffp128", .v = 0x0.ffffffp128 },
+ .{ .s = "0x0.1234570p-125", .v = 0x0.1234570p-125 },
+ // Max normalized value.
+ .{ .s = "0x1.fffffeP+127", .v = math.f32_max },
+ .{ .s = "-0x1.fffffeP+127", .v = -math.f32_max },
+ // Min normalized value.
+ .{ .s = "0x1p-126", .v = math.f32_min },
+ .{ .s = "-0x1p-126", .v = -math.f32_min },
+ // Min denormal value.
+ .{ .s = "0x1P-149", .v = math.f32_true_min },
+ .{ .s = "-0x1P-149", .v = -math.f32_true_min },
+ };
+
+ for (cases) |case| {
+ testing.expectEqual(case.v, try parseHexFloat(f32, case.s));
+ }
+}
+test "f64" {
+ const Case = struct { s: []const u8, v: f64 };
+ const cases: []const Case = &[_]Case{
+ .{ .s = "0x1p0", .v = 1.0 },
+ .{ .s = "-0x1p-1", .v = -0.5 },
+ .{ .s = "0x10p+10", .v = 16384.0 },
+ .{ .s = "0x10p-10", .v = 0.015625 },
+ // Max normalized value.
+ .{ .s = "0x1.fffffffffffffp+1023", .v = math.f64_max },
+ .{ .s = "-0x1.fffffffffffffp1023", .v = -math.f64_max },
+ // Min normalized value.
+ .{ .s = "0x1p-1022", .v = math.f64_min },
+ .{ .s = "-0x1p-1022", .v = -math.f64_min },
+ // Min denormalized value.
+ .{ .s = "0x1p-1074", .v = math.f64_true_min },
+ .{ .s = "-0x1p-1074", .v = -math.f64_true_min },
+ };
+
+ for (cases) |case| {
+ testing.expectEqual(case.v, try parseHexFloat(f64, case.s));
+ }
+}
+test "f128" {
+ const Case = struct { s: []const u8, v: f128 };
+ const cases: []const Case = &[_]Case{
+ .{ .s = "0x1p0", .v = 1.0 },
+ .{ .s = "-0x1p-1", .v = -0.5 },
+ .{ .s = "0x10p+10", .v = 16384.0 },
+ .{ .s = "0x10p-10", .v = 0.015625 },
+ // Max normalized value.
+ .{ .s = "0xf.fffffffffffffffffffffffffff8p+16380", .v = math.f128_max },
+ .{ .s = "-0xf.fffffffffffffffffffffffffff8p+16380", .v = -math.f128_max },
+ // Min normalized value.
+ .{ .s = "0x1p-16382", .v = math.f128_min },
+ .{ .s = "-0x1p-16382", .v = -math.f128_min },
+ // // Min denormalized value.
+ .{ .s = "0x1p-16494", .v = math.f128_true_min },
+ .{ .s = "-0x1p-16494", .v = -math.f128_true_min },
+ };
+
+ for (cases) |case| {
+ testing.expectEqual(@bitCast(u128, case.v), @bitCast(u128, try parseHexFloat(f128, case.s)));
+ }
+}
diff --git a/zig/lib/std/json/test.zig b/zig/lib/std/json/test.zig
index b6ff03350c..b0d873c910 100644
--- a/zig/lib/std/json/test.zig
+++ b/zig/lib/std/json/test.zig
@@ -29,8 +29,7 @@ fn ok(s: []const u8) !void {
fn err(s: []const u8) void {
testing.expect(!json.validate(s));
- testNonStreaming(s) catch return;
- testing.expect(false);
+ testing.expect(std.meta.isError(testNonStreaming(s)));
}
fn utf8Error(s: []const u8) void {
@@ -48,8 +47,7 @@ fn any(s: []const u8) void {
fn anyStreamingErrNonStreaming(s: []const u8) void {
_ = json.validate(s);
- testNonStreaming(s) catch return;
- testing.expect(false);
+ testing.expect(std.meta.isError(testNonStreaming(s)));
}
fn roundTrip(s: []const u8) !void {
diff --git a/zig/lib/std/macho.zig b/zig/lib/std/macho.zig
index f66626bafe..8f60d8fe94 100644
--- a/zig/lib/std/macho.zig
+++ b/zig/lib/std/macho.zig
@@ -1314,11 +1314,11 @@ pub const BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: u8 = 0x40;
pub const BIND_OPCODE_SET_TYPE_IMM: u8 = 0x50;
pub const BIND_OPCODE_SET_ADDEND_SLEB: u8 = 0x60;
pub const BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: u8 = 0x70;
-pub const BIND_OPCODE_ADD_ADDR_ULEB: 0x80;
+pub const BIND_OPCODE_ADD_ADDR_ULEB: u8 = 0x80;
pub const BIND_OPCODE_DO_BIND: u8 = 0x90;
pub const BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: u8 = 0xa0;
pub const BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: u8 = 0xb0;
-pub const BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: u8 = xc0;
+pub const BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: u8 = 0xc0;
pub const reloc_type_x86_64 = packed enum(u4) {
/// for absolute addresses
diff --git a/zig/lib/std/math.zig b/zig/lib/std/math.zig
index d71cafe5ef..558f541c00 100644
--- a/zig/lib/std/math.zig
+++ b/zig/lib/std/math.zig
@@ -1349,15 +1349,6 @@ pub fn boolMask(comptime MaskInt: type, value: bool) callconv(.Inline) MaskInt {
return @bitCast(i1, @as(u1, @boolToInt(value)));
}
- // At comptime, -% is disallowed on unsigned values.
- // So we need to jump through some hoops in that case.
- // This is a workaround for #7951
- if (@typeInfo(@TypeOf(.{value})).Struct.fields[0].is_comptime) {
- // Since it's comptime, we don't need this to generate nice code.
- // We can just do a branch here.
- return if (value) ~@as(MaskInt, 0) else 0;
- }
-
return -%@intCast(MaskInt, @boolToInt(value));
}
diff --git a/zig/lib/std/math/copysign.zig b/zig/lib/std/math/copysign.zig
index 2804d10495..7861cda8eb 100644
--- a/zig/lib/std/math/copysign.zig
+++ b/zig/lib/std/math/copysign.zig
@@ -20,6 +20,7 @@ pub fn copysign(comptime T: type, x: T, y: T) T {
f16 => copysign16(x, y),
f32 => copysign32(x, y),
f64 => copysign64(x, y),
+ f128 => copysign128(x, y),
else => @compileError("copysign not implemented for " ++ @typeName(T)),
};
}
@@ -51,10 +52,20 @@ fn copysign64(x: f64, y: f64) f64 {
return @bitCast(f64, h1 | h2);
}
+fn copysign128(x: f128, y: f128) f128 {
+ const ux = @bitCast(u128, x);
+ const uy = @bitCast(u128, y);
+
+ const h1 = ux & (maxInt(u128) / 2);
+ const h2 = uy & (@as(u128, 1) << 127);
+ return @bitCast(f128, h1 | h2);
+}
+
test "math.copysign" {
expect(copysign(f16, 1.0, 1.0) == copysign16(1.0, 1.0));
expect(copysign(f32, 1.0, 1.0) == copysign32(1.0, 1.0));
expect(copysign(f64, 1.0, 1.0) == copysign64(1.0, 1.0));
+ expect(copysign(f128, 1.0, 1.0) == copysign128(1.0, 1.0));
}
test "math.copysign16" {
@@ -77,3 +88,10 @@ test "math.copysign64" {
expect(copysign64(-5.0, -1.0) == -5.0);
expect(copysign64(-5.0, 1.0) == 5.0);
}
+
+test "math.copysign128" {
+ expect(copysign128(5.0, 1.0) == 5.0);
+ expect(copysign128(5.0, -1.0) == -5.0);
+ expect(copysign128(-5.0, -1.0) == -5.0);
+ expect(copysign128(-5.0, 1.0) == 5.0);
+}
diff --git a/zig/lib/std/math/isfinite.zig b/zig/lib/std/math/isfinite.zig
index 5266b918df..11a352b042 100644
--- a/zig/lib/std/math/isfinite.zig
+++ b/zig/lib/std/math/isfinite.zig
@@ -24,6 +24,10 @@ pub fn isFinite(x: anytype) bool {
const bits = @bitCast(u64, x);
return bits & (maxInt(u64) >> 1) < (0x7FF << 52);
},
+ f128 => {
+ const bits = @bitCast(u128, x);
+ return bits & (maxInt(u128) >> 1) < (0x7FFF << 112);
+ },
else => {
@compileError("isFinite not implemented for " ++ @typeName(T));
},
@@ -37,10 +41,24 @@ test "math.isFinite" {
expect(isFinite(@as(f32, -0.0)));
expect(isFinite(@as(f64, 0.0)));
expect(isFinite(@as(f64, -0.0)));
+ expect(isFinite(@as(f128, 0.0)));
+ expect(isFinite(@as(f128, -0.0)));
+
expect(!isFinite(math.inf(f16)));
expect(!isFinite(-math.inf(f16)));
expect(!isFinite(math.inf(f32)));
expect(!isFinite(-math.inf(f32)));
expect(!isFinite(math.inf(f64)));
expect(!isFinite(-math.inf(f64)));
+ expect(!isFinite(math.inf(f128)));
+ expect(!isFinite(-math.inf(f128)));
+
+ expect(!isFinite(math.nan(f16)));
+ expect(!isFinite(-math.nan(f16)));
+ expect(!isFinite(math.nan(f32)));
+ expect(!isFinite(-math.nan(f32)));
+ expect(!isFinite(math.nan(f64)));
+ expect(!isFinite(-math.nan(f64)));
+ expect(!isFinite(math.nan(f128)));
+ expect(!isFinite(-math.nan(f128)));
}
diff --git a/zig/lib/std/math/signbit.zig b/zig/lib/std/math/signbit.zig
index 9fb245c3c6..08963b3d94 100644
--- a/zig/lib/std/math/signbit.zig
+++ b/zig/lib/std/math/signbit.zig
@@ -14,6 +14,7 @@ pub fn signbit(x: anytype) bool {
f16 => signbit16(x),
f32 => signbit32(x),
f64 => signbit64(x),
+ f128 => signbit128(x),
else => @compileError("signbit not implemented for " ++ @typeName(T)),
};
}
@@ -33,10 +34,16 @@ fn signbit64(x: f64) bool {
return bits >> 63 != 0;
}
+fn signbit128(x: f128) bool {
+ const bits = @bitCast(u128, x);
+ return bits >> 127 != 0;
+}
+
test "math.signbit" {
expect(signbit(@as(f16, 4.0)) == signbit16(4.0));
expect(signbit(@as(f32, 4.0)) == signbit32(4.0));
expect(signbit(@as(f64, 4.0)) == signbit64(4.0));
+ expect(signbit(@as(f128, 4.0)) == signbit128(4.0));
}
test "math.signbit16" {
@@ -53,3 +60,8 @@ test "math.signbit64" {
expect(!signbit64(4.0));
expect(signbit64(-3.0));
}
+
+test "math.signbit128" {
+ expect(!signbit128(4.0));
+ expect(signbit128(-3.0));
+}
diff --git a/zig/lib/std/math/sqrt.zig b/zig/lib/std/math/sqrt.zig
index 394164ff54..4f32581270 100644
--- a/zig/lib/std/math/sqrt.zig
+++ b/zig/lib/std/math/sqrt.zig
@@ -39,7 +39,13 @@ pub fn sqrt(x: anytype) Sqrt(@TypeOf(x)) {
}
}
-fn sqrt_int(comptime T: type, value: T) std.meta.Int(.unsigned, @typeInfo(T).Int.bits / 2) {
+fn sqrt_int(comptime T: type, value: T) Sqrt(T) {
+ switch (T) {
+ u0 => return 0,
+ u1 => return value,
+ else => {},
+ }
+
var op = value;
var res: T = 0;
var one: T = 1 << (@typeInfo(T).Int.bits - 2);
@@ -58,11 +64,13 @@ fn sqrt_int(comptime T: type, value: T) std.meta.Int(.unsigned, @typeInfo(T).Int
one >>= 2;
}
- const ResultType = std.meta.Int(.unsigned, @typeInfo(T).Int.bits / 2);
+ const ResultType = Sqrt(T);
return @intCast(ResultType, res);
}
test "math.sqrt_int" {
+ expect(sqrt_int(u0, 0) == 0);
+ expect(sqrt_int(u1, 1) == 1);
expect(sqrt_int(u32, 3) == 1);
expect(sqrt_int(u32, 4) == 2);
expect(sqrt_int(u32, 5) == 2);
@@ -74,7 +82,13 @@ test "math.sqrt_int" {
/// Returns the return type `sqrt` will return given an operand of type `T`.
pub fn Sqrt(comptime T: type) type {
return switch (@typeInfo(T)) {
- .Int => |int| std.meta.Int(.unsigned, int.bits / 2),
+ .Int => |int| {
+ return switch (int.bits) {
+ 0 => u0,
+ 1 => u1,
+ else => std.meta.Int(.unsigned, int.bits / 2),
+ };
+ },
else => T,
};
}
diff --git a/zig/lib/std/mem.zig b/zig/lib/std/mem.zig
index 66505f5d29..274da3b8f1 100644
--- a/zig/lib/std/mem.zig
+++ b/zig/lib/std/mem.zig
@@ -1876,7 +1876,11 @@ test "rotate" {
/// Replace needle with replacement as many times as possible, writing to an output buffer which is assumed to be of
/// appropriate size. Use replacementSize to calculate an appropriate buffer size.
+/// The needle must not be empty.
pub fn replace(comptime T: type, input: []const T, needle: []const T, replacement: []const T, output: []T) usize {
+ // Empty needle will loop until output buffer overflows.
+ assert(needle.len > 0);
+
var i: usize = 0;
var slide: usize = 0;
var replacements: usize = 0;
@@ -1899,22 +1903,48 @@ pub fn replace(comptime T: type, input: []const T, needle: []const T, replacemen
test "replace" {
var output: [29]u8 = undefined;
var replacements = replace(u8, "All your base are belong to us", "base", "Zig", output[0..]);
+ var expected: []const u8 = "All your Zig are belong to us";
testing.expect(replacements == 1);
- testing.expect(eql(u8, output[0..], "All your Zig are belong to us"));
+ testing.expectEqualStrings(expected, output[0..expected.len]);
replacements = replace(u8, "Favor reading code over writing code.", "code", "", output[0..]);
+ expected = "Favor reading over writing .";
testing.expect(replacements == 2);
- testing.expect(eql(u8, output[0..], "Favor reading over writing ."));
+ testing.expectEqualStrings(expected, output[0..expected.len]);
+
+ // Empty needle is not allowed but input may be empty.
+ replacements = replace(u8, "", "x", "y", output[0..0]);
+ expected = "";
+ testing.expect(replacements == 0);
+ testing.expectEqualStrings(expected, output[0..expected.len]);
+
+ // Adjacent replacements.
+
+ replacements = replace(u8, "\\n\\n", "\\n", "\n", output[0..]);
+ expected = "\n\n";
+ testing.expect(replacements == 2);
+ testing.expectEqualStrings(expected, output[0..expected.len]);
+
+ replacements = replace(u8, "abbba", "b", "cd", output[0..]);
+ expected = "acdcdcda";
+ testing.expect(replacements == 3);
+ testing.expectEqualStrings(expected, output[0..expected.len]);
}
/// Calculate the size needed in an output buffer to perform a replacement.
+/// The needle must not be empty.
pub fn replacementSize(comptime T: type, input: []const T, needle: []const T, replacement: []const T) usize {
+ // Empty needle will loop forever.
+ assert(needle.len > 0);
+
var i: usize = 0;
var size: usize = input.len;
- while (i < input.len) : (i += 1) {
+ while (i < input.len) {
if (mem.indexOf(T, input[i..], needle) == @as(usize, 0)) {
size = size - needle.len + replacement.len;
i += needle.len;
+ } else {
+ i += 1;
}
}
@@ -1923,9 +1953,15 @@ pub fn replacementSize(comptime T: type, input: []const T, needle: []const T, re
test "replacementSize" {
testing.expect(replacementSize(u8, "All your base are belong to us", "base", "Zig") == 29);
- testing.expect(replacementSize(u8, "", "", "") == 0);
testing.expect(replacementSize(u8, "Favor reading code over writing code.", "code", "") == 29);
testing.expect(replacementSize(u8, "Only one obvious way to do things.", "things.", "things in Zig.") == 41);
+
+ // Empty needle is not allowed but input may be empty.
+ testing.expect(replacementSize(u8, "", "x", "y") == 0);
+
+ // Adjacent replacements.
+ testing.expect(replacementSize(u8, "\\n\\n", "\\n", "\n") == 2);
+ testing.expect(replacementSize(u8, "abbba", "b", "cd") == 8);
}
/// Perform a replacement on an allocated buffer of pre-determined size. Caller must free returned memory.
diff --git a/zig/lib/std/meta.zig b/zig/lib/std/meta.zig
index 860b6874c0..600f3d3c5d 100644
--- a/zig/lib/std/meta.zig
+++ b/zig/lib/std/meta.zig
@@ -117,10 +117,21 @@ test "std.meta.bitCount" {
testing.expect(bitCount(f32) == 32);
}
+/// Returns the alignment of type T.
+/// Note that if T is a pointer or function type the result is different than
+/// the one returned by @alignOf(T).
+/// If T is a pointer type the alignment of the type it points to is returned.
+/// If T is a function type the alignment a target-dependent value is returned.
pub fn alignment(comptime T: type) comptime_int {
- //@alignOf works on non-pointer types
- const P = if (comptime trait.is(.Pointer)(T)) T else *T;
- return @typeInfo(P).Pointer.alignment;
+ return switch (@typeInfo(T)) {
+ .Optional => |info| switch (@typeInfo(info.child)) {
+ .Pointer, .Fn => alignment(info.child),
+ else => @alignOf(T),
+ },
+ .Pointer => |info| info.alignment,
+ .Fn => |info| info.alignment,
+ else => @alignOf(T),
+ };
}
test "std.meta.alignment" {
@@ -129,6 +140,8 @@ test "std.meta.alignment" {
testing.expect(alignment(*align(2) u8) == 2);
testing.expect(alignment([]align(1) u8) == 1);
testing.expect(alignment([]align(2) u8) == 2);
+ testing.expect(alignment(fn () void) > 0);
+ testing.expect(alignment(fn () align(128) void) == 128);
}
pub fn Child(comptime T: type) type {
@@ -888,7 +901,7 @@ pub fn Vector(comptime len: u32, comptime child: type) type {
/// Given a type and value, cast the value to the type as c would.
/// This is for translate-c and is not intended for general use.
pub fn cast(comptime DestType: type, target: anytype) DestType {
- // this function should behave like transCCast in translate-c, except it's for macros
+ // this function should behave like transCCast in translate-c, except it's for macros and enums
const SourceType = @TypeOf(target);
switch (@typeInfo(DestType)) {
.Pointer => {
@@ -925,9 +938,10 @@ pub fn cast(comptime DestType: type, target: anytype) DestType {
}
}
},
- .Enum => {
+ .Enum => |enum_type| {
if (@typeInfo(SourceType) == .Int or @typeInfo(SourceType) == .ComptimeInt) {
- return @intToEnum(DestType, target);
+ const intermediate = cast(enum_type.tag_type, target);
+ return @intToEnum(DestType, intermediate);
}
},
.Int => {
@@ -1015,6 +1029,17 @@ test "std.meta.cast" {
testing.expectEqual(@intToPtr(*u8, 2), cast(*u8, @intToPtr(*volatile u8, 2)));
testing.expectEqual(@intToPtr(?*c_void, 2), cast(?*c_void, @intToPtr(*u8, 2)));
+
+ const C_ENUM = extern enum(c_int) {
+ A = 0,
+ B,
+ C,
+ _,
+ };
+ testing.expectEqual(cast(C_ENUM, @as(i64, -1)), @intToEnum(C_ENUM, -1));
+ testing.expectEqual(cast(C_ENUM, @as(i8, 1)), .B);
+ testing.expectEqual(cast(C_ENUM, @as(u64, 1)), .B);
+ testing.expectEqual(cast(C_ENUM, @as(u64, 42)), @intToEnum(C_ENUM, 42));
}
/// Given a value returns its size as C's sizeof operator would.
@@ -1334,3 +1359,13 @@ test "shuffleVectorIndex" {
testing.expect(shuffleVectorIndex(6, vector_len) == -3);
testing.expect(shuffleVectorIndex(7, vector_len) == -4);
}
+
+/// Returns whether `error_union` contains an error.
+pub fn isError(error_union: anytype) bool {
+ return if (error_union) |_| false else |_| true;
+}
+
+test "isError" {
+ std.testing.expect(isError(math.absInt(@as(i8, -128))));
+ std.testing.expect(!isError(math.absInt(@as(i8, -127))));
+}
diff --git a/zig/lib/std/os.zig b/zig/lib/std/os.zig
index 9826ba46f1..ef6d6a85cd 100644
--- a/zig/lib/std/os.zig
+++ b/zig/lib/std/os.zig
@@ -675,6 +675,9 @@ pub const WriteError = error{
/// This error occurs when no global event loop is configured,
/// and reading from the file descriptor would block.
WouldBlock,
+
+ /// Connection reset by peer.
+ ConnectionResetByPeer,
} || UnexpectedError;
/// Write to a file descriptor.
@@ -752,6 +755,7 @@ pub fn write(fd: fd_t, bytes: []const u8) WriteError!usize {
ENOSPC => return error.NoSpaceLeft,
EPERM => return error.AccessDenied,
EPIPE => return error.BrokenPipe,
+ ECONNRESET => return error.ConnectionResetByPeer,
else => |err| return unexpectedErrno(err),
}
}
@@ -820,6 +824,7 @@ pub fn writev(fd: fd_t, iov: []const iovec_const) WriteError!usize {
ENOSPC => return error.NoSpaceLeft,
EPERM => return error.AccessDenied,
EPIPE => return error.BrokenPipe,
+ ECONNRESET => return error.ConnectionResetByPeer,
else => |err| return unexpectedErrno(err),
}
}
@@ -1044,7 +1049,7 @@ pub const OpenError = error{
} || UnexpectedError;
/// Open and possibly create a file. Keeps trying if it gets interrupted.
-/// See also `openC`.
+/// See also `openZ`.
pub fn open(file_path: []const u8, flags: u32, perm: mode_t) OpenError!fd_t {
if (std.Target.current.os.tag == .windows) {
const file_path_w = try windows.sliceToPrefixedFileW(file_path);
@@ -1142,7 +1147,7 @@ pub fn openW(file_path_w: []const u16, flags: u32, perm: mode_t) OpenError!fd_t
/// Open and possibly create a file. Keeps trying if it gets interrupted.
/// `file_path` is relative to the open directory handle `dir_fd`.
-/// See also `openatC`.
+/// See also `openatZ`.
pub fn openat(dir_fd: fd_t, file_path: []const u8, flags: u32, mode: mode_t) OpenError!fd_t {
if (builtin.os.tag == .wasi) {
@compileError("use openatWasi instead");
@@ -1749,7 +1754,7 @@ pub const UnlinkError = error{
} || UnexpectedError;
/// Delete a name and possibly the file it refers to.
-/// See also `unlinkC`.
+/// See also `unlinkZ`.
pub fn unlink(file_path: []const u8) UnlinkError!void {
if (builtin.os.tag == .wasi) {
@compileError("unlink is not supported in WASI; use unlinkat instead");
@@ -3414,7 +3419,7 @@ pub fn fstat(fd: fd_t) FStatError!Stat {
}
}
-pub const FStatAtError = FStatError || error{ NameTooLong, FileNotFound };
+pub const FStatAtError = FStatError || error{ NameTooLong, FileNotFound, SymLinkLoop };
/// Similar to `fstat`, but returns stat of a resource pointed to by `pathname`
/// which is relative to `dirfd` handle.
@@ -3461,8 +3466,10 @@ pub fn fstatatZ(dirfd: fd_t, pathname: [*:0]const u8, flags: u32) FStatAtError!S
EBADF => unreachable, // Always a race condition.
ENOMEM => return error.SystemResources,
EACCES => return error.AccessDenied,
+ EPERM => return error.AccessDenied,
EFAULT => unreachable,
ENAMETOOLONG => return error.NameTooLong,
+ ELOOP => return error.SymLinkLoop,
ENOENT => return error.FileNotFound,
ENOTDIR => return error.FileNotFound,
else => |err| return unexpectedErrno(err),
diff --git a/zig/lib/std/os/bits/darwin.zig b/zig/lib/std/os/bits/darwin.zig
index aca24b1c0c..e8a477c5d6 100644
--- a/zig/lib/std/os/bits/darwin.zig
+++ b/zig/lib/std/os/bits/darwin.zig
@@ -832,6 +832,13 @@ pub const SO_RCVTIMEO = 0x1006;
pub const SO_ERROR = 0x1007;
pub const SO_TYPE = 0x1008;
+pub const SO_NREAD = 0x1020;
+pub const SO_NKE = 0x1021;
+pub const SO_NOSIGPIPE = 0x1022;
+pub const SO_NOADDRERR = 0x1023;
+pub const SO_NWRITE = 0x1024;
+pub const SO_REUSESHAREUID = 0x1025;
+
fn wstatus(x: u32) u32 {
return x & 0o177;
}
diff --git a/zig/lib/std/os/bits/haiku.zig b/zig/lib/std/os/bits/haiku.zig
index 32093570d7..25a881ba56 100644
--- a/zig/lib/std/os/bits/haiku.zig
+++ b/zig/lib/std/os/bits/haiku.zig
@@ -279,20 +279,10 @@ pub const PROT_READ = 1;
pub const PROT_WRITE = 2;
pub const PROT_EXEC = 4;
-pub const CLOCK_REALTIME = 0;
-pub const CLOCK_VIRTUAL = 1;
-pub const CLOCK_PROF = 2;
-pub const CLOCK_MONOTONIC = 4;
-pub const CLOCK_UPTIME = 5;
-pub const CLOCK_UPTIME_PRECISE = 7;
-pub const CLOCK_UPTIME_FAST = 8;
-pub const CLOCK_REALTIME_PRECISE = 9;
-pub const CLOCK_REALTIME_FAST = 10;
-pub const CLOCK_MONOTONIC_PRECISE = 11;
-pub const CLOCK_MONOTONIC_FAST = 12;
-pub const CLOCK_SECOND = 13;
-pub const CLOCK_THREAD_CPUTIME_ID = 14;
-pub const CLOCK_PROCESS_CPUTIME_ID = 15;
+pub const CLOCK_MONOTONIC = 0;
+pub const CLOCK_REALTIME = -1;
+pub const CLOCK_PROCESS_CPUTIME_ID = -2;
+pub const CLOCK_THREAD_CPUTIME_ID = -3;
pub const MAP_FAILED = @intToPtr(*c_void, maxInt(usize));
pub const MAP_SHARED = 0x0001;
@@ -310,58 +300,59 @@ pub const MAP_NOCORE = 0x00020000;
pub const MAP_PREFAULT_READ = 0x00040000;
pub const MAP_32BIT = 0x00080000;
-pub const WNOHANG = 1;
-pub const WUNTRACED = 2;
-pub const WSTOPPED = WUNTRACED;
-pub const WCONTINUED = 4;
-pub const WNOWAIT = 8;
-pub const WEXITED = 16;
-pub const WTRAPPED = 32;
-
-pub const SA_ONSTACK = 0x0001;
-pub const SA_RESTART = 0x0002;
-pub const SA_RESETHAND = 0x0004;
-pub const SA_NOCLDSTOP = 0x0008;
-pub const SA_NODEFER = 0x0010;
-pub const SA_NOCLDWAIT = 0x0020;
-pub const SA_SIGINFO = 0x0040;
+pub const WNOHANG = 0x1;
+pub const WUNTRACED = 0x2;
+pub const WSTOPPED = 0x10;
+pub const WCONTINUED = 0x4;
+pub const WNOWAIT = 0x20;
+pub const WEXITED = 0x08;
+
+pub const SA_ONSTACK = 0x20;
+pub const SA_RESTART = 0x10;
+pub const SA_RESETHAND = 0x04;
+pub const SA_NOCLDSTOP = 0x01;
+pub const SA_NODEFER = 0x08;
+pub const SA_NOCLDWAIT = 0x02;
+pub const SA_SIGINFO = 0x40;
+pub const SA_NOMASK = SA_NODEFER;
+pub const SA_STACK = SA_ONSTACK;
+pub const SA_ONESHOT = SA_RESETHAND;
pub const SIGHUP = 1;
pub const SIGINT = 2;
pub const SIGQUIT = 3;
pub const SIGILL = 4;
-pub const SIGTRAP = 5;
+pub const SIGCHLD = 5;
pub const SIGABRT = 6;
pub const SIGIOT = SIGABRT;
-pub const SIGEMT = 7;
+pub const SIGPIPE = 7;
pub const SIGFPE = 8;
pub const SIGKILL = 9;
-pub const SIGBUS = 10;
+pub const SIGSTOP = 10;
pub const SIGSEGV = 11;
-pub const SIGSYS = 12;
-pub const SIGPIPE = 13;
+pub const SIGCONT = 12;
+pub const SIGTSTP = 13;
pub const SIGALRM = 14;
pub const SIGTERM = 15;
-pub const SIGURG = 16;
-pub const SIGSTOP = 17;
-pub const SIGTSTP = 18;
-pub const SIGCONT = 19;
-pub const SIGCHLD = 20;
-pub const SIGTTIN = 21;
-pub const SIGTTOU = 22;
-pub const SIGIO = 23;
-pub const SIGXCPU = 24;
-pub const SIGXFSZ = 25;
-pub const SIGVTALRM = 26;
-pub const SIGPROF = 27;
-pub const SIGWINCH = 28;
-pub const SIGINFO = 29;
-pub const SIGUSR1 = 30;
-pub const SIGUSR2 = 31;
-pub const SIGTHR = 32;
-pub const SIGLWP = SIGTHR;
-pub const SIGLIBRT = 33;
-
+pub const SIGTTIN = 16;
+pub const SIGTTOU = 17;
+pub const SIGUSR1 = 18;
+pub const SIGUSR2 = 19;
+pub const SIGWINCH = 20;
+pub const SIGKILLTHR = 21;
+pub const SIGTRAP = 22;
+pub const SIGPOLL = 23;
+pub const SIGPROF = 24;
+pub const SIGSYS = 25;
+pub const SIGURG = 26;
+pub const SIGVTALRM = 27;
+pub const SIGXCPU = 28;
+pub const SIGXFSZ = 29;
+pub const SIGBUS = 30;
+pub const SIGRESERVED1 = 31;
+pub const SIGRESERVED2 = 32;
+
+// TODO: check
pub const SIGRTMIN = 65;
pub const SIGRTMAX = 126;
@@ -645,135 +636,51 @@ pub const EVFILT_SENDFILE = -12;
pub const EVFILT_EMPTY = -13;
-/// On input, NOTE_TRIGGER causes the event to be triggered for output.
-pub const NOTE_TRIGGER = 0x01000000;
-
-/// ignore input fflags
-pub const NOTE_FFNOP = 0x00000000;
-
-/// and fflags
-pub const NOTE_FFAND = 0x40000000;
-
-/// or fflags
-pub const NOTE_FFOR = 0x80000000;
-
-/// copy fflags
-pub const NOTE_FFCOPY = 0xc0000000;
-
-/// mask for operations
-pub const NOTE_FFCTRLMASK = 0xc0000000;
-pub const NOTE_FFLAGSMASK = 0x00ffffff;
-
-/// low water mark
-pub const NOTE_LOWAT = 0x00000001;
-
-/// behave like poll()
-pub const NOTE_FILE_POLL = 0x00000002;
-
-/// vnode was removed
-pub const NOTE_DELETE = 0x00000001;
-
-/// data contents changed
-pub const NOTE_WRITE = 0x00000002;
-
-/// size increased
-pub const NOTE_EXTEND = 0x00000004;
-
-/// attributes changed
-pub const NOTE_ATTRIB = 0x00000008;
-
-/// link count changed
-pub const NOTE_LINK = 0x00000010;
-
-/// vnode was renamed
-pub const NOTE_RENAME = 0x00000020;
-
-/// vnode access was revoked
-pub const NOTE_REVOKE = 0x00000040;
-
-/// vnode was opened
-pub const NOTE_OPEN = 0x00000080;
-
-/// file closed, fd did not allow write
-pub const NOTE_CLOSE = 0x00000100;
-
-/// file closed, fd did allow write
-pub const NOTE_CLOSE_WRITE = 0x00000200;
-
-/// file was read
-pub const NOTE_READ = 0x00000400;
-
-/// process exited
-pub const NOTE_EXIT = 0x80000000;
-
-/// process forked
-pub const NOTE_FORK = 0x40000000;
-
-/// process exec'd
-pub const NOTE_EXEC = 0x20000000;
-
-/// mask for signal & exit status
-pub const NOTE_PDATAMASK = 0x000fffff;
-pub const NOTE_PCTRLMASK = (~NOTE_PDATAMASK);
-
-/// data is seconds
-pub const NOTE_SECONDS = 0x00000001;
-
-/// data is milliseconds
-pub const NOTE_MSECONDS = 0x00000002;
-
-/// data is microseconds
-pub const NOTE_USECONDS = 0x00000004;
-
-/// data is nanoseconds
-pub const NOTE_NSECONDS = 0x00000008;
-
-/// timeout is absolute
-pub const NOTE_ABSTIME = 0x00000010;
-
-pub const TIOCEXCL = 0x2000740d;
-pub const TIOCNXCL = 0x2000740e;
-pub const TIOCSCTTY = 0x20007461;
-pub const TIOCGPGRP = 0x40047477;
-pub const TIOCSPGRP = 0x80047476;
-pub const TIOCOUTQ = 0x40047473;
-pub const TIOCSTI = 0x80017472;
-pub const TIOCGWINSZ = 0x40087468;
-pub const TIOCSWINSZ = 0x80087467;
-pub const TIOCMGET = 0x4004746a;
-pub const TIOCMBIS = 0x8004746c;
-pub const TIOCMBIC = 0x8004746b;
-pub const TIOCMSET = 0x8004746d;
-pub const FIONREAD = 0x4004667f;
-pub const TIOCCONS = 0x80047462;
-pub const TIOCPKT = 0x80047470;
-pub const FIONBIO = 0x8004667e;
-pub const TIOCNOTTY = 0x20007471;
-pub const TIOCSETD = 0x8004741b;
-pub const TIOCGETD = 0x4004741a;
-pub const TIOCSBRK = 0x2000747b;
-pub const TIOCCBRK = 0x2000747a;
-pub const TIOCGSID = 0x40047463;
-pub const TIOCGPTN = 0x4004740f;
-pub const TIOCSIG = 0x2004745f;
+pub const TCGETA = 0x8000;
+pub const TCSETA = 0x8001;
+pub const TCSETAW = 0x8004;
+pub const TCSETAF = 0x8003;
+pub const TCSBRK = 08005;
+pub const TCXONC = 0x8007;
+pub const TCFLSH = 0x8006;
+
+pub const TIOCSCTTY = 0x8017;
+pub const TIOCGPGRP = 0x8015;
+pub const TIOCSPGRP = 0x8016;
+pub const TIOCGWINSZ = 0x8012;
+pub const TIOCSWINSZ = 0x8013;
+pub const TIOCMGET = 0x8018;
+pub const TIOCMBIS = 0x8022;
+pub const TIOCMBIC = 0x8023;
+pub const TIOCMSET = 0x8019;
+pub const FIONREAD = 0xbe000001;
+pub const FIONBIO = 0xbe000000;
+pub const TIOCSBRK = 0x8020;
+pub const TIOCCBRK = 0x8021;
+pub const TIOCGSID = 0x8024;
pub fn WEXITSTATUS(s: u32) u32 {
- return (s & 0xff00) >> 8;
+ return (s & 0xff);
}
+
pub fn WTERMSIG(s: u32) u32 {
- return s & 0x7f;
+ return (s >> 8) & 0xff;
}
+
pub fn WSTOPSIG(s: u32) u32 {
return WEXITSTATUS(s);
}
+
pub fn WIFEXITED(s: u32) bool {
return WTERMSIG(s) == 0;
}
+
pub fn WIFSTOPPED(s: u32) bool {
- return @intCast(u16, (((s & 0xffff) *% 0x10001) >> 8)) > 0x7f00;
+ return ((s >> 16) & 0xff) != 0;
}
+
pub fn WIFSIGNALED(s: u32) bool {
- return (s & 0xffff) -% 1 < 0xff;
+ return ((s >> 8) & 0xff) != 0;
}
pub const winsize = extern struct {
@@ -823,49 +730,47 @@ pub const sigset_t = extern struct {
__bits: [_SIG_WORDS]u32,
};
-pub const EPERM = 1; // Operation not permitted
-pub const ENOENT = 2; // No such file or directory
-pub const ESRCH = 3; // No such process
-pub const EINTR = 4; // Interrupted system call
-pub const EIO = 5; // Input/output error
-pub const ENXIO = 6; // Device not configured
-pub const E2BIG = 7; // Argument list too long
-pub const ENOEXEC = 8; // Exec format error
-pub const EBADF = 9; // Bad file descriptor
-pub const ECHILD = 10; // No child processes
-pub const EDEADLK = 11; // Resource deadlock avoided
-// 11 was EAGAIN
-pub const ENOMEM = 12; // Cannot allocate memory
-pub const EACCES = 13; // Permission denied
-pub const EFAULT = 14; // Bad address
-pub const ENOTBLK = 15; // Block device required
-pub const EBUSY = 16; // Device busy
-pub const EEXIST = 17; // File exists
-pub const EXDEV = 18; // Cross-device link
-pub const ENODEV = 19; // Operation not supported by device
-pub const ENOTDIR = 20; // Not a directory
-pub const EISDIR = 21; // Is a directory
-pub const EINVAL = 22; // Invalid argument
-pub const ENFILE = 23; // Too many open files in system
-pub const EMFILE = 24; // Too many open files
-pub const ENOTTY = 25; // Inappropriate ioctl for device
-pub const ETXTBSY = 26; // Text file busy
-pub const EFBIG = 27; // File too large
-pub const ENOSPC = 28; // No space left on device
-pub const ESPIPE = 29; // Illegal seek
-pub const EROFS = 30; // Read-only filesystem
-pub const EMLINK = 31; // Too many links
-pub const EPIPE = 32; // Broken pipe
+pub const EPERM = -0x7ffffff1; // Operation not permitted
+pub const ENOENT = -0x7fff9ffd; // No such file or directory
+pub const ESRCH = -0x7fff8ff3; // No such process
+pub const EINTR = -0x7ffffff6; // Interrupted system call
+pub const EIO = -0x7fffffff; // Input/output error
+pub const ENXIO = -0x7fff8ff5; // Device not configured
+pub const E2BIG = -0x7fff8fff; // Argument list too long
+pub const ENOEXEC = -0x7fffecfe; // Exec format error
+pub const ECHILD = -0x7fff8ffe; // No child processes
+pub const EDEADLK = -0x7fff8ffd; // Resource deadlock avoided
+pub const ENOMEM = -0x80000000; // Cannot allocate memory
+pub const EACCES = -0x7ffffffe; // Permission denied
+pub const EFAULT = -0x7fffecff; // Bad address
+pub const EBUSY = -0x7ffffff2; // Device busy
+pub const EEXIST = -0x7fff9ffe; // File exists
+pub const EXDEV = -0x7fff9ff5; // Cross-device link
+pub const ENODEV = -0x7fff8ff9; // Operation not supported by device
+pub const ENOTDIR = -0x7fff9ffb; // Not a directory
+pub const EISDIR = -0x7fff9ff7; // Is a directory
+pub const EINVAL = -0x7ffffffb; // Invalid argument
+pub const ENFILE = -0x7fff8ffa; // Too many open files in system
+pub const EMFILE = -0x7fff9ff6; // Too many open files
+pub const ENOTTY = -0x7fff8ff6; // Inappropriate ioctl for device
+pub const ETXTBSY = -0x7fff8fc5; // Text file busy
+pub const EFBIG = -0x7fff8ffc; // File too large
+pub const ENOSPC = -0x7fff9ff9; // No space left on device
+pub const ESPIPE = -0x7fff8ff4; // Illegal seek
+pub const EROFS = -0x7fff9ff8; // Read-only filesystem
+pub const EMLINK = -0x7fff8ffb; // Too many links
+pub const EPIPE = -0x7fff9ff3; // Broken pipe
+pub const EBADF = -0x7fffa000; // Bad file descriptor
// math software
pub const EDOM = 33; // Numerical argument out of domain
pub const ERANGE = 34; // Result too large
// non-blocking and interrupt i/o
-pub const EAGAIN = 35; // Resource temporarily unavailable
-pub const EWOULDBLOCK = EAGAIN; // Operation would block
-pub const EINPROGRESS = 36; // Operation now in progress
-pub const EALREADY = 37; // Operation already in progress
+pub const EAGAIN = -0x7ffffff5;
+pub const EWOULDBLOCK = -0x7ffffff5;
+pub const EINPROGRESS = -0x7fff8fdc;
+pub const EALREADY = -0x7fff8fdb;
// ipc/network software -- argument errors
pub const ENOTSOCK = 38; // Socket operation on non-socket
@@ -1447,3 +1352,20 @@ pub const directory_which = extern enum(c_int) {
_,
};
+
+pub const cc_t = u8;
+pub const speed_t = u8;
+pub const tcflag_t = u32;
+
+pub const NCCS = 32;
+
+pub const termios = extern struct {
+ c_iflag: tcflag_t,
+ c_oflag: tcflag_t,
+ c_cflag: tcflag_t,
+ c_lflag: tcflag_t,
+ c_line: cc_t,
+ c_ispeed: speed_t,
+ c_ospeed: speed_t,
+ cc_t: [NCCS]cc_t,
+};
diff --git a/zig/lib/std/os/bits/linux.zig b/zig/lib/std/os/bits/linux.zig
index 86d89016f3..74f9b14ca2 100644
--- a/zig/lib/std/os/bits/linux.zig
+++ b/zig/lib/std/os/bits/linux.zig
@@ -10,6 +10,7 @@ usingnamespace @import("../bits.zig");
pub usingnamespace switch (builtin.arch) {
.mips, .mipsel => @import("linux/errno-mips.zig"),
+ .sparc, .sparcel, .sparcv9 => @import("linux/errno-sparc.zig"),
else => @import("linux/errno-generic.zig"),
};
@@ -31,6 +32,7 @@ pub usingnamespace @import("linux/prctl.zig");
pub usingnamespace @import("linux/securebits.zig");
const is_mips = builtin.arch.isMIPS();
+const is_ppc = builtin.arch.isPPC();
const is_ppc64 = builtin.arch.isPPC64();
const is_sparc = builtin.arch.isSPARC();
@@ -247,40 +249,78 @@ else
pub const SIG_SETMASK = 2;
};
-pub const SIGHUP = 1;
-pub const SIGINT = 2;
-pub const SIGQUIT = 3;
-pub const SIGILL = 4;
-pub const SIGTRAP = 5;
-pub const SIGABRT = 6;
-pub const SIGIOT = SIGABRT;
-pub const SIGBUS = 7;
-pub const SIGFPE = 8;
-pub const SIGKILL = 9;
-pub const SIGUSR1 = 10;
-pub const SIGSEGV = 11;
-pub const SIGUSR2 = 12;
-pub const SIGPIPE = 13;
-pub const SIGALRM = 14;
-pub const SIGTERM = 15;
-pub const SIGSTKFLT = 16;
-pub const SIGCHLD = 17;
-pub const SIGCONT = 18;
-pub const SIGSTOP = 19;
-pub const SIGTSTP = 20;
-pub const SIGTTIN = 21;
-pub const SIGTTOU = 22;
-pub const SIGURG = 23;
-pub const SIGXCPU = 24;
-pub const SIGXFSZ = 25;
-pub const SIGVTALRM = 26;
-pub const SIGPROF = 27;
-pub const SIGWINCH = 28;
-pub const SIGIO = 29;
-pub const SIGPOLL = 29;
-pub const SIGPWR = 30;
-pub const SIGSYS = 31;
-pub const SIGUNUSED = SIGSYS;
+pub usingnamespace if (is_sparc) struct {
+ pub const SIGHUP = 1;
+ pub const SIGINT = 2;
+ pub const SIGQUIT = 3;
+ pub const SIGILL = 4;
+ pub const SIGTRAP = 5;
+ pub const SIGABRT = 6;
+ pub const SIGEMT = 7;
+ pub const SIGFPE = 8;
+ pub const SIGKILL = 9;
+ pub const SIGBUS = 10;
+ pub const SIGSEGV = 11;
+ pub const SIGSYS = 12;
+ pub const SIGPIPE = 13;
+ pub const SIGALRM = 14;
+ pub const SIGTERM = 15;
+ pub const SIGURG = 16;
+ pub const SIGSTOP = 17;
+ pub const SIGTSTP = 18;
+ pub const SIGCONT = 19;
+ pub const SIGCHLD = 20;
+ pub const SIGTTIN = 21;
+ pub const SIGTTOU = 22;
+ pub const SIGPOLL = 23;
+ pub const SIGXCPU = 24;
+ pub const SIGXFSZ = 25;
+ pub const SIGVTALRM = 26;
+ pub const SIGPROF = 27;
+ pub const SIGWINCH = 28;
+ pub const SIGLOST = 29;
+ pub const SIGUSR1 = 30;
+ pub const SIGUSR2 = 31;
+ pub const SIGIOT = SIGABRT;
+ pub const SIGCLD = SIGCHLD;
+ pub const SIGPWR = SIGLOST;
+ pub const SIGIO = SIGPOLL;
+} else struct {
+ pub const SIGHUP = 1;
+ pub const SIGINT = 2;
+ pub const SIGQUIT = 3;
+ pub const SIGILL = 4;
+ pub const SIGTRAP = 5;
+ pub const SIGABRT = 6;
+ pub const SIGIOT = SIGABRT;
+ pub const SIGBUS = 7;
+ pub const SIGFPE = 8;
+ pub const SIGKILL = 9;
+ pub const SIGUSR1 = 10;
+ pub const SIGSEGV = 11;
+ pub const SIGUSR2 = 12;
+ pub const SIGPIPE = 13;
+ pub const SIGALRM = 14;
+ pub const SIGTERM = 15;
+ pub const SIGSTKFLT = 16;
+ pub const SIGCHLD = 17;
+ pub const SIGCONT = 18;
+ pub const SIGSTOP = 19;
+ pub const SIGTSTP = 20;
+ pub const SIGTTIN = 21;
+ pub const SIGTTOU = 22;
+ pub const SIGURG = 23;
+ pub const SIGXCPU = 24;
+ pub const SIGXFSZ = 25;
+ pub const SIGVTALRM = 26;
+ pub const SIGPROF = 27;
+ pub const SIGWINCH = 28;
+ pub const SIGIO = 29;
+ pub const SIGPOLL = 29;
+ pub const SIGPWR = 30;
+ pub const SIGSYS = 31;
+ pub const SIGUNUSED = SIGSYS;
+};
pub const O_RDONLY = 0o0;
pub const O_WRONLY = 0o1;
@@ -419,7 +459,39 @@ pub const AF_QIPCRTR = PF_QIPCRTR;
pub const AF_SMC = PF_SMC;
pub const AF_MAX = PF_MAX;
-pub usingnamespace if (!is_mips)
+pub usingnamespace if (is_mips)
+ struct {}
+else if (is_ppc or is_ppc64)
+ struct {
+ pub const SO_DEBUG = 1;
+ pub const SO_REUSEADDR = 2;
+ pub const SO_TYPE = 3;
+ pub const SO_ERROR = 4;
+ pub const SO_DONTROUTE = 5;
+ pub const SO_BROADCAST = 6;
+ pub const SO_SNDBUF = 7;
+ pub const SO_RCVBUF = 8;
+ pub const SO_KEEPALIVE = 9;
+ pub const SO_OOBINLINE = 10;
+ pub const SO_NO_CHECK = 11;
+ pub const SO_PRIORITY = 12;
+ pub const SO_LINGER = 13;
+ pub const SO_BSDCOMPAT = 14;
+ pub const SO_REUSEPORT = 15;
+ pub const SO_RCVLOWAT = 16;
+ pub const SO_SNDLOWAT = 17;
+ pub const SO_RCVTIMEO = 18;
+ pub const SO_SNDTIMEO = 19;
+ pub const SO_PASSCRED = 20;
+ pub const SO_PEERCRED = 21;
+ pub const SO_ACCEPTCONN = 30;
+ pub const SO_PEERSEC = 31;
+ pub const SO_SNDBUFFORCE = 32;
+ pub const SO_RCVBUFFORCE = 33;
+ pub const SO_PROTOCOL = 38;
+ pub const SO_DOMAIN = 39;
+ }
+else
struct {
pub const SO_DEBUG = 1;
pub const SO_REUSEADDR = 2;
@@ -448,9 +520,7 @@ pub usingnamespace if (!is_mips)
pub const SO_RCVBUFFORCE = 33;
pub const SO_PROTOCOL = 38;
pub const SO_DOMAIN = 39;
- }
-else
- struct {};
+ };
pub const SO_SECURITY_AUTHENTICATION = 22;
pub const SO_SECURITY_ENCRYPTION_TRANSPORT = 23;
diff --git a/zig/lib/std/os/bits/linux/arm64.zig b/zig/lib/std/os/bits/linux/arm64.zig
index e373d978e1..9737a68de1 100644
--- a/zig/lib/std/os/bits/linux/arm64.zig
+++ b/zig/lib/std/os/bits/linux/arm64.zig
@@ -9,6 +9,7 @@
const std = @import("../../../std.zig");
const linux = std.os.linux;
const socklen_t = linux.socklen_t;
+const sockaddr = linux.sockaddr;
const iovec = linux.iovec;
const iovec_const = linux.iovec_const;
const uid_t = linux.uid_t;
diff --git a/zig/lib/std/os/bits/linux/errno-mips.zig b/zig/lib/std/os/bits/linux/errno-mips.zig
index 2c74fa6f8c..2c22290288 100644
--- a/zig/lib/std/os/bits/linux/errno-mips.zig
+++ b/zig/lib/std/os/bits/linux/errno-mips.zig
@@ -3,6 +3,9 @@
// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
// The MIT license requires this copyright notice to be included in all copies
// and substantial portions of the software.
+
+// These are MIPS ABI compatible.
+
pub const EPERM = 1;
pub const ENOENT = 2;
pub const ESRCH = 3;
@@ -37,6 +40,7 @@ pub const EMLINK = 31;
pub const EPIPE = 32;
pub const EDOM = 33;
pub const ERANGE = 34;
+
pub const ENOMSG = 35;
pub const EIDRM = 36;
pub const ECHRNG = 37;
diff --git a/zig/lib/std/os/bits/linux/errno-sparc.zig b/zig/lib/std/os/bits/linux/errno-sparc.zig
new file mode 100644
index 0000000000..bbeabaaef0
--- /dev/null
+++ b/zig/lib/std/os/bits/linux/errno-sparc.zig
@@ -0,0 +1,144 @@
+// SPDX-License-Identifier: MIT
+// Copyright (c) 2015-2021 Zig Contributors
+// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
+// The MIT license requires this copyright notice to be included in all copies
+// and substantial portions of the software.
+
+// These match the SunOS error numbering scheme.
+
+pub const EPERM = 1;
+pub const ENOENT = 2;
+pub const ESRCH = 3;
+pub const EINTR = 4;
+pub const EIO = 5;
+pub const ENXIO = 6;
+pub const E2BIG = 7;
+pub const ENOEXEC = 8;
+pub const EBADF = 9;
+pub const ECHILD = 10;
+pub const EAGAIN = 11;
+pub const ENOMEM = 12;
+pub const EACCES = 13;
+pub const EFAULT = 14;
+pub const ENOTBLK = 15;
+pub const EBUSY = 16;
+pub const EEXIST = 17;
+pub const EXDEV = 18;
+pub const ENODEV = 19;
+pub const ENOTDIR = 20;
+pub const EISDIR = 21;
+pub const EINVAL = 22;
+pub const ENFILE = 23;
+pub const EMFILE = 24;
+pub const ENOTTY = 25;
+pub const ETXTBSY = 26;
+pub const EFBIG = 27;
+pub const ENOSPC = 28;
+pub const ESPIPE = 29;
+pub const EROFS = 30;
+pub const EMLINK = 31;
+pub const EPIPE = 32;
+pub const EDOM = 33;
+pub const ERANGE = 34;
+
+pub const EWOULDBLOCK = EAGAIN;
+pub const EINPROGRESS = 36;
+pub const EALREADY = 37;
+pub const ENOTSOCK = 38;
+pub const EDESTADDRREQ = 39;
+pub const EMSGSIZE = 40;
+pub const EPROTOTYPE = 41;
+pub const ENOPROTOOPT = 42;
+pub const EPROTONOSUPPORT = 43;
+pub const ESOCKTNOSUPPORT = 44;
+pub const EOPNOTSUPP = 45;
+pub const EPFNOSUPPORT = 46;
+pub const EAFNOSUPPORT = 47;
+pub const EADDRINUSE = 48;
+pub const EADDRNOTAVAIL = 49;
+pub const ENETDOWN = 50;
+pub const ENETUNREACH = 51;
+pub const ENETRESET = 52;
+pub const ECONNABORTED = 53;
+pub const ECONNRESET = 54;
+pub const ENOBUFS = 55;
+pub const EISCONN = 56;
+pub const ENOTCONN = 57;
+pub const ESHUTDOWN = 58;
+pub const ETOOMANYREFS = 59;
+pub const ETIMEDOUT = 60;
+pub const ECONNREFUSED = 61;
+pub const ELOOP = 62;
+pub const ENAMETOOLONG = 63;
+pub const EHOSTDOWN = 64;
+pub const EHOSTUNREACH = 65;
+pub const ENOTEMPTY = 66;
+pub const EPROCLIM = 67;
+pub const EUSERS = 68;
+pub const EDQUOT = 69;
+pub const ESTALE = 70;
+pub const EREMOTE = 71;
+pub const ENOSTR = 72;
+pub const ETIME = 73;
+pub const ENOSR = 74;
+pub const ENOMSG = 75;
+pub const EBADMSG = 76;
+pub const EIDRM = 77;
+pub const EDEADLK = 78;
+pub const ENOLCK = 79;
+pub const ENONET = 80;
+pub const ERREMOTE = 81;
+pub const ENOLINK = 82;
+pub const EADV = 83;
+pub const ESRMNT = 84;
+pub const ECOMM = 85;
+pub const EPROTO = 86;
+pub const EMULTIHOP = 87;
+pub const EDOTDOT = 88;
+pub const EREMCHG = 89;
+pub const ENOSYS = 90;
+pub const ESTRPIPE = 91;
+pub const EOVERFLOW = 92;
+pub const EBADFD = 93;
+pub const ECHRNG = 94;
+pub const EL2NSYNC = 95;
+pub const EL3HLT = 96;
+pub const EL3RST = 97;
+pub const ELNRNG = 98;
+pub const EUNATCH = 99;
+pub const ENOCSI = 100;
+pub const EL2HLT = 101;
+pub const EBADE = 102;
+pub const EBADR = 103;
+pub const EXFULL = 104;
+pub const ENOANO = 105;
+pub const EBADRQC = 106;
+pub const EBADSLT = 107;
+pub const EDEADLOCK = 108;
+pub const EBFONT = 109;
+pub const ELIBEXEC = 110;
+pub const ENODATA = 111;
+pub const ELIBBAD = 112;
+pub const ENOPKG = 113;
+pub const ELIBACC = 114;
+pub const ENOTUNIQ = 115;
+pub const ERESTART = 116;
+pub const EUCLEAN = 117;
+pub const ENOTNAM = 118;
+pub const ENAVAIL = 119;
+pub const EISNAM = 120;
+pub const EREMOTEIO = 121;
+pub const EILSEQ = 122;
+pub const ELIBMAX = 123;
+pub const ELIBSCN = 124;
+pub const ENOMEDIUM = 125;
+pub const EMEDIUMTYPE = 126;
+pub const ECANCELED = 127;
+pub const ENOKEY = 128;
+pub const EKEYEXPIRED = 129;
+pub const EKEYREVOKED = 130;
+pub const EKEYREJECTED = 131;
+pub const EOWNERDEAD = 132;
+pub const ENOTRECOVERABLE = 133;
+pub const ERFKILL = 134;
+pub const EHWPOISON = 135;
diff --git a/zig/lib/std/os/bits/linux/powerpc.zig b/zig/lib/std/os/bits/linux/powerpc.zig
index baa6a57bcf..158a5dab3d 100644
--- a/zig/lib/std/os/bits/linux/powerpc.zig
+++ b/zig/lib/std/os/bits/linux/powerpc.zig
@@ -557,18 +557,10 @@ pub const kernel_stat = extern struct {
size: off_t,
blksize: blksize_t,
blocks: blkcnt_t,
- __atim32: timespec32,
- __mtim32: timespec32,
- __ctim32: timespec32,
- __unused: [2]u32,
atim: timespec,
mtim: timespec,
ctim: timespec,
-
- const timespec32 = extern struct {
- tv_sec: i32,
- tv_nsec: i32,
- };
+ __unused: [2]u32,
pub fn atime(self: @This()) timespec {
return self.atim;
diff --git a/zig/lib/std/os/bits/linux/riscv64.zig b/zig/lib/std/os/bits/linux/riscv64.zig
index 0cbdea415c..192a2a4f71 100644
--- a/zig/lib/std/os/bits/linux/riscv64.zig
+++ b/zig/lib/std/os/bits/linux/riscv64.zig
@@ -376,6 +376,11 @@ pub const timespec = extern struct {
tv_nsec: isize,
};
+pub const timeval = extern struct {
+ tv_sec: time_t,
+ tv_usec: i64,
+};
+
pub const Flock = extern struct {
l_type: i16,
l_whence: i16,
diff --git a/zig/lib/std/os/bits/openbsd.zig b/zig/lib/std/os/bits/openbsd.zig
index 8d1e74ec20..1aa5ce1c9c 100644
--- a/zig/lib/std/os/bits/openbsd.zig
+++ b/zig/lib/std/os/bits/openbsd.zig
@@ -805,7 +805,7 @@ comptime {
if (@sizeOf(usize) == 4)
std.debug.assert(@sizeOf(siginfo_t) == 128)
else
- // Take into account the padding between errno and data fields.
+ // Take into account the padding between errno and data fields.
std.debug.assert(@sizeOf(siginfo_t) == 136);
}
diff --git a/zig/lib/std/os/bits/windows.zig b/zig/lib/std/os/bits/windows.zig
index 28a6a251f8..00ca2a1532 100644
--- a/zig/lib/std/os/bits/windows.zig
+++ b/zig/lib/std/os/bits/windows.zig
@@ -22,6 +22,11 @@ pub const timespec = extern struct {
tv_nsec: c_long,
};
+pub const timeval = extern struct {
+ tv_sec: c_long,
+ tv_usec: c_long,
+};
+
pub const sig_atomic_t = c_int;
/// maximum signal number + 1
diff --git a/zig/lib/std/os/linux.zig b/zig/lib/std/os/linux.zig
index ed08438425..4a67ca7685 100644
--- a/zig/lib/std/os/linux.zig
+++ b/zig/lib/std/os/linux.zig
@@ -52,6 +52,7 @@ pub fn getauxval(index: usize) usize {
// Some architectures (and some syscalls) require 64bit parameters to be passed
// in a even-aligned register pair.
const require_aligned_register_pair =
+ std.Target.current.cpu.arch.isPPC() or
std.Target.current.cpu.arch.isMIPS() or
std.Target.current.cpu.arch.isARM() or
std.Target.current.cpu.arch.isThumb();
@@ -385,7 +386,7 @@ pub fn symlinkat(existing: [*:0]const u8, newfd: i32, newpath: [*:0]const u8) us
}
pub fn pread(fd: i32, buf: [*]u8, count: usize, offset: u64) usize {
- if (@hasField(SYS, "pread64")) {
+ if (@hasField(SYS, "pread64") and usize_bits < 64) {
const offset_halves = splitValue64(offset);
if (require_aligned_register_pair) {
return syscall6(
@@ -408,8 +409,10 @@ pub fn pread(fd: i32, buf: [*]u8, count: usize, offset: u64) usize {
);
}
} else {
+ // Some architectures (eg. 64bit SPARC) pread is called pread64.
+ const S = if (!@hasField(SYS, "pread") and @hasField(SYS, "pread64")) .pread64 else .pread;
return syscall4(
- .pread,
+ S,
@bitCast(usize, @as(isize, fd)),
@ptrToInt(buf),
count,
@@ -449,7 +452,7 @@ pub fn write(fd: i32, buf: [*]const u8, count: usize) usize {
}
pub fn ftruncate(fd: i32, length: u64) usize {
- if (@hasField(SYS, "ftruncate64")) {
+ if (@hasField(SYS, "ftruncate64") and usize_bits < 64) {
const length_halves = splitValue64(length);
if (require_aligned_register_pair) {
return syscall4(
@@ -477,7 +480,7 @@ pub fn ftruncate(fd: i32, length: u64) usize {
}
pub fn pwrite(fd: i32, buf: [*]const u8, count: usize, offset: u64) usize {
- if (@hasField(SYS, "pwrite64")) {
+ if (@hasField(SYS, "pwrite64") and usize_bits < 64) {
const offset_halves = splitValue64(offset);
if (require_aligned_register_pair) {
@@ -501,8 +504,10 @@ pub fn pwrite(fd: i32, buf: [*]const u8, count: usize, offset: u64) usize {
);
}
} else {
+ // Some architectures (eg. 64bit SPARC) pwrite is called pwrite64.
+ const S = if (!@hasField(SYS, "pwrite") and @hasField(SYS, "pwrite64")) .pwrite64 else .pwrite;
return syscall4(
- .pwrite,
+ S,
@bitCast(usize, @as(isize, fd)),
@ptrToInt(buf),
count,
@@ -632,7 +637,7 @@ pub fn tkill(tid: pid_t, sig: i32) usize {
}
pub fn tgkill(tgid: pid_t, tid: pid_t, sig: i32) usize {
- return syscall2(.tgkill, @bitCast(usize, @as(isize, tgid)), @bitCast(usize, @as(isize, tid)), @bitCast(usize, @as(isize, sig)));
+ return syscall3(.tgkill, @bitCast(usize, @as(isize, tgid)), @bitCast(usize, @as(isize, tid)), @bitCast(usize, @as(isize, sig)));
}
pub fn link(oldpath: [*:0]const u8, newpath: [*:0]const u8, flags: i32) usize {
@@ -1387,6 +1392,53 @@ pub fn madvise(address: [*]u8, len: usize, advice: u32) usize {
return syscall3(.madvise, @ptrToInt(address), len, advice);
}
+pub fn pidfd_open(pid: pid_t, flags: u32) usize {
+ return syscall2(.pidfd_open, @bitCast(usize, @as(isize, pid)), flags);
+}
+
+pub fn pidfd_getfd(pidfd: fd_t, targetfd: fd_t, flags: u32) usize {
+ return syscall3(
+ .pidfd_getfd,
+ @bitCast(usize, @as(isize, pidfd)),
+ @bitCast(usize, @as(isize, targetfd)),
+ flags,
+ );
+}
+
+pub fn pidfd_send_signal(pidfd: fd_t, sig: i32, info: ?*siginfo_t, flags: u32) usize {
+ return syscall4(
+ .pidfd_send_signal,
+ @bitCast(usize, @as(isize, pidfd)),
+ @bitCast(usize, @as(isize, sig)),
+ @ptrToInt(info),
+ flags,
+ );
+}
+
+pub fn process_vm_readv(pid: pid_t, local: [*]const iovec, local_count: usize, remote: [*]const iovec, remote_count: usize, flags: usize) usize {
+ return syscall6(
+ .process_vm_readv,
+ @bitCast(usize, @as(isize, pid)),
+ @ptrToInt(local),
+ local_count,
+ @ptrToInt(remote),
+ remote_count,
+ flags,
+ );
+}
+
+pub fn process_vm_writev(pid: pid_t, local: [*]const iovec, local_count: usize, remote: [*]const iovec, remote_count: usize, flags: usize) usize {
+ return syscall6(
+ .process_vm_writev,
+ @bitCast(usize, @as(isize, pid)),
+ @ptrToInt(local),
+ local_count,
+ @ptrToInt(remote),
+ remote_count,
+ flags,
+ );
+}
+
test {
if (builtin.os.tag == .linux) {
_ = @import("linux/test.zig");
diff --git a/zig/lib/std/os/linux/bpf/btf.zig b/zig/lib/std/os/linux/bpf/btf.zig
index b28f65945a..9ba3a0f942 100644
--- a/zig/lib/std/os/linux/bpf/btf.zig
+++ b/zig/lib/std/os/linux/bpf/btf.zig
@@ -6,7 +6,7 @@
const magic = 0xeb9f;
const version = 1;
-pub const ext = @import("ext.zig");
+pub const ext = @import("btf_ext.zig");
/// All offsets are in bytes relative to the end of this header
pub const Header = packed struct {
diff --git a/zig/lib/std/os/linux/tls.zig b/zig/lib/std/os/linux/tls.zig
index 757e77bff3..4a36b0d485 100644
--- a/zig/lib/std/os/linux/tls.zig
+++ b/zig/lib/std/os/linux/tls.zig
@@ -248,7 +248,7 @@ fn initTLS() void {
tls_data = @intToPtr([*]u8, img_base + phdr.p_vaddr)[0..phdr.p_filesz];
tls_data_alloc_size = phdr.p_memsz;
} else {
- tls_align_factor = @alignOf(*usize);
+ tls_align_factor = @alignOf(usize);
tls_data = &[_]u8{};
tls_data_alloc_size = 0;
}
@@ -308,7 +308,7 @@ fn initTLS() void {
}
fn alignPtrCast(comptime T: type, ptr: [*]u8) callconv(.Inline) *T {
- return @ptrCast(*T, @alignCast(@alignOf(*T), ptr));
+ return @ptrCast(*T, @alignCast(@alignOf(T), ptr));
}
/// Initializes all the fields of the static TLS area and returns the computed
diff --git a/zig/lib/std/os/test.zig b/zig/lib/std/os/test.zig
index c8cef38d5d..f0f0a7c988 100644
--- a/zig/lib/std/os/test.zig
+++ b/zig/lib/std/os/test.zig
@@ -261,6 +261,10 @@ test "linkat with different directories" {
test "fstatat" {
// enable when `fstat` and `fstatat` are implemented on Windows
if (builtin.os.tag == .windows) return error.SkipZigTest;
+ if (builtin.os.tag == .freebsd and builtin.mode == .ReleaseFast) {
+ // https://github.com/ziglang/zig/issues/8538
+ return error.SkipZigTest;
+ }
var tmp = tmpDir(.{});
defer tmp.cleanup();
diff --git a/zig/lib/std/os/windows/user32.zig b/zig/lib/std/os/windows/user32.zig
index 9a058f35c0..95ae5f0149 100644
--- a/zig/lib/std/os/windows/user32.zig
+++ b/zig/lib/std/os/windows/user32.zig
@@ -663,7 +663,7 @@ pub fn messageBoxA(hWnd: ?HWND, lpText: [*:0]const u8, lpCaption: [*:0]const u8,
pub extern "user32" fn MessageBoxW(hWnd: ?HWND, lpText: [*:0]const u16, lpCaption: ?[*:0]const u16, uType: UINT) callconv(WINAPI) i32;
pub var pfnMessageBoxW: @TypeOf(MessageBoxW) = undefined;
pub fn messageBoxW(hWnd: ?HWND, lpText: [*:0]const u16, lpCaption: [*:0]const u16, uType: u32) !i32 {
- const function = selectSymbol(pfnMessageBoxW, MessageBoxW, .win2k);
+ const function = selectSymbol(MessageBoxW, pfnMessageBoxW, .win2k);
const value = function(hWnd, lpText, lpCaption, uType);
if (value != 0) return value;
switch (GetLastError()) {
diff --git a/zig/lib/std/special/build_runner.zig b/zig/lib/std/special/build_runner.zig
index 70aa3c8dc6..c6185ef093 100644
--- a/zig/lib/std/special/build_runner.zig
+++ b/zig/lib/std/special/build_runner.zig
@@ -82,9 +82,9 @@ pub fn main() !void {
builder.verbose = true;
} else if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {
return usage(builder, false, stdout_stream);
- } else if (mem.eql(u8, arg, "--prefix")) {
+ } else if (mem.eql(u8, arg, "-p") or mem.eql(u8, arg, "--prefix")) {
install_prefix = nextArg(args, &arg_idx) orelse {
- warn("Expected argument after --prefix\n\n", .{});
+ warn("Expected argument after {s}\n\n", .{arg});
return usageAndErr(builder, false, stderr_stream);
};
} else if (mem.eql(u8, arg, "--search-prefix")) {
@@ -188,7 +188,7 @@ fn usage(builder: *Builder, already_ran_build: bool, out_stream: anytype) !void
\\General Options:
\\ -h, --help Print this help and exit
\\ --verbose Print commands before executing them
- \\ --prefix [path] Override default install prefix
+ \\ -p, --prefix [path] Override default install prefix
\\ --search-prefix [path] Add a path to look for binaries, libraries, headers
\\ --color [auto|off|on] Enable or disable colored error messages
\\
diff --git a/zig/lib/std/special/c.zig b/zig/lib/std/special/c.zig
index f2f55e508e..c7084f3a11 100644
--- a/zig/lib/std/special/c.zig
+++ b/zig/lib/std/special/c.zig
@@ -85,7 +85,7 @@ test "strncpy" {
var s1: [9:0]u8 = undefined;
s1[0] = 0;
- _ = strncpy(&s1, "foobarbaz", 9);
+ _ = strncpy(&s1, "foobarbaz", @sizeOf(@TypeOf(s1)));
std.testing.expectEqualSlices(u8, "foobarbaz", std.mem.spanZ(&s1));
}
@@ -239,7 +239,7 @@ export fn memcmp(vl: ?[*]const u8, vr: ?[*]const u8, n: usize) callconv(.C) isiz
return 0;
}
-test "test_memcmp" {
+test "memcmp" {
const base_arr = &[_]u8{ 1, 1, 1 };
const arr1 = &[_]u8{ 1, 1, 1 };
const arr2 = &[_]u8{ 1, 0, 1 };
@@ -263,7 +263,7 @@ export fn bcmp(vl: [*]allowzero const u8, vr: [*]allowzero const u8, n: usize) c
return 0;
}
-test "test_bcmp" {
+test "bcmp" {
const base_arr = &[_]u8{ 1, 1, 1 };
const arr1 = &[_]u8{ 1, 1, 1 };
const arr2 = &[_]u8{ 1, 0, 1 };
@@ -614,23 +614,24 @@ fn clone() callconv(.Naked) void {
\\ # Shuffle the arguments
\\ mov 217, %%g1
\\ mov %%i2, %%o0
- \\ sub %%i1, 2047, %%o1
+ \\ # Add some extra space for the initial frame
+ \\ sub %%i1, 176 + 2047, %%o1
\\ mov %%i4, %%o2
\\ mov %%i5, %%o3
- \\ ldx [%%fp + 192 - 2*8 + 2047], %%o4
+ \\ ldx [%%fp + 0x8af], %%o4
\\ t 0x6d
\\ bcs,pn %%xcc, 2f
\\ nop
- \\ # sparc64 returns the child pid in o0 and a flag telling
- \\ # whether the process is the child in o1
+ \\ # The child pid is returned in o0 while o1 tells if this
+ \\ # process is # the child (=1) or the parent (=0).
\\ brnz %%o1, 1f
\\ nop
- \\ # This is the parent process, return the child pid
+ \\ # Parent process, return the child pid
\\ mov %%o0, %%i0
\\ ret
\\ restore
\\1:
- \\ # This is the child process
+ \\ # Child process, call func(arg)
\\ mov %%g0, %%fp
\\ call %%g2
\\ mov %%g3, %%o0
@@ -859,6 +860,85 @@ fn generic_fmod(comptime T: type, x: T, y: T) T {
return @bitCast(T, ux);
}
+test "fmod, fmodf" {
+ inline for ([_]type{ f32, f64 }) |T| {
+ const nan_val = math.nan(T);
+ const inf_val = math.inf(T);
+
+ std.testing.expect(isNan(generic_fmod(T, nan_val, 1.0)));
+ std.testing.expect(isNan(generic_fmod(T, 1.0, nan_val)));
+ std.testing.expect(isNan(generic_fmod(T, inf_val, 1.0)));
+ std.testing.expect(isNan(generic_fmod(T, 0.0, 0.0)));
+ std.testing.expect(isNan(generic_fmod(T, 1.0, 0.0)));
+
+ std.testing.expectEqual(@as(T, 0.0), generic_fmod(T, 0.0, 2.0));
+ std.testing.expectEqual(@as(T, -0.0), generic_fmod(T, -0.0, 2.0));
+
+ std.testing.expectEqual(@as(T, -2.0), generic_fmod(T, -32.0, 10.0));
+ std.testing.expectEqual(@as(T, -2.0), generic_fmod(T, -32.0, -10.0));
+ std.testing.expectEqual(@as(T, 2.0), generic_fmod(T, 32.0, 10.0));
+ std.testing.expectEqual(@as(T, 2.0), generic_fmod(T, 32.0, -10.0));
+ }
+}
+
+fn generic_fmin(comptime T: type, x: T, y: T) T {
+ if (isNan(x))
+ return y;
+ if (isNan(y))
+ return x;
+ return if (x < y) x else y;
+}
+
+export fn fminf(x: f32, y: f32) callconv(.C) f32 {
+ return generic_fmin(f32, x, y);
+}
+
+export fn fmin(x: f64, y: f64) callconv(.C) f64 {
+ return generic_fmin(f64, x, y);
+}
+
+test "fmin, fminf" {
+ inline for ([_]type{ f32, f64 }) |T| {
+ const nan_val = math.nan(T);
+
+ std.testing.expect(isNan(generic_fmin(T, nan_val, nan_val)));
+ std.testing.expectEqual(@as(T, 1.0), generic_fmin(T, nan_val, 1.0));
+ std.testing.expectEqual(@as(T, 1.0), generic_fmin(T, 1.0, nan_val));
+
+ std.testing.expectEqual(@as(T, 1.0), generic_fmin(T, 1.0, 10.0));
+ std.testing.expectEqual(@as(T, -1.0), generic_fmin(T, 1.0, -1.0));
+ }
+}
+
+fn generic_fmax(comptime T: type, x: T, y: T) T {
+ if (isNan(x))
+ return y;
+ if (isNan(y))
+ return x;
+ return if (x < y) y else x;
+}
+
+export fn fmaxf(x: f32, y: f32) callconv(.C) f32 {
+ return generic_fmax(f32, x, y);
+}
+
+export fn fmax(x: f64, y: f64) callconv(.C) f64 {
+ return generic_fmax(f64, x, y);
+}
+
+test "fmax, fmaxf" {
+ inline for ([_]type{ f32, f64 }) |T| {
+ const nan_val = math.nan(T);
+
+ std.testing.expect(isNan(generic_fmax(T, nan_val, nan_val)));
+ std.testing.expectEqual(@as(T, 1.0), generic_fmax(T, nan_val, 1.0));
+ std.testing.expectEqual(@as(T, 1.0), generic_fmax(T, 1.0, nan_val));
+
+ std.testing.expectEqual(@as(T, 10.0), generic_fmax(T, 1.0, 10.0));
+ std.testing.expectEqual(@as(T, 1.0), generic_fmax(T, 1.0, -1.0));
+ }
+}
+
// NOTE: The original code is full of implicit signed -> unsigned assumptions and u32 wraparound
// behaviour. Most intermediate i32 values are changed to u32 where appropriate but there are
// potentially some edge cases remaining that are not handled in the same way.
@@ -993,25 +1073,32 @@ export fn sqrt(x: f64) f64 {
}
test "sqrt" {
- const epsilon = 0.000001;
-
- std.testing.expect(sqrt(0.0) == 0.0);
- std.testing.expect(std.math.approxEqAbs(f64, sqrt(2.0), 1.414214, epsilon));
- std.testing.expect(std.math.approxEqAbs(f64, sqrt(3.6), 1.897367, epsilon));
- std.testing.expect(sqrt(4.0) == 2.0);
- std.testing.expect(std.math.approxEqAbs(f64, sqrt(7.539840), 2.745877, epsilon));
- std.testing.expect(std.math.approxEqAbs(f64, sqrt(19.230934), 4.385309, epsilon));
- std.testing.expect(sqrt(64.0) == 8.0);
- std.testing.expect(std.math.approxEqAbs(f64, sqrt(64.1), 8.006248, epsilon));
- std.testing.expect(std.math.approxEqAbs(f64, sqrt(8942.230469), 94.563367, epsilon));
+ const V = [_]f64{
+ 0.0,
+ 4.089288054930154,
+ 7.538757127071935,
+ 8.97780793672623,
+ 5.304443821913729,
+ 5.682408965311888,
+ 0.5846878579110049,
+ 3.650338664297043,
+ 0.3178091951800732,
+ 7.1505232436382835,
+ 3.6589165881946464,
+ };
+
+ // Note that @sqrt will either generate the sqrt opcode (if supported by the
+ // target ISA) or a call to `sqrtf` otherwise.
+ for (V) |val|
+ std.testing.expectEqual(@sqrt(val), sqrt(val));
}
test "sqrt special" {
std.testing.expect(std.math.isPositiveInf(sqrt(std.math.inf(f64))));
std.testing.expect(sqrt(0.0) == 0.0);
std.testing.expect(sqrt(-0.0) == -0.0);
- std.testing.expect(std.math.isNan(sqrt(-1.0)));
- std.testing.expect(std.math.isNan(sqrt(std.math.nan(f64))));
+ std.testing.expect(isNan(sqrt(-1.0)));
+ std.testing.expect(isNan(sqrt(std.math.nan(f64))));
}
export fn sqrtf(x: f32) f32 {
@@ -1091,23 +1178,30 @@ export fn sqrtf(x: f32) f32 {
}
test "sqrtf" {
- const epsilon = 0.000001;
-
- std.testing.expect(sqrtf(0.0) == 0.0);
- std.testing.expect(std.math.approxEqAbs(f32, sqrtf(2.0), 1.414214, epsilon));
- std.testing.expect(std.math.approxEqAbs(f32, sqrtf(3.6), 1.897367, epsilon));
- std.testing.expect(sqrtf(4.0) == 2.0);
- std.testing.expect(std.math.approxEqAbs(f32, sqrtf(7.539840), 2.745877, epsilon));
- std.testing.expect(std.math.approxEqAbs(f32, sqrtf(19.230934), 4.385309, epsilon));
- std.testing.expect(sqrtf(64.0) == 8.0);
- std.testing.expect(std.math.approxEqAbs(f32, sqrtf(64.1), 8.006248, epsilon));
- std.testing.expect(std.math.approxEqAbs(f32, sqrtf(8942.230469), 94.563370, epsilon));
+ const V = [_]f32{
+ 0.0,
+ 4.089288054930154,
+ 7.538757127071935,
+ 8.97780793672623,
+ 5.304443821913729,
+ 5.682408965311888,
+ 0.5846878579110049,
+ 3.650338664297043,
+ 0.3178091951800732,
+ 7.1505232436382835,
+ 3.6589165881946464,
+ };
+
+ // Note that @sqrt will either generate the sqrt opcode (if supported by the
+ // target ISA) or a call to `sqrtf` otherwise.
+ for (V) |val|
+ std.testing.expectEqual(@sqrt(val), sqrtf(val));
}
test "sqrtf special" {
std.testing.expect(std.math.isPositiveInf(sqrtf(std.math.inf(f32))));
std.testing.expect(sqrtf(0.0) == 0.0);
std.testing.expect(sqrtf(-0.0) == -0.0);
- std.testing.expect(std.math.isNan(sqrtf(-1.0)));
- std.testing.expect(std.math.isNan(sqrtf(std.math.nan(f32))));
+ std.testing.expect(isNan(sqrtf(-1.0)));
+ std.testing.expect(isNan(sqrtf(std.math.nan(f32))));
}
diff --git a/zig/lib/std/special/compiler_rt.zig b/zig/lib/std/special/compiler_rt.zig
index 3a7457a4fd..b0cf37553d 100644
--- a/zig/lib/std/special/compiler_rt.zig
+++ b/zig/lib/std/special/compiler_rt.zig
@@ -113,9 +113,11 @@ comptime {
@export(@import("compiler_rt/extendXfYf2.zig").__extenddftf2, .{ .name = "__extenddftf2", .linkage = linkage });
@export(@import("compiler_rt/extendXfYf2.zig").__extendsftf2, .{ .name = "__extendsftf2", .linkage = linkage });
@export(@import("compiler_rt/extendXfYf2.zig").__extendhfsf2, .{ .name = "__extendhfsf2", .linkage = linkage });
+ @export(@import("compiler_rt/extendXfYf2.zig").__extendhftf2, .{ .name = "__extendhftf2", .linkage = linkage });
@export(@import("compiler_rt/truncXfYf2.zig").__truncsfhf2, .{ .name = "__truncsfhf2", .linkage = linkage });
@export(@import("compiler_rt/truncXfYf2.zig").__truncdfhf2, .{ .name = "__truncdfhf2", .linkage = linkage });
+ @export(@import("compiler_rt/truncXfYf2.zig").__trunctfhf2, .{ .name = "__trunctfhf2", .linkage = linkage });
@export(@import("compiler_rt/truncXfYf2.zig").__trunctfdf2, .{ .name = "__trunctfdf2", .linkage = linkage });
@export(@import("compiler_rt/truncXfYf2.zig").__trunctfsf2, .{ .name = "__trunctfsf2", .linkage = linkage });
@@ -296,7 +298,7 @@ comptime {
@export(@import("compiler_rt/sparc.zig")._Qp_qtod, .{ .name = "_Qp_qtod", .linkage = linkage });
}
- if (builtin.arch == .powerpc or builtin.arch.isPPC64()) {
+ if ((builtin.arch == .powerpc or builtin.arch.isPPC64()) and !is_test) {
@export(@import("compiler_rt/addXf3.zig").__addtf3, .{ .name = "__addkf3", .linkage = linkage });
@export(@import("compiler_rt/addXf3.zig").__subtf3, .{ .name = "__subkf3", .linkage = linkage });
@export(@import("compiler_rt/mulXf3.zig").__multf3, .{ .name = "__mulkf3", .linkage = linkage });
diff --git a/zig/lib/std/special/compiler_rt/extendXfYf2.zig b/zig/lib/std/special/compiler_rt/extendXfYf2.zig
index c5b93fa51e..59be8441fa 100644
--- a/zig/lib/std/special/compiler_rt/extendXfYf2.zig
+++ b/zig/lib/std/special/compiler_rt/extendXfYf2.zig
@@ -23,6 +23,10 @@ pub fn __extendhfsf2(a: u16) callconv(.C) f32 {
return @call(.{ .modifier = .always_inline }, extendXfYf2, .{ f32, f16, a });
}
+pub fn __extendhftf2(a: u16) callconv(.C) f128 {
+ return @call(.{ .modifier = .always_inline }, extendXfYf2, .{ f128, f16, a });
+}
+
pub fn __aeabi_h2f(arg: u16) callconv(.AAPCS) f32 {
@setRuntimeSafety(false);
return @call(.{ .modifier = .always_inline }, __extendhfsf2, .{arg});
diff --git a/zig/lib/std/special/compiler_rt/extendXfYf2_test.zig b/zig/lib/std/special/compiler_rt/extendXfYf2_test.zig
index 6a3f69d8e9..f05d33eac3 100644
--- a/zig/lib/std/special/compiler_rt/extendXfYf2_test.zig
+++ b/zig/lib/std/special/compiler_rt/extendXfYf2_test.zig
@@ -4,9 +4,10 @@
// The MIT license requires this copyright notice to be included in all copies
// and substantial portions of the software.
const builtin = @import("builtin");
-const __extenddftf2 = @import("extendXfYf2.zig").__extenddftf2;
const __extendhfsf2 = @import("extendXfYf2.zig").__extendhfsf2;
+const __extendhftf2 = @import("extendXfYf2.zig").__extendhftf2;
const __extendsftf2 = @import("extendXfYf2.zig").__extendsftf2;
+const __extenddftf2 = @import("extendXfYf2.zig").__extenddftf2;
fn test__extenddftf2(a: f64, expectedHi: u64, expectedLo: u64) void {
const x = __extenddftf2(a);
@@ -161,3 +162,49 @@ fn makeNaN32(rand: u32) f32 {
fn makeInf32() f32 {
return @bitCast(f32, @as(u32, 0x7f800000));
}
+
+fn test__extendhftf2(a: u16, expectedHi: u64, expectedLo: u64) void {
+ const x = __extendhftf2(a);
+
+ const rep = @bitCast(u128, x);
+ const hi = @intCast(u64, rep >> 64);
+ const lo = @truncate(u64, rep);
+
+ if (hi == expectedHi and lo == expectedLo)
+ return;
+
+ // test other possible NaN representation(signal NaN)
+ if (expectedHi == 0x7fff800000000000 and expectedLo == 0x0) {
+ if ((hi & 0x7fff000000000000) == 0x7fff000000000000 and
+ ((hi & 0xffffffffffff) > 0 or lo > 0))
+ {
+ return;
+ }
+ }
+
+ @panic("__extendhftf2 test failure");
+}
+
+test "extendhftf2" {
+ // qNaN
+ test__extendhftf2(0x7e00, 0x7fff800000000000, 0x0);
+ // NaN
+ test__extendhftf2(0x7d00, 0x7fff400000000000, 0x0);
+ // inf
+ test__extendhftf2(0x7c00, 0x7fff000000000000, 0x0);
+ test__extendhftf2(0xfc00, 0xffff000000000000, 0x0);
+ // zero
+ test__extendhftf2(0x0000, 0x0000000000000000, 0x0);
+ test__extendhftf2(0x8000, 0x8000000000000000, 0x0);
+ // denormal
+ test__extendhftf2(0x0010, 0x3feb000000000000, 0x0);
+ test__extendhftf2(0x0001, 0x3fe7000000000000, 0x0);
+ test__extendhftf2(0x8001, 0xbfe7000000000000, 0x0);
+
+ // pi
+ test__extendhftf2(0x4248, 0x4000920000000000, 0x0);
+ test__extendhftf2(0xc248, 0xc000920000000000, 0x0);
+
+ test__extendhftf2(0x508c, 0x4004230000000000, 0x0);
+ test__extendhftf2(0x1bb7, 0x3ff6edc000000000, 0x0);
+}
diff --git a/zig/lib/std/special/compiler_rt/truncXfYf2.zig b/zig/lib/std/special/compiler_rt/truncXfYf2.zig
index 470ac17c2c..e85aa363db 100644
--- a/zig/lib/std/special/compiler_rt/truncXfYf2.zig
+++ b/zig/lib/std/special/compiler_rt/truncXfYf2.zig
@@ -13,6 +13,10 @@ pub fn __truncdfhf2(a: f64) callconv(.C) u16 {
return @bitCast(u16, @call(.{ .modifier = .always_inline }, truncXfYf2, .{ f16, f64, a }));
}
+pub fn __trunctfhf2(a: f128) callconv(.C) u16 {
+ return @bitCast(u16, @call(.{ .modifier = .always_inline }, truncXfYf2, .{ f16, f128, a }));
+}
+
pub fn __trunctfsf2(a: f128) callconv(.C) f32 {
return @call(.{ .modifier = .always_inline }, truncXfYf2, .{ f32, f128, a });
}
@@ -122,7 +126,7 @@ fn truncXfYf2(comptime dst_t: type, comptime src_t: type, a: src_t) dst_t {
if (shift > srcSigBits) {
absResult = 0;
} else {
- const sticky: src_rep_t = significand << @intCast(SrcShift, srcBits - shift);
+ const sticky: src_rep_t = @boolToInt(significand << @intCast(SrcShift, srcBits - shift) != 0);
const denormalizedSignificand: src_rep_t = significand >> @intCast(SrcShift, shift) | sticky;
absResult = @intCast(dst_rep_t, denormalizedSignificand >> (srcSigBits - dstSigBits));
const roundBits: src_rep_t = denormalizedSignificand & roundMask;
diff --git a/zig/lib/std/special/compiler_rt/truncXfYf2_test.zig b/zig/lib/std/special/compiler_rt/truncXfYf2_test.zig
index 6426614b07..4fae5d1fc0 100644
--- a/zig/lib/std/special/compiler_rt/truncXfYf2_test.zig
+++ b/zig/lib/std/special/compiler_rt/truncXfYf2_test.zig
@@ -242,3 +242,59 @@ test "truncdfsf2" {
// huge number becomes inf
test__truncdfsf2(340282366920938463463374607431768211456.0, 0x7f800000);
}
+
+const __trunctfhf2 = @import("truncXfYf2.zig").__trunctfhf2;
+
+fn test__trunctfhf2(a: f128, expected: u16) void {
+ const x = __trunctfhf2(a);
+
+ const rep = @bitCast(u16, x);
+ if (rep == expected) {
+ return;
+ }
+
+ @import("std").debug.warn("got 0x{x} wanted 0x{x}\n", .{ rep, expected });
+
+ @panic("__trunctfhf2 test failure");
+}
+
+test "trunctfhf2" {
+ // qNaN
+ test__trunctfhf2(@bitCast(f128, @as(u128, 0x7fff8000000000000000000000000000)), 0x7e00);
+ // NaN
+ test__trunctfhf2(@bitCast(f128, @as(u128, 0x7fff0000000000000000000000000001)), 0x7e00);
+ // inf
+ test__trunctfhf2(@bitCast(f128, @as(u128, 0x7fff0000000000000000000000000000)), 0x7c00);
+ test__trunctfhf2(-@bitCast(f128, @as(u128, 0x7fff0000000000000000000000000000)), 0xfc00);
+ // zero
+ test__trunctfhf2(0.0, 0x0);
+ test__trunctfhf2(-0.0, 0x8000);
+
+ test__trunctfhf2(3.1415926535, 0x4248);
+ test__trunctfhf2(-3.1415926535, 0xc248);
+ test__trunctfhf2(0x1.987124876876324p+100, 0x7c00);
+ test__trunctfhf2(0x1.987124876876324p+12, 0x6e62);
+ test__trunctfhf2(0x1.0p+0, 0x3c00);
+ test__trunctfhf2(0x1.0p-14, 0x0400);
+ // denormal
+ test__trunctfhf2(0x1.0p-20, 0x0010);
+ test__trunctfhf2(0x1.0p-24, 0x0001);
+ test__trunctfhf2(-0x1.0p-24, 0x8001);
+ test__trunctfhf2(0x1.5p-25, 0x0001);
+ // and back to zero
+ test__trunctfhf2(0x1.0p-25, 0x0000);
+ test__trunctfhf2(-0x1.0p-25, 0x8000);
+ // max (precise)
+ test__trunctfhf2(65504.0, 0x7bff);
+ // max (rounded)
+ test__trunctfhf2(65519.0, 0x7bff);
+ // max (to +inf)
+ test__trunctfhf2(65520.0, 0x7c00);
+ test__trunctfhf2(65536.0, 0x7c00);
+ test__trunctfhf2(-65520.0, 0xfc00);
+
+ test__trunctfhf2(0x1.23a2abb4a2ddee355f36789abcdep+5, 0x508f);
+ test__trunctfhf2(0x1.e3d3c45bd3abfd98b76a54cc321fp-9, 0x1b8f);
+ test__trunctfhf2(0x1.234eebb5faa678f4488693abcdefp+453, 0x7c00);
+ test__trunctfhf2(0x1.edcba9bb8c76a5a43dd21f334634p-43, 0x0);
+}
diff --git a/zig/lib/std/std.zig b/zig/lib/std/std.zig
index 5f10def72e..940d1ab42e 100644
--- a/zig/lib/std/std.zig
+++ b/zig/lib/std/std.zig
@@ -88,6 +88,7 @@ pub const time = @import("time.zig");
pub const unicode = @import("unicode.zig");
pub const valgrind = @import("valgrind.zig");
pub const wasm = @import("wasm.zig");
+pub const x = @import("x.zig");
pub const zig = @import("zig.zig");
pub const start = @import("start.zig");
diff --git a/zig/lib/std/target.zig b/zig/lib/std/target.zig
index 3372f617a8..e9185ef345 100644
--- a/zig/lib/std/target.zig
+++ b/zig/lib/std/target.zig
@@ -211,8 +211,9 @@ pub const Target = struct {
/// If neither of these cases apply, a runtime check should be used to determine if the
/// target supports a given OS feature.
///
- /// Binaries built with a given maximum version will continue to function on newer operating system
- /// versions. However, such a binary may not take full advantage of the newer operating system APIs.
+ /// Binaries built with a given maximum version will continue to function on newer
+ /// operating system versions. However, such a binary may not take full advantage of the
+ /// newer operating system APIs.
///
/// See `Os.isAtLeast`.
pub const VersionRange = union {
@@ -260,7 +261,7 @@ pub const Target = struct {
.freebsd => return .{
.semver = Version.Range{
.min = .{ .major = 12, .minor = 0 },
- .max = .{ .major = 12, .minor = 1 },
+ .max = .{ .major = 13, .minor = 0 },
},
},
.macos => return .{
@@ -800,6 +801,13 @@ pub const Target = struct {
};
}
+ pub fn isPPC(arch: Arch) bool {
+ return switch (arch) {
+ .powerpc, .powerpcle => true,
+ else => false,
+ };
+ }
+
pub fn isPPC64(arch: Arch) bool {
return switch (arch) {
.powerpc64, .powerpc64le => true,
@@ -1184,8 +1192,8 @@ pub const Target = struct {
.mips, .mipsel => &mips.cpu.mips32,
.mips64, .mips64el => &mips.cpu.mips64,
.msp430 => &msp430.cpu.generic,
- .powerpc => &powerpc.cpu.ppc32,
- .powerpcle => &powerpc.cpu.ppc32,
+ .powerpc => &powerpc.cpu.ppc,
+ .powerpcle => &powerpc.cpu.ppc,
.powerpc64 => &powerpc.cpu.ppc64,
.powerpc64le => &powerpc.cpu.ppc64le,
.amdgcn => &amdgpu.cpu.generic,
diff --git a/zig/lib/std/target/aarch64.zig b/zig/lib/std/target/aarch64.zig
index 03c2031207..a331d8a874 100644
--- a/zig/lib/std/target/aarch64.zig
+++ b/zig/lib/std/target/aarch64.zig
@@ -1621,6 +1621,16 @@ pub const cpu = struct {
.apple_a7,
}),
};
+ pub const emag = CpuModel{
+ .name = "emag",
+ .llvm_name = null,
+ .features = featureSet(&[_]Feature{
+ .crc,
+ .crypto,
+ .perfmon,
+ .v8a,
+ }),
+ };
pub const exynos_m1 = CpuModel{
.name = "exynos_m1",
.llvm_name = null,
@@ -1867,4 +1877,12 @@ pub const cpu = struct {
.v8_2a,
}),
};
+ pub const xgene1 = CpuModel{
+ .name = "xgene1",
+ .llvm_name = null,
+ .features = featureSet(&[_]Feature{
+ .perfmon,
+ .v8a,
+ }),
+ };
};
diff --git a/zig/lib/std/target/powerpc.zig b/zig/lib/std/target/powerpc.zig
index 4e2200a47f..db4d5dccdc 100644
--- a/zig/lib/std/target/powerpc.zig
+++ b/zig/lib/std/target/powerpc.zig
@@ -751,13 +751,6 @@ pub const cpu = struct {
.hard_float,
}),
};
- pub const ppc32 = CpuModel{
- .name = "ppc32",
- .llvm_name = "ppc32",
- .features = featureSet(&[_]Feature{
- .hard_float,
- }),
- };
pub const ppc64 = CpuModel{
.name = "ppc64",
.llvm_name = "ppc64",
diff --git a/zig/lib/std/unicode.zig b/zig/lib/std/unicode.zig
index f9ad6e3eb5..9eed0f466f 100644
--- a/zig/lib/std/unicode.zig
+++ b/zig/lib/std/unicode.zig
@@ -206,7 +206,7 @@ pub fn utf8ValidateSlice(s: []const u8) bool {
return false;
}
- if (utf8Decode(s[i .. i + cp_len])) |_| {} else |_| {
+ if (std.meta.isError(utf8Decode(s[i .. i + cp_len]))) {
return false;
}
i += cp_len;
diff --git a/zig/lib/std/x.zig b/zig/lib/std/x.zig
new file mode 100644
index 0000000000..a123591470
--- /dev/null
+++ b/zig/lib/std/x.zig
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: MIT
+// Copyright (c) 2015-2021 Zig Contributors
+// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
+// The MIT license requires this copyright notice to be included in all copies
+// and substantial portions of the software.
+
+const std = @import("std.zig");
+
+pub const os = struct {
+ pub const Socket = @import("x/os/Socket.zig");
+ pub usingnamespace @import("x/os/net.zig");
+};
+
+pub const net = struct {
+ pub const ip = @import("x/net/ip.zig");
+ pub const tcp = @import("x/net/tcp.zig");
+};
+
+test {
+ inline for (.{ os, net }) |module| {
+ std.testing.refAllDecls(module);
+ }
+}
diff --git a/zig/lib/std/x/net/ip.zig b/zig/lib/std/x/net/ip.zig
new file mode 100644
index 0000000000..7f2d82d208
--- /dev/null
+++ b/zig/lib/std/x/net/ip.zig
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: MIT
+// Copyright (c) 2015-2021 Zig Contributors
+// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
+// The MIT license requires this copyright notice to be included in all copies
+// and substantial portions of the software.
+
+const std = @import("../../std.zig");
+
+const fmt = std.fmt;
+
+const IPv4 = std.x.os.IPv4;
+const IPv6 = std.x.os.IPv6;
+const Socket = std.x.os.Socket;
+
+/// A generic IP abstraction.
+const ip = @This();
+
+/// A union of all eligible types of IP addresses.
+pub const Address = union(enum) {
+ ipv4: IPv4.Address,
+ ipv6: IPv6.Address,
+
+ /// Instantiate a new address with a IPv4 host and port.
+ pub fn initIPv4(host: IPv4, port: u16) Address {
+ return .{ .ipv4 = .{ .host = host, .port = port } };
+ }
+
+ /// Instantiate a new address with a IPv6 host and port.
+ pub fn initIPv6(host: IPv6, port: u16) Address {
+ return .{ .ipv6 = .{ .host = host, .port = port } };
+ }
+
+ /// Re-interpret a generic socket address into an IP address.
+ pub fn from(address: Socket.Address) ip.Address {
+ return switch (address) {
+ .ipv4 => |ipv4_address| .{ .ipv4 = ipv4_address },
+ .ipv6 => |ipv6_address| .{ .ipv6 = ipv6_address },
+ };
+ }
+
+ /// Re-interpret an IP address into a generic socket address.
+ pub fn into(self: ip.Address) Socket.Address {
+ return switch (self) {
+ .ipv4 => |ipv4_address| .{ .ipv4 = ipv4_address },
+ .ipv6 => |ipv6_address| .{ .ipv6 = ipv6_address },
+ };
+ }
+
+ /// Implements the `std.fmt.format` API.
+ pub fn format(
+ self: ip.Address,
+ comptime layout: []const u8,
+ opts: fmt.FormatOptions,
+ writer: anytype,
+ ) !void {
+ switch (self) {
+ .ipv4 => |address| try fmt.format(writer, "{}:{}", .{ address.host, address.port }),
+ .ipv6 => |address| try fmt.format(writer, "{}:{}", .{ address.host, address.port }),
+ }
+ }
+};
diff --git a/zig/lib/std/x/net/tcp.zig b/zig/lib/std/x/net/tcp.zig
new file mode 100644
index 0000000000..a4cc4a288c
--- /dev/null
+++ b/zig/lib/std/x/net/tcp.zig
@@ -0,0 +1,352 @@
+// SPDX-License-Identifier: MIT
+// Copyright (c) 2015-2021 Zig Contributors
+// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
+// The MIT license requires this copyright notice to be included in all copies
+// and substantial portions of the software.
+
+const std = @import("../../std.zig");
+
+const os = std.os;
+const ip = std.x.net.ip;
+
+const fmt = std.fmt;
+const mem = std.mem;
+const builtin = std.builtin;
+const testing = std.testing;
+
+const IPv4 = std.x.os.IPv4;
+const IPv6 = std.x.os.IPv6;
+const Socket = std.x.os.Socket;
+
+/// A generic TCP socket abstraction.
+const tcp = @This();
+
+/// A TCP client-address pair.
+pub const Connection = struct {
+ client: tcp.Client,
+ address: ip.Address,
+
+ /// Enclose a TCP client and address into a client-address pair.
+ pub fn from(conn: Socket.Connection) tcp.Connection {
+ return .{
+ .client = tcp.Client.from(conn.socket),
+ .address = ip.Address.from(conn.address),
+ };
+ }
+
+ /// Unravel a TCP client-address pair into a socket-address pair.
+ pub fn into(self: tcp.Connection) Socket.Connection {
+ return .{
+ .socket = self.client.socket,
+ .address = self.address.into(),
+ };
+ }
+
+ /// Closes the underlying client of the connection.
+ pub fn deinit(self: tcp.Connection) void {
+ self.client.deinit();
+ }
+};
+
+/// Possible domains that a TCP client/listener may operate over.
+pub const Domain = extern enum(u16) {
+ ip = os.AF_INET,
+ ipv6 = os.AF_INET6,
+};
+
+/// A TCP client.
+pub const Client = struct {
+ socket: Socket,
+
+ /// Opens a new client.
+ pub fn init(domain: tcp.Domain, flags: u32) !Client {
+ return Client{
+ .socket = try Socket.init(
+ @enumToInt(domain),
+ os.SOCK_STREAM | flags,
+ os.IPPROTO_TCP,
+ ),
+ };
+ }
+
+ /// Enclose a TCP client over an existing socket.
+ pub fn from(socket: Socket) Client {
+ return Client{ .socket = socket };
+ }
+
+ /// Closes the client.
+ pub fn deinit(self: Client) void {
+ self.socket.deinit();
+ }
+
+ /// Shutdown either the read side, write side, or all sides of the client's underlying socket.
+ pub fn shutdown(self: Client, how: os.ShutdownHow) !void {
+ return self.socket.shutdown(how);
+ }
+
+ /// Have the client attempt to the connect to an address.
+ pub fn connect(self: Client, address: ip.Address) !void {
+ return self.socket.connect(address.into());
+ }
+
+ /// Read data from the socket into the buffer provided. It returns the
+ /// number of bytes read into the buffer provided.
+ pub fn read(self: Client, buf: []u8) !usize {
+ return self.socket.read(buf);
+ }
+
+ /// Read data from the socket into the buffer provided with a set of flags
+ /// specified. It returns the number of bytes read into the buffer provided.
+ pub fn recv(self: Client, buf: []u8, flags: u32) !usize {
+ return self.socket.recv(buf, flags);
+ }
+
+ /// Write a buffer of data provided to the socket. It returns the number
+ /// of bytes that are written to the socket.
+ pub fn write(self: Client, buf: []const u8) !usize {
+ return self.socket.write(buf);
+ }
+
+ /// Writes multiple I/O vectors to the socket. It returns the number
+ /// of bytes that are written to the socket.
+ pub fn writev(self: Client, buffers: []const os.iovec_const) !usize {
+ return self.socket.writev(buffers);
+ }
+
+ /// Write a buffer of data provided to the socket with a set of flags specified.
+ /// It returns the number of bytes that are written to the socket.
+ pub fn send(self: Client, buf: []const u8, flags: u32) !usize {
+ return self.socket.send(buf, flags);
+ }
+
+ /// Writes multiple I/O vectors with a prepended message header to the socket
+ /// with a set of flags specified. It returns the number of bytes that are
+ /// written to the socket.
+ pub fn sendmsg(self: Client, msg: os.msghdr_const, flags: u32) !usize {
+ return self.socket.sendmsg(msg, flags);
+ }
+
+ /// Query and return the latest cached error on the client's underlying socket.
+ pub fn getError(self: Client) !void {
+ return self.socket.getError();
+ }
+
+ /// Query the read buffer size of the client's underlying socket.
+ pub fn getReadBufferSize(self: Client) !u32 {
+ return self.socket.getReadBufferSize();
+ }
+
+ /// Query the write buffer size of the client's underlying socket.
+ pub fn getWriteBufferSize(self: Client) !u32 {
+ return self.socket.getWriteBufferSize();
+ }
+
+ /// Query the address that the client's socket is locally bounded to.
+ pub fn getLocalAddress(self: Client) !ip.Address {
+ return ip.Address.from(try self.socket.getLocalAddress());
+ }
+
+ /// Disable Nagle's algorithm on a TCP socket. It returns `error.UnsupportedSocketOption` if
+ /// the host does not support sockets disabling Nagle's algorithm.
+ pub fn setNoDelay(self: Client, enabled: bool) !void {
+ if (comptime @hasDecl(os, "TCP_NODELAY")) {
+ const bytes = mem.asBytes(&@as(usize, @boolToInt(enabled)));
+ return os.setsockopt(self.socket.fd, os.IPPROTO_TCP, os.TCP_NODELAY, bytes);
+ }
+ return error.UnsupportedSocketOption;
+ }
+
+ /// Set the write buffer size of the socket.
+ pub fn setWriteBufferSize(self: Client, size: u32) !void {
+ return self.socket.setWriteBufferSize(size);
+ }
+
+ /// Set the read buffer size of the socket.
+ pub fn setReadBufferSize(self: Client, size: u32) !void {
+ return self.socket.setReadBufferSize(size);
+ }
+
+ /// Set a timeout on the socket that is to occur if no messages are successfully written
+ /// to its bound destination after a specified number of milliseconds. A subsequent write
+ /// to the socket will thereafter return `error.WouldBlock` should the timeout be exceeded.
+ pub fn setWriteTimeout(self: Client, milliseconds: usize) !void {
+ return self.socket.setWriteTimeout(milliseconds);
+ }
+
+ /// Set a timeout on the socket that is to occur if no messages are successfully read
+ /// from its bound destination after a specified number of milliseconds. A subsequent
+ /// read from the socket will thereafter return `error.WouldBlock` should the timeout be
+ /// exceeded.
+ pub fn setReadTimeout(self: Client, milliseconds: usize) !void {
+ return self.socket.setReadTimeout(milliseconds);
+ }
+};
+
+/// A TCP listener.
+pub const Listener = struct {
+ socket: Socket,
+
+ /// Opens a new listener.
+ pub fn init(domain: tcp.Domain, flags: u32) !Listener {
+ return Listener{
+ .socket = try Socket.init(
+ @enumToInt(domain),
+ os.SOCK_STREAM | flags,
+ os.IPPROTO_TCP,
+ ),
+ };
+ }
+
+ /// Closes the listener.
+ pub fn deinit(self: Listener) void {
+ self.socket.deinit();
+ }
+
+ /// Shuts down the underlying listener's socket. The next subsequent call, or
+ /// a current pending call to accept() after shutdown is called will return
+ /// an error.
+ pub fn shutdown(self: Listener) !void {
+ return self.socket.shutdown(.recv);
+ }
+
+ /// Binds the listener's socket to an address.
+ pub fn bind(self: Listener, address: ip.Address) !void {
+ return self.socket.bind(address.into());
+ }
+
+ /// Start listening for incoming connections.
+ pub fn listen(self: Listener, max_backlog_size: u31) !void {
+ return self.socket.listen(max_backlog_size);
+ }
+
+ /// Accept a pending incoming connection queued to the kernel backlog
+ /// of the listener's socket.
+ pub fn accept(self: Listener, flags: u32) !tcp.Connection {
+ return tcp.Connection.from(try self.socket.accept(flags));
+ }
+
+ /// Query and return the latest cached error on the listener's underlying socket.
+ pub fn getError(self: Client) !void {
+ return self.socket.getError();
+ }
+
+ /// Query the address that the listener's socket is locally bounded to.
+ pub fn getLocalAddress(self: Listener) !ip.Address {
+ return ip.Address.from(try self.socket.getLocalAddress());
+ }
+
+ /// Allow multiple sockets on the same host to listen on the same address. It returns `error.UnsupportedSocketOption` if
+ /// the host does not support sockets listening the same address.
+ pub fn setReuseAddress(self: Listener, enabled: bool) !void {
+ return self.socket.setReuseAddress(enabled);
+ }
+
+ /// Allow multiple sockets on the same host to listen on the same port. It returns `error.UnsupportedSocketOption` if
+ /// the host does not supports sockets listening on the same port.
+ pub fn setReusePort(self: Listener, enabled: bool) !void {
+ return self.socket.setReusePort(enabled);
+ }
+
+ /// Enables TCP Fast Open (RFC 7413) on a TCP socket. It returns `error.UnsupportedSocketOption` if the host does not
+ /// support TCP Fast Open.
+ pub fn setFastOpen(self: Listener, enabled: bool) !void {
+ if (comptime @hasDecl(os, "TCP_FASTOPEN")) {
+ return os.setsockopt(self.socket.fd, os.IPPROTO_TCP, os.TCP_FASTOPEN, mem.asBytes(&@as(usize, @boolToInt(enabled))));
+ }
+ return error.UnsupportedSocketOption;
+ }
+
+ /// Enables TCP Quick ACK on a TCP socket to immediately send rather than delay ACKs when necessary. It returns
+ /// `error.UnsupportedSocketOption` if the host does not support TCP Quick ACK.
+ pub fn setQuickACK(self: Listener, enabled: bool) !void {
+ if (comptime @hasDecl(os, "TCP_QUICKACK")) {
+ return os.setsockopt(self.socket.fd, os.IPPROTO_TCP, os.TCP_QUICKACK, mem.asBytes(&@as(usize, @boolToInt(enabled))));
+ }
+ return error.UnsupportedSocketOption;
+ }
+
+ /// Set a timeout on the listener that is to occur if no new incoming connections come in
+ /// after a specified number of milliseconds. A subsequent accept call to the listener
+ /// will thereafter return `error.WouldBlock` should the timeout be exceeded.
+ pub fn setAcceptTimeout(self: Listener, milliseconds: usize) !void {
+ return self.socket.setReadTimeout(milliseconds);
+ }
+};
+
+test "tcp: create client/listener pair" {
+ if (builtin.os.tag == .wasi) return error.SkipZigTest;
+
+ const listener = try tcp.Listener.init(.ip, os.SOCK_CLOEXEC);
+ defer listener.deinit();
+
+ try listener.bind(ip.Address.initIPv4(IPv4.unspecified, 0));
+ try listener.listen(128);
+
+ var binded_address = try listener.getLocalAddress();
+ switch (binded_address) {
+ .ipv4 => |*ipv4| ipv4.host = IPv4.localhost,
+ .ipv6 => |*ipv6| ipv6.host = IPv6.localhost,
+ }
+
+ const client = try tcp.Client.init(.ip, os.SOCK_CLOEXEC);
+ defer client.deinit();
+
+ try client.connect(binded_address);
+
+ const conn = try listener.accept(os.SOCK_CLOEXEC);
+ defer conn.deinit();
+}
+
+test "tcp/client: set read timeout of 1 millisecond on blocking client" {
+ if (builtin.os.tag == .wasi) return error.SkipZigTest;
+
+ const listener = try tcp.Listener.init(.ip, os.SOCK_CLOEXEC);
+ defer listener.deinit();
+
+ try listener.bind(ip.Address.initIPv4(IPv4.unspecified, 0));
+ try listener.listen(128);
+
+ var binded_address = try listener.getLocalAddress();
+ switch (binded_address) {
+ .ipv4 => |*ipv4| ipv4.host = IPv4.localhost,
+ .ipv6 => |*ipv6| ipv6.host = IPv6.localhost,
+ }
+
+ const client = try tcp.Client.init(.ip, os.SOCK_CLOEXEC);
+ defer client.deinit();
+
+ try client.connect(binded_address);
+ try client.setReadTimeout(1);
+
+ const conn = try listener.accept(os.SOCK_CLOEXEC);
+ defer conn.deinit();
+
+ var buf: [1]u8 = undefined;
+ testing.expectError(error.WouldBlock, client.read(&buf));
+}
+
+test "tcp/listener: bind to unspecified ipv4 address" {
+ if (builtin.os.tag == .wasi) return error.SkipZigTest;
+
+ const listener = try tcp.Listener.init(.ip, os.SOCK_CLOEXEC);
+ defer listener.deinit();
+
+ try listener.bind(ip.Address.initIPv4(IPv4.unspecified, 0));
+ try listener.listen(128);
+
+ const address = try listener.getLocalAddress();
+ testing.expect(address == .ipv4);
+}
+
+test "tcp/listener: bind to unspecified ipv6 address" {
+ if (builtin.os.tag == .wasi) return error.SkipZigTest;
+
+ const listener = try tcp.Listener.init(.ipv6, os.SOCK_CLOEXEC);
+ defer listener.deinit();
+
+ try listener.bind(ip.Address.initIPv6(IPv6.unspecified, 0));
+ try listener.listen(128);
+
+ const address = try listener.getLocalAddress();
+ testing.expect(address == .ipv6);
+}
diff --git a/zig/lib/std/x/os/Socket.zig b/zig/lib/std/x/os/Socket.zig
new file mode 100644
index 0000000000..3656899aea
--- /dev/null
+++ b/zig/lib/std/x/os/Socket.zig
@@ -0,0 +1,295 @@
+// SPDX-License-Identifier: MIT
+// Copyright (c) 2015-2021 Zig Contributors
+// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
+// The MIT license requires this copyright notice to be included in all copies
+// and substantial portions of the software.
+
+const std = @import("../../std.zig");
+const net = @import("net.zig");
+
+const os = std.os;
+const fmt = std.fmt;
+const mem = std.mem;
+const time = std.time;
+
+/// A generic socket abstraction.
+const Socket = @This();
+
+/// A socket-address pair.
+pub const Connection = struct {
+ socket: Socket,
+ address: Socket.Address,
+
+ /// Enclose a socket and address into a socket-address pair.
+ pub fn from(socket: Socket, address: Socket.Address) Socket.Connection {
+ return .{ .socket = socket, .address = address };
+ }
+};
+
+/// A generic socket address abstraction. It is safe to directly access and modify
+/// the fields of a `Socket.Address`.
+pub const Address = union(enum) {
+ ipv4: net.IPv4.Address,
+ ipv6: net.IPv6.Address,
+
+ /// Instantiate a new address with a IPv4 host and port.
+ pub fn initIPv4(host: net.IPv4, port: u16) Socket.Address {
+ return .{ .ipv4 = .{ .host = host, .port = port } };
+ }
+
+ /// Instantiate a new address with a IPv6 host and port.
+ pub fn initIPv6(host: net.IPv6, port: u16) Socket.Address {
+ return .{ .ipv6 = .{ .host = host, .port = port } };
+ }
+
+ /// Parses a `sockaddr` into a generic socket address.
+ pub fn fromNative(address: *align(4) const os.sockaddr) Socket.Address {
+ switch (address.family) {
+ os.AF_INET => {
+ const info = @ptrCast(*const os.sockaddr_in, address);
+ const host = net.IPv4{ .octets = @bitCast([4]u8, info.addr) };
+ const port = mem.bigToNative(u16, info.port);
+ return Socket.Address.initIPv4(host, port);
+ },
+ os.AF_INET6 => {
+ const info = @ptrCast(*const os.sockaddr_in6, address);
+ const host = net.IPv6{ .octets = info.addr, .scope_id = info.scope_id };
+ const port = mem.bigToNative(u16, info.port);
+ return Socket.Address.initIPv6(host, port);
+ },
+ else => unreachable,
+ }
+ }
+
+ /// Encodes a generic socket address into an extern union that may be reliably
+ /// casted into a `sockaddr` which may be passed into socket syscalls.
+ pub fn toNative(self: Socket.Address) extern union {
+ ipv4: os.sockaddr_in,
+ ipv6: os.sockaddr_in6,
+ } {
+ return switch (self) {
+ .ipv4 => |address| .{
+ .ipv4 = .{
+ .addr = @bitCast(u32, address.host.octets),
+ .port = mem.nativeToBig(u16, address.port),
+ },
+ },
+ .ipv6 => |address| .{
+ .ipv6 = .{
+ .addr = address.host.octets,
+ .port = mem.nativeToBig(u16, address.port),
+ .scope_id = address.host.scope_id,
+ .flowinfo = 0,
+ },
+ },
+ };
+ }
+
+ /// Returns the number of bytes that make up the `sockaddr` equivalent to the address.
+ pub fn getNativeSize(self: Socket.Address) u32 {
+ return switch (self) {
+ .ipv4 => @sizeOf(os.sockaddr_in),
+ .ipv6 => @sizeOf(os.sockaddr_in6),
+ };
+ }
+
+ /// Implements the `std.fmt.format` API.
+ pub fn format(
+ self: Socket.Address,
+ comptime layout: []const u8,
+ opts: fmt.FormatOptions,
+ writer: anytype,
+ ) !void {
+ switch (self) {
+ .ipv4 => |address| try fmt.format(writer, "{}:{}", .{ address.host, address.port }),
+ .ipv6 => |address| try fmt.format(writer, "{}:{}", .{ address.host, address.port }),
+ }
+ }
+};
+
+/// The underlying handle of a socket.
+fd: os.socket_t,
+
+/// Open a new socket.
+pub fn init(domain: u32, socket_type: u32, protocol: u32) !Socket {
+ return Socket{ .fd = try os.socket(domain, socket_type, protocol) };
+}
+
+/// Enclose a socket abstraction over an existing socket file descriptor.
+pub fn from(fd: os.socket_t) Socket {
+ return Socket{ .fd = fd };
+}
+
+/// Closes the socket.
+pub fn deinit(self: Socket) void {
+ os.closeSocket(self.fd);
+}
+
+/// Shutdown either the read side, write side, or all side of the socket.
+pub fn shutdown(self: Socket, how: os.ShutdownHow) !void {
+ return os.shutdown(self.fd, how);
+}
+
+/// Binds the socket to an address.
+pub fn bind(self: Socket, address: Socket.Address) !void {
+ return os.bind(self.fd, @ptrCast(*const os.sockaddr, &address.toNative()), address.getNativeSize());
+}
+
+/// Start listening for incoming connections on the socket.
+pub fn listen(self: Socket, max_backlog_size: u31) !void {
+ return os.listen(self.fd, max_backlog_size);
+}
+
+/// Have the socket attempt to the connect to an address.
+pub fn connect(self: Socket, address: Socket.Address) !void {
+ return os.connect(self.fd, @ptrCast(*const os.sockaddr, &address.toNative()), address.getNativeSize());
+}
+
+/// Accept a pending incoming connection queued to the kernel backlog
+/// of the socket.
+pub fn accept(self: Socket, flags: u32) !Socket.Connection {
+ var address: os.sockaddr = undefined;
+ var address_len: u32 = @sizeOf(os.sockaddr);
+
+ const socket = Socket{ .fd = try os.accept(self.fd, &address, &address_len, flags) };
+ const socket_address = Socket.Address.fromNative(@alignCast(4, &address));
+
+ return Socket.Connection.from(socket, socket_address);
+}
+
+/// Read data from the socket into the buffer provided. It returns the
+/// number of bytes read into the buffer provided.
+pub fn read(self: Socket, buf: []u8) !usize {
+ return os.read(self.fd, buf);
+}
+
+/// Read data from the socket into the buffer provided with a set of flags
+/// specified. It returns the number of bytes read into the buffer provided.
+pub fn recv(self: Socket, buf: []u8, flags: u32) !usize {
+ return os.recv(self.fd, buf, flags);
+}
+
+/// Write a buffer of data provided to the socket. It returns the number
+/// of bytes that are written to the socket.
+pub fn write(self: Socket, buf: []const u8) !usize {
+ return os.write(self.fd, buf);
+}
+
+/// Writes multiple I/O vectors to the socket. It returns the number
+/// of bytes that are written to the socket.
+pub fn writev(self: Socket, buffers: []const os.iovec_const) !usize {
+ return os.writev(self.fd, buffers);
+}
+
+/// Write a buffer of data provided to the socket with a set of flags specified.
+/// It returns the number of bytes that are written to the socket.
+pub fn send(self: Socket, buf: []const u8, flags: u32) !usize {
+ return os.send(self.fd, buf, flags);
+}
+
+/// Writes multiple I/O vectors with a prepended message header to the socket
+/// with a set of flags specified. It returns the number of bytes that are
+/// written to the socket.
+pub fn sendmsg(self: Socket, msg: os.msghdr_const, flags: u32) !usize {
+ return os.sendmsg(self.fd, msg, flags);
+}
+
+/// Query the address that the socket is locally bounded to.
+pub fn getLocalAddress(self: Socket) !Socket.Address {
+ var address: os.sockaddr = undefined;
+ var address_len: u32 = @sizeOf(os.sockaddr);
+ try os.getsockname(self.fd, &address, &address_len);
+ return Socket.Address.fromNative(@alignCast(4, &address));
+}
+
+/// Query and return the latest cached error on the socket.
+pub fn getError(self: Socket) !void {
+ return os.getsockoptError(self.fd);
+}
+
+/// Query the read buffer size of the socket.
+pub fn getReadBufferSize(self: Socket) !u32 {
+ var value: u32 = undefined;
+ var value_len: u32 = @sizeOf(u32);
+
+ const rc = os.system.getsockopt(self.fd, os.SOL_SOCKET, os.SO_RCVBUF, mem.asBytes(&value), &value_len);
+ return switch (os.errno(rc)) {
+ 0 => value,
+ os.EBADF => error.BadFileDescriptor,
+ os.EFAULT => error.InvalidAddressSpace,
+ os.EINVAL => error.InvalidSocketOption,
+ os.ENOPROTOOPT => error.UnknownSocketOption,
+ os.ENOTSOCK => error.NotASocket,
+ else => |err| os.unexpectedErrno(err),
+ };
+}
+
+/// Query the write buffer size of the socket.
+pub fn getWriteBufferSize(self: Socket) !u32 {
+ var value: u32 = undefined;
+ var value_len: u32 = @sizeOf(u32);
+
+ const rc = os.system.getsockopt(self.fd, os.SOL_SOCKET, os.SO_SNDBUF, mem.asBytes(&value), &value_len);
+ return switch (os.errno(rc)) {
+ 0 => value,
+ os.EBADF => error.BadFileDescriptor,
+ os.EFAULT => error.InvalidAddressSpace,
+ os.EINVAL => error.InvalidSocketOption,
+ os.ENOPROTOOPT => error.UnknownSocketOption,
+ os.ENOTSOCK => error.NotASocket,
+ else => |err| os.unexpectedErrno(err),
+ };
+}
+
+/// Allow multiple sockets on the same host to listen on the same address. It returns `error.UnsupportedSocketOption` if
+/// the host does not support sockets listening the same address.
+pub fn setReuseAddress(self: Socket, enabled: bool) !void {
+ if (comptime @hasDecl(os, "SO_REUSEADDR")) {
+ return os.setsockopt(self.fd, os.SOL_SOCKET, os.SO_REUSEADDR, mem.asBytes(&@as(usize, @boolToInt(enabled))));
+ }
+ return error.UnsupportedSocketOption;
+}
+
+/// Allow multiple sockets on the same host to listen on the same port. It returns `error.UnsupportedSocketOption` if
+/// the host does not supports sockets listening on the same port.
+pub fn setReusePort(self: Socket, enabled: bool) !void {
+ if (comptime @hasDecl(os, "SO_REUSEPORT")) {
+ return os.setsockopt(self.fd, os.SOL_SOCKET, os.SO_REUSEPORT, mem.asBytes(&@as(usize, @boolToInt(enabled))));
+ }
+ return error.UnsupportedSocketOption;
+}
+
+/// Set the write buffer size of the socket.
+pub fn setWriteBufferSize(self: Socket, size: u32) !void {
+ return os.setsockopt(self.fd, os.SOL_SOCKET, os.SO_SNDBUF, mem.asBytes(&size));
+}
+
+/// Set the read buffer size of the socket.
+pub fn setReadBufferSize(self: Socket, size: u32) !void {
+ return os.setsockopt(self.fd, os.SOL_SOCKET, os.SO_RCVBUF, mem.asBytes(&size));
+}
+
+/// Set a timeout on the socket that is to occur if no messages are successfully written
+/// to its bound destination after a specified number of milliseconds. A subsequent write
+/// to the socket will thereafter return `error.WouldBlock` should the timeout be exceeded.
+pub fn setWriteTimeout(self: Socket, milliseconds: usize) !void {
+ const timeout = os.timeval{
+ .tv_sec = @intCast(i32, milliseconds / time.ms_per_s),
+ .tv_usec = @intCast(i32, (milliseconds % time.ms_per_s) * time.us_per_ms),
+ };
+
+ return os.setsockopt(self.fd, os.SOL_SOCKET, os.SO_SNDTIMEO, mem.asBytes(&timeout));
+}
+
+/// Set a timeout on the socket that is to occur if no messages are successfully read
+/// from its bound destination after a specified number of milliseconds. A subsequent
+/// read from the socket will thereafter return `error.WouldBlock` should the timeout be
+/// exceeded.
+pub fn setReadTimeout(self: Socket, milliseconds: usize) !void {
+ const timeout = os.timeval{
+ .tv_sec = @intCast(i32, milliseconds / time.ms_per_s),
+ .tv_usec = @intCast(i32, (milliseconds % time.ms_per_s) * time.us_per_ms),
+ };
+
+ return os.setsockopt(self.fd, os.SOL_SOCKET, os.SO_RCVTIMEO, mem.asBytes(&timeout));
+}
diff --git a/zig/lib/std/x/os/net.zig b/zig/lib/std/x/os/net.zig
new file mode 100644
index 0000000000..a8d9f095d3
--- /dev/null
+++ b/zig/lib/std/x/os/net.zig
@@ -0,0 +1,567 @@
+// SPDX-License-Identifier: MIT
+// Copyright (c) 2015-2021 Zig Contributors
+// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
+// The MIT license requires this copyright notice to be included in all copies
+// and substantial portions of the software.
+
+const std = @import("../../std.zig");
+
+const os = std.os;
+const fmt = std.fmt;
+const mem = std.mem;
+const math = std.math;
+const builtin = std.builtin;
+const testing = std.testing;
+
+/// Resolves a network interface name into a scope/zone ID. It returns
+/// an error if either resolution fails, or if the interface name is
+/// too long.
+pub fn resolveScopeID(name: []const u8) !u32 {
+ if (comptime @hasDecl(os, "IFNAMESIZE")) {
+ if (name.len >= os.IFNAMESIZE - 1) return error.NameTooLong;
+
+ const fd = try os.socket(os.AF_UNIX, os.SOCK_DGRAM, 0);
+ defer os.closeSocket(fd);
+
+ var f: os.ifreq = undefined;
+ mem.copy(u8, &f.ifrn.name, name);
+ f.ifrn.name[name.len] = 0;
+
+ try os.ioctl_SIOCGIFINDEX(fd, &f);
+
+ return @bitCast(u32, f.ifru.ivalue);
+ }
+ return error.Unsupported;
+}
+
+/// An IPv4 address comprised of 4 bytes.
+pub const IPv4 = extern struct {
+ /// A IPv4 host-port pair.
+ pub const Address = extern struct {
+ host: IPv4,
+ port: u16,
+ };
+
+ /// Octets of a IPv4 address designating the local host.
+ pub const localhost_octets = [_]u8{ 127, 0, 0, 1 };
+
+ /// The IPv4 address of the local host.
+ pub const localhost: IPv4 = .{ .octets = localhost_octets };
+
+ /// Octets of an unspecified IPv4 address.
+ pub const unspecified_octets = [_]u8{0} ** 4;
+
+ /// An unspecified IPv4 address.
+ pub const unspecified: IPv4 = .{ .octets = unspecified_octets };
+
+ /// Octets of a broadcast IPv4 address.
+ pub const broadcast_octets = [_]u8{255} ** 4;
+
+ /// An IPv4 broadcast address.
+ pub const broadcast: IPv4 = .{ .octets = broadcast_octets };
+
+ /// The prefix octet pattern of a link-local IPv4 address.
+ pub const link_local_prefix = [_]u8{ 169, 254 };
+
+ /// The prefix octet patterns of IPv4 addresses intended for
+ /// documentation.
+ pub const documentation_prefixes = [_][]const u8{
+ &[_]u8{ 192, 0, 2 },
+ &[_]u8{ 198, 51, 100 },
+ &[_]u8{ 203, 0, 113 },
+ };
+
+ octets: [4]u8,
+
+ /// Returns whether or not the two addresses are equal to, less than, or
+ /// greater than each other.
+ pub fn cmp(self: IPv4, other: IPv4) math.Order {
+ return mem.order(u8, &self.octets, &other.octets);
+ }
+
+ /// Returns true if both addresses are semantically equivalent.
+ pub fn eql(self: IPv4, other: IPv4) bool {
+ return mem.eql(u8, &self.octets, &other.octets);
+ }
+
+ /// Returns true if the address is a loopback address.
+ pub fn isLoopback(self: IPv4) bool {
+ return self.octets[0] == 127;
+ }
+
+ /// Returns true if the address is an unspecified IPv4 address.
+ pub fn isUnspecified(self: IPv4) bool {
+ return mem.eql(u8, &self.octets, &unspecified_octets);
+ }
+
+ /// Returns true if the address is a private IPv4 address.
+ pub fn isPrivate(self: IPv4) bool {
+ return self.octets[0] == 10 or
+ (self.octets[0] == 172 and self.octets[1] >= 16 and self.octets[1] <= 31) or
+ (self.octets[0] == 192 and self.octets[1] == 168);
+ }
+
+ /// Returns true if the address is a link-local IPv4 address.
+ pub fn isLinkLocal(self: IPv4) bool {
+ return mem.startsWith(u8, &self.octets, &link_local_prefix);
+ }
+
+ /// Returns true if the address is a multicast IPv4 address.
+ pub fn isMulticast(self: IPv4) bool {
+ return self.octets[0] >= 224 and self.octets[0] <= 239;
+ }
+
+ /// Returns true if the address is a IPv4 broadcast address.
+ pub fn isBroadcast(self: IPv4) bool {
+ return mem.eql(u8, &self.octets, &broadcast_octets);
+ }
+
+ /// Returns true if the address is in a range designated for documentation. Refer
+ /// to IETF RFC 5737 for more details.
+ pub fn isDocumentation(self: IPv4) bool {
+ inline for (documentation_prefixes) |prefix| {
+ if (mem.startsWith(u8, &self.octets, prefix)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /// Implements the `std.fmt.format` API.
+ pub fn format(
+ self: IPv4,
+ comptime layout: []const u8,
+ opts: fmt.FormatOptions,
+ writer: anytype,
+ ) !void {
+ if (comptime layout.len != 0 and layout[0] != 's') {
+ @compileError("Unsupported format specifier for IPv4 type '" ++ layout ++ "'.");
+ }
+
+ try fmt.format(writer, "{}.{}.{}.{}", .{
+ self.octets[0],
+ self.octets[1],
+ self.octets[2],
+ self.octets[3],
+ });
+ }
+
+ /// Set of possible errors that may encountered when parsing an IPv4
+ /// address.
+ pub const ParseError = error{
+ UnexpectedEndOfOctet,
+ TooManyOctets,
+ OctetOverflow,
+ UnexpectedToken,
+ IncompleteAddress,
+ };
+
+ /// Parses an arbitrary IPv4 address.
+ pub fn parse(buf: []const u8) ParseError!IPv4 {
+ var octets: [4]u8 = undefined;
+ var octet: u8 = 0;
+
+ var index: u8 = 0;
+ var saw_any_digits: bool = false;
+
+ for (buf) |c| {
+ switch (c) {
+ '.' => {
+ if (!saw_any_digits) return error.UnexpectedEndOfOctet;
+ if (index == 3) return error.TooManyOctets;
+ octets[index] = octet;
+ index += 1;
+ octet = 0;
+ saw_any_digits = false;
+ },
+ '0'...'9' => {
+ saw_any_digits = true;
+ octet = math.mul(u8, octet, 10) catch return error.OctetOverflow;
+ octet = math.add(u8, octet, c - '0') catch return error.OctetOverflow;
+ },
+ else => return error.UnexpectedToken,
+ }
+ }
+
+ if (index == 3 and saw_any_digits) {
+ octets[index] = octet;
+ return IPv4{ .octets = octets };
+ }
+
+ return error.IncompleteAddress;
+ }
+
+ /// Maps the address to its IPv6 equivalent. In most cases, you would
+ /// want to map the address to its IPv6 equivalent rather than directly
+ /// re-interpreting the address.
+ pub fn mapToIPv6(self: IPv4) IPv6 {
+ var octets: [16]u8 = undefined;
+ mem.copy(u8, octets[0..12], &IPv6.v4_mapped_prefix);
+ mem.copy(u8, octets[12..], &self.octets);
+ return IPv6{ .octets = octets, .scope_id = IPv6.no_scope_id };
+ }
+
+ /// Directly re-interprets the address to its IPv6 equivalent. In most
+ /// cases, you would want to map the address to its IPv6 equivalent rather
+ /// than directly re-interpreting the address.
+ pub fn toIPv6(self: IPv4) IPv6 {
+ var octets: [16]u8 = undefined;
+ mem.set(u8, octets[0..12], 0);
+ mem.copy(u8, octets[12..], &self.octets);
+ return IPv6{ .octets = octets, .scope_id = IPv6.no_scope_id };
+ }
+};
+
+/// An IPv6 address comprised of 16 bytes for an address, and 4 bytes
+/// for a scope ID; cumulatively summing to 20 bytes in total.
+pub const IPv6 = extern struct {
+ /// A IPv6 host-port pair.
+ pub const Address = extern struct {
+ host: IPv6,
+ port: u16,
+ };
+
+ /// Octets of a IPv6 address designating the local host.
+ pub const localhost_octets = [_]u8{0} ** 15 ++ [_]u8{0x01};
+
+ /// The IPv6 address of the local host.
+ pub const localhost: IPv6 = .{
+ .octets = localhost_octets,
+ .scope_id = no_scope_id,
+ };
+
+ /// Octets of an unspecified IPv6 address.
+ pub const unspecified_octets = [_]u8{0} ** 16;
+
+ /// An unspecified IPv6 address.
+ pub const unspecified: IPv6 = .{
+ .octets = unspecified_octets,
+ .scope_id = no_scope_id,
+ };
+
+ /// The prefix of a IPv6 address that is mapped to a IPv4 address.
+ pub const v4_mapped_prefix = [_]u8{0} ** 10 ++ [_]u8{0xFF} ** 2;
+
+ /// A marker value used to designate an IPv6 address with no
+ /// associated scope ID.
+ pub const no_scope_id = math.maxInt(u32);
+
+ octets: [16]u8,
+ scope_id: u32,
+
+ /// Returns whether or not the two addresses are equal to, less than, or
+ /// greater than each other.
+ pub fn cmp(self: IPv6, other: IPv6) math.Order {
+ return switch (mem.order(u8, self.octets, other.octets)) {
+ .eq => math.order(self.scope_id, other.scope_id),
+ else => |order| order,
+ };
+ }
+
+ /// Returns true if both addresses are semantically equivalent.
+ pub fn eql(self: IPv6, other: IPv6) bool {
+ return self.scope_id == other.scope_id and mem.eql(u8, &self.octets, &other.octets);
+ }
+
+ /// Returns true if the address is an unspecified IPv6 address.
+ pub fn isUnspecified(self: IPv6) bool {
+ return mem.eql(u8, &self.octets, &unspecified_octets);
+ }
+
+ /// Returns true if the address is a loopback address.
+ pub fn isLoopback(self: IPv6) bool {
+ return mem.eql(u8, self.octets[0..3], &[_]u8{ 0, 0, 0 }) and
+ mem.eql(u8, self.octets[12..], &[_]u8{ 0, 0, 0, 1 });
+ }
+
+ /// Returns true if the address maps to an IPv4 address.
+ pub fn mapsToIPv4(self: IPv6) bool {
+ return mem.startsWith(u8, &self.octets, &v4_mapped_prefix);
+ }
+
+ /// Returns an IPv4 address representative of the address should
+ /// it the address be mapped to an IPv4 address. It returns null
+ /// otherwise.
+ pub fn toIPv4(self: IPv6) ?IPv4 {
+ if (!self.mapsToIPv4()) return null;
+ return IPv4{ .octets = self.octets[12..][0..4].* };
+ }
+
+ /// Returns true if the address is a multicast IPv6 address.
+ pub fn isMulticast(self: IPv6) bool {
+ return self.octets[0] == 0xFF;
+ }
+
+ /// Returns true if the address is a unicast link local IPv6 address.
+ pub fn isLinkLocal(self: IPv6) bool {
+ return self.octets[0] == 0xFE and self.octets[1] & 0xC0 == 0x80;
+ }
+
+ /// Returns true if the address is a deprecated unicast site local
+ /// IPv6 address. Refer to IETF RFC 3879 for more details as to
+ /// why they are deprecated.
+ pub fn isSiteLocal(self: IPv6) bool {
+ return self.octets[0] == 0xFE and self.octets[1] & 0xC0 == 0xC0;
+ }
+
+ /// IPv6 multicast address scopes.
+ pub const Scope = enum(u8) {
+ interface = 1,
+ link = 2,
+ realm = 3,
+ admin = 4,
+ site = 5,
+ organization = 8,
+ global = 14,
+ unknown = 0xFF,
+ };
+
+ /// Returns the multicast scope of the address.
+ pub fn scope(self: IPv6) Scope {
+ if (!self.isMulticast()) return .unknown;
+
+ return switch (self.octets[0] & 0x0F) {
+ 1 => .interface,
+ 2 => .link,
+ 3 => .realm,
+ 4 => .admin,
+ 5 => .site,
+ 8 => .organization,
+ 14 => .global,
+ else => .unknown,
+ };
+ }
+
+ /// Implements the `std.fmt.format` API. Specifying 'x' or 's' formats the
+ /// address lower-cased octets, while specifying 'X' or 'S' formats the
+ /// address using upper-cased ASCII octets.
+ ///
+ /// The default specifier is 'x'.
+ pub fn format(
+ self: IPv6,
+ comptime layout: []const u8,
+ opts: fmt.FormatOptions,
+ writer: anytype,
+ ) !void {
+ comptime const specifier = &[_]u8{if (layout.len == 0) 'x' else switch (layout[0]) {
+ 'x', 'X' => |specifier| specifier,
+ 's' => 'x',
+ 'S' => 'X',
+ else => @compileError("Unsupported format specifier for IPv6 type '" ++ layout ++ "'."),
+ }};
+
+ if (mem.startsWith(u8, &self.octets, &v4_mapped_prefix)) {
+ return fmt.format(writer, "::{" ++ specifier ++ "}{" ++ specifier ++ "}:{}.{}.{}.{}", .{
+ 0xFF,
+ 0xFF,
+ self.octets[12],
+ self.octets[13],
+ self.octets[14],
+ self.octets[15],
+ });
+ }
+
+ const zero_span = span: {
+ var i: usize = 0;
+ while (i < self.octets.len) : (i += 2) {
+ if (self.octets[i] == 0 and self.octets[i + 1] == 0) break;
+ } else break :span .{ .from = 0, .to = 0 };
+
+ const from = i;
+
+ while (i < self.octets.len) : (i += 2) {
+ if (self.octets[i] != 0 or self.octets[i + 1] != 0) break;
+ }
+
+ break :span .{ .from = from, .to = i };
+ };
+
+ var i: usize = 0;
+ while (i != 16) : (i += 2) {
+ if (zero_span.from != zero_span.to and i == zero_span.from) {
+ try writer.writeAll("::");
+ } else if (i >= zero_span.from and i < zero_span.to) {} else {
+ if (i != 0 and i != zero_span.to) try writer.writeAll(":");
+
+ const val = @as(u16, self.octets[i]) << 8 | self.octets[i + 1];
+ try fmt.formatIntValue(val, specifier, .{}, writer);
+ }
+ }
+
+ if (self.scope_id != no_scope_id and self.scope_id != 0) {
+ try fmt.format(writer, "%{d}", .{self.scope_id});
+ }
+ }
+
+ /// Set of possible errors that may encountered when parsing an IPv6
+ /// address.
+ pub const ParseError = error{
+ MalformedV4Mapping,
+ BadScopeID,
+ } || IPv4.ParseError;
+
+ /// Parses an arbitrary IPv6 address, including link-local addresses.
+ pub fn parse(buf: []const u8) ParseError!IPv6 {
+ if (mem.lastIndexOfScalar(u8, buf, '%')) |index| {
+ const ip_slice = buf[0..index];
+ const scope_id_slice = buf[index + 1 ..];
+
+ if (scope_id_slice.len == 0) return error.BadScopeID;
+
+ const scope_id: u32 = switch (scope_id_slice[0]) {
+ '0'...'9' => fmt.parseInt(u32, scope_id_slice, 10),
+ else => resolveScopeID(scope_id_slice),
+ } catch return error.BadScopeID;
+
+ return parseWithScopeID(ip_slice, scope_id);
+ }
+
+ return parseWithScopeID(buf, no_scope_id);
+ }
+
+ /// Parses an IPv6 address with a pre-specified scope ID. Presumes
+ /// that the address is not a link-local address.
+ pub fn parseWithScopeID(buf: []const u8, scope_id: u32) ParseError!IPv6 {
+ var octets: [16]u8 = undefined;
+ var octet: u16 = 0;
+ var tail: [16]u8 = undefined;
+
+ var out: []u8 = &octets;
+ var index: u8 = 0;
+
+ var saw_any_digits: bool = false;
+ var abbrv: bool = false;
+
+ for (buf) |c, i| {
+ switch (c) {
+ ':' => {
+ if (!saw_any_digits) {
+ if (abbrv) return error.UnexpectedToken;
+ if (i != 0) abbrv = true;
+ mem.set(u8, out[index..], 0);
+ out = &tail;
+ index = 0;
+ continue;
+ }
+ if (index == 14) return error.TooManyOctets;
+
+ out[index] = @truncate(u8, octet >> 8);
+ index += 1;
+ out[index] = @truncate(u8, octet);
+ index += 1;
+
+ octet = 0;
+ saw_any_digits = false;
+ },
+ '.' => {
+ if (!abbrv or out[0] != 0xFF and out[1] != 0xFF) {
+ return error.MalformedV4Mapping;
+ }
+ const start_index = mem.lastIndexOfScalar(u8, buf[0..i], ':').? + 1;
+ const v4 = try IPv4.parse(buf[start_index..]);
+ octets[10] = 0xFF;
+ octets[11] = 0xFF;
+ mem.copy(u8, octets[12..], &v4.octets);
+
+ return IPv6{ .octets = octets, .scope_id = scope_id };
+ },
+ else => {
+ saw_any_digits = true;
+ const digit = fmt.charToDigit(c, 16) catch return error.UnexpectedToken;
+ octet = math.mul(u16, octet, 16) catch return error.OctetOverflow;
+ octet = math.add(u16, octet, digit) catch return error.OctetOverflow;
+ },
+ }
+ }
+
+ if (!saw_any_digits and !abbrv) {
+ return error.IncompleteAddress;
+ }
+
+ if (index == 14) {
+ out[14] = @truncate(u8, octet >> 8);
+ out[15] = @truncate(u8, octet);
+ } else {
+ out[index] = @truncate(u8, octet >> 8);
+ index += 1;
+ out[index] = @truncate(u8, octet);
+ index += 1;
+ mem.copy(u8, octets[16 - index ..], out[0..index]);
+ }
+
+ return IPv6{ .octets = octets, .scope_id = scope_id };
+ }
+};
+
+test {
+ testing.refAllDecls(@This());
+}
+
+test "ip: convert to and from ipv6" {
+ try testing.expectFmt("::7f00:1", "{}", .{IPv4.localhost.toIPv6()});
+ testing.expect(!IPv4.localhost.toIPv6().mapsToIPv4());
+
+ try testing.expectFmt("::ffff:127.0.0.1", "{}", .{IPv4.localhost.mapToIPv6()});
+ testing.expect(IPv4.localhost.mapToIPv6().mapsToIPv4());
+
+ testing.expect(IPv4.localhost.toIPv6().toIPv4() == null);
+ try testing.expectFmt("127.0.0.1", "{}", .{IPv4.localhost.mapToIPv6().toIPv4()});
+}
+
+test "ipv4: parse & format" {
+ const cases = [_][]const u8{
+ "0.0.0.0",
+ "255.255.255.255",
+ "1.2.3.4",
+ "123.255.0.91",
+ "127.0.0.1",
+ };
+
+ for (cases) |case| {
+ try testing.expectFmt(case, "{}", .{try IPv4.parse(case)});
+ }
+}
+
+test "ipv6: parse & format" {
+ const inputs = [_][]const u8{
+ "FF01:0:0:0:0:0:0:FB",
+ "FF01::Fb",
+ "::1",
+ "::",
+ "2001:db8::",
+ "::1234:5678",
+ "2001:db8::1234:5678",
+ "::ffff:123.5.123.5",
+ };
+
+ const outputs = [_][]const u8{
+ "ff01::fb",
+ "ff01::fb",
+ "::1",
+ "::",
+ "2001:db8::",
+ "::1234:5678",
+ "2001:db8::1234:5678",
+ "::ffff:123.5.123.5",
+ };
+
+ for (inputs) |input, i| {
+ try testing.expectFmt(outputs[i], "{}", .{try IPv6.parse(input)});
+ }
+}
+
+test "ipv6: parse & format addresses with scope ids" {
+ if (!@hasDecl(os, "IFNAMESIZE")) return error.SkipZigTest;
+
+ const inputs = [_][]const u8{
+ "FF01::FB%lo",
+ };
+
+ const outputs = [_][]const u8{
+ "ff01::fb%1",
+ };
+
+ for (inputs) |input, i| {
+ try testing.expectFmt(outputs[i], "{}", .{try IPv6.parse(input)});
+ }
+}
diff --git a/zig/lib/std/zig/ast.zig b/zig/lib/std/zig/ast.zig
index a0e7754896..cab7749691 100644
--- a/zig/lib/std/zig/ast.zig
+++ b/zig/lib/std/zig/ast.zig
@@ -1979,20 +1979,26 @@ pub const Tree = struct {
// asm ("foo" :: [_] "" (y) : "a", "b");
const last_input = result.inputs[result.inputs.len - 1];
const rparen = tree.lastToken(last_input);
- if (token_tags[rparen + 1] == .colon and
- token_tags[rparen + 2] == .string_literal)
+ var i = rparen + 1;
+ // Allow a (useless) comma right after the closing parenthesis.
+ if (token_tags[i] == .comma) i += 1;
+ if (token_tags[i] == .colon and
+ token_tags[i + 1] == .string_literal)
{
- result.first_clobber = rparen + 2;
+ result.first_clobber = i + 1;
}
} else {
// asm ("foo" : [_] "" (x) :: "a", "b");
const last_output = result.outputs[result.outputs.len - 1];
const rparen = tree.lastToken(last_output);
- if (token_tags[rparen + 1] == .colon and
- token_tags[rparen + 2] == .colon and
- token_tags[rparen + 3] == .string_literal)
+ var i = rparen + 1;
+ // Allow a (useless) comma right after the closing parenthesis.
+ if (token_tags[i] == .comma) i += 1;
+ if (token_tags[i] == .colon and
+ token_tags[i + 1] == .colon and
+ token_tags[i + 2] == .string_literal)
{
- result.first_clobber = rparen + 3;
+ result.first_clobber = i + 2;
}
}
diff --git a/zig/lib/std/zig/parse.zig b/zig/lib/std/zig/parse.zig
index 029d8ede50..d6880ad273 100644
--- a/zig/lib/std/zig/parse.zig
+++ b/zig/lib/std/zig/parse.zig
@@ -852,7 +852,7 @@ const Parser = struct {
/// <- KEYWORD_comptime? VarDecl
/// / KEYWORD_comptime BlockExprStatement
/// / KEYWORD_nosuspend BlockExprStatement
- /// / KEYWORD_suspend (SEMICOLON / BlockExprStatement)
+ /// / KEYWORD_suspend BlockExprStatement
/// / KEYWORD_defer BlockExprStatement
/// / KEYWORD_errdefer Payload? BlockExprStatement
/// / IfStatement
@@ -892,6 +892,7 @@ const Parser = struct {
},
.keyword_suspend => {
const token = p.nextToken();
+ // TODO remove this special case when 0.9.0 is released.
const block_expr: Node.Index = if (p.eatToken(.semicolon) != null)
0
else
diff --git a/zig/lib/std/zig/parser_test.zig b/zig/lib/std/zig/parser_test.zig
index 1bed86f42d..fe119a5d27 100644
--- a/zig/lib/std/zig/parser_test.zig
+++ b/zig/lib/std/zig/parser_test.zig
@@ -4,6 +4,38 @@
// The MIT license requires this copyright notice to be included in all copies
// and substantial portions of the software.
+test "zig fmt: preserves clobbers in inline asm with stray comma" {
+ try testTransform(
+ \\fn foo() void {
+ \\ asm volatile (""
+ \\ : [_] "" (-> type),
+ \\ :
+ \\ : "clobber"
+ \\ );
+ \\ asm volatile (""
+ \\ :
+ \\ : [_] "" (type),
+ \\ : "clobber"
+ \\ );
+ \\}
+ \\
+ ,
+ \\fn foo() void {
+ \\ asm volatile (""
+ \\ : [_] "" (-> type)
+ \\ :
+ \\ : "clobber"
+ \\ );
+ \\ asm volatile (""
+ \\ :
+ \\ : [_] "" (type)
+ \\ : "clobber"
+ \\ );
+ \\}
+ \\
+ );
+}
+
test "zig fmt: respect line breaks in struct field value declaration" {
try testCanonical(
\\const Foo = struct {
@@ -40,6 +72,21 @@ test "zig fmt: rewrite inline functions as callconv(.Inline)" {
);
}
+// TODO Remove this after zig 0.9.0 is released.
+test "zig fmt: rewrite suspend without block expression" {
+ try testTransform(
+ \\fn foo() void {
+ \\ suspend;
+ \\}
+ \\
+ ,
+ \\fn foo() void {
+ \\ suspend {}
+ \\}
+ \\
+ );
+}
+
test "zig fmt: simple top level comptime block" {
try testCanonical(
\\// line comment
@@ -1315,6 +1362,27 @@ test "zig fmt: 'zig fmt: (off|on)' works in the middle of code" {
);
}
+test "zig fmt: 'zig fmt: on' indentation is unchanged" {
+ try testCanonical(
+ \\fn initOptionsAndLayouts(output: *Output, context: *Context) !void {
+ \\ // zig fmt: off
+ \\ try output.main_amount.init(output, "main_amount"); errdefer optput.main_amount.deinit();
+ \\ try output.main_factor.init(output, "main_factor"); errdefer optput.main_factor.deinit();
+ \\ try output.view_padding.init(output, "view_padding"); errdefer optput.view_padding.deinit();
+ \\ try output.outer_padding.init(output, "outer_padding"); errdefer optput.outer_padding.deinit();
+ \\ // zig fmt: on
+ \\
+ \\ // zig fmt: off
+ \\ try output.top.init(output, .top); errdefer optput.top.deinit();
+ \\ try output.right.init(output, .right); errdefer optput.right.deinit();
+ \\ try output.bottom.init(output, .bottom); errdefer optput.bottom.deinit();
+ \\ try output.left.init(output, .left); errdefer optput.left.deinit();
+ \\ // zig fmt: on
+ \\}
+ \\
+ );
+}
+
test "zig fmt: pointer of unknown length" {
try testCanonical(
\\fn foo(ptr: [*]u8) void {}
@@ -3644,9 +3712,9 @@ test "zig fmt: async functions" {
\\fn simpleAsyncFn() void {
\\ const a = async a.b();
\\ x += 1;
- \\ suspend;
+ \\ suspend {}
\\ x += 1;
- \\ suspend;
+ \\ suspend {}
\\ const p: anyframe->void = async simpleAsyncFn() catch unreachable;
\\ await p;
\\}
@@ -5001,6 +5069,21 @@ test "recovery: invalid comptime" {
});
}
+test "recovery: missing block after suspend" {
+ // TODO Enable this after zig 0.9.0 is released.
+ if (true) return error.SkipZigTest;
+
+ try testError(
+ \\fn foo() void {
+ \\ suspend;
+ \\ nosuspend;
+ \\}
+ , &[_]Error{
+ .expected_block_or_expr,
+ .expected_block_or_expr,
+ });
+}
+
test "recovery: missing block after for/while loops" {
try testError(
\\test "" { while (foo) }
@@ -5144,7 +5227,7 @@ fn testError(source: []const u8, expected_errors: []const Error) !void {
var tree = try std.zig.parse(std.testing.allocator, source);
defer tree.deinit(std.testing.allocator);
- std.testing.expect(tree.errors.len == expected_errors.len);
+ std.testing.expectEqual(expected_errors.len, tree.errors.len);
for (expected_errors) |expected, i| {
std.testing.expectEqual(expected, tree.errors[i].tag);
}
diff --git a/zig/lib/std/zig/render.zig b/zig/lib/std/zig/render.zig
index 71d5e51bb9..a762b78728 100644
--- a/zig/lib/std/zig/render.zig
+++ b/zig/lib/std/zig/render.zig
@@ -269,7 +269,12 @@ fn renderExpression(gpa: *Allocator, ais: *Ais, tree: ast.Tree, node: ast.Node.I
try renderToken(ais, tree, suspend_token, .space);
return renderExpression(gpa, ais, tree, body, space);
} else {
- return renderToken(ais, tree, suspend_token, space);
+ // TODO remove this special case when 0.9.0 is released.
+ assert(space == .semicolon);
+ try renderToken(ais, tree, suspend_token, .space);
+ try ais.writer().writeAll("{}");
+ try ais.insertNewline();
+ return;
}
},
@@ -2311,9 +2316,9 @@ fn renderComments(ais: *Ais, tree: ast.Tree, start: usize, end: usize) Error!boo
// to the underlying writer, fixing up invaild whitespace.
const disabled_source = tree.source[ais.disabled_offset.?..comment_start];
try writeFixingWhitespace(ais.underlying_writer, disabled_source);
- ais.disabled_offset = null;
// Write with the canonical single space.
- try ais.writer().writeAll("// zig fmt: on\n");
+ try ais.underlying_writer.writeAll("// zig fmt: on\n");
+ ais.disabled_offset = null;
} else if (ais.disabled_offset == null and mem.eql(u8, comment_content, "zig fmt: off")) {
// Write with the canonical single space.
try ais.writer().writeAll("// zig fmt: off\n");
diff --git a/zig/lib/std/zig/system.zig b/zig/lib/std/zig/system.zig
index 485bd479bf..42099c6efe 100644
--- a/zig/lib/std/zig/system.zig
+++ b/zig/lib/std/zig/system.zig
@@ -14,6 +14,7 @@ const process = std.process;
const Target = std.Target;
const CrossTarget = std.zig.CrossTarget;
const macos = @import("system/macos.zig");
+const linux = @import("system/linux.zig");
pub const windows = @import("system/windows.zig");
pub const getSDKPath = macos.getSDKPath;
@@ -911,15 +912,19 @@ pub const NativeTargetInfo = struct {
.x86_64, .i386 => {
return @import("system/x86.zig").detectNativeCpuAndFeatures(cpu_arch, os, cross_target);
},
- else => {
- // This architecture does not have CPU model & feature detection yet.
- // See https://github.com/ziglang/zig/issues/4591
- return null;
- },
+ else => {},
}
+
+ // This architecture does not have CPU model & feature detection yet.
+ // See https://github.com/ziglang/zig/issues/4591
+ if (std.Target.current.os.tag != .linux)
+ return null;
+
+ return linux.detectNativeCpuAndFeatures();
}
};
test {
_ = @import("system/macos.zig");
+ _ = @import("system/linux.zig");
}
diff --git a/zig/lib/std/zig/system/linux.zig b/zig/lib/std/zig/system/linux.zig
new file mode 100644
index 0000000000..c2cf7b009d
--- /dev/null
+++ b/zig/lib/std/zig/system/linux.zig
@@ -0,0 +1,468 @@
+const std = @import("std");
+const mem = std.mem;
+const io = std.io;
+const fs = std.fs;
+const fmt = std.fmt;
+const testing = std.testing;
+
+const Target = std.Target;
+const CrossTarget = std.zig.CrossTarget;
+
+const assert = std.debug.assert;
+
+const SparcCpuinfoImpl = struct {
+ model: ?*const Target.Cpu.Model = null,
+ is_64bit: bool = false,
+
+ const cpu_names = .{
+ .{ "SuperSparc", &Target.sparc.cpu.supersparc },
+ .{ "HyperSparc", &Target.sparc.cpu.hypersparc },
+ .{ "SpitFire", &Target.sparc.cpu.ultrasparc },
+ .{ "BlackBird", &Target.sparc.cpu.ultrasparc },
+ .{ "Sabre", &Target.sparc.cpu.ultrasparc },
+ .{ "Hummingbird", &Target.sparc.cpu.ultrasparc },
+ .{ "Cheetah", &Target.sparc.cpu.ultrasparc3 },
+ .{ "Jalapeno", &Target.sparc.cpu.ultrasparc3 },
+ .{ "Jaguar", &Target.sparc.cpu.ultrasparc3 },
+ .{ "Panther", &Target.sparc.cpu.ultrasparc3 },
+ .{ "Serrano", &Target.sparc.cpu.ultrasparc3 },
+ .{ "UltraSparc T1", &Target.sparc.cpu.niagara },
+ .{ "UltraSparc T2", &Target.sparc.cpu.niagara2 },
+ .{ "UltraSparc T3", &Target.sparc.cpu.niagara3 },
+ .{ "UltraSparc T4", &Target.sparc.cpu.niagara4 },
+ .{ "UltraSparc T5", &Target.sparc.cpu.niagara4 },
+ .{ "LEON", &Target.sparc.cpu.leon3 },
+ };
+
+ fn line_hook(self: *SparcCpuinfoImpl, key: []const u8, value: []const u8) !bool {
+ if (mem.eql(u8, key, "cpu")) {
+ inline for (cpu_names) |pair| {
+ if (mem.indexOfPos(u8, value, 0, pair[0]) != null) {
+ self.model = pair[1];
+ break;
+ }
+ }
+ } else if (mem.eql(u8, key, "type")) {
+ self.is_64bit = mem.eql(u8, value, "sun4u") or mem.eql(u8, value, "sun4v");
+ }
+
+ return true;
+ }
+
+ fn finalize(self: *const SparcCpuinfoImpl, arch: Target.Cpu.Arch) ?Target.Cpu {
+ // At the moment we only support 64bit SPARC systems.
+ assert(self.is_64bit);
+
+ const model = self.model orelse return null;
+ return Target.Cpu{
+ .arch = arch,
+ .model = model,
+ .features = model.features,
+ };
+ }
+};
+
+const SparcCpuinfoParser = CpuinfoParser(SparcCpuinfoImpl);
+
+test "cpuinfo: SPARC" {
+ try testParser(SparcCpuinfoParser, .sparcv9, &Target.sparc.cpu.niagara2,
+ \\cpu : UltraSparc T2 (Niagara2)
+ \\fpu : UltraSparc T2 integrated FPU
+ \\pmu : niagara2
+ \\type : sun4v
+ );
+}
+
+const PowerpcCpuinfoImpl = struct {
+ model: ?*const Target.Cpu.Model = null,
+
+ const cpu_names = .{
+ .{ "604e", &Target.powerpc.cpu.@"604e" },
+ .{ "604", &Target.powerpc.cpu.@"604" },
+ .{ "7400", &Target.powerpc.cpu.@"7400" },
+ .{ "7410", &Target.powerpc.cpu.@"7400" },
+ .{ "7447", &Target.powerpc.cpu.@"7400" },
+ .{ "7455", &Target.powerpc.cpu.@"7450" },
+ .{ "G4", &Target.powerpc.cpu.@"g4" },
+ .{ "POWER4", &Target.powerpc.cpu.@"970" },
+ .{ "PPC970FX", &Target.powerpc.cpu.@"970" },
+ .{ "PPC970MP", &Target.powerpc.cpu.@"970" },
+ .{ "G5", &Target.powerpc.cpu.@"g5" },
+ .{ "POWER5", &Target.powerpc.cpu.@"g5" },
+ .{ "A2", &Target.powerpc.cpu.@"a2" },
+ .{ "POWER6", &Target.powerpc.cpu.@"pwr6" },
+ .{ "POWER7", &Target.powerpc.cpu.@"pwr7" },
+ .{ "POWER8", &Target.powerpc.cpu.@"pwr8" },
+ .{ "POWER8E", &Target.powerpc.cpu.@"pwr8" },
+ .{ "POWER8NVL", &Target.powerpc.cpu.@"pwr8" },
+ .{ "POWER9", &Target.powerpc.cpu.@"pwr9" },
+ .{ "POWER10", &Target.powerpc.cpu.@"pwr10" },
+ };
+
+ fn line_hook(self: *PowerpcCpuinfoImpl, key: []const u8, value: []const u8) !bool {
+ if (mem.eql(u8, key, "cpu")) {
+ // The model name is often followed by a comma or space and extra
+ // info.
+ inline for (cpu_names) |pair| {
+ const end_index = mem.indexOfAny(u8, value, ", ") orelse value.len;
+ if (mem.eql(u8, value[0..end_index], pair[0])) {
+ self.model = pair[1];
+ break;
+ }
+ }
+
+ // Stop the detection once we've seen the first core.
+ return false;
+ }
+
+ return true;
+ }
+
+ fn finalize(self: *const PowerpcCpuinfoImpl, arch: Target.Cpu.Arch) ?Target.Cpu {
+ const model = self.model orelse return null;
+ return Target.Cpu{
+ .arch = arch,
+ .model = model,
+ .features = model.features,
+ };
+ }
+};
+
+const PowerpcCpuinfoParser = CpuinfoParser(PowerpcCpuinfoImpl);
+
+test "cpuinfo: PowerPC" {
+ try testParser(PowerpcCpuinfoParser, .powerpc, &Target.powerpc.cpu.@"970",
+ \\processor : 0
+ \\cpu : PPC970MP, altivec supported
+ \\clock : 1250.000000MHz
+ \\revision : 1.1 (pvr 0044 0101)
+ );
+ try testParser(PowerpcCpuinfoParser, .powerpc64le, &Target.powerpc.cpu.pwr8,
+ \\processor : 0
+ \\cpu : POWER8 (raw), altivec supported
+ \\clock : 2926.000000MHz
+ \\revision : 2.0 (pvr 004d 0200)
+ );
+}
+
+const ArmCpuinfoImpl = struct {
+ cores: [4]CoreInfo = undefined,
+ core_no: usize = 0,
+ have_fields: usize = 0,
+
+ const CoreInfo = struct {
+ architecture: u8 = 0,
+ implementer: u8 = 0,
+ variant: u8 = 0,
+ part: u16 = 0,
+ is_really_v6: bool = false,
+ };
+
+ const cpu_models = struct {
+ // Shorthands to simplify the tables below.
+ const A32 = Target.arm.cpu;
+ const A64 = Target.aarch64.cpu;
+
+ const E = struct {
+ part: u16,
+ variant: ?u8 = null, // null if matches any variant
+ m32: ?*const Target.Cpu.Model = null,
+ m64: ?*const Target.Cpu.Model = null,
+ };
+
+ // implementer = 0x41
+ const ARM = [_]E{
+ E{ .part = 0x926, .m32 = &A32.arm926ej_s, .m64 = null },
+ E{ .part = 0xb02, .m32 = &A32.mpcore, .m64 = null },
+ E{ .part = 0xb36, .m32 = &A32.arm1136j_s, .m64 = null },
+ E{ .part = 0xb56, .m32 = &A32.arm1156t2_s, .m64 = null },
+ E{ .part = 0xb76, .m32 = &A32.arm1176jz_s, .m64 = null },
+ E{ .part = 0xc05, .m32 = &A32.cortex_a5, .m64 = null },
+ E{ .part = 0xc07, .m32 = &A32.cortex_a7, .m64 = null },
+ E{ .part = 0xc08, .m32 = &A32.cortex_a8, .m64 = null },
+ E{ .part = 0xc09, .m32 = &A32.cortex_a9, .m64 = null },
+ E{ .part = 0xc0d, .m32 = &A32.cortex_a17, .m64 = null },
+ E{ .part = 0xc0f, .m32 = &A32.cortex_a15, .m64 = null },
+ E{ .part = 0xc0e, .m32 = &A32.cortex_a17, .m64 = null },
+ E{ .part = 0xc14, .m32 = &A32.cortex_r4, .m64 = null },
+ E{ .part = 0xc15, .m32 = &A32.cortex_r5, .m64 = null },
+ E{ .part = 0xc17, .m32 = &A32.cortex_r7, .m64 = null },
+ E{ .part = 0xc18, .m32 = &A32.cortex_r8, .m64 = null },
+ E{ .part = 0xc20, .m32 = &A32.cortex_m0, .m64 = null },
+ E{ .part = 0xc21, .m32 = &A32.cortex_m1, .m64 = null },
+ E{ .part = 0xc23, .m32 = &A32.cortex_m3, .m64 = null },
+ E{ .part = 0xc24, .m32 = &A32.cortex_m4, .m64 = null },
+ E{ .part = 0xc27, .m32 = &A32.cortex_m7, .m64 = null },
+ E{ .part = 0xc60, .m32 = &A32.cortex_m0plus, .m64 = null },
+ E{ .part = 0xd01, .m32 = &A32.cortex_a32, .m64 = null },
+ E{ .part = 0xd03, .m32 = &A32.cortex_a53, .m64 = &A64.cortex_a53 },
+ E{ .part = 0xd04, .m32 = &A32.cortex_a35, .m64 = &A64.cortex_a35 },
+ E{ .part = 0xd05, .m32 = &A32.cortex_a55, .m64 = &A64.cortex_a55 },
+ E{ .part = 0xd07, .m32 = &A32.cortex_a57, .m64 = &A64.cortex_a57 },
+ E{ .part = 0xd08, .m32 = &A32.cortex_a72, .m64 = &A64.cortex_a72 },
+ E{ .part = 0xd09, .m32 = &A32.cortex_a73, .m64 = &A64.cortex_a73 },
+ E{ .part = 0xd0a, .m32 = &A32.cortex_a75, .m64 = &A64.cortex_a75 },
+ E{ .part = 0xd0b, .m32 = &A32.cortex_a76, .m64 = &A64.cortex_a76 },
+ E{ .part = 0xd0c, .m32 = &A32.neoverse_n1, .m64 = null },
+ E{ .part = 0xd0d, .m32 = &A32.cortex_a77, .m64 = &A64.cortex_a77 },
+ E{ .part = 0xd13, .m32 = &A32.cortex_r52, .m64 = null },
+ E{ .part = 0xd20, .m32 = &A32.cortex_m23, .m64 = null },
+ E{ .part = 0xd21, .m32 = &A32.cortex_m33, .m64 = null },
+ E{ .part = 0xd41, .m32 = &A32.cortex_a78, .m64 = &A64.cortex_a78 },
+ E{ .part = 0xd4b, .m32 = &A32.cortex_a78c, .m64 = &A64.cortex_a78c },
+ E{ .part = 0xd44, .m32 = &A32.cortex_x1, .m64 = &A64.cortex_x1 },
+ E{ .part = 0xd02, .m64 = &A64.cortex_a34 },
+ E{ .part = 0xd06, .m64 = &A64.cortex_a65 },
+ E{ .part = 0xd43, .m64 = &A64.cortex_a65ae },
+ };
+ // implementer = 0x42
+ const Broadcom = [_]E{
+ E{ .part = 0x516, .m64 = &A64.thunderx2t99 },
+ };
+ // implementer = 0x43
+ const Cavium = [_]E{
+ E{ .part = 0x0a0, .m64 = &A64.thunderx },
+ E{ .part = 0x0a2, .m64 = &A64.thunderxt81 },
+ E{ .part = 0x0a3, .m64 = &A64.thunderxt83 },
+ E{ .part = 0x0a1, .m64 = &A64.thunderxt88 },
+ E{ .part = 0x0af, .m64 = &A64.thunderx2t99 },
+ };
+ // implementer = 0x46
+ const Fujitsu = [_]E{
+ E{ .part = 0x001, .m64 = &A64.a64fx },
+ };
+ // implementer = 0x48
+ const HiSilicon = [_]E{
+ E{ .part = 0xd01, .m64 = &A64.tsv110 },
+ };
+ // implementer = 0x4e
+ const Nvidia = [_]E{
+ E{ .part = 0x004, .m64 = &A64.carmel },
+ };
+ // implementer = 0x50
+ const Ampere = [_]E{
+ E{ .part = 0x000, .variant = 3, .m64 = &A64.emag },
+ E{ .part = 0x000, .m64 = &A64.xgene1 },
+ };
+ // implementer = 0x51
+ const Qualcomm = [_]E{
+ E{ .part = 0x06f, .m32 = &A32.krait },
+ E{ .part = 0x201, .m64 = &A64.kryo, .m32 = &A64.kryo },
+ E{ .part = 0x205, .m64 = &A64.kryo, .m32 = &A64.kryo },
+ E{ .part = 0x211, .m64 = &A64.kryo, .m32 = &A64.kryo },
+ E{ .part = 0x800, .m64 = &A64.cortex_a73, .m32 = &A64.cortex_a73 },
+ E{ .part = 0x801, .m64 = &A64.cortex_a73, .m32 = &A64.cortex_a73 },
+ E{ .part = 0x802, .m64 = &A64.cortex_a75, .m32 = &A64.cortex_a75 },
+ E{ .part = 0x803, .m64 = &A64.cortex_a75, .m32 = &A64.cortex_a75 },
+ E{ .part = 0x804, .m64 = &A64.cortex_a76, .m32 = &A64.cortex_a76 },
+ E{ .part = 0x805, .m64 = &A64.cortex_a76, .m32 = &A64.cortex_a76 },
+ E{ .part = 0xc00, .m64 = &A64.falkor },
+ E{ .part = 0xc01, .m64 = &A64.saphira },
+ };
+
+ fn isKnown(core: CoreInfo, is_64bit: bool) ?*const Target.Cpu.Model {
+ const models = switch (core.implementer) {
+ 0x41 => &ARM,
+ 0x42 => &Broadcom,
+ 0x43 => &Cavium,
+ 0x46 => &Fujitsu,
+ 0x48 => &HiSilicon,
+ 0x50 => &Ampere,
+ 0x51 => &Qualcomm,
+ else => return null,
+ };
+
+ for (models) |model| {
+ if (model.part == core.part and
+ (model.variant == null or model.variant.? == core.variant))
+ return if (is_64bit) model.m64 else model.m32;
+ }
+
+ return null;
+ }
+ };
+
+ fn addOne(self: *ArmCpuinfoImpl) void {
+ if (self.have_fields == 4 and self.core_no < self.cores.len) {
+ if (self.core_no > 0) {
+ // Deduplicate the core info.
+ for (self.cores[0..self.core_no]) |it| {
+ if (std.meta.eql(it, self.cores[self.core_no]))
+ return;
+ }
+ }
+ self.core_no += 1;
+ }
+ }
+
+ fn line_hook(self: *ArmCpuinfoImpl, key: []const u8, value: []const u8) !bool {
+ const info = &self.cores[self.core_no];
+
+ if (mem.eql(u8, key, "processor")) {
+ // Handle both old-style and new-style cpuinfo formats.
+ // The former prints a sequence of "processor: N" lines for each
+ // core and then the info for the core that's executing this code(!)
+ // while the latter prints the infos for each core right after the
+ // "processor" key.
+ self.have_fields = 0;
+ self.cores[self.core_no] = .{};
+ } else if (mem.eql(u8, key, "CPU implementer")) {
+ info.implementer = try fmt.parseInt(u8, value, 0);
+ self.have_fields += 1;
+ } else if (mem.eql(u8, key, "CPU architecture")) {
+ // "AArch64" on older kernels.
+ info.architecture = if (mem.startsWith(u8, value, "AArch64"))
+ 8
+ else
+ try fmt.parseInt(u8, value, 0);
+ self.have_fields += 1;
+ } else if (mem.eql(u8, key, "CPU variant")) {
+ info.variant = try fmt.parseInt(u8, value, 0);
+ self.have_fields += 1;
+ } else if (mem.eql(u8, key, "CPU part")) {
+ info.part = try fmt.parseInt(u16, value, 0);
+ self.have_fields += 1;
+ } else if (mem.eql(u8, key, "model name")) {
+ // ARMv6 cores report "CPU architecture" equal to 7.
+ if (mem.indexOf(u8, value, "(v6l)")) |_| {
+ info.is_really_v6 = true;
+ }
+ } else if (mem.eql(u8, key, "CPU revision")) {
+ // This field is always the last one for each CPU section.
+ _ = self.addOne();
+ }
+
+ return true;
+ }
+
+ fn finalize(self: *ArmCpuinfoImpl, arch: Target.Cpu.Arch) ?Target.Cpu {
+ if (self.core_no == 0) return null;
+
+ const is_64bit = switch (arch) {
+ .aarch64, .aarch64_be, .aarch64_32 => true,
+ else => false,
+ };
+
+ var known_models: [self.cores.len]?*const Target.Cpu.Model = undefined;
+ for (self.cores[0..self.core_no]) |core, i| {
+ known_models[i] = cpu_models.isKnown(core, is_64bit);
+ }
+
+ // XXX We pick the first core on big.LITTLE systems, hopefully the
+ // LITTLE one.
+ const model = known_models[0] orelse return null;
+ return Target.Cpu{
+ .arch = arch,
+ .model = model,
+ .features = model.features,
+ };
+ }
+};
+
+const ArmCpuinfoParser = CpuinfoParser(ArmCpuinfoImpl);
+
+test "cpuinfo: ARM" {
+ try testParser(ArmCpuinfoParser, .arm, &Target.arm.cpu.arm1176jz_s,
+ \\processor : 0
+ \\model name : ARMv6-compatible processor rev 7 (v6l)
+ \\BogoMIPS : 997.08
+ \\Features : half thumb fastmult vfp edsp java tls
+ \\CPU implementer : 0x41
+ \\CPU architecture: 7
+ \\CPU variant : 0x0
+ \\CPU part : 0xb76
+ \\CPU revision : 7
+ );
+ try testParser(ArmCpuinfoParser, .arm, &Target.arm.cpu.cortex_a7,
+ \\processor : 0
+ \\model name : ARMv7 Processor rev 3 (v7l)
+ \\BogoMIPS : 18.00
+ \\Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae
+ \\CPU implementer : 0x41
+ \\CPU architecture: 7
+ \\CPU variant : 0x0
+ \\CPU part : 0xc07
+ \\CPU revision : 3
+ \\
+ \\processor : 4
+ \\model name : ARMv7 Processor rev 3 (v7l)
+ \\BogoMIPS : 90.00
+ \\Features : half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae
+ \\CPU implementer : 0x41
+ \\CPU architecture: 7
+ \\CPU variant : 0x2
+ \\CPU part : 0xc0f
+ \\CPU revision : 3
+ );
+ try testParser(ArmCpuinfoParser, .aarch64, &Target.aarch64.cpu.cortex_a72,
+ \\processor : 0
+ \\BogoMIPS : 108.00
+ \\Features : fp asimd evtstrm crc32 cpuid
+ \\CPU implementer : 0x41
+ \\CPU architecture: 8
+ \\CPU variant : 0x0
+ \\CPU part : 0xd08
+ \\CPU revision : 3
+ );
+}
+
+fn testParser(
+ parser: anytype,
+ arch: Target.Cpu.Arch,
+ expected_model: *const Target.Cpu.Model,
+ input: []const u8,
+) !void {
+ var fbs = io.fixedBufferStream(input);
+ const result = try parser.parse(arch, fbs.reader());
+ testing.expectEqual(expected_model, result.?.model);
+ testing.expect(expected_model.features.eql(result.?.features));
+}
+
+// The generic implementation of a /proc/cpuinfo parser.
+// For every line it invokes the line_hook method with the key and value strings
+// as first and second parameters. Returning false from the hook function stops
+// the iteration without raising an error.
+// When all the lines have been analyzed the finalize method is called.
+fn CpuinfoParser(comptime impl: anytype) type {
+ return struct {
+ fn parse(arch: Target.Cpu.Arch, reader: anytype) anyerror!?Target.Cpu {
+ var line_buf: [1024]u8 = undefined;
+ var obj: impl = .{};
+
+ while (true) {
+ const line = (try reader.readUntilDelimiterOrEof(&line_buf, '\n')) orelse break;
+ const colon_pos = mem.indexOfScalar(u8, line, ':') orelse continue;
+ const key = mem.trimRight(u8, line[0..colon_pos], " \t");
+ const value = mem.trimLeft(u8, line[colon_pos + 1 ..], " \t");
+
+ if (!try obj.line_hook(key, value))
+ break;
+ }
+
+ return obj.finalize(arch);
+ }
+ };
+}
+
+pub fn detectNativeCpuAndFeatures() ?Target.Cpu {
+ var f = fs.openFileAbsolute("/proc/cpuinfo", .{ .intended_io_mode = .blocking }) catch |err| switch (err) {
+ else => return null,
+ };
+ defer f.close();
+
+ const current_arch = std.Target.current.cpu.arch;
+ switch (current_arch) {
+ .arm, .armeb, .thumb, .thumbeb, .aarch64, .aarch64_be, .aarch64_32 => {
+ return ArmCpuinfoParser.parse(current_arch, f.reader()) catch null;
+ },
+ .sparcv9 => {
+ return SparcCpuinfoParser.parse(current_arch, f.reader()) catch null;
+ },
+ .powerpc, .powerpcle, .powerpc64, .powerpc64le => {
+ return PowerpcCpuinfoParser.parse(current_arch, f.reader()) catch null;
+ },
+ else => {},
+ }
+
+ return null;
+}
diff --git a/zig/src/Compilation.zig b/zig/src/Compilation.zig
index 485d7690f5..58d6f41858 100644
--- a/zig/src/Compilation.zig
+++ b/zig/src/Compilation.zig
@@ -53,6 +53,9 @@ c_object_work_queue: std.fifo.LinearFifo(*CObject, .Dynamic),
/// This data is accessed by multiple threads and is protected by `mutex`.
failed_c_objects: std.AutoArrayHashMapUnmanaged(*CObject, *CObject.ErrorMsg) = .{},
+/// Miscellaneous things that can fail.
+misc_failures: std.AutoArrayHashMapUnmanaged(MiscTask, MiscError) = .{},
+
keep_source_files_loaded: bool,
use_clang: bool,
sanitize_c: bool,
@@ -229,7 +232,6 @@ pub const CObject = struct {
pub fn destroy(em: *ErrorMsg, gpa: *Allocator) void {
gpa.free(em.msg);
gpa.destroy(em);
- em.* = undefined;
}
};
@@ -256,6 +258,36 @@ pub const CObject = struct {
}
};
+pub const MiscTask = enum {
+ write_builtin_zig,
+ glibc_crt_file,
+ glibc_shared_objects,
+ musl_crt_file,
+ mingw_crt_file,
+ windows_import_lib,
+ libunwind,
+ libcxx,
+ libcxxabi,
+ libtsan,
+ compiler_rt,
+ libssp,
+ zig_libc,
+};
+
+pub const MiscError = struct {
+ /// Allocated with gpa.
+ msg: []u8,
+ children: ?AllErrors = null,
+
+ pub fn deinit(misc_err: *MiscError, gpa: *Allocator) void {
+ gpa.free(misc_err.msg);
+ if (misc_err.children) |*children| {
+ children.deinit(gpa);
+ }
+ misc_err.* = undefined;
+ }
+};
+
/// To support incremental compilation, errors are stored in various places
/// so that they can be created and destroyed appropriately. This structure
/// is used to collect all the errors from the various places into one
@@ -278,6 +310,7 @@ pub const AllErrors = struct {
},
plain: struct {
msg: []const u8,
+ notes: []Message = &.{},
},
pub fn renderToStdErr(msg: Message, ttyconf: std.debug.TTY.Config) void {
@@ -285,7 +318,7 @@ pub const AllErrors = struct {
const held = std.debug.getStderrMutex().acquire();
defer held.release();
const stderr = std.io.getStdErr();
- return msg.renderToStdErrInner(ttyconf, stderr, "error:", .Red) catch return;
+ return msg.renderToStdErrInner(ttyconf, stderr, "error:", .Red, 0) catch return;
}
fn renderToStdErrInner(
@@ -294,6 +327,7 @@ pub const AllErrors = struct {
stderr_file: std.fs.File,
kind: []const u8,
color: std.debug.TTY.Color,
+ indent: usize,
) anyerror!void {
const stderr = stderr_file.writer();
switch (msg) {
@@ -305,6 +339,7 @@ pub const AllErrors = struct {
src.column + 1,
});
ttyconf.setColor(stderr, color);
+ try stderr.writeByteNTimes(' ', indent);
try stderr.writeAll(kind);
ttyconf.setColor(stderr, .Bold);
try stderr.print(" {s}\n", .{src.msg});
@@ -318,11 +353,19 @@ pub const AllErrors = struct {
ttyconf.setColor(stderr, .Reset);
}
for (src.notes) |note| {
- try note.renderToStdErrInner(ttyconf, stderr_file, "note:", .Cyan);
+ try note.renderToStdErrInner(ttyconf, stderr_file, "note:", .Cyan, indent);
}
},
.plain => |plain| {
- try stderr.print("{s}: {s}\n", .{ kind, plain.msg });
+ ttyconf.setColor(stderr, color);
+ try stderr.writeByteNTimes(' ', indent);
+ try stderr.writeAll(kind);
+ ttyconf.setColor(stderr, .Reset);
+ try stderr.print(" {s}\n", .{plain.msg});
+ ttyconf.setColor(stderr, .Reset);
+ for (plain.notes) |note| {
+ try note.renderToStdErrInner(ttyconf, stderr_file, "error:", .Red, indent + 4);
+ }
},
}
}
@@ -380,6 +423,45 @@ pub const AllErrors = struct {
) !void {
try errors.append(.{ .plain = .{ .msg = msg } });
}
+
+ fn addPlainWithChildren(
+ arena: *std.heap.ArenaAllocator,
+ errors: *std.ArrayList(Message),
+ msg: []const u8,
+ optional_children: ?AllErrors,
+ ) !void {
+ const duped_msg = try arena.allocator.dupe(u8, msg);
+ if (optional_children) |*children| {
+ try errors.append(.{ .plain = .{
+ .msg = duped_msg,
+ .notes = try dupeList(children.list, &arena.allocator),
+ } });
+ } else {
+ try errors.append(.{ .plain = .{ .msg = duped_msg } });
+ }
+ }
+
+ fn dupeList(list: []const Message, arena: *Allocator) Allocator.Error![]Message {
+ const duped_list = try arena.alloc(Message, list.len);
+ for (list) |item, i| {
+ duped_list[i] = switch (item) {
+ .src => |src| .{ .src = .{
+ .msg = try arena.dupe(u8, src.msg),
+ .src_path = try arena.dupe(u8, src.src_path),
+ .line = src.line,
+ .column = src.column,
+ .byte_offset = src.byte_offset,
+ .source_line = if (src.source_line) |s| try arena.dupe(u8, s) else null,
+ .notes = try dupeList(src.notes, arena),
+ } },
+ .plain => |plain| .{ .plain = .{
+ .msg = try arena.dupe(u8, plain.msg),
+ .notes = try dupeList(plain.notes, arena),
+ } },
+ };
+ }
+ return duped_list;
+ }
};
pub const Directory = struct {
@@ -1357,6 +1439,8 @@ pub fn destroy(self: *Compilation) void {
}
self.failed_c_objects.deinit(gpa);
+ self.clearMiscFailures();
+
self.cache_parent.manifest_dir.close();
if (self.owned_link_dir) |*dir| dir.close();
@@ -1366,6 +1450,14 @@ pub fn destroy(self: *Compilation) void {
self.arena_state.promote(gpa).deinit();
}
+pub fn clearMiscFailures(comp: *Compilation) void {
+ for (comp.misc_failures.items()) |*entry| {
+ entry.value.deinit(comp.gpa);
+ }
+ comp.misc_failures.deinit(comp.gpa);
+ comp.misc_failures = .{};
+}
+
pub fn getTarget(self: Compilation) Target {
return self.bin_file.options.target;
}
@@ -1375,6 +1467,7 @@ pub fn update(self: *Compilation) !void {
const tracy = trace(@src());
defer tracy.end();
+ self.clearMiscFailures();
self.c_object_cache_digest_set.clearRetainingCapacity();
// For compiling C objects, we rely on the cache hash system to avoid duplicating work.
@@ -1475,7 +1568,7 @@ pub fn makeBinFileWritable(self: *Compilation) !void {
}
pub fn totalErrorCount(self: *Compilation) usize {
- var total: usize = self.failed_c_objects.items().len;
+ var total: usize = self.failed_c_objects.count() + self.misc_failures.count();
if (self.bin_file.options.module) |module| {
total += module.failed_exports.items().len +
@@ -1539,6 +1632,9 @@ pub fn getAllErrorsAlloc(self: *Compilation) !AllErrors {
},
});
}
+ for (self.misc_failures.items()) |entry| {
+ try AllErrors.addPlainWithChildren(&arena, &errors, entry.value.msg, entry.value.children);
+ }
if (self.bin_file.options.module) |module| {
for (module.failed_files.items()) |entry| {
try AllErrors.add(module, &arena, &errors, entry.value.*);
@@ -1775,89 +1871,160 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor
},
.glibc_crt_file => |crt_file| {
glibc.buildCRTFile(self, crt_file) catch |err| {
- // TODO Expose this as a normal compile error rather than crashing here.
- fatal("unable to build glibc CRT file: {s}", .{@errorName(err)});
+ // TODO Surface more error details.
+ try self.setMiscFailure(.glibc_crt_file, "unable to build glibc CRT file: {s}", .{
+ @errorName(err),
+ });
};
},
.glibc_shared_objects => {
glibc.buildSharedObjects(self) catch |err| {
- // TODO Expose this as a normal compile error rather than crashing here.
- fatal("unable to build glibc shared objects: {s}", .{@errorName(err)});
+ // TODO Surface more error details.
+ try self.setMiscFailure(
+ .glibc_shared_objects,
+ "unable to build glibc shared objects: {s}",
+ .{@errorName(err)},
+ );
};
},
.musl_crt_file => |crt_file| {
musl.buildCRTFile(self, crt_file) catch |err| {
- // TODO Expose this as a normal compile error rather than crashing here.
- fatal("unable to build musl CRT file: {s}", .{@errorName(err)});
+ // TODO Surface more error details.
+ try self.setMiscFailure(
+ .musl_crt_file,
+ "unable to build musl CRT file: {s}",
+ .{@errorName(err)},
+ );
};
},
.mingw_crt_file => |crt_file| {
mingw.buildCRTFile(self, crt_file) catch |err| {
- // TODO Expose this as a normal compile error rather than crashing here.
- fatal("unable to build mingw-w64 CRT file: {s}", .{@errorName(err)});
+ // TODO Surface more error details.
+ try self.setMiscFailure(
+ .mingw_crt_file,
+ "unable to build mingw-w64 CRT file: {s}",
+ .{@errorName(err)},
+ );
};
},
.windows_import_lib => |index| {
const link_lib = self.bin_file.options.system_libs.items()[index].key;
mingw.buildImportLib(self, link_lib) catch |err| {
- // TODO Expose this as a normal compile error rather than crashing here.
- fatal("unable to generate DLL import .lib file: {s}", .{@errorName(err)});
+ // TODO Surface more error details.
+ try self.setMiscFailure(
+ .windows_import_lib,
+ "unable to generate DLL import .lib file: {s}",
+ .{@errorName(err)},
+ );
};
},
.libunwind => {
libunwind.buildStaticLib(self) catch |err| {
- // TODO Expose this as a normal compile error rather than crashing here.
- fatal("unable to build libunwind: {s}", .{@errorName(err)});
+ // TODO Surface more error details.
+ try self.setMiscFailure(
+ .libunwind,
+ "unable to build libunwind: {s}",
+ .{@errorName(err)},
+ );
};
},
.libcxx => {
libcxx.buildLibCXX(self) catch |err| {
- // TODO Expose this as a normal compile error rather than crashing here.
- fatal("unable to build libcxx: {s}", .{@errorName(err)});
+ // TODO Surface more error details.
+ try self.setMiscFailure(
+ .libcxx,
+ "unable to build libcxx: {s}",
+ .{@errorName(err)},
+ );
};
},
.libcxxabi => {
libcxx.buildLibCXXABI(self) catch |err| {
- // TODO Expose this as a normal compile error rather than crashing here.
- fatal("unable to build libcxxabi: {s}", .{@errorName(err)});
+ // TODO Surface more error details.
+ try self.setMiscFailure(
+ .libcxxabi,
+ "unable to build libcxxabi: {s}",
+ .{@errorName(err)},
+ );
};
},
.libtsan => {
libtsan.buildTsan(self) catch |err| {
- // TODO Expose this as a normal compile error rather than crashing here.
- fatal("unable to build TSAN library: {s}", .{@errorName(err)});
+ // TODO Surface more error details.
+ try self.setMiscFailure(
+ .libtsan,
+ "unable to build TSAN library: {s}",
+ .{@errorName(err)},
+ );
};
},
.compiler_rt_lib => {
- self.buildOutputFromZig("compiler_rt.zig", .Lib, &self.compiler_rt_static_lib) catch |err| {
- // TODO Expose this as a normal compile error rather than crashing here.
- fatal("unable to build compiler_rt: {s}", .{@errorName(err)});
+ self.buildOutputFromZig(
+ "compiler_rt.zig",
+ .Lib,
+ &self.compiler_rt_static_lib,
+ .compiler_rt,
+ ) catch |err| switch (err) {
+ error.OutOfMemory => return error.OutOfMemory,
+ error.SubCompilationFailed => continue, // error reported already
+ else => try self.setMiscFailure(
+ .compiler_rt,
+ "unable to build compiler_rt: {s}",
+ .{@errorName(err)},
+ ),
};
},
.compiler_rt_obj => {
- self.buildOutputFromZig("compiler_rt.zig", .Obj, &self.compiler_rt_obj) catch |err| {
- // TODO Expose this as a normal compile error rather than crashing here.
- fatal("unable to build compiler_rt: {s}", .{@errorName(err)});
+ self.buildOutputFromZig(
+ "compiler_rt.zig",
+ .Obj,
+ &self.compiler_rt_obj,
+ .compiler_rt,
+ ) catch |err| switch (err) {
+ error.OutOfMemory => return error.OutOfMemory,
+ error.SubCompilationFailed => continue, // error reported already
+ else => try self.setMiscFailure(
+ .compiler_rt,
+ "unable to build compiler_rt: {s}",
+ .{@errorName(err)},
+ ),
};
},
.libssp => {
- self.buildOutputFromZig("ssp.zig", .Lib, &self.libssp_static_lib) catch |err| {
- // TODO Expose this as a normal compile error rather than crashing here.
- fatal("unable to build libssp: {s}", .{@errorName(err)});
+ self.buildOutputFromZig(
+ "ssp.zig",
+ .Lib,
+ &self.libssp_static_lib,
+ .libssp,
+ ) catch |err| switch (err) {
+ error.OutOfMemory => return error.OutOfMemory,
+ error.SubCompilationFailed => continue, // error reported already
+ else => try self.setMiscFailure(
+ .libssp,
+ "unable to build libssp: {s}",
+ .{@errorName(err)},
+ ),
};
},
.zig_libc => {
- self.buildOutputFromZig("c.zig", .Lib, &self.libc_static_lib) catch |err| {
- // TODO Expose this as a normal compile error rather than crashing here.
- fatal("unable to build zig's multitarget libc: {s}", .{@errorName(err)});
+ self.buildOutputFromZig(
+ "c.zig",
+ .Lib,
+ &self.libc_static_lib,
+ .zig_libc,
+ ) catch |err| switch (err) {
+ error.OutOfMemory => return error.OutOfMemory,
+ error.SubCompilationFailed => continue, // error reported already
+ else => try self.setMiscFailure(
+ .zig_libc,
+ "unable to build zig's multitarget libc: {s}",
+ .{@errorName(err)},
+ ),
};
},
.generate_builtin_zig => {
// This Job is only queued up if there is a zig module.
- self.updateBuiltinZigFile(self.bin_file.options.module.?) catch |err| {
- // TODO Expose this as a normal compile error rather than crashing here.
- fatal("unable to update builtin.zig file: {s}", .{@errorName(err)});
- };
+ try self.updateBuiltinZigFile(self.bin_file.options.module.?);
},
.stage1_module => {
if (!build_options.is_stage1)
@@ -2511,25 +2678,29 @@ pub fn addCCArgs(
try argv.append("-fPIC");
}
},
- .shared_library, .assembly, .ll, .bc, .unknown, .static_library, .object, .zig => {},
+ .shared_library, .ll, .bc, .unknown, .static_library, .object, .zig => {},
+ .assembly => {
+ // Argh, why doesn't the assembler accept the list of CPU features?!
+ // I don't see a way to do this other than hard coding everything.
+ switch (target.cpu.arch) {
+ .riscv32, .riscv64 => {
+ if (std.Target.riscv.featureSetHas(target.cpu.features, .relax)) {
+ try argv.append("-mrelax");
+ } else {
+ try argv.append("-mno-relax");
+ }
+ },
+ else => {
+ // TODO
+ },
+ }
+ if (target.cpu.model.llvm_name) |ln|
+ try argv.append(try std.fmt.allocPrint(arena, "-mcpu={s}", .{ln}));
+ },
}
if (out_dep_path) |p| {
try argv.appendSlice(&[_][]const u8{ "-MD", "-MV", "-MF", p });
}
- // Argh, why doesn't the assembler accept the list of CPU features?!
- // I don't see a way to do this other than hard coding everything.
- switch (target.cpu.arch) {
- .riscv32, .riscv64 => {
- if (std.Target.riscv.featureSetHas(target.cpu.features, .relax)) {
- try argv.append("-mrelax");
- } else {
- try argv.append("-mno-relax");
- }
- },
- else => {
- // TODO
- },
- }
if (target.os.tag == .freestanding) {
try argv.append("-ffreestanding");
@@ -2858,13 +3029,31 @@ fn wantBuildLibUnwindFromSource(comp: *Compilation) bool {
target_util.libcNeedsLibUnwind(comp.getTarget());
}
-fn updateBuiltinZigFile(comp: *Compilation, mod: *Module) !void {
+fn updateBuiltinZigFile(comp: *Compilation, mod: *Module) Allocator.Error!void {
const tracy = trace(@src());
defer tracy.end();
const source = try comp.generateBuiltinZigSource(comp.gpa);
defer comp.gpa.free(source);
- try mod.zig_cache_artifact_directory.handle.writeFile("builtin.zig", source);
+
+ mod.zig_cache_artifact_directory.handle.writeFile("builtin.zig", source) catch |err| {
+ const dir_path: []const u8 = mod.zig_cache_artifact_directory.path orelse ".";
+ try comp.setMiscFailure(.write_builtin_zig, "unable to write builtin.zig to {s}: {s}", .{
+ dir_path,
+ @errorName(err),
+ });
+ };
+}
+
+fn setMiscFailure(
+ comp: *Compilation,
+ tag: MiscTask,
+ comptime format: []const u8,
+ args: anytype,
+) Allocator.Error!void {
+ try comp.misc_failures.ensureCapacity(comp.gpa, comp.misc_failures.count() + 1);
+ const msg = try std.fmt.allocPrint(comp.gpa, format, args);
+ comp.misc_failures.putAssumeCapacityNoClobber(tag, .{ .msg = msg });
}
pub fn dump_argv(argv: []const []const u8) void {
@@ -2874,7 +3063,7 @@ pub fn dump_argv(argv: []const []const u8) void {
std.debug.print("{s}\n", .{argv[argv.len - 1]});
}
-pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) ![]u8 {
+pub fn generateBuiltinZigSource(comp: *Compilation, allocator: *Allocator) Allocator.Error![]u8 {
const tracy = trace(@src());
defer tracy.end();
@@ -3071,6 +3260,10 @@ pub fn updateSubCompilation(sub_compilation: *Compilation) !void {
try sub_compilation.update();
// Look for compilation errors in this sub_compilation
+ // TODO instead of logging these errors, handle them in the callsites
+ // of updateSubCompilation and attach them as sub-errors, properly
+ // surfacing the errors. You can see an example of this already
+ // done inside buildOutputFromZig.
var errors = try sub_compilation.getAllErrorsAlloc();
defer errors.deinit(sub_compilation.gpa);
@@ -3099,6 +3292,7 @@ fn buildOutputFromZig(
src_basename: []const u8,
output_mode: std.builtin.OutputMode,
out: *?CRTFile,
+ misc_task_tag: MiscTask,
) !void {
const tracy = trace(@src());
defer tracy.end();
@@ -3173,7 +3367,23 @@ fn buildOutputFromZig(
});
defer sub_compilation.destroy();
- try sub_compilation.updateSubCompilation();
+ try sub_compilation.update();
+ // Look for compilation errors in this sub_compilation.
+ var keep_errors = false;
+ var errors = try sub_compilation.getAllErrorsAlloc();
+ defer if (!keep_errors) errors.deinit(sub_compilation.gpa);
+
+ if (errors.list.len != 0) {
+ try comp.misc_failures.ensureCapacity(comp.gpa, comp.misc_failures.count() + 1);
+ comp.misc_failures.putAssumeCapacityNoClobber(misc_task_tag, .{
+ .msg = try std.fmt.allocPrint(comp.gpa, "sub-compilation of {s} failed", .{
+ @tagName(misc_task_tag),
+ }),
+ .children = errors,
+ });
+ keep_errors = true;
+ return error.SubCompilationFailed;
+ }
assert(out.* == null);
out.* = Compilation.CRTFile{
diff --git a/zig/src/clang.zig b/zig/src/clang.zig
index d53accbaf7..e00271968b 100644
--- a/zig/src/clang.zig
+++ b/zig/src/clang.zig
@@ -104,6 +104,16 @@ pub const APFloat = opaque {
extern fn ZigClangAPFloat_toString(*const APFloat, precision: c_uint, maxPadding: c_uint, truncateZero: bool) [*:0]const u8;
};
+pub const APFloatBaseSemantics = extern enum {
+ IEEEhalf,
+ BFloat,
+ IEEEsingle,
+ IEEEdouble,
+ x86DoubleExtended,
+ IEEEquad,
+ PPCDoubleDouble,
+};
+
pub const APInt = opaque {
pub const getLimitedValue = ZigClangAPInt_getLimitedValue;
extern fn ZigClangAPInt_getLimitedValue(*const APInt, limit: u64) u64;
@@ -455,6 +465,12 @@ pub const FileID = opaque {};
pub const FloatingLiteral = opaque {
pub const getValueAsApproximateDouble = ZigClangFloatingLiteral_getValueAsApproximateDouble;
extern fn ZigClangFloatingLiteral_getValueAsApproximateDouble(*const FloatingLiteral) f64;
+
+ pub const getBeginLoc = ZigClangIntegerLiteral_getBeginLoc;
+ extern fn ZigClangIntegerLiteral_getBeginLoc(*const FloatingLiteral) SourceLocation;
+
+ pub const getRawSemantics = ZigClangFloatingLiteral_getRawSemantics;
+ extern fn ZigClangFloatingLiteral_getRawSemantics(*const FloatingLiteral) APFloatBaseSemantics;
};
pub const ForStmt = opaque {
diff --git a/zig/src/codegen.zig b/zig/src/codegen.zig
index a345fd8058..2f83bfe6f3 100644
--- a/zig/src/codegen.zig
+++ b/zig/src/codegen.zig
@@ -449,7 +449,6 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
.rbrace_src = src_data.rbrace_src,
.source = src_data.source,
};
- defer function.register_manager.deinit(bin_file.allocator);
defer function.stack.deinit(bin_file.allocator);
defer function.exitlude_jump_relocs.deinit(bin_file.allocator);
@@ -779,8 +778,12 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
branch.inst_table.putAssumeCapacity(inst, .dead);
switch (prev_value) {
.register => |reg| {
- const canon_reg = toCanonicalReg(reg);
- self.register_manager.freeReg(canon_reg);
+ // TODO separate architectures with registers from
+ // stack-based architectures (spu_2)
+ if (callee_preserved_regs.len > 0) {
+ const canon_reg = toCanonicalReg(reg);
+ self.register_manager.freeReg(canon_reg);
+ }
},
else => {}, // TODO process stack allocation death
}
@@ -920,9 +923,12 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
const ptr_bits = arch.ptrBitWidth();
const ptr_bytes: u64 = @divExact(ptr_bits, 8);
if (abi_size <= ptr_bytes) {
- try self.register_manager.registers.ensureCapacity(self.gpa, self.register_manager.registers.count() + 1);
- if (self.register_manager.tryAllocReg(inst)) |reg| {
- return MCValue{ .register = registerAlias(reg, abi_size) };
+ // TODO separate architectures with registers from
+ // stack-based architectures (spu_2)
+ if (callee_preserved_regs.len > 0) {
+ if (self.register_manager.tryAllocReg(inst)) |reg| {
+ return MCValue{ .register = registerAlias(reg, abi_size) };
+ }
}
}
}
@@ -952,8 +958,6 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
/// `reg_owner` is the instruction that gets associated with the register in the register table.
/// This can have a side effect of spilling instructions to the stack to free up a register.
fn copyToNewRegister(self: *Self, reg_owner: *ir.Inst, mcv: MCValue) !MCValue {
- try self.register_manager.registers.ensureCapacity(self.gpa, @intCast(u32, self.register_manager.registers.count() + 1));
-
const reg = try self.register_manager.allocReg(reg_owner);
try self.genSetReg(reg_owner.src, reg_owner.ty, reg, mcv);
return MCValue{ .register = reg };
@@ -1240,14 +1244,19 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
.register => |reg| {
// If it's in the registers table, need to associate the register with the
// new instruction.
- if (self.register_manager.registers.getEntry(toCanonicalReg(reg))) |entry| {
- entry.value = inst;
+ // TODO separate architectures with registers from
+ // stack-based architectures (spu_2)
+ if (callee_preserved_regs.len > 0) {
+ if (reg.allocIndex()) |index| {
+ if (!self.register_manager.isRegFree(reg)) {
+ self.register_manager.registers[index] = inst;
+ }
+ }
+ log.debug("reusing {} => {*}", .{ reg, inst });
}
- log.debug("reusing {} => {*}", .{ reg, inst });
},
.stack_offset => |off| {
log.debug("reusing stack offset {} => {*}", .{ off, inst });
- return true;
},
else => return false,
}
@@ -1739,6 +1748,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
const arg_index = self.arg_index;
self.arg_index += 1;
+ // TODO separate architectures with registers from
+ // stack-based architectures (spu_2)
if (callee_preserved_regs.len == 0) {
return self.fail(inst.base.src, "TODO implement Register enum for {}", .{self.target.cpu.arch});
}
@@ -1770,7 +1781,6 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
switch (mcv) {
.register => |reg| {
- try self.register_manager.registers.ensureCapacity(self.gpa, self.register_manager.registers.count() + 1);
self.register_manager.getRegAssumeFree(toCanonicalReg(reg), &inst.base);
},
else => {},
@@ -2076,7 +2086,11 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
switch (mc_arg) {
.none => continue,
.register => |reg| {
- try self.register_manager.getRegWithoutTracking(reg);
+ // TODO prevent this macho if block to be generated for all archs
+ switch (arch) {
+ .x86_64, .aarch64 => try self.register_manager.getRegWithoutTracking(reg),
+ else => unreachable,
+ }
try self.genSetReg(arg.src, arg.ty, reg, arg_mcv);
},
.stack_offset => {
@@ -2398,8 +2412,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
const parent_free_registers = self.register_manager.free_registers;
var parent_stack = try self.stack.clone(self.gpa);
defer parent_stack.deinit(self.gpa);
- var parent_registers = try self.register_manager.registers.clone(self.gpa);
- defer parent_registers.deinit(self.gpa);
+ const parent_registers = self.register_manager.registers;
try self.branch_stack.append(.{});
@@ -2415,9 +2428,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
var saved_then_branch = self.branch_stack.pop();
defer saved_then_branch.deinit(self.gpa);
- self.register_manager.registers.deinit(self.gpa);
self.register_manager.registers = parent_registers;
- parent_registers = .{};
self.stack.deinit(self.gpa);
self.stack = parent_stack;
diff --git a/zig/src/codegen/riscv64.zig b/zig/src/codegen/riscv64.zig
index 96b9c58f9c..a01f38289a 100644
--- a/zig/src/codegen/riscv64.zig
+++ b/zig/src/codegen/riscv64.zig
@@ -1,5 +1,7 @@
const std = @import("std");
const DW = std.dwarf;
+const assert = std.debug.assert;
+const testing = std.testing;
// TODO: this is only tagged to facilitate the monstrosity.
// Once packed structs work make it packed.
@@ -110,7 +112,7 @@ pub const Instruction = union(enum) {
// -- less burden on callsite, bonus semantic checking
fn bType(op: u7, fn3: u3, r1: Register, r2: Register, imm: i13) Instruction {
const umm = @bitCast(u13, imm);
- if (umm % 2 != 0) @panic("Internal error: misaligned branch target");
+ assert(umm % 2 == 0); // misaligned branch target
return Instruction{
.B = .{
@@ -140,15 +142,15 @@ pub const Instruction = union(enum) {
}
fn jType(op: u7, rd: Register, imm: i21) Instruction {
- const umm = @bitcast(u21, imm);
- if (umm % 2 != 0) @panic("Internal error: misaligned jump target");
+ const umm = @bitCast(u21, imm);
+ assert(umm % 2 == 0); // misaligned jump target
return Instruction{
.J = .{
.opcode = op,
.rd = @enumToInt(rd),
.imm1_10 = @truncate(u10, umm >> 1),
- .imm11 = @truncate(u1, umm >> 1),
+ .imm11 = @truncate(u1, umm >> 11),
.imm12_19 = @truncate(u8, umm >> 12),
.imm20 = @truncate(u1, umm >> 20),
},
@@ -340,27 +342,27 @@ pub const Instruction = union(enum) {
// Branch
- pub fn beq(r1: Register, r2: Register, offset: u13) Instruction {
+ pub fn beq(r1: Register, r2: Register, offset: i13) Instruction {
return bType(0b1100011, 0b000, r1, r2, offset);
}
- pub fn bne(r1: Register, r2: Register, offset: u13) Instruction {
+ pub fn bne(r1: Register, r2: Register, offset: i13) Instruction {
return bType(0b1100011, 0b001, r1, r2, offset);
}
- pub fn blt(r1: Register, r2: Register, offset: u13) Instruction {
+ pub fn blt(r1: Register, r2: Register, offset: i13) Instruction {
return bType(0b1100011, 0b100, r1, r2, offset);
}
- pub fn bge(r1: Register, r2: Register, offset: u13) Instruction {
+ pub fn bge(r1: Register, r2: Register, offset: i13) Instruction {
return bType(0b1100011, 0b101, r1, r2, offset);
}
- pub fn bltu(r1: Register, r2: Register, offset: u13) Instruction {
+ pub fn bltu(r1: Register, r2: Register, offset: i13) Instruction {
return bType(0b1100011, 0b110, r1, r2, offset);
}
- pub fn bgeu(r1: Register, r2: Register, offset: u13) Instruction {
+ pub fn bgeu(r1: Register, r2: Register, offset: i13) Instruction {
return bType(0b1100011, 0b111, r1, r2, offset);
}
@@ -431,3 +433,38 @@ pub const Register = enum(u5) {
pub const callee_preserved_regs = [_]Register{
.s0, .s1, .s2, .s3, .s4, .s5, .s6, .s7, .s8, .s9, .s10, .s11,
};
+
+test "serialize instructions" {
+ const Testcase = struct {
+ inst: Instruction,
+ expected: u32,
+ };
+
+ const testcases = [_]Testcase{
+ .{ // add t6, zero, zero
+ .inst = Instruction.add(.t6, .zero, .zero),
+ .expected = 0b0000000_00000_00000_000_11111_0110011,
+ },
+ .{ // sd s0, 0x7f(s0)
+ .inst = Instruction.sd(.s0, 0x7f, .s0),
+ .expected = 0b0000011_01000_01000_011_11111_0100011,
+ },
+ .{ // bne s0, s1, 0x42
+ .inst = Instruction.bne(.s0, .s1, 0x42),
+ .expected = 0b0_000010_01001_01000_001_0001_0_1100011,
+ },
+ .{ // j 0x1a
+ .inst = Instruction.jal(.zero, 0x1a),
+ .expected = 0b0_0000001101_0_00000000_00000_1101111,
+ },
+ .{ // ebreak
+ .inst = Instruction.ebreak,
+ .expected = 0b000000000001_00000_000_00000_1110011,
+ },
+ };
+
+ for (testcases) |case| {
+ const actual = case.inst.toU32();
+ testing.expectEqual(case.expected, actual);
+ }
+}
diff --git a/zig/src/libc_installation.zig b/zig/src/libc_installation.zig
index 6700787925..bb83416d30 100644
--- a/zig/src/libc_installation.zig
+++ b/zig/src/libc_installation.zig
@@ -9,6 +9,7 @@ const build_options = @import("build_options");
const is_darwin = Target.current.isDarwin();
const is_windows = Target.current.os.tag == .windows;
const is_gnu = Target.current.isGnu();
+const is_haiku = Target.current.os.tag == .haiku;
const log = std.log.scoped(.libc_installation);
@@ -279,8 +280,14 @@ pub const LibCInstallation = struct {
return error.CCompilerCannotFindHeaders;
}
- const include_dir_example_file = "stdlib.h";
- const sys_include_dir_example_file = if (is_windows) "sys\\types.h" else "sys/errno.h";
+ const include_dir_example_file = if (is_haiku) "posix/stdlib.h" else "stdlib.h";
+ const sys_include_dir_example_file = if (is_windows)
+ "sys\\types.h"
+ else if (is_haiku)
+ "posix/errno.h"
+ else
+ "sys/errno.h"
+ ;
var path_i: usize = 0;
while (path_i < search_paths.items.len) : (path_i += 1) {
diff --git a/zig/src/link/MachO.zig b/zig/src/link/MachO.zig
index 9a94b90137..aaf88ad815 100644
--- a/zig/src/link/MachO.zig
+++ b/zig/src/link/MachO.zig
@@ -645,8 +645,7 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {
break :blk true;
}
- if (self.base.options.link_libcpp or
- self.base.options.output_mode == .Lib or
+ if (self.base.options.output_mode == .Lib or
self.base.options.linker_script != null)
{
// Fallback to LLD in this handful of cases on x86_64 only.
diff --git a/zig/src/link/MachO/Archive.zig b/zig/src/link/MachO/Archive.zig
index 86e160ba4d..702a807a4d 100644
--- a/zig/src/link/MachO/Archive.zig
+++ b/zig/src/link/MachO/Archive.zig
@@ -16,7 +16,7 @@ allocator: *Allocator,
arch: ?std.Target.Cpu.Arch = null,
file: ?fs.File = null,
header: ?ar_hdr = null,
-name: ?[]u8 = null,
+name: ?[]const u8 = null,
/// Parsed table of contents.
/// Each symbol name points to a list of all definition
@@ -195,7 +195,7 @@ fn parseTableOfContents(self: *Archive, reader: anytype) !void {
}
/// Caller owns the Object instance.
-pub fn parseObject(self: Archive, offset: u32) !Object {
+pub fn parseObject(self: Archive, offset: u32) !*Object {
var reader = self.file.?.reader();
try reader.context.seekTo(offset);
@@ -208,17 +208,19 @@ pub fn parseObject(self: Archive, offset: u32) !Object {
const object_name = try parseName(self.allocator, object_header, reader);
defer self.allocator.free(object_name);
- const object_basename = std.fs.path.basename(object_name);
- log.debug("extracting object '{s}' from archive '{s}'", .{ object_basename, self.name.? });
+ log.debug("extracting object '{s}' from archive '{s}'", .{ object_name, self.name.? });
const name = name: {
var buffer: [std.fs.MAX_PATH_BYTES]u8 = undefined;
const path = try std.os.realpath(self.name.?, &buffer);
- break :name try std.fmt.allocPrint(self.allocator, "{s}({s})", .{ path, object_basename });
+ break :name try std.fmt.allocPrint(self.allocator, "{s}({s})", .{ path, object_name });
};
- var object = Object.init(self.allocator);
+ var object = try self.allocator.create(Object);
+ errdefer self.allocator.destroy(object);
+
+ object.* = Object.init(self.allocator);
object.arch = self.arch.?;
object.file = try fs.cwd().openFile(self.name.?, .{});
object.name = name;
diff --git a/zig/src/link/MachO/Object.zig b/zig/src/link/MachO/Object.zig
index 7b5f23756a..4d2ade7aad 100644
--- a/zig/src/link/MachO/Object.zig
+++ b/zig/src/link/MachO/Object.zig
@@ -22,7 +22,7 @@ arch: ?std.Target.Cpu.Arch = null,
header: ?macho.mach_header_64 = null,
file: ?fs.File = null,
file_offset: ?u32 = null,
-name: ?[]u8 = null,
+name: ?[]const u8 = null,
load_commands: std.ArrayListUnmanaged(LoadCommand) = .{},
sections: std.ArrayListUnmanaged(Section) = .{},
@@ -32,7 +32,9 @@ symtab_cmd_index: ?u16 = null,
dysymtab_cmd_index: ?u16 = null,
build_version_cmd_index: ?u16 = null,
data_in_code_cmd_index: ?u16 = null,
+
text_section_index: ?u16 = null,
+mod_init_func_section_index: ?u16 = null,
// __DWARF segment sections
dwarf_debug_info_index: ?u16 = null,
@@ -41,16 +43,13 @@ dwarf_debug_str_index: ?u16 = null,
dwarf_debug_line_index: ?u16 = null,
dwarf_debug_ranges_index: ?u16 = null,
-symtab: std.ArrayListUnmanaged(macho.nlist_64) = .{},
-strtab: std.ArrayListUnmanaged(u8) = .{},
+symbols: std.ArrayListUnmanaged(*Symbol) = .{},
+initializers: std.ArrayListUnmanaged(*Symbol) = .{},
+data_in_code_entries: std.ArrayListUnmanaged(macho.data_in_code_entry) = .{},
-locals: std.StringArrayHashMapUnmanaged(Symbol) = .{},
-stabs: std.ArrayListUnmanaged(Stab) = .{},
tu_path: ?[]const u8 = null,
tu_mtime: ?u64 = null,
-data_in_code_entries: std.ArrayListUnmanaged(macho.data_in_code_entry) = .{},
-
pub const Section = struct {
inner: macho.section_64,
code: []u8,
@@ -68,18 +67,6 @@ pub const Section = struct {
}
};
-const Stab = struct {
- tag: Tag,
- symbol: u32,
- size: ?u64 = null,
-
- const Tag = enum {
- function,
- global,
- static,
- };
-};
-
const DebugInfo = struct {
inner: dwarf.DwarfInfo,
debug_info: []u8,
@@ -161,15 +148,14 @@ pub fn deinit(self: *Object) void {
}
self.sections.deinit(self.allocator);
- for (self.locals.items()) |*entry| {
- entry.value.deinit(self.allocator);
+ for (self.symbols.items) |sym| {
+ sym.deinit(self.allocator);
+ self.allocator.destroy(sym);
}
- self.locals.deinit(self.allocator);
+ self.symbols.deinit(self.allocator);
- self.symtab.deinit(self.allocator);
- self.strtab.deinit(self.allocator);
- self.stabs.deinit(self.allocator);
self.data_in_code_entries.deinit(self.allocator);
+ self.initializers.deinit(self.allocator);
if (self.name) |n| {
self.allocator.free(n);
@@ -213,9 +199,10 @@ pub fn parse(self: *Object) !void {
}
try self.readLoadCommands(reader);
+ try self.parseSymbols();
try self.parseSections();
- if (self.symtab_cmd_index != null) try self.parseSymtab();
- if (self.data_in_code_cmd_index != null) try self.readDataInCode();
+ try self.parseDataInCode();
+ try self.parseInitializers();
try self.parseDebugInfo();
}
@@ -250,6 +237,10 @@ pub fn readLoadCommands(self: *Object, reader: anytype) !void {
if (mem.eql(u8, sectname, "__text")) {
self.text_section_index = index;
}
+ } else if (mem.eql(u8, segname, "__DATA")) {
+ if (mem.eql(u8, sectname, "__mod_init_func")) {
+ self.mod_init_func_section_index = index;
+ }
}
sect.offset += offset;
@@ -284,9 +275,10 @@ pub fn readLoadCommands(self: *Object, reader: anytype) !void {
}
pub fn parseSections(self: *Object) !void {
- log.debug("parsing sections in {s}", .{self.name.?});
const seg = self.load_commands.items[self.segment_cmd_index.?].Segment;
+ log.debug("parsing sections in {s}", .{self.name.?});
+
try self.sections.ensureCapacity(self.allocator, seg.sections.items.len);
for (seg.sections.items) |sect| {
@@ -298,67 +290,119 @@ pub fn parseSections(self: *Object) !void {
var section = Section{
.inner = sect,
.code = code,
- .relocs = undefined,
+ .relocs = null,
};
// Parse relocations
- section.relocs = if (sect.nreloc > 0) relocs: {
+ if (sect.nreloc > 0) {
var raw_relocs = try self.allocator.alloc(u8, @sizeOf(macho.relocation_info) * sect.nreloc);
defer self.allocator.free(raw_relocs);
_ = try self.file.?.preadAll(raw_relocs, sect.reloff);
- break :relocs try reloc.parse(
+ section.relocs = try reloc.parse(
self.allocator,
self.arch.?,
section.code,
mem.bytesAsSlice(macho.relocation_info, raw_relocs),
+ self.symbols.items,
);
- } else null;
+ }
self.sections.appendAssumeCapacity(section);
}
}
-pub fn parseSymtab(self: *Object) !void {
- const symtab_cmd = self.load_commands.items[self.symtab_cmd_index.?].Symtab;
+pub fn parseInitializers(self: *Object) !void {
+ const index = self.mod_init_func_section_index orelse return;
+ const section = self.sections.items[index];
+
+ log.debug("parsing initializers in {s}", .{self.name.?});
+
+ // Parse C++ initializers
+ const relocs = section.relocs orelse unreachable;
+ try self.initializers.ensureCapacity(self.allocator, relocs.len);
+ for (relocs) |rel| {
+ self.initializers.appendAssumeCapacity(rel.target.symbol);
+ }
+
+ mem.reverse(*Symbol, self.initializers.items);
+}
+
+pub fn parseSymbols(self: *Object) !void {
+ const index = self.symtab_cmd_index orelse return;
+ const symtab_cmd = self.load_commands.items[index].Symtab;
var symtab = try self.allocator.alloc(u8, @sizeOf(macho.nlist_64) * symtab_cmd.nsyms);
defer self.allocator.free(symtab);
-
_ = try self.file.?.preadAll(symtab, symtab_cmd.symoff);
const slice = @alignCast(@alignOf(macho.nlist_64), mem.bytesAsSlice(macho.nlist_64, symtab));
- try self.symtab.appendSlice(self.allocator, slice);
var strtab = try self.allocator.alloc(u8, symtab_cmd.strsize);
defer self.allocator.free(strtab);
-
_ = try self.file.?.preadAll(strtab, symtab_cmd.stroff);
- try self.strtab.appendSlice(self.allocator, strtab);
- for (self.symtab.items) |sym, sym_id| {
- if (Symbol.isStab(sym) or Symbol.isUndef(sym)) continue;
+ for (slice) |sym| {
+ const sym_name = mem.spanZ(@ptrCast([*:0]const u8, strtab.ptr + sym.n_strx));
+
+ if (Symbol.isStab(sym)) {
+ log.err("stab {s} in {s}", .{ sym_name, self.name.? });
+ return error.UnhandledSymbolType;
+ }
+ if (Symbol.isIndr(sym)) {
+ log.err("indirect symbol {s} in {s}", .{ sym_name, self.name.? });
+ return error.UnhandledSymbolType;
+ }
+ if (Symbol.isAbs(sym)) {
+ log.err("absolute symbol {s} in {s}", .{ sym_name, self.name.? });
+ return error.UnhandledSymbolType;
+ }
- const sym_name = self.getString(sym.n_strx);
- const tag: Symbol.Tag = tag: {
- if (Symbol.isLocal(sym)) {
- if (self.arch.? == .aarch64 and mem.startsWith(u8, sym_name, "l")) continue;
- break :tag .local;
+ const name = try self.allocator.dupe(u8, sym_name);
+ const symbol: *Symbol = symbol: {
+ if (Symbol.isSect(sym)) {
+ const linkage: Symbol.Regular.Linkage = linkage: {
+ if (!Symbol.isExt(sym)) break :linkage .translation_unit;
+ if (Symbol.isWeakDef(sym) or Symbol.isPext(sym)) break :linkage .linkage_unit;
+ break :linkage .global;
+ };
+ const regular = try self.allocator.create(Symbol.Regular);
+ errdefer self.allocator.destroy(regular);
+ regular.* = .{
+ .base = .{
+ .@"type" = .regular,
+ .name = name,
+ },
+ .linkage = linkage,
+ .address = sym.n_value,
+ .section = sym.n_sect - 1,
+ .weak_ref = Symbol.isWeakRef(sym),
+ .file = self,
+ };
+ break :symbol ®ular.base;
}
- if (Symbol.isWeakDef(sym)) {
- break :tag .weak;
+
+ if (sym.n_value != 0) {
+ log.err("common symbol {s} in {s}", .{ sym_name, self.name.? });
+ return error.UnhandledSymbolType;
+ // const comm_size = sym.n_value;
+ // const comm_align = (sym.n_desc >> 8) & 0x0f;
+ // log.warn("Common symbol: size 0x{x}, align 0x{x}", .{ comm_size, comm_align });
}
- break :tag .strong;
+
+ const undef = try self.allocator.create(Symbol.Unresolved);
+ errdefer self.allocator.destroy(undef);
+ undef.* = .{
+ .base = .{
+ .@"type" = .unresolved,
+ .name = name,
+ },
+ .file = self,
+ };
+ break :symbol &undef.base;
};
- const name = try self.allocator.dupe(u8, sym_name);
- try self.locals.putNoClobber(self.allocator, name, .{
- .tag = tag,
- .name = name,
- .address = 0,
- .section = 0,
- .index = @intCast(u32, sym_id),
- });
+ try self.symbols.append(self.allocator, symbol);
}
}
@@ -390,38 +434,31 @@ pub fn parseDebugInfo(self: *Object) !void {
break :mtime @intCast(u64, @divFloor(stat.mtime, 1_000_000_000));
};
- for (self.locals.items()) |entry, index| {
- const local = entry.value;
- const source_sym = self.symtab.items[local.index.?];
- const size = blk: for (debug_info.inner.func_list.items) |func| {
- if (func.pc_range) |range| {
- if (source_sym.n_value >= range.start and source_sym.n_value < range.end) {
- break :blk range.end - range.start;
+ for (self.symbols.items) |sym| {
+ if (sym.cast(Symbol.Regular)) |reg| {
+ const size: u64 = blk: for (debug_info.inner.func_list.items) |func| {
+ if (func.pc_range) |range| {
+ if (reg.address >= range.start and reg.address < range.end) {
+ break :blk range.end - range.start;
+ }
}
- }
- } else null;
- const tag: Stab.Tag = tag: {
- if (size != null) break :tag .function;
- switch (local.tag) {
- .weak, .strong => break :tag .global,
- else => break :tag .static,
- }
- };
-
- try self.stabs.append(self.allocator, .{
- .tag = tag,
- .size = size,
- .symbol = @intCast(u32, index),
- });
+ } else 0;
+
+ reg.stab = .{
+ .kind = kind: {
+ if (size > 0) break :kind .function;
+ switch (reg.linkage) {
+ .translation_unit => break :kind .static,
+ else => break :kind .global,
+ }
+ },
+ .size = size,
+ };
+ }
}
}
-pub fn getString(self: *const Object, str_off: u32) []const u8 {
- assert(str_off < self.strtab.items.len);
- return mem.spanZ(@ptrCast([*:0]const u8, self.strtab.items.ptr + str_off));
-}
-
-pub fn readSection(self: Object, allocator: *Allocator, index: u16) ![]u8 {
+fn readSection(self: Object, allocator: *Allocator, index: u16) ![]u8 {
const seg = self.load_commands.items[self.segment_cmd_index.?].Segment;
const sect = seg.sections.items[index];
var buffer = try allocator.alloc(u8, sect.size);
@@ -429,7 +466,7 @@ pub fn readSection(self: Object, allocator: *Allocator, index: u16) ![]u8 {
return buffer;
}
-pub fn readDataInCode(self: *Object) !void {
+pub fn parseDataInCode(self: *Object) !void {
const index = self.data_in_code_cmd_index orelse return;
const data_in_code = self.load_commands.items[index].LinkeditData;
diff --git a/zig/src/link/MachO/Symbol.zig b/zig/src/link/MachO/Symbol.zig
index f65a694f75..f928c807a3 100644
--- a/zig/src/link/MachO/Symbol.zig
+++ b/zig/src/link/MachO/Symbol.zig
@@ -2,31 +2,113 @@ const Symbol = @This();
const std = @import("std");
const macho = std.macho;
+const mem = std.mem;
-const Allocator = std.mem.Allocator;
+const Allocator = mem.Allocator;
+const Object = @import("Object.zig");
-pub const Tag = enum {
- local,
- weak,
- strong,
- import,
- undef,
+pub const Type = enum {
+ regular,
+ proxy,
+ unresolved,
};
-tag: Tag,
+/// Symbol type.
+@"type": Type,
+
+/// Symbol name. Owned slice.
name: []u8,
-address: u64,
-section: u8,
-/// Index of file where to locate this symbol.
-/// Depending on context, this is either an object file, or a dylib.
-file: ?u16 = null,
+/// Alias of.
+alias: ?*Symbol = null,
+
+/// Index in GOT table for indirection.
+got_index: ?u32 = null,
+
+/// Index in stubs table for late binding.
+stubs_index: ?u32 = null,
+
+pub const Regular = struct {
+ base: Symbol,
+
+ /// Linkage type.
+ linkage: Linkage,
+
+ /// Symbol address.
+ address: u64,
+
+ /// Section ID where the symbol resides.
+ section: u8,
+
+ /// Whether the symbol is a weak ref.
+ weak_ref: bool,
+
+ /// File where to locate this symbol.
+ file: *Object,
+
+ /// Debug stab if defined.
+ stab: ?struct {
+ /// Stab kind
+ kind: enum {
+ function,
+ global,
+ static,
+ },
+
+ /// Size of the stab.
+ size: u64,
+ } = null,
+
+ pub const base_type: Symbol.Type = .regular;
+
+ pub const Linkage = enum {
+ translation_unit,
+ linkage_unit,
+ global,
+ };
+
+ pub fn isTemp(regular: *Regular) bool {
+ if (regular.linkage == .translation_unit) {
+ return mem.startsWith(u8, regular.base.name, "l") or mem.startsWith(u8, regular.base.name, "L");
+ }
+ return false;
+ }
+};
+
+pub const Proxy = struct {
+ base: Symbol,
+
+ /// Dylib ordinal.
+ dylib: u16,
+
+ pub const base_type: Symbol.Type = .proxy;
+};
+
+pub const Unresolved = struct {
+ base: Symbol,
+
+ /// File where this symbol was referenced.
+ file: *Object,
-/// Index of this symbol within the file's symbol table.
-index: ?u32 = null,
+ pub const base_type: Symbol.Type = .unresolved;
+};
-pub fn deinit(self: *Symbol, allocator: *Allocator) void {
- allocator.free(self.name);
+pub fn deinit(base: *Symbol, allocator: *Allocator) void {
+ allocator.free(base.name);
+}
+
+pub fn cast(base: *Symbol, comptime T: type) ?*T {
+ if (base.@"type" != T.base_type) {
+ return null;
+ }
+ return @fieldParentPtr(T, "base", base);
+}
+
+pub fn getTopmostAlias(base: *Symbol) *Symbol {
+ if (base.alias) |alias| {
+ return alias.getTopmostAlias();
+ }
+ return base;
}
pub fn isStab(sym: macho.nlist_64) bool {
@@ -51,21 +133,20 @@ pub fn isUndf(sym: macho.nlist_64) bool {
return type_ == macho.N_UNDF;
}
-pub fn isWeakDef(sym: macho.nlist_64) bool {
- return sym.n_desc == macho.N_WEAK_DEF;
+pub fn isIndr(sym: macho.nlist_64) bool {
+ const type_ = macho.N_TYPE & sym.n_type;
+ return type_ == macho.N_INDR;
}
-/// Symbol is local if it is defined and not an extern.
-pub fn isLocal(sym: macho.nlist_64) bool {
- return isSect(sym) and !isExt(sym);
+pub fn isAbs(sym: macho.nlist_64) bool {
+ const type_ = macho.N_TYPE & sym.n_type;
+ return type_ == macho.N_ABS;
}
-/// Symbol is global if it is defined and an extern.
-pub fn isGlobal(sym: macho.nlist_64) bool {
- return isSect(sym) and isExt(sym);
+pub fn isWeakDef(sym: macho.nlist_64) bool {
+ return (sym.n_desc & macho.N_WEAK_DEF) != 0;
}
-/// Symbol is undefined if it is not defined and an extern.
-pub fn isUndef(sym: macho.nlist_64) bool {
- return isUndf(sym) and isExt(sym);
+pub fn isWeakRef(sym: macho.nlist_64) bool {
+ return (sym.n_desc & macho.N_WEAK_REF) != 0;
}
diff --git a/zig/src/link/MachO/Zld.zig b/zig/src/link/MachO/Zld.zig
index ae475ab30d..4d19da1e97 100644
--- a/zig/src/link/MachO/Zld.zig
+++ b/zig/src/link/MachO/Zld.zig
@@ -29,8 +29,8 @@ page_size: ?u16 = null,
file: ?fs.File = null,
out_path: ?[]const u8 = null,
-objects: std.ArrayListUnmanaged(Object) = .{},
-archives: std.ArrayListUnmanaged(Archive) = .{},
+objects: std.ArrayListUnmanaged(*Object) = .{},
+archives: std.ArrayListUnmanaged(*Archive) = .{},
load_commands: std.ArrayListUnmanaged(LoadCommand) = .{},
@@ -58,6 +58,7 @@ stubs_section_index: ?u16 = null,
stub_helper_section_index: ?u16 = null,
text_const_section_index: ?u16 = null,
cstring_section_index: ?u16 = null,
+ustring_section_index: ?u16 = null,
// __DATA_CONST segment sections
got_section_index: ?u16 = null,
@@ -72,29 +73,32 @@ tlv_bss_section_index: ?u16 = null,
la_symbol_ptr_section_index: ?u16 = null,
data_section_index: ?u16 = null,
bss_section_index: ?u16 = null,
+common_section_index: ?u16 = null,
+
+globals: std.StringArrayHashMapUnmanaged(*Symbol) = .{},
+imports: std.StringArrayHashMapUnmanaged(*Symbol) = .{},
+unresolved: std.StringArrayHashMapUnmanaged(*Symbol) = .{},
-symtab: std.StringArrayHashMapUnmanaged(Symbol) = .{},
strtab: std.ArrayListUnmanaged(u8) = .{},
strtab_dir: std.StringHashMapUnmanaged(u32) = .{},
-threadlocal_offsets: std.ArrayListUnmanaged(u64) = .{},
+threadlocal_offsets: std.ArrayListUnmanaged(TlvOffset) = .{}, // TODO merge with Symbol abstraction
local_rebases: std.ArrayListUnmanaged(Pointer) = .{},
-stubs: std.StringArrayHashMapUnmanaged(u32) = .{},
-got_entries: std.StringArrayHashMapUnmanaged(GotEntry) = .{},
+stubs: std.ArrayListUnmanaged(*Symbol) = .{},
+got_entries: std.ArrayListUnmanaged(*Symbol) = .{},
stub_helper_stubs_start_off: ?u64 = null,
mappings: std.AutoHashMapUnmanaged(MappingKey, SectionMapping) = .{},
unhandled_sections: std.AutoHashMapUnmanaged(MappingKey, u0) = .{},
-const GotEntry = struct {
- tag: enum {
- local,
- import,
- },
- index: u32,
- target_addr: u64,
- file: u16,
+const TlvOffset = struct {
+ source_addr: u64,
+ offset: u64,
+
+ fn cmp(context: void, a: TlvOffset, b: TlvOffset) bool {
+ return a.source_addr < b.source_addr;
+ }
};
const MappingKey = struct {
@@ -123,15 +127,7 @@ pub fn init(allocator: *Allocator) Zld {
pub fn deinit(self: *Zld) void {
self.threadlocal_offsets.deinit(self.allocator);
self.local_rebases.deinit(self.allocator);
-
- for (self.stubs.items()) |entry| {
- self.allocator.free(entry.key);
- }
self.stubs.deinit(self.allocator);
-
- for (self.got_entries.items()) |entry| {
- self.allocator.free(entry.key);
- }
self.got_entries.deinit(self.allocator);
for (self.load_commands.items) |*lc| {
@@ -139,23 +135,22 @@ pub fn deinit(self: *Zld) void {
}
self.load_commands.deinit(self.allocator);
- for (self.objects.items) |*object| {
+ for (self.objects.items) |object| {
object.deinit();
+ self.allocator.destroy(object);
}
self.objects.deinit(self.allocator);
- for (self.archives.items) |*archive| {
+ for (self.archives.items) |archive| {
archive.deinit();
+ self.allocator.destroy(archive);
}
self.archives.deinit(self.allocator);
self.mappings.deinit(self.allocator);
self.unhandled_sections.deinit(self.allocator);
- for (self.symtab.items()) |*entry| {
- entry.value.deinit(self.allocator);
- }
- self.symtab.deinit(self.allocator);
+ self.globals.deinit(self.allocator);
self.strtab.deinit(self.allocator);
{
@@ -223,9 +218,6 @@ pub fn link(self: *Zld, files: []const []const u8, out_path: []const u8) !void {
try self.allocateDataSegment();
self.allocateLinkeditSegment();
try self.allocateSymbols();
- try self.allocateStubsAndGotEntries();
- try self.writeStubHelperCommon();
- try self.resolveRelocsAndWriteSections();
try self.flush();
}
@@ -289,17 +281,23 @@ fn parseInputFiles(self: *Zld, files: []const []const u8) !void {
for (classified.items) |input| {
switch (input.kind) {
.object => {
- var object = Object.init(self.allocator);
+ const object = try self.allocator.create(Object);
+ errdefer self.allocator.destroy(object);
+
+ object.* = Object.init(self.allocator);
object.arch = self.arch.?;
- object.name = try self.allocator.dupe(u8, input.name);
+ object.name = input.name;
object.file = input.file;
try object.parse();
try self.objects.append(self.allocator, object);
},
.archive => {
- var archive = Archive.init(self.allocator);
+ const archive = try self.allocator.create(Archive);
+ errdefer self.allocator.destroy(archive);
+
+ archive.* = Archive.init(self.allocator);
archive.arch = self.arch.?;
- archive.name = try self.allocator.dupe(u8, input.name);
+ archive.name = input.name;
archive.file = input.file;
try archive.parse();
try self.archives.append(self.allocator, archive);
@@ -365,23 +363,43 @@ fn updateMetadata(self: *Zld) !void {
switch (flags) {
macho.S_REGULAR, macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS => {
if (mem.eql(u8, segname, "__TEXT")) {
- if (self.text_const_section_index != null) continue;
-
- self.text_const_section_index = @intCast(u16, text_seg.sections.items.len);
- try text_seg.addSection(self.allocator, .{
- .sectname = makeStaticString("__const"),
- .segname = makeStaticString("__TEXT"),
- .addr = 0,
- .size = 0,
- .offset = 0,
- .@"align" = 0,
- .reloff = 0,
- .nreloc = 0,
- .flags = macho.S_REGULAR,
- .reserved1 = 0,
- .reserved2 = 0,
- .reserved3 = 0,
- });
+ if (mem.eql(u8, sectname, "__ustring")) {
+ if (self.ustring_section_index != null) continue;
+
+ self.ustring_section_index = @intCast(u16, text_seg.sections.items.len);
+ try text_seg.addSection(self.allocator, .{
+ .sectname = makeStaticString("__ustring"),
+ .segname = makeStaticString("__TEXT"),
+ .addr = 0,
+ .size = 0,
+ .offset = 0,
+ .@"align" = 0,
+ .reloff = 0,
+ .nreloc = 0,
+ .flags = macho.S_REGULAR,
+ .reserved1 = 0,
+ .reserved2 = 0,
+ .reserved3 = 0,
+ });
+ } else {
+ if (self.text_const_section_index != null) continue;
+
+ self.text_const_section_index = @intCast(u16, text_seg.sections.items.len);
+ try text_seg.addSection(self.allocator, .{
+ .sectname = makeStaticString("__const"),
+ .segname = makeStaticString("__TEXT"),
+ .addr = 0,
+ .size = 0,
+ .offset = 0,
+ .@"align" = 0,
+ .reloff = 0,
+ .nreloc = 0,
+ .flags = macho.S_REGULAR,
+ .reserved1 = 0,
+ .reserved2 = 0,
+ .reserved3 = 0,
+ });
+ }
} else if (mem.eql(u8, segname, "__DATA")) {
if (!mem.eql(u8, sectname, "__const")) continue;
if (self.data_const_section_index != null) continue;
@@ -465,23 +483,43 @@ fn updateMetadata(self: *Zld) !void {
},
macho.S_ZEROFILL => {
if (!mem.eql(u8, segname, "__DATA")) continue;
- if (self.bss_section_index != null) continue;
+ if (mem.eql(u8, sectname, "__common")) {
+ if (self.common_section_index != null) continue;
- self.bss_section_index = @intCast(u16, data_seg.sections.items.len);
- try data_seg.addSection(self.allocator, .{
- .sectname = makeStaticString("__bss"),
- .segname = makeStaticString("__DATA"),
- .addr = 0,
- .size = 0,
- .offset = 0,
- .@"align" = 0,
- .reloff = 0,
- .nreloc = 0,
- .flags = macho.S_ZEROFILL,
- .reserved1 = 0,
- .reserved2 = 0,
- .reserved3 = 0,
- });
+ self.common_section_index = @intCast(u16, data_seg.sections.items.len);
+ try data_seg.addSection(self.allocator, .{
+ .sectname = makeStaticString("__common"),
+ .segname = makeStaticString("__DATA"),
+ .addr = 0,
+ .size = 0,
+ .offset = 0,
+ .@"align" = 0,
+ .reloff = 0,
+ .nreloc = 0,
+ .flags = macho.S_ZEROFILL,
+ .reserved1 = 0,
+ .reserved2 = 0,
+ .reserved3 = 0,
+ });
+ } else {
+ if (self.bss_section_index != null) continue;
+
+ self.bss_section_index = @intCast(u16, data_seg.sections.items.len);
+ try data_seg.addSection(self.allocator, .{
+ .sectname = makeStaticString("__bss"),
+ .segname = makeStaticString("__DATA"),
+ .addr = 0,
+ .size = 0,
+ .offset = 0,
+ .@"align" = 0,
+ .reloff = 0,
+ .nreloc = 0,
+ .flags = macho.S_ZEROFILL,
+ .reserved1 = 0,
+ .reserved2 = 0,
+ .reserved3 = 0,
+ });
+ }
},
macho.S_THREAD_LOCAL_VARIABLES => {
if (!mem.eql(u8, segname, "__DATA")) continue;
@@ -568,13 +606,59 @@ fn updateMetadata(self: *Zld) !void {
const segname = parseName(&source_sect.segname);
const sectname = parseName(&source_sect.sectname);
+
log.debug("section '{s}/{s}' will be unmapped", .{ segname, sectname });
+
try self.unhandled_sections.putNoClobber(self.allocator, .{
.object_id = object_id,
.source_sect_id = source_sect_id,
}, 0);
}
}
+
+ tlv_align: {
+ const has_tlv =
+ self.tlv_section_index != null or
+ self.tlv_data_section_index != null or
+ self.tlv_bss_section_index != null;
+
+ if (!has_tlv) break :tlv_align;
+
+ const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
+
+ if (self.tlv_section_index) |index| {
+ const sect = &seg.sections.items[index];
+ sect.@"align" = 3; // __thread_vars is always 8byte aligned
+ }
+
+ // Apparently __tlv_data and __tlv_bss need to have matching alignment, so fix it up.
+ //