Auto merge of #155709 - tgross35:compiler-builtins-sync-2026-04-22, r=tgross35

compiler-builtins subtree update

Subtree update of `compiler-builtins` to https://github.com/rust-lang/compiler-builtins/commit/4d3ab8695dcf965be926882c92878b99017bf99b.

Created using https://github.com/rust-lang/josh-sync.

Closes: https://github.com/rust-lang/rust/pull/155653
This commit is contained in:
bors
2026-04-24 10:39:25 +00:00
205 changed files with 9287 additions and 5064 deletions
+1 -3
View File
@@ -1,5 +1,3 @@
# EditorConfig helps developers define and maintain consistent
# coding styles between different editors and IDEs
# editorconfig.org
root = true
@@ -12,5 +10,5 @@ insert_final_newline = true
indent_style = space
indent_size = 4
[*.yml]
[*.{yaml,yml}]
indent_size = 2
+37
View File
@@ -0,0 +1,37 @@
{
$schema: "https://docs.renovatebot.com/renovate-schema.json",
extends: [
"config:recommended",
":maintainLockFilesMonthly",
"helpers:pinGitHubActionDigestsToSemver"
],
packageRules: [
{
matchCategories: [
"rust"
],
matchJsonata: [
"isBreaking != true"
],
// Disable non-breaking change updates because they
// are updated periodically with lockfile maintainance.
enabled: false,
},
{
matchManagers: [
"github-actions"
],
// Every month
schedule: "* 0 1 * *",
groupName: "Github Actions",
}
],
// Receive any update that fixes security vulnerabilities.
// We need this because we disabled "patch" updates for Rust.
// Note: You need to enable "Dependabot alerts" in "Code security" GitHub
// Settings to receive security updates.
// See https://docs.renovatebot.com/configuration-options/#vulnerabilityalerts
vulnerabilityAlerts: {
enabled: true,
},
}
+92 -52
View File
@@ -1,4 +1,5 @@
name: CI
permissions: {}
on:
push: { branches: [main] }
pull_request:
@@ -10,6 +11,7 @@ concurrency:
env:
CARGO_TERM_COLOR: always
LIBM_BUILD_VERBOSE: true
RUSTDOCFLAGS: -Dwarnings
RUSTFLAGS: -Dwarnings
RUST_BACKTRACE: full
@@ -28,8 +30,9 @@ jobs:
extensive_matrix: ${{ steps.script.outputs.extensive_matrix }}
may_skip_libm_ci: ${{ steps.script.outputs.may_skip_libm_ci }}
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
fetch-depth: 500
- name: Fetch pull request ref
run: git fetch origin "$GITHUB_REF:$GITHUB_REF"
@@ -42,6 +45,9 @@ jobs:
test:
name: Build and test
timeout-minutes: 60
# NOTE: self-hosted riscv64 runners are experimental and may be flaky.
# Do not block CI on failures from this platform for now.
continue-on-error: ${{ contains(matrix.os, 'self-hosted') }}
strategy:
fail-fast: false
matrix:
@@ -72,6 +78,9 @@ jobs:
os: ubuntu-24.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
- target: s390x-unknown-linux-gnu
@@ -104,53 +113,58 @@ jobs:
needs: [calculate_vars]
env:
BUILD_ONLY: ${{ matrix.build_only }}
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' }}
steps:
- name: Print $HOME
- name: Print runner information
shell: bash
run: |
set -x
echo "${HOME:-not found}"
uname -a
lscpu || (sysctl -a | grep cpu) || true
echo "home: ${HOME:-not found}"
pwd
printenv
- name: Print runner information
run: uname -a
# 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'
run: sudo apt-get update && sudo apt-get install -y rustup
- uses: actions/checkout@v4
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: { persist-credentials: false }
- name: Install Rust (rustup)
shell: bash
run: |
channel="nightly"
# Account for channels that have required components (MinGW)
[ -n "${{ matrix.channel }}" ] && channel="${{ matrix.channel }}"
[ -n "$JOB_CHANNEL" ] && channel="$JOB_CHANNEL"
rustup update "$channel" --no-self-update
rustup default "$channel"
rustup target add "${{ matrix.target }}"
rustup target add "$JOB_TARGET"
- uses: taiki-e/install-action@nextest
- uses: taiki-e/install-action@bfadeaba214680fb4ab63e710bcb2a6a17019fdc # v2.70.4
with:
tool: nextest@0.9.131
- uses: Swatinem/rust-cache@v2
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
with:
key: ${{ matrix.target }}
- name: Cache Docker layers
uses: actions/cache@v4
if: matrix.os == 'ubuntu-24.04'
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
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@v3
if: matrix.os == 'ubuntu-24.04'
- uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4
if: ${{ env.RUN_IN_DOCKER == 'true' }}
- name: Cache compiler-rt
id: cache-compiler-rt
uses: actions/cache@v4
uses: actions/cache@668228422ae6a00e4ad889ee87cd7109ec5666a7 # v5.0.4
with:
path: compiler-rt
key: ${{ runner.os }}-compiler-rt-${{ hashFiles('ci/download-compiler-rt.sh') }}
@@ -166,19 +180,22 @@ jobs:
shell: bash
- name: Verify API list
if: matrix.os == 'ubuntu-24.04'
run: python3 etc/update-api-list.py --check
if: matrix.os == 'ubuntu-24.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
cargo test -p update-api-list
# Non-linux tests just use our raw script
- name: Run locally
if: matrix.os != 'ubuntu-24.04'
if: ${{ env.RUN_IN_DOCKER != 'true' }}
shell: bash
run: ./ci/run.sh ${{ matrix.target }}
run: ./ci/run.sh "$JOB_TARGET"
# Otherwise we use our docker containers to run builds
- name: Run in Docker
if: matrix.os == 'ubuntu-24.04'
run: ./ci/run-docker.sh ${{ matrix.target }}
if: ${{ env.RUN_IN_DOCKER == 'true' }}
run: ./ci/run-docker.sh "$JOB_TARGET"
- name: Print test logs if available
if: always()
@@ -189,7 +206,7 @@ jobs:
# https://github.com/docker/build-push-action/issues/252
# https://github.com/moby/buildkit/issues/1896
- name: Move Docker cache
if: matrix.os == 'ubuntu-24.04'
if: ${{ env.RUN_IN_DOCKER == 'true' }}
run: |
rm -rf /tmp/.buildx-cache
mv /tmp/.buildx-cache-new /tmp/.buildx-cache
@@ -199,30 +216,43 @@ jobs:
runs-on: ubuntu-24.04
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: { persist-credentials: false }
# Unlike rustfmt, stable clippy does not work on code with nightly features.
- name: Install nightly `clippy`
run: |
rustup update nightly --no-self-update
rustup default nightly
rustup component add clippy
- uses: Swatinem/rust-cache@v2
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
- 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
permissions:
security-events: write
timeout-minutes: 10
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: { persist-credentials: false }
- uses: zizmorcore/zizmor-action@71321a20a9ded102f6e9ce5718a2fcec2c4f70d8 # v0.5.2
build-custom:
name: Build custom target
runs-on: ubuntu-24.04
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
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@v2
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
- run: |
# Ensure we can build with custom target.json files (these can interact
# poorly with build scripts)
@@ -237,13 +267,14 @@ jobs:
runs-on: ubuntu-24.04
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
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@v2
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
- run: |
cargo build -p compiler_builtins -p libm \
--target etc/thumbv6-none-eabi.json \
@@ -252,23 +283,30 @@ jobs:
benchmarks:
name: Benchmarks
timeout-minutes: 20
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
include:
- target: x86_64-unknown-linux-gnu
os: ubuntu-24.04
- target: aarch64-unknown-linux-gnu
os: ubuntu-24.04-arm
- target: i686-unknown-linux-gnu
os: ubuntu-24.04
- target: x86_64-unknown-linux-gnu
os: ubuntu-24.04
runs-on: ${{ matrix.os }}
env:
JOB_TARGET: ${{ matrix.target }}
steps:
- uses: actions/checkout@master
- uses: taiki-e/install-action@cargo-binstall
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: { persist-credentials: false }
- uses: taiki-e/install-action@bfadeaba214680fb4ab63e710bcb2a6a17019fdc # v2.70.4
with:
tool: cargo-binstall@1.17.7
- name: Set up dependencies
run: ./ci/install-bench-deps.sh
- uses: Swatinem/rust-cache@v2
run: ./ci/install-bench-deps.sh "$JOB_TARGET"
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
with:
key: ${{ matrix.target }}
- name: Download musl source
@@ -278,17 +316,14 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ github.event.pull_request.number }}
run: ./ci/bench-icount.sh ${{ matrix.target }}
run: ./ci/bench-icount.sh "$JOB_TARGET"
- name: Upload the benchmark baseline
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: ${{ env.BASELINE_NAME }}
path: ${{ env.BASELINE_NAME }}.tar.xz
- name: Run wall time benchmarks
run: ./ci/bench-walltime.sh
- name: Print test logs if available
if: always()
run: if [ -f "target/test-log.txt" ]; then cat target/test-log.txt; fi
@@ -299,15 +334,14 @@ jobs:
runs-on: ubuntu-24.04
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: { persist-credentials: false }
- name: Install Rust (rustup)
# FIXME(ci): not working in the 2026-02-11 nightly
# https://rust-lang.zulipchat.com/#narrow/channel/269128-miri/topic/build-script-build.20contains.20outdated.20or.20invalid.20JSON/with/573426109
run: rustup update nightly-2026-02-10 --no-self-update && rustup default nightly-2026-02-10
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@v2
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
- run: ./ci/miri.sh
msrv:
@@ -317,13 +351,14 @@ jobs:
env:
RUSTFLAGS: # No need to check warnings on old MSRV, unset `-Dwarnings`
steps:
- uses: actions/checkout@master
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
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@v2
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
- run: |
# FIXME(msrv): Remove the workspace Cargo.toml so 1.63 cargo doesn't see
# `edition = "2024"` and get spooked.
@@ -335,7 +370,8 @@ jobs:
runs-on: ubuntu-24.04
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: { persist-credentials: false }
- name: Install nightly `rustfmt`
run: rustup set profile minimal && rustup default nightly && rustup component add rustfmt
- run: cargo fmt -- --check
@@ -358,12 +394,13 @@ jobs:
env:
TO_TEST: ${{ matrix.to_test }}
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: { persist-credentials: false }
- name: Install Rust
run: |
rustup update nightly --no-self-update
rustup default nightly
- uses: Swatinem/rust-cache@v2
- uses: Swatinem/rust-cache@c19371144df3bb44fab255c43d04cbc2ab54d1c4 # v2.9.1
- name: download musl source
run: ./ci/update-musl.sh
- name: Run extensive tests
@@ -383,13 +420,16 @@ jobs:
- msrv
- rustfmt
- test
- zizmor
runs-on: ubuntu-24.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
# dependencies fails.
if: always() # make sure this is never "skipped"
env:
NEEDS: ${{ toJson(needs) }}
steps:
# Manually check the status of all dependencies. `if: failure()` does not work.
- name: check if any dependency failed
run: jq --exit-status 'all(.result == "success")' <<< '${{ toJson(needs) }}'
run: jq --exit-status 'all(.result == "success")' <<< "$NEEDS"
+4 -4
View File
@@ -11,15 +11,15 @@ jobs:
release-plz:
name: Release-plz
runs-on: ubuntu-24.04
environment: publish
steps:
- name: Checkout repository
uses: actions/checkout@v4
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
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: MarcoIeni/release-plz-action@v0.5
uses: release-plz/action@1528104d2ca23787631a1c1f022abb64b34c1e11 # v0.5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
+7 -3
View File
@@ -5,7 +5,7 @@ on:
workflow_dispatch:
schedule:
# Run at 04:00 UTC every Monday and Thursday
- cron: '0 4 * * 1,4'
- cron: "0 4 * * 1,4"
env:
JOSH_SYNC_VERBOSE: true
@@ -13,15 +13,19 @@ env:
jobs:
pull:
if: github.repository == 'rust-lang/compiler-builtins'
uses: rust-lang/josh-sync/.github/workflows/rustc-pull.yml@main
uses: rust-lang/josh-sync/.github/workflows/rustc-pull.yml@8970a6eb3a6095db68e4d765b3b5fba5e9c42cf6 # main
with:
github-app-id: ${{ vars.APP_CLIENT_ID }}
pr-author: "workflows-compiler-builtins[bot]"
# https://rust-lang.zulipchat.com/#narrow/channel/219381-t-libs/topic/compiler-builtins.20subtree.20sync.20automation/with/528482375
zulip-stream-id: 219381
zulip-topic: 'compiler-builtins subtree sync automation'
zulip-topic: "compiler-builtins subtree sync automation"
zulip-bot-email: "compiler-builtins-ci-bot@rust-lang.zulipchat.com"
pr-base-branch: main
branch-name: rustc-pull
secrets:
zulip-api-token: ${{ secrets.ZULIP_API_TOKEN }}
github-app-secret: ${{ secrets.APP_PRIVATE_KEY }}
permissions:
contents: write
pull-requests: write
+144 -200
View File
@@ -34,9 +34,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
[[package]]
name = "anstream"
version = "0.6.21"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a"
checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d"
dependencies = [
"anstyle",
"anstyle-parse",
@@ -49,15 +49,15 @@ dependencies = [
[[package]]
name = "anstyle"
version = "1.0.13"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78"
checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000"
[[package]]
name = "anstyle-parse"
version = "0.2.7"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2"
checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e"
dependencies = [
"utf8parse",
]
@@ -68,7 +68,7 @@ version = "1.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc"
dependencies = [
"windows-sys 0.61.2",
"windows-sys",
]
[[package]]
@@ -79,20 +79,24 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d"
dependencies = [
"anstyle",
"once_cell_polyfill",
"windows-sys 0.61.2",
"windows-sys",
]
[[package]]
name = "anyhow"
version = "1.0.101"
version = "1.0.102"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f0e0fee31ef5ed1ba1316088939cea399010ed7731dba877ed44aeb407a75ea"
checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c"
[[package]]
name = "api-list-common"
version = "0.1.0"
[[package]]
name = "assert_cmd"
version = "2.1.2"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c5bcfa8749ac45dd12cb11055aeeb6b27a3895560d60d71e3c23bf979e60514"
checksum = "9a686bbee5efb88a82df0621b236e74d925f470e5445d3220a5648b892ec99c9"
dependencies = [
"anstyle",
"bstr",
@@ -151,16 +155,13 @@ dependencies = [
"paste",
"rand_xoshiro",
"rustc_apfloat",
"test",
"utest-cortex-m-qemu",
"utest-macros",
]
[[package]]
name = "bumpalo"
version = "3.19.1"
version = "3.20.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510"
checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb"
[[package]]
name = "cast"
@@ -170,9 +171,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
[[package]]
name = "cc"
version = "1.2.56"
version = "1.2.58"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2"
checksum = "e1e928d4b69e3077709075a938a05ffbedfa53a84c8f766efbf8220bb1ff60e1"
dependencies = [
"find-msvc-tools",
"shlex",
@@ -224,9 +225,9 @@ dependencies = [
[[package]]
name = "clap"
version = "4.5.58"
version = "4.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63be97961acde393029492ce0be7a1af7e323e6bae9511ebfac33751be5e6806"
checksum = "b193af5b67834b676abd72466a96c1024e6a6ad978a1f484bd90b85c94041351"
dependencies = [
"clap_builder",
"clap_derive",
@@ -234,9 +235,9 @@ dependencies = [
[[package]]
name = "clap_builder"
version = "4.5.58"
version = "4.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f13174bda5dfd69d7e947827e5af4b0f2f94a4a3ee92912fba07a66150f21e2"
checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f"
dependencies = [
"anstream",
"anstyle",
@@ -246,9 +247,9 @@ dependencies = [
[[package]]
name = "clap_derive"
version = "4.5.55"
version = "4.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a92793da1a46a5f2a02a6f4c46c6496b28c43638adea8306fcb0caa1634f24e5"
checksum = "1110bd8a634a1ab8cb04345d8d878267d57c3cf1b38d91b71af6686408bbca6a"
dependencies = [
"heck",
"proc-macro2",
@@ -258,15 +259,15 @@ dependencies = [
[[package]]
name = "clap_lex"
version = "1.0.0"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a822ea5bc7590f9d40f1ba12c0dc3c2760f3482c6984db1573ad11031420831"
checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9"
[[package]]
name = "colorchoice"
version = "1.0.4"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75"
checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570"
[[package]]
name = "compiler_builtins"
@@ -277,14 +278,13 @@ dependencies = [
[[package]]
name = "console"
version = "0.16.2"
version = "0.16.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "03e45a4a8926227e4197636ba97a9fc9b00477e9f4bd711395687c5f0734bec4"
checksum = "d64e8af5551369d19cf50138de61f1c42074ab970f74e99be916646777f8fc87"
dependencies = [
"encode_unicode",
"libc",
"once_cell",
"windows-sys 0.61.2",
"windows-sys",
]
[[package]]
@@ -391,6 +391,12 @@ dependencies = [
"syn",
]
[[package]]
name = "diff"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
[[package]]
name = "difflib"
version = "0.4.0"
@@ -422,7 +428,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
dependencies = [
"libc",
"windows-sys 0.61.2",
"windows-sys",
]
[[package]]
@@ -470,9 +476,9 @@ dependencies = [
[[package]]
name = "getrandom"
version = "0.4.1"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "139ef39800118c7683f2fd3c98c1b23c09ae076556b435f8e9064ae108aaeeec"
checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555"
dependencies = [
"cfg-if",
"js-sys",
@@ -485,20 +491,26 @@ dependencies = [
]
[[package]]
name = "gmp-mpfr-sys"
version = "1.6.8"
name = "glob"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60f8970a75c006bb2f8ae79c6768a116dd215fa8346a87aed99bf9d82ca43394"
checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280"
[[package]]
name = "gmp-mpfr-sys"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8cfc928d8ff4ab3767a3674cf55f81186436fb6070866bb1443ffe65a640d2d6"
dependencies = [
"libc",
"windows-sys 0.60.2",
"windows-sys",
]
[[package]]
name = "gungraun"
version = "0.17.2"
version = "0.18.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61c1bbe46f51c63bc08a1fac0ee0c530a77c961613a86ecf828ab1b0ffc6687a"
checksum = "2e2e7d17b75a18300d495a5e79970067b92d74e4858c28326e125f2d55b1b566"
dependencies = [
"bincode",
"derive_more",
@@ -508,9 +520,9 @@ dependencies = [
[[package]]
name = "gungraun-macros"
version = "0.7.2"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdccd089c36fb2ee66ef0eb7b1baa3ce7e7878a8eae682d9c8c368869ff6eca1"
checksum = "e35c7fb6133421db1cf752b7a2838d9277a26810ccaeeca7aa449f96ad7c2b01"
dependencies = [
"derive_more",
"proc-macro-error2",
@@ -524,9 +536,9 @@ dependencies = [
[[package]]
name = "gungraun-runner"
version = "0.17.2"
version = "0.18.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6da6487203fa53ae6b1c8fead642fe79a3199464b0dd1337635594d675a9ac05"
checksum = "c19bb4c552085f983300b11694022d7584810dca3500c220962ab2353327fb45"
dependencies = [
"serde",
]
@@ -610,15 +622,15 @@ dependencies = [
[[package]]
name = "itoa"
version = "1.0.17"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2"
checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
[[package]]
name = "js-sys"
version = "0.3.85"
version = "0.3.94"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8c942ebf8e95485ca0d52d97da7c5a2c387d0e7f0ba4c35e93bfcaee045955b3"
checksum = "2e04e2ef80ce82e13552136fabeef8a5ed1f985a96805761cbb9a2c34e7664d9"
dependencies = [
"once_cell",
"wasm-bindgen",
@@ -632,9 +644,9 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
[[package]]
name = "libc"
version = "0.2.182"
version = "0.2.183"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112"
checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d"
[[package]]
name = "libm"
@@ -653,6 +665,7 @@ checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981"
name = "libm-macros"
version = "0.1.0"
dependencies = [
"api-list-common",
"heck",
"proc-macro2",
"quote",
@@ -664,6 +677,8 @@ name = "libm-test"
version = "0.1.0"
dependencies = [
"anyhow",
"api-list-common",
"compiler_builtins",
"criterion",
"getrandom",
"gmp-mpfr-sys",
@@ -682,9 +697,9 @@ dependencies = [
[[package]]
name = "libtest-mimic"
version = "0.8.1"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5297962ef19edda4ce33aaa484386e0a5b3d7f2f4e037cbeee00503ef6b29d33"
checksum = "14e6ba06f0ade6e504aff834d7c34298e5155c6baca353cc6a4aaff2f9fd7f33"
dependencies = [
"anstream",
"anstyle",
@@ -694,9 +709,9 @@ dependencies = [
[[package]]
name = "linux-raw-sys"
version = "0.11.0"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039"
checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53"
[[package]]
name = "log"
@@ -750,21 +765,21 @@ dependencies = [
[[package]]
name = "object"
version = "0.38.1"
version = "0.39.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "271638cd5fa9cca89c4c304675ca658efc4e64a66c716b7cfe1afb4b9611dbbc"
checksum = "63944c133d03f44e75866bbd160b95af0ec3f6a13d936d69d31c81078cbc5baf"
dependencies = [
"flate2",
"memchr",
"ruzstd",
"wasmparser 0.243.0",
"wasmparser 0.245.1",
]
[[package]]
name = "once_cell"
version = "1.21.3"
version = "1.21.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
[[package]]
name = "once_cell_polyfill"
@@ -868,6 +883,16 @@ dependencies = [
"termtree",
]
[[package]]
name = "pretty_assertions"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d"
dependencies = [
"diff",
"yansi",
]
[[package]]
name = "prettyplease"
version = "0.2.37"
@@ -911,24 +936,24 @@ dependencies = [
[[package]]
name = "quote"
version = "1.0.44"
version = "1.0.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4"
checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
dependencies = [
"proc-macro2",
]
[[package]]
name = "r-efi"
version = "5.3.0"
version = "6.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf"
[[package]]
name = "rand"
version = "0.10.0"
version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc266eb313df6c5c09c1c7b1fbe2510961e5bcd3add930c1e31f7ed9da0feff8"
checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207"
dependencies = [
"chacha20",
"getrandom",
@@ -1005,15 +1030,15 @@ dependencies = [
[[package]]
name = "regex-syntax"
version = "0.8.9"
version = "0.8.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a96887878f22d7bad8a3b6dc5b7440e0ada9a245242924394987b21cf2210a4c"
checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a"
[[package]]
name = "rug"
version = "1.28.1"
version = "1.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de190ec858987c79cad4da30e19e546139b3339331282832af004d0ea7829639"
checksum = "25f6c8f906c90b48e0c1745c9f814c3a31c5eba847043b05c3e9a934dec7c4b3"
dependencies = [
"az",
"gmp-mpfr-sys",
@@ -1042,15 +1067,15 @@ dependencies = [
[[package]]
name = "rustix"
version = "1.1.3"
version = "1.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34"
checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190"
dependencies = [
"bitflags",
"errno",
"libc",
"linux-raw-sys",
"windows-sys 0.61.2",
"windows-sys",
]
[[package]]
@@ -1077,12 +1102,6 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "sc"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "010e18bd3bfd1d45a7e666b236c78720df0d9a7698ebaa9c1c559961eb60a38b"
[[package]]
name = "semver"
version = "1.0.27"
@@ -1140,9 +1159,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "simd-adler32"
version = "0.3.8"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2"
checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214"
[[package]]
name = "smallvec"
@@ -1171,9 +1190,9 @@ dependencies = [
[[package]]
name = "syn"
version = "2.0.116"
version = "2.0.117"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3df424c70518695237746f84cede799c9c58fcb37450d7b23716568cc8bc69cb"
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
dependencies = [
"proc-macro2",
"quote",
@@ -1182,15 +1201,15 @@ dependencies = [
[[package]]
name = "tempfile"
version = "3.25.0"
version = "3.27.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0136791f7c95b1f6dd99f9cc786b91bb81c3800b639b3478e561ddb7be95e5f1"
checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd"
dependencies = [
"fastrand",
"getrandom",
"once_cell",
"rustix",
"windows-sys 0.61.2",
"windows-sys",
]
[[package]]
@@ -1199,11 +1218,6 @@ version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f50febec83f5ee1df3015341d8bd429f2d1cc62bcba7ea2076759d315084683"
[[package]]
name = "test"
version = "0.1.0"
source = "git+https://github.com/japaric/utest#e32073e2b078e3bee46001c13ae4c1acf368d762"
[[package]]
name = "tinytemplate"
version = "1.2.1"
@@ -1245,18 +1259,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81e544489bf3d8ef66c953931f56617f423cd4b5494be343d9b9d3dda037b9a3"
[[package]]
name = "utest-cortex-m-qemu"
name = "update-api-list"
version = "0.1.0"
source = "git+https://github.com/japaric/utest#e32073e2b078e3bee46001c13ae4c1acf368d762"
dependencies = [
"sc",
"api-list-common",
"getopts",
"glob",
"pretty_assertions",
"regex",
]
[[package]]
name = "utest-macros"
version = "0.1.0"
source = "git+https://github.com/japaric/utest#e32073e2b078e3bee46001c13ae4c1acf368d762"
[[package]]
name = "utf8parse"
version = "0.2.2"
@@ -1314,9 +1326,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen"
version = "0.2.108"
version = "0.2.117"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64024a30ec1e37399cf85a7ffefebdb72205ca1c972291c51512360d90bd8566"
checksum = "0551fc1bb415591e3372d0bc4780db7e587d84e2a7e79da121051c5c4b89d0b0"
dependencies = [
"cfg-if",
"once_cell",
@@ -1327,9 +1339,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.108"
version = "0.2.117"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "008b239d9c740232e71bd39e8ef6429d27097518b6b30bdf9086833bd5b6d608"
checksum = "7fbdf9a35adf44786aecd5ff89b4563a90325f9da0923236f6104e603c7e86be"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -1337,9 +1349,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.108"
version = "0.2.117"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5256bae2d58f54820e6490f9839c49780dff84c65aeab9e772f15d5f0e913a55"
checksum = "dca9693ef2bab6d4e6707234500350d8dad079eb508dca05530c85dc3a529ff2"
dependencies = [
"bumpalo",
"proc-macro2",
@@ -1350,9 +1362,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.108"
version = "0.2.117"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f01b580c9ac74c8d8f0c0e4afb04eeef2acf145458e52c03845ee9cd23e3d12"
checksum = "39129a682a6d2d841b6c429d0c51e5cb0ed1a03829d8b3d1e69a011e62cb3d3b"
dependencies = [
"unicode-ident",
]
@@ -1379,15 +1391,6 @@ dependencies = [
"wasmparser 0.244.0",
]
[[package]]
name = "wasmparser"
version = "0.243.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6d8db401b0528ec316dfbe579e6ab4152d61739cfe076706d2009127970159d"
dependencies = [
"bitflags",
]
[[package]]
name = "wasmparser"
version = "0.244.0"
@@ -1401,10 +1404,19 @@ dependencies = [
]
[[package]]
name = "web-sys"
version = "0.3.85"
name = "wasmparser"
version = "0.245.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "312e32e551d92129218ea9a2452120f4aabc03529ef03e4d0d82fb2780608598"
checksum = "4f08c9adee0428b7bddf3890fc27e015ac4b761cc608c822667102b8bfd6995e"
dependencies = [
"bitflags",
]
[[package]]
name = "web-sys"
version = "0.3.94"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd70027e39b12f0849461e08ffc50b9cd7688d942c1c8e3c7b22273236b4dd0a"
dependencies = [
"js-sys",
"wasm-bindgen",
@@ -1442,7 +1454,7 @@ version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
dependencies = [
"windows-sys 0.61.2",
"windows-sys",
]
[[package]]
@@ -1457,15 +1469,6 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
[[package]]
name = "windows-sys"
version = "0.60.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
dependencies = [
"windows-targets",
]
[[package]]
name = "windows-sys"
version = "0.61.2"
@@ -1475,71 +1478,6 @@ dependencies = [
"windows-link",
]
[[package]]
name = "windows-targets"
version = "0.53.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3"
dependencies = [
"windows-link",
"windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53"
[[package]]
name = "windows_aarch64_msvc"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006"
[[package]]
name = "windows_i686_gnu"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3"
[[package]]
name = "windows_i686_gnullvm"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c"
[[package]]
name = "windows_i686_msvc"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2"
[[package]]
name = "windows_x86_64_gnu"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1"
[[package]]
name = "windows_x86_64_msvc"
version = "0.53.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650"
[[package]]
name = "wit-bindgen"
version = "0.51.0"
@@ -1629,19 +1567,25 @@ dependencies = [
]
[[package]]
name = "zerocopy"
version = "0.8.39"
name = "yansi"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db6d35d663eadb6c932438e763b262fe1a70987f9ae936e60158176d710cae4a"
checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049"
[[package]]
name = "zerocopy"
version = "0.8.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.8.39"
version = "0.8.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4122cd3169e94605190e77839c9a40d40ed048d305bfdc146e7df40ab0f3e517"
checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4"
dependencies = [
"proc-macro2",
"quote",
+10 -4
View File
@@ -3,10 +3,12 @@ resolver = "2"
members = [
"builtins-shim",
"builtins-test",
"crates/api-list-common",
"crates/libm-macros",
"crates/musl-math-sys",
"crates/panic-handler",
"crates/symbol-check",
"crates/update-api-list",
"crates/util",
"libm",
"libm-test",
@@ -15,14 +17,15 @@ members = [
default-members = [
"builtins-shim",
"builtins-test",
"crates/api-list-common",
"crates/libm-macros",
"libm",
"libm-test",
]
exclude = [
# `builtins-test-intrinsics` needs the feature `compiler-builtins` enabled
# and `mangled-names` disabled, which is the opposite of what is needed for
# `builtins-test-intrinsics` needs the features `compiler-builtins` and
# `unmangled-names` enabled, which is the opposite of what is needed for
# other tests, so it makes sense to keep it out of the workspace.
"builtins-test-intrinsics",
# We test via the `builtins-shim` crate, so exclude the `compiler-builtins`
@@ -33,6 +36,7 @@ exclude = [
[workspace.dependencies]
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"
@@ -40,8 +44,9 @@ compiler_builtins = { path = "builtins-shim", default-features = false }
criterion = { version = "0.8.2", default-features = false, features = ["cargo_bench_support"] }
getopts = "0.2.24"
getrandom = "0.4.1"
glob = "0.3.3"
gmp-mpfr-sys = { version = "1.6.8", default-features = false }
gungraun = "0.17.2"
gungraun = "0.18.0"
heck = "0.5.0"
indicatif = { version = "0.18.3", default-features = false }
libm = { path = "libm", default-features = false }
@@ -50,9 +55,10 @@ 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.38.1", features = ["wasm"] }
object = { version = "0.39.0", features = ["wasm"] }
panic-handler = { path = "crates/panic-handler" }
paste = "1.0.15"
pretty_assertions = "1.4.1"
proc-macro2 = "1.0.106"
quote = "1.0.44"
rand = "0.10.0"
@@ -39,27 +39,28 @@ test = false
cc = { version = "1.2", optional = true }
[features]
default = []
default = ["arch"]
# Enable architecture-specific features such as SIMD or assembly routines. If
# disabled, the generic version can be tested on any platform.
arch = []
# Enable compilation of C code in compiler-rt, filling in some more optimized
# implementations and also filling in unimplemented intrinsics
c = ["dep:cc"]
# For implementations where there is both a generic version and a platform-
# specific version, use the generic version. This is meant to enable testing
# the generic versions on all platforms.
no-asm = []
# Flag this library as the unstable compiler-builtins lib. This must be enabled
# when using as `std`'s dependency.'
compiler-builtins = []
compiler-builtins = ["unmangled-names"]
# Generate memory-related intrinsics like memcpy
# Enable `no_mangle` symbols for memory-related intrinsics like memcpy. The
# mangled versions are always available.
mem = []
# Mangle all names so this can be linked in with other versions or other
# compiler-rt implementations. Also used for testing
mangled-names = []
# Enable `no_mangle` symbols so this crate gets used as the runtime intrinsic
# implementation. Leave this disabled for testing to avoid conflicting with
# the system intrinsics.
unmangled-names = []
# This makes certain traits and function specializations public that
# are not normally public but are required by the `builtins-test`
@@ -6,9 +6,15 @@ publish = false
license = "MIT OR Apache-2.0"
[dependencies]
compiler_builtins = { path = "../builtins-shim", features = ["compiler-builtins"] }
# FIXME: `aeabi_mem*` tests will require the "mem" feature to be enabled here.
compiler_builtins = { path = "../builtins-shim", features = ["compiler-builtins", "unmangled-names"] }
panic-handler = { path = "../crates/panic-handler" }
[target.'cfg(all(target_arch = "arm", not(any(target_env = "gnu", target_env = "musl")), target_os = "linux"))'.dev-dependencies]
test = { git = "https://github.com/japaric/utest" }
utest-cortex-m-qemu = { default-features = false, git = "https://github.com/japaric/utest" }
utest-macros = { git = "https://github.com/japaric/utest" }
[features]
c = ["compiler_builtins/c"]
@@ -1,10 +1,10 @@
mod builtins_configure {
include!("../compiler-builtins/configure.rs");
}
#[path = "../libm/configure.rs"]
mod configure;
use configure::{Config, Library};
fn main() {
println!("cargo::rerun-if-changed=../configure.rs");
let target = builtins_configure::Target::from_env();
builtins_configure::configure_aliases(&target);
println!("cargo::rerun-if-changed=../libm/configure.rs");
let cfg = Config::from_env(Library::BuiltinsTestIntrinsics);
configure::emit(&cfg);
}
@@ -1,7 +1,9 @@
// By compiling this file we check that all the intrinsics we care about continue to be provided by
// the `compiler_builtins` crate regardless of the changes we make to it. If we, by mistake, stop
// compiling a C implementation and forget to implement that intrinsic in Rust, this file will fail
// to link due to the missing intrinsic (symbol).
//! Tests that require unmangled symbols from `compiler-builtins`.
//!
//! By compiling this file we check that all the intrinsics we care about continue to be provided by
//! the `compiler_builtins` crate regardless of the changes we make to it. If we, by mistake, stop
//! compiling a C implementation and forget to implement that intrinsic in Rust, this file will fail
//! to link due to the missing intrinsic (symbol).
#![allow(internal_features, unused_features)]
#![deny(dead_code)]
@@ -2,7 +2,6 @@
target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
feature = "mem"
))]
#![feature(compiler_builtins_lib)]
#![no_std]
@@ -2,7 +2,6 @@
target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
feature = "mem"
))]
#![feature(compiler_builtins_lib)]
#![no_std]
@@ -2,7 +2,6 @@
target_arch = "arm",
not(any(target_env = "gnu", target_env = "musl")),
target_os = "linux",
feature = "mem"
))]
#![feature(compiler_builtins_lib)]
#![no_std]
@@ -6,7 +6,7 @@ publish = false
license = "MIT AND Apache-2.0 WITH LLVM-exception AND (MIT OR Apache-2.0)"
[dependencies]
compiler_builtins = { workspace = true, features = ["unstable-public-internals"] }
compiler_builtins = { workspace = true, default-features = false, features = ["unstable-public-internals"] }
# For fuzzing tests we want a deterministic seedable RNG. We also eliminate potential
# problems with system RNGs on the variety of platforms this crate is tested on.
@@ -23,25 +23,11 @@ gungraun = { workspace = true, optional = true }
[dev-dependencies]
paste.workspace = true
[target.'cfg(all(target_arch = "arm", not(any(target_env = "gnu", target_env = "musl")), target_os = "linux"))'.dev-dependencies]
test = { git = "https://github.com/japaric/utest" }
utest-cortex-m-qemu = { default-features = false, git = "https://github.com/japaric/utest" }
utest-macros = { git = "https://github.com/japaric/utest" }
[features]
default = ["mangled-names"]
# Defaults should match the defaults in compiler-builtins since we have that
# dependency with `default-features=false`.
default = ["compiler_builtins/arch"]
c = ["compiler_builtins/c"]
no-asm = ["compiler_builtins/no-asm"]
mem = ["compiler_builtins/mem"]
mangled-names = ["compiler_builtins/mangled-names"]
# Skip tests that rely on f128 symbols being available on the system
no-sys-f128 = ["no-sys-f128-int-convert", "no-sys-f16-f128-convert"]
# Some platforms have some f128 functions but everything except integer conversions
no-sys-f128-int-convert = []
no-sys-f16-f128-convert = []
no-sys-f16-f64-convert = []
# Skip tests that rely on f16 symbols being available on the system
no-sys-f16 = ["no-sys-f16-f64-convert"]
# Enable icount benchmarks (requires gungraun-runner and valgrind locally)
icount = ["dep:gungraun"]
@@ -51,11 +37,6 @@ icount = ["dep:gungraun"]
benchmarking-reports = ["walltime", "criterion/plotters", "criterion/html_reports"]
walltime = ["dep:criterion"]
# NOTE: benchmarks must be run with `--no-default-features` or with
# `-p builtins-test`, otherwise the default `compiler-builtins` feature
# of the `compiler_builtins` crate gets activated, resulting in linker
# errors.
[[bench]]
name = "float_add"
harness = false
@@ -74,7 +74,7 @@
crate_fn_ppc: add::__addkf3,
sys_fn: __addtf3,
sys_fn_ppc: __addkf3,
sys_available: not(feature = "no-sys-f128"),
sys_available: not(no_sys_f128),
asm: []
}
@@ -185,7 +185,7 @@ fn gt_res_eq(mut a: CmpResult, mut b: CmpResult) -> bool {
crate_fn_ppc: cmp::__gtkf2,
sys_fn: __gttf2,
sys_fn_ppc: __gtkf2,
sys_available: not(feature = "no-sys-f128"),
sys_available: not(no_sys_f128),
output_eq: gt_res_eq,
asm: []
}
@@ -198,7 +198,7 @@ fn gt_res_eq(mut a: CmpResult, mut b: CmpResult) -> bool {
crate_fn_ppc: cmp::__unordkf2,
sys_fn: __unordtf2,
sys_fn_ppc: __unordkf2,
sys_available: not(feature = "no-sys-f128"),
sys_available: not(no_sys_f128),
asm: []
}
@@ -84,7 +84,7 @@
crate_fn_ppc: conv::__floatunsikf,
sys_fn: __floatunsitf,
sys_fn_ppc: __floatunsikf,
sys_available: not(feature = "no-sys-f16-f128-convert"),
sys_available: not(no_sys_f16_f128_convert),
asm: []
}
@@ -138,7 +138,7 @@
crate_fn_ppc: conv::__floatundikf,
sys_fn: __floatunditf,
sys_fn_ppc: __floatundikf,
sys_available: not(feature = "no-sys-f16-f128-convert"),
sys_available: not(no_sys_f16_f128_convert),
asm: []
}
@@ -168,7 +168,7 @@
crate_fn_ppc: conv::__floatuntikf,
sys_fn: __floatuntitf,
sys_fn_ppc: __floatuntikf,
sys_available: not(feature = "no-sys-f16-f128-convert"),
sys_available: not(no_sys_f16_f128_convert),
asm: []
}
@@ -249,7 +249,7 @@
crate_fn_ppc: conv::__floatsikf,
sys_fn: __floatsitf,
sys_fn_ppc: __floatsikf,
sys_available: not(feature = "no-sys-f16-f128-convert"),
sys_available: not(no_sys_f16_f128_convert),
asm: []
}
@@ -328,7 +328,7 @@
crate_fn_ppc: conv::__floatdikf,
sys_fn: __floatditf,
sys_fn_ppc: __floatdikf,
sys_available: not(feature = "no-sys-f16-f128-convert"),
sys_available: not(no_sys_f16_f128_convert),
asm: []
}
@@ -358,7 +358,7 @@
crate_fn_ppc: conv::__floattikf,
sys_fn: __floattitf,
sys_fn_ppc: __floattikf,
sys_available: not(feature = "no-sys-f16-f128-convert"),
sys_available: not(no_sys_f16_f128_convert),
asm: []
}
@@ -473,7 +473,7 @@
crate_fn: conv::__fixunstfsi,
crate_fn_ppc: conv::__fixunskfsi,
sys_fn: __fixunstfsi,
sys_available: not(feature = "no-sys-f16-f128-convert"),
sys_available: not(no_sys_f16_f128_convert),
asm: []
}
@@ -484,7 +484,7 @@
crate_fn: conv::__fixunstfdi,
crate_fn_ppc: conv::__fixunskfdi,
sys_fn: __fixunstfdi,
sys_available: not(feature = "no-sys-f16-f128-convert"),
sys_available: not(no_sys_f16_f128_convert),
asm: []
}
@@ -495,7 +495,7 @@
crate_fn: conv::__fixunstfti,
crate_fn_ppc: conv::__fixunskfti,
sys_fn: __fixunstfti,
sys_available: not(feature = "no-sys-f16-f128-convert"),
sys_available: not(no_sys_f16_f128_convert),
asm: []
}
@@ -610,7 +610,7 @@
crate_fn: conv::__fixtfsi,
crate_fn_ppc: conv::__fixkfsi,
sys_fn: __fixtfsi,
sys_available: not(feature = "no-sys-f16-f128-convert"),
sys_available: not(no_sys_f16_f128_convert),
asm: []
}
@@ -621,7 +621,7 @@
crate_fn: conv::__fixtfdi,
crate_fn_ppc: conv::__fixkfdi,
sys_fn: __fixtfdi,
sys_available: not(feature = "no-sys-f16-f128-convert"),
sys_available: not(no_sys_f16_f128_convert),
asm: []
}
@@ -632,7 +632,7 @@
crate_fn: conv::__fixtfti,
crate_fn_ppc: conv::__fixkfti,
sys_fn: __fixtfti,
sys_available: not(feature = "no-sys-f16-f128-convert"),
sys_available: not(no_sys_f16_f128_convert),
asm: []
}
@@ -74,7 +74,7 @@
crate_fn_ppc: div::__divkf3,
sys_fn: __divtf3,
sys_fn_ppc: __divkf3,
sys_available: not(feature = "no-sys-f128"),
sys_available: not(no_sys_f128),
asm: []
}
@@ -12,7 +12,7 @@
sig: (a: f16) -> f32,
crate_fn: extend::__extendhfsf2,
sys_fn: __extendhfsf2,
sys_available: not(feature = "no-sys-f16"),
sys_available: not(no_sys_f16),
asm: [
#[cfg(target_arch = "aarch64")] {
let ret: f32;
@@ -34,7 +34,7 @@
sig: (a: f16) -> f64,
crate_fn: extend::__extendhfdf2,
sys_fn: __extendhfdf2,
sys_available: not(feature = "no-sys-f16-f64-convert"),
sys_available: not(no_sys_f16_f64_convert),
asm: [
#[cfg(target_arch = "aarch64")] {
let ret: f64;
@@ -58,7 +58,7 @@
crate_fn_ppc: extend::__extendhfkf2,
sys_fn: __extendhftf2,
sys_fn_ppc: __extendhfkf2,
sys_available: not(feature = "no-sys-f16-f128-convert"),
sys_available: not(no_sys_f16_f128_convert),
asm: [],
}
@@ -91,7 +91,7 @@
crate_fn_ppc: extend::__extendsfkf2,
sys_fn: __extendsftf2,
sys_fn_ppc: __extendsfkf2,
sys_available: not(feature = "no-sys-f128"),
sys_available: not(no_sys_f128),
asm: [],
}
@@ -103,7 +103,7 @@
crate_fn_ppc: extend::__extenddfkf2,
sys_fn: __extenddftf2,
sys_fn_ppc: __extenddfkf2,
sys_available: not(feature = "no-sys-f128"),
sys_available: not(no_sys_f128),
asm: [],
}
@@ -74,7 +74,7 @@
crate_fn_ppc: mul::__mulkf3,
sys_fn: __multf3,
sys_fn_ppc: __mulkf3,
sys_available: not(feature = "no-sys-f128"),
sys_available: not(no_sys_f128),
asm: []
}
@@ -24,7 +24,7 @@
// FIXME(f16_f128): can be changed to only `f128_enabled` once `__multf3` and `__divtf3` are
// distributed by nightly.
#[cfg(all(f128_enabled, not(feature = "no-sys-f128")))]
#[cfg(all(f128_enabled, not(no_sys_f128)))]
float_bench! {
name: powi_f128,
sig: (a: f128, b: i32) -> f128,
@@ -32,7 +32,7 @@
crate_fn_ppc: pow::__powikf2,
sys_fn: __powitf2,
sys_fn_ppc: __powikf2,
sys_available: not(feature = "no-sys-f128"),
sys_available: not(no_sys_f128),
asm: []
}
@@ -42,7 +42,7 @@ pub fn float_pow() {
powi_f32(&mut criterion);
powi_f64(&mut criterion);
#[cfg(all(f128_enabled, not(feature = "no-sys-f128")))]
#[cfg(all(f128_enabled, not(no_sys_f128)))]
powi_f128(&mut criterion);
}
@@ -74,7 +74,7 @@
crate_fn_ppc: sub::__subkf3,
sys_fn: __subtf3,
sys_fn_ppc: __subkf3,
sys_available: not(feature = "no-sys-f128"),
sys_available: not(no_sys_f128),
asm: []
}
@@ -11,7 +11,7 @@
sig: (a: f32) -> f16,
crate_fn: trunc::__truncsfhf2,
sys_fn: __truncsfhf2,
sys_available: not(feature = "no-sys-f16"),
sys_available: not(no_sys_f16),
asm: [
#[cfg(target_arch = "aarch64")] {
let ret: f16;
@@ -33,7 +33,7 @@
sig: (a: f64) -> f16,
crate_fn: trunc::__truncdfhf2,
sys_fn: __truncdfhf2,
sys_available: not(feature = "no-sys-f16-f64-convert"),
sys_available: not(no_sys_f16_f64_convert),
asm: [
#[cfg(target_arch = "aarch64")] {
let ret: f16;
@@ -90,7 +90,7 @@
crate_fn_ppc: trunc::__trunckfhf2,
sys_fn: __trunctfhf2,
sys_fn_ppc: __trunckfhf2,
sys_available: not(feature = "no-sys-f16-f128-convert"),
sys_available: not(no_sys_f16_f128_convert),
asm: [],
}
@@ -102,7 +102,7 @@
crate_fn_ppc: trunc::__trunckfsf2,
sys_fn: __trunctfsf2,
sys_fn_ppc: __trunckfsf2,
sys_available: not(feature = "no-sys-f128"),
sys_available: not(no_sys_f128),
asm: [],
}
@@ -114,7 +114,7 @@
crate_fn_ppc: trunc::__trunckfdf2,
sys_fn: __trunctfdf2,
sys_fn_ppc: __trunckfdf2,
sys_available: not(feature = "no-sys-f128"),
sys_available: not(no_sys_f128),
asm: [],
}
@@ -118,7 +118,7 @@ fn bench_cpy((len, mut dst, src): (usize, AlignedSlice, AlignedSlice)) {
}
}
library_benchmark_group!(name = memcpy; benchmarks = bench_cpy);
library_benchmark_group!(name = memcpy, benchmarks = [bench_cpy]);
}
mod mset {
@@ -167,7 +167,7 @@ fn bench_set((len, mut dst): (usize, AlignedSlice)) {
}
}
library_benchmark_group!(name = memset; benchmarks = bench_set);
library_benchmark_group!(name = memset, benchmarks = [bench_set]);
}
mod mcmp {
@@ -235,7 +235,7 @@ fn bench_cmp((len, mut dst, src): (usize, AlignedSlice, AlignedSlice)) {
}
}
library_benchmark_group!(name = memcmp; benchmarks = bench_cmp);
library_benchmark_group!(name = memcmp, benchmarks = [bench_cmp]);
}
mod mmove {
@@ -489,7 +489,7 @@ fn backward_move((len, spread, mut buf): (usize, usize, AlignedSlice)) {
}
}
library_benchmark_group!(name = memmove; benchmarks = forward_move, backward_move);
library_benchmark_group!(name = memmove, benchmarks = [forward_move, backward_move]);
}
use mcmp::memcmp;
@@ -497,4 +497,4 @@ fn backward_move((len, spread, mut buf): (usize, usize, AlignedSlice)) {
use mmove::memmove;
use mset::memset;
main!(library_benchmark_groups = memcpy, memset, memcmp, memmove);
main!(library_benchmark_groups = [memcpy, memset, memcmp, memmove]);
@@ -1,12 +1,13 @@
#[path = "../libm/configure.rs"]
mod configure;
use std::collections::HashSet;
mod builtins_configure {
include!("../compiler-builtins/configure.rs");
}
use configure::{Config, Library, set_cfg};
/// Features to enable
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
enum Feature {
enum SetCfg {
NoSysF128,
NoSysF128IntConvert,
NoSysF16,
@@ -14,7 +15,15 @@ enum Feature {
NoSysF16F128Convert,
}
impl Feature {
impl SetCfg {
const ALL: &[Self] = &[
Self::NoSysF128,
Self::NoSysF128IntConvert,
Self::NoSysF16,
Self::NoSysF16F64Convert,
Self::NoSysF16F128Convert,
];
fn implies(self) -> &'static [Self] {
match self {
Self::NoSysF128 => [Self::NoSysF128IntConvert, Self::NoSysF16F128Convert].as_slice(),
@@ -24,96 +33,89 @@ fn implies(self) -> &'static [Self] {
Self::NoSysF16F128Convert => [].as_slice(),
}
}
fn name(self) -> &'static str {
match self {
Self::NoSysF128 => "no_sys_f128",
Self::NoSysF128IntConvert => "no_sys_f128_int_convert",
Self::NoSysF16F64Convert => "no_sys_f16_f64_convert",
Self::NoSysF16F128Convert => "no_sys_f16_f128_convert",
Self::NoSysF16 => "no_sys_f16",
}
}
}
fn main() {
println!("cargo::rerun-if-changed=../configure.rs");
println!("cargo::rerun-if-changed=../libm/configure.rs");
let target = builtins_configure::Target::from_env();
let mut features = HashSet::new();
let cfg = Config::from_env(Library::BuiltinsTest);
configure::emit(&cfg);
let mut to_set = HashSet::new();
// These platforms do not have f128 symbols available in their system libraries, so
// skip related tests.
if target.arch == "arm"
|| target.vendor == "apple"
|| target.env == "msvc"
if cfg.target_arch == "arm"
|| cfg.target_vendor == "apple"
|| cfg.target_env == "msvc"
// GCC and LLVM disagree on the ABI of `f16` and `f128` with MinGW. See
// <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115054>.
|| (target.os == "windows" && target.env == "gnu")
|| (cfg.target_os == "windows" && cfg.target_env == "gnu")
// FIXME(llvm): There is an ABI incompatibility between GCC and Clang on 32-bit x86.
// See <https://github.com/llvm/llvm-project/issues/77401>.
|| target.arch == "x86"
|| cfg.target_arch == "x86"
// 32-bit PowerPC and 64-bit LE gets code generated that Qemu cannot handle. See
// <https://github.com/rust-lang/compiler-builtins/pull/606#issuecomment-2105635926>.
|| target.arch == "powerpc"
|| target.arch == "powerpc64le"
|| cfg.target_arch == "powerpc"
|| cfg.target_arch == "powerpc64le"
// FIXME: We get different results from the builtin functions. See
// <https://github.com/rust-lang/compiler-builtins/pull/606#issuecomment-2105657287>.
|| target.arch == "powerpc64"
|| cfg.target_arch == "powerpc64"
{
features.insert(Feature::NoSysF128);
to_set.insert(SetCfg::NoSysF128);
}
if target.arch == "x86" {
if cfg.target_arch == "x86" {
// 32-bit x86 does not have `__fixunstfti`/`__fixtfti` but does have everything else
features.insert(Feature::NoSysF128IntConvert);
to_set.insert(SetCfg::NoSysF128IntConvert);
// FIXME: 32-bit x86 has a bug in `f128 -> f16` system libraries
features.insert(Feature::NoSysF16F128Convert);
to_set.insert(SetCfg::NoSysF16F128Convert);
}
// These platforms do not have f16 symbols available in their system libraries, so
// skip related tests. Most of these are missing `f16 <-> f32` conversion routines.
if (target.arch == "aarch64" && target.os == "linux")
|| target.arch.starts_with("arm")
|| target.arch == "powerpc"
|| target.arch == "powerpc64"
|| target.arch == "powerpc64le"
|| target.arch == "loongarch64"
|| (target.arch == "x86" && !target.has_feature("sse"))
|| target.os == "windows"
if (cfg.target_arch == "aarch64" && cfg.target_os == "linux")
|| cfg.target_arch.starts_with("arm")
|| cfg.target_arch == "powerpc"
|| cfg.target_arch == "powerpc64"
|| cfg.target_arch == "powerpc64le"
|| cfg.target_arch == "loongarch64"
|| (cfg.target_arch == "x86" && !cfg.has_target_feature("sse"))
|| cfg.target_os == "windows"
// Linking says "error: function signature mismatch: __extendhfsf2" and seems to
// think the signature is either `(i32) -> f32` or `(f32) -> f32`. See
// <https://github.com/llvm/llvm-project/issues/96438>.
|| target.arch == "wasm32"
|| target.arch == "wasm64"
|| cfg.target_arch == "wasm32"
|| cfg.target_arch == "wasm64"
{
features.insert(Feature::NoSysF16);
to_set.insert(SetCfg::NoSysF16);
}
// These platforms are missing either `__extendhfdf2` or `__truncdfhf2`.
if target.vendor == "apple" || target.os == "windows" {
features.insert(Feature::NoSysF16F64Convert);
if cfg.target_vendor == "apple" || cfg.target_os == "windows" {
to_set.insert(SetCfg::NoSysF16F64Convert);
}
// Add implied features. Collection is required for borrows.
features.extend(
features
to_set.extend(
to_set
.iter()
.flat_map(|x| x.implies())
.copied()
.collect::<Vec<_>>(),
);
for feature in features {
let (name, warning) = match feature {
Feature::NoSysF128 => ("no-sys-f128", "using apfloat fallback for f128"),
Feature::NoSysF128IntConvert => (
"no-sys-f128-int-convert",
"using apfloat fallback for f128 <-> int conversions",
),
Feature::NoSysF16F64Convert => (
"no-sys-f16-f64-convert",
"using apfloat fallback for f16 <-> f64 conversions",
),
Feature::NoSysF16F128Convert => (
"no-sys-f16-f128-convert",
"using apfloat fallback for f16 <-> f128 conversions",
),
Feature::NoSysF16 => ("no-sys-f16", "using apfloat fallback for f16"),
};
println!("cargo:warning={warning}");
println!("cargo:rustc-cfg=feature=\"{name}\"");
for cfg in SetCfg::ALL {
set_cfg(cfg.name(), to_set.contains(cfg));
}
builtins_configure::configure_aliases(&target);
}
@@ -1,7 +1,7 @@
use alloc::vec::Vec;
use core::cell::RefCell;
use compiler_builtins::float::Float;
use compiler_builtins::support::Float;
/// Fuzz with these many items to ensure equal functions
pub const CHECK_ITER_ITEMS: u32 = 10_000;
@@ -43,7 +43,7 @@ pub fn skip_sys_checks(test_name: &str) -> bool {
return true;
}
if cfg!(x86_no_sse) && X86_NO_SSE_SKIPPED.contains(&test_name) {
if cfg!(x86_no_sse2) && X86_NO_SSE_SKIPPED.contains(&test_name) {
return true;
}
@@ -19,8 +19,7 @@
pub mod bench;
extern crate alloc;
use compiler_builtins::float::Float;
use compiler_builtins::int::{Int, MinInt};
use compiler_builtins::support::{Float, Int, MinInt};
use rand_xoshiro::Xoshiro128StarStar;
use rand_xoshiro::rand_core::{Rng, SeedableRng};
@@ -245,18 +244,18 @@ fn fuzz_float_step<F: Float>(rng: &mut Xoshiro128StarStar, f: &mut F) {
let sign = (rng32 & 1) != 0;
// exponent fuzzing. Only 4 bits for the selector needed.
let ones = (F::Int::ONE << F::EXP_BITS) - F::Int::ONE;
let ones = F::EXP_SAT;
let r0 = (rng32 >> 1) % F::EXP_BITS;
let r1 = (rng32 >> 5) % F::EXP_BITS;
// custom rotate shift. Note that `F::Int` is unsigned, so we can shift right without smearing
// the sign bit.
let mask = if r1 == 0 {
ones.wrapping_shr(r0)
ones >> r0
} else {
let tmp = ones.wrapping_shr(r0);
(tmp.wrapping_shl(r1) | tmp.wrapping_shr(F::EXP_BITS - r1)) & ones
let tmp = ones >> r0;
((tmp << r1) | (tmp >> (F::EXP_BITS - r1))) & ones
};
let mut exp = (f.to_bits() & F::EXP_MASK) >> F::SIG_BITS;
let mut exp = f.ex();
match (rng32 >> 9) % 4 {
0 => exp |= mask,
1 => exp &= mask,
@@ -274,13 +273,13 @@ fn fuzz_float_step<F: Float>(rng: &mut Xoshiro128StarStar, f: &mut F) {
macro_rules! float_edge_cases {
($F:ident, $case:ident, $inner:block) => {
for exponent in [
F::Int::ZERO,
F::Int::ONE,
F::Int::ONE << (F::EXP_BITS / 2),
(F::Int::ONE << (F::EXP_BITS - 1)) - F::Int::ONE,
F::Int::ONE << (F::EXP_BITS - 1),
(F::Int::ONE << (F::EXP_BITS - 1)) + F::Int::ONE,
(F::Int::ONE << F::EXP_BITS) - F::Int::ONE,
0,
1,
1 << (F::EXP_BITS / 2),
(1 << (F::EXP_BITS - 1)) - 1,
1 << (F::EXP_BITS - 1),
(1 << (F::EXP_BITS - 1)) + 1,
(1 << F::EXP_BITS) - 1,
]
.iter()
{
@@ -87,7 +87,8 @@ macro_rules! float_sum {
#[test]
fn $fn_add() {
use core::ops::{Add, Sub};
use compiler_builtins::float::{{add::$fn_add, sub::$fn_sub}, Float};
use compiler_builtins::float::{add::$fn_add, sub::$fn_sub};
use compiler_builtins::support::Float;
fuzz_float_2(N, |x: $f, y: $f| {
let add0 = apfloat_fallback!($f, $apfloat_ty, $sys_available, Add::add, x, y);
@@ -112,7 +113,7 @@ fn $fn_add() {
}
}
#[cfg(not(x86_no_sse))]
#[cfg(not(x86_no_sse2))]
mod float_addsub {
use super::*;
@@ -127,15 +128,15 @@ mod float_addsub {
}
#[cfg(f128_enabled)]
#[cfg(not(x86_no_sse))]
#[cfg(not(x86_no_sse2))]
#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
float_sum! {
f128, __addtf3, __subtf3, Quad, not(feature = "no-sys-f128");
f128, __addtf3, __subtf3, Quad, not(no_sys_f128);
}
#[cfg(f128_enabled)]
#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
float_sum! {
f128, __addkf3, __subkf3, Quad, not(feature = "no-sys-f128");
f128, __addkf3, __subkf3, Quad, not(no_sys_f128);
}
}
@@ -1,134 +0,0 @@
use compiler_builtins::int::{HInt, MinInt, i256, u256};
const LOHI_SPLIT: u128 = 0xaaaaaaaaaaaaaaaaffffffffffffffff;
/// Print a `u256` as hex since we can't add format implementations
fn hexu(v: u256) -> String {
format!(
"0x{:016x}{:016x}{:016x}{:016x}",
v.0[3], v.0[2], v.0[1], v.0[0]
)
}
#[test]
fn widen_u128() {
assert_eq!(u128::MAX.widen(), u256([u64::MAX, u64::MAX, 0, 0]));
assert_eq!(
LOHI_SPLIT.widen(),
u256([u64::MAX, 0xaaaaaaaaaaaaaaaa, 0, 0])
);
}
#[test]
fn widen_i128() {
assert_eq!((-1i128).widen(), u256::MAX.signed());
assert_eq!(
(LOHI_SPLIT as i128).widen(),
i256([u64::MAX, 0xaaaaaaaaaaaaaaaa, u64::MAX, u64::MAX])
);
assert_eq!((-1i128).zero_widen().unsigned(), (u128::MAX).widen());
}
#[test]
fn widen_mul_u128() {
let tests = [
(u128::MAX / 2, 2_u128, u256([u64::MAX - 1, u64::MAX, 0, 0])),
(u128::MAX, 2_u128, u256([u64::MAX - 1, u64::MAX, 1, 0])),
(u128::MAX, u128::MAX, u256([1, 0, u64::MAX - 1, u64::MAX])),
(u128::MIN, u128::MIN, u256::ZERO),
(1234, 0, u256::ZERO),
(0, 1234, u256::ZERO),
];
let mut errors = Vec::new();
for (i, (a, b, exp)) in tests.iter().copied().enumerate() {
let res = a.widen_mul(b);
let res_z = a.zero_widen_mul(b);
assert_eq!(res, res_z);
if res != exp {
errors.push((i, a, b, exp, res));
}
}
for (i, a, b, exp, res) in &errors {
eprintln!(
"FAILURE ({i}): {a:#034x} * {b:#034x} = {} got {}",
hexu(*exp),
hexu(*res)
);
}
assert!(errors.is_empty());
}
#[test]
fn not_u128() {
assert_eq!(!u256::ZERO, u256::MAX);
}
#[test]
fn shr_u128() {
let only_low = [
1,
u16::MAX.into(),
u32::MAX.into(),
u64::MAX.into(),
u128::MAX,
];
let mut errors = Vec::new();
for a in only_low {
for perturb in 0..10 {
let a = a.saturating_add(perturb);
for shift in 0..128 {
let res = a.widen() >> shift;
let expected = (a >> shift).widen();
if res != expected {
errors.push((a.widen(), shift, res, expected));
}
}
}
}
let check = [
(
u256::MAX,
1,
u256([u64::MAX, u64::MAX, u64::MAX, u64::MAX >> 1]),
),
(
u256::MAX,
5,
u256([u64::MAX, u64::MAX, u64::MAX, u64::MAX >> 5]),
),
(u256::MAX, 63, u256([u64::MAX, u64::MAX, u64::MAX, 1])),
(u256::MAX, 64, u256([u64::MAX, u64::MAX, u64::MAX, 0])),
(u256::MAX, 65, u256([u64::MAX, u64::MAX, u64::MAX >> 1, 0])),
(u256::MAX, 127, u256([u64::MAX, u64::MAX, 1, 0])),
(u256::MAX, 128, u256([u64::MAX, u64::MAX, 0, 0])),
(u256::MAX, 129, u256([u64::MAX, u64::MAX >> 1, 0, 0])),
(u256::MAX, 191, u256([u64::MAX, 1, 0, 0])),
(u256::MAX, 192, u256([u64::MAX, 0, 0, 0])),
(u256::MAX, 193, u256([u64::MAX >> 1, 0, 0, 0])),
(u256::MAX, 191, u256([u64::MAX, 1, 0, 0])),
(u256::MAX, 254, u256([0b11, 0, 0, 0])),
(u256::MAX, 255, u256([1, 0, 0, 0])),
];
for (input, shift, expected) in check {
let res = input >> shift;
if res != expected {
errors.push((input, shift, res, expected));
}
}
for (a, b, res, expected) in &errors {
eprintln!(
"FAILURE: {} >> {b} = {} got {}",
hexu(*a),
hexu(*expected),
hexu(*res),
);
}
assert!(errors.is_empty());
}
@@ -125,19 +125,19 @@ fn cmp_f128() {
fuzz_float_2(N, |x: f128, y: f128| {
let x_is_nan = apfloat_fallback!(
f128, Quad, not(feature = "no-sys-f128"),
f128, Quad, not(no_sys_f128),
|x: FloatTy| x.is_nan() => no_convert,
x
);
let y_is_nan = apfloat_fallback!(
f128, Quad, not(feature = "no-sys-f128"),
f128, Quad, not(no_sys_f128),
|x: FloatTy| x.is_nan() => no_convert,
y
);
assert_eq!(__unordtf2(x, y) != 0, x_is_nan || y_is_nan);
cmp!(f128, x, y, Quad, not(feature = "no-sys-f128"),
cmp!(f128, x, y, Quad, not(no_sys_f128),
1, __lttf2;
1, __letf2;
1, __eqtf2;
@@ -6,7 +6,7 @@
#![allow(unused_macros)]
use builtins_test::*;
use compiler_builtins::float::Float;
use compiler_builtins::support::Float;
use rustc_apfloat::{Float as _, FloatConvert as _};
mod i_to_f {
@@ -18,7 +18,7 @@ macro_rules! i_to_f {
#[test]
fn $fn() {
use compiler_builtins::float::conv::$fn;
use compiler_builtins::int::Int;
use compiler_builtins::support::Int;
fuzz(N, |x: $i_ty| {
let f0 = apfloat_fallback!(
@@ -27,7 +27,7 @@ fn $fn() {
// When the builtin is not available, we need to use a different conversion
// method (since apfloat doesn't support `as` casting).
|x: $i_ty| {
use compiler_builtins::int::MinInt;
use compiler_builtins::support::MinInt;
let apf = if <$i_ty>::SIGNED {
FloatTy::from_i128(x.try_into().unwrap()).value
@@ -117,7 +117,7 @@ fn $fn() {
#[cfg(f128_enabled)]
#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
i_to_f! { f128, Quad, not(feature = "no-sys-f128-int-convert"),
i_to_f! { f128, Quad, not(no_sys_f128_int_convert),
u32, __floatunsitf;
i32, __floatsitf;
u64, __floatunditf;
@@ -128,7 +128,7 @@ fn $fn() {
#[cfg(f128_enabled)]
#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
i_to_f! { f128, Quad, not(feature = "no-sys-f128-int-convert"),
i_to_f! { f128, Quad, not(no_sys_f128_int_convert),
u32, __floatunsikf;
i32, __floatsikf;
u64, __floatundikf;
@@ -155,7 +155,7 @@ macro_rules! f_to_i {
// When the builtin is not available, we need to use a different conversion
// method (since apfloat doesn't support `as` casting).
|x: $f_ty| {
use compiler_builtins::int::MinInt;
use compiler_builtins::support::MinInt;
let apf = FloatTy::from_bits(x.to_bits().into());
let bits: usize = <$i_ty>::BITS.try_into().unwrap();
@@ -236,7 +236,7 @@ fn f128_to_int() {
x,
f128,
Quad,
not(feature = "no-sys-f128-int-convert"),
not(no_sys_f128_int_convert),
u32, __fixunstfsi;
u64, __fixunstfdi;
u128, __fixunstfti;
@@ -259,7 +259,8 @@ macro_rules! f_to_f {
) => {$(
#[test]
fn $fn() {
use compiler_builtins::float::{$mod::$fn, Float};
use compiler_builtins::float::$mod::$fn;
use compiler_builtins::support::Float;
use rustc_apfloat::ieee::{$from_ap_ty, $to_ap_ty};
fuzz_float(N, |x: $from_ty| {
@@ -308,12 +309,12 @@ mod extend {
)))]
f_to_f! {
extend,
f16 => f32, Half => Single, __extendhfsf2, not(feature = "no-sys-f16");
f16 => f32, Half => Single, __gnu_h2f_ieee, not(feature = "no-sys-f16");
f16 => f64, Half => Double, __extendhfdf2, not(feature = "no-sys-f16-f64-convert");
f16 => f128, Half => Quad, __extendhftf2, not(feature = "no-sys-f16-f128-convert");
f32 => f128, Single => Quad, __extendsftf2, not(feature = "no-sys-f128");
f64 => f128, Double => Quad, __extenddftf2, not(feature = "no-sys-f128");
f16 => f32, Half => Single, __extendhfsf2, not(no_sys_f16);
f16 => f32, Half => Single, __gnu_h2f_ieee, not(no_sys_f16);
f16 => f64, Half => Double, __extendhfdf2, not(no_sys_f16_f64_convert);
f16 => f128, Half => Quad, __extendhftf2, not(no_sys_f16_f128_convert);
f32 => f128, Single => Quad, __extendsftf2, not(no_sys_f128);
f64 => f128, Double => Quad, __extenddftf2, not(no_sys_f128);
}
#[cfg(f128_enabled)]
@@ -321,8 +322,8 @@ mod extend {
f_to_f! {
extend,
// FIXME(#655): `f16` tests disabled until we can bootstrap symbols
f32 => f128, Single => Quad, __extendsfkf2, not(feature = "no-sys-f128");
f64 => f128, Double => Quad, __extenddfkf2, not(feature = "no-sys-f128");
f32 => f128, Single => Quad, __extendsfkf2, not(no_sys_f128);
f64 => f128, Double => Quad, __extenddfkf2, not(no_sys_f128);
}
}
@@ -342,12 +343,12 @@ mod trunc {
)))]
f_to_f! {
trunc,
f32 => f16, Single => Half, __truncsfhf2, not(feature = "no-sys-f16");
f32 => f16, Single => Half, __gnu_f2h_ieee, not(feature = "no-sys-f16");
f64 => f16, Double => Half, __truncdfhf2, not(feature = "no-sys-f16-f64-convert");
f128 => f16, Quad => Half, __trunctfhf2, not(feature = "no-sys-f16-f128-convert");
f128 => f32, Quad => Single, __trunctfsf2, not(feature = "no-sys-f128");
f128 => f64, Quad => Double, __trunctfdf2, not(feature = "no-sys-f128");
f32 => f16, Single => Half, __truncsfhf2, not(no_sys_f16);
f32 => f16, Single => Half, __gnu_f2h_ieee, not(no_sys_f16);
f64 => f16, Double => Half, __truncdfhf2, not(no_sys_f16_f64_convert);
f128 => f16, Quad => Half, __trunctfhf2, not(no_sys_f16_f128_convert);
f128 => f32, Quad => Single, __trunctfsf2, not(no_sys_f128);
f128 => f64, Quad => Double, __trunctfdf2, not(no_sys_f128);
}
#[cfg(f128_enabled)]
@@ -355,7 +356,7 @@ mod trunc {
f_to_f! {
trunc,
// FIXME(#655): `f16` tests disabled until we can bootstrap symbols
f128 => f32, Quad => Single, __trunckfsf2, not(feature = "no-sys-f128");
f128 => f64, Quad => Double, __trunckfdf2, not(feature = "no-sys-f128");
f128 => f32, Quad => Single, __trunckfsf2, not(no_sys_f128);
f128 => f64, Quad => Double, __trunckfdf2, not(no_sys_f128);
}
}
@@ -109,7 +109,8 @@ macro_rules! float {
$(
#[test]
fn $fn() {
use compiler_builtins::float::{div::$fn, Float};
use compiler_builtins::float::div::$fn;
use compiler_builtins::support::Float;
use core::ops::Div;
fuzz_float_2(N, |x: $f, y: $f| {
@@ -138,7 +139,7 @@ fn $fn() {
};
}
#[cfg(not(x86_no_sse))]
#[cfg(not(x86_no_sse2))]
mod float_div {
use super::*;
@@ -153,12 +154,12 @@ mod float_div {
f128, __divtf3, Quad,
// FIXME(llvm): there is a bug in LLVM rt.
// See <https://github.com/llvm/llvm-project/issues/91840>.
not(any(feature = "no-sys-f128", all(target_arch = "aarch64", target_os = "linux")));
not(any(no_sys_f128, all(target_arch = "aarch64", target_os = "linux")));
}
#[cfg(f128_enabled)]
#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
float! {
f128, __divkf3, Quad, not(feature = "no-sys-f128");
f128, __divkf3, Quad, not(no_sys_f128);
}
}
@@ -1,7 +1,7 @@
#![allow(unused_macros, unused_features)]
#![cfg_attr(f128_enabled, feature(f128))]
#[cfg_attr(x86_no_sse, allow(unused))]
#[cfg_attr(x86_no_sse2, allow(unused))]
use builtins_test::*;
// This is approximate because of issues related to
@@ -16,7 +16,8 @@ macro_rules! pow {
#[cfg($sys_available)]
fn $fn() {
use compiler_builtins::float::pow::$fn;
use compiler_builtins::float::Float;
use compiler_builtins::support::Float;
fuzz_float_2(N, |x: $f, y: $f| {
if !(Float::is_subnormal(x) || Float::is_subnormal(y) || x.is_nan()) {
let n = y.to_bits() & !<$f as Float>::SIG_MASK;
@@ -52,7 +53,7 @@ fn $fn() {
};
}
#[cfg(not(x86_no_sse))] // FIXME(i586): failure for powidf2
#[cfg(not(x86_no_sse2))] // FIXME(i586): failure for powidf2
pow! {
f32, 1e-4, __powisf2, all();
f64, 1e-12, __powidf2, all();
@@ -61,11 +62,11 @@ fn $fn() {
#[cfg(f128_enabled)]
#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
pow! {
f128, 1e-36, __powitf2, not(feature = "no-sys-f128");
f128, 1e-36, __powitf2, not(no_sys_f128);
}
#[cfg(f128_enabled)]
#[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
pow! {
f128, 1e-36, __powikf2, not(feature = "no-sys-f128");
f128, 1e-36, __powikf2, not(no_sys_f128);
}
@@ -1,12 +1,12 @@
#![allow(unused_features)]
#![feature(decl_macro)] // so we can use pub(super)
#![feature(macro_metavar_expr_concat)]
#![cfg(all(target_arch = "aarch64", feature = "mangled-names"))]
#![cfg(target_arch = "aarch64")]
use std::sync::Mutex;
use compiler_builtins::aarch64_outline_atomics::{get_have_lse_atomics, set_have_lse_atomics};
use compiler_builtins::int::{Int, MinInt};
use compiler_builtins::support::{Int, MinInt};
use compiler_builtins::{foreach_bytes, foreach_ordering};
#[track_caller]
@@ -96,7 +96,8 @@ macro_rules! float_mul {
$(
#[test]
fn $fn() {
use compiler_builtins::float::{mul::$fn, Float};
use compiler_builtins::float::mul::$fn;
use compiler_builtins::support::Float;
use core::ops::Mul;
fuzz_float_2(N, |x: $f, y: $f| {
@@ -114,7 +115,7 @@ fn $fn() {
};
}
#[cfg(not(x86_no_sse))]
#[cfg(not(x86_no_sse2))]
mod float_mul {
use super::*;
@@ -132,7 +133,7 @@ mod float_mul {
}
#[cfg(f128_enabled)]
#[cfg(not(x86_no_sse))]
#[cfg(not(x86_no_sse2))]
#[cfg(not(any(target_arch = "powerpc", target_arch = "powerpc64")))]
mod float_mul_f128 {
use super::*;
@@ -141,7 +142,7 @@ mod float_mul_f128 {
f128, __multf3, Quad,
// FIXME(llvm): there is a bug in LLVM rt.
// See <https://github.com/llvm/llvm-project/issues/91840>.
not(any(feature = "no-sys-f128", all(target_arch = "aarch64", target_os = "linux")));
not(any(no_sys_f128, all(target_arch = "aarch64", target_os = "linux")));
}
}
@@ -151,6 +152,6 @@ mod float_mul_f128_ppc {
use super::*;
float_mul! {
f128, __mulkf3, Quad, not(feature = "no-sys-f128");
f128, __mulkf3, Quad, not(no_sys_f128);
}
}
+17 -4
View File
@@ -26,12 +26,20 @@ tag="$(echo "$target" | cut -d'-' -f1)"
# after the first run with gungraun.
[ -d "iai-home" ] && mv "iai-home" "$gungraun_home"
failed="0"
# Run benchmarks once
function run_icount_benchmarks() {
cargo_args=(
"--target" "$target"
"--bench" "*icount*"
"--no-default-features"
"--features" "unstable,unstable-float,icount"
"--features" "unstable unstable-float icount"
# Enable unmangled-names so our compiler-builtins gets used for
# intrinsics. This makes performance impacts of c-b changes show up
# in libm benchmarks and gives us a better idea of what will happen
# in std (e.g. speedups in __addtf3 will show up in fmaf128).
"--features" "compiler_builtins/unmangled-names"
)
gungraun_args=(
@@ -65,13 +73,18 @@ function run_icount_benchmarks() {
# Disregard regressions after merge
echo "Benchmarks completed with regressions; ignoring (not in a PR)"
else
./ci/ci-util.py handle-bench-regressions "$PR_NUMBER"
./ci/ci-util.py handle-bench-regressions "$PR_NUMBER" || failed="1"
fi
}
# Run once with softfloats, once with arch instructions enabled
run_icount_benchmarks --features force-soft-floats -- --save-baseline=softfloat
run_icount_benchmarks -- --save-baseline=hardfloat
run_icount_benchmarks -- --save-baseline=arch_disabled
run_icount_benchmarks --features arch -- --save-baseline=arch_enabled
if [ "$failed" != "0" ]; then
echo "One or more benchmarks failed"
exit 1
fi
# Name and tar the new baseline
name="baseline-icount-$tag-$(date -u +'%Y%m%d%H%M')-${GITHUB_SHA:0:12}"
@@ -6,4 +6,4 @@
export LIBM_SEED=benchesbenchesbenchesbencheswoo!
cargo bench --package libm-test \
--no-default-features \
--features walltime,short-benchmarks,build-musl,libm/force-soft-floats
--features walltime,short-benchmarks,build-musl
+4
View File
@@ -361,6 +361,10 @@ def base_name(name: str) -> tuple[str, str]:
return (name.rstrip("f"), "f32")
elif name.endswith("f16"):
return (name.rstrip("f16"), "f16")
elif name.endswith("f32"):
return (name.rstrip("f32"), "f32")
elif name.endswith("f64"):
return (name.rstrip("f64"), "f64")
elif name.endswith("f128"):
return (name.rstrip("f128"), "f128")
@@ -1,4 +1,4 @@
ARG IMAGE=ubuntu:25.10
ARG IMAGE=ubuntu:26.04
FROM $IMAGE
RUN apt-get update && \
@@ -1,4 +1,4 @@
ARG IMAGE=ubuntu:25.10
ARG IMAGE=ubuntu:26.04
FROM $IMAGE
RUN apt-get update && \
@@ -1,4 +1,4 @@
ARG IMAGE=ubuntu:25.10
ARG IMAGE=ubuntu:26.04
FROM $IMAGE
RUN apt-get update && \
@@ -1,4 +1,4 @@
ARG IMAGE=ubuntu:25.10
ARG IMAGE=ubuntu:26.04
FROM $IMAGE
RUN apt-get update && \
@@ -1,4 +1,4 @@
ARG IMAGE=ubuntu:25.10
ARG IMAGE=ubuntu:26.04
FROM $IMAGE
RUN apt-get update && \
@@ -1,4 +1,4 @@
ARG IMAGE=ubuntu:25.10
ARG IMAGE=ubuntu:26.04
FROM $IMAGE
RUN apt-get update && \
@@ -1,4 +1,4 @@
ARG IMAGE=ubuntu:25.10
ARG IMAGE=ubuntu:26.04
FROM $IMAGE
RUN apt-get update && \
@@ -1,4 +1,4 @@
ARG IMAGE=ubuntu:25.10
ARG IMAGE=ubuntu:26.04
FROM $IMAGE
RUN apt-get update && \
@@ -1,4 +1,4 @@
ARG IMAGE=ubuntu:25.10
ARG IMAGE=ubuntu:26.04
FROM $IMAGE
RUN apt-get update && \
@@ -1,4 +1,4 @@
ARG IMAGE=ubuntu:25.10
ARG IMAGE=ubuntu:26.04
FROM $IMAGE
RUN apt-get update && \
@@ -1,4 +1,4 @@
ARG IMAGE=ubuntu:25.10
ARG IMAGE=ubuntu:26.04
FROM $IMAGE
RUN apt-get update && \
@@ -1,4 +1,4 @@
ARG IMAGE=ubuntu:25.10
ARG IMAGE=ubuntu:26.04
FROM $IMAGE
RUN apt-get update && \
@@ -1,4 +1,4 @@
ARG IMAGE=ubuntu:25.10
ARG IMAGE=ubuntu:26.04
FROM $IMAGE
RUN apt-get update && \
@@ -1,4 +1,4 @@
ARG IMAGE=ubuntu:25.10
ARG IMAGE=ubuntu:26.04
FROM $IMAGE
RUN apt-get update && \
@@ -1,11 +1,11 @@
ARG IMAGE=ubuntu:25.10
ARG IMAGE=ubuntu:26.04
FROM $IMAGE
RUN apt-get update && \
apt-get install -y --no-install-recommends \
gcc libc6-dev qemu-user ca-certificates \
gcc-riscv64-linux-gnu libc6-dev-riscv64-cross \
qemu-system-riscv64
qemu-system-riscv
ENV TOOLCHAIN_PREFIX=riscv64-linux-gnu-
ENV CARGO_TARGET_RISCV64GC_UNKNOWN_LINUX_GNU_LINKER="$TOOLCHAIN_PREFIX"gcc \
@@ -1,4 +1,4 @@
ARG IMAGE=ubuntu:25.10
ARG IMAGE=ubuntu:26.04
FROM $IMAGE
RUN apt-get update && \
@@ -1,4 +1,4 @@
ARG IMAGE=ubuntu:25.10
ARG IMAGE=ubuntu:26.04
FROM $IMAGE
RUN apt-get update && \
@@ -1,4 +1,4 @@
ARG IMAGE=ubuntu:25.10
ARG IMAGE=ubuntu:26.04
FROM $IMAGE
RUN apt-get update && \
@@ -1,4 +1,4 @@
ARG IMAGE=ubuntu:25.10
ARG IMAGE=ubuntu:26.04
FROM $IMAGE
RUN apt-get update && \
@@ -1,4 +1,4 @@
ARG IMAGE=ubuntu:25.10
ARG IMAGE=ubuntu:26.04
FROM $IMAGE
RUN apt-get update && \
@@ -1,4 +1,4 @@
ARG IMAGE=ubuntu:25.10
ARG IMAGE=ubuntu:26.04
FROM $IMAGE
RUN apt-get update && \
@@ -6,5 +6,5 @@ set -eux
rust_llvm_version=20.1-2025-02-13
curl -L -o code.tar.gz "https://github.com/rust-lang/llvm-project/archive/rustc/${rust_llvm_version}.tar.gz"
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
@@ -1,10 +1,22 @@
#!/bin/sh
#!/bin/bash
# Install needed dependencies for gungraun.
set -eux
target="${1:-}"
# Needed for gungraun
deps=(valgrind gdb libc6-dbg)
[[ "$target" = *"i686"* ]] && deps+=(gcc-multilib)
sudo apt-get update
sudo apt-get install -y valgrind gdb libc6-dbg # Needed for gungraun
sudo apt-get install -y "${deps[@]}"
rustup update "$BENCHMARK_RUSTC" --no-self-update
rustup default "$BENCHMARK_RUSTC"
[ -n "$target" ] && rustup target add "$target"
# Install the version of gungraun-runner that is specified in Cargo.toml
gungraun_version="$(cargo metadata --format-version=1 --features icount |
jq -r '.packages[] | select(.name == "gungraun").version')"
+4 -3
View File
@@ -5,7 +5,7 @@ set -eux
# compatible with Stacked Borrows.
export MIRIFLAGS="-Zmiri-tree-borrows"
# One target that sets `mem-unaligned` and one that does not,
# One target that sets `mem_unaligned` and one that does not,
# and a big-endian target.
targets=(
x86_64-unknown-linux-gnu
@@ -13,10 +13,11 @@ targets=(
s390x-unknown-linux-gnu
)
for target in "${targets[@]}"; do
# Only run the `mem` tests to avoid this taking too long.
# Only run the `mem` tests to avoid this taking too long. Disable default
# features to turn off `arch` and avoid inline assembly.
cargo miri test \
--manifest-path builtins-test/Cargo.toml \
--features no-asm \
--no-default-features \
--target "$target" \
-- mem
done
+2 -1
View File
@@ -78,6 +78,7 @@ run() {
-e CI \
-e CARGO_TARGET_DIR=/builtins-target \
-e CARGO_TERM_COLOR \
-e LIBM_BUILD_VERBOSE \
-e MAY_SKIP_LIBM_CI \
-e RUSTFLAGS \
-e RUST_BACKTRACE \
@@ -97,7 +98,7 @@ if [ "${1:-}" = "--help" ] || [ "$#" -gt 1 ]; then
usage: ./ci/run-docker.sh [target]
you can also set DOCKER_BASE_IMAGE to use something other than the default
ubuntu:25.10 (or rustlang/rust:nightly).
ubuntu:26.04 (or rustlang/rust:nightly).
"
exit
fi
@@ -14,7 +14,15 @@ set -x
test_cmd=(
cargo test
--package libm-test
--features "build-mpfr,libm/unstable,libm/force-soft-floats"
--no-default-features
# Don't enable `arch` for extensive tests. Usually anything in asm is
# only a single instruction or a small sequence, and we rely on the
# vendors to test that for us.
#
# libm/unstable enables libm/unstable-intrinsics, which means we usually
# get the single-instruction ops anyway when we aren't specifically
# testing for them.
--features "libm-test/build-mpfr libm-test/unstable-float libm/unstable"
--profile release-checked
)
+46 -39
View File
@@ -20,19 +20,45 @@ if [ "${USING_CONTAINER_RUSTC:-}" = 1 ]; then
rustup target add "$target"
fi
# If nextest is available, use that
command -v cargo-nextest && nextest=1 || nextest=0
if [ "$nextest" = "1" ]; then
test_runner=(cargo nextest run --max-fail=20)
profile_flag="--cargo-profile"
# Workaround for https://github.com/nextest-rs/nextest/issues/2066
if [ -n "${CARGO_TARGET_DIR:-}" ]; then
cfg_file="/tmp/nextest-config.toml"
echo "[store]" >> "$cfg_file"
echo "dir = \"$CARGO_TARGET_DIR/nextest\"" >> "$cfg_file"
test_runner+=(--config-file "$cfg_file")
fi
# Not all configurations have tests to run on wasm
[[ "$target" = *"wasm"* ]] && test_runner+=(--no-tests=warn)
else
test_runner=(cargo test --no-fail-fast)
profile_flag="--profile"
fi
# Test our implementation
if [ "${BUILD_ONLY:-}" = "1" ]; then
echo "no tests to run for build-only targets"
else
test_builtins=(cargo test --package builtins-test --no-fail-fast --target "$target")
test_builtins=(
"${test_runner[@]}"
--package builtins-test
--target "$target"
)
"${test_builtins[@]}"
"${test_builtins[@]}" --release
"${test_builtins[@]}" --features c
"${test_builtins[@]}" --features c --release
"${test_builtins[@]}" --features no-asm
"${test_builtins[@]}" --features no-asm --release
"${test_builtins[@]}" --benches
"${test_builtins[@]}" --benches --release
"${test_builtins[@]}" --no-default-features
"${test_builtins[@]}" --no-default-features --release
# Validate that having a verbatim path for the target directory works
# (trivial to regress using `/` in paths to build artifacts rather than
@@ -53,12 +79,14 @@ symcheck+=(-- --build-and-check --target "$target")
# Executable section checks are meaningless on no-std targets
[[ "$target" == *"-none"* ]] && symcheck+=(--no-os)
"${symcheck[@]}" -- -p compiler_builtins
"${symcheck[@]}" -- -p compiler_builtins --release
"${symcheck[@]}" -- -p compiler_builtins --features c
"${symcheck[@]}" -- -p compiler_builtins --features c --release
"${symcheck[@]}" -- -p compiler_builtins --features no-asm
"${symcheck[@]}" -- -p compiler_builtins --features no-asm --release
# We only need to check the configurations std may use
symcheck_cb_args=(-- --package compiler_builtins --features compiler-builtins)
"${symcheck[@]}" "${symcheck_cb_args[@]}"
"${symcheck[@]}" "${symcheck_cb_args[@]}" --release
"${symcheck[@]}" "${symcheck_cb_args[@]}" --features c
"${symcheck[@]}" "${symcheck_cb_args[@]}" --features c --release
"${symcheck[@]}" "${symcheck_cb_args[@]}" --no-default-features
"${symcheck[@]}" "${symcheck_cb_args[@]}" --no-default-features --release
run_intrinsics_test() {
build_args=(--verbose --manifest-path builtins-test-intrinsics/Cargo.toml)
@@ -100,13 +128,13 @@ mflags=()
# We enumerate features manually.
mflags+=(--no-default-features)
# Enable arch-specific routines when available.
mflags+=(--features arch)
# Always enable `unstable-float` since it expands available API but does not
# change any implementations.
mflags+=(--features unstable-float)
# This is a host program that may not run in containers.
mflags+=(--exclude update-api-list)
# We need to specifically skip tests for musl-math-sys on systems that can't
# build musl since otherwise `--all` will activate it.
case "$target" in
@@ -157,28 +185,7 @@ if [ "${BUILD_ONLY:-}" = "1" ]; then
else
# symcheck tests need specific env setup, and is already tested above
mflags+=(--workspace --exclude symbol-check --target "$target")
cmd=(cargo test "${mflags[@]}")
profile_flag="--profile"
# If nextest is available, use that
command -v cargo-nextest && nextest=1 || nextest=0
if [ "$nextest" = "1" ]; then
cmd=(cargo nextest run --max-fail=10)
# Workaround for https://github.com/nextest-rs/nextest/issues/2066
if [ -f /.dockerenv ]; then
cfg_file="/tmp/nextest-config.toml"
echo "[store]" >> "$cfg_file"
echo "dir = \"$CARGO_TARGET_DIR/nextest\"" >> "$cfg_file"
cmd+=(--config-file "$cfg_file")
fi
# Not all configurations have tests to run on wasm
[[ "$target" = *"wasm"* ]] && cmd+=(--no-tests=warn)
cmd+=("${mflags[@]}")
profile_flag="--cargo-profile"
fi
cmd=("${test_runner[@]}" "${mflags[@]}")
# Test once without intrinsics
"${cmd[@]}"
@@ -191,15 +198,15 @@ else
cmd+=(--exclude util --exclude libm-macros)
# Test once with intrinsics enabled
"${cmd[@]}" --features unstable-intrinsics
"${cmd[@]}" --features unstable-intrinsics --benches
"${cmd[@]}" --features arch,unstable-intrinsics
"${cmd[@]}" --features arch,unstable-intrinsics --benches
# Test the same in release mode, which also increases coverage. Also ensure
# the soft float routines are checked.
"${cmd[@]}" "$profile_flag" release-checked
"${cmd[@]}" "$profile_flag" release-checked --features force-soft-floats
"${cmd[@]}" "$profile_flag" release-checked --features unstable-intrinsics
"${cmd[@]}" "$profile_flag" release-checked --features unstable-intrinsics --benches
"${cmd[@]}" "$profile_flag" release-checked --features arch
"${cmd[@]}" "$profile_flag" release-checked --features arch,unstable-intrinsics
"${cmd[@]}" "$profile_flag" release-checked --features arch,unstable-intrinsics --benches
# Ensure that the routines do not panic.
#
@@ -34,27 +34,28 @@ core = { path = "../../core", optional = true }
cc = { version = "1.2", optional = true }
[features]
default = []
default = ["arch"]
# Enable architecture-specific features such as SIMD or assembly routines. If
# disabled, the generic version can be tested on any platform.
arch = []
# Enable compilation of C code in compiler-rt, filling in some more optimized
# implementations and also filling in unimplemented intrinsics
c = ["dep:cc"]
# For implementations where there is both a generic version and a platform-
# specific version, use the generic version. This is meant to enable testing
# the generic versions on all platforms.
no-asm = []
# Flag this library as the unstable compiler-builtins lib. This must be enabled
# when using as `std`'s dependency.'
compiler-builtins = ["dep:core"]
compiler-builtins = ["dep:core", "unmangled-names"]
# Generate memory-related intrinsics like memcpy
# Enable `no_mangle` symbols for memory-related intrinsics like memcpy. The
# mangled versions are always available.
mem = []
# Mangle all names so this can be linked in with other versions or other
# compiler-rt implementations. Also used for testing
mangled-names = []
# Enable `no_mangle` symbols so this crate gets used as the runtime intrinsic
# implementation. Leave this disabled for testing to avoid conflicting with
# the system intrinsics.
unmangled-names = []
# This makes certain traits and function specializations public that
# are not normally public but are required by the `builtins-test`
@@ -1,120 +1,85 @@
#[path = "../libm/configure.rs"]
mod configure;
use std::env;
use configure::{Target, configure_aliases};
use configure::{Config, Library, set_cfg};
fn main() {
println!("cargo::rerun-if-changed=build.rs");
println!("cargo::rerun-if-changed=configure.rs");
let cfg = Config::from_env(Library::CompilerBuiltins);
let llvm_target = &cfg.target_triple_split;
let target = Target::from_env();
let cwd = env::current_dir().unwrap();
// Work around building as part of `builtins-shim`: if only `build.rs` is used, Cargo always
// considers the build dirty because `builtins-shim/build.rs` does not exist. If only
// `../c-b/build.rs` is used, the same may happen if not built in the workspace.
if cfg.manifest_dir.file_name().unwrap() == "builtins-shim" {
println!("cargo::rerun-if-changed=../compiler-builtins/build.rs");
} else {
println!("cargo::rerun-if-changed=build.rs");
}
println!("cargo::rerun-if-changed=../libm/configure.rs");
configure::emit(&cfg);
configure_check_cfg();
configure_aliases(&target);
configure_libm(&target);
let cwd = env::current_dir().unwrap();
println!("cargo:compiler-rt={}", cwd.join("compiler-rt").display());
println!("cargo::rustc-check-cfg=cfg(kernel_user_helpers)");
println!("cargo::rustc-check-cfg=cfg(feature, values(\"mem-unaligned\"))");
// Emscripten's runtime includes all the builtins
if target.os == "emscripten" {
return;
}
// OpenBSD provides compiler_rt by default, use it instead of rebuilding it from source
if target.os == "openbsd" {
println!("cargo:rustc-link-search=native=/usr/lib");
println!("cargo:rustc-link-lib=compiler_rt");
return;
}
// Forcibly enable memory intrinsics on wasm & SGX as we don't have a libc to
// provide them.
if (target.triple.contains("wasm") && !target.triple.contains("wasi"))
|| (target.triple.contains("sgx") && target.triple.contains("fortanix"))
|| target.triple.contains("-none")
|| target.triple.contains("nvptx")
|| target.triple.contains("uefi")
|| target.triple.contains("xous")
if (cfg.target_triple.contains("wasm") && !cfg.target_triple.contains("wasi"))
|| (cfg.target_triple.contains("sgx") && cfg.target_triple.contains("fortanix"))
|| cfg.target_triple.contains("-none")
|| cfg.target_triple.contains("nvptx")
|| cfg.target_triple.contains("uefi")
|| cfg.target_triple.contains("xous")
{
println!("cargo:rustc-cfg=feature=\"mem\"");
}
// These targets have hardware unaligned access support.
if target.arch.contains("x86_64")
|| target.arch.contains("x86")
|| target.arch.contains("aarch64")
|| target.arch.contains("bpf")
{
println!("cargo:rustc-cfg=feature=\"mem-unaligned\"");
let mem_unaligned = cfg.target_arch.contains("x86_64")
|| cfg.target_arch.contains("x86")
|| cfg.target_arch.contains("aarch64")
|| cfg.target_arch.contains("bpf");
set_cfg("mem_unaligned", mem_unaligned);
// Only emit the ARM Linux atomic emulation on pre-ARMv6 architectures. This
// includes the old androideabi. It is deprecated but it is available as a
// rustc target (arm-linux-androideabi).
let kernel_user_helpers = llvm_target[0] == "armv4t"
|| llvm_target[0] == "armv5te"
|| cfg.target_triple == "arm-linux-androideabi";
set_cfg("kernel_user_helpers", kernel_user_helpers);
let mut maybe_build_c = true;
// Emscripten's runtime includes all the builtins
if cfg.target_os == "emscripten" {
maybe_build_c = false;
}
// NOTE we are going to assume that llvm-target, what determines our codegen option, matches the
// target triple. This is usually correct for our built-in targets but can break in presence of
// custom targets, which can have arbitrary names.
let llvm_target = target.triple.split('-').collect::<Vec<_>>();
// OpenBSD provides compiler_rt by default, use it instead of rebuilding it from source
if cfg.target_os == "openbsd" {
println!("cargo:rustc-link-search=native=/usr/lib");
println!("cargo:rustc-link-lib=compiler_rt");
maybe_build_c = false;
}
// Everything is LLVM bitcode, not compatible with mixed C/Rust
if cfg.target_arch.contains("nvptx") {
maybe_build_c = false;
}
// Build missing intrinsics from compiler-rt C source code. If we're
// mangling names though we assume that we're also in test mode so we don't
// build anything and we rely on the upstream implementation of compiler-rt
// functions
if !cfg!(feature = "mangled-names") && cfg!(feature = "c") {
// Don't use a C compiler for these targets:
//
// * nvptx - everything is bitcode, not compatible with mixed C/Rust
if !target.arch.contains("nvptx") {
#[cfg(feature = "c")]
c::compile(&llvm_target, &target);
}
if cfg!(feature = "unmangled-names") && cfg!(feature = "c") && maybe_build_c {
#[cfg(feature = "c")]
c::compile(&cfg);
}
// Only emit the ARM Linux atomic emulation on pre-ARMv6 architectures. This
// includes the old androideabi. It is deprecated but it is available as a
// rustc target (arm-linux-androideabi).
if llvm_target[0] == "armv4t"
|| llvm_target[0] == "armv5te"
|| target.triple == "arm-linux-androideabi"
{
println!("cargo:rustc-cfg=kernel_user_helpers")
}
}
/// Run configuration for `libm` since it is included directly.
///
/// Much of this is copied from `libm/configure.rs`.
fn configure_libm(target: &Target) {
println!("cargo:rustc-check-cfg=cfg(intrinsics_enabled)");
println!("cargo:rustc-check-cfg=cfg(arch_enabled)");
println!("cargo:rustc-check-cfg=cfg(optimizations_enabled)");
println!("cargo:rustc-check-cfg=cfg(feature, values(\"unstable-public-internals\"))");
// Always use intrinsics
println!("cargo:rustc-cfg=intrinsics_enabled");
// The arch module may contain assembly.
if !cfg!(feature = "no-asm") {
println!("cargo:rustc-cfg=arch_enabled");
}
println!("cargo:rustc-check-cfg=cfg(optimizations_enabled)");
if !matches!(target.opt_level.as_str(), "0" | "1") {
println!("cargo:rustc-cfg=optimizations_enabled");
}
println!(
"cargo:rustc-env=CFG_CARGO_FEATURES={:?}",
target.cargo_features
);
println!("cargo:rustc-env=CFG_OPT_LEVEL={}", target.opt_level);
println!("cargo:rustc-env=CFG_TARGET_FEATURES={:?}", target.features);
// Activate libm's unstable features to make full use of Nightly.
println!("cargo:rustc-cfg=feature=\"unstable-intrinsics\"");
}
/// Emit directives for features we expect to support that aren't in `Cargo.toml`.
@@ -176,10 +141,6 @@ fn configure_check_cfg() {
// Rustc is unaware of sparc target features, but this does show up from
// `rustc --print target-features --target sparc64-unknown-linux-gnu`.
println!("cargo::rustc-check-cfg=cfg(target_feature, values(\"vis3\"))");
// FIXME: these come from libm and should be changed there
println!("cargo::rustc-check-cfg=cfg(feature, values(\"checked\"))");
println!("cargo::rustc-check-cfg=cfg(assert_no_panic)");
}
#[cfg(feature = "c")]
@@ -190,7 +151,7 @@ mod c {
use std::io::Write;
use std::path::{Path, PathBuf};
use super::Target;
use super::Config;
struct Sources {
// SYMBOL -> PATH TO SOURCE
@@ -232,17 +193,18 @@ fn remove(&mut self, symbols: &[&str]) {
}
/// Compile intrinsics from the compiler-rt C source code
pub fn compile(llvm_target: &[&str], target: &Target) {
pub fn compile(cfg: &Config) {
let llvm_target = &cfg.target_triple_split;
let mut consider_float_intrinsics = true;
let cfg = &mut cc::Build::new();
let build = &mut cc::Build::new();
// AArch64 GCCs exit with an error condition when they encounter any kind of floating point
// code if the `nofp` and/or `nosimd` compiler flags have been set.
//
// Therefore, evaluate if those flags are present and set a boolean that causes any
// compiler-rt intrinsics that contain floating point source to be excluded for this target.
if target.arch == "aarch64" {
let cflags_key = String::from("CFLAGS_") + &(target.triple.replace("-", "_"));
if cfg.target_arch == "aarch64" {
let cflags_key = String::from("CFLAGS_") + &(cfg.target_triple.replace("-", "_"));
if let Ok(cflags_value) = env::var(cflags_key) {
if cflags_value.contains("+nofp") || cflags_value.contains("+nosimd") {
consider_float_intrinsics = false;
@@ -256,22 +218,22 @@ pub fn compile(llvm_target: &[&str], target: &Target) {
// support `_Float16` on all targets (whereas Rust does). However, define the macro
// anyway to prevent issues like rust#118813 and rust#123885 silently reoccuring if more
// `f16` intrinsics get accidentally added here in the future.
cfg.define("COMPILER_RT_HAS_FLOAT16", None);
build.define("COMPILER_RT_HAS_FLOAT16", None);
cfg.warnings(false);
build.warnings(false);
if target.env == "msvc" {
if cfg.target_env == "msvc" {
// Don't pull in extra libraries on MSVC
cfg.flag("/Zl");
build.flag("/Zl");
// Emulate C99 and C++11's __func__ for MSVC prior to 2013 CTP
cfg.define("__func__", Some("__FUNCTION__"));
build.define("__func__", Some("__FUNCTION__"));
} else {
// Turn off various features of gcc and such, mostly copying
// compiler-rt's build system already
cfg.flag("-fno-builtin");
cfg.flag("-fvisibility=hidden");
cfg.flag("-ffreestanding");
build.flag("-fno-builtin");
build.flag("-fvisibility=hidden");
build.flag("-ffreestanding");
// Avoid the following warning appearing once **per file**:
// clang: warning: optimization flag '-fomit-frame-pointer' is not supported for target 'armv7' [-Wignored-optimization-argument]
//
@@ -280,17 +242,17 @@ pub fn compile(llvm_target: &[&str], target: &Target) {
// `check_cxx_compiler_flag(-fomit-frame-pointer COMPILER_RT_HAS_FOMIT_FRAME_POINTER_FLAG)`
//
// in https://github.com/rust-lang/compiler-rt/blob/c8fbcb3/cmake/config-ix.cmake#L19.
cfg.flag_if_supported("-fomit-frame-pointer");
cfg.define("VISIBILITY_HIDDEN", None);
build.flag_if_supported("-fomit-frame-pointer");
build.define("VISIBILITY_HIDDEN", None);
if let "aarch64" | "arm64ec" = target.arch.as_str() {
if let "aarch64" | "arm64ec" = cfg.target_arch.as_str() {
// FIXME(llvm20): Older GCCs on A64 fail to build with
// -Werror=implicit-function-declaration due to a compiler-rt bug.
// With a newer LLVM we should be able to enable the flag everywhere.
// https://github.com/llvm/llvm-project/commit/8aa9d6206ce55bdaaf422839c351fbd63f033b89
} else {
// Avoid implicitly creating references to undefined functions
cfg.flag("-Werror=implicit-function-declaration");
build.flag("-Werror=implicit-function-declaration");
}
}
@@ -299,14 +261,14 @@ pub fn compile(llvm_target: &[&str], target: &Target) {
// at odds with compiling with `-ffreestanding`, as the header
// may be incompatible or not present. Create a minimal stub
// header to use instead.
if target.os == "uefi" {
if cfg.target_os == "uefi" {
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
let include_dir = out_dir.join("include");
if !include_dir.exists() {
fs::create_dir(&include_dir).unwrap();
}
fs::write(include_dir.join("stdlib.h"), "#include <stddef.h>").unwrap();
cfg.flag(&format!("-I{}", include_dir.to_str().unwrap()));
build.flag(&format!("-I{}", include_dir.to_str().unwrap()));
}
let mut sources = Sources::new();
@@ -344,7 +306,7 @@ pub fn compile(llvm_target: &[&str], target: &Target) {
// On iOS and 32-bit OSX these are all just empty intrinsics, no need to
// include them.
if target.vendor != "apple" || target.arch != "x86" {
if cfg.target_vendor != "apple" || cfg.target_arch != "x86" {
sources.extend(&[
("__absvti2", "absvti2.c"),
("__addvti3", "addvti3.c"),
@@ -363,7 +325,7 @@ pub fn compile(llvm_target: &[&str], target: &Target) {
}
}
if target.vendor == "apple" {
if cfg.target_vendor == "apple" {
sources.extend(&[
("atomic_flag_clear", "atomic_flag_clear.c"),
("atomic_flag_clear_explicit", "atomic_flag_clear_explicit.c"),
@@ -377,8 +339,8 @@ pub fn compile(llvm_target: &[&str], target: &Target) {
]);
}
if target.env != "msvc" {
if target.arch == "x86" {
if cfg.target_env != "msvc" {
if cfg.target_arch == "x86" {
sources.extend(&[
("__ashldi3", "i386/ashldi3.S"),
("__ashrdi3", "i386/ashrdi3.S"),
@@ -392,7 +354,7 @@ pub fn compile(llvm_target: &[&str], target: &Target) {
}
}
if target.arch == "arm" && target.vendor != "apple" && target.env != "msvc" {
if cfg.target_arch == "arm" && cfg.target_vendor != "apple" && cfg.target_env != "msvc" {
sources.extend(&[
("__aeabi_div0", "arm/aeabi_div0.c"),
("__aeabi_drsub", "arm/aeabi_drsub.c"),
@@ -412,7 +374,7 @@ pub fn compile(llvm_target: &[&str], target: &Target) {
("__umodsi3", "arm/umodsi3.S"),
]);
if target.os == "freebsd" {
if cfg.target_os == "freebsd" {
sources.extend(&[("__clear_cache", "clear_cache.c")]);
}
@@ -484,31 +446,36 @@ pub fn compile(llvm_target: &[&str], target: &Target) {
]);
}
if (target.arch == "aarch64" || target.arch == "arm64ec") && consider_float_intrinsics {
if (cfg.target_arch == "aarch64" || cfg.target_arch == "arm64ec")
&& consider_float_intrinsics
{
sources.extend(&[
("__fe_getround", "fp_mode.c"),
("__fe_raise_inexact", "fp_mode.c"),
]);
if target.os != "windows" && target.os != "cygwin" {
if cfg.target_os != "windows" && cfg.target_os != "cygwin" {
sources.extend(&[("__multc3", "multc3.c")]);
}
}
if target.arch == "mips" || target.arch == "riscv32" || target.arch == "riscv64" {
if cfg.target_arch == "mips" || cfg.target_arch == "riscv32" || cfg.target_arch == "riscv64"
{
sources.extend(&[("__bswapsi2", "bswapsi2.c")]);
}
if target.arch == "mips64" {
if cfg.target_arch == "mips64" {
sources.extend(&[("__fe_getround", "fp_mode.c")]);
}
if target.arch == "loongarch64" {
if cfg.target_arch == "loongarch64" {
sources.extend(&[("__fe_getround", "fp_mode.c")]);
}
// Remove the assembly implementations that won't compile for the target
if llvm_target[0] == "thumbv6m" || llvm_target[0] == "thumbv8m.base" || target.os == "uefi"
if llvm_target[0] == "thumbv6m"
|| llvm_target[0] == "thumbv8m.base"
|| cfg.target_os == "uefi"
{
let mut to_remove = Vec::new();
for (k, v) in sources.map.iter() {
@@ -524,19 +491,19 @@ pub fn compile(llvm_target: &[&str], target: &Target) {
}
// Android and Cygwin uses emulated TLS so we need a runtime support function.
if target.os == "android" || target.os == "cygwin" {
if cfg.target_os == "android" || cfg.target_os == "cygwin" {
sources.extend(&[("__emutls_get_address", "emutls.c")]);
}
// Work around a bug in the NDK headers (fixed in
// https://r.android.com/2038949 which will be released in a future
// NDK version) by providing a definition of LONG_BIT.
if target.os == "android" {
cfg.define("LONG_BIT", "(8 * sizeof(long))");
if cfg.target_os == "android" {
build.define("LONG_BIT", "(8 * sizeof(long))");
}
// OpenHarmony also uses emulated TLS.
if target.env == "ohos" {
if cfg.target_env == "ohos" {
sources.extend(&[("__emutls_get_address", "emutls.c")]);
}
@@ -568,16 +535,16 @@ pub fn compile(llvm_target: &[&str], target: &Target) {
// Support deterministic builds by remapping the __FILE__ prefix if the
// compiler supports it. This fixes the nondeterminism caused by the
// use of that macro in lib/builtins/int_util.h in compiler-rt.
cfg.flag_if_supported(&format!("-ffile-prefix-map={}=.", root.display()));
build.flag_if_supported(&format!("-ffile-prefix-map={}=.", root.display()));
// Include out-of-line atomics for aarch64, which are all generated by supplying different
// sets of flags to the same source file.
// Note: Out-of-line aarch64 atomics are not supported by the msvc toolchain (#430) and
// on uefi.
let src_dir = root.join("lib/builtins");
if target.arch == "aarch64" && target.env != "msvc" && target.os != "uefi" {
if cfg.target_arch == "aarch64" && cfg.target_env != "msvc" && cfg.target_os != "uefi" {
// See below for why we're building these as separate libraries.
build_aarch64_out_of_line_atomics_libraries(&src_dir, cfg, link_against_prebuilt_rt);
build_aarch64_out_of_line_atomics_libraries(&src_dir, build, link_against_prebuilt_rt);
// Some run-time CPU feature detection is necessary, as well.
let cpu_model_src = if src_dir.join("cpu_model.c").exists() {
@@ -592,7 +559,7 @@ pub fn compile(llvm_target: &[&str], target: &Target) {
for (sym, src) in sources.map.iter() {
let src = src_dir.join(src);
if !link_against_prebuilt_rt && added_sources.insert(src.clone()) {
cfg.file(&src);
build.file(&src);
println!("cargo:rerun-if-changed={}", src.display());
}
println!("cargo:rustc-cfg={}=\"optimized-c\"", sym);
@@ -616,7 +583,7 @@ pub fn compile(llvm_target: &[&str], target: &Target) {
);
}
} else {
cfg.compile("libcompiler-rt.a");
build.compile("libcompiler-rt.a");
}
}
@@ -1,107 +0,0 @@
// Configuration that is shared between `compiler_builtins` and `builtins_test`.
use std::{env, str};
#[derive(Debug)]
#[allow(dead_code)]
pub struct Target {
pub triple: String,
pub triple_split: Vec<String>,
pub opt_level: String,
pub cargo_features: Vec<String>,
pub os: String,
pub arch: String,
pub vendor: String,
pub env: String,
pub pointer_width: u8,
pub little_endian: bool,
pub features: Vec<String>,
pub reliable_f128: bool,
pub reliable_f16: bool,
}
impl Target {
pub fn from_env() -> Self {
let triple = env::var("TARGET").unwrap();
let triple_split = triple.split('-').map(ToOwned::to_owned).collect();
let little_endian = match env::var("CARGO_CFG_TARGET_ENDIAN").unwrap().as_str() {
"little" => true,
"big" => false,
x => panic!("unknown endian {x}"),
};
let cargo_features = env::vars()
.filter_map(|(name, _value)| name.strip_prefix("CARGO_FEATURE_").map(ToOwned::to_owned))
.map(|s| s.to_lowercase().replace("_", "-"))
.collect();
Self {
triple,
triple_split,
os: env::var("CARGO_CFG_TARGET_OS").unwrap(),
opt_level: env::var("OPT_LEVEL").unwrap(),
cargo_features,
arch: env::var("CARGO_CFG_TARGET_ARCH").unwrap(),
vendor: env::var("CARGO_CFG_TARGET_VENDOR").unwrap(),
env: env::var("CARGO_CFG_TARGET_ENV").unwrap(),
pointer_width: env::var("CARGO_CFG_TARGET_POINTER_WIDTH")
.unwrap()
.parse()
.unwrap(),
little_endian,
features: env::var("CARGO_CFG_TARGET_FEATURE")
.unwrap_or_default()
.split(",")
.map(ToOwned::to_owned)
.collect(),
// Note that these are unstable options, so only show up with the nightly compiler or
// with `RUSTC_BOOTSTRAP=1` (which is required to use the types anyway).
reliable_f128: env::var_os("CARGO_CFG_TARGET_HAS_RELIABLE_F128").is_some(),
reliable_f16: env::var_os("CARGO_CFG_TARGET_HAS_RELIABLE_F16").is_some(),
}
}
#[allow(dead_code)]
pub fn has_feature(&self, feature: &str) -> bool {
self.features.iter().any(|f| f == feature)
}
}
pub fn configure_aliases(target: &Target) {
// To compile builtins-test-intrinsics for thumb targets, where there is no libc
println!("cargo::rustc-check-cfg=cfg(thumb)");
if target.triple_split[0].starts_with("thumb") {
println!("cargo:rustc-cfg=thumb")
}
// compiler-rt `cfg`s away some intrinsics for thumbv6m and thumbv8m.base because
// these targets do not have full Thumb-2 support but only original Thumb-1.
// We have to cfg our code accordingly.
println!("cargo::rustc-check-cfg=cfg(thumb_1)");
if target.triple_split[0] == "thumbv6m" || target.triple_split[0] == "thumbv8m.base" {
println!("cargo:rustc-cfg=thumb_1")
}
// Config shorthands
println!("cargo:rustc-check-cfg=cfg(x86_no_sse)");
if target.arch == "x86" && !target.features.iter().any(|f| f == "sse") {
// Shorthand to detect i586 targets
println!("cargo:rustc-cfg=x86_no_sse");
}
/* Not all backends support `f16` and `f128` to the same level on all architectures, so we
* need to disable things if the compiler may crash. See configuration at:
* * https://github.com/rust-lang/rust/blob/c65dccabacdfd6c8a7f7439eba13422fdd89b91e/compiler/rustc_codegen_llvm/src/llvm_util.rs#L367-L432
* * https://github.com/rust-lang/rustc_codegen_gcc/blob/4b5c44b14166083eef8d71f15f5ea1f53fc976a0/src/lib.rs#L496-L507
* * https://github.com/rust-lang/rustc_codegen_cranelift/blob/c713ffab3c6e28ab4b4dd4e392330f786ea657ad/src/lib.rs#L196-L226
*/
println!("cargo::rustc-check-cfg=cfg(f16_enabled)");
if target.reliable_f16 {
println!("cargo::rustc-cfg=f16_enabled");
}
println!("cargo::rustc-check-cfg=cfg(f128_enabled)");
if target.reliable_f128 {
println!("cargo::rustc-cfg=f128_enabled");
}
}
@@ -35,14 +35,14 @@ pub extern "C" fn __rust_enable_lse() {
}
/// Function to enable/disable LSE. To be used only for testing purposes.
#[cfg(feature = "mangled-names")]
#[cfg(feature = "unstable-public-internals")]
pub unsafe fn set_have_lse_atomics(has_lse: bool) {
let lse_flag = if has_lse { 1 } else { 0 };
HAVE_LSE_ATOMICS.store(lse_flag, Ordering::Relaxed);
}
/// Function to obtain whether LSE is enabled or not. To be used only for testing purposes.
#[cfg(feature = "mangled-names")]
#[cfg(feature = "unstable-public-internals")]
pub fn get_have_lse_atomics() -> bool {
HAVE_LSE_ATOMICS.load(Ordering::Relaxed) != 0
}
@@ -1,5 +1,4 @@
use crate::float::Float;
use crate::int::{CastFrom, CastInto, Int, MinInt};
use crate::support::{CastFrom, CastInto, Float, Int, MinInt};
/// Returns `a + b`
fn add<F: Float>(a: F, b: F) -> F
@@ -1,21 +1,28 @@
#![allow(unreachable_code)]
use crate::float::Float;
use crate::int::MinInt;
use crate::support::cfg_if;
use crate::support::{Float, MinInt, cfg_if};
// Taken from LLVM config:
// https://github.com/llvm/llvm-project/blob/0cf3c437c18ed27d9663d87804a9a15ff6874af2/compiler-rt/lib/builtins/fp_compare_impl.inc#L11-L27
// 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
// in GCC, there are a few things to grep for:
//
// * `default_libgcc_cmp_return_mode` for the default (word sized)
// * `TARGET_LIBGCC_CMP_RETURN_MODE` for the target hook to override the default
// * `# *define *CMPtype` as a last resort, for overrides that don't use the hook (AVR)
//
// [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"))] {
if #[cfg(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")] {
// AVR uses a single byte.
pub type CmpResult = i8;
} else {
// In compiler-rt, LLP64 ABIs use `long long` and everything else uses `long`. In effect,
// this means the return value is always pointer-sized.
// 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;
}
}
@@ -28,8 +35,18 @@ enum Result {
Unordered,
}
/// Conversions to match GCC intrinsics [1].
///
/// * `unord`: nonzero if either NaN, 0 otherwise
/// * `eq`, `ne`: 0 if a == b and both YaN, nonzero otherwise
/// * `ge`, `gt`, `lt`, `le`: return an int result that provides the same comparison to 0 if both
/// YaN and the comparison matches. E.g. if a >= b, `ge` returns an `x >= 0`.
///
/// The separate map functions are only needed to handle the unordered case.
///
/// [1]: https://gcc.gnu.org/onlinedocs/gccint/Soft-float-library-routines.html#Comparison-functions-1
impl Result {
fn to_le_abi(self) -> CmpResult {
fn to_default_cmp_result(self) -> CmpResult {
match self {
Result::Less => -1,
Result::Equal => 0,
@@ -38,7 +55,7 @@ fn to_le_abi(self) -> CmpResult {
}
}
fn to_ge_abi(self) -> CmpResult {
fn to_gt_ge_cmp_result(self) -> CmpResult {
match self {
Result::Less => -1,
Result::Equal => 0,
@@ -118,11 +135,11 @@ fn unord<F: Float>(a: F, b: F) -> bool {
#[cfg(f16_enabled)]
intrinsics! {
pub extern "C" fn __lehf2(a: f16, b: f16) -> crate::float::cmp::CmpResult {
cmp(a, b).to_le_abi()
cmp(a, b).to_default_cmp_result()
}
pub extern "C" fn __gehf2(a: f16, b: f16) -> crate::float::cmp::CmpResult {
cmp(a, b).to_ge_abi()
cmp(a, b).to_gt_ge_cmp_result()
}
pub extern "C" fn __unordhf2(a: f16, b: f16) -> crate::float::cmp::CmpResult {
@@ -130,29 +147,29 @@ pub extern "C" fn __unordhf2(a: f16, b: f16) -> crate::float::cmp::CmpResult {
}
pub extern "C" fn __eqhf2(a: f16, b: f16) -> crate::float::cmp::CmpResult {
cmp(a, b).to_le_abi()
cmp(a, b).to_default_cmp_result()
}
pub extern "C" fn __lthf2(a: f16, b: f16) -> crate::float::cmp::CmpResult {
cmp(a, b).to_le_abi()
cmp(a, b).to_default_cmp_result()
}
pub extern "C" fn __nehf2(a: f16, b: f16) -> crate::float::cmp::CmpResult {
cmp(a, b).to_le_abi()
cmp(a, b).to_default_cmp_result()
}
pub extern "C" fn __gthf2(a: f16, b: f16) -> crate::float::cmp::CmpResult {
cmp(a, b).to_ge_abi()
cmp(a, b).to_gt_ge_cmp_result()
}
}
intrinsics! {
pub extern "C" fn __lesf2(a: f32, b: f32) -> crate::float::cmp::CmpResult {
cmp(a, b).to_le_abi()
cmp(a, b).to_default_cmp_result()
}
pub extern "C" fn __gesf2(a: f32, b: f32) -> crate::float::cmp::CmpResult {
cmp(a, b).to_ge_abi()
cmp(a, b).to_gt_ge_cmp_result()
}
#[arm_aeabi_alias = __aeabi_fcmpun]
@@ -161,27 +178,27 @@ pub extern "C" fn __unordsf2(a: f32, b: f32) -> crate::float::cmp::CmpResult {
}
pub extern "C" fn __eqsf2(a: f32, b: f32) -> crate::float::cmp::CmpResult {
cmp(a, b).to_le_abi()
cmp(a, b).to_default_cmp_result()
}
pub extern "C" fn __ltsf2(a: f32, b: f32) -> crate::float::cmp::CmpResult {
cmp(a, b).to_le_abi()
cmp(a, b).to_default_cmp_result()
}
pub extern "C" fn __nesf2(a: f32, b: f32) -> crate::float::cmp::CmpResult {
cmp(a, b).to_le_abi()
cmp(a, b).to_default_cmp_result()
}
pub extern "C" fn __gtsf2(a: f32, b: f32) -> crate::float::cmp::CmpResult {
cmp(a, b).to_ge_abi()
cmp(a, b).to_gt_ge_cmp_result()
}
pub extern "C" fn __ledf2(a: f64, b: f64) -> crate::float::cmp::CmpResult {
cmp(a, b).to_le_abi()
cmp(a, b).to_default_cmp_result()
}
pub extern "C" fn __gedf2(a: f64, b: f64) -> crate::float::cmp::CmpResult {
cmp(a, b).to_ge_abi()
cmp(a, b).to_gt_ge_cmp_result()
}
#[arm_aeabi_alias = __aeabi_dcmpun]
@@ -190,19 +207,19 @@ pub extern "C" fn __unorddf2(a: f64, b: f64) -> crate::float::cmp::CmpResult {
}
pub extern "C" fn __eqdf2(a: f64, b: f64) -> crate::float::cmp::CmpResult {
cmp(a, b).to_le_abi()
cmp(a, b).to_default_cmp_result()
}
pub extern "C" fn __ltdf2(a: f64, b: f64) -> crate::float::cmp::CmpResult {
cmp(a, b).to_le_abi()
cmp(a, b).to_default_cmp_result()
}
pub extern "C" fn __nedf2(a: f64, b: f64) -> crate::float::cmp::CmpResult {
cmp(a, b).to_le_abi()
cmp(a, b).to_default_cmp_result()
}
pub extern "C" fn __gtdf2(a: f64, b: f64) -> crate::float::cmp::CmpResult {
cmp(a, b).to_ge_abi()
cmp(a, b).to_gt_ge_cmp_result()
}
}
@@ -210,12 +227,12 @@ pub extern "C" fn __gtdf2(a: f64, b: f64) -> crate::float::cmp::CmpResult {
intrinsics! {
#[ppc_alias = __lekf2]
pub extern "C" fn __letf2(a: f128, b: f128) -> crate::float::cmp::CmpResult {
cmp(a, b).to_le_abi()
cmp(a, b).to_default_cmp_result()
}
#[ppc_alias = __gekf2]
pub extern "C" fn __getf2(a: f128, b: f128) -> crate::float::cmp::CmpResult {
cmp(a, b).to_ge_abi()
cmp(a, b).to_gt_ge_cmp_result()
}
#[ppc_alias = __unordkf2]
@@ -225,22 +242,22 @@ pub extern "C" fn __unordtf2(a: f128, b: f128) -> crate::float::cmp::CmpResult {
#[ppc_alias = __eqkf2]
pub extern "C" fn __eqtf2(a: f128, b: f128) -> crate::float::cmp::CmpResult {
cmp(a, b).to_le_abi()
cmp(a, b).to_default_cmp_result()
}
#[ppc_alias = __ltkf2]
pub extern "C" fn __lttf2(a: f128, b: f128) -> crate::float::cmp::CmpResult {
cmp(a, b).to_le_abi()
cmp(a, b).to_default_cmp_result()
}
#[ppc_alias = __nekf2]
pub extern "C" fn __netf2(a: f128, b: f128) -> crate::float::cmp::CmpResult {
cmp(a, b).to_le_abi()
cmp(a, b).to_default_cmp_result()
}
#[ppc_alias = __gtkf2]
pub extern "C" fn __gttf2(a: f128, b: f128) -> crate::float::cmp::CmpResult {
cmp(a, b).to_ge_abi()
cmp(a, b).to_gt_ge_cmp_result()
}
}
@@ -1,7 +1,6 @@
use core::ops::Neg;
use super::Float;
use crate::int::{CastFrom, CastInto, Int, MinInt};
use crate::support::{CastFrom, CastInto, Float, Int, MinInt};
/// Conversions from integers to floats.
///
@@ -82,9 +82,7 @@
use core::mem::size_of;
use core::ops;
use super::HalfRep;
use crate::float::Float;
use crate::int::{CastFrom, CastInto, DInt, HInt, Int, MinInt};
use crate::support::{CastFrom, CastInto, DInt, Float, HInt, HalfRep, Int, MinInt};
fn div<F: Float>(a: F, b: F) -> F
where
@@ -1,5 +1,4 @@
use crate::float::Float;
use crate::int::{CastInto, Int, MinInt};
use crate::support::{CastInto, Float, Int, MinInt};
/// Generic conversion from a narrower to a wider IEEE-754 floating-point type
fn extend<F: Float, R: Float>(a: F) -> R
@@ -6,10 +6,4 @@
pub mod mul;
pub mod pow;
pub mod sub;
pub(crate) mod traits;
pub mod trunc;
#[cfg(not(feature = "unstable-public-internals"))]
pub(crate) use traits::{Float, HalfRep};
#[cfg(feature = "unstable-public-internals")]
pub use traits::{Float, HalfRep};
@@ -1,5 +1,4 @@
use crate::float::Float;
use crate::int::{CastInto, DInt, HInt, Int, MinInt};
use crate::support::{CastInto, DInt, Float, HInt, Int, MinInt};
fn mul<F: Float>(a: F, b: F) -> F
where
@@ -1,5 +1,4 @@
use crate::float::Float;
use crate::int::Int;
use crate::support::{Float, Int};
/// Returns `a` raised to the power `b`
fn pow<F: Float>(a: F, b: i32) -> F {
@@ -1,4 +1,4 @@
use crate::float::Float;
use crate::support::Float;
intrinsics! {
#[cfg(f16_enabled)]
@@ -1,189 +0,0 @@
use core::ops;
use crate::int::{DInt, Int, MinInt};
/// Wrapper to extract the integer type half of the float's size
pub type HalfRep<F> = <<F as Float>::Int as DInt>::H;
/// Trait for some basic operations on floats
#[allow(dead_code)]
pub trait Float:
Copy
+ core::fmt::Debug
+ PartialEq
+ PartialOrd
+ ops::AddAssign
+ ops::MulAssign
+ ops::Add<Output = Self>
+ ops::Sub<Output = Self>
+ ops::Div<Output = Self>
+ ops::Rem<Output = Self>
{
/// A uint of the same width as the float
type Int: Int<OtherSign = Self::SignedInt, Unsigned = Self::Int>;
/// A int of the same width as the float
type SignedInt: Int + MinInt<OtherSign = Self::Int, Unsigned = Self::Int>;
/// An int capable of containing the exponent bits plus a sign bit. This is signed.
type ExpInt: Int;
const ZERO: Self;
const ONE: Self;
/// The bitwidth of the float type.
const BITS: u32;
/// The bitwidth of the significand.
const SIG_BITS: u32;
/// The bitwidth of the exponent.
const EXP_BITS: u32 = Self::BITS - Self::SIG_BITS - 1;
/// The saturated (maximum bitpattern) value of the exponent, i.e. the infinite
/// representation.
///
/// This is in the rightmost position, use `EXP_MASK` for the shifted value.
const EXP_SAT: u32 = (1 << Self::EXP_BITS) - 1;
/// The exponent bias value.
const EXP_BIAS: u32 = Self::EXP_SAT >> 1;
/// A mask for the sign bit.
const SIGN_MASK: Self::Int;
/// A mask for the significand.
const SIG_MASK: Self::Int;
/// The implicit bit of the float format.
const IMPLICIT_BIT: Self::Int;
/// A mask for the exponent.
const EXP_MASK: Self::Int;
/// Returns `self` transmuted to `Self::Int`
fn to_bits(self) -> Self::Int;
/// Returns `self` transmuted to `Self::SignedInt`
fn to_bits_signed(self) -> Self::SignedInt;
/// Checks if two floats have the same bit representation. *Except* for NaNs! NaN can be
/// represented in multiple different ways. This method returns `true` if two NaNs are
/// compared.
fn eq_repr(self, rhs: Self) -> bool;
/// Returns true if the sign is negative
fn is_sign_negative(self) -> bool;
/// Returns the exponent, not adjusting for bias.
fn exp(self) -> Self::ExpInt;
/// Returns the significand with no implicit bit (or the "fractional" part)
fn frac(self) -> Self::Int;
/// Returns the significand with implicit bit
fn imp_frac(self) -> Self::Int;
/// Returns a `Self::Int` transmuted back to `Self`
fn from_bits(a: Self::Int) -> Self;
/// Constructs a `Self` from its parts. Inputs are treated as bits and shifted into position.
fn from_parts(negative: bool, exponent: Self::Int, significand: Self::Int) -> Self;
fn abs(self) -> Self {
let abs_mask = !Self::SIGN_MASK;
Self::from_bits(self.to_bits() & abs_mask)
}
/// Returns (normalized exponent, normalized significand)
fn normalize(significand: Self::Int) -> (i32, Self::Int);
/// Returns if `self` is subnormal
fn is_subnormal(self) -> bool;
}
macro_rules! float_impl {
($ty:ident, $ity:ident, $sity:ident, $expty:ident, $bits:expr, $significand_bits:expr) => {
impl Float for $ty {
type Int = $ity;
type SignedInt = $sity;
type ExpInt = $expty;
const ZERO: Self = 0.0;
const ONE: Self = 1.0;
const BITS: u32 = $bits;
const SIG_BITS: u32 = $significand_bits;
const SIGN_MASK: Self::Int = 1 << (Self::BITS - 1);
const SIG_MASK: Self::Int = (1 << Self::SIG_BITS) - 1;
const IMPLICIT_BIT: Self::Int = 1 << Self::SIG_BITS;
const EXP_MASK: Self::Int = !(Self::SIGN_MASK | Self::SIG_MASK);
fn to_bits(self) -> Self::Int {
self.to_bits()
}
fn to_bits_signed(self) -> Self::SignedInt {
self.to_bits() as Self::SignedInt
}
fn eq_repr(self, rhs: Self) -> bool {
#[cfg(feature = "mangled-names")]
fn is_nan(x: $ty) -> bool {
// When using mangled-names, the "real" compiler-builtins might not have the
// necessary builtin (__unordtf2) to test whether `f128` is NaN.
// FIXME(f16_f128): Remove once the nightly toolchain has the __unordtf2 builtin
// x is NaN if all the bits of the exponent are set and the significand is non-0
x.to_bits() & $ty::EXP_MASK == $ty::EXP_MASK && x.to_bits() & $ty::SIG_MASK != 0
}
#[cfg(not(feature = "mangled-names"))]
fn is_nan(x: $ty) -> bool {
x.is_nan()
}
if is_nan(self) && is_nan(rhs) {
true
} else {
self.to_bits() == rhs.to_bits()
}
}
fn is_sign_negative(self) -> bool {
self.is_sign_negative()
}
fn exp(self) -> Self::ExpInt {
((self.to_bits() & Self::EXP_MASK) >> Self::SIG_BITS) as Self::ExpInt
}
fn frac(self) -> Self::Int {
self.to_bits() & Self::SIG_MASK
}
fn imp_frac(self) -> Self::Int {
self.frac() | Self::IMPLICIT_BIT
}
fn from_bits(a: Self::Int) -> Self {
Self::from_bits(a)
}
fn from_parts(negative: bool, exponent: Self::Int, significand: Self::Int) -> Self {
Self::from_bits(
((negative as Self::Int) << (Self::BITS - 1))
| ((exponent << Self::SIG_BITS) & Self::EXP_MASK)
| (significand & Self::SIG_MASK),
)
}
fn normalize(significand: Self::Int) -> (i32, Self::Int) {
let shift = significand.leading_zeros().wrapping_sub(Self::EXP_BITS);
(
1i32.wrapping_sub(shift as i32),
significand << shift as Self::Int,
)
}
fn is_subnormal(self) -> bool {
(self.to_bits() & Self::EXP_MASK) == Self::Int::ZERO
}
}
};
}
#[cfg(f16_enabled)]
float_impl!(f16, u16, i16, i8, 16, 10);
float_impl!(f32, u32, i32, i16, 32, 23);
float_impl!(f64, u64, i64, i16, 64, 52);
#[cfg(f128_enabled)]
float_impl!(f128, u128, i128, i16, 128, 112);
@@ -1,5 +1,4 @@
use crate::float::Float;
use crate::int::{CastInto, Int, MinInt};
use crate::support::{CastInto, Float, Int, MinInt};
fn trunc<F: Float, R: Float>(a: F) -> R
where
@@ -1,7 +1,66 @@
use core::arch::global_asm;
// Hexagon L1 cache line size in bytes (Hexagon PRM sections 5.10.3-5.10.4).
const CACHE_LINE_SIZE: usize = 32;
intrinsics! {
pub unsafe extern "C" fn __clear_cache(start: *mut u8, end: *mut u8) {
// Hexagon has separate instruction and data caches.
let mask = !(CACHE_LINE_SIZE - 1);
let start_line = start.addr() & mask;
let end_addr = end.addr();
// Clean and invalidate data cache to push new code to memory and
// invalidate stale lines in the L2 cache.
let mut addr = start_line;
while addr < end_addr {
unsafe {
core::arch::asm!(
"dccleaninva({addr})",
addr = in(reg) addr,
options(nostack, preserves_flags),
);
}
addr += CACHE_LINE_SIZE;
}
// Invalidate instruction cache so it re-fetches from memory.
addr = start_line;
while addr < end_addr {
unsafe {
core::arch::asm!(
"icinva({addr})",
addr = in(reg) addr,
options(nostack, preserves_flags),
);
}
addr += CACHE_LINE_SIZE;
}
// Instruction sync barrier ensures subsequent fetches see the new code.
unsafe {
core::arch::asm!("isync", options(nostack, preserves_flags));
}
}
}
global_asm!(include_str!("hexagon/func_macro.s"), options(raw));
global_asm!(
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));
@@ -0,0 +1,42 @@
FUNCTION_BEGIN __save_r24_through_r27
memd(fp+#-16) = r27:26
FALLTHROUGH_TAIL_CALL __save_r24_through_r27 __save_r24_through_r25
{
memd(fp+#-8) = r25:24
jumpr lr
}
FUNCTION_END __save_r24_through_r25
FUNCTION_BEGIN __restore_r24_through_r27_and_deallocframe_before_tailcall
r27:26 = memd(fp+#-16)
FALLTHROUGH_TAIL_CALL __restore_r24_through_r27_and_deallocframe_before_tailcall __restore_r24_through_r25_and_deallocframe_before_tailcall
{
r25:24 = memd(fp+#-8)
deallocframe
jumpr lr
}
FUNCTION_END __restore_r24_through_r25_and_deallocframe_before_tailcall
FUNCTION_BEGIN __restore_r24_through_r27_and_deallocframe
{
lr = memw(fp+#4)
r27:26 = memd(fp+#-16)
}
{
r25:24 = memd(fp+#-8)
deallocframe
jumpr lr
}
FUNCTION_END __restore_r24_through_r27_and_deallocframe
FUNCTION_BEGIN __restore_r24_through_r25_and_deallocframe
{
r25:24 = memd(fp+#-8)
deallocframe
}
jumpr lr
FUNCTION_END __restore_r24_through_r25_and_deallocframe
@@ -0,0 +1,237 @@
.macro ABI2_FUNCTION_BEGIN name
.p2align 2
.section .text.\name,"ax",@progbits
.globl \name
.type \name, @function
\name:
.endm
.macro ABI2_FUNCTION_END name
.size \name, . - \name
.endm
ABI2_FUNCTION_BEGIN __save_r16_through_r27
{
memd(fp+#-48) = r27:26
memd(fp+#-40) = r25:24
}
{
memd(fp+#-32) = r23:22
memd(fp+#-24) = r21:20
}
{
memd(fp+#-16) = r19:18
memd(fp+#-8) = r17:16
jumpr lr
}
ABI2_FUNCTION_END __save_r16_through_r27
ABI2_FUNCTION_BEGIN __save_r16_through_r25
{
memd(fp+#-40) = r25:24
memd(fp+#-32) = r23:22
}
{
memd(fp+#-24) = r21:20
memd(fp+#-16) = r19:18
}
{
memd(fp+#-8) = r17:16
jumpr lr
}
ABI2_FUNCTION_END __save_r16_through_r25
ABI2_FUNCTION_BEGIN __save_r16_through_r23
{
memd(fp+#-32) = r23:22
memd(fp+#-24) = r21:20
}
{
memd(fp+#-16) = r19:18
memd(fp+#-8) = r17:16
jumpr lr
}
ABI2_FUNCTION_END __save_r16_through_r23
ABI2_FUNCTION_BEGIN __save_r16_through_r21
{
memd(fp+#-24) = r21:20
memd(fp+#-16) = r19:18
}
{
memd(fp+#-8) = r17:16
jumpr lr
}
ABI2_FUNCTION_END __save_r16_through_r21
ABI2_FUNCTION_BEGIN __save_r16_through_r19
{
memd(fp+#-16) = r19:18
memd(fp+#-8) = r17:16
jumpr lr
}
ABI2_FUNCTION_END __save_r16_through_r19
ABI2_FUNCTION_BEGIN __save_r16_through_r17
{
memd(fp+#-8) = r17:16
jumpr lr
}
ABI2_FUNCTION_END __save_r16_through_r17
ABI2_FUNCTION_BEGIN __restore_r16_through_r27_and_deallocframe_before_tailcall
r27:26 = memd(fp+#-48)
{
r25:24 = memd(fp+#-40)
r23:22 = memd(fp+#-32)
}
{
r21:20 = memd(fp+#-24)
r19:18 = memd(fp+#-16)
}
{
r17:16 = memd(fp+#-8)
deallocframe
jumpr lr
}
ABI2_FUNCTION_END __restore_r16_through_r27_and_deallocframe_before_tailcall
ABI2_FUNCTION_BEGIN __restore_r16_through_r25_and_deallocframe_before_tailcall
{
r25:24 = memd(fp+#-40)
r23:22 = memd(fp+#-32)
}
{
r21:20 = memd(fp+#-24)
r19:18 = memd(fp+#-16)
}
{
r17:16 = memd(fp+#-8)
deallocframe
jumpr lr
}
ABI2_FUNCTION_END __restore_r16_through_r25_and_deallocframe_before_tailcall
ABI2_FUNCTION_BEGIN __restore_r16_through_r23_and_deallocframe_before_tailcall
{
r23:22 = memd(fp+#-32)
r21:20 = memd(fp+#-24)
}
r19:18 = memd(fp+#-16)
{
r17:16 = memd(fp+#-8)
deallocframe
jumpr lr
}
ABI2_FUNCTION_END __restore_r16_through_r23_and_deallocframe_before_tailcall
ABI2_FUNCTION_BEGIN __restore_r16_through_r21_and_deallocframe_before_tailcall
{
r21:20 = memd(fp+#-24)
r19:18 = memd(fp+#-16)
}
{
r17:16 = memd(fp+#-8)
deallocframe
jumpr lr
}
ABI2_FUNCTION_END __restore_r16_through_r21_and_deallocframe_before_tailcall
ABI2_FUNCTION_BEGIN __restore_r16_through_r19_and_deallocframe_before_tailcall
r19:18 = memd(fp+#-16)
{
r17:16 = memd(fp+#-8)
deallocframe
jumpr lr
}
ABI2_FUNCTION_END __restore_r16_through_r19_and_deallocframe_before_tailcall
ABI2_FUNCTION_BEGIN __restore_r16_through_r17_and_deallocframe_before_tailcall
{
r17:16 = memd(fp+#-8)
deallocframe
jumpr lr
}
ABI2_FUNCTION_END __restore_r16_through_r17_and_deallocframe_before_tailcall
ABI2_FUNCTION_BEGIN __restore_r16_through_r27_and_deallocframe
r27:26 = memd(fp+#-48)
{
r25:24 = memd(fp+#-40)
r23:22 = memd(fp+#-32)
}
{
r21:20 = memd(fp+#-24)
r19:18 = memd(fp+#-16)
}
{
r17:16 = memd(fp+#-8)
dealloc_return
}
ABI2_FUNCTION_END __restore_r16_through_r27_and_deallocframe
ABI2_FUNCTION_BEGIN __restore_r16_through_r25_and_deallocframe
{
r25:24 = memd(fp+#-40)
r23:22 = memd(fp+#-32)
}
{
r21:20 = memd(fp+#-24)
r19:18 = memd(fp+#-16)
}
{
r17:16 = memd(fp+#-8)
dealloc_return
}
ABI2_FUNCTION_END __restore_r16_through_r25_and_deallocframe
ABI2_FUNCTION_BEGIN __restore_r16_through_r23_and_deallocframe
{
r23:22 = memd(fp+#-32)
}
{
r21:20 = memd(fp+#-24)
r19:18 = memd(fp+#-16)
}
{
r17:16 = memd(fp+#-8)
dealloc_return
}
ABI2_FUNCTION_END __restore_r16_through_r23_and_deallocframe
ABI2_FUNCTION_BEGIN __restore_r16_through_r21_and_deallocframe
{
r21:20 = memd(fp+#-24)
r19:18 = memd(fp+#-16)
}
{
r17:16 = memd(fp+#-8)
dealloc_return
}
ABI2_FUNCTION_END __restore_r16_through_r21_and_deallocframe
ABI2_FUNCTION_BEGIN __restore_r16_through_r19_and_deallocframe
{
r19:18 = memd(fp+#-16)
r17:16 = memd(fp+#-8)
}
{
dealloc_return
}
ABI2_FUNCTION_END __restore_r16_through_r19_and_deallocframe
ABI2_FUNCTION_BEGIN __restore_r16_through_r17_and_deallocframe
{
r17:16 = memd(fp+#-8)
dealloc_return
}
ABI2_FUNCTION_END __restore_r16_through_r17_and_deallocframe
ABI2_FUNCTION_BEGIN __deallocframe
dealloc_return
ABI2_FUNCTION_END __deallocframe
@@ -0,0 +1,92 @@
FUNCTION_BEGIN __save_r27_through_r16
memd(fp+#-48) = r17:16
FALLTHROUGH_TAIL_CALL __save_r27_through_r16 __save_r27_through_r18
memd(fp+#-40) = r19:18
FALLTHROUGH_TAIL_CALL __save_r27_through_r18 __save_r27_through_r20
memd(fp+#-32) = r21:20
FALLTHROUGH_TAIL_CALL __save_r27_through_r20 __save_r27_through_r22
memd(fp+#-24) = r23:22
FALLTHROUGH_TAIL_CALL __save_r27_through_r22 __save_r27_through_r24
memd(fp+#-16) = r25:24
{
memd(fp+#-8) = r27:26
jumpr lr
}
FUNCTION_END __save_r27_through_r24
FUNCTION_BEGIN __restore_r27_through_r20_and_deallocframe_before_sibcall
{
r21:20 = memd(fp+#-32)
r23:22 = memd(fp+#-24)
}
FALLTHROUGH_TAIL_CALL __restore_r27_through_r20_and_deallocframe_before_sibcall __restore_r27_through_r24_and_deallocframe_before_sibcall
{
r25:24 = memd(fp+#-16)
jump __restore_r27_through_r26_and_deallocframe_before_sibcall
}
FUNCTION_END __restore_r27_through_r24_and_deallocframe_before_sibcall
FUNCTION_BEGIN __restore_r27_through_r16_and_deallocframe_before_sibcall
r17:16 = memd(fp+#-48)
FALLTHROUGH_TAIL_CALL __restore_r27_through_r16_and_deallocframe_before_sibcall __restore_r27_through_r18_and_deallocframe_before_sibcall
{
r19:18 = memd(fp+#-40)
r21:20 = memd(fp+#-32)
}
FALLTHROUGH_TAIL_CALL __restore_r27_through_r18_and_deallocframe_before_sibcall __restore_r27_through_r22_and_deallocframe_before_sibcall
{
r23:22 = memd(fp+#-24)
r25:24 = memd(fp+#-16)
}
FALLTHROUGH_TAIL_CALL __restore_r27_through_r22_and_deallocframe_before_sibcall __restore_r27_through_r26_and_deallocframe_before_sibcall
{
r27:26 = memd(fp+#-8)
deallocframe
jumpr lr
}
FUNCTION_END __restore_r27_through_r26_and_deallocframe_before_sibcall
FUNCTION_BEGIN __restore_r27_through_r16_and_deallocframe
{
r17:16 = memd(fp+#-48)
r19:18 = memd(fp+#-40)
}
FALLTHROUGH_TAIL_CALL __restore_r27_through_r16_and_deallocframe __restore_r27_through_r20_and_deallocframe
{
r21:20 = memd(fp+#-32)
r23:22 = memd(fp+#-24)
}
FALLTHROUGH_TAIL_CALL __restore_r27_through_r20_and_deallocframe __restore_r27_through_r24_and_deallocframe
{
lr = memw(fp+#4)
r25:24 = memd(fp+#-16)
}
{
r27:26 = memd(fp+#-8)
deallocframe
jumpr lr
}
FUNCTION_END __restore_r27_through_r24_and_deallocframe
FUNCTION_BEGIN __restore_r27_through_r18_and_deallocframe
{
r19:18 = memd(fp+#-40)
r21:20 = memd(fp+#-32)
}
FALLTHROUGH_TAIL_CALL __restore_r27_through_r18_and_deallocframe __restore_r27_through_r22_and_deallocframe
{
r23:22 = memd(fp+#-24)
r25:24 = memd(fp+#-16)
}
FALLTHROUGH_TAIL_CALL __restore_r27_through_r22_and_deallocframe __restore_r27_through_r26_and_deallocframe
{
r27:26 = memd(fp+#-8)
deallocframe
}
jumpr lr
FUNCTION_END __restore_r27_through_r26_and_deallocframe
@@ -10,3 +10,11 @@
.size \name, . - \name
.endm
.macro FALLTHROUGH_TAIL_CALL name0 name1
.size \name0, . - \name0
.globl \name1
.type \name1, @function
.falign
\name1:
.endm
@@ -31,6 +31,35 @@ FUNCTION_BEGIN __hexagon_memcpy_likely_aligned_min32bytes_mult8bytes
}
FUNCTION_END __hexagon_memcpy_likely_aligned_min32bytes_mult8bytes
FUNCTION_BEGIN __hexagon_memcpy_dwloop
{
r5:4 = memd(r1)
r3 = #-3
}
{
memd(r0++#8) = r5:4
r5:4 = memd(r1+#8)
r3 += lsr(r2,#3)
}
{
memd(r0++#8) = r5:4
r5:4 = memd(r1+#16)
r1 = add(r1,#24)
loop0(1f,r3)
}
.falign
1:
{
memd(r0++#8) = r5:4
r5:4 = memd(r1++#8)
}:endloop0
{
memd(r0) = r5:4
r0 -= add(r2,#-8)
jumpr r31
}
FUNCTION_END __hexagon_memcpy_dwloop
.Lmemcpy_call:
jump memcpy@PLT
@@ -1,4 +1,4 @@
use crate::int::{DInt, Int, MinInt};
use crate::support::{DInt, Int, MinInt};
trait UAddSub: DInt + Int {
fn uadd(self, other: Self) -> Self {
@@ -1,295 +0,0 @@
//! Integers used for wide operations, larger than `u128`.
#![allow(unused)]
use core::{fmt, ops};
use crate::int::{DInt, HInt, Int, MinInt};
const WORD_LO_MASK: u64 = 0x00000000ffffffff;
const WORD_HI_MASK: u64 = 0xffffffff00000000;
const WORD_FULL_MASK: u64 = 0xffffffffffffffff;
const U128_LO_MASK: u128 = u64::MAX as u128;
const U128_HI_MASK: u128 = (u64::MAX as u128) << 64;
/// A 256-bit unsigned integer represented as 4 64-bit limbs.
///
/// Each limb is a native-endian number, but the array is little-limb-endian.
#[allow(non_camel_case_types)]
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
pub struct u256(pub [u64; 4]);
impl u256 {
pub const MAX: Self = Self([u64::MAX, u64::MAX, u64::MAX, u64::MAX]);
/// Reinterpret as a signed integer
pub fn signed(self) -> i256 {
i256(self.0)
}
}
/// A 256-bit signed integer represented as 4 64-bit limbs.
///
/// Each limb is a native-endian number, but the array is little-limb-endian.
#[allow(non_camel_case_types)]
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
pub struct i256(pub [u64; 4]);
impl i256 {
/// Reinterpret as an unsigned integer
pub fn unsigned(self) -> u256 {
u256(self.0)
}
}
impl MinInt for u256 {
type OtherSign = i256;
type Unsigned = u256;
const SIGNED: bool = false;
const BITS: u32 = 256;
const ZERO: Self = Self([0u64; 4]);
const ONE: Self = Self([1, 0, 0, 0]);
const MIN: Self = Self([0u64; 4]);
const MAX: Self = Self([u64::MAX; 4]);
}
impl MinInt for i256 {
type OtherSign = u256;
type Unsigned = u256;
const SIGNED: bool = false;
const BITS: u32 = 256;
const ZERO: Self = Self([0u64; 4]);
const ONE: Self = Self([1, 0, 0, 0]);
const MIN: Self = Self([0, 0, 0, 1 << 63]);
const MAX: Self = Self([u64::MAX, u64::MAX, u64::MAX, u64::MAX >> 1]);
}
macro_rules! impl_common {
($ty:ty) => {
impl ops::BitOr for $ty {
type Output = Self;
fn bitor(mut self, rhs: Self) -> Self::Output {
self.0[0] |= rhs.0[0];
self.0[1] |= rhs.0[1];
self.0[2] |= rhs.0[2];
self.0[3] |= rhs.0[3];
self
}
}
impl ops::Not for $ty {
type Output = Self;
fn not(self) -> Self::Output {
Self([!self.0[0], !self.0[1], !self.0[2], !self.0[3]])
}
}
impl ops::Shl<u32> for $ty {
type Output = Self;
fn shl(self, rhs: u32) -> Self::Output {
unimplemented!("only used to meet trait bounds")
}
}
};
}
impl_common!(i256);
impl_common!(u256);
impl ops::Shr<u32> for u256 {
type Output = Self;
fn shr(self, rhs: u32) -> Self::Output {
assert!(rhs < Self::BITS, "attempted to shift right with overflow");
if rhs == 0 {
return self;
}
let mut ret = self;
let byte_shift = rhs / 64;
let bit_shift = rhs % 64;
for idx in 0..4 {
let base_idx = idx + byte_shift as usize;
let Some(base) = ret.0.get(base_idx) else {
ret.0[idx] = 0;
continue;
};
let mut new_val = base >> bit_shift;
if let Some(new) = ret.0.get(base_idx + 1) {
new_val |= new.overflowing_shl(64 - bit_shift).0;
}
ret.0[idx] = new_val;
}
ret
}
}
macro_rules! word {
(1, $val:expr) => {
(($val >> (32 * 3)) & Self::from(WORD_LO_MASK)) as u64
};
(2, $val:expr) => {
(($val >> (32 * 2)) & Self::from(WORD_LO_MASK)) as u64
};
(3, $val:expr) => {
(($val >> (32 * 1)) & Self::from(WORD_LO_MASK)) as u64
};
(4, $val:expr) => {
(($val >> (32 * 0)) & Self::from(WORD_LO_MASK)) as u64
};
}
impl HInt for u128 {
type D = u256;
fn widen(self) -> Self::D {
let w0 = self & u128::from(u64::MAX);
let w1 = (self >> u64::BITS) & u128::from(u64::MAX);
u256([w0 as u64, w1 as u64, 0, 0])
}
fn zero_widen(self) -> Self::D {
self.widen()
}
fn zero_widen_mul(self, rhs: Self) -> Self::D {
let product11: u64 = word!(1, self) * word!(1, rhs);
let product12: u64 = word!(1, self) * word!(2, rhs);
let product13: u64 = word!(1, self) * word!(3, rhs);
let product14: u64 = word!(1, self) * word!(4, rhs);
let product21: u64 = word!(2, self) * word!(1, rhs);
let product22: u64 = word!(2, self) * word!(2, rhs);
let product23: u64 = word!(2, self) * word!(3, rhs);
let product24: u64 = word!(2, self) * word!(4, rhs);
let product31: u64 = word!(3, self) * word!(1, rhs);
let product32: u64 = word!(3, self) * word!(2, rhs);
let product33: u64 = word!(3, self) * word!(3, rhs);
let product34: u64 = word!(3, self) * word!(4, rhs);
let product41: u64 = word!(4, self) * word!(1, rhs);
let product42: u64 = word!(4, self) * word!(2, rhs);
let product43: u64 = word!(4, self) * word!(3, rhs);
let product44: u64 = word!(4, self) * word!(4, rhs);
let sum0: u128 = u128::from(product44);
let sum1: u128 = u128::from(product34) + u128::from(product43);
let sum2: u128 = u128::from(product24) + u128::from(product33) + u128::from(product42);
let sum3: u128 = u128::from(product14)
+ u128::from(product23)
+ u128::from(product32)
+ u128::from(product41);
let sum4: u128 = u128::from(product13) + u128::from(product22) + u128::from(product31);
let sum5: u128 = u128::from(product12) + u128::from(product21);
let sum6: u128 = u128::from(product11);
let r0: u128 =
(sum0 & u128::from(WORD_FULL_MASK)) + ((sum1 & u128::from(WORD_LO_MASK)) << 32);
let r1: u128 = (sum0 >> 64)
+ ((sum1 >> 32) & u128::from(WORD_FULL_MASK))
+ (sum2 & u128::from(WORD_FULL_MASK))
+ ((sum3 << 32) & u128::from(WORD_HI_MASK));
let (lo, carry) = r0.overflowing_add(r1 << 64);
let hi = (r1 >> 64)
+ (sum1 >> 96)
+ (sum2 >> 64)
+ (sum3 >> 32)
+ sum4
+ (sum5 << 32)
+ (sum6 << 64)
+ u128::from(carry);
u256([
(lo & U128_LO_MASK) as u64,
((lo >> 64) & U128_LO_MASK) as u64,
(hi & U128_LO_MASK) as u64,
((hi >> 64) & U128_LO_MASK) as u64,
])
}
fn widen_mul(self, rhs: Self) -> Self::D {
self.zero_widen_mul(rhs)
}
fn widen_hi(self) -> Self::D {
self.widen() << <Self as MinInt>::BITS
}
}
impl HInt for i128 {
type D = i256;
fn widen(self) -> Self::D {
let mut ret = self.unsigned().zero_widen().signed();
if self.is_negative() {
ret.0[2] = u64::MAX;
ret.0[3] = u64::MAX;
}
ret
}
fn zero_widen(self) -> Self::D {
self.unsigned().zero_widen().signed()
}
fn zero_widen_mul(self, rhs: Self) -> Self::D {
self.unsigned().zero_widen_mul(rhs.unsigned()).signed()
}
fn widen_mul(self, rhs: Self) -> Self::D {
unimplemented!("signed i128 widening multiply is not used")
}
fn widen_hi(self) -> Self::D {
self.widen() << <Self as MinInt>::BITS
}
}
impl DInt for u256 {
type H = u128;
fn lo(self) -> Self::H {
let mut tmp = [0u8; 16];
tmp[..8].copy_from_slice(&self.0[0].to_le_bytes());
tmp[8..].copy_from_slice(&self.0[1].to_le_bytes());
u128::from_le_bytes(tmp)
}
fn hi(self) -> Self::H {
let mut tmp = [0u8; 16];
tmp[..8].copy_from_slice(&self.0[2].to_le_bytes());
tmp[8..].copy_from_slice(&self.0[3].to_le_bytes());
u128::from_le_bytes(tmp)
}
}
impl DInt for i256 {
type H = i128;
fn lo(self) -> Self::H {
let mut tmp = [0u8; 16];
tmp[..8].copy_from_slice(&self.0[0].to_le_bytes());
tmp[8..].copy_from_slice(&self.0[1].to_le_bytes());
i128::from_le_bytes(tmp)
}
fn hi(self) -> Self::H {
let mut tmp = [0u8; 16];
tmp[..8].copy_from_slice(&self.0[2].to_le_bytes());
tmp[8..].copy_from_slice(&self.0[3].to_le_bytes());
i128::from_le_bytes(tmp)
}
}
@@ -9,7 +9,7 @@
pub(crate) use implementation::{leading_zeros_default, leading_zeros_riscv};
mod implementation {
use crate::int::{CastFrom, Int};
use crate::support::{CastFrom, Int};
/// Returns the number of leading binary zeros in `x`.
#[allow(dead_code)]
@@ -1,18 +1,10 @@
mod specialized_div_rem;
pub mod addsub;
mod big;
pub mod bswap;
pub mod leading_zeros;
pub mod mul;
pub mod sdiv;
pub mod shift;
pub mod trailing_zeros;
mod traits;
pub mod udiv;
pub use big::{i256, u256};
#[cfg(not(feature = "unstable-public-internals"))]
pub(crate) use traits::{CastFrom, CastInto, DInt, HInt, Int, MinInt};
#[cfg(feature = "unstable-public-internals")]
pub use traits::{CastFrom, CastInto, DInt, HInt, Int, MinInt};
@@ -1,4 +1,4 @@
use crate::int::{DInt, HInt, Int};
use crate::support::{DInt, HInt, Int};
trait Mul: DInt + Int
where
@@ -98,11 +98,63 @@ fn $fn(lhs: $iD, rhs: $iD) -> ($iD, bool) {
impl_signed_mulo!(i128_overflowing_mul, i128, u128);
intrinsics! {
// Ancient Egyptian/Ethiopian/Russian multiplication method
// see https://en.wikipedia.org/wiki/Ancient_Egyptian_multiplication
//
// This is a long-available stock algorithm; e.g. it is documented in
// Knuth's "The Art of Computer Programming" volume 2 (under the section
// "Evaluation of Powers") since at least the 2nd edition (1981).
//
// The main attraction of this method is that it implements (software)
// multiplication atop four simple operations: doubling, halving, checking
// if a value is even/odd, and addition. This is *not* considered to be the
// fastest multiplication method, but it may be amongst the simplest (and
// smallest with respect to code size).
//
// for reference, see also implementation from gcc
// https://raw.githubusercontent.com/gcc-mirror/gcc/master/libgcc/config/epiphany/mulsi3.c
//
// and from LLVM (in relatively readable RISC-V assembly):
// https://github.com/llvm/llvm-project/blob/main/compiler-rt/lib/builtins/riscv/int_mul_impl.inc
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64", target_arch = "m68k"))]
pub extern "C" fn __mulsi3(a: u32, b: u32) -> u32 {
let (mut a, mut b) = (a, b);
let mut r: u32 = 0;
while a > 0 {
if a & 1 > 0 {
r = r.wrapping_add(b);
}
a >>= 1;
b <<= 1;
}
r
}
#[maybe_use_optimized_c_shim]
#[arm_aeabi_alias = __aeabi_lmul]
#[cfg(any(not(any(target_arch = "riscv32", target_arch = "riscv64")), target_feature = "m"))]
pub extern "C" fn __muldi3(a: u64, b: u64) -> u64 {
a.mul(b)
#[cfg(all(any(target_arch = "riscv32", target_arch = "riscv64"), not(target_feature = "m")))]
{
let (mut a, mut b) = (a, b);
let mut r: u64 = 0;
while a > 0 {
if a & 1 > 0 {
r = r.wrapping_add(b);
}
a >>= 1;
b <<= 1;
}
r
}
#[cfg(not(all(any(target_arch = "riscv32", target_arch = "riscv64"), not(target_feature = "m"))))]
{
a.mul(b)
}
}
pub extern "C" fn __multi3(a: i128, b: i128) -> i128 {
@@ -139,4 +191,5 @@ pub extern "C" fn __rust_u128_mulo(a: u128, b: u128, oflow: &mut i32) -> u128 {
*oflow = o.into();
mul
}
}
@@ -1,4 +1,4 @@
use crate::int::{DInt, HInt, Int, MinInt};
use crate::support::{DInt, HInt, Int, MinInt};
trait Ashl: DInt {
/// Returns `a << b`, requires `b < Self::BITS`
@@ -144,7 +144,7 @@ fn u64_by_u64_div_rem(duo: u64, div: u64) -> (u64, u64) {
target_family = "wasm",
not(any(target_pointer_width = "16", target_pointer_width = "32")),
),
not(all(not(feature = "no-asm"), target_arch = "x86_64")),
not(all(feature = "arch", target_arch = "x86_64")),
not(any(target_arch = "sparc", target_arch = "sparc64"))
))]
impl_trifecta!(
@@ -165,7 +165,7 @@ fn u64_by_u64_div_rem(duo: u64, div: u64) -> (u64, u64) {
target_family = "wasm",
not(any(target_pointer_width = "16", target_pointer_width = "32")),
)),
not(all(not(feature = "no-asm"), target_arch = "x86_64")),
not(all(feature = "arch", target_arch = "x86_64")),
not(any(target_arch = "sparc", target_arch = "sparc64"))
))]
impl_delegate!(
@@ -186,7 +186,7 @@ fn u64_by_u64_div_rem(duo: u64, div: u64) -> (u64, u64) {
///
/// If the quotient does not fit in a `u64`, a floating point exception occurs.
/// If `div == 0`, then a division by zero exception occurs.
#[cfg(all(not(feature = "no-asm"), target_arch = "x86_64"))]
#[cfg(all(feature = "arch", target_arch = "x86_64"))]
#[inline]
unsafe fn u128_by_u64_div_rem(duo: u128, div: u64) -> (u64, u64) {
let duo_lo = duo as u64;
@@ -208,7 +208,7 @@ unsafe fn u128_by_u64_div_rem(duo: u128, div: u64) -> (u64, u64) {
}
// use `asymmetric` instead of `trifecta` on x86_64
#[cfg(all(not(feature = "no-asm"), target_arch = "x86_64"))]
#[cfg(all(feature = "arch", target_arch = "x86_64"))]
impl_asymmetric!(
u128_div_rem,
zero_div_fn,
@@ -237,7 +237,7 @@ fn u32_by_u32_div_rem(duo: u32, div: u32) -> (u32, u32) {
// When not on x86 and the pointer width is not 64, use `delegate` since the division size is larger
// than register size.
#[cfg(all(
not(all(not(feature = "no-asm"), target_arch = "x86")),
not(all(feature = "arch", target_arch = "x86")),
not(target_pointer_width = "64")
))]
impl_delegate!(
@@ -254,7 +254,7 @@ fn u32_by_u32_div_rem(duo: u32, div: u32) -> (u32, u32) {
// When not on x86 and the pointer width is 64, use `binary_long`.
#[cfg(all(
not(all(not(feature = "no-asm"), target_arch = "x86")),
not(all(feature = "arch", target_arch = "x86")),
target_pointer_width = "64"
))]
impl_binary_long!(
@@ -272,7 +272,7 @@ fn u32_by_u32_div_rem(duo: u32, div: u32) -> (u32, u32) {
///
/// If the quotient does not fit in a `u32`, a floating point exception occurs.
/// If `div == 0`, then a division by zero exception occurs.
#[cfg(all(not(feature = "no-asm"), target_arch = "x86"))]
#[cfg(all(feature = "arch", target_arch = "x86"))]
#[inline]
unsafe fn u64_by_u32_div_rem(duo: u64, div: u32) -> (u32, u32) {
let duo_lo = duo as u32;
@@ -294,7 +294,7 @@ unsafe fn u64_by_u32_div_rem(duo: u64, div: u32) -> (u32, u32) {
}
// use `asymmetric` instead of `delegate` on x86
#[cfg(all(not(feature = "no-asm"), target_arch = "x86"))]
#[cfg(all(feature = "arch", target_arch = "x86"))]
impl_asymmetric!(
u64_div_rem,
zero_div_fn,
@@ -4,7 +4,7 @@
pub(crate) use implementation::trailing_zeros;
mod implementation {
use crate::int::{CastFrom, Int};
use crate::support::{CastFrom, Int};
/// Returns number of trailing binary zeros in `x`.
#[allow(dead_code)]
@@ -1,99 +0,0 @@
pub use crate::support::{CastFrom, CastInto, Int, MinInt};
/// Trait for integers twice the bit width of another integer. This is implemented for all
/// primitives except for `u8`, because there is not a smaller primitive.
pub trait DInt: MinInt {
/// Integer that is half the bit width of the integer this trait is implemented for
type H: HInt<D = Self>;
/// Returns the low half of `self`
fn lo(self) -> Self::H;
/// Returns the high half of `self`
fn hi(self) -> Self::H;
/// Returns the low and high halves of `self` as a tuple
fn lo_hi(self) -> (Self::H, Self::H) {
(self.lo(), self.hi())
}
/// Constructs an integer using lower and higher half parts
fn from_lo_hi(lo: Self::H, hi: Self::H) -> Self {
lo.zero_widen() | hi.widen_hi()
}
}
/// Trait for integers half the bit width of another integer. This is implemented for all
/// primitives except for `u128`, because it there is not a larger primitive.
pub trait HInt: Int {
/// Integer that is double the bit width of the integer this trait is implemented for
type D: DInt<H = Self> + MinInt;
// NB: some of the below methods could have default implementations (e.g. `widen_hi`), but for
// unknown reasons this can cause infinite recursion when optimizations are disabled. See
// <https://github.com/rust-lang/compiler-builtins/pull/707> for context.
/// Widens (using default extension) the integer to have double bit width
fn widen(self) -> Self::D;
/// Widens (zero extension only) the integer to have double bit width. This is needed to get
/// around problems with associated type bounds (such as `Int<Othersign: DInt>`) being unstable
fn zero_widen(self) -> Self::D;
/// Widens the integer to have double bit width and shifts the integer into the higher bits
fn widen_hi(self) -> Self::D;
/// Widening multiplication with zero widening. This cannot overflow.
fn zero_widen_mul(self, rhs: Self) -> Self::D;
/// Widening multiplication. This cannot overflow.
fn widen_mul(self, rhs: Self) -> Self::D;
}
macro_rules! impl_d_int {
($($X:ident $D:ident),*) => {
$(
impl DInt for $D {
type H = $X;
fn lo(self) -> Self::H {
self as $X
}
fn hi(self) -> Self::H {
(self >> <$X as MinInt>::BITS) as $X
}
}
)*
};
}
macro_rules! impl_h_int {
($($H:ident $uH:ident $X:ident),*) => {
$(
impl HInt for $H {
type D = $X;
fn widen(self) -> Self::D {
self as $X
}
fn zero_widen(self) -> Self::D {
(self as $uH) as $X
}
fn zero_widen_mul(self, rhs: Self) -> Self::D {
self.zero_widen().wrapping_mul(rhs.zero_widen())
}
fn widen_mul(self, rhs: Self) -> Self::D {
self.widen().wrapping_mul(rhs.widen())
}
fn widen_hi(self) -> Self::D {
(self as $X) << <Self as MinInt>::BITS
}
}
)*
};
}
impl_d_int!(u8 u16, u16 u32, u32 u64, u64 u128, i8 i16, i16 i32, i32 i64, i64 i128);
impl_h_int!(
u8 u8 u16,
u16 u16 u32,
u32 u32 u64,
u64 u64 u128,
i8 u8 i16,
i16 u16 i32,
i32 u32 i64,
i64 u64 i128
);
@@ -48,6 +48,9 @@
pub mod sync;
// `libm` expects its `support` module to be available in the crate root.
#[cfg(feature = "unstable-public-internals")]
pub use math::libm_math::support;
#[cfg(not(feature = "unstable-public-internals"))]
use math::libm_math::support;
#[cfg(target_arch = "arm")]
@@ -60,7 +63,10 @@
// in the builtins-test tests. So this is a way of enabling the module during testing.
#[cfg(all(
target_arch = "aarch64",
any(target_feature = "outline-atomics", feature = "mangled-names")
any(
target_feature = "outline-atomics",
feature = "unstable-public-internals"
)
))]
pub mod aarch64_outline_atomics;
@@ -70,9 +76,6 @@
#[cfg(target_arch = "hexagon")]
pub mod hexagon;
#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
pub mod riscv;
#[cfg(target_arch = "x86")]
pub mod x86;
@@ -254,7 +254,7 @@ pub extern "unadjusted" fn $name( $($argname: $ty),* ) $(-> $ret)? {
$($body)*
}
#[cfg(all(target_vendor = "apple", any(target_arch = "x86", target_arch = "x86_64"), not(feature = "mangled-names")))]
#[cfg(all(target_vendor = "apple", any(target_arch = "x86", target_arch = "x86_64"), feature = "unmangled-names"))]
mod $name {
#[unsafe(no_mangle)]
#[cfg_attr(not(any(all(windows, target_env = "gnu"), target_os = "cygwin")), linkage = "weak")]
@@ -290,7 +290,7 @@ mod $name {
$($body)*
}
#[cfg(all(target_vendor = "apple", any(target_arch = "x86", target_arch = "x86_64"), not(feature = "mangled-names")))]
#[cfg(all(target_vendor = "apple", any(target_arch = "x86", target_arch = "x86_64"), feature = "unmangled-names"))]
mod $name {
#[unsafe(no_mangle)]
#[cfg_attr(not(any(all(windows, target_env = "gnu"), target_os = "cygwin")), linkage = "weak")]
@@ -331,7 +331,7 @@ mod $name {
$($body)*
}
#[cfg(all(target_arch = "arm", not(feature = "mangled-names")))]
#[cfg(all(target_arch = "arm", feature = "unmangled-names"))]
mod $name {
#[unsafe(no_mangle)]
#[cfg_attr(not(any(all(windows, target_env = "gnu"), target_os = "cygwin")), linkage = "weak")]
@@ -341,7 +341,7 @@ mod $name {
}
}
#[cfg(all(target_arch = "arm", not(feature = "mangled-names")))]
#[cfg(all(target_arch = "arm", feature = "unmangled-names"))]
mod $alias {
#[unsafe(no_mangle)]
#[cfg_attr(not(any(all(windows, target_env = "gnu"), target_os = "cygwin")), linkage = "weak")]
@@ -392,7 +392,7 @@ extern "aapcs" fn $alias( $($argname: $ty),* ) $(-> $ret)? {
intrinsics!($($rest)*);
);
// C mem* functions are only generated when the "mem" feature is enabled.
// C mem* functions are only exposed via `no_mangle` when the "mem" feature is enabled.
(
#[mem_builtin]
$(#[$($attr:tt)*])*
@@ -407,7 +407,7 @@ extern "aapcs" fn $alias( $($argname: $ty),* ) $(-> $ret)? {
$($body)*
}
#[cfg(all(feature = "mem", not(feature = "mangled-names")))]
#[cfg(all(feature = "mem", feature = "unmangled-names"))]
mod $name {
$(#[$($attr)*])*
#[unsafe(no_mangle)]
@@ -435,7 +435,7 @@ mod $name {
pub mod $name {
#[unsafe(naked)]
$(#[$($attr)*])*
#[cfg_attr(not(feature = "mangled-names"), unsafe(no_mangle))]
#[cfg_attr(feature = "unmangled-names", unsafe(no_mangle))]
#[cfg_attr(not(any(all(windows, target_env = "gnu"), target_os = "cygwin")), linkage = "weak")]
pub unsafe extern $abi fn $name( $($argname: $ty),* ) $(-> $ret)? {
$($body)*
@@ -470,7 +470,7 @@ pub mod $name {
$($body)*
}
#[cfg(not(feature = "mangled-names"))]
#[cfg(feature = "unmangled-names")]
mod $name {
$(#[$($attr)*])*
#[unsafe(no_mangle)]
@@ -9,7 +9,7 @@
// ptr::add in these loops will wrap. And if compiler-builtins is compiled with cfg(ub_checks),
// this will fail a UB check at runtime.
//
// Since this scenario is UB, we are within our rights hit this check and halt execution...
// Since this scenario is UB, we are within our rights to hit this check and halt execution...
// But we are also within our rights to try to make it work.
// We use wrapping_add/wrapping_sub for pointer arithmetic in this module in an attempt to support
// this use. Of course this is not a guarantee that such use will work, it just means that this
@@ -35,7 +35,7 @@
16
};
#[cfg(feature = "mem-unaligned")]
#[cfg(mem_unaligned)]
unsafe fn read_usize_unaligned(x: *const usize) -> usize {
// Do not use `core::ptr::read_unaligned` here, since it calls `copy_nonoverlapping` which
// is translated to memcpy in LLVM.
@@ -46,7 +46,7 @@ unsafe fn read_usize_unaligned(x: *const usize) -> usize {
/// Loads a `T`-sized chunk from `src` into `dst` at offset `offset`, if that does not exceed
/// `load_sz`. The offset pointers must both be `T`-aligned. Returns the new offset, advanced by the
/// chunk size if a load happened.
#[cfg(not(feature = "mem-unaligned"))]
#[cfg(not(mem_unaligned))]
#[inline(always)]
unsafe fn load_chunk_aligned<T: Copy>(
src: *const usize,
@@ -66,7 +66,7 @@ unsafe fn load_chunk_aligned<T: Copy>(
/// Load `load_sz` many bytes from `src`, which must be usize-aligned. Acts as if we did a `usize`
/// read with the out-of-bounds part filled with 0s.
/// `load_sz` be strictly less than `WORD_SIZE`.
#[cfg(not(feature = "mem-unaligned"))]
#[cfg(not(mem_unaligned))]
#[inline(always)]
unsafe fn load_aligned_partial(src: *const usize, load_sz: usize) -> usize {
debug_assert!(load_sz < WORD_SIZE);
@@ -88,7 +88,7 @@ unsafe fn load_aligned_partial(src: *const usize, load_sz: usize) -> usize {
/// `usize`-aligned. The bytes are returned as the *last* bytes of the return value, i.e., this acts
/// as if we had done a `usize` read from `src`, with the out-of-bounds part filled with 0s.
/// `load_sz` be strictly less than `WORD_SIZE`.
#[cfg(not(feature = "mem-unaligned"))]
#[cfg(not(mem_unaligned))]
#[inline(always)]
unsafe fn load_aligned_end_partial(src: *const usize, load_sz: usize) -> usize {
debug_assert!(load_sz < WORD_SIZE);
@@ -136,7 +136,7 @@ unsafe fn copy_forward_aligned_words(dest: *mut u8, src: *const u8, n: usize) {
/// `n` is in units of bytes, but must be a multiple of the word size and must not be 0.
/// `src` *must not* be `usize`-aligned.
#[cfg(not(feature = "mem-unaligned"))]
#[cfg(not(mem_unaligned))]
#[inline(always)]
unsafe fn copy_forward_misaligned_words(dest: *mut u8, src: *const u8, n: usize) {
debug_assert!(n > 0 && n % WORD_SIZE == 0);
@@ -185,7 +185,7 @@ unsafe fn copy_forward_misaligned_words(dest: *mut u8, src: *const u8, n: usize)
/// `n` is in units of bytes, but must be a multiple of the word size and must not be 0.
/// `src` *must not* be `usize`-aligned.
#[cfg(feature = "mem-unaligned")]
#[cfg(mem_unaligned)]
#[inline(always)]
unsafe fn copy_forward_misaligned_words(dest: *mut u8, src: *const u8, n: usize) {
let mut dest_usize = dest as *mut usize;
@@ -252,7 +252,7 @@ unsafe fn copy_backward_aligned_words(dest: *mut u8, src: *const u8, n: usize) {
/// `n` is in units of bytes, but must be a multiple of the word size and must not be 0.
/// `src` *must not* be `usize`-aligned.
#[cfg(not(feature = "mem-unaligned"))]
#[cfg(not(mem_unaligned))]
#[inline(always)]
unsafe fn copy_backward_misaligned_words(dest: *mut u8, src: *const u8, n: usize) {
debug_assert!(n > 0 && n % WORD_SIZE == 0);
@@ -301,7 +301,7 @@ unsafe fn copy_backward_misaligned_words(dest: *mut u8, src: *const u8, n: usize
/// `n` is in units of bytes, but must be a multiple of the word size and must not be 0.
/// `src` *must not* be `usize`-aligned.
#[cfg(feature = "mem-unaligned")]
#[cfg(mem_unaligned)]
#[inline(always)]
unsafe fn copy_backward_misaligned_words(dest: *mut u8, src: *const u8, n: usize) {
let mut dest_usize = dest as *mut usize;
@@ -4,10 +4,7 @@
#![allow(unsafe_op_in_unsafe_fn)]
// memcpy/memmove/memset have optimized implementations on some architectures
#[cfg_attr(
all(not(feature = "no-asm"), target_arch = "x86_64"),
path = "x86_64.rs"
)]
#[cfg_attr(all(feature = "arch", target_arch = "x86_64"), path = "x86_64.rs")]
mod impls;
intrinsics! {

Some files were not shown because too many files have changed in this diff Show More