diff --git a/library/compiler-builtins/.github/workflows/main.yaml b/library/compiler-builtins/.github/workflows/main.yaml index 2729b8fa5d5c3..2ded0f6177d7b 100644 --- a/library/compiler-builtins/.github/workflows/main.yaml +++ b/library/compiler-builtins/.github/workflows/main.yaml @@ -15,13 +15,19 @@ env: RUSTDOCFLAGS: -Dwarnings RUSTFLAGS: -Dwarnings RUST_BACKTRACE: full - BENCHMARK_RUSTC: nightly-2026-02-10 # Pin the toolchain for reproducable results + BENCHMARK_RUSTC: nightly-2026-08-05 # Pin the toolchain for reproducable results + +defaults: + run: + # Add `-ux` to the default template specified at + # https://docs.github.com/en/actions/reference/workflows-and-actions/workflow-syntax#defaultsrunshell + shell: bash --noprofile --norc -euxo pipefail {0} jobs: # Determine which tests should be run based on changed files. calculate_vars: name: Calculate workflow variables - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 timeout-minutes: 10 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -30,7 +36,7 @@ jobs: extensive_matrix: ${{ steps.script.outputs.extensive_matrix }} may_skip_libm_ci: ${{ steps.script.outputs.may_skip_libm_ci }} steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false fetch-depth: 500 @@ -53,61 +59,63 @@ jobs: matrix: include: - target: aarch64-apple-darwin - os: macos-15 + os: macos-26 - target: aarch64-unknown-linux-gnu - os: ubuntu-24.04-arm + os: ubuntu-26.04-arm - target: aarch64-pc-windows-msvc - os: windows-11-arm + os: windows-11-vs2026-arm - target: arm-unknown-linux-gnueabi - os: ubuntu-24.04 + os: ubuntu-26.04 - target: arm-unknown-linux-gnueabihf - os: ubuntu-24.04 + os: ubuntu-26.04 - target: armv7-unknown-linux-gnueabihf - os: ubuntu-24.04 + os: ubuntu-26.04 - target: i586-unknown-linux-gnu - os: ubuntu-24.04 + os: ubuntu-26.04 - target: i686-unknown-linux-gnu - os: ubuntu-24.04 + os: ubuntu-26.04 - target: loongarch64-unknown-linux-gnu - os: ubuntu-24.04 + os: ubuntu-26.04 - target: powerpc-unknown-linux-gnu - os: ubuntu-24.04 + os: ubuntu-26.04 - target: powerpc64-unknown-linux-gnu - os: ubuntu-24.04 + os: ubuntu-26.04 + - target: powerpc64-unknown-linux-musl + os: ["self-hosted", "linux", "powerpc64", "musl"] - target: powerpc64le-unknown-linux-gnu - os: ubuntu-24.04 + os: ubuntu-26.04 - target: powerpc64le-unknown-linux-gnu os: ubuntu-24.04-ppc64le # FIXME(ci): re-enable these once more capacity is avialable # - target: riscv64gc-unknown-linux-gnu # os: ["self-hosted", "linux", "riscv64"] - target: riscv64gc-unknown-linux-gnu - os: ubuntu-24.04 + os: ubuntu-26.04 - target: s390x-unknown-linux-gnu os: ubuntu-24.04-s390x - target: thumbv6m-none-eabi - os: ubuntu-24.04 + os: ubuntu-26.04 - target: thumbv7em-none-eabi - os: ubuntu-24.04 + os: ubuntu-26.04 - target: thumbv7em-none-eabihf - os: ubuntu-24.04 + os: ubuntu-26.04 - target: thumbv7m-none-eabi - os: ubuntu-24.04 + os: ubuntu-26.04 - target: wasm32-unknown-unknown - os: ubuntu-24.04 + os: ubuntu-26.04 - target: x86_64-unknown-linux-gnu - os: ubuntu-24.04 + os: ubuntu-26.04 - target: x86_64-apple-darwin - os: macos-15-intel + os: macos-26-intel - target: i686-pc-windows-msvc - os: windows-2025 + os: windows-2025-vs2026 - target: x86_64-pc-windows-msvc - os: windows-2025 + os: windows-2025-vs2026 - target: i686-pc-windows-gnu - os: windows-2025 + os: windows-2025-vs2026 channel: nightly-i686-gnu - target: x86_64-pc-windows-gnu - os: windows-2025 + os: windows-2025-vs2026 channel: nightly-x86_64-gnu runs-on: ${{ matrix.os }} needs: [calculate_vars] @@ -116,12 +124,10 @@ jobs: JOB_TARGET: ${{ matrix.target }} JOB_CHANNEL: ${{ matrix.channel }} MAY_SKIP_LIBM_CI: ${{ needs.calculate_vars.outputs.may_skip_libm_ci }} - RUN_IN_DOCKER: ${{ matrix.os == 'ubuntu-24.04' }} + RUN_IN_DOCKER: ${{ matrix.os == 'ubuntu-26.04' }} steps: - name: Print runner information - shell: bash run: | - set -x uname -a lscpu || (sysctl -a | grep cpu) || true echo "home: ${HOME:-not found}" @@ -129,13 +135,12 @@ jobs: # Native ppc and s390x runners don't have rustup by default - name: Install rustup - if: matrix.os == 'ubuntu-24.04-ppc64le' || matrix.os == 'ubuntu-24.04-s390x' + if: matrix.os == 'ubuntu-26.04-ppc64le' || matrix.os == 'ubuntu-26.04-s390x' run: sudo apt-get update && sudo apt-get install -y rustup - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: { persist-credentials: false } - name: Install Rust (rustup) - shell: bash run: | channel="nightly" # Account for channels that have required components (MinGW) @@ -144,43 +149,40 @@ jobs: rustup default "$channel" rustup target add "$JOB_TARGET" - - uses: taiki-e/install-action@920ab1831fbf4fb3ef75c8ead83556c918bb7290 # v2.79.8 + - uses: taiki-e/install-action@7f4eb899022d8fe70b20c4f3de697aa85c309026 # v2.85.11 with: tool: nextest@0.9.131 - - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 + - uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 with: key: ${{ matrix.target }} - name: Cache Docker layers - uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 if: ${{ env.RUN_IN_DOCKER == 'true' }} with: path: /tmp/.buildx-cache key: ${{ matrix.target }}-buildx-${{ github.sha }} restore-keys: ${{ matrix.target }}-buildx- # Configure buildx to use Docker layer caching - - uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4 + - uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0 if: ${{ env.RUN_IN_DOCKER == 'true' }} - name: Cache compiler-rt id: cache-compiler-rt - uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4 + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: path: compiler-rt - key: ${{ runner.os }}-compiler-rt-${{ hashFiles('ci/download-compiler-rt.sh') }} + key: ${{ runner.os }}-compiler-rt-${{ hashFiles('ci/download-compiler-rt.sh', 'ci/compiler-rt-patches') }} - name: Download compiler-rt reference sources if: steps.cache-compiler-rt.outputs.cache-hit != 'true' run: ./ci/download-compiler-rt.sh - shell: bash - run: echo "RUST_COMPILER_RT_ROOT=$(realpath ./compiler-rt)" >> "$GITHUB_ENV" - shell: bash - name: Download musl source run: ./ci/update-musl.sh - shell: bash - name: Verify API list - if: matrix.os == 'ubuntu-24.04' || contains(matrix.os, 'self-hosted') + if: matrix.os == 'ubuntu-26.04' || contains(matrix.os, 'self-hosted') run: | # Must be run on the host (not in Docker) because git and fs access is required. python3 etc/update-api-list.py --check @@ -189,7 +191,6 @@ jobs: # Non-linux tests just use our raw script - name: Run locally if: ${{ env.RUN_IN_DOCKER != 'true' }} - shell: bash run: ./ci/run.sh "$JOB_TARGET" # Otherwise we use our docker containers to run builds @@ -200,7 +201,6 @@ jobs: - name: Print test logs if available if: always() run: if [ -f "target/test-log.txt" ]; then cat target/test-log.txt; fi - shell: bash # Workaround to keep Docker cache smaller # https://github.com/docker/build-push-action/issues/252 @@ -213,10 +213,10 @@ jobs: clippy: name: Clippy - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 timeout-minutes: 10 steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: { persist-credentials: false } # Unlike rustfmt, stable clippy does not work on code with nightly features. - name: Install nightly `clippy` @@ -224,35 +224,35 @@ jobs: rustup update nightly --no-self-update rustup default nightly rustup component add clippy - - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 + - uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 - name: Download musl source run: ./ci/update-musl.sh - run: cargo clippy --workspace --all-targets zizmor: name: Zizmor (Static analysis for GitHub Actions) - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 permissions: security-events: write timeout-minutes: 10 steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: { persist-credentials: false } - - uses: zizmorcore/zizmor-action@71321a20a9ded102f6e9ce5718a2fcec2c4f70d8 # v0.5.2 + - uses: zizmorcore/zizmor-action@3dc1ecc9bcb9e94e9b2c709687979e1298497054 # v0.6.2 build-custom: name: Build custom target - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 timeout-minutes: 10 steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: { persist-credentials: false } - name: Install Rust run: | rustup update nightly --no-self-update rustup default nightly rustup component add rust-src - - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 + - uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 - run: | # Ensure we can build with custom target.json files (these can interact # poorly with build scripts) @@ -264,17 +264,17 @@ jobs: # FIXME: move this target to test job once https://github.com/rust-lang/rust/pull/150138 merged. build-thumbv6k: name: Build thumbv6k - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 timeout-minutes: 10 steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: { persist-credentials: false } - name: Install Rust run: | rustup update nightly --no-self-update rustup default nightly rustup component add rust-src - - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 + - uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 - run: | cargo build -p compiler_builtins -p libm \ --target etc/thumbv6-none-eabi.json \ @@ -289,24 +289,24 @@ jobs: matrix: include: - target: aarch64-unknown-linux-gnu - os: ubuntu-24.04-arm + os: ubuntu-26.04-arm - target: i686-unknown-linux-gnu - os: ubuntu-24.04 + os: ubuntu-26.04 - target: x86_64-unknown-linux-gnu - os: ubuntu-24.04 + os: ubuntu-26.04 runs-on: ${{ matrix.os }} env: JOB_TARGET: ${{ matrix.target }} steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: { persist-credentials: false } - - uses: taiki-e/install-action@920ab1831fbf4fb3ef75c8ead83556c918bb7290 # v2.79.8 + - uses: taiki-e/install-action@7f4eb899022d8fe70b20c4f3de697aa85c309026 # v2.85.11 with: tool: cargo-binstall@1.17.7 - name: Set up dependencies run: ./ci/install-bench-deps.sh "$JOB_TARGET" - - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 + - uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 with: key: ${{ matrix.target }} - name: Download musl source @@ -319,7 +319,7 @@ jobs: run: ./ci/bench-icount.sh "$JOB_TARGET" - name: Upload the benchmark baseline - uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: ${{ env.BASELINE_NAME }} path: ${{ env.BASELINE_NAME }}.tar.xz @@ -327,38 +327,36 @@ jobs: - name: Print test logs if available if: always() run: if [ -f "target/test-log.txt" ]; then cat target/test-log.txt; fi - shell: bash miri: name: Miri - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 timeout-minutes: 10 steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: { persist-credentials: false } - name: Install Rust (rustup) run: rustup update nightly --no-self-update && rustup default nightly - shell: bash - run: rustup component add miri - run: cargo miri setup - - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 + - uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 - run: ./ci/miri.sh msrv: name: Check libm MSRV - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 timeout-minutes: 10 env: RUSTFLAGS: # No need to check warnings on old MSRV, unset `-Dwarnings` steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: { persist-credentials: false } - name: Install Rust run: | msrv="$(perl -ne 'print if s/rust-version\s*=\s*"(.*)"/\1/g' libm/Cargo.toml)" echo "MSRV: $msrv" rustup update "$msrv" --no-self-update && rustup default "$msrv" - - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 + - uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 - run: | # FIXME(msrv): Remove the workspace Cargo.toml so 1.63 cargo doesn't see # `edition = "2024"` and get spooked. @@ -367,10 +365,10 @@ jobs: rustfmt: name: Rustfmt - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 timeout-minutes: 10 steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: { persist-credentials: false } - name: Install nightly `rustfmt` run: rustup set profile minimal && rustup default nightly && rustup component add rustfmt @@ -382,7 +380,7 @@ jobs: # Wait on `clippy` so we have some confidence that the crate will build - clippy - calculate_vars - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 timeout-minutes: 240 # 4 hours strategy: matrix: @@ -394,20 +392,19 @@ jobs: env: TO_TEST: ${{ matrix.to_test }} steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: { persist-credentials: false } - name: Install Rust run: | rustup update nightly --no-self-update rustup default nightly - - uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1 + - uses: Swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6 # v2.9.2 - name: download musl source run: ./ci/update-musl.sh - name: Run extensive tests run: ./ci/run-extensive.sh - name: Print test logs if available run: if [ -f "target/test-log.txt" ]; then cat target/test-log.txt; fi - shell: bash success: needs: @@ -421,7 +418,7 @@ jobs: - rustfmt - test - zizmor - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 timeout-minutes: 10 # GitHub branch protection is exceedingly silly and treats "jobs skipped because a dependency # failed" as success. So we have to do some contortions to ensure the job fails if any of its diff --git a/library/compiler-builtins/.github/workflows/publish.yaml b/library/compiler-builtins/.github/workflows/publish.yaml index aa742914a5344..02ddf0babdf40 100644 --- a/library/compiler-builtins/.github/workflows/publish.yaml +++ b/library/compiler-builtins/.github/workflows/publish.yaml @@ -13,13 +13,13 @@ jobs: runs-on: ubuntu-24.04 environment: publish steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false fetch-depth: 0 - name: Install Rust (rustup) run: rustup update nightly --no-self-update && rustup default nightly - name: Run release-plz - uses: release-plz/action@1528104d2ca23787631a1c1f022abb64b34c1e11 # v0.5 + uses: release-plz/action@2eb1d8bcb770b4c48ccfaad919734b38b51958c9 # v0.5 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/library/compiler-builtins/.github/workflows/rustc-pull.yml b/library/compiler-builtins/.github/workflows/rustc-pull.yml index ff8305d3729fd..34e78e445677c 100644 --- a/library/compiler-builtins/.github/workflows/rustc-pull.yml +++ b/library/compiler-builtins/.github/workflows/rustc-pull.yml @@ -13,7 +13,7 @@ env: jobs: pull: if: github.repository == 'rust-lang/compiler-builtins' - uses: rust-lang/josh-sync/.github/workflows/rustc-pull.yml@8970a6eb3a6095db68e4d765b3b5fba5e9c42cf6 # main + uses: rust-lang/josh-sync/.github/workflows/rustc-pull.yml@00d007cf377c524bc2968b40a61ef1d2ce20e283 # main with: github-app-id: ${{ vars.APP_CLIENT_ID }} pr-author: "workflows-compiler-builtins[bot]" diff --git a/library/compiler-builtins/.gitignore b/library/compiler-builtins/.gitignore index 1137a19cf093b..ec7130db73802 100644 --- a/library/compiler-builtins/.gitignore +++ b/library/compiler-builtins/.gitignore @@ -1,11 +1,6 @@ # Rust files target -# We have a couple of potential Cargo.lock files, but we only the root -# workspace should have dependencies other than (optional) `cc`. -Cargo.lock -!/Cargo.lock - # Sources for external files compiler-rt *.tar.gz diff --git a/library/compiler-builtins/Cargo.lock b/library/compiler-builtins/Cargo.lock index ed27483d44b4e..1c216f5165b54 100644 --- a/library/compiler-builtins/Cargo.lock +++ b/library/compiler-builtins/Cargo.lock @@ -10,9 +10,9 @@ checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "aho-corasick" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +checksum = "c982642fa9e8606056828ee9a8505737230110bb1099153c79efe865c59d12ba" dependencies = [ "memchr", ] @@ -84,9 +84,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.102" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" +checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470" [[package]] name = "api-list-common" @@ -94,9 +94,9 @@ version = "0.1.0" [[package]] name = "assert_cmd" -version = "2.2.1" +version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39bae1d3fa576f7c6519514180a72559268dd7d1fe104070956cb687bc6673bd" +checksum = "2aa3a22042e45de04255c7bf3626e239f450200fd0493c1e382263544b20aea6" dependencies = [ "anstyle", "bstr", @@ -109,9 +109,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" [[package]] name = "az" @@ -121,29 +121,31 @@ checksum = "be5eb007b7cacc6c660343e96f650fedf4b5a77512399eb952ca6642cf8d13f7" [[package]] name = "bincode-next" -version = "2.1.0" +version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbe9e7e6d14aeb39557f226bff158a30e367fac279d0e69b8b42fb41999f9a86" +checksum = "1d6626829353ae29293be5c86f42de5f0468bc758af074b0c7d08f07e538ccbc" dependencies = [ + "pastey", + "rapidhash", "serde", "unty-next", ] [[package]] name = "bitflags" -version = "2.11.1" +version = "2.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" +checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da" [[package]] name = "bstr" -version = "1.12.1" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab" +checksum = "1f7dc094d718f2e1c1559ad110e27eeaae14a5465d3d56dd6dbd793079fbd530" dependencies = [ "memchr", "regex-automata", - "serde", + "serde_core", ] [[package]] @@ -160,9 +162,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.20.2" +version = "3.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" [[package]] name = "cast" @@ -172,9 +174,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.61" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d16d90359e986641506914ba71350897565610e87ce0ad9e6f28569db3dd5c6d" +checksum = "5d262e149917187838d5b42777c8253bcb64500067342904e7d429499a6f277e" dependencies = [ "find-msvc-tools", "shlex", @@ -188,9 +190,9 @@ checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "chacha20" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" +checksum = "d524456ba66e72eb8b115ff89e01e497f8e6d11d78b70b1aa13c0fbd97540a81" dependencies = [ "cfg-if", "cpufeatures", @@ -226,9 +228,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.6.1" +version = "4.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" +checksum = "473c7e07f409a8d772161724aa8db6a765a2532a70f9667eeb7b49d3d02fbdca" dependencies = [ "clap_builder", "clap_derive", @@ -236,9 +238,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.6.0" +version = "4.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" +checksum = "7b48fea5a88e9ae728a2dcbedbfc0e730f7d60da42e1cb049a83c9fb8b789889" dependencies = [ "anstream", "anstyle", @@ -248,14 +250,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.6.1" +version = "4.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9" +checksum = "d012d2b9d65aca7f18f4d9878a045bc17899bba951561ba5ec3c2ba1eed9a061" dependencies = [ "heck", "proc-macro2", "quote", - "syn", + "syn 3.0.3", ] [[package]] @@ -279,9 +281,9 @@ dependencies = [ [[package]] name = "console" -version = "0.16.3" +version = "0.16.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d64e8af5551369d19cf50138de61f1c42074ab970f74e99be916646777f8fc87" +checksum = "4fe5f465a4f6fee88fad41b85d990f84c835335e85b5d9e6e63e0d06d28cba7c" dependencies = [ "encode_unicode", "libc", @@ -342,9 +344,9 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +checksum = "5181e0de7b61eb03a81e347d6dd8797bae9da5146707b51077e2d71a54ec0ceb" dependencies = [ "crossbeam-epoch", "crossbeam-utils", @@ -352,18 +354,18 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.18" +version = "0.9.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +checksum = "2d6914041f254d6e9176c01941b21115dcfb7089e55135a35411081bd106ef3f" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.21" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" +checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17" [[package]] name = "crunchy" @@ -389,7 +391,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version", - "syn", + "syn 2.0.119", ] [[package]] @@ -406,9 +408,19 @@ checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" [[package]] name = "either" -version = "1.15.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +checksum = "9e5e8f6c15a24b9a3ee5efec809ccd006d3b30e8b3bb63c39af737c7f87daa1d" + +[[package]] +name = "either-or-both" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6717164c227120ba9ddf3e2b32305fc0122741d3ee41a54968eae7573ee01933" +dependencies = [ + "indexmap", + "serde", +] [[package]] name = "encode_unicode" @@ -440,15 +452,15 @@ checksum = "5692dd7b5a1978a5aeb0ce83b7655c58ca8efdcb79d21036ea249da95afec2c6" [[package]] name = "fastrand" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" +checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223" [[package]] name = "find-msvc-tools" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" +checksum = "26b73573e6edcd2af0cdf47bd6cb58f0b3839491263c314eaad1ccf24430e1de" [[package]] name = "flate2" @@ -460,29 +472,23 @@ dependencies = [ "miniz_oxide", ] -[[package]] -name = "foldhash" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" - [[package]] name = "futures-core" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" +checksum = "2cd50c473c80f6d7c3670a752354b8e569b1a7cbfdc0419ec88e5edad85e0dc7" [[package]] name = "futures-task" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" +checksum = "b231ed28831efb4a61a08580c4bc233ec56bc009f4cd8f52da2c3cb97df0c109" [[package]] name = "futures-util" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +checksum = "a77a90a256fce34da66415271e30f94ee91c57b04b8a2c042d9cf3220179deaa" dependencies = [ "futures-core", "futures-task", @@ -501,25 +507,23 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" dependencies = [ "cfg-if", "js-sys", "libc", "r-efi", "rand_core", - "wasip2", - "wasip3", "wasm-bindgen", ] [[package]] name = "glob" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" +checksum = "e4eba85ea1d0a966a983acd07deee566e67395d2d96b6fb39e62b5a833f1eb0b" [[package]] name = "gmp-mpfr-sys" @@ -533,9 +537,9 @@ dependencies = [ [[package]] name = "gungraun" -version = "0.19.0" +version = "0.19.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a710656785d3ed71a73a1007956874d6ebfdbc2f8660c492bb8d838c91e3f085" +checksum = "9300d38d30facf6870c15bc9e243edcc47e5ddc270c9d2c1ae824a00b1faea79" dependencies = [ "bincode-next", "derive_more", @@ -545,26 +549,27 @@ dependencies = [ [[package]] name = "gungraun-macros" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cc6269e89921872ec32af29af3a992618b9bd2ef47cbf3704af476066cb7182" +checksum = "d7f3214bae6cfd6739f4f29edb262bae439c6393a7b7b12c4eeb96417c2e50df" dependencies = [ "derive_more", - "proc-macro-error2", + "proc-macro-error3", "proc-macro2", "quote", "rustc_version", "serde", "serde_json", - "syn", + "syn 2.0.119", ] [[package]] name = "gungraun-runner" -version = "0.19.0" +version = "0.19.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12016920cc6ba0a8aefe276c8f19421a3bf7a125385e25697658b9dd66bde024" +checksum = "47c68c92812da579a2510a2cc702d5aa3251992b9662d4a98502ca46e0cbe16e" dependencies = [ + "either-or-both", "serde", ] @@ -581,18 +586,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.5" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" -dependencies = [ - "foldhash", -] - -[[package]] -name = "hashbrown" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" [[package]] name = "heck" @@ -600,12 +596,6 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" -[[package]] -name = "id-arena" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" - [[package]] name = "indexmap" version = "2.14.0" @@ -613,16 +603,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown 0.17.0", - "serde", - "serde_core", + "hashbrown", ] [[package]] name = "indicatif" -version = "0.18.4" +version = "0.18.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25470f23803092da7d239834776d653104d551bc4d7eacaf31e6837854b8e9eb" +checksum = "9433806cd6b4ec1aba79c021c7e4c58fb4c3b9977c085062e611ac929998fb0c" dependencies = [ "console", "portable-atomic", @@ -653,27 +641,20 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "js-sys" -version = "0.3.97" +version = "0.3.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1840c94c045fbcf8ba2812c95db44499f7c64910a912551aaaa541decebcacf" +checksum = "0e0c1080212aad755ea003d18543e8768dd432c48819efd73a7bf1e39b7a5a3a" dependencies = [ "cfg-if", "futures-util", - "once_cell", "wasm-bindgen", ] -[[package]] -name = "leb128fmt" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" - [[package]] name = "libc" -version = "0.2.186" +version = "0.2.189" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" +checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" [[package]] name = "libm" @@ -696,7 +677,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn", + "syn 3.0.3", ] [[package]] @@ -740,17 +721,11 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" -[[package]] -name = "log" -version = "0.4.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" - [[package]] name = "memchr" -version = "2.8.0" +version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" +checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" [[package]] name = "miniz_oxide" @@ -772,13 +747,13 @@ dependencies = [ [[package]] name = "no-panic" -version = "0.1.36" +version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f967505aabc8af5752d098c34146544a43684817cdba8f9725b292530cabbf53" +checksum = "fc80370b4544f28ffa317e3c3474ee3ecbfe269196c01ae657d9f837a7d944a1" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 3.0.3", ] [[package]] @@ -792,14 +767,14 @@ dependencies = [ [[package]] name = "object" -version = "0.39.1" +version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e5a6c098c7a3b6547378093f5cc30bc54fd361ce711e05293a5cc589562739b" +checksum = "dd229a0361b9d0d4396176e02d65897f487eebeab7caa6d443855ee152ca0b9c" dependencies = [ "flate2", "memchr", "ruzstd", - "wasmparser 0.247.0", + "wasmparser", ] [[package]] @@ -840,6 +815,12 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +[[package]] +name = "pastey" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ee67f1008b1ba2321834326597b8e186293b049a023cdef258527550b9935b4" + [[package]] name = "pin-project-lite" version = "0.2.17" @@ -876,9 +857,9 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.13.1" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" +checksum = "05c8b63e8d9609db387f0324918f81d68fe27748f084ef092fb35954d0539a85" [[package]] name = "ppv-lite86" @@ -927,51 +908,41 @@ dependencies = [ ] [[package]] -name = "prettyplease" -version = "0.2.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" -dependencies = [ - "proc-macro2", - "syn", -] - -[[package]] -name = "proc-macro-error-attr2" -version = "2.0.0" +name = "proc-macro-error-attr3" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" +checksum = "b0084e6206a967a2dad822180626b2f6b07a3b379325e8f1ec0438e33a469ba7" dependencies = [ "proc-macro2", "quote", ] [[package]] -name = "proc-macro-error2" -version = "2.0.1" +name = "proc-macro-error3" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" +checksum = "0cf066225f2373bc711684792b69bdeac0356019b007e721090c24d92d5d5a50" dependencies = [ - "proc-macro-error-attr2", + "proc-macro-error-attr3", "proc-macro2", "quote", - "syn", + "syn 3.0.3", ] [[package]] name = "proc-macro2" -version = "1.0.106" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.45" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" dependencies = [ "proc-macro2", ] @@ -984,9 +955,9 @@ checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" [[package]] name = "rand" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" +checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80" dependencies = [ "chacha20", "getrandom", @@ -1011,13 +982,22 @@ checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" [[package]] name = "rand_xoshiro" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f0b2cc7bfeef8f0320ca45f88b00157a03c67137022d59393614352d6bf4312" +checksum = "662effc7698e08ea324d3acccf8d9d7f7bf79b9785e270a174ea36e56900c91d" dependencies = [ "rand_core", ] +[[package]] +name = "rapidhash" +version = "4.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5da7e78a036ce858e8d55b7e7dc8ba3a88b78350fd2155d3591bbd966b58589e" +dependencies = [ + "rustversion", +] + [[package]] name = "rayon" version = "1.12.0" @@ -1040,9 +1020,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.12.3" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" +checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d" dependencies = [ "aho-corasick", "memchr", @@ -1052,9 +1032,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.14" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2" dependencies = [ "aho-corasick", "memchr", @@ -1063,9 +1043,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" [[package]] name = "rug" @@ -1113,15 +1093,15 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" +checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" [[package]] name = "ruzstd" -version = "0.8.2" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ff0cc5e135c8870a775d3320910cd9b564ec036b4dc0b8741629020be63f01" +checksum = "a252f5e20f038fe7b4ea53e073e65398d652c864cc162fc77c56c2f13717b888" dependencies = [ "twox-hash", ] @@ -1143,9 +1123,9 @@ checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" [[package]] name = "serde" -version = "1.0.228" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" dependencies = [ "serde_core", "serde_derive", @@ -1153,29 +1133,29 @@ dependencies = [ [[package]] name = "serde_core" -version = "1.0.228" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.228" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 3.0.3", ] [[package]] name = "serde_json" -version = "1.0.149" +version = "1.0.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" +checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" dependencies = [ "itoa", "memchr", @@ -1186,15 +1166,15 @@ dependencies = [ [[package]] name = "shlex" -version = "1.3.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" [[package]] name = "simd-adler32" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" +checksum = "3a219298ac11a56ea9a6d2120044824d6f01aeb034955e7af7bc16858527deea" [[package]] name = "slab" @@ -1204,9 +1184,9 @@ checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smallvec" -version = "1.15.1" +version = "1.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" [[package]] name = "strsim" @@ -1215,7 +1195,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] -name = "symbol-check" +name = "symcheck" version = "0.1.0" dependencies = [ "assert_cmd", @@ -1229,9 +1209,20 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.117" +version = "2.0.119" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3" dependencies = [ "proc-macro2", "quote", @@ -1269,9 +1260,9 @@ dependencies = [ [[package]] name = "twox-hash" -version = "2.1.2" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ea3136b675547379c4bd395ca6b938e5ad3c3d20fad76e7fe85f9e0d011419c" +checksum = "8464ec13c3691491391d9fce00f6416c9a48e46972f72d7865688be2080192c9" [[package]] name = "unicode-ident" @@ -1285,12 +1276,6 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" -[[package]] -name = "unicode-xid" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" - [[package]] name = "unit-prefix" version = "0.5.2" @@ -1299,9 +1284,9 @@ checksum = "81e544489bf3d8ef66c953931f56617f423cd4b5494be343d9b9d3dda037b9a3" [[package]] name = "unty-next" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa66022bbd1ab992fad72bdedcfd07a0023b6f5ecc83d50121e39e3a3caed41" +checksum = "16062d030850f35054e37746427b9febb74a2f24c9c6dd6fa2d0c13c5f53221e" [[package]] name = "update-api-list" @@ -1324,7 +1309,6 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" name = "util" version = "0.1.0" dependencies = [ - "cfg-if", "libm 0.2.16", "libm-macros", "libm-test", @@ -1351,29 +1335,11 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "wasip2" -version = "1.0.3+wasi-0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" -dependencies = [ - "wit-bindgen 0.57.1", -] - -[[package]] -name = "wasip3" -version = "0.4.0+wasi-0.3.0-rc-2026-01-06" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" -dependencies = [ - "wit-bindgen 0.51.0", -] - [[package]] name = "wasm-bindgen" -version = "0.2.120" +version = "0.2.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df52b6d9b87e0c74c9edfa1eb2d9bf85e5d63515474513aa50fa181b3c4f5db1" +checksum = "1b70935747edd64d89de3efa29d73789b806c15798f8e7dca4d8ac356b50ce70" dependencies = [ "cfg-if", "once_cell", @@ -1384,9 +1350,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.120" +version = "0.2.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b1041f495fb322e64aca85f5756b2172e35cd459376e67f2a6c9dffcedb103" +checksum = "77775f8f3f7217702089053b94958f8f54061a3f663417df76e19cbdcca29bc1" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1394,74 +1360,40 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.120" +version = "0.2.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dcd0ff20416988a18ac686d4d4d0f6aae9ebf08a389ff5d29012b05af2a1b41" +checksum = "e11d33f857dc2fb11b8bc75aee111aa9cbeb12cd9f25efd3d4c2a3dd4e235284" dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn", + "syn 2.0.119", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.120" +version = "0.2.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49757b3c82ebf16c57d69365a142940b384176c24df52a087fb748e2085359ea" +checksum = "7ef64dbcc55df09c7e5a46182d181c2cfa3e925f3da937ea764728b4bbb9dcbf" dependencies = [ "unicode-ident", ] -[[package]] -name = "wasm-encoder" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" -dependencies = [ - "leb128fmt", - "wasmparser 0.244.0", -] - -[[package]] -name = "wasm-metadata" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" -dependencies = [ - "anyhow", - "indexmap", - "wasm-encoder", - "wasmparser 0.244.0", -] - [[package]] name = "wasmparser" -version = "0.244.0" +version = "0.255.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" -dependencies = [ - "bitflags", - "hashbrown 0.15.5", - "indexmap", - "semver", -] - -[[package]] -name = "wasmparser" -version = "0.247.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e6fb4c2bee46c5ea4d40f8cdb5c131725cd976718ec56f1c8e82fbde5fa2a80" +checksum = "e8e329ef4b5d46e73b91d3ac6924417cad55a8cbbf869c199283383427c3320b" dependencies = [ "bitflags", ] [[package]] name = "web-sys" -version = "0.3.97" +version = "0.3.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eadbac71025cd7b0834f20d1fe8472e8495821b4e9801eb0a60bd1f19827602" +checksum = "c435338968042f4f59a557f690a253676d47ce13ceb55d70100e7facf6620a30" dependencies = [ "js-sys", "wasm-bindgen", @@ -1523,100 +1455,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "wit-bindgen" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" -dependencies = [ - "wit-bindgen-rust-macro", -] - -[[package]] -name = "wit-bindgen" -version = "0.57.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" - -[[package]] -name = "wit-bindgen-core" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" -dependencies = [ - "anyhow", - "heck", - "wit-parser", -] - -[[package]] -name = "wit-bindgen-rust" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" -dependencies = [ - "anyhow", - "heck", - "indexmap", - "prettyplease", - "syn", - "wasm-metadata", - "wit-bindgen-core", - "wit-component", -] - -[[package]] -name = "wit-bindgen-rust-macro" -version = "0.51.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" -dependencies = [ - "anyhow", - "prettyplease", - "proc-macro2", - "quote", - "syn", - "wit-bindgen-core", - "wit-bindgen-rust", -] - -[[package]] -name = "wit-component" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" -dependencies = [ - "anyhow", - "bitflags", - "indexmap", - "log", - "serde", - "serde_derive", - "serde_json", - "wasm-encoder", - "wasm-metadata", - "wasmparser 0.244.0", - "wit-parser", -] - -[[package]] -name = "wit-parser" -version = "0.244.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" -dependencies = [ - "anyhow", - "id-arena", - "indexmap", - "log", - "semver", - "serde", - "serde_derive", - "serde_json", - "unicode-xid", - "wasmparser 0.244.0", -] - [[package]] name = "yansi" version = "1.0.1" @@ -1625,26 +1463,26 @@ checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" [[package]] name = "zerocopy" -version = "0.8.48" +version = "0.8.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" +checksum = "556764e583adb45a9f8d413c2a147fa7e8d821e48e12b14fd560b607998b75eb" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.48" +version = "0.8.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" +checksum = "f2ab42fc20575779bd240faa45f94a74256f755c0fa9e89f0ede20d91d0cdfc1" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.119", ] [[package]] name = "zmij" -version = "1.0.21" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" +checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" diff --git a/library/compiler-builtins/Cargo.toml b/library/compiler-builtins/Cargo.toml index ceff63ac930a2..423adfbcbd02c 100644 --- a/library/compiler-builtins/Cargo.toml +++ b/library/compiler-builtins/Cargo.toml @@ -7,7 +7,7 @@ members = [ "crates/libm-macros", "crates/musl-math-sys", "crates/panic-handler", - "crates/symbol-check", + "crates/symcheck", "crates/update-api-list", "crates/util", "libm", @@ -39,7 +39,6 @@ anyhow = "1.0.101" api-list-common = { path = "crates/api-list-common" } assert_cmd = "2.1.2" cc = "1.2.56" -cfg-if = "1.0.4" compiler_builtins = { path = "builtins-shim", default-features = false } criterion = { version = "0.8.2", default-features = false, features = ["cargo_bench_support"] } getopts = "0.2.24" @@ -55,7 +54,7 @@ libm-test = { path = "libm-test", default-features = false } libtest-mimic = "0.8.1" musl-math-sys = { path = "crates/musl-math-sys" } no-panic = "0.1.36" -object = { version = "0.39.0", features = ["wasm"] } +object = { version = "0.40.0", features = ["wasm"] } panic-handler = { path = "crates/panic-handler" } paste = "1.0.15" pretty_assertions = "1.4.1" @@ -69,7 +68,7 @@ regex = "1.12.3" rug = { version = "1.28.1", default-features = false, features = ["float", "integer", "std"] } rustc_apfloat = "0.2.3" serde_json = "1.0.149" -syn = "2.0.115" +syn = "3.0.3" tempfile = "3.25.0" [profile.release] diff --git a/library/compiler-builtins/builtins-test-intrinsics/Cargo.lock b/library/compiler-builtins/builtins-test-intrinsics/Cargo.lock new file mode 100644 index 0000000000000..5f3754a2de305 --- /dev/null +++ b/library/compiler-builtins/builtins-test-intrinsics/Cargo.lock @@ -0,0 +1,71 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "builtins-test-intrinsics" +version = "0.1.0" +dependencies = [ + "compiler_builtins", + "panic-handler", + "test", + "utest-cortex-m-qemu", + "utest-macros", +] + +[[package]] +name = "cc" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d262e149917187838d5b42777c8253bcb64500067342904e7d429499a6f277e" +dependencies = [ + "find-msvc-tools", + "shlex", +] + +[[package]] +name = "compiler_builtins" +version = "0.1.160" +dependencies = [ + "cc", +] + +[[package]] +name = "find-msvc-tools" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b73573e6edcd2af0cdf47bd6cb58f0b3839491263c314eaad1ccf24430e1de" + +[[package]] +name = "panic-handler" +version = "0.1.0" + +[[package]] +name = "sc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "010e18bd3bfd1d45a7e666b236c78720df0d9a7698ebaa9c1c559961eb60a38b" + +[[package]] +name = "shlex" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" + +[[package]] +name = "test" +version = "0.1.0" +source = "git+https://github.com/japaric/utest#e32073e2b078e3bee46001c13ae4c1acf368d762" + +[[package]] +name = "utest-cortex-m-qemu" +version = "0.1.0" +source = "git+https://github.com/japaric/utest#e32073e2b078e3bee46001c13ae4c1acf368d762" +dependencies = [ + "sc", +] + +[[package]] +name = "utest-macros" +version = "0.1.0" +source = "git+https://github.com/japaric/utest#e32073e2b078e3bee46001c13ae4c1acf368d762" diff --git a/library/compiler-builtins/builtins-test/src/lib.rs b/library/compiler-builtins/builtins-test/src/lib.rs index 70478f5f6d745..56c04e551df9d 100644 --- a/library/compiler-builtins/builtins-test/src/lib.rs +++ b/library/compiler-builtins/builtins-test/src/lib.rs @@ -1,6 +1,6 @@ //! This crate is for integration testing and fuzz testing of functions in `compiler-builtins`. This //! includes publicly documented intrinsics and some internal alternative implementation functions -//! such as `usize_leading_zeros_riscv` (which are tested because they are configured for +//! such as `usize_leading_zeros_condset` (which are tested because they are configured for //! architectures not tested by the CI). //! //! The general idea is to use a combination of edge case testing and randomized fuzz testing. The diff --git a/library/compiler-builtins/builtins-test/tests/misc.rs b/library/compiler-builtins/builtins-test/tests/misc.rs index 64a9d56f36b33..a637cb71189e5 100644 --- a/library/compiler-builtins/builtins-test/tests/misc.rs +++ b/library/compiler-builtins/builtins-test/tests/misc.rs @@ -65,7 +65,7 @@ fn fuzz_values() { #[test] fn leading_zeros() { - use compiler_builtins::int::leading_zeros::{leading_zeros_default, leading_zeros_riscv}; + use compiler_builtins::int::leading_zeros::{leading_zeros_condset, leading_zeros_default}; { use compiler_builtins::int::leading_zeros::__clzsi2; fuzz(N, |x: u32| { @@ -75,7 +75,7 @@ fn leading_zeros() { let lz = x.leading_zeros() as usize; let lz0 = __clzsi2(x); let lz1 = leading_zeros_default(x); - let lz2 = leading_zeros_riscv(x); + let lz2 = leading_zeros_condset(x); if lz0 != lz { panic!("__clzsi2({x}): std: {lz}, builtins: {lz0}"); } @@ -83,7 +83,7 @@ fn leading_zeros() { panic!("leading_zeros_default({x}): std: {lz}, builtins: {lz1}"); } if lz2 != lz { - panic!("leading_zeros_riscv({x}): std: {lz}, builtins: {lz2}"); + panic!("leading_zeros_condset({x}): std: {lz}, builtins: {lz2}"); } }); } @@ -97,7 +97,7 @@ fn leading_zeros() { let lz = x.leading_zeros() as usize; let lz0 = __clzdi2(x); let lz1 = leading_zeros_default(x); - let lz2 = leading_zeros_riscv(x); + let lz2 = leading_zeros_condset(x); if lz0 != lz { panic!("__clzdi2({x}): std: {lz}, builtins: {lz0}"); } @@ -105,7 +105,7 @@ fn leading_zeros() { panic!("leading_zeros_default({x}): std: {lz}, builtins: {lz1}"); } if lz2 != lz { - panic!("leading_zeros_riscv({x}): std: {lz}, builtins: {lz2}"); + panic!("leading_zeros_condset({x}): std: {lz}, builtins: {lz2}"); } }); } diff --git a/library/compiler-builtins/ci/bench-icount.sh b/library/compiler-builtins/ci/bench-icount.sh index cd36303ca316a..ac86453bceb18 100755 --- a/library/compiler-builtins/ci/bench-icount.sh +++ b/library/compiler-builtins/ci/bench-icount.sh @@ -13,6 +13,7 @@ fi # Print machine information uname -a lscpu || true +rustc -Vv gungraun_home="gungraun-home" diff --git a/library/compiler-builtins/ci/ci-util.py b/library/compiler-builtins/ci/ci-util.py index f359c59797448..97f563dbd6230 100755 --- a/library/compiler-builtins/ci/ci-util.py +++ b/library/compiler-builtins/ci/ci-util.py @@ -229,12 +229,21 @@ def _init_change_list(self): assert len(parents) == 2, f"expected two-parent merge but got:\n{parents}" base = parents[0].strip() incoming = parents[1].strip() - eprint(f"base: {base}, incoming: {incoming}") + + merge_base = sp.check_output( + GIT + ["merge-base", base, incoming], text=True + ).strip() + eprint(f"merge base: {merge_base}") + textlist = sp.check_output( - GIT + ["diff", base, incoming, "--name-only"], text=True + GIT + ["diff", merge_base, incoming, "--name-only"], text=True ) self.changed = [Path(p) for p in textlist.splitlines()] + eprint("all changed: [") + for f in self.changed: + eprint(f" {f},") + eprint("]") def is_pr(self) -> bool: """Check if we are looking at a PR rather than a push.""" @@ -304,7 +313,7 @@ def emit_workflow_output(self): eprint("Skipping all extensive tests") changed = self.changed_routines() - eprint(f"Changed: {changed}") + eprint(f"changed routines: {changed}") matrix = [] total_to_test = 0 diff --git a/library/compiler-builtins/ci/compiler-rt-patches/0001-compiler-rt-Disable-executable-stack-on-aeabi_u-read.patch b/library/compiler-builtins/ci/compiler-rt-patches/0001-compiler-rt-Disable-executable-stack-on-aeabi_u-read.patch new file mode 100644 index 0000000000000..13f4bc31d08f7 --- /dev/null +++ b/library/compiler-builtins/ci/compiler-rt-patches/0001-compiler-rt-Disable-executable-stack-on-aeabi_u-read.patch @@ -0,0 +1,95 @@ +From 849c51e082b0958524246a0a880f46d468a55147 Mon Sep 17 00:00:00 2001 +From: Trevor Gross +Date: Thu, 6 Aug 2026 09:08:27 -0400 +Subject: [PATCH] [compiler-rt] Disable executable stack on + `aeabi_u{read,write}*.S` (#214465) + +These were missing `NO_EXEC_STACK_DIRECTIVE` to add `.note.GNU-stack`; +without it, a binary including any of these files will have the stack +marked executable. Add the directive here, matching other similar files. + +Symtab diff before: + +$ clang compiler-rt/lib/builtins/arm/aeabi_uread4.S +--target=arm-unknown-linux-gnueabi -c + $ llvm-readelf aeabi_uread4.o -S + There are 5 section headers, starting at offset 0xe4: + + Section Headers: +[Nr] Name Type Address Off Size ES Flg Lk Inf Al +[ 0] NULL 00000000 000000 000000 00 0 0 0 +[ 1] .strtab STRTAB 00000000 0000a8 000039 00 0 0 1 +[ 2] .text PROGBITS 00000000 000034 000020 00 AX 0 0 4 +[ 3] .ARM.attributes ARM_ATTRIBUTES 00000000 000054 000022 00 0 0 1 +[ 4] .symtab SYMTAB 00000000 000078 000030 10 1 2 4 + +After: + +$ clang compiler-rt/lib/builtins/arm/aeabi_uread4.S +--target=arm-unknown-linux-gnueabi -c + $ llvm-readelf aeabi_uread4.o -S + There are 6 section headers, starting at offset 0xf4: + + Section Headers: +[Nr] Name Type Address Off Size ES Flg Lk Inf Al +[ 0] NULL 00000000 000000 000000 00 0 0 0 +[ 1] .strtab STRTAB 00000000 0000a8 000049 00 0 0 1 +[ 2] .text PROGBITS 00000000 000034 000020 00 AX 0 0 4 +[ 3] .note.GNU-stack PROGBITS 00000000 000054 000000 00 0 0 1 +[ 4] .ARM.attributes ARM_ATTRIBUTES 00000000 000054 000022 00 0 0 1 +[ 5] .symtab SYMTAB 00000000 000078 000030 10 1 2 4 + +Fixes: 39413af931a7 ("[Compiler-rt] Implement AEABI Unaligned Read/Write + Helpers in compiler-rt (#167913)") +--- + +Add this patch to avoid a symcheck failure until the LLVM update can work +through. + + compiler-rt/lib/builtins/arm/aeabi_uread4.S | 1 + + compiler-rt/lib/builtins/arm/aeabi_uread8.S | 2 ++ + compiler-rt/lib/builtins/arm/aeabi_uwrite4.S | 2 ++ + compiler-rt/lib/builtins/arm/aeabi_uwrite8.S | 2 ++ + 4 files changed, 7 insertions(+) + +diff --git a/compiler-rt/lib/builtins/arm/aeabi_uread4.S b/compiler-rt/lib/builtins/arm/aeabi_uread4.S +index 4a54890fdf83..05e476a17905 100644 +--- a/compiler-rt/lib/builtins/arm/aeabi_uread4.S ++++ b/compiler-rt/lib/builtins/arm/aeabi_uread4.S +@@ -61,3 +61,4 @@ DEFINE_COMPILERRT_FUNCTION(__aeabi_uread4) + #endif + END_COMPILERRT_FUNCTION(__aeabi_uread4) + ++NO_EXEC_STACK_DIRECTIVE +diff --git a/compiler-rt/lib/builtins/arm/aeabi_uread8.S b/compiler-rt/lib/builtins/arm/aeabi_uread8.S +index 32844b8b3c7e..0b12c48ae46f 100644 +--- a/compiler-rt/lib/builtins/arm/aeabi_uread8.S ++++ b/compiler-rt/lib/builtins/arm/aeabi_uread8.S +@@ -98,3 +98,5 @@ DEFINE_COMPILERRT_FUNCTION(__aeabi_uread8) + #endif + + END_COMPILERRT_FUNCTION(__aeabi_uread8) ++ ++NO_EXEC_STACK_DIRECTIVE +diff --git a/compiler-rt/lib/builtins/arm/aeabi_uwrite4.S b/compiler-rt/lib/builtins/arm/aeabi_uwrite4.S +index 9f749695910b..7e9a0337b781 100644 +--- a/compiler-rt/lib/builtins/arm/aeabi_uwrite4.S ++++ b/compiler-rt/lib/builtins/arm/aeabi_uwrite4.S +@@ -33,3 +33,5 @@ DEFINE_COMPILERRT_FUNCTION(__aeabi_uwrite4) + #endif + bx lr + END_COMPILERRT_FUNCTION(__aeabi_uwrite4) ++ ++NO_EXEC_STACK_DIRECTIVE +diff --git a/compiler-rt/lib/builtins/arm/aeabi_uwrite8.S b/compiler-rt/lib/builtins/arm/aeabi_uwrite8.S +index 8188032fc3bd..763f42ff7ed0 100644 +--- a/compiler-rt/lib/builtins/arm/aeabi_uwrite8.S ++++ b/compiler-rt/lib/builtins/arm/aeabi_uwrite8.S +@@ -49,3 +49,5 @@ DEFINE_COMPILERRT_FUNCTION(__aeabi_uwrite8) + #endif + bx lr + END_COMPILERRT_FUNCTION(__aeabi_uwrite8) ++ ++NO_EXEC_STACK_DIRECTIVE +-- +2.50.1 (Apple Git-155) diff --git a/library/compiler-builtins/ci/download-compiler-rt.sh b/library/compiler-builtins/ci/download-compiler-rt.sh index 87b337d8255bb..55498c61d54b4 100755 --- a/library/compiler-builtins/ci/download-compiler-rt.sh +++ b/library/compiler-builtins/ci/download-compiler-rt.sh @@ -4,7 +4,13 @@ set -eux -rust_llvm_version=20.1-2025-02-13 +rust_llvm_version=23.1-2026-07-22 curl -L --retry 3 -o code.tar.gz "https://github.com/rust-lang/llvm-project/archive/rustc/${rust_llvm_version}.tar.gz" tar xzf code.tar.gz --strip-components 1 llvm-project-rustc-${rust_llvm_version}/compiler-rt + +cd compiler-rt + +for p in ../ci/compiler-rt-patches/*; do + cat "$p" | patch -p 2 +done diff --git a/library/compiler-builtins/ci/miri.sh b/library/compiler-builtins/ci/miri.sh index 2751bf0dc49e1..498bbe3c47f00 100755 --- a/library/compiler-builtins/ci/miri.sh +++ b/library/compiler-builtins/ci/miri.sh @@ -1,9 +1,11 @@ #!/bin/bash set -eux +# We need to disable the randomness that Miri intentionally introduces when +# performing floating-point operations # We need Tree Borrows as some of our raw pointer patterns are not # compatible with Stacked Borrows. -export MIRIFLAGS="-Zmiri-tree-borrows" +export MIRIFLAGS="-Zmiri-deterministic-floats -Zmiri-tree-borrows" # One target that sets `mem_unaligned` and one that does not, # and a big-endian target. @@ -20,4 +22,10 @@ for target in "${targets[@]}"; do --no-default-features \ --target "$target" \ -- mem + + # Run the `libm` tests as well, but not `libm-test` to avoid this taking + # too long. + cargo miri test \ + --manifest-path libm/Cargo.toml \ + --target "$target" done diff --git a/library/compiler-builtins/ci/run-docker.sh b/library/compiler-builtins/ci/run-docker.sh index a894677b59f90..08f20b934acd5 100755 --- a/library/compiler-builtins/ci/run-docker.sh +++ b/library/compiler-builtins/ci/run-docker.sh @@ -11,8 +11,6 @@ host_arch="$(uname -m | sed 's/arm64/aarch64/')" # calling docker, otherwise docker will create them but they will be owned # by root. mkdir -p target -cargo generate-lockfile -cargo generate-lockfile --manifest-path builtins-test-intrinsics/Cargo.toml run() { local target="$1" diff --git a/library/compiler-builtins/ci/run.sh b/library/compiler-builtins/ci/run.sh index 93c551dc52ec7..359bf3d945b9b 100755 --- a/library/compiler-builtins/ci/run.sh +++ b/library/compiler-builtins/ci/run.sh @@ -13,6 +13,12 @@ if [ -z "$target" ]; then target="$host_target" fi +# Print machine information +uname -a +lscpu || true +rustc -Vv +cc -v || true + if [ "${USING_CONTAINER_RUSTC:-}" = 1 ]; then # Install nonstandard components if we have control of the environment rustup target list --installed | @@ -72,8 +78,8 @@ fi # Ensure there are no duplicate symbols or references to `core` when # `compiler-builtins` is built with various features. Symcheck invokes Cargo to # build with the arguments we provide it, then validates the built artifacts. -SYMCHECK_TEST_TARGET="$target" cargo test -p symbol-check --release -symcheck=(cargo run -p symbol-check --release) +SYMCHECK_TEST_TARGET="$target" cargo test -p symcheck --release +symcheck=(cargo run -p symcheck --release) symcheck+=(-- --build-and-check --target "$target") # Executable section checks are meaningless on no-std targets @@ -145,10 +151,6 @@ case "$target" in # We can build musl on MinGW but running tests gets a stack overflow *windows-gnu*) ;; - # FIXME(#309): LE PPC crashes calling the musl version of some functions. It - # seems like a qemu bug but should be investigated further at some point. - # See . - *powerpc64le*) ;; # Everything else gets musl enabled *) mflags+=(--features libm-test/build-musl) ;; @@ -184,7 +186,7 @@ if [ "${BUILD_ONLY:-}" = "1" ]; then echo "can't run tests on $target; skipping" else # symcheck tests need specific env setup, and is already tested above - mflags+=(--workspace --exclude symbol-check --target "$target") + mflags+=(--workspace --exclude symcheck --target "$target") cmd=("${test_runner[@]}" "${mflags[@]}") # Test once without intrinsics diff --git a/library/compiler-builtins/compiler-builtins/src/arm.rs b/library/compiler-builtins/compiler-builtins/src/arm.rs index f26fce2d912b6..0c15b37df1dc1 100644 --- a/library/compiler-builtins/compiler-builtins/src/arm.rs +++ b/library/compiler-builtins/compiler-builtins/src/arm.rs @@ -84,11 +84,7 @@ intrinsics! { /// /// Usual `memcpy` requirements apply. #[cfg(not(target_vendor = "apple"))] - pub unsafe extern "aapcs" fn __aeabi_memcpy( - dst: *mut core::ffi::c_void, - src: *const core::ffi::c_void, - n: usize - ) { + pub unsafe extern "aapcs" fn __aeabi_memcpy(dst: *mut u8, src: *const u8, n: usize) { // SAFETY: memcpy preconditions apply. unsafe { crate::mem::memcpy(dst, src, n) }; } @@ -100,11 +96,7 @@ intrinsics! { /// Usual `memcpy` requirements apply. Additionally, `dest` and `src` must be aligned to /// four bytes. #[cfg(not(target_vendor = "apple"))] - pub unsafe extern "aapcs" fn __aeabi_memcpy4( - dst: *mut core::ffi::c_void, - src: *const core::ffi::c_void, - n: usize - ) { + pub unsafe extern "aapcs" fn __aeabi_memcpy4(dst: *mut u8, src: *const u8, n: usize) { // We are guaranteed 4-alignment, so accessing at u32 is okay. let mut dst = dst.cast::(); let mut src = src.cast::(); @@ -129,7 +121,7 @@ intrinsics! { } // SAFETY: `dst` and `src` will still be valid for `n` bytes - unsafe { __aeabi_memcpy(dst.cast::(), src.cast::(), n) }; + unsafe { __aeabi_memcpy(dst.cast::(), src.cast::(), n) }; } /// `memcpy` for 8-byte alignment. @@ -139,11 +131,7 @@ intrinsics! { /// Usual `memcpy` requirements apply. Additionally, `dest` and `src` must be aligned to /// eight bytes. #[cfg(not(target_vendor = "apple"))] - pub unsafe extern "aapcs" fn __aeabi_memcpy8( - dst: *mut core::ffi::c_void, - src: *const core::ffi::c_void, - n: usize - ) { + pub unsafe extern "aapcs" fn __aeabi_memcpy8(dst: *mut u8, src: *const u8, n: usize) { debug_assert!(dst.addr().is_multiple_of(8)); debug_assert!(src.addr().is_multiple_of(8)); @@ -157,11 +145,7 @@ intrinsics! { /// /// Usual `memmove` requirements apply. #[cfg(not(target_vendor = "apple"))] - pub unsafe extern "aapcs" fn __aeabi_memmove( - dst: *mut core::ffi::c_void, - src: *const core::ffi::c_void, - n: usize - ) { + pub unsafe extern "aapcs" fn __aeabi_memmove(dst: *mut u8, src: *const u8, n: usize) { // SAFETY: memmove preconditions apply. unsafe { crate::mem::memmove(dst, src, n) }; } @@ -173,11 +157,7 @@ intrinsics! { /// Usual `memmove` requirements apply. Additionally, `dest` and `src` must be aligned to /// four bytes. #[cfg(not(any(target_vendor = "apple", target_env = "msvc")))] - pub unsafe extern "aapcs" fn __aeabi_memmove4( - dst: *mut core::ffi::c_void, - src: *const core::ffi::c_void, - n: usize - ) { + pub unsafe extern "aapcs" fn __aeabi_memmove4(dst: *mut u8, src: *const u8, n: usize) { debug_assert!(dst.addr().is_multiple_of(4)); debug_assert!(src.addr().is_multiple_of(4)); @@ -192,11 +172,7 @@ intrinsics! { /// Usual `memmove` requirements apply. Additionally, `dst` and `src` must be aligned to /// eight bytes. #[cfg(not(any(target_vendor = "apple", target_env = "msvc")))] - pub unsafe extern "aapcs" fn __aeabi_memmove8( - dst: *mut core::ffi::c_void, - src: *const core::ffi::c_void, - n: usize - ) { + pub unsafe extern "aapcs" fn __aeabi_memmove8(dst: *mut u8, src: *const u8, n: usize) { debug_assert!(dst.addr().is_multiple_of(8)); debug_assert!(src.addr().is_multiple_of(8)); @@ -210,11 +186,7 @@ intrinsics! { /// /// Usual `memset` requirements apply. #[cfg(not(target_vendor = "apple"))] - pub unsafe extern "aapcs" fn __aeabi_memset( - dst: *mut core::ffi::c_void, - n: usize, - c: i32 - ) { + pub unsafe extern "aapcs" fn __aeabi_memset(dst: *mut u8, n: usize, c: i32) { // Note the different argument order // SAFETY: memset preconditions apply. unsafe { crate::mem::memset(dst, c, n) }; @@ -227,11 +199,7 @@ intrinsics! { /// Usual `memset` requirements apply. Additionally, `dest` and `src` must be aligned to /// four bytes. #[cfg(not(target_vendor = "apple"))] - pub unsafe extern "aapcs" fn __aeabi_memset4( - dst: *mut core::ffi::c_void, - n: usize, - c: i32 - ) { + pub unsafe extern "aapcs" fn __aeabi_memset4(dst: *mut u8, n: usize, c: i32) { let mut dst = dst.cast::(); debug_assert!(dst.is_aligned()); let mut n = n; @@ -254,7 +222,7 @@ intrinsics! { } // SAFETY: `dst` will still be valid for `n` bytes - unsafe { __aeabi_memset(dst.cast::(), n, byte as i32) }; + unsafe { __aeabi_memset(dst.cast::(), n, byte as i32) }; } /// `memset` for 8-byte alignment. @@ -264,11 +232,7 @@ intrinsics! { /// Usual `memset` requirements apply. Additionally, `dst` and `src` must be aligned to /// eight bytes. #[cfg(not(target_vendor = "apple"))] - pub unsafe extern "aapcs" fn __aeabi_memset8( - dst: *mut core::ffi::c_void, - n: usize, - c: i32 - ) { + pub unsafe extern "aapcs" fn __aeabi_memset8(dst: *mut u8, n: usize, c: i32) { debug_assert!(dst.addr().is_multiple_of(8)); // SAFETY: memset preconditions apply, less strict alignment. @@ -281,7 +245,7 @@ intrinsics! { /// /// Usual `memclr` requirements apply. #[cfg(not(target_vendor = "apple"))] - pub unsafe extern "aapcs" fn __aeabi_memclr(dst: *mut core::ffi::c_void, n: usize) { + pub unsafe extern "aapcs" fn __aeabi_memclr(dst: *mut u8, n: usize) { // SAFETY: memclr preconditions apply, less strict alignment. unsafe { __aeabi_memset(dst, n, 0) }; } @@ -293,7 +257,7 @@ intrinsics! { /// Usual `memclr` requirements apply. Additionally, `dest` and `src` must be aligned to /// four bytes. #[cfg(not(any(target_vendor = "apple", target_env = "msvc")))] - pub unsafe extern "aapcs" fn __aeabi_memclr4(dst: *mut core::ffi::c_void, n: usize) { + pub unsafe extern "aapcs" fn __aeabi_memclr4(dst: *mut u8, n: usize) { debug_assert!(dst.addr().is_multiple_of(4)); // SAFETY: memclr preconditions apply, less strict alignment. @@ -307,7 +271,7 @@ intrinsics! { /// Usual `memclr` requirements apply. Additionally, `dst` and `src` must be aligned to /// eight bytes. #[cfg(not(any(target_vendor = "apple", target_env = "msvc")))] - pub unsafe extern "aapcs" fn __aeabi_memclr8(dst: *mut core::ffi::c_void, n: usize) { + pub unsafe extern "aapcs" fn __aeabi_memclr8(dst: *mut u8, n: usize) { debug_assert!(dst.addr().is_multiple_of(8)); // SAFETY: memclr preconditions apply, less strict alignment. diff --git a/library/compiler-builtins/compiler-builtins/src/float/cmp.rs b/library/compiler-builtins/compiler-builtins/src/float/cmp.rs index a59365a2bdb8b..243c9c767f61b 100644 --- a/library/compiler-builtins/compiler-builtins/src/float/cmp.rs +++ b/library/compiler-builtins/compiler-builtins/src/float/cmp.rs @@ -1,6 +1,6 @@ #![allow(unreachable_code)] -use crate::support::{Float, MinInt, cfg_if}; +use crate::support::{Float, MinInt, cfg_select_nofmt}; // These definitions should be consistent with LLVM's definition from `getCmpLibcallReturnType`, // compiler-rt's definitions [1], GCC's `CMPtype` [2], and `libgcc`. To find the definitions @@ -12,15 +12,17 @@ use crate::support::{Float, MinInt, cfg_if}; // // [1]: https://github.com/llvm/llvm-project/blob/0cf3c437c18ed27d9663d87804a9a15ff6874af2/compiler-rt/lib/builtins/fp_compare_impl.inc#L11-L27 // [2]: https://gcc.gnu.org/onlinedocs/gccint/Soft-float-library-routines.html#Comparison-functions-1 -cfg_if! { - if #[cfg(any(target_arch = "aarch64", target_arch = "arm64ec", target_family = "wasm"))] { +cfg_select_nofmt! { + any(target_arch = "aarch64", target_arch = "arm64ec", target_family = "wasm") => { // Aarch64 uses `int` rather than a pointer-sized value. // `getCmpLibcallReturnType` for WASM is always set to i32. pub type CmpResult = i32; - } else if #[cfg(target_arch = "avr")] { + } + target_arch = "avr" => { // AVR uses a single byte. pub type CmpResult = i8; - } else { + } + _ => { // The default is word-sized. In LLVM's compiler-rt, this is done by using `long long` on // LLP64 ABIs and `long` on everything else. pub type CmpResult = isize; diff --git a/library/compiler-builtins/compiler-builtins/src/hexagon.rs b/library/compiler-builtins/compiler-builtins/src/hexagon.rs index 46062fc3700d8..551186b1db861 100644 --- a/library/compiler-builtins/compiler-builtins/src/hexagon.rs +++ b/library/compiler-builtins/compiler-builtins/src/hexagon.rs @@ -44,69 +44,34 @@ intrinsics! { } } -global_asm!(include_str!("hexagon/func_macro.s"), options(raw)); - +// All hexagon assembly must live in ONE `global_asm!` invocation, and +// `func_macro.s` must come first. global_asm!( + include_str!("hexagon/func_macro.s"), include_str!("hexagon/common_entry_exit_abi1.s"), - options(raw) -); - -global_asm!( include_str!("hexagon/common_entry_exit_abi2.s"), - options(raw) -); - -global_asm!( include_str!("hexagon/common_entry_exit_legacy.s"), - options(raw) -); - -global_asm!(include_str!("hexagon/dfaddsub.s"), options(raw)); - -global_asm!(include_str!("hexagon/dfdiv.s"), options(raw)); - -global_asm!(include_str!("hexagon/dffma.s"), options(raw)); - -global_asm!(include_str!("hexagon/dfminmax.s"), options(raw)); - -global_asm!(include_str!("hexagon/dfmul.s"), options(raw)); - -global_asm!(include_str!("hexagon/dfsqrt.s"), options(raw)); - -global_asm!(include_str!("hexagon/divdi3.s"), options(raw)); - -global_asm!(include_str!("hexagon/divsi3.s"), options(raw)); - -global_asm!(include_str!("hexagon/fastmath2_dlib_asm.s"), options(raw)); - -global_asm!(include_str!("hexagon/fastmath2_ldlib_asm.s"), options(raw)); - -global_asm!( + include_str!("hexagon/dfaddsub.s"), + include_str!("hexagon/dfdiv.s"), + include_str!("hexagon/dffma.s"), + include_str!("hexagon/dfminmax.s"), + include_str!("hexagon/dfmul.s"), + include_str!("hexagon/dfsqrt.s"), + include_str!("hexagon/divdi3.s"), + include_str!("hexagon/divsi3.s"), + include_str!("hexagon/fastmath2_dlib_asm.s"), + include_str!("hexagon/fastmath2_ldlib_asm.s"), include_str!("hexagon/memcpy_forward_vp4cp4n2.s"), - options(raw) -); - -global_asm!( include_str!("hexagon/memcpy_likely_aligned.s"), + include_str!("hexagon/moddi3.s"), + include_str!("hexagon/modsi3.s"), + include_str!("hexagon/sfdiv_opt.s"), + include_str!("hexagon/sfsqrt_opt.s"), + include_str!("hexagon/udivdi3.s"), + include_str!("hexagon/udivmoddi4.s"), + include_str!("hexagon/udivmodsi4.s"), + include_str!("hexagon/udivsi3.s"), + include_str!("hexagon/umoddi3.s"), + include_str!("hexagon/umodsi3.s"), options(raw) ); - -global_asm!(include_str!("hexagon/moddi3.s"), options(raw)); - -global_asm!(include_str!("hexagon/modsi3.s"), options(raw)); - -global_asm!(include_str!("hexagon/sfdiv_opt.s"), options(raw)); - -global_asm!(include_str!("hexagon/sfsqrt_opt.s"), options(raw)); - -global_asm!(include_str!("hexagon/udivdi3.s"), options(raw)); - -global_asm!(include_str!("hexagon/udivmoddi4.s"), options(raw)); - -global_asm!(include_str!("hexagon/udivmodsi4.s"), options(raw)); - -global_asm!(include_str!("hexagon/udivsi3.s"), options(raw)); - -global_asm!(include_str!("hexagon/umoddi3.s"), options(raw)); - -global_asm!(include_str!("hexagon/umodsi3.s"), options(raw)); diff --git a/library/compiler-builtins/compiler-builtins/src/hexagon/dffma.s b/library/compiler-builtins/compiler-builtins/src/hexagon/dffma.s index 6cd1f1b79f87a..b57ed17dc1fd2 100644 --- a/library/compiler-builtins/compiler-builtins/src/hexagon/dffma.s +++ b/library/compiler-builtins/compiler-builtins/src/hexagon/dffma.s @@ -338,10 +338,8 @@ __hexagon_fmadf5: { p0 = !cmp.eq(r2,#1) p0 = !cmp.eq(r3,#2) - } - { - p0 = dfcmp.eq(r9:8,r9:8) if (p0.new) r11:10 = r9:8 + p0 = dfcmp.eq(r9:8,r9:8) } { r1:0 = insert(r11:10,#63,#0) diff --git a/library/compiler-builtins/compiler-builtins/src/int/leading_zeros.rs b/library/compiler-builtins/compiler-builtins/src/int/leading_zeros.rs index 3b920ecff6b20..c4d2569b3ab4e 100644 --- a/library/compiler-builtins/compiler-builtins/src/int/leading_zeros.rs +++ b/library/compiler-builtins/compiler-builtins/src/int/leading_zeros.rs @@ -4,9 +4,9 @@ // Compilers will insert the check for zero in cases where it is needed. #[cfg(feature = "unstable-public-internals")] -pub use implementation::{leading_zeros_default, leading_zeros_riscv}; +pub use implementation::{leading_zeros_condset, leading_zeros_default}; #[cfg(not(feature = "unstable-public-internals"))] -pub(crate) use implementation::{leading_zeros_default, leading_zeros_riscv}; +pub(crate) use implementation::{leading_zeros_condset, leading_zeros_default}; mod implementation { use crate::support::{CastFrom, Int}; @@ -82,14 +82,15 @@ mod implementation { // execution effects. Changing to using a LUT and branching is risky for smaller cores. } - // The above method does not compile well on RISC-V (because of the lack of predicated - // instructions), producing code with many branches or using an excessively long - // branchless solution. This method takes advantage of the set-if-less-than instruction on - // RISC-V that allows `(x >= power-of-two) as usize` to be branchless. + // The above method does not compile well on RISC-V and LoongArch (because of the lack + // of predicated instructions), producing code with many branches or using an + // excessively long branchless solution. This method takes advantage of the + // set-if-less-than instruction on RISC-V and LoongArch that allows + // `(x >= power-of-two) as usize` to be branchless. /// Returns the number of leading binary zeros in `x`. #[allow(dead_code)] - pub fn leading_zeros_riscv(x: I) -> usize + pub fn leading_zeros_condset(x: I) -> usize where usize: CastFrom, { @@ -99,7 +100,7 @@ mod implementation { // a temporary let mut t: u32; - // RISC-V does not have a set-if-greater-than-or-equal instruction and + // RISC-V and LoongArch do not have a set-if-greater-than-or-equal instruction and // `(x >= power-of-two) as usize` will get compiled into two instructions, but this is // still the most optimal method. A conditional set can only be turned into a single // immediate instruction if `x` is compared with an immediate `imm` (that can fit into @@ -146,8 +147,9 @@ mod implementation { intrinsics! { /// Returns the number of leading binary zeros in `x` pub extern "C" fn __clzsi2(x: u32) -> usize { - if cfg!(any(target_arch = "riscv32", target_arch = "riscv64")) { - leading_zeros_riscv(x) + if cfg!(any(target_arch = "loongarch32", target_arch = "loongarch64", + target_arch = "riscv32", target_arch = "riscv64")) { + leading_zeros_condset(x) } else { leading_zeros_default(x) } @@ -155,8 +157,9 @@ intrinsics! { /// Returns the number of leading binary zeros in `x` pub extern "C" fn __clzdi2(x: u64) -> usize { - if cfg!(any(target_arch = "riscv32", target_arch = "riscv64")) { - leading_zeros_riscv(x) + if cfg!(any(target_arch = "loongarch32", target_arch = "loongarch64", + target_arch = "riscv32", target_arch = "riscv64")) { + leading_zeros_condset(x) } else { leading_zeros_default(x) } diff --git a/library/compiler-builtins/compiler-builtins/src/int/specialized_div_rem/mod.rs b/library/compiler-builtins/compiler-builtins/src/int/specialized_div_rem/mod.rs index 902c191d65285..e5324cdbd941e 100644 --- a/library/compiler-builtins/compiler-builtins/src/int/specialized_div_rem/mod.rs +++ b/library/compiler-builtins/compiler-builtins/src/int/specialized_div_rem/mod.rs @@ -97,6 +97,13 @@ const USE_LZ: bool = { // The 'Zbb' Basic Bit-Manipulation extension on RISC-V // determines if a CLZ assembly instruction exists cfg!(target_feature = "zbb") + } else if cfg!(any( + target_arch = "loongarch32", + target_arch = "loongarch64" + )) { + // The '32s' 32-bit standard feature on LoongArch + // determines if a CLZ assembly instruction exists + cfg!(target_feature = "32s") } else { // All other common targets Rust supports should have CLZ instructions true diff --git a/library/compiler-builtins/compiler-builtins/src/lib.rs b/library/compiler-builtins/compiler-builtins/src/lib.rs index 6bde5195e8af4..829475dcd42e2 100644 --- a/library/compiler-builtins/compiler-builtins/src/lib.rs +++ b/library/compiler-builtins/compiler-builtins/src/lib.rs @@ -1,5 +1,8 @@ #![cfg_attr(feature = "compiler-builtins", compiler_builtins)] -#![cfg_attr(all(target_family = "wasm"), feature(wasm_numeric_instr))] +#![no_builtins] +#![no_std] +// +#![feature(abi_custom)] #![feature(abi_unadjusted)] #![feature(asm_experimental_arch)] #![feature(cfg_target_has_atomic)] @@ -11,8 +14,8 @@ #![feature(rustc_attrs)] #![cfg_attr(f16_enabled, feature(f16))] #![cfg_attr(f128_enabled, feature(f128))] -#![no_builtins] -#![no_std] +#![cfg_attr(all(target_family = "wasm"), feature(wasm_numeric_instr))] +// #![allow(unstable_name_collisions)] // FIXME(float_bits_const): remove when stable #![allow(unused_features)] #![allow(internal_features)] @@ -20,9 +23,6 @@ #![allow(clippy::manual_swap)] // Support compiling on both stage0 and stage1 which may differ in supported stable features. #![allow(stable_features)] -// By default, disallow this as it is forbidden in edition 2024. There is a lot of unsafe code to -// be migrated, however, so exceptions exist. -#![warn(unsafe_op_in_unsafe_fn)] // We disable #[no_mangle] for tests so that we can verify the test results // against the native compiler-rt implementations of the builtins. diff --git a/library/compiler-builtins/compiler-builtins/src/mem/mod.rs b/library/compiler-builtins/compiler-builtins/src/mem/mod.rs index ef0f4da228e96..e3c701892b671 100644 --- a/library/compiler-builtins/compiler-builtins/src/mem/mod.rs +++ b/library/compiler-builtins/compiler-builtins/src/mem/mod.rs @@ -2,6 +2,8 @@ #![allow(clippy::style)] // FIXME(e2024): this eventually needs to be removed. #![allow(unsafe_op_in_unsafe_fn)] +// FIXME(bench): remove when the benchmark rustc version is updated +#![allow(unknown_lints)] // memcpy/memmove/memset have optimized implementations on some architectures #[cfg_attr(all(feature = "arch", target_arch = "x86_64"), path = "x86_64.rs")] @@ -9,57 +11,42 @@ mod impls; intrinsics! { #[mem_builtin] - pub unsafe extern "C" fn memcpy( - dest: *mut core::ffi::c_void, - src: *const core::ffi::c_void, - n: usize - ) -> *mut core::ffi::c_void { - impls::copy_forward(dest.cast(), src.cast(), n); + #[allow(suspicious_runtime_symbol_definitions)] + pub unsafe extern "C" fn memcpy(dest: *mut u8, src: *const u8, n: usize) -> *mut u8 { + impls::copy_forward(dest, src, n); dest } #[mem_builtin] - pub unsafe extern "C" fn memmove( - dest: *mut core::ffi::c_void, - src: *const core::ffi::c_void, - n: usize - ) -> *mut core::ffi::c_void { + #[allow(suspicious_runtime_symbol_definitions)] + pub unsafe extern "C" fn memmove(dest: *mut u8, src: *const u8, n: usize) -> *mut u8 { let delta = (dest as usize).wrapping_sub(src as usize); if delta >= n { // We can copy forwards because either dest is far enough ahead of src, // or src is ahead of dest (and delta overflowed). - impls::copy_forward(dest.cast(), src.cast(), n); + impls::copy_forward(dest, src, n); } else { - impls::copy_backward(dest.cast(), src.cast(), n); + impls::copy_backward(dest, src, n); } dest } #[mem_builtin] - pub unsafe extern "C" fn memset( - s: *mut core::ffi::c_void, - c: core::ffi::c_int, - n: usize - ) -> *mut core::ffi::c_void { - impls::set_bytes(s.cast(), c as u8, n); + #[allow(suspicious_runtime_symbol_definitions)] + pub unsafe extern "C" fn memset(s: *mut u8, c: core::ffi::c_int, n: usize) -> *mut u8 { + impls::set_bytes(s, c as u8, n); s } #[mem_builtin] - pub unsafe extern "C" fn memcmp( - s1: *const core::ffi::c_void, - s2: *const core::ffi::c_void, - n: usize - ) -> core::ffi::c_int { - impls::compare_bytes(s1.cast(), s2.cast(), n) + #[allow(suspicious_runtime_symbol_definitions)] + pub unsafe extern "C" fn memcmp(s1: *const u8, s2: *const u8, n: usize) -> core::ffi::c_int { + impls::compare_bytes(s1, s2, n) } #[mem_builtin] - pub unsafe extern "C" fn bcmp( - s1: *const core::ffi::c_void, - s2: *const core::ffi::c_void, - n: usize - ) -> core::ffi::c_int { + #[allow(suspicious_runtime_symbol_definitions)] + pub unsafe extern "C" fn bcmp(s1: *const u8, s2: *const u8, n: usize) -> core::ffi::c_int { memcmp(s1, s2, n) } diff --git a/library/compiler-builtins/crates/libm-macros/src/parse.rs b/library/compiler-builtins/crates/libm-macros/src/parse.rs index 97067b876bda6..87add92996ccc 100644 --- a/library/compiler-builtins/crates/libm-macros/src/parse.rs +++ b/library/compiler-builtins/crates/libm-macros/src/parse.rs @@ -181,7 +181,6 @@ fn extract_fn_extra_field(expr: Expr) -> syn::Result> { let Arm { attrs, pat, - guard, fat_arrow_token: _, body, comma: _, @@ -190,15 +189,15 @@ fn extract_fn_extra_field(expr: Expr) -> syn::Result> { expect_empty_attrs(&attrs)?; let keys = match pat { + syn::Pat::Ident(id) => Parser::parse2(parse_ident_pat, id.into_token_stream())?, + syn::Pat::Or(or) => Parser::parse2(parse_ident_pat, or.into_token_stream())?, syn::Pat::Wild(w) => vec![Ident::new("_", w.span())], - _ => Parser::parse2(parse_ident_pat, pat.into_token_stream())?, + _ => { + let e = syn::Error::new(pat.span(), "unsupported pattern type"); + return Err(e); + } }; - if let Some(guard) = guard { - let e = syn::Error::new(guard.0.span(), "no guards allowed in this position"); - return Err(e); - } - for key in keys { let inserted = res.insert(key.clone(), *body.clone()); if inserted.is_some() { diff --git a/library/compiler-builtins/crates/symbol-check/Cargo.toml b/library/compiler-builtins/crates/symcheck/Cargo.toml similarity index 92% rename from library/compiler-builtins/crates/symbol-check/Cargo.toml rename to library/compiler-builtins/crates/symcheck/Cargo.toml index 6d13f94888004..470cb61413c38 100644 --- a/library/compiler-builtins/crates/symbol-check/Cargo.toml +++ b/library/compiler-builtins/crates/symcheck/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "symbol-check" +name = "symcheck" version = "0.1.0" edition = "2024" publish = false diff --git a/library/compiler-builtins/crates/symbol-check/build.rs b/library/compiler-builtins/crates/symcheck/build.rs similarity index 100% rename from library/compiler-builtins/crates/symbol-check/build.rs rename to library/compiler-builtins/crates/symcheck/build.rs diff --git a/library/compiler-builtins/crates/symbol-check/src/main.rs b/library/compiler-builtins/crates/symcheck/src/main.rs similarity index 59% rename from library/compiler-builtins/crates/symbol-check/src/main.rs rename to library/compiler-builtins/crates/symcheck/src/main.rs index 11486b6ff1138..a88aeed40fb0d 100644 --- a/library/compiler-builtins/crates/symbol-check/src/main.rs +++ b/library/compiler-builtins/crates/symcheck/src/main.rs @@ -4,17 +4,22 @@ //! Note that symcheck is a "hostprog", i.e. is built and run on the host target even when the //! actual target is cross compiled. +#![allow(clippy::enum_variant_names)] + use std::collections::{BTreeMap, BTreeSet, HashSet}; use std::io::{BufRead, BufReader}; use std::path::{Path, PathBuf}; use std::process::{Command, Stdio, exit}; use std::sync::LazyLock; -use std::{env, fs}; +use std::{env, fmt, fs}; +use object::elf::{ProgramFlags, ProgramType}; use object::read::archive::ArchiveFile; +use object::read::pe::ImageOptionalHeader; use object::{ Architecture, BinaryFormat, Endianness, File as ObjFile, FileFlags, Object, ObjectSection, - ObjectSymbol, Result as ObjResult, SectionFlags, Symbol, SymbolKind, SymbolScope, U32, elf, + ObjectSymbol, Result as ObjResult, SectionFlags, SubArchitecture, Symbol, SymbolKind, + SymbolScope, U32, elf, macho, pe, read, }; use regex::Regex; use serde_json::Value; @@ -25,8 +30,8 @@ const GNU_STACK: &str = ".note.GNU-stack"; const USAGE: &str = "Usage: - symbol-check --build-and-check [--target TARGET] [--no-os] -- CARGO_BUILD_ARGS ... - symbol-check --check PATHS ...\ + symcheck --build-and-check [--target TARGET] [--no-os] -- CARGO_BUILD_ARGS ... + symcheck --check [--target TARGET] PATHS ...\ "; fn main() { @@ -43,7 +48,10 @@ fn main() { opts.optopt( "", "target", - "Set the target for build-and-check. Falls back to the host target otherwise.", + // We could add a `--no-target-checks` flag to skip checks that need a target specified, + // if that winds up being useful at some point. + "Set the target when building, and the expected target for tests. Falls back to the host \ + target if not specified.", "TARGET", ); opts.optflag( @@ -80,25 +88,32 @@ fn main() { for arg in &free_args { assert!( !arg.contains("--target"), - "target must be passed to symbol-check" + "target must be passed to symcheck" ); } + let target = m.opt_str("target").unwrap_or(env!("HOST").to_string()); + let target = Target::from_rustc(&target); + if m.opt_present("build-and-check") { - let target = m.opt_str("target").unwrap_or(env!("HOST").to_string()); - let paths = exec_cargo_with_args(&target, &free_args); - check_paths(&paths, no_os_target, check_visibility); + let paths = exec_cargo_with_args(&target.name, &free_args); + check_paths(&target, &paths, no_os_target, check_visibility); } else if m.opt_present("check") { if free_args.is_empty() { print_usage_and_exit(1); } - check_paths(&free_args, no_os_target, check_visibility); + check_paths(&target, &free_args, no_os_target, check_visibility); } else { print_usage_and_exit(1); } } -fn check_paths>(paths: &[P], no_os_target: bool, check_visibility: bool) { +fn check_paths>( + target: &Target, + paths: &[P], + no_os_target: bool, + check_visibility: bool, +) { for path in paths { let path = path.as_ref(); println!("Checking {}", path.display()); @@ -106,6 +121,7 @@ fn check_paths>(paths: &[P], no_os_target: bool, check_visibility verify_no_duplicates(&archive); verify_core_symbols(&archive); + verify_expected_target(target, &archive); verify_no_exec_stack(&archive, no_os_target); if check_visibility { verify_hidden_visibility(&archive); @@ -113,6 +129,231 @@ fn check_paths>(paths: &[P], no_os_target: bool, check_visibility } } +#[derive(Debug)] +struct Target { + name: String, + arch: Architecture, + subarch: Option, + endian: Endianness, + pointer_width: PointerWidth, + os: Os, + env: Option, + abi: Option, + families: Vec, + vendors: Vec, +} + +impl Target { + /// Use `rustc` to query target information rather than parsing it ourselves. + fn from_rustc(target: &str) -> Self { + let mut cmd = Command::new("rustc"); + cmd.args(["--target", target, "--print=cfg"]) + .stdout(Stdio::piped()); + println!("running: {cmd:?}"); + let out = cmd.output().expect("failed to launch rustc"); + + let check_empty = |s: &str| { + if s.is_empty() { + None + } else { + Some(s.to_string()) + } + }; + + let mut t = Target { + name: target.to_string(), + arch: Architecture::Unknown, + subarch: None, + endian: Endianness::Little, + pointer_width: PointerWidth::P64, + os: Os::Unknown, + env: None, + abi: None, + families: Vec::new(), + vendors: Vec::new(), + }; + + for line in out.stdout.lines() { + let line = line.expect("failed to read line"); + let Some((k, v)) = line.split_once('=') else { + continue; + }; + let v = v.trim_matches('"'); + + match k { + "target_os" => { + t.os = match v { + "aix" => Os::Aix, + "amdhsa" => Os::Amdhsa, + "android" => Os::Android, + "cuda" => Os::Cuda, + "cygwin" => Os::Cygwin, + "dragonfly" => Os::Dragonfly, + "emscripten" => Os::Emscripten, + "espidf" => Os::EspIdf, + "freebsd" => Os::FreeBsd, + "fuchsia" => Os::Fuchsia, + "haiku" => Os::Haiku, + "helenos" => Os::HelenOs, + "hermit" => Os::Hermit, + "horizon" => Os::Horizon, + "hurd" => Os::Hurd, + "illumos" => Os::Illumos, + "ios" => Os::IOs, + "l4re" => Os::L4re, + "linux" => Os::Linux, + "lynxos178" => Os::LynxOs178, + "macos" => Os::MacOs, + "managarm" => Os::Managarm, + "motor" => Os::Motor, + "netbsd" => Os::NetBsd, + "nto" => Os::Nto, + "nuttx" => Os::Nuttx, + "openbsd" => Os::OpenBsd, + "psp" => Os::Psp, + "psx" => Os::Psx, + "qurt" => Os::Qurt, + "redox" => Os::Redox, + "rtems" => Os::Rtems, + "solaris" => Os::Solaris, + "solid_asp3" => Os::SolidAsp3, + "teeos" => Os::Teeos, + "trusty" => Os::Trusty, + "tvos" => Os::TvOs, + "uefi" => Os::Uefi, + "vexos" => Os::Vexos, + "visionos" => Os::VisionOs, + "vita" => Os::Vita, + "vxworks" => Os::VxXorks, + "wasi" => Os::Wasi, + "watchos" => Os::WatchOs, + "windows" => Os::Windows, + "xous" => Os::Xous, + "zkvm" => Os::Zkvm, + "unknown" | "none" => Os::Unknown, + _ => panic!("unrecognized OS `{v}`"), + } + } + "target_arch" => { + t.arch = match v { + "aarch64" => Architecture::Aarch64, + "arm64ec" => { + t.subarch = Some(SubArchitecture::Arm64EC); + Architecture::Aarch64 + } + "arm" => Architecture::Arm, + "avr" => Architecture::Avr, + "bpf" => Architecture::Bpf, + "csky" => Architecture::Csky, + "hexagon" => Architecture::Hexagon, + "loongarch32" => Architecture::LoongArch32, + "loongarch64" => Architecture::LoongArch64, + "m68k" => Architecture::M68k, + "mips" | "mips32r6" => Architecture::Mips, + "mips64" | "mips64r6" => Architecture::Mips64, + "msp430" => Architecture::Msp430, + "powerpc" => Architecture::PowerPc, + "powerpc64" => Architecture::PowerPc64, + "riscv32" => Architecture::Riscv32, + "riscv64" => Architecture::Riscv64, + "s390x" => Architecture::S390x, + "sparc" => Architecture::Sparc, + "sparc64" => Architecture::Sparc64, + "wasm32" => Architecture::Wasm32, + "wasm64" => Architecture::Wasm64, + "x86" => Architecture::I386, + "x86_64" => Architecture::X86_64, + "xtensa" => Architecture::Xtensa, + _ => panic!("unrecognized arch {v}"), + } + } + "target_abi" => t.abi = check_empty(v), + "target_env" => t.env = check_empty(v), + "target_family" if let Some(fam) = check_empty(v) => t.families.push(fam), + "target_vendor" if let Some(ven) = check_empty(v) => t.vendors.push(ven), + "target_endian" => { + t.endian = match v { + "little" => Endianness::Little, + "big" => Endianness::Big, + _ => panic!("unknown endian {v}"), + } + } + "target_pointer_width" => { + t.pointer_width = match v { + "16" => PointerWidth::P16, + "32" => PointerWidth::P32, + "64" => PointerWidth::P64, + _ => panic!("unknown pointer width {v}"), + } + } + _ => (), + } + } + + assert_ne!(t.arch, Architecture::Unknown, "arch not found"); + t + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +enum Os { + Aix, + Amdhsa, + Android, + Cuda, + Cygwin, + Dragonfly, + Emscripten, + EspIdf, + FreeBsd, + Fuchsia, + Haiku, + HelenOs, + Hermit, + Horizon, + Hurd, + Illumos, + IOs, + L4re, + Linux, + LynxOs178, + MacOs, + Managarm, + Motor, + NetBsd, + Nto, + Nuttx, + OpenBsd, + Psp, + Psx, + Qurt, + Redox, + Rtems, + Solaris, + SolidAsp3, + Teeos, + Trusty, + TvOs, + Uefi, + Unknown, + Vexos, + VisionOs, + Vita, + VxXorks, + Wasi, + WatchOs, + Windows, + Xous, + Zkvm, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +enum PointerWidth { + P16, + P32, + P64, +} + /// Run `cargo build` with the provided additional arguments, collecting the list of created /// libraries. fn exec_cargo_with_args(target: &str, args: &[&str]) -> Vec { @@ -366,6 +607,123 @@ fn verify_hidden_visibility(archive: &BinFile) { println!(" success: no visible symbols found"); } +/// Check that all object files are actually for the target architecture and, if provided, +/// for the target operating system. +fn verify_expected_target(target: &Target, archive: &BinFile) { + let mut mismatched = Vec::new(); + + archive.for_each_object(|obj, obj_path| { + let mut mismatch = |field: &str, a: &dyn fmt::Debug, b: &dyn fmt::Debug| { + let msg = format!("mismatched {field} {a:?} != {b:?}"); + mismatched.push((obj_path.to_owned(), msg)); + }; + + if obj.architecture() != target.arch { + mismatch("arch", &obj.architecture(), &target.arch); + } + if obj.sub_architecture() != target.subarch { + mismatch("subarch", &obj.sub_architecture(), &target.subarch); + } + if obj.endianness() != target.endian { + mismatch("endian", &obj.sub_architecture(), &target.endian); + } + + let obj_os = match &obj { + ObjFile::Elf32(f) => elf_os(f), + ObjFile::Elf64(f) => elf_os(f), + + ObjFile::MachO32(f) => mach_os(f), + ObjFile::MachO64(f) => mach_os(f), + + // The non-executable header doesn't store OS + ObjFile::Coff(_) => Os::Windows, + ObjFile::CoffBig(_) => Os::Windows, + ObjFile::Pe32(f) => pe_os(f), + ObjFile::Pe64(f) => pe_os(f), + + // Wasm files don't seem to have metadata (at least in `object`) + ObjFile::Wasm(_) => Os::Unknown, + + // Out of supported platforms, this is only used by AIX + ObjFile::Xcoff32(_) => Os::Aix, + ObjFile::Xcoff64(_) => Os::Aix, + + _ => { + unimplemented!( + "os check for binary format {:?} is not yet supported", + obj.format() + ) + } + }; + + if !(obj_os == target.os + || obj_os == Os::Unknown + // Cygwin and Windows object files look the same + || (obj_os == Os::Windows && target.os == Os::Cygwin)) + { + mismatch("OS", &obj_os, &target.os); + } + }); + + for (file, msg) in &mismatched { + eprintln!("in `{file}`: {msg}"); + } + + assert!( + mismatched.is_empty(), + "some object files do not match the intended target" + ); + println!(" success: object files match target"); +} + +/* Note that we only match OS tags that have been tested. There are others for other platforms + * that Rust supports but aren't as easy to test, they can be added as needed. */ + +/// Get the OS from an elf file, or `Unknown` if not specified. +fn elf_os(f: &read::elf::ElfFile) -> Os { + let os_abi = f.elf_header().e_ident().os_abi; + match os_abi { + elf::ELFOSABI_NONE => Os::Unknown, + elf::ELFOSABI_FREEBSD => Os::FreeBsd, + elf::ELFOSABI_SOLARIS => Os::Solaris, + // In practice, these seem not to be specified and instead match ELFOSABI_NONE. + elf::ELFOSABI_HURD => Os::Hurd, + elf::ELFOSABI_LINUX => Os::Linux, + elf::ELFOSABI_NETBSD => Os::NetBsd, + elf::ELFOSABI_OPENBSD => Os::OpenBsd, + _ => panic!("unrecognized ELF os_abi {os_abi}"), + } +} + +/// Get the OS from a mach file, or `Unknown` if not specified. +fn mach_os(f: &read::macho::MachOFile) -> Os { + // Note that this only returns something on `.rmeta` objects, not `.o`s. + let Ok(Some((build_cmd, build_tool))) = f.build_version() else { + return Os::Unknown; + }; + let platform = build_cmd.platform.get(f.endian()); + + match platform { + macho::PLATFORM_UNKNOWN => Os::Unknown, + macho::PLATFORM_MACOS => Os::MacOs, + macho::PLATFORM_IOS | macho::PLATFORM_IOSSIMULATOR | macho::PLATFORM_MACCATALYST => Os::IOs, + macho::PLATFORM_TVOS | macho::PLATFORM_TVOSSIMULATOR => Os::TvOs, + macho::PLATFORM_VISIONOS | macho::PLATFORM_VISIONOSSIMULATOR => Os::VisionOs, + macho::PLATFORM_WATCHOS | macho::PLATFORM_WATCHOSSIMULATOR => Os::WatchOs, + _ => panic!("unrecognized Mach-O platform {platform} ({build_cmd:?} {build_tool:?})"), + } +} + +/// Get the OS from a PE file, or `Unknown` if not specified. +fn pe_os(f: &read::pe::PeFile) -> Os { + let opt_hdr = f.nt_headers().optional_header(); + let sub = opt_hdr.subsystem(); + match sub { + pe::IMAGE_SUBSYSTEM_WINDOWS_CUI | pe::IMAGE_SUBSYSTEM_WINDOWS_GUI => Os::Windows, + _ => panic!("unrecognized PE subsystem {sub}, {opt_hdr:?}"), + } +} + /// Reasons a binary is considered to have an executable stack. enum ExeStack { MissingGnuStackSec, @@ -451,7 +809,8 @@ fn check_elf_exe_stack(obj: &ObjFile) -> Result<(), ExeStack> { // Check for PT_GNU_STACK marked executable let mut is_obj_exe = false; let mut found_gnu_stack = false; - let mut check_ph = |p_type: U32, p_flags: U32| { + let mut check_ph = |p_type: U32, + p_flags: U32| { let ty = p_type.get(end); let flags = p_flags.get(end); @@ -464,7 +823,7 @@ fn check_elf_exe_stack(obj: &ObjFile) -> Result<(), ExeStack> { if ty == elf::PT_GNU_STACK { assert!(!found_gnu_stack, "multiple PT_GNU_STACK sections"); found_gnu_stack = true; - if flags & elf::PF_X != 0 { + if flags.contains(elf::PF_X) { return Err(ExeStack::ExePtGnuStack); } } @@ -495,11 +854,15 @@ fn check_elf_exe_stack(obj: &ObjFile) -> Result<(), ExeStack> { let mut gnu_stack_exe = None; let mut has_exe_sections = false; for sec in obj.sections() { - let SectionFlags::Elf { sh_flags } = sec.flags() else { + let SectionFlags::Elf { + sh_type: _, + sh_flags, + } = sec.flags() + else { unreachable!("only elf files are being checked"); }; - let is_sec_exe = sh_flags & u64::from(elf::SHF_EXECINSTR) != 0; + let is_sec_exe = sh_flags.contains(elf::SHF_EXECINSTR); // If the magic section is present, its exe bit tells us whether or not the object // file requires an executable stack. @@ -534,7 +897,7 @@ fn check_elf_exe_stack(obj: &ObjFile) -> Result<(), ExeStack> { match obj.architecture() { // PPC64 doesn't set `.note.GNU-stack` since GNU nested functions don't need a trampoline, // . This only applies to ELFv1. - Architecture::PowerPc64 if e_flags & elf::EF_PPC64_ABI != 2 => Ok(()), + Architecture::PowerPc64 if e_flags.0 & elf::EF_PPC64_ABI != 2 => Ok(()), _ => Err(ExeStack::MissingGnuStackSec), } diff --git a/library/compiler-builtins/crates/symbol-check/tests/all.rs b/library/compiler-builtins/crates/symcheck/tests/all.rs similarity index 85% rename from library/compiler-builtins/crates/symbol-check/tests/all.rs rename to library/compiler-builtins/crates/symcheck/tests/all.rs index d038fd0dc935f..ce7d09798dc65 100644 --- a/library/compiler-builtins/crates/symbol-check/tests/all.rs +++ b/library/compiler-builtins/crates/symcheck/tests/all.rs @@ -1,7 +1,7 @@ -use std::env; use std::ffi::OsString; use std::path::{Path, PathBuf}; use std::process::{Command, Stdio}; +use std::{env, str}; use assert_cmd::assert::Assert; use assert_cmd::cargo::cargo_bin_cmd; @@ -89,6 +89,43 @@ fn test_visible_symbols() { assert.failure().stderr_contains("found 1 visible symbols"); // good is visible. } +#[test] +fn test_target_mismatch() { + // Build with the target we know we have a toolchain for, but check against something else. + let t_build = TestTarget::from_env(); + let t_check = if t_build.triple.starts_with("x86_64") { + TestTarget { + triple: "aarch64-unknown-linux-gnu".to_string(), + } + } else { + TestTarget { + triple: "x86_64-unknown-linux-gnu".to_string(), + } + }; + + let dir = tempdir().unwrap(); + let lib_out = dir.path().join("libfoo.rlib"); + t_build.rustc_build(&input_dir().join("good_lib.rs"), &lib_out, |cmd| cmd); + + let assert = t_check.symcheck_exe().arg(&lib_out).assert(); + assert + .failure() + .stderr_contains("some object files do not match the intended target"); + + // Try with C as well since some checks rely on rmeta archive members (Mach-O `build_version`). + let objs = t_build + .cc_build() + .file(input_dir().join("good_lib.c")) + .out_dir(&dir) + .compile_intermediates(); + let [c_obj] = objs.as_slice() else { panic!() }; + + let assert = t_check.symcheck_exe().arg(c_obj).assert(); + assert + .failure() + .stderr_contains("some object files do not match the intended target"); +} + mod exe_stack { use super::*; @@ -111,10 +148,7 @@ mod exe_stack { let assert = t.symcheck_exe().arg(obj).arg("--no-visibility").assert(); - if (t.is_ppc64be() && t.is_glibc()) - || t.no_os() - || t.binary_obj_format() != BinaryFormat::Elf - { + if t.is_ppc64_elfv1() || t.no_os() || t.binary_obj_format() != BinaryFormat::Elf { // Ppc64be ELFv1 doesn't emit `.note.GNU-stack`, not relevant without an OS, and non-elf // targets don't use `.note.GNU-stack`. assert.success(); @@ -146,7 +180,7 @@ mod exe_stack { let assert = t.symcheck_exe().arg(obj).arg("--no-visibility").assert(); - if (t.is_ppc64be() && t.is_glibc()) || t.no_os() { + if t.is_ppc64_elfv1() || t.no_os() { // Ppc64be ELFv1 doesn't emit `.note.GNU-stack`, not relevant without an OS. assert.success(); return; @@ -270,7 +304,7 @@ impl TestTarget { fn symcheck_exe(&self) -> assert_cmd::Command { let mut cmd = cargo_bin_cmd!(); - cmd.arg("--check"); + cmd.arg("--check").arg("--target").arg(&self.triple); if self.no_os() { cmd.arg("--no-os"); } @@ -315,12 +349,16 @@ impl TestTarget { self.triple.contains("-windows-msvc") } - fn is_ppc64be(&self) -> bool { - self.triple.starts_with("powerpc64-") - } - - fn is_glibc(&self) -> bool { - self.triple.contains("-linux-gnu") + fn is_ppc64_elfv1(&self) -> bool { + let output = Command::new("rustc") + .arg("--target") + .arg(&self.triple) + .arg("--print=cfg") + .output() + .unwrap(); + assert!(output.status.success()); + let stdout = str::from_utf8(&output.stdout).unwrap(); + self.triple.starts_with("powerpc64") && stdout.contains(r#"target_abi="elfv1""#) } /// True if the target needs `--no-os` passed to symcheck. diff --git a/library/compiler-builtins/crates/symbol-check/tests/input/core_symbols.rs b/library/compiler-builtins/crates/symcheck/tests/input/core_symbols.rs similarity index 100% rename from library/compiler-builtins/crates/symbol-check/tests/input/core_symbols.rs rename to library/compiler-builtins/crates/symcheck/tests/input/core_symbols.rs diff --git a/library/compiler-builtins/crates/symbol-check/tests/input/duplicates.rs b/library/compiler-builtins/crates/symcheck/tests/input/duplicates.rs similarity index 100% rename from library/compiler-builtins/crates/symbol-check/tests/input/duplicates.rs rename to library/compiler-builtins/crates/symcheck/tests/input/duplicates.rs diff --git a/library/compiler-builtins/crates/symbol-check/tests/input/good_bin.c b/library/compiler-builtins/crates/symcheck/tests/input/good_bin.c similarity index 100% rename from library/compiler-builtins/crates/symbol-check/tests/input/good_bin.c rename to library/compiler-builtins/crates/symcheck/tests/input/good_bin.c diff --git a/library/compiler-builtins/crates/symcheck/tests/input/good_lib.c b/library/compiler-builtins/crates/symcheck/tests/input/good_lib.c new file mode 100644 index 0000000000000..0b7e431cb90f2 --- /dev/null +++ b/library/compiler-builtins/crates/symcheck/tests/input/good_lib.c @@ -0,0 +1 @@ +void good() {} diff --git a/library/compiler-builtins/crates/symbol-check/tests/input/good_lib.rs b/library/compiler-builtins/crates/symcheck/tests/input/good_lib.rs similarity index 100% rename from library/compiler-builtins/crates/symbol-check/tests/input/good_lib.rs rename to library/compiler-builtins/crates/symcheck/tests/input/good_lib.rs diff --git a/library/compiler-builtins/crates/symbol-check/tests/input/has_exe_gnu_stack_section.c b/library/compiler-builtins/crates/symcheck/tests/input/has_exe_gnu_stack_section.c similarity index 100% rename from library/compiler-builtins/crates/symbol-check/tests/input/has_exe_gnu_stack_section.c rename to library/compiler-builtins/crates/symcheck/tests/input/has_exe_gnu_stack_section.c diff --git a/library/compiler-builtins/crates/symbol-check/tests/input/missing_gnu_stack_section.S b/library/compiler-builtins/crates/symcheck/tests/input/missing_gnu_stack_section.S similarity index 100% rename from library/compiler-builtins/crates/symbol-check/tests/input/missing_gnu_stack_section.S rename to library/compiler-builtins/crates/symcheck/tests/input/missing_gnu_stack_section.S diff --git a/library/compiler-builtins/crates/util/Cargo.toml b/library/compiler-builtins/crates/util/Cargo.toml index b0a365e4735b0..c56e2cc12ea58 100644 --- a/library/compiler-builtins/crates/util/Cargo.toml +++ b/library/compiler-builtins/crates/util/Cargo.toml @@ -6,7 +6,6 @@ publish = false license = "MIT OR Apache-2.0" [dependencies] -cfg-if.workspace = true libm.workspace = true libm-macros.workspace = true libm-test.workspace = true diff --git a/library/compiler-builtins/crates/util/src/main.rs b/library/compiler-builtins/crates/util/src/main.rs index ac2c126d8c0d1..aa79354a57159 100644 --- a/library/compiler-builtins/crates/util/src/main.rs +++ b/library/compiler-builtins/crates/util/src/main.rs @@ -8,7 +8,6 @@ use std::env; use std::num::ParseIntError; use std::str::FromStr; -use cfg_if::cfg_if; use libm::support::{Float, Hex, hf32, hf64}; #[cfg(feature = "build-mpfr")] use libm_test::mpfloat::MpOp; @@ -127,13 +126,14 @@ fn do_eval(basis: &str, op: &str, inputs: &[&str]) { fn do_classify(inputs: &[&str]) { for s in inputs { if let Some(s) = s.strip_suffix("f16") { - cfg_if! { - if #[cfg(f16_enabled)] { + cfg_select! { + f16_enabled => { let s = s.trim_end_matches("_"); let x: f16 = parse(&[s], 0); classify_print(x); continue; - } else { + } + _ => { panic!("parsing this type requires f16 support: `{s}`"); } } @@ -150,15 +150,18 @@ fn do_classify(inputs: &[&str]) { continue; } if let Some(s) = s.strip_suffix("f128") { - cfg_if! { - if #[cfg(all(f128_enabled, feature = "build-mpfr"))] { + cfg_select! { + all(f128_enabled, feature = "build-mpfr") => { let s = s.trim_end_matches("_"); let x: f128 = parse_rug(&[s], 0); classify_print(x); continue; - } else { - panic!("parsing this type requires f128 support and \ - the `build-mpfr` feature: `{s}`"); + } + _ => { + panic!( + "parsing this type requires f128 support and \ + the `build-mpfr` feature: `{s}`" + ); } } }; diff --git a/library/compiler-builtins/etc/function-definitions.json b/library/compiler-builtins/etc/function-definitions.json index f59bb7ceebb42..88070abf0ce09 100644 --- a/library/compiler-builtins/etc/function-definitions.json +++ b/library/compiler-builtins/etc/function-definitions.json @@ -343,6 +343,7 @@ "fma": { "sources": [ "libm/src/math/arch/aarch64/fma.rs", + "libm/src/math/arch/loongarch/fma.rs", "libm/src/math/arch/x86/fma.rs", "libm/src/math/fma.rs", "libm/src/math/generic/fma.rs" @@ -352,6 +353,7 @@ "fmaf": { "sources": [ "libm/src/math/arch/aarch64/fma.rs", + "libm/src/math/arch/loongarch/fma.rs", "libm/src/math/arch/x86/fma.rs", "libm/src/math/fma.rs", "libm/src/math/generic/fma.rs" @@ -832,6 +834,7 @@ "sources": [ "libm/src/math/arch/aarch64/rounding.rs", "libm/src/math/arch/i586/rounding.rs", + "libm/src/math/arch/loongarch/rounding.rs", "libm/src/math/arch/wasm32/rounding.rs", "libm/src/math/generic/rint.rs", "libm/src/math/rint.rs" @@ -841,6 +844,7 @@ "rintf": { "sources": [ "libm/src/math/arch/aarch64/rounding.rs", + "libm/src/math/arch/loongarch/rounding.rs", "libm/src/math/arch/wasm32/rounding.rs", "libm/src/math/generic/rint.rs", "libm/src/math/rint.rs" @@ -981,6 +985,7 @@ "sqrt": { "sources": [ "libm/src/math/arch/aarch64/sqrt.rs", + "libm/src/math/arch/loongarch/sqrt.rs", "libm/src/math/arch/wasm32/sqrt.rs", "libm/src/math/arch/x86/sqrt.rs", "libm/src/math/generic/sqrt.rs", @@ -991,6 +996,7 @@ "sqrtf": { "sources": [ "libm/src/math/arch/aarch64/sqrt.rs", + "libm/src/math/arch/loongarch/sqrt.rs", "libm/src/math/arch/wasm32/sqrt.rs", "libm/src/math/arch/x86/sqrt.rs", "libm/src/math/generic/sqrt.rs", diff --git a/library/compiler-builtins/libm-test/src/generate.rs b/library/compiler-builtins/libm-test/src/generate.rs index 7118752f4f0bb..29c2b9f92236b 100644 --- a/library/compiler-builtins/libm-test/src/generate.rs +++ b/library/compiler-builtins/libm-test/src/generate.rs @@ -1,5 +1,6 @@ //! Different generators that can create random or systematic bit patterns. +pub mod bitpattern; pub mod case_list; pub mod edge_cases; pub mod random; diff --git a/library/compiler-builtins/libm-test/src/generate/bitpattern.rs b/library/compiler-builtins/libm-test/src/generate/bitpattern.rs new file mode 100644 index 0000000000000..45b2ff0b21acb --- /dev/null +++ b/library/compiler-builtins/libm-test/src/generate/bitpattern.rs @@ -0,0 +1,371 @@ +use libm::support::{Float, Int, MinInt}; + +/// Iterate all the bitwise subsets of the given mask. +/// +/// Produces the same sequence as `(0..=uN::MAX).filter(|x| x & !mask == 0)`, +/// but each item is generated in O(1) time. +/// +/// # Panics +/// +/// Panics if the mask has all bits set. +/// +/// # Example +/// +/// ```ignore +/// assert!(bitwise_subsets(0b1001).eq([0b0000, 0b0001, 0b1000, 0b1001])); +/// ``` +fn bitwise_subsets(mask: I) -> impl Iterator + Clone +where + I: Int, +{ + assert!( + mask != I::MAX, + "to optimize the implementation, varying every bit is not supported" + ); + let fixed = !mask; + let mut counter = fixed - I::ONE; + + // `(counter + 1) & !fixed` is initially 0, and increases after each item returned + std::iter::from_fn(move || { + counter = counter.checked_add(I::ONE)? | fixed; + Some(counter ^ fixed) + }) +} + +/// Create a bitmask with `count` ones. The ones are filled in this order: +/// +/// 1. Sign bit +/// 2. Significand low bits +/// 3. Significand high bits, exponent low bits, exponent high bits (increment together) +fn most_wanted_bitmask(count: u32) -> F::Int { + if count == 0 { + return F::Int::ZERO; + } + let mut mask = F::SIGN_MASK; + let n = (count - 1) / 4; + mask |= low_mask_bits(n, F::EXP_MASK); + mask |= high_mask_bits(n, F::EXP_MASK); + mask |= high_mask_bits(n, F::SIG_MASK); + // spend most of the remaining budget on the least significant bits, then use up remainders + mask |= low_mask_bits(count - mask.count_ones(), F::SIG_MASK); + mask |= high_mask_bits(n + count - mask.count_ones(), F::SIG_MASK); + mask |= high_mask_bits(n + count - mask.count_ones(), F::EXP_MASK); + mask |= low_mask_bits(n + count - mask.count_ones(), F::EXP_MASK); + mask +} + +/// Similar to `most_wanted_bitmask` but adds bits around the middle of the int rather than at +/// a sign/exponent/significand boundary. +fn most_wanted_int_bitmask>(count: u32) -> I { + if count == 0 { + return I::ZERO; + } + let mut mask = I::ZERO; + let n = count / 4; + + let low_mask = I::MAX >> (I::BITS / 2); + let high_mask = low_mask << (I::BITS / 2); + + mask |= low_mask_bits(n, high_mask); + mask |= high_mask_bits(n, high_mask); + mask |= high_mask_bits(n, low_mask); + // spend most of the remaining budget on the least significant bits, then use up remainders + mask |= low_mask_bits(count - mask.count_ones(), low_mask); + mask |= high_mask_bits(n + count - mask.count_ones(), low_mask); + mask |= high_mask_bits(n + count - mask.count_ones(), high_mask); + mask |= low_mask_bits(n + count - mask.count_ones(), high_mask); + mask +} + +/// Set `count` bits in the LSB of `mask`. +fn low_mask_bits(count: u32, mask: I) -> I { + mask & (mask >> (mask.count_ones().saturating_sub(count))) +} + +/// Set `count` bits in the MSB of `mask`. +fn high_mask_bits(count: u32, mask: I) -> I { + mask & (mask << (mask.count_ones().saturating_sub(count))) +} + +/// Biased generator for floats. +/// +/// Starts with the first value of `fillers`, then toggles `bits_to_vary` bits exhaustively. Once +/// that has completed, move on to the next filler. +/// +/// The returned iterator will produce `fillers.len() << bits_to_vary` items. +#[cfg_attr(not(test), expect(dead_code))] +fn float_gen( + bits_to_vary: u32, + fillers: impl IntoIterator, +) -> impl Iterator +where + F: Float, + F::Int: Int, +{ + let varying = most_wanted_bitmask::(bits_to_vary); + let patterns = bitwise_subsets(varying); + + fillers + .into_iter() + .flat_map(move |preset| patterns.clone().map(move |x| x ^ preset)) + .map(F::from_bits) +} + +/// See [`float_gen`] docs for details. +#[cfg_attr(not(test), expect(dead_code))] +fn int_gen(bits_to_vary: u32, fillers: impl IntoIterator) -> impl Iterator +where + I: Int, +{ + let varying = most_wanted_int_bitmask::(bits_to_vary); + let patterns = bitwise_subsets(varying); + + fillers + .into_iter() + .flat_map(move |preset| patterns.clone().map(move |x| x ^ preset)) +} + +#[cfg(test)] +mod test { + use super::*; + use crate::f8; + + #[test] + fn equivalence() { + // with a small integer type, we can easily verify that behaviour matches for all arguments + for mask in 0..u8::MAX { + let expect = (0..=u8::MAX).filter(|x| x & !mask == 0); + assert!(bitwise_subsets(mask).eq(expect)); + } + } + + #[test] + fn most_wanted() { + let expected8 = [ + 0b0_0000_000, + // + 0b1_0000_000, + 0b1_0000_001, + 0b1_0000_011, + 0b1_0000_111, + // + 0b1_1001_101, + 0b1_1001_111, + 0b1_1101_111, + 0b1_1111_111, + ]; + let expected32 = [ + 0b0_00000000_00000000000000000000000, + // + 0b1_00000000_00000000000000000000000, + 0b1_00000000_00000000000000000000001, + 0b1_00000000_00000000000000000000011, + 0b1_00000000_00000000000000000000111, + // + 0b1_10000001_10000000000000000000001, + 0b1_10000001_10000000000000000000011, + 0b1_10000001_10000000000000000000111, + 0b1_10000001_10000000000000000001111, + // + 0b1_11000011_11000000000000000000011, + 0b1_11000011_11000000000000000000111, + 0b1_11000011_11000000000000000001111, + 0b1_11000011_11000000000000000011111, + // + 0b1_11100111_11100000000000000000111, + 0b1_11100111_11100000000000000001111, + 0b1_11100111_11100000000000000011111, + 0b1_11100111_11100000000000000111111, + // + 0b1_11111111_11110000000000000001111, + 0b1_11111111_11110000000000000011111, + 0b1_11111111_11110000000000000111111, + 0b1_11111111_11110000000000001111111, + // + 0b1_11111111_11111000000000001111111, + 0b1_11111111_11111000000000011111111, + 0b1_11111111_11111000000000111111111, + 0b1_11111111_11111000000001111111111, + // + 0b1_11111111_11111100000001111111111, + 0b1_11111111_11111100000011111111111, + 0b1_11111111_11111100000111111111111, + 0b1_11111111_11111100001111111111111, + // + 0b1_11111111_11111110001111111111111, + 0b1_11111111_11111110011111111111111, + 0b1_11111111_11111110111111111111111, + 0b1_11111111_11111111111111111111111, + ]; + for k in 0..=8 { + let mask = most_wanted_bitmask::(k); + assert_eq!(mask, expected8[k as usize], "{k}"); + assert_eq!(mask.count_ones(), k); + } + for k in 0..=32 { + let mask = most_wanted_bitmask::(k); + assert_eq!(mask, expected32[k as usize], "{k}"); + assert_eq!(mask.count_ones(), k); + } + } + + #[test] + fn most_wanted_int() { + let expected = [ + 0b0000_0000_0000_0000, + 0b0000_0000_0000_0001, + 0b0000_0000_0000_0011, + 0b0000_0000_0000_0111, + // + 0b1000_0001_1000_0001, + 0b1000_0001_1000_0011, + 0b1000_0001_1000_0111, + 0b1000_0001_1000_1111, + // + 0b1100_0011_1100_0011, + 0b1100_0011_1100_0111, + 0b1100_0011_1100_1111, + 0b1100_0011_1101_1111, + // + 0b1110_0111_1110_0111, + 0b1110_0111_1110_1111, + 0b1110_0111_1111_1111, + 0b1111_0111_1111_1111, + // + 0b1111_1111_1111_1111, + ]; + let mut x = vec![]; + for k in 0..=16 { + let mask = most_wanted_int_bitmask::(k); + x.push(mask); + assert_eq!(mask, expected[k as usize], "{k}"); + assert_eq!(mask.count_ones(), k); + } + } + + #[test] + #[cfg(f16_enabled)] + fn gen_with_fillers() { + let expected = [ + // Filler: zeros + 0b0_00000_0000000000, + 0b0_00000_0000000001, + 0b0_00000_0000000010, + 0b0_00000_0000000011, + 0b1_00000_0000000000, + 0b1_00000_0000000001, + 0b1_00000_0000000010, + 0b1_00000_0000000011, + // Filler: ones + 0b1_11111_1111111111, + 0b1_11111_1111111110, + 0b1_11111_1111111101, + 0b1_11111_1111111100, + 0b0_11111_1111111111, + 0b0_11111_1111111110, + 0b0_11111_1111111101, + 0b0_11111_1111111100, + // Filler: pattern + 0b1_00110_1000101011, + 0b1_00110_1000101010, + 0b1_00110_1000101001, + 0b1_00110_1000101000, + 0b0_00110_1000101011, + 0b0_00110_1000101010, + 0b0_00110_1000101001, + 0b0_00110_1000101000, + ]; + let v = float_gen::(3, [0, u16::MAX, 0b1_00110_1000101011]) + .map(|x| x.to_bits()) + .collect::>(); + assert_eq!(expected.as_slice(), v); + } + + #[test] + fn gen_int_with_fillers() { + let expected = [ + // Filler: zeros + 0b0000_0000_0000_0000, + 0b0000_0000_0000_0001, + 0b0000_0000_0000_0010, + 0b0000_0000_0000_0011, + 0b0000_0000_0000_0100, + 0b0000_0000_0000_0101, + 0b0000_0000_0000_0110, + 0b0000_0000_0000_0111, + // Filler: ones + 0b1111_1111_1111_1111, + 0b1111_1111_1111_1110, + 0b1111_1111_1111_1101, + 0b1111_1111_1111_1100, + 0b1111_1111_1111_1011, + 0b1111_1111_1111_1010, + 0b1111_1111_1111_1001, + 0b1111_1111_1111_1000, + // Filler: pattern + 0b1001_1010_0010_1011, + 0b1001_1010_0010_1010, + 0b1001_1010_0010_1001, + 0b1001_1010_0010_1000, + 0b1001_1010_0010_1111, + 0b1001_1010_0010_1110, + 0b1001_1010_0010_1101, + 0b1001_1010_0010_1100, + ]; + let v = int_gen::(3, [0, u16::MAX, 0b1001_1010_0010_1011]).collect::>(); + assert_eq!(expected.as_slice(), v); + } + + #[test] + fn gen_includes_specials() { + let v: Vec<_> = float_gen(5, vec![0, 0x7fffff, !0x7fffff, !0]) + .map(f32::to_bits) + .collect(); + for x in &[ + 0.0, + f32::from_bits(1), + f32::MIN_POSITIVE, + f32::MAX, + f32::INFINITY, + f32::NAN, + ] { + assert!(v.contains(&x.to_bits()), "{x} not found"); + assert!(v.contains(&(-x).to_bits()), "-{x} not found"); + } + } + + #[test] + fn count() { + for k in 0..10 { + assert!(float_gen::(k, vec![0]).count() == 1 << k); + assert!(float_gen::(k, vec![0, !0]).count() == 2 << k); + assert!(float_gen::(k, vec![0, 1, 2]).count() == 3 << k); + } + } + + #[test] + fn specific() { + let iter = float_gen::(1, vec![0]).map(f32::to_bits); + assert!(iter.eq([0.0_f32.to_bits(), (-0.0_f32).to_bits()])); + let iter = float_gen::(1, vec![0]).map(f64::to_bits); + assert!(iter.eq([0.0_f64.to_bits(), (-0.0_f64).to_bits()])); + + let mut v: Vec<_> = float_gen::(5, vec![0]).map(f32::to_bits).collect(); + assert!(v.len() == 32); + assert!(v.is_sorted()); + v.dedup(); + assert!(v.len() == 32); + for bits in v { + assert!(bits & 0xc0c0_0001 == bits); + } + + let mut v: Vec<_> = float_gen::(5, vec![0]).map(f64::to_bits).collect(); + assert!(v.len() == 32); + assert!(v.is_sorted()); + v.dedup(); + assert!(v.len() == 32); + for bits in v { + assert!(bits & 0xc018_0000_0000_0001 == bits); + } + } +} diff --git a/library/compiler-builtins/libm-test/src/generate/random.rs b/library/compiler-builtins/libm-test/src/generate/random.rs index 32bd2f24ee044..b6cd315ef34c1 100644 --- a/library/compiler-builtins/libm-test/src/generate/random.rs +++ b/library/compiler-builtins/libm-test/src/generate/random.rs @@ -12,7 +12,7 @@ use rand_chacha::ChaCha8Rng; use crate::CheckCtx; use crate::generate::{KnownSize, product2, product3}; use crate::num::full_range; -use crate::run_cfg::{int_range, iteration_count}; +use crate::run_cfg::{arg_max_iterations, int_range}; pub(crate) const SEED_ENV: &str = "LIBM_SEED"; @@ -57,7 +57,7 @@ macro_rules! impl_random_input { ($fty:ty) => { impl RandomInput for ($fty,) { fn get_cases(ctx: &CheckCtx) -> (impl Iterator, u64) { - let count = iteration_count(ctx, 0); + let count = arg_max_iterations(ctx, 0); let iter = random_floats(count).map(|f: $fty| (f,)); (iter, count) } @@ -65,8 +65,8 @@ macro_rules! impl_random_input { impl RandomInput for ($fty, $fty) { fn get_cases(ctx: &CheckCtx) -> (impl Iterator, u64) { - let count0 = iteration_count(ctx, 0); - let count1 = iteration_count(ctx, 1); + let count0 = arg_max_iterations(ctx, 0); + let count1 = arg_max_iterations(ctx, 1); let iter0 = random_floats(count0); let iter1 = random_floats(count1); let iter = product2(iter0, iter1); @@ -77,9 +77,9 @@ macro_rules! impl_random_input { impl RandomInput for ($fty, $fty, $fty) { fn get_cases(ctx: &CheckCtx) -> (impl Iterator, u64) { - let count0 = iteration_count(ctx, 0); - let count1 = iteration_count(ctx, 1); - let count2 = iteration_count(ctx, 2); + let count0 = arg_max_iterations(ctx, 0); + let count1 = arg_max_iterations(ctx, 1); + let count2 = arg_max_iterations(ctx, 2); let iter0 = random_floats(count0); let iter1 = random_floats(count1); let iter2 = random_floats(count2); @@ -91,8 +91,8 @@ macro_rules! impl_random_input { impl RandomInput for (i32, $fty) { fn get_cases(ctx: &CheckCtx) -> (impl Iterator, u64) { - let count0 = iteration_count(ctx, 0); - let count1 = iteration_count(ctx, 1); + let count0 = arg_max_iterations(ctx, 0); + let count1 = arg_max_iterations(ctx, 1); let range0 = int_range::(ctx, 0).unwrap_or(full_range()); let iter0 = random_ints(count0, range0); let iter1 = random_floats(count1); @@ -104,8 +104,8 @@ macro_rules! impl_random_input { impl RandomInput for ($fty, i32) { fn get_cases(ctx: &CheckCtx) -> (impl Iterator, u64) { - let count0 = iteration_count(ctx, 0); - let count1 = iteration_count(ctx, 1); + let count0 = arg_max_iterations(ctx, 0); + let count1 = arg_max_iterations(ctx, 1); let range1 = int_range::(ctx, 1).unwrap_or(full_range()); let iter0 = random_floats(count0); let iter1 = random_ints(count1, range1.clone()); @@ -128,7 +128,7 @@ macro_rules! impl_random_input_int { (@skip_u32 $ity:ty) => { impl RandomInput for ($ity,) { fn get_cases(ctx: &CheckCtx) -> (impl Iterator, u64) { - let count = iteration_count(ctx, 0); + let count = arg_max_iterations(ctx, 0); let range = int_range::<$ity>(ctx, 0).unwrap_or(full_range()); let iter = random_ints(count, range).map(|f: $ity| (f,)); (iter, count) @@ -137,8 +137,8 @@ macro_rules! impl_random_input_int { impl RandomInput for ($ity, $ity) { fn get_cases(ctx: &CheckCtx) -> (impl Iterator, u64) { - let count0 = iteration_count(ctx, 0); - let count1 = iteration_count(ctx, 1); + let count0 = arg_max_iterations(ctx, 0); + let count1 = arg_max_iterations(ctx, 1); let range0 = int_range::<$ity>(ctx, 0).unwrap_or(full_range()); let range1 = int_range::<$ity>(ctx, 1).unwrap_or(full_range()); let iter0 = random_ints(count0, range0); @@ -153,8 +153,8 @@ macro_rules! impl_random_input_int { impl RandomInput for ($ity, u32) { fn get_cases(ctx: &CheckCtx) -> (impl Iterator, u64) { - let count0 = iteration_count(ctx, 0); - let count1 = iteration_count(ctx, 1); + let count0 = arg_max_iterations(ctx, 0); + let count1 = arg_max_iterations(ctx, 1); let range0 = int_range::<$ity>(ctx, 0).unwrap_or(full_range()); let range1 = int_range::(ctx, 1).unwrap_or(full_range()); let iter0 = random_ints(count0, range0); diff --git a/library/compiler-builtins/libm-test/src/generate/spaced.rs b/library/compiler-builtins/libm-test/src/generate/spaced.rs index 192106cc61827..051dd2687d8cb 100644 --- a/library/compiler-builtins/libm-test/src/generate/spaced.rs +++ b/library/compiler-builtins/libm-test/src/generate/spaced.rs @@ -6,7 +6,7 @@ use libm::support::{Float, Int, MinInt}; use crate::domain::get_domain; use crate::generate::{product2, product3}; use crate::num::full_range; -use crate::run_cfg::{int_range, iteration_count}; +use crate::run_cfg::{arg_max_iterations, int_range}; use crate::{Arg0, Arg1, Arg2, CheckCtx, MathOp, linear_ints, logspace}; /// Generate a sequence of inputs that eiher cover the domain in completeness (for smaller float @@ -101,7 +101,7 @@ macro_rules! impl_spaced_input { Op: MathOp, { fn get_cases(ctx: &CheckCtx) -> (impl Iterator, u64) { - let max_steps0 = iteration_count(ctx, 0); + let max_steps0 = arg_max_iterations(ctx, 0); // Unary tests: `f16` and `f32` may be exhaustive. if let Some(exhaustive_steps0) = total_value_count::>() @@ -125,8 +125,8 @@ macro_rules! impl_spaced_input { Op: MathOp, { fn get_cases(ctx: &CheckCtx) -> (impl Iterator, u64) { - let max_steps0 = iteration_count(ctx, 0); - let max_steps1 = iteration_count(ctx, 1); + let max_steps0 = arg_max_iterations(ctx, 0); + let max_steps1 = arg_max_iterations(ctx, 1); // Binary test: `f16` may be exhaustive. if let Some(exhaustive_steps0) = total_value_count::>() @@ -159,9 +159,9 @@ macro_rules! impl_spaced_input { Op: MathOp, { fn get_cases(ctx: &CheckCtx) -> (impl Iterator, u64) { - let max_steps0 = iteration_count(ctx, 0); - let max_steps1 = iteration_count(ctx, 1); - let max_steps2 = iteration_count(ctx, 2); + let max_steps0 = arg_max_iterations(ctx, 0); + let max_steps1 = arg_max_iterations(ctx, 1); + let max_steps2 = arg_max_iterations(ctx, 2); // Ternary test: `f16` may be exhaustive tested if `LIBM_EXTENSIVE_TESTS` // is incresed. @@ -200,8 +200,8 @@ macro_rules! impl_spaced_input { { fn get_cases(ctx: &CheckCtx) -> (impl Iterator, u64) { let range0 = int_range(ctx, 0).unwrap_or(full_range()); - let max_steps0 = iteration_count(ctx, 0); - let max_steps1 = iteration_count(ctx, 1); + let max_steps0 = arg_max_iterations(ctx, 0); + let max_steps1 = arg_max_iterations(ctx, 1); if let Some(exhaustive_steps0) = total_value_count_int::>() && exhaustive_steps0 <= max_steps0 @@ -232,9 +232,9 @@ macro_rules! impl_spaced_input { Op: MathOp, { fn get_cases(ctx: &CheckCtx) -> (impl Iterator, u64) { - let max_steps0 = iteration_count(ctx, 0); + let max_steps0 = arg_max_iterations(ctx, 0); let range1 = int_range(ctx, 1).unwrap_or(full_range()); - let max_steps1 = iteration_count(ctx, 1); + let max_steps1 = arg_max_iterations(ctx, 1); if let Some(exhaustive_steps0) = total_value_count::>() && exhaustive_steps0 <= max_steps0 @@ -275,7 +275,7 @@ macro_rules! impl_spaced_input_int { { fn get_cases(ctx: &CheckCtx) -> (impl Iterator, u64) { let range = int_range(ctx, 0).unwrap_or(full_range()); - let max_steps0 = iteration_count(ctx, 0); + let max_steps0 = arg_max_iterations(ctx, 0); if let Some(steps0) = total_value_count_int::>() && steps0 <= max_steps0 @@ -297,8 +297,8 @@ macro_rules! impl_spaced_input_int { fn get_cases(ctx: &CheckCtx) -> (impl Iterator, u64) { let range0 = int_range(ctx, 0).unwrap_or(full_range()); let range1 = int_range(ctx, 1).unwrap_or(full_range()); - let max_steps0 = iteration_count(ctx, 0); - let max_steps1 = iteration_count(ctx, 0); + let max_steps0 = arg_max_iterations(ctx, 0); + let max_steps1 = arg_max_iterations(ctx, 0); if let Some(steps0) = total_value_count_int::>() && steps0 <= max_steps0 @@ -331,8 +331,8 @@ macro_rules! impl_spaced_input_int { fn get_cases(ctx: &CheckCtx) -> (impl Iterator, u64) { let range0 = int_range(ctx, 0).unwrap_or(full_range()); let range1 = int_range(ctx, 1).unwrap_or(full_range()); - let max_steps0 = iteration_count(ctx, 0); - let max_steps1 = iteration_count(ctx, 0); + let max_steps0 = arg_max_iterations(ctx, 0); + let max_steps1 = arg_max_iterations(ctx, 0); if let Some(steps0) = total_value_count_int::>() && steps0 <= max_steps0 diff --git a/library/compiler-builtins/libm-test/src/run_cfg.rs b/library/compiler-builtins/libm-test/src/run_cfg.rs index 2b42d581b4c9f..234eb914e6d2b 100644 --- a/library/compiler-builtins/libm-test/src/run_cfg.rs +++ b/library/compiler-builtins/libm-test/src/run_cfg.rs @@ -15,9 +15,12 @@ pub const EXTENSIVE_ITER_ENV: &str = "LIBM_EXTENSIVE_ITERATIONS"; /// The override value, if set by the above environment. static EXTENSIVE_ITER_OVERRIDE: LazyLock> = LazyLock::new(|| { - env::var(EXTENSIVE_ITER_ENV) - .map(|v| v.parse().expect("failed to parse iteration count")) - .ok() + let s = env::var(EXTENSIVE_ITER_ENV).ok()?; + let r = match s.as_str() { + "unlimited" | "max" => u64::MAX, + _ => s.parse().expect("failed to parse iteration count"), + }; + Some(r) }); /// Specific tests that need to have a reduced amount of iterations to complete in a reasonable @@ -236,8 +239,9 @@ fn slow_platform() -> bool { slow_on_ci && crate::ci() } -/// The number of iterations to run for a given test. -pub fn iteration_count(ctx: &CheckCtx, argnum: usize) -> u64 { +/// The maximum number of iterations to run for a given argument in a given test. This may be +/// greater than the number of representable values. +pub fn arg_max_iterations(ctx: &CheckCtx, argnum: usize) -> u64 { let t_env = TestEnv::from_env(ctx); // Ideally run 5M tests @@ -258,52 +262,58 @@ pub fn iteration_count(ctx: &CheckCtx, argnum: usize) -> u64 { // Run fewer random tests than domain tests. let random_iter_count = domain_iter_count / 100; + let mut should_adjust = true; let mut total_iterations = match ctx.gen_kind { - GeneratorKind::Spaced if ctx.extensive => extensive_max_iterations(), + GeneratorKind::Spaced if ctx.extensive => { + // If an exact number is provided, no need to adjust + should_adjust = EXTENSIVE_ITER_OVERRIDE.is_none(); + extensive_max_iterations() + } GeneratorKind::Spaced => domain_iter_count, GeneratorKind::Random => random_iter_count, GeneratorKind::EdgeCases | GeneratorKind::List => { - unimplemented!("shoudn't need `iteration_count` for {:?}", ctx.gen_kind) + unimplemented!("shoudn't need `arg_max_iterations` for {:?}", ctx.gen_kind) } }; - // This signature has too many possible inputs to test exhaustively, so increase input count - // on all other kinds of tests to get better coverage. - if t_env.total_input_bits > MAX_REASONABLE_EXHAUSTIVE_BITS { - if ctx.extensive { - // Extensive already has a pretty high test count. - total_iterations *= 2; - } else { - total_iterations *= 4; + // Apply some adjustments so tests with more possible inputs (argument count or larger float + // types) get more tests. + if should_adjust { + // This signature has too many possible inputs to test exhaustively, so increase input count + // on all other kinds of tests to get better coverage. + if t_env.total_input_bits > MAX_REASONABLE_EXHAUSTIVE_BITS { + if ctx.extensive { + // Extensive already has a pretty high test count. + total_iterations *= 2; + } else { + total_iterations *= 4; + } } - } - // Functions with more arguments get more iterations. - let arg_multiplier = 1 << (t_env.input_count - 1); - total_iterations *= arg_multiplier; + // Functions with more arguments get more iterations. + let arg_multiplier = 1 << (t_env.input_count - 1); + total_iterations *= arg_multiplier; - // FMA has a huge domain but is reasonably fast to run, so increase another 1.5x. - if ctx.base_name == BaseName::Fma { - total_iterations = 3 * total_iterations / 2; - } + // FMA has a huge domain but is reasonably fast to run, so increase another 1.5x. + if ctx.base_name == BaseName::Fma { + total_iterations = 3 * total_iterations / 2; + } - // Some tests are significantly slower than others and need to be further reduced. - if let Some(slow) = EXTREMELY_SLOW_TESTS - .iter() - .find(|slow| slow.matches_ctx(ctx)) - { - // However, do not override if the extensive iteration count has been manually set. - if !(ctx.extensive && EXTENSIVE_ITER_OVERRIDE.is_some()) { + // Some tests are significantly slower than others and need to be further reduced. + if let Some(slow) = EXTREMELY_SLOW_TESTS + .iter() + .find(|slow| slow.matches_ctx(ctx)) + { total_iterations /= slow.reduce_factor; } - } - if cfg!(optimizations_enabled) { - // Always run at least 10,000 tests. - total_iterations = total_iterations.max(10_000); - } else { - // Without optimizations, just run a quick check regardless of other parameters. - total_iterations = 800; + if cfg!(optimizations_enabled) { + // Always run at least 10,000 tests. + total_iterations = total_iterations.max(10_000); + } else { + // Without optimizations, just run a quick check regardless of other parameters. + total_iterations = 800; + } } let mut overridden = false; @@ -312,7 +322,7 @@ pub fn iteration_count(ctx: &CheckCtx, argnum: usize) -> u64 { overridden = true; } - // Adjust for the number of inputs + // Distribute available iterations among inputs. let ntests = match t_env.input_count { 1 => total_iterations, 2 => (total_iterations as f64).sqrt().ceil() as u64, @@ -320,7 +330,7 @@ pub fn iteration_count(ctx: &CheckCtx, argnum: usize) -> u64 { _ => panic!("test has more than three arguments"), }; - let total = ntests.pow(t_env.input_count.try_into().unwrap()); + let total = ntests.saturating_pow(t_env.input_count.try_into().unwrap()); let seed_msg = match ctx.gen_kind { GeneratorKind::Spaced => String::new(), diff --git a/library/compiler-builtins/libm/Cargo.toml b/library/compiler-builtins/libm/Cargo.toml index 8d7fe9515e4d1..f9dbd29ffc3ea 100644 --- a/library/compiler-builtins/libm/Cargo.toml +++ b/library/compiler-builtins/libm/Cargo.toml @@ -16,7 +16,7 @@ edition = "2021" rust-version = "1.67" [dev-dependencies] -# FIXME(msrv): switch to `no-panic.workspace` when possible +# FIXME(msrv>=1.85): switch to `no-panic.workspace` no-panic = "0.1.36" [features] diff --git a/library/compiler-builtins/libm/src/lib.rs b/library/compiler-builtins/libm/src/lib.rs index 85ed5e2c9fc63..9c323347a04dd 100644 --- a/library/compiler-builtins/libm/src/lib.rs +++ b/library/compiler-builtins/libm/src/lib.rs @@ -1,5 +1,6 @@ //! libm in pure Rust #![no_std] +// #![cfg_attr(intrinsics_enabled, allow(internal_features))] #![cfg_attr(intrinsics_enabled, feature(core_intrinsics))] #![cfg_attr( @@ -8,21 +9,26 @@ )] #![cfg_attr(f128_enabled, feature(f128))] #![cfg_attr(f16_enabled, feature(f16))] -#![allow(unstable_name_collisions)] // FIXME(float_bits_const): remove when stable +// +// The edition is 2021 but we follow 2024 idioms. +#![deny(rust_2024_compatibility)] +#![allow(edition_2024_expr_fragment_specifier)] +// +// FIXME(float_bits_const): remove when stable +#![allow(unstable_name_collisions)] +// Allow idioms that come from ported C or may be more clear #![allow(clippy::assign_op_pattern)] -#![allow(clippy::deprecated_cfg_attr)] -#![allow(clippy::eq_op)] -#![allow(clippy::excessive_precision)] -#![allow(clippy::float_cmp)] #![allow(clippy::int_plus_one)] -#![allow(clippy::just_underscores_and_digits)] -#![allow(clippy::many_single_char_names)] -#![allow(clippy::mixed_case_hex_literals)] #![allow(clippy::needless_late_init)] #![allow(clippy::needless_return)] -#![allow(clippy::unreadable_literal)] +// Literals are usually intentional +#![allow(clippy::excessive_precision)] +// Allow needed patterns like `(z - z) / (z - z)` and `0.0 / 0.0` that we need for exceptions +// and rounding. +#![allow(clippy::eq_op)] #![allow(clippy::zero_divided_by_zero)] -#![forbid(unsafe_op_in_unsafe_fn)] +// In generic code we use bits like `let _0 = F::ZERO` +#![allow(clippy::just_underscores_and_digits)] mod libm_helper; mod math; diff --git a/library/compiler-builtins/libm/src/math/arch/loongarch/fma.rs b/library/compiler-builtins/libm/src/math/arch/loongarch/fma.rs new file mode 100644 index 0000000000000..8ea24ea6954ff --- /dev/null +++ b/library/compiler-builtins/libm/src/math/arch/loongarch/fma.rs @@ -0,0 +1,31 @@ +use core::arch::asm; + +#[cfg(target_feature = "d")] +pub fn fma(mut x: f64, y: f64, z: f64) -> f64 { + // SAFETY: `fmadd.d` is available with `d and has no side effects. + unsafe { + asm!( + "fmadd.d {x}, {x}, {y}, {z}", + x = inout(freg) x, + y = in(freg) y, + z = in(freg) z, + options(nomem, nostack, pure) + ); + } + x +} + +#[cfg(target_feature = "f")] +pub fn fmaf(mut x: f32, y: f32, z: f32) -> f32 { + // SAFETY: `fmadd.s` is available with `f` and has no side effects. + unsafe { + asm!( + "fmadd.s {x}, {x}, {y}, {z}", + x = inout(freg) x, + y = in(freg) y, + z = in(freg) z, + options(nomem, nostack, pure) + ); + } + x +} diff --git a/library/compiler-builtins/libm/src/math/arch/loongarch/mod.rs b/library/compiler-builtins/libm/src/math/arch/loongarch/mod.rs new file mode 100644 index 0000000000000..90c61e30ec067 --- /dev/null +++ b/library/compiler-builtins/libm/src/math/arch/loongarch/mod.rs @@ -0,0 +1,16 @@ +//! Architecture-specific support for LoongArch with FPU + +mod fma; +mod rounding; +mod sqrt; + +#[cfg(target_feature = "d")] +pub use fma::fma; +#[cfg(target_feature = "f")] +pub use fma::fmaf; +#[cfg(target_feature = "lsx")] +pub use rounding::{rint, rintf}; +#[cfg(target_feature = "d")] +pub use sqrt::sqrt; +#[cfg(target_feature = "f")] +pub use sqrt::sqrtf; diff --git a/library/compiler-builtins/libm/src/math/arch/loongarch/rounding.rs b/library/compiler-builtins/libm/src/math/arch/loongarch/rounding.rs new file mode 100644 index 0000000000000..ebbef09fea127 --- /dev/null +++ b/library/compiler-builtins/libm/src/math/arch/loongarch/rounding.rs @@ -0,0 +1,39 @@ +//! NB: `frint.{s.d}` is technically the correct instruction for C's `rint`. +//! However, in Rust (and LLVM by default), `rint` is identical to `roundeven` +//! (no fpenv interaction) so we use the side-effect-free `vfrintrne.{s,d}`. +//! +//! In general, C code that calls Rust's libm should assume that fpenv is ignored. + +use core::arch::asm; + +#[cfg(target_feature = "lsx")] +pub fn rint(mut x: f64) -> f64 { + // SAFETY: `vfrintrne.d` is available with `lsx` and has no side effects. + // + // `vfrintrne.d` is always round-to-nearest which does not match the + // C specification, but Rust does not support rounding modes. + unsafe { + asm!( + "vfrintrne.d {x:w}, {x:w}", + x = inout(freg) x, + options(nomem, nostack, pure) + ); + } + x +} + +#[cfg(target_feature = "lsx")] +pub fn rintf(mut x: f32) -> f32 { + // SAFETY: `vfrintrne.s` is available with `lsx` and has no side effects. + // + // `vfrintrne.s` is always round-to-nearest which does not match the + // C specification, but Rust does not support rounding modes. + unsafe { + asm!( + "vfrintrne.s {x:w}, {x:w}", + x = inout(freg) x, + options(nomem, nostack, pure) + ); + } + x +} diff --git a/library/compiler-builtins/libm/src/math/arch/loongarch/sqrt.rs b/library/compiler-builtins/libm/src/math/arch/loongarch/sqrt.rs new file mode 100644 index 0000000000000..e23d3facc0375 --- /dev/null +++ b/library/compiler-builtins/libm/src/math/arch/loongarch/sqrt.rs @@ -0,0 +1,27 @@ +use core::arch::asm; + +#[cfg(target_feature = "d")] +pub fn sqrt(mut x: f64) -> f64 { + // SAFETY: `fsqrt.d` is available with `d` and has no side effects. + unsafe { + asm!( + "fsqrt.d {x}, {x}", + x = inout(freg) x, + options(nomem, nostack, pure) + ); + } + x +} + +#[cfg(target_feature = "f")] +pub fn sqrtf(mut x: f32) -> f32 { + // SAFETY: `fsqrt.s` is available with `f` and has no side effects. + unsafe { + asm!( + "fsqrt.s {x}, {x}", + x = inout(freg) x, + options(nomem, nostack, pure) + ); + } + x +} diff --git a/library/compiler-builtins/libm/src/math/arch/mod.rs b/library/compiler-builtins/libm/src/math/arch/mod.rs index 1bed464cfa7d6..ab2c4a17760b4 100644 --- a/library/compiler-builtins/libm/src/math/arch/mod.rs +++ b/library/compiler-builtins/libm/src/math/arch/mod.rs @@ -6,21 +6,24 @@ //! well as improving things when these routines are called as part of other implementations. // Most implementations should be defined here, to ensure they are not made available when -// soft floats are required. -#[cfg(feature = "arch")] -cfg_if! { - if #[cfg(all(target_arch = "wasm32", intrinsics_enabled))] { +// soft floats are required. Primarily gated on the `arch` feature, Miri does not support inline +// assembly. +#[cfg(all(feature = "arch", not(miri)))] +cfg_select_nofmt! { + all(target_arch = "wasm32", intrinsics_enabled) => { mod wasm32; pub use wasm32::{ ceil, ceilf, fabs, fabsf, floor, floorf, rint, rintf, sqrt, sqrtf, trunc, truncf, }; - } else if #[cfg(target_feature = "sse2")] { + } + target_feature = "sse2" => { mod x86; pub use x86::{sqrt, sqrtf, fma, fmaf}; - } else if #[cfg(all( + } + all( any(target_arch = "aarch64", target_arch = "arm64ec"), target_feature = "neon" - ))] { + ) => { mod aarch64; pub use aarch64::{ @@ -38,12 +41,27 @@ cfg_if! { sqrtf16, }; } + any(target_arch = "loongarch32", target_arch = "loongarch64") => { + mod loongarch; + + #[cfg(target_feature = "d")] + pub use loongarch::fma; + #[cfg(target_feature = "f")] + pub use loongarch::fmaf; + #[cfg(target_feature = "lsx")] + pub use loongarch::{rint, rintf}; + #[cfg(target_feature = "d")] + pub use loongarch::sqrt; + #[cfg(target_feature = "f")] + pub use loongarch::sqrtf; + } + _ => {} } // There are certain architecture-specific implementations that are needed for correctness // even with `arch` disabled. These are configured here. -cfg_if! { - if #[cfg(x86_no_sse2)] { +cfg_select_nofmt! { + x86_no_sse2 => { mod i586; pub use i586::{ ceil, @@ -57,4 +75,5 @@ cfg_if! { x87_expf, }; } + _ => {} } diff --git a/library/compiler-builtins/libm/src/math/fdim.rs b/library/compiler-builtins/libm/src/math/fdim.rs index dac409e86b135..b61630847f808 100644 --- a/library/compiler-builtins/libm/src/math/fdim.rs +++ b/library/compiler-builtins/libm/src/math/fdim.rs @@ -2,8 +2,8 @@ /// /// Determines the positive difference between arguments, returning: /// * x - y if x > y, or -/// * +0 if x <= y, or -/// * NAN if either argument is NAN. +/// * +0 if x <= y, or +/// * NAN if either argument is NAN. /// /// A range error may occur. #[cfg(f16_enabled)] @@ -16,8 +16,8 @@ pub fn fdimf16(x: f16, y: f16) -> f16 { /// /// Determines the positive difference between arguments, returning: /// * x - y if x > y, or -/// * +0 if x <= y, or -/// * NAN if either argument is NAN. +/// * +0 if x <= y, or +/// * NAN if either argument is NAN. /// /// A range error may occur. #[cfg_attr(assert_no_panic, no_panic::no_panic)] @@ -29,8 +29,8 @@ pub fn fdimf(x: f32, y: f32) -> f32 { /// /// Determines the positive difference between arguments, returning: /// * x - y if x > y, or -/// * +0 if x <= y, or -/// * NAN if either argument is NAN. +/// * +0 if x <= y, or +/// * NAN if either argument is NAN. /// /// A range error may occur. #[cfg_attr(assert_no_panic, no_panic::no_panic)] @@ -42,8 +42,8 @@ pub fn fdim(x: f64, y: f64) -> f64 { /// /// Determines the positive difference between arguments, returning: /// * x - y if x > y, or -/// * +0 if x <= y, or -/// * NAN if either argument is NAN. +/// * +0 if x <= y, or +/// * NAN if either argument is NAN. /// /// A range error may occur. #[cfg(f128_enabled)] @@ -51,3 +51,101 @@ pub fn fdim(x: f64, y: f64) -> f64 { pub fn fdimf128(x: f128, y: f128) -> f128 { super::generic::fdim(x, y) } + +#[cfg(test)] +mod tests { + use crate::support::{Float, Hex}; + + macro_rules! cases { + ($f:ty) => { + [ + // x = -inf + (<$f>::NEG_INFINITY, <$f>::NEG_INFINITY, 0.0), + (<$f>::NEG_INFINITY, -1.0, 0.0), + (<$f>::NEG_INFINITY, -0.0, 0.0), + (<$f>::NEG_INFINITY, 0.0, 0.0), + (<$f>::NEG_INFINITY, 1.0, 0.0), + (<$f>::NEG_INFINITY, <$f>::INFINITY, 0.0), + (<$f>::NEG_INFINITY, <$f>::NAN, <$f>::NAN), + // x = -1.0 + (-1.0, <$f>::NEG_INFINITY, <$f>::INFINITY), + (-1.0, -1.0, 0.0), + (-1.0, -0.0, 0.0), + (-1.0, 0.0, 0.0), + (-1.0, 1.0, 0.0), + (-1.0, <$f>::INFINITY, 0.0), + (-1.0, <$f>::NAN, <$f>::NAN), + // x = -0.0 + (-0.0, <$f>::NEG_INFINITY, <$f>::INFINITY), + (-0.0, -1.0, 1.0), + (-0.0, -0.0, 0.0), + (-0.0, 0.0, 0.0), + (-0.0, 1.0, 0.0), + (-0.0, <$f>::INFINITY, 0.0), + (-0.0, <$f>::NAN, <$f>::NAN), + // x = 0.0 + (0.0, <$f>::NEG_INFINITY, <$f>::INFINITY), + (0.0, -1.0, 1.0), + (0.0, -0.0, 0.0), + (0.0, 0.0, 0.0), + (0.0, 1.0, 0.0), + (0.0, <$f>::INFINITY, 0.0), + (0.0, <$f>::NAN, <$f>::NAN), + // x = 1.0 + (1.0, <$f>::NEG_INFINITY, <$f>::INFINITY), + (1.0, -1.0, 2.0), + (1.0, -0.0, 1.0), + (1.0, 0.0, 1.0), + (1.0, 1.0, 0.0), + (1.0, <$f>::INFINITY, 0.0), + (1.0, <$f>::NAN, <$f>::NAN), + // x = inf + (<$f>::INFINITY, <$f>::NEG_INFINITY, <$f>::INFINITY), + (<$f>::INFINITY, -1.0, <$f>::INFINITY), + (<$f>::INFINITY, -0.0, <$f>::INFINITY), + (<$f>::INFINITY, 0.0, <$f>::INFINITY), + (<$f>::INFINITY, 1.0, <$f>::INFINITY), + (<$f>::INFINITY, <$f>::INFINITY, 0.0), + (<$f>::INFINITY, <$f>::NAN, <$f>::NAN), + // x = nan + (<$f>::NAN, <$f>::NEG_INFINITY, <$f>::NAN), + (<$f>::NAN, -1.0, <$f>::NAN), + (<$f>::NAN, -0.0, <$f>::NAN), + (<$f>::NAN, 0.0, <$f>::NAN), + (<$f>::NAN, 1.0, <$f>::NAN), + (<$f>::NAN, <$f>::INFINITY, <$f>::NAN), + (<$f>::NAN, <$f>::NAN, <$f>::NAN), + ] + }; + } + + #[track_caller] + fn check(f: fn(F, F) -> F, cases: &[(F, F, F)]) { + for &(x, y, exp_res) in cases { + let val = f(x, y); + assert_biteq!(val, exp_res, "fdim({x:?}, {y:?}) ({} {})", Hex(x), Hex(y)); + } + } + + #[test] + #[cfg(f16_enabled)] + fn check_f16() { + check::(super::super::fdimf16, &cases!(f16)); + } + + #[test] + fn check_f32() { + check::(super::super::fdimf, &cases!(f32)); + } + + #[test] + fn check_f64() { + check::(super::super::fdim, &cases!(f64)); + } + + #[test] + #[cfg(f128_enabled)] + fn check_f128() { + check::(super::super::fdimf128, &cases!(f128)); + } +} diff --git a/library/compiler-builtins/libm/src/math/fma.rs b/library/compiler-builtins/libm/src/math/fma.rs index 513921d530faf..e6b9e8fa1b60b 100644 --- a/library/compiler-builtins/libm/src/math/fma.rs +++ b/library/compiler-builtins/libm/src/math/fma.rs @@ -1,6 +1,3 @@ -/* SPDX-License-Identifier: MIT */ -/* origin: musl src/math/fma.c, fmaf.c Ported to generic Rust algorithm in 2025, TG. */ - use super::generic; use crate::support::Round; @@ -15,6 +12,7 @@ pub fn fmaf(x: f32, y: f32, z: f32) -> f32 { name: fmaf, use_arch: any( all(target_arch = "aarch64", target_feature = "neon"), + all(any(target_arch = "loongarch32", target_arch = "loongarch64"), target_feature = "f"), target_feature = "sse2", ), args: x, y, z, @@ -32,6 +30,7 @@ pub fn fma(x: f64, y: f64, z: f64) -> f64 { name: fma, use_arch: any( all(target_arch = "aarch64", target_feature = "neon"), + all(any(target_arch = "loongarch32", target_arch = "loongarch64"), target_feature = "d"), target_feature = "sse2", ), args: x, y, z, diff --git a/library/compiler-builtins/libm/src/math/generic/fma_wide.rs b/library/compiler-builtins/libm/src/math/generic/fma_wide.rs index a2ef59d3e3d6f..e7d540694135d 100644 --- a/library/compiler-builtins/libm/src/math/generic/fma_wide.rs +++ b/library/compiler-builtins/libm/src/math/generic/fma_wide.rs @@ -1,5 +1,8 @@ +/* SPDX-License-Identifier: MIT */ +/* origin: musl src/math/fmaf.c Ported to generic Rust algorithm in 2025, TG. */ + use crate::support::{ - CastFrom, CastInto, DFloat, Float, FpResult, HFloat, IntTy, MinInt, Round, Status, + CastFrom, CastInto, Float, FpResult, IntTy, MinInt, NarrowFloat, Round, Status, WideFloat, }; /// Fma implementation when a hardware-backed larger float type is available. For `f32` and `f64`, @@ -7,8 +10,8 @@ use crate::support::{ #[inline] pub fn fma_wide_round(x: F, y: F, z: F, round: Round) -> FpResult where - F: Float + HFloat, - B: Float + DFloat, + F: Float + NarrowFloat, + B: Float + WideFloat, B::Int: CastInto, i32: CastFrom, { diff --git a/library/compiler-builtins/libm/src/math/lgammaf_r.rs b/library/compiler-builtins/libm/src/math/lgammaf_r.rs index 5c087f14d7df2..9e60bb267cb77 100644 --- a/library/compiler-builtins/libm/src/math/lgammaf_r.rs +++ b/library/compiler-builtins/libm/src/math/lgammaf_r.rs @@ -178,7 +178,7 @@ pub fn lgammaf_r(mut x: f32) -> (f32, i32) { /* [1.7316,2] */ y = 2.0 - x; i = 0; - } else if ix >= 0x3F9da620 { + } else if ix >= 0x3f9da620 { /* [1.23,1.73] */ y = x - TC; i = 1; diff --git a/library/compiler-builtins/libm/src/math/mod.rs b/library/compiler-builtins/libm/src/math/mod.rs index 809d5e5d18092..50b42e0c07972 100644 --- a/library/compiler-builtins/libm/src/math/mod.rs +++ b/library/compiler-builtins/libm/src/math/mod.rs @@ -67,15 +67,16 @@ pub mod support; #[cfg(not(feature = "unstable-public-internals"))] pub(crate) mod support; -cfg_if! { - if #[cfg(feature = "unstable-public-internals")] { +cfg_select_nofmt! { + feature = "unstable-public-internals" => { pub mod generic; - } else { + } + _ => { mod generic; } } -pub mod approx; +pub mod relaxed; // Private modules mod arch; @@ -106,7 +107,9 @@ use self::rem_pio2::rem_pio2; use self::rem_pio2_large::rem_pio2_large; use self::rem_pio2f::rem_pio2f; #[allow(unused_imports)] -use self::support::{CastFrom, CastInto, DFloat, DInt, Float, HFloat, HInt, Int, IntTy, MinInt}; +use self::support::{ + CastFrom, CastInto, DInt, Float, HInt, Int, IntTy, MinInt, NarrowFloat, WideFloat, +}; // Public modules mod acos; @@ -294,8 +297,8 @@ pub use self::tgamma::tgamma; pub use self::tgammaf::tgammaf; pub use self::trunc::{trunc, truncf}; -cfg_if! { - if #[cfg(f16_enabled)] { +cfg_select_nofmt! { + f16_enabled => { mod fmaf16; // verify-sorted-start @@ -320,10 +323,11 @@ cfg_if! { pub use self::trunc::truncf16; // verify-sorted-end } + _ => {} } -cfg_if! { - if #[cfg(f128_enabled)] { +cfg_select_nofmt! { + f128_enabled => { // verify-sorted-start pub use self::ceil::ceilf128; pub use self::copysign::copysignf128; @@ -346,6 +350,7 @@ cfg_if! { pub use self::trunc::truncf128; // verify-sorted-end } + _ => {} } #[inline] diff --git a/library/compiler-builtins/libm/src/math/approx/cbrtf64.rs b/library/compiler-builtins/libm/src/math/relaxed/cbrtf64.rs similarity index 100% rename from library/compiler-builtins/libm/src/math/approx/cbrtf64.rs rename to library/compiler-builtins/libm/src/math/relaxed/cbrtf64.rs diff --git a/library/compiler-builtins/libm/src/math/approx/hypot.rs b/library/compiler-builtins/libm/src/math/relaxed/hypotf64.rs similarity index 95% rename from library/compiler-builtins/libm/src/math/approx/hypot.rs rename to library/compiler-builtins/libm/src/math/relaxed/hypotf64.rs index c0b2a19370cd7..ae4196aefff03 100644 --- a/library/compiler-builtins/libm/src/math/approx/hypot.rs +++ b/library/compiler-builtins/libm/src/math/relaxed/hypotf64.rs @@ -1,4 +1,4 @@ -use super::sqrt; +use super::super::sqrt; const SPLIT: f64 = 134217728. + 1.; // 0x1p27 + 1 === (2 ^ 27) + 1 @@ -16,7 +16,7 @@ fn sq(x: f64) -> (f64, f64) { } #[cfg_attr(assert_no_panic, no_panic::no_panic)] -pub fn hypot(mut x: f64, mut y: f64) -> f64 { +pub fn hypotf64(mut x: f64, mut y: f64) -> f64 { let x1p700 = f64::from_bits(0x6bb0000000000000); // 0x1p700 === 2 ^ 700 let x1p_700 = f64::from_bits(0x1430000000000000); // 0x1p-700 === 2 ^ -700 diff --git a/library/compiler-builtins/libm/src/math/approx/mod.rs b/library/compiler-builtins/libm/src/math/relaxed/mod.rs similarity index 66% rename from library/compiler-builtins/libm/src/math/approx/mod.rs rename to library/compiler-builtins/libm/src/math/relaxed/mod.rs index da0d0bf39efc4..ed3b4146249fb 100644 --- a/library/compiler-builtins/libm/src/math/approx/mod.rs +++ b/library/compiler-builtins/libm/src/math/relaxed/mod.rs @@ -1,8 +1,10 @@ -//! Approximate implementations. +//! Relaxed precision implementations. //! //! These functions may be smaller or faster than those in the main `math` module, but will //! not be as accurate. mod cbrtf64; +mod hypotf64; pub use cbrtf64::cbrtf64; +pub use hypotf64::hypotf64; diff --git a/library/compiler-builtins/libm/src/math/rint.rs b/library/compiler-builtins/libm/src/math/rint.rs index 75c46acc0e856..ca3864b1582c9 100644 --- a/library/compiler-builtins/libm/src/math/rint.rs +++ b/library/compiler-builtins/libm/src/math/rint.rs @@ -20,6 +20,7 @@ pub fn rintf(x: f32) -> f32 { name: rintf, use_arch: any( all(target_arch = "aarch64", target_feature = "neon"), + all(any(target_arch = "loongarch32", target_arch = "loongarch64"), target_feature = "lsx"), all(target_arch = "wasm32", intrinsics_enabled), ), args: x, @@ -35,6 +36,7 @@ pub fn rint(x: f64) -> f64 { name: rint, use_arch: any( all(target_arch = "aarch64", target_feature = "neon"), + all(any(target_arch = "loongarch32", target_arch = "loongarch64"), target_feature = "lsx"), all(target_arch = "wasm32", intrinsics_enabled), ), use_arch_required: x86_no_sse2, diff --git a/library/compiler-builtins/libm/src/math/sin.rs b/library/compiler-builtins/libm/src/math/sin.rs index 2f54074c25ef0..ded0df85ad237 100644 --- a/library/compiler-builtins/libm/src/math/sin.rs +++ b/library/compiler-builtins/libm/src/math/sin.rs @@ -88,7 +88,7 @@ mod tests { #[test] #[cfg_attr(x86_no_sse2, ignore = "FIXME(i586): possible incorrect rounding")] fn test_near_pi() { - let x = f64::from_bits(0x400921fb000FD5DD); // 3.141592026217707 + let x = f64::from_bits(0x400921fb000fd5dd); // 3.141592026217707 let sx = f64::from_bits(0x3ea50d15ced1a4a2); // 6.273720864039205e-7 assert_eq!(sin(x), sx); } diff --git a/library/compiler-builtins/libm/src/math/sqrt.rs b/library/compiler-builtins/libm/src/math/sqrt.rs index 10edf397a0a0a..a8e2a387661cf 100644 --- a/library/compiler-builtins/libm/src/math/sqrt.rs +++ b/library/compiler-builtins/libm/src/math/sqrt.rs @@ -22,6 +22,7 @@ pub fn sqrtf(x: f32) -> f32 { use_arch: any( all(target_arch = "aarch64", target_feature = "neon"), all(target_arch = "wasm32", intrinsics_enabled), + all(any(target_arch = "loongarch32", target_arch = "loongarch64"), target_feature = "f"), target_feature = "sse2" ), args: x, @@ -38,6 +39,7 @@ pub fn sqrt(x: f64) -> f64 { use_arch: any( all(target_arch = "aarch64", target_feature = "neon"), all(target_arch = "wasm32", intrinsics_enabled), + all(any(target_arch = "loongarch32", target_arch = "loongarch64"), target_feature = "d"), target_feature = "sse2" ), args: x, diff --git a/library/compiler-builtins/libm/src/math/support/big.rs b/library/compiler-builtins/libm/src/math/support/big.rs index c316d93f524ab..9b8728c987cfd 100644 --- a/library/compiler-builtins/libm/src/math/support/big.rs +++ b/library/compiler-builtins/libm/src/math/support/big.rs @@ -294,11 +294,12 @@ impl fmt::Debug for i256 { impl fmt::LowerHex for u256 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - cfg_if! { - if #[cfg(feature = "compiler-builtins")] { + cfg_select_nofmt! { + feature = "compiler-builtins" => { let _ = f; unimplemented!() - } else { + } + _ => { let pfx= if f.alternate() { "0x"} else {""}; write!(f, "{pfx}{:032x}{:032x}", self.hi, self.lo) } diff --git a/library/compiler-builtins/libm/src/math/support/big/tests.rs b/library/compiler-builtins/libm/src/math/support/big/tests.rs index 0ac8f9721a4dd..2f0ba7ebc3182 100644 --- a/library/compiler-builtins/libm/src/math/support/big/tests.rs +++ b/library/compiler-builtins/libm/src/math/support/big/tests.rs @@ -488,6 +488,7 @@ fn i256_shifts() { } } #[test] +#[cfg_attr(miri, ignore)] // This test is very slow when using Miri fn div_u256_by_u128() { for j in i8::MIN..=i8::MAX { let y: u128 = (j as i128).rotate_right(4).unsigned(); diff --git a/library/compiler-builtins/libm/src/math/support/float_traits.rs b/library/compiler-builtins/libm/src/math/support/float_traits.rs index 7bc9734a20994..f802f4be6c2d7 100644 --- a/library/compiler-builtins/libm/src/math/support/float_traits.rs +++ b/library/compiler-builtins/libm/src/math/support/float_traits.rs @@ -337,31 +337,34 @@ macro_rules! float_impl { Self::from_bits(a) } fn abs(self) -> Self { - cfg_if! { + cfg_select_nofmt! { // FIXME(msrv): `abs` is available in `core` starting with 1.85. - if #[cfg(intrinsics_enabled)] { + intrinsics_enabled => { self.abs() - } else { + } + _ => { super::super::generic::fabs(self) } } } fn copysign(self, other: Self) -> Self { - cfg_if! { + cfg_select_nofmt! { // FIXME(msrv): `copysign` is available in `core` starting with 1.85. - if #[cfg(intrinsics_enabled)] { + intrinsics_enabled => { self.copysign(other) - } else { + } + _ => { super::super::generic::copysign(self, other) } } } fn fma(self, y: Self, z: Self) -> Self { - cfg_if! { + cfg_select_nofmt! { // fma is not yet available in `core` - if #[cfg(intrinsics_enabled)] { + intrinsics_enabled => { core::intrinsics::$fma_intrinsic(self, y, z) - } else { + } + _ => { super::super::$fma_fn(self, y, z) } } @@ -453,28 +456,28 @@ pub const fn f64_to_bits(x: f64) -> u64 { unsafe { mem::transmute::(x) } } -/// Trait for floats twice the bit width of another integer. -pub trait DFloat: Float { +/// Trait for floats that are wider than a `NFloat` type. +pub trait WideFloat: Float { /// Float that is half the bit width of the floatthis trait is implemented for. - type H: HFloat; + type H: NarrowFloat; /// Narrow the float type. fn narrow(self) -> Self::H; } -/// Trait for floats half the bit width of another float. -pub trait HFloat: Float { +/// Trait for floats narrower than a `WFloat` type. +pub trait NarrowFloat: Float { /// Float that is double the bit width of the float this trait is implemented for. - type D: DFloat; + type D: WideFloat; /// Widen the float type. fn widen(self) -> Self::D; } -macro_rules! impl_d_float { +macro_rules! impl_wide_float { ($($X:ident $D:ident),*) => { $( - impl DFloat for $D { + impl WideFloat for $D { type H = $X; fn narrow(self) -> Self::H { @@ -485,10 +488,10 @@ macro_rules! impl_d_float { }; } -macro_rules! impl_h_float { +macro_rules! impl_narrow_float { ($($H:ident $X:ident),*) => { $( - impl HFloat for $H { + impl NarrowFloat for $H { type D = $X; fn widen(self) -> Self::D { @@ -499,17 +502,17 @@ macro_rules! impl_h_float { }; } -impl_d_float!(f32 f64); +impl_wide_float!(f32 f64); #[cfg(f16_enabled)] -impl_d_float!(f16 f32); +impl_wide_float!(f16 f32); #[cfg(f128_enabled)] -impl_d_float!(f64 f128); +impl_wide_float!(f64 f128); -impl_h_float!(f32 f64); +impl_narrow_float!(f32 f64); #[cfg(f16_enabled)] -impl_h_float!(f16 f32); +impl_narrow_float!(f16 f32); #[cfg(f128_enabled)] -impl_h_float!(f64 f128); +impl_narrow_float!(f64 f128); #[cfg(test)] mod tests { diff --git a/library/compiler-builtins/libm/src/math/support/hex_float.rs b/library/compiler-builtins/libm/src/math/support/hex_float.rs index e1100a4a119f0..607ba7964023b 100644 --- a/library/compiler-builtins/libm/src/math/support/hex_float.rs +++ b/library/compiler-builtins/libm/src/math/support/hex_float.rs @@ -448,11 +448,12 @@ mod hex_fmt { // Not really a meaningful impl, but makes some generics easier. impl DisplayHex for bool { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - cfg_if! { - if #[cfg(feature = "compiler-builtins")] { + cfg_select_nofmt! { + feature = "compiler-builtins" => { let _ = f; unimplemented!() - } else { + } + _ => { write!(f, "{self}") } } @@ -585,6 +586,7 @@ mod parse_tests { } #[test] + #[cfg_attr(miri, ignore)] // This test is very slow when using Miri fn test_parse_any() { for k in -149..=127 { let s = format!("0x1p{k}"); @@ -676,6 +678,7 @@ mod parse_tests { } } #[test] + #[cfg_attr(miri, ignore)] // This test is very slow when using Miri fn long_tail() { for k in 1..1000 { let s = format!("0x1.{}p0", "0".repeat(k)); diff --git a/library/compiler-builtins/libm/src/math/support/int_traits.rs b/library/compiler-builtins/libm/src/math/support/int_traits.rs index f113f9d62d143..48c0e0438bc1d 100644 --- a/library/compiler-builtins/libm/src/math/support/int_traits.rs +++ b/library/compiler-builtins/libm/src/math/support/int_traits.rs @@ -110,6 +110,7 @@ pub trait Int: fn borrowing_sub(self, other: Self, borrow: bool) -> (Self, bool); fn leading_zeros(self) -> u32; fn trailing_zeros(self) -> u32; + fn count_ones(self) -> u32; fn ilog2(self) -> u32; } @@ -179,6 +180,10 @@ macro_rules! int_impl_common { ::trailing_zeros(self) } + fn count_ones(self) -> u32 { + ::count_ones(self) + } + fn ilog2(self) -> u32 { // On our older MSRV, this resolves to the trait method. Which won't actually work, // but this is only called behind other gates. diff --git a/library/compiler-builtins/libm/src/math/support/int_traits/narrowing_div.rs b/library/compiler-builtins/libm/src/math/support/int_traits/narrowing_div.rs index e76fc5ae9f4ca..942cd5ed2acc0 100644 --- a/library/compiler-builtins/libm/src/math/support/int_traits/narrowing_div.rs +++ b/library/compiler-builtins/libm/src/math/support/int_traits/narrowing_div.rs @@ -153,6 +153,7 @@ mod test { use super::{HInt, NarrowingDiv}; #[test] + #[cfg_attr(miri, ignore)] // This test is very slow when using Miri fn inverse_mul() { for x in 0..=u8::MAX { for y in 1..=u8::MAX { diff --git a/library/compiler-builtins/libm/src/math/support/macros.rs b/library/compiler-builtins/libm/src/math/support/macros.rs index f1bfa21eec7f7..767f15a1c14a3 100644 --- a/library/compiler-builtins/libm/src/math/support/macros.rs +++ b/library/compiler-builtins/libm/src/math/support/macros.rs @@ -1,67 +1,28 @@ -/// `libm` cannot have dependencies, so this is vendored directly from the `cfg-if` crate -/// (with some comments stripped for compactness). -macro_rules! cfg_if { - ( - if #[cfg( $($i_meta:tt)+ )] { $( $i_tokens:tt )* } - $( - else if #[cfg( $($ei_meta:tt)+ )] { $( $ei_tokens:tt )* } - )* - $( - else { $( $e_tokens:tt )* } - )? - ) => { - cfg_if! { - @__items () ; - (( $($i_meta)+ ) ( $( $i_tokens )* )), - $( - (( $($ei_meta)+ ) ( $( $ei_tokens )* )), - )* - $( - (() ( $( $e_tokens )* )), - )? - } +// Because `cfg_select` requires rust verion 1.95 and we support older versions, +// we use the following replacement until that is no longer true. +// +// Doesn't support the syntax that rustfmt changes to, hence not calling it just +// `cfg_seelect`. +// +// FIXME(msrv) +macro_rules! cfg_select_nofmt { + ({ $($tt:tt)* }) => {{ + $crate::cfg_select_nofmt! { $($tt)* } + }}; + (_ => { $($output:tt)* }) => { + $($output)* }; - - // Internal and recursive macro to emit all the items - // - // Collects all the previous cfgs in a list at the beginning, so they can be - // negated. After the semicolon are all the remaining items. - (@__items ( $( ($($_:tt)*) , )* ) ; ) => {}; ( - @__items ( $( ($($no:tt)+) , )* ) ; - (( $( $($yes:tt)+ )? ) ( $( $tokens:tt )* )), - $( $rest:tt , )* + $cfg:meta => $output:tt + $($( $rest:tt )+)? ) => { - // Emit all items within one block, applying an appropriate #[cfg]. The - // #[cfg] will require all `$yes` matchers specified and must also negate - // all previous matchers. - #[cfg(all( - $( $($yes)+ , )? - not(any( $( $($no)+ ),* )) - ))] - // Subtle: You might think we could put `$( $tokens )*` here. But if - // that contains multiple items then the `#[cfg(all(..))]` above would - // only apply to the first one. By wrapping `$( $tokens )*` in this - // macro call, we temporarily group the items into a single thing (the - // macro call) that will be included/excluded by the `#[cfg(all(..))]` - // as appropriate. If the `#[cfg(all(..))]` succeeds, the macro call - // will be included, and then evaluated, producing `$( $tokens )*`. See - // also the "issue #90" test below. - cfg_if! { @__temp_group $( $tokens )* } - - // Recurse to emit all other items in `$rest`, and when we do so add all - // our `$yes` matchers to the list of `$no` matchers as future emissions - // will have to negate everything we just matched as well. - cfg_if! { - @__items ( $( ($($no)+) , )* $( ($($yes)+) , )? ) ; - $( $rest , )* - } - }; - - // See the "Subtle" comment above. - (@__temp_group $( $tokens:tt )* ) => { - $( $tokens )* - }; + #[cfg($cfg)] + cfg_select_nofmt! { _ => $output } + $( + #[cfg(not($cfg))] + cfg_select_nofmt! { $($rest)+ } + )? + } } /// Choose between using an arch-specific implementation and the function body. Returns directly @@ -96,8 +57,9 @@ macro_rules! select_implementation { } } - // By default, never use arch-specific implementations if `arch` is disabled. - #[cfg(feature = "arch")] + // By default, never use arch-specific implementations if `arch` is disabled or with Miri + // (no inline assembly support). + #[cfg(all(feature = "arch", not(miri)))] select_implementation! { @cfg $($use_arch)?; // Wrap in `if true` to avoid unused warnings diff --git a/library/compiler-builtins/libm/src/math/support/mod.rs b/library/compiler-builtins/libm/src/math/support/mod.rs index 61999a1f94059..260c37080c981 100644 --- a/library/compiler-builtins/libm/src/math/support/mod.rs +++ b/library/compiler-builtins/libm/src/math/support/mod.rs @@ -14,10 +14,10 @@ mod modular; pub use big::{i256, u256}; // Clippy seems to have a false positive #[allow(unused_imports, clippy::single_component_path_imports)] -pub(crate) use cfg_if; +pub(crate) use cfg_select_nofmt; pub use env::{FpResult, Round, Status}; #[allow(unused_imports)] -pub use float_traits::{DFloat, Float, HFloat, HalfRep, IntTy}; +pub use float_traits::{Float, HalfRep, IntTy, NarrowFloat, WideFloat}; pub(crate) use float_traits::{f32_from_bits, f64_from_bits}; #[cfg(f16_enabled)] #[allow(unused_imports)] @@ -40,8 +40,8 @@ pub fn cold_path() { /// /// `y` must not be zero and the result must not overflow (`x > i32::MIN`). pub unsafe fn unchecked_div_i32(x: i32, y: i32) -> i32 { - cfg_if! { - if #[cfg(all(not(debug_assertions), intrinsics_enabled))] { + cfg_select_nofmt! { + all(not(debug_assertions), intrinsics_enabled) => { // Temporary macro to avoid panic codegen for division (in debug mode too). At // the time of this writing this is only used in a few places, and once // rust-lang/rust#72751 is fixed then this macro will no longer be necessary and @@ -50,7 +50,8 @@ pub unsafe fn unchecked_div_i32(x: i32, y: i32) -> i32 { // Note: I am not sure whether the above comment is still up to date, we need // to double check whether panics are elided where we use this. unsafe { core::intrinsics::unchecked_div(x, y) } - } else { + } + _ => { x / y } } @@ -60,10 +61,11 @@ pub unsafe fn unchecked_div_i32(x: i32, y: i32) -> i32 { /// /// `y` must not be zero and the result must not overflow (`x > isize::MIN`). pub unsafe fn unchecked_div_isize(x: isize, y: isize) -> isize { - cfg_if! { - if #[cfg(all(not(debug_assertions), intrinsics_enabled))] { + cfg_select_nofmt! { + all(not(debug_assertions), intrinsics_enabled) => { unsafe { core::intrinsics::unchecked_div(x, y) } - } else { + } + _ => { x / y } } diff --git a/library/compiler-builtins/libm/src/math/support/modular.rs b/library/compiler-builtins/libm/src/math/support/modular.rs index cc0edf2f2bc04..026c599c1bba4 100644 --- a/library/compiler-builtins/libm/src/math/support/modular.rs +++ b/library/compiler-builtins/libm/src/math/support/modular.rs @@ -231,6 +231,7 @@ mod test { use crate::support::modular::Reducer; #[test] + #[cfg_attr(miri, ignore)] // This test is very slow when using Miri fn reducer_ops() { for n in 33..=63_u8 { for x in 0..2 * n { @@ -259,6 +260,7 @@ mod test { } } #[test] + #[cfg_attr(miri, ignore)] // This test is very slow when using Miri fn reduction_u8() { for y in 1..64u8 { for x in 0..2 * y { diff --git a/library/compiler-builtins/rust-version b/library/compiler-builtins/rust-version index e3a2981071adc..2f175e966812d 100644 --- a/library/compiler-builtins/rust-version +++ b/library/compiler-builtins/rust-version @@ -1 +1 @@ -68ffae46b581747074413e4242ab0c6ecc4db4a9 +2c39ff499469be916d4e45506d1afed69bbaddb7