Merge branch 'master' into hooks
This commit is contained in:
commit
44af74f6dd
|
@ -23,7 +23,7 @@ The feature gate for the issue is `#![feature(FFF)]`.
|
|||
### About tracking issues
|
||||
|
||||
Tracking issues are used to record the overall progress of implementation.
|
||||
They are also uses as hubs connecting to other relevant issues, e.g., bugs or open design questions.
|
||||
They are also used as hubs connecting to other relevant issues, e.g., bugs or open design questions.
|
||||
A tracking issue is however *not* meant for large scale discussion, questions, or bug reports about a feature.
|
||||
Instead, open a dedicated issue for the specific matter and add the relevant feature gate label.
|
||||
|
||||
|
|
|
@ -76,111 +76,7 @@ jobs:
|
|||
uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master
|
||||
with:
|
||||
github_token: "${{ secrets.github_token }}"
|
||||
if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try' && !env.RUST_CI_TEMP_SKIP_CANCEL_OUTDATED"
|
||||
- name: collect CPU statistics
|
||||
run: src/ci/scripts/collect-cpu-stats.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: show the current environment
|
||||
run: src/ci/scripts/dump-environment.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: install awscli
|
||||
run: src/ci/scripts/install-awscli.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: install sccache
|
||||
run: src/ci/scripts/install-sccache.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: install clang
|
||||
run: src/ci/scripts/install-clang.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: install WIX
|
||||
run: src/ci/scripts/install-wix.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: ensure the build happens on a partition with enough space
|
||||
run: src/ci/scripts/symlink-build-dir.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: disable git crlf conversion
|
||||
run: src/ci/scripts/disable-git-crlf-conversion.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: install MSYS2
|
||||
run: src/ci/scripts/install-msys2.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: install MinGW
|
||||
run: src/ci/scripts/install-mingw.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: install ninja
|
||||
run: src/ci/scripts/install-ninja.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: enable ipv6 on Docker
|
||||
run: src/ci/scripts/enable-docker-ipv6.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: disable git crlf conversion
|
||||
run: src/ci/scripts/disable-git-crlf-conversion.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: checkout submodules
|
||||
run: src/ci/scripts/checkout-submodules.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: ensure line endings are correct
|
||||
run: src/ci/scripts/verify-line-endings.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: run the build
|
||||
run: src/ci/scripts/run-build-from-ci.sh
|
||||
env:
|
||||
AWS_ACCESS_KEY_ID: "${{ env.CACHES_AWS_ACCESS_KEY_ID }}"
|
||||
AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.CACHES_AWS_ACCESS_KEY_ID)] }}"
|
||||
TOOLSTATE_REPO_ACCESS_TOKEN: "${{ secrets.TOOLSTATE_REPO_ACCESS_TOKEN }}"
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: upload artifacts to S3
|
||||
run: src/ci/scripts/upload-artifacts.sh
|
||||
env:
|
||||
AWS_ACCESS_KEY_ID: "${{ env.ARTIFACTS_AWS_ACCESS_KEY_ID }}"
|
||||
AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.ARTIFACTS_AWS_ACCESS_KEY_ID)] }}"
|
||||
if: "success() && !env.SKIP_JOB && (github.event_name == 'push' || env.DEPLOY == '1' || env.DEPLOY_ALT == '1')"
|
||||
try:
|
||||
name: try
|
||||
env:
|
||||
CI_JOB_NAME: "${{ matrix.name }}"
|
||||
SCCACHE_BUCKET: rust-lang-ci-sccache2
|
||||
DEPLOY_BUCKET: rust-lang-ci2
|
||||
TOOLSTATE_REPO: "https://github.com/rust-lang-nursery/rust-toolstate"
|
||||
TOOLSTATE_ISSUES_API_URL: "https://api.github.com/repos/rust-lang/rust/issues"
|
||||
TOOLSTATE_PUBLISH: 1
|
||||
CACHES_AWS_ACCESS_KEY_ID: AKIA46X5W6CZI5DHEBFL
|
||||
ARTIFACTS_AWS_ACCESS_KEY_ID: AKIA46X5W6CZN24CBO55
|
||||
CACHE_DOMAIN: ci-caches.rust-lang.org
|
||||
if: "github.event_name == 'push' && (github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.repository == 'rust-lang-ci/rust'"
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- name: dist-x86_64-linux
|
||||
os: ubuntu-latest-xl
|
||||
env: {}
|
||||
timeout-minutes: 600
|
||||
runs-on: "${{ matrix.os }}"
|
||||
steps:
|
||||
- name: disable git crlf conversion
|
||||
run: git config --global core.autocrlf false
|
||||
- name: checkout the source code
|
||||
uses: actions/checkout@v1
|
||||
with:
|
||||
fetch-depth: 2
|
||||
- name: configure the PR in which the error message will be posted
|
||||
run: "echo \"[CI_PR_NUMBER=$num]\""
|
||||
env:
|
||||
num: "${{ github.event.number }}"
|
||||
if: "success() && !env.SKIP_JOBS && github.event_name == 'pull_request'"
|
||||
- name: add extra environment variables
|
||||
run: src/ci/scripts/setup-environment.sh
|
||||
env:
|
||||
EXTRA_VARIABLES: "${{ toJson(matrix.env) }}"
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: decide whether to skip this job
|
||||
run: src/ci/scripts/should-skip-this.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: configure GitHub Actions to kill the build when outdated
|
||||
uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master
|
||||
with:
|
||||
github_token: "${{ secrets.github_token }}"
|
||||
if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try' && !env.RUST_CI_TEMP_SKIP_CANCEL_OUTDATED"
|
||||
if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try'"
|
||||
- name: collect CPU statistics
|
||||
run: src/ci/scripts/collect-cpu-stats.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
|
@ -375,6 +271,35 @@ jobs:
|
|||
env:
|
||||
DEPLOY_TOOLSTATES_JSON: toolstates-linux.json
|
||||
os: ubuntu-latest-xl
|
||||
- name: dist-x86_64-apple
|
||||
env:
|
||||
SCRIPT: "./x.py dist"
|
||||
RUST_CONFIGURE_ARGS: "--host=x86_64-apple-darwin --target=x86_64-apple-darwin,aarch64-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false"
|
||||
RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
|
||||
MACOSX_DEPLOYMENT_TARGET: 10.7
|
||||
NO_LLVM_ASSERTIONS: 1
|
||||
NO_DEBUG_ASSERTIONS: 1
|
||||
DIST_REQUIRE_ALL_TOOLS: 1
|
||||
os: macos-latest
|
||||
- name: dist-x86_64-apple-alt
|
||||
env:
|
||||
SCRIPT: "./x.py dist"
|
||||
RUST_CONFIGURE_ARGS: "--enable-extended --enable-profiler --set rust.jemalloc --set llvm.ninja=false"
|
||||
RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
|
||||
MACOSX_DEPLOYMENT_TARGET: 10.7
|
||||
NO_LLVM_ASSERTIONS: 1
|
||||
NO_DEBUG_ASSERTIONS: 1
|
||||
os: macos-latest
|
||||
- name: x86_64-apple
|
||||
env:
|
||||
SCRIPT: "./x.py --stage 2 test"
|
||||
RUST_CONFIGURE_ARGS: "--build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false"
|
||||
RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
|
||||
MACOSX_DEPLOYMENT_TARGET: 10.8
|
||||
MACOSX_STD_DEPLOYMENT_TARGET: 10.7
|
||||
NO_LLVM_ASSERTIONS: 1
|
||||
NO_DEBUG_ASSERTIONS: 1
|
||||
os: macos-latest
|
||||
- name: x86_64-msvc-1
|
||||
env:
|
||||
RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --enable-profiler"
|
||||
|
@ -431,7 +356,7 @@ jobs:
|
|||
- name: x86_64-mingw-1
|
||||
env:
|
||||
SCRIPT: make ci-mingw-subset-1
|
||||
RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-gnu"
|
||||
RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-gnu --enable-profiler"
|
||||
CUSTOM_MINGW: 1
|
||||
NO_DEBUG_ASSERTIONS: 1
|
||||
NO_LLVM_ASSERTIONS: 1
|
||||
|
@ -439,18 +364,18 @@ jobs:
|
|||
- name: x86_64-mingw-2
|
||||
env:
|
||||
SCRIPT: make ci-mingw-subset-2
|
||||
RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-gnu"
|
||||
RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-gnu --enable-profiler"
|
||||
CUSTOM_MINGW: 1
|
||||
os: windows-latest-xl
|
||||
- name: dist-x86_64-msvc
|
||||
env:
|
||||
RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --target=x86_64-pc-windows-msvc,aarch64-pc-windows-msvc --enable-full-tools --enable-profiler"
|
||||
RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --host=x86_64-pc-windows-msvc --target=x86_64-pc-windows-msvc,aarch64-pc-windows-msvc --enable-full-tools --enable-profiler"
|
||||
SCRIPT: python x.py dist
|
||||
DIST_REQUIRE_ALL_TOOLS: 1
|
||||
os: windows-latest-xl
|
||||
- name: dist-i686-msvc
|
||||
env:
|
||||
RUST_CONFIGURE_ARGS: "--build=i686-pc-windows-msvc --target=i586-pc-windows-msvc --enable-full-tools --enable-profiler"
|
||||
RUST_CONFIGURE_ARGS: "--build=i686-pc-windows-msvc --host=i686-pc-windows-msvc --target=i686-pc-windows-msvc,i586-pc-windows-msvc --enable-full-tools --enable-profiler"
|
||||
SCRIPT: python x.py dist
|
||||
DIST_REQUIRE_ALL_TOOLS: 1
|
||||
os: windows-latest-xl
|
||||
|
@ -499,7 +424,7 @@ jobs:
|
|||
uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master
|
||||
with:
|
||||
github_token: "${{ secrets.github_token }}"
|
||||
if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try' && !env.RUST_CI_TEMP_SKIP_CANCEL_OUTDATED"
|
||||
if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try'"
|
||||
- name: collect CPU statistics
|
||||
run: src/ci/scripts/collect-cpu-stats.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
|
@ -580,38 +505,6 @@ jobs:
|
|||
- self-hosted
|
||||
- ARM64
|
||||
- linux
|
||||
- name: dist-x86_64-apple
|
||||
env:
|
||||
SCRIPT: "./x.py dist"
|
||||
RUST_CONFIGURE_ARGS: "--target=aarch64-apple-ios,x86_64-apple-ios --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false"
|
||||
RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
|
||||
MACOSX_DEPLOYMENT_TARGET: 10.7
|
||||
NO_LLVM_ASSERTIONS: 1
|
||||
NO_DEBUG_ASSERTIONS: 1
|
||||
DIST_REQUIRE_ALL_TOOLS: 1
|
||||
RUST_CI_TEMP_SKIP_CANCEL_OUTDATED: 1
|
||||
os: macos-latest
|
||||
- name: dist-x86_64-apple-alt
|
||||
env:
|
||||
SCRIPT: "./x.py dist"
|
||||
RUST_CONFIGURE_ARGS: "--enable-extended --enable-profiler --set rust.jemalloc --set llvm.ninja=false"
|
||||
RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
|
||||
MACOSX_DEPLOYMENT_TARGET: 10.7
|
||||
NO_LLVM_ASSERTIONS: 1
|
||||
NO_DEBUG_ASSERTIONS: 1
|
||||
RUST_CI_TEMP_SKIP_CANCEL_OUTDATED: 1
|
||||
os: macos-latest
|
||||
- name: x86_64-apple
|
||||
env:
|
||||
SCRIPT: "./x.py --stage 2 test"
|
||||
RUST_CONFIGURE_ARGS: "--build=x86_64-apple-darwin --enable-sanitizers --enable-profiler --set rust.jemalloc --set llvm.ninja=false"
|
||||
RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
|
||||
MACOSX_DEPLOYMENT_TARGET: 10.8
|
||||
MACOSX_STD_DEPLOYMENT_TARGET: 10.7
|
||||
NO_LLVM_ASSERTIONS: 1
|
||||
NO_DEBUG_ASSERTIONS: 1
|
||||
RUST_CI_TEMP_SKIP_CANCEL_OUTDATED: 1
|
||||
os: macos-latest
|
||||
timeout-minutes: 600
|
||||
runs-on: "${{ matrix.os }}"
|
||||
steps:
|
||||
|
@ -638,7 +531,111 @@ jobs:
|
|||
uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master
|
||||
with:
|
||||
github_token: "${{ secrets.github_token }}"
|
||||
if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try' && !env.RUST_CI_TEMP_SKIP_CANCEL_OUTDATED"
|
||||
if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try'"
|
||||
- name: collect CPU statistics
|
||||
run: src/ci/scripts/collect-cpu-stats.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: show the current environment
|
||||
run: src/ci/scripts/dump-environment.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: install awscli
|
||||
run: src/ci/scripts/install-awscli.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: install sccache
|
||||
run: src/ci/scripts/install-sccache.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: install clang
|
||||
run: src/ci/scripts/install-clang.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: install WIX
|
||||
run: src/ci/scripts/install-wix.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: ensure the build happens on a partition with enough space
|
||||
run: src/ci/scripts/symlink-build-dir.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: disable git crlf conversion
|
||||
run: src/ci/scripts/disable-git-crlf-conversion.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: install MSYS2
|
||||
run: src/ci/scripts/install-msys2.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: install MinGW
|
||||
run: src/ci/scripts/install-mingw.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: install ninja
|
||||
run: src/ci/scripts/install-ninja.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: enable ipv6 on Docker
|
||||
run: src/ci/scripts/enable-docker-ipv6.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: disable git crlf conversion
|
||||
run: src/ci/scripts/disable-git-crlf-conversion.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: checkout submodules
|
||||
run: src/ci/scripts/checkout-submodules.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: ensure line endings are correct
|
||||
run: src/ci/scripts/verify-line-endings.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: run the build
|
||||
run: src/ci/scripts/run-build-from-ci.sh
|
||||
env:
|
||||
AWS_ACCESS_KEY_ID: "${{ env.CACHES_AWS_ACCESS_KEY_ID }}"
|
||||
AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.CACHES_AWS_ACCESS_KEY_ID)] }}"
|
||||
TOOLSTATE_REPO_ACCESS_TOKEN: "${{ secrets.TOOLSTATE_REPO_ACCESS_TOKEN }}"
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: upload artifacts to S3
|
||||
run: src/ci/scripts/upload-artifacts.sh
|
||||
env:
|
||||
AWS_ACCESS_KEY_ID: "${{ env.ARTIFACTS_AWS_ACCESS_KEY_ID }}"
|
||||
AWS_SECRET_ACCESS_KEY: "${{ secrets[format('AWS_SECRET_ACCESS_KEY_{0}', env.ARTIFACTS_AWS_ACCESS_KEY_ID)] }}"
|
||||
if: "success() && !env.SKIP_JOB && (github.event_name == 'push' || env.DEPLOY == '1' || env.DEPLOY_ALT == '1')"
|
||||
try:
|
||||
name: try
|
||||
env:
|
||||
CI_JOB_NAME: "${{ matrix.name }}"
|
||||
SCCACHE_BUCKET: rust-lang-ci-sccache2
|
||||
DEPLOY_BUCKET: rust-lang-ci2
|
||||
TOOLSTATE_REPO: "https://github.com/rust-lang-nursery/rust-toolstate"
|
||||
TOOLSTATE_ISSUES_API_URL: "https://api.github.com/repos/rust-lang/rust/issues"
|
||||
TOOLSTATE_PUBLISH: 1
|
||||
CACHES_AWS_ACCESS_KEY_ID: AKIA46X5W6CZI5DHEBFL
|
||||
ARTIFACTS_AWS_ACCESS_KEY_ID: AKIA46X5W6CZN24CBO55
|
||||
CACHE_DOMAIN: ci-caches.rust-lang.org
|
||||
if: "github.event_name == 'push' && (github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf') && github.repository == 'rust-lang-ci/rust'"
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- name: dist-x86_64-linux
|
||||
os: ubuntu-latest-xl
|
||||
env: {}
|
||||
timeout-minutes: 600
|
||||
runs-on: "${{ matrix.os }}"
|
||||
steps:
|
||||
- name: disable git crlf conversion
|
||||
run: git config --global core.autocrlf false
|
||||
- name: checkout the source code
|
||||
uses: actions/checkout@v1
|
||||
with:
|
||||
fetch-depth: 2
|
||||
- name: configure the PR in which the error message will be posted
|
||||
run: "echo \"[CI_PR_NUMBER=$num]\""
|
||||
env:
|
||||
num: "${{ github.event.number }}"
|
||||
if: "success() && !env.SKIP_JOBS && github.event_name == 'pull_request'"
|
||||
- name: add extra environment variables
|
||||
run: src/ci/scripts/setup-environment.sh
|
||||
env:
|
||||
EXTRA_VARIABLES: "${{ toJson(matrix.env) }}"
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: decide whether to skip this job
|
||||
run: src/ci/scripts/should-skip-this.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
- name: configure GitHub Actions to kill the build when outdated
|
||||
uses: rust-lang/simpleinfra/github-actions/cancel-outdated-builds@master
|
||||
with:
|
||||
github_token: "${{ secrets.github_token }}"
|
||||
if: "success() && !env.SKIP_JOB && github.ref != 'refs/heads/try'"
|
||||
- name: collect CPU statistics
|
||||
run: src/ci/scripts/collect-cpu-stats.sh
|
||||
if: success() && !env.SKIP_JOB
|
||||
|
|
|
@ -33,7 +33,6 @@ __pycache__/
|
|||
/mingw-build/
|
||||
# Created by default with `src/ci/docker/run.sh`:
|
||||
/obj/
|
||||
/rustllvm/
|
||||
/unicode-downloads
|
||||
/target
|
||||
# Generated by compiletest for incremental:
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
[submodule "src/llvm-project"]
|
||||
path = src/llvm-project
|
||||
url = https://github.com/rust-lang/llvm-project.git
|
||||
branch = rustc/11.0-2020-08-20
|
||||
branch = rustc/11.0-2020-09-22
|
||||
[submodule "src/doc/embedded-book"]
|
||||
path = src/doc/embedded-book
|
||||
url = https://github.com/rust-embedded/book.git
|
||||
|
|
3
.mailmap
3
.mailmap
|
@ -55,6 +55,9 @@ Chris C Cerami <chrisccerami@users.noreply.github.com> Chris C Cerami <chrisccer
|
|||
Chris Pressey <cpressey@gmail.com>
|
||||
Chris Thorn <chris@thorn.co> Chris Thorn <thorn@thoughtbot.com>
|
||||
Chris Vittal <christopher.vittal@gmail.com> Christopher Vittal <christopher.vittal@gmail.com>
|
||||
Christiaan Dirkx <christiaan@dirkx.email> <christiaan@dirkx.com>
|
||||
Christiaan Dirkx <christiaan@dirkx.email> CDirkx <christiaan@dirkx.com>
|
||||
Christiaan Dirkx <christiaan@dirkx.email> CDirkx <christiaan@dirkx.email>
|
||||
Christian Poveda <git@christianpoveda.xyz> <christianpoveda@protonmail.com>
|
||||
Christian Poveda <git@christianpoveda.xyz> <cn.poveda.ruiz@gmail.com>
|
||||
Christian Poveda <git@christianpoveda.xyz> <z1mvader@protonmail.com>
|
||||
|
|
396
Cargo.lock
396
Cargo.lock
|
@ -183,7 +183,16 @@ dependencies = [
|
|||
"block-padding",
|
||||
"byte-tools",
|
||||
"byteorder",
|
||||
"generic-array",
|
||||
"generic-array 0.12.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
|
||||
dependencies = [
|
||||
"generic-array 0.14.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -207,6 +216,7 @@ dependencies = [
|
|||
"ignore",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"merge",
|
||||
"num_cpus",
|
||||
"opener",
|
||||
"pretty_assertions",
|
||||
|
@ -230,8 +240,14 @@ dependencies = [
|
|||
name = "build-manifest"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"flate2",
|
||||
"hex 0.4.2",
|
||||
"rayon",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2",
|
||||
"tar",
|
||||
"toml",
|
||||
]
|
||||
|
||||
|
@ -342,7 +358,6 @@ dependencies = [
|
|||
name = "cargo-miri"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"cargo_metadata 0.11.1",
|
||||
"directories",
|
||||
"rustc-workspace-hack",
|
||||
"rustc_version",
|
||||
|
@ -408,9 +423,9 @@ version = "0.1.0"
|
|||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.58"
|
||||
version = "1.0.60"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f9a06fb2e53271d7c279ec1efea6ab691c35a2ae67ec0d91d7acec0caf13b518"
|
||||
checksum = "ef611cc68ff783f18535d77ddd080185275713d852c4f5cbb6122c462a7a825c"
|
||||
dependencies = [
|
||||
"jobserver",
|
||||
]
|
||||
|
@ -427,9 +442,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "chalk-derive"
|
||||
version = "0.14.0"
|
||||
version = "0.29.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d463e01905d607e181de72e8608721d3269f29176c9a14ce037011316ae7131d"
|
||||
checksum = "3a7f257e3bcdc56d8877ae31c012bd69fba0be66929d588e603905f2632c0c59"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -439,21 +454,22 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "chalk-engine"
|
||||
version = "0.14.0"
|
||||
version = "0.29.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "efaf428f5398d36284f79690cf988762b7c091249f50a6c11db613a46c057000"
|
||||
checksum = "c43fcc7edf4d51b42f44ed50e2337bd90ddc8e088d0cd78a71db92a6f780f782"
|
||||
dependencies = [
|
||||
"chalk-derive",
|
||||
"chalk-ir",
|
||||
"chalk-solve",
|
||||
"rustc-hash",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "chalk-ir"
|
||||
version = "0.14.0"
|
||||
version = "0.29.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd3fdc1e9f68498ffe80f4a23b0b95f1ca6fb21d5a4c9b0c085fab3ca712bdbe"
|
||||
checksum = "03a4050029ecb2b5a1ff3bfc64c39279179b294821ec2e8891a4a5c6e3a08db0"
|
||||
dependencies = [
|
||||
"chalk-derive",
|
||||
"lazy_static",
|
||||
|
@ -461,18 +477,19 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "chalk-solve"
|
||||
version = "0.14.0"
|
||||
version = "0.29.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b9fd4102807b7ebe8fb034fa0f488c5656e1966d3261b558b81a08d519cdb29"
|
||||
checksum = "828c1f80d4eaf681027cce02050c54a3c97370f81988d31bf2a56df54048746c"
|
||||
dependencies = [
|
||||
"chalk-derive",
|
||||
"chalk-engine",
|
||||
"chalk-ir",
|
||||
"ena",
|
||||
"itertools 0.9.0",
|
||||
"petgraph",
|
||||
"rustc-hash",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
"tracing-tree",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -532,7 +549,7 @@ dependencies = [
|
|||
"if_chain",
|
||||
"itertools 0.9.0",
|
||||
"lazy_static",
|
||||
"pulldown-cmark",
|
||||
"pulldown-cmark 0.8.0",
|
||||
"quine-mc_cluskey",
|
||||
"quote",
|
||||
"regex-syntax",
|
||||
|
@ -574,9 +591,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "colored"
|
||||
version = "1.9.3"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4ffc801dacf156c5854b9df4f425a626539c3a6ef7893cc0c5084a23f0b6c59"
|
||||
checksum = "b3616f750b84d8f0de8a58bda93e08e2a81ad3f523089b05f1dffecab48c6cbd"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"lazy_static",
|
||||
|
@ -682,6 +699,12 @@ version = "0.8.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a21fa21941700a3cd8fcb4091f361a6a712fac632f85d9f487cc892045d55c6"
|
||||
|
||||
[[package]]
|
||||
name = "cpuid-bool"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8aebca1129a03dc6dc2b127edd729435bbc4a37e1d5f4d7513165089ceb02634"
|
||||
|
||||
[[package]]
|
||||
name = "crates-io"
|
||||
version = "0.31.1"
|
||||
|
@ -879,16 +902,24 @@ version = "0.8.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"generic-array 0.12.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
|
||||
dependencies = [
|
||||
"generic-array 0.14.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "directories"
|
||||
version = "2.0.2"
|
||||
version = "3.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "551a778172a450d7fc12e629ca3b0428d00f6afa9a43da1b630d54604e97371c"
|
||||
checksum = "f8fed639d60b58d0f53498ab13d26f621fd77569cc6edb031f4cc36a2ad9da0f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"dirs-sys",
|
||||
]
|
||||
|
||||
|
@ -1162,6 +1193,16 @@ dependencies = [
|
|||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "0.14.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getopts"
|
||||
version = "0.2.21"
|
||||
|
@ -1184,6 +1225,17 @@ dependencies = [
|
|||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee8025cf36f917e6a52cce185b7c7177689b838b7ec138364e50cc2277a56cf4"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.22.0"
|
||||
|
@ -1257,11 +1309,10 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.8.2"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e91b62f79061a0bc2e046024cb7ba44b08419ed238ecbd9adbd787434b9e8c25"
|
||||
checksum = "00d63df3d41950fb462ed38308eea019113ad1508da725bbedcd0fa5a85ef5f7"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-alloc",
|
||||
"rustc-std-workspace-core",
|
||||
|
@ -1399,9 +1450,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.5.1"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "86b45e59b16c76b11bf9738fd5d38879d3bd28ad292d7b313608becb17ae2df9"
|
||||
checksum = "55e2e4c765aa53a0424761bf9f41aa7a6ac1efa87238f59560640e27fca028f2"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"hashbrown",
|
||||
|
@ -1613,9 +1664,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
|
|||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.74"
|
||||
version = "0.2.77"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2f02823cf78b754822df5f7f268fb59822e7296276d3e069d8e8cb26a14bd10"
|
||||
checksum = "f2f96b10ec2560088a8e76961b00d47107b3a625fecb76dedb29ee7ccbf98235"
|
||||
dependencies = [
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
@ -1660,9 +1711,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "libz-sys"
|
||||
version = "1.0.27"
|
||||
version = "1.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ca8894883d250240341478bf987467332fbdd5da5c42426c69a8f93dbc302f2"
|
||||
checksum = "602113192b08db8f38796c4e85c39e960c145965140e918018bcde1952429655"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"libc",
|
||||
|
@ -1680,6 +1731,15 @@ version = "0.5.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a"
|
||||
|
||||
[[package]]
|
||||
name = "lint-docs"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"serde_json",
|
||||
"tempfile",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.3.4"
|
||||
|
@ -1707,15 +1767,6 @@ dependencies = [
|
|||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log_settings"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "19af41f0565d7c19b2058153ad0b42d4d5ce89ec4dbf06ed6741114a8b63e7cd"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lsp-codec"
|
||||
version = "0.1.2"
|
||||
|
@ -1825,16 +1876,16 @@ version = "0.8.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a18af3dcaf2b0219366cdb4e2af65a6101457b415c3d1a5c71dd9c2b7c77b9c8"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"digest",
|
||||
"opaque-debug",
|
||||
"block-buffer 0.7.3",
|
||||
"digest 0.8.1",
|
||||
"opaque-debug 0.2.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mdbook"
|
||||
version = "0.4.2"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b75e31ae4eaa0e45e17ee2b6b9e3ed969c3c6ff12bb4c2e352c42493f4ebb706"
|
||||
checksum = "29be448fcafb00c5a8966c4020c2a5ffbbc333e5b96d0bb5ef54b5bd0524d9ff"
|
||||
dependencies = [
|
||||
"ammonia",
|
||||
"anyhow",
|
||||
|
@ -1847,7 +1898,7 @@ dependencies = [
|
|||
"log",
|
||||
"memchr",
|
||||
"open",
|
||||
"pulldown-cmark",
|
||||
"pulldown-cmark 0.7.2",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
|
@ -1894,6 +1945,28 @@ dependencies = [
|
|||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "merge"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "10bbef93abb1da61525bbc45eeaff6473a41907d19f8f9aa5168d214e10693e9"
|
||||
dependencies = [
|
||||
"merge_derive",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "merge_derive"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "209d075476da2e63b4b29e72a2ef627b840589588e71400a25e3565c4f849d07"
|
||||
dependencies = [
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "minifier"
|
||||
version = "0.0.33"
|
||||
|
@ -1986,7 +2059,7 @@ dependencies = [
|
|||
"colored",
|
||||
"compiletest_rs",
|
||||
"env_logger 0.7.1",
|
||||
"getrandom",
|
||||
"getrandom 0.2.0",
|
||||
"hex 0.4.2",
|
||||
"libc",
|
||||
"log",
|
||||
|
@ -2058,9 +2131,6 @@ name = "once_cell"
|
|||
version = "1.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "260e51e7efe62b592207e9e13a68e43692a7a279171d6ba57abd208bf23645ad"
|
||||
dependencies = [
|
||||
"parking_lot 0.11.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "opaque-debug"
|
||||
|
@ -2068,6 +2138,12 @@ version = "0.2.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c"
|
||||
|
||||
[[package]]
|
||||
name = "opaque-debug"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
|
||||
|
||||
[[package]]
|
||||
name = "open"
|
||||
version = "1.4.0"
|
||||
|
@ -2508,6 +2584,17 @@ dependencies = [
|
|||
"unicase",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pulldown-cmark"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ffade02495f22453cd593159ea2f59827aae7f53fa8323f756799b670881dcf8"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"memchr",
|
||||
"unicase",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "punycode"
|
||||
version = "0.4.1"
|
||||
|
@ -2543,9 +2630,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "racer"
|
||||
version = "2.1.37"
|
||||
version = "2.1.38"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db975752fc2c2430b4159d262585f7e45eb9aa43d733bf02c5f2fde512b00bfb"
|
||||
checksum = "51dd5fd4247115b28f3e038eb8cda76a0c6f9cb473f769f41f930af8adff22d0"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"clap",
|
||||
|
@ -2570,7 +2657,7 @@ version = "0.7.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"getrandom 0.1.14",
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
|
@ -2594,7 +2681,7 @@ version = "0.5.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"getrandom 0.1.14",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -2670,7 +2757,7 @@ version = "0.3.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09b23093265f8d200fa7b4c2c76297f47e681c655f6f1285a8780d6a022f7431"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"getrandom 0.1.14",
|
||||
"redox_syscall",
|
||||
"rust-argon2",
|
||||
]
|
||||
|
@ -2855,8 +2942,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rust-demangler"
|
||||
version = "0.0.0"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"regex",
|
||||
"rustc-demangle",
|
||||
]
|
||||
|
||||
|
@ -2870,9 +2958,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rustc-ap-rustc_arena"
|
||||
version = "671.0.0"
|
||||
version = "677.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4a3941333c39ffa778611a34692244052fc9ba0f6b02dcf019c8d24925707dd6"
|
||||
checksum = "2958af0d6e0458434a25cd3a96f6e19f24f71bf50b900add520dec52e212866b"
|
||||
dependencies = [
|
||||
"rustc-ap-rustc_data_structures",
|
||||
"smallvec 1.4.2",
|
||||
|
@ -2880,30 +2968,28 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rustc-ap-rustc_ast"
|
||||
version = "671.0.0"
|
||||
version = "677.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "27c579f7d89e6fc971b433e92bb2b8c65b716d7c797b21de8685945be9455610"
|
||||
checksum = "0c82c2510460f2133548e62399e5acd30c25ae6ece30245baab3d1e00c2fefac"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"log",
|
||||
"rustc-ap-rustc_data_structures",
|
||||
"rustc-ap-rustc_index",
|
||||
"rustc-ap-rustc_lexer",
|
||||
"rustc-ap-rustc_macros",
|
||||
"rustc-ap-rustc_serialize",
|
||||
"rustc-ap-rustc_span",
|
||||
"scoped-tls",
|
||||
"smallvec 1.4.2",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-ap-rustc_ast_passes"
|
||||
version = "671.0.0"
|
||||
version = "677.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f9914fadee461568d19ca2ebaec8699ff898f8ffec9928154659a57ee018e5fd"
|
||||
checksum = "83977da57f81c6edd89bad47e49136680eaa33288de4abb702e95358c2a0fc6c"
|
||||
dependencies = [
|
||||
"itertools 0.8.2",
|
||||
"log",
|
||||
"rustc-ap-rustc_ast",
|
||||
"rustc-ap-rustc_ast_pretty",
|
||||
"rustc-ap-rustc_attr",
|
||||
|
@ -2913,31 +2999,33 @@ dependencies = [
|
|||
"rustc-ap-rustc_parse",
|
||||
"rustc-ap-rustc_session",
|
||||
"rustc-ap-rustc_span",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-ap-rustc_ast_pretty"
|
||||
version = "671.0.0"
|
||||
version = "677.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a78c5cc50a2f294d3c4e9131a15676724c9f136d3ed54e9ba419850b6025cb3"
|
||||
checksum = "becf4ca1638b214694c71a8752192683048ab8bd47947cc481f57bd48157eeb9"
|
||||
dependencies = [
|
||||
"log",
|
||||
"rustc-ap-rustc_ast",
|
||||
"rustc-ap-rustc_span",
|
||||
"rustc-ap-rustc_target",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-ap-rustc_attr"
|
||||
version = "671.0.0"
|
||||
version = "677.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a78ce08227d146949755175c0cf710280a4b5bf6ee504c0e3f7ccc30d66fbfd9"
|
||||
checksum = "0f21ca5dadce8a40d75a2756b77eab75b4c2d827f645c622dd93ee2285599640"
|
||||
dependencies = [
|
||||
"rustc-ap-rustc_ast",
|
||||
"rustc-ap-rustc_ast_pretty",
|
||||
"rustc-ap-rustc_data_structures",
|
||||
"rustc-ap-rustc_errors",
|
||||
"rustc-ap-rustc_feature",
|
||||
"rustc-ap-rustc_lexer",
|
||||
"rustc-ap-rustc_macros",
|
||||
"rustc-ap-rustc_serialize",
|
||||
"rustc-ap-rustc_session",
|
||||
|
@ -2947,9 +3035,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rustc-ap-rustc_data_structures"
|
||||
version = "671.0.0"
|
||||
version = "677.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9d5ac3735c38d2d0e95991ebcd7eb1618b60e784194a738e0ce2e8d39c39b809"
|
||||
checksum = "a4cd204764727fde9abf75333eb661f058bfc7242062d91019440fe1b240688b"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
|
@ -2959,12 +3047,11 @@ dependencies = [
|
|||
"jobserver",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
"log",
|
||||
"measureme",
|
||||
"once_cell",
|
||||
"parking_lot 0.10.2",
|
||||
"rustc-ap-rustc_graphviz",
|
||||
"rustc-ap-rustc_index",
|
||||
"rustc-ap-rustc_macros",
|
||||
"rustc-ap-rustc_serialize",
|
||||
"rustc-hash",
|
||||
"rustc-rayon",
|
||||
|
@ -2972,34 +3059,36 @@ dependencies = [
|
|||
"smallvec 1.4.2",
|
||||
"stable_deref_trait",
|
||||
"stacker",
|
||||
"tempfile",
|
||||
"tracing",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-ap-rustc_errors"
|
||||
version = "671.0.0"
|
||||
version = "677.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5166a95afa6e3b78ccbece4c2f1e163634854297f1147c6fd90e2712ed3fede5"
|
||||
checksum = "58116f119e37f14c029f99077b347069621118e048a69df74695b98204e7c136"
|
||||
dependencies = [
|
||||
"annotate-snippets 0.8.0",
|
||||
"atty",
|
||||
"log",
|
||||
"rustc-ap-rustc_data_structures",
|
||||
"rustc-ap-rustc_macros",
|
||||
"rustc-ap-rustc_serialize",
|
||||
"rustc-ap-rustc_span",
|
||||
"termcolor",
|
||||
"termize",
|
||||
"tracing",
|
||||
"unicode-width",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-ap-rustc_expand"
|
||||
version = "671.0.0"
|
||||
version = "677.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1a0586e83bdfe70eda8393429a8a38ecb529525dd252d787e479af075d3cab08"
|
||||
checksum = "48e3c4bda9b64b92805bebe7431fdb8e24fd112b35a8c6d2174827441f10a6b2"
|
||||
dependencies = [
|
||||
"log",
|
||||
"rustc-ap-rustc_ast",
|
||||
"rustc-ap-rustc_ast_passes",
|
||||
"rustc-ap-rustc_ast_pretty",
|
||||
|
@ -3008,18 +3097,20 @@ dependencies = [
|
|||
"rustc-ap-rustc_errors",
|
||||
"rustc-ap-rustc_feature",
|
||||
"rustc-ap-rustc_lexer",
|
||||
"rustc-ap-rustc_macros",
|
||||
"rustc-ap-rustc_parse",
|
||||
"rustc-ap-rustc_serialize",
|
||||
"rustc-ap-rustc_session",
|
||||
"rustc-ap-rustc_span",
|
||||
"smallvec 1.4.2",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-ap-rustc_feature"
|
||||
version = "671.0.0"
|
||||
version = "677.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "48fc3aa8de0737a8c5a4353e6948548f469150d2b5d3eac391843de32c6c6ca2"
|
||||
checksum = "4b612bb67d3fc49f395b03fc4ea4384a0145b05afbadab725803074ec827632b"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"rustc-ap-rustc_data_structures",
|
||||
|
@ -3028,40 +3119,41 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rustc-ap-rustc_fs_util"
|
||||
version = "671.0.0"
|
||||
version = "677.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59fd3380f4029020b693bbfd5a14ec8c893ec33c5c0063ad2e68e46d3fbd6a1f"
|
||||
checksum = "7630ad1a73a8434ee920676148cb5440ac57509bd20e94ec41087fb0b1d11c28"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-ap-rustc_graphviz"
|
||||
version = "671.0.0"
|
||||
version = "677.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b54bd98f70e04291bf611151d1fcd4d7770b35f7ec603d301c4aee0d1979cca4"
|
||||
checksum = "a603fca4817062eb4fb23ff129d475bd66a69fb32f34ed4362ae950cf814b49d"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-ap-rustc_index"
|
||||
version = "671.0.0"
|
||||
version = "677.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "335bfb187a2489a59ee8c67fcf5d1760e9dcdbe0f02025c199a74caa05096b15"
|
||||
checksum = "9850c4a5d7c341513e10802bca9588bf8f452ceea2d5cfa87b934246a52622bc"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"rustc-ap-rustc_macros",
|
||||
"rustc-ap-rustc_serialize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-ap-rustc_lexer"
|
||||
version = "671.0.0"
|
||||
version = "677.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "22e1221f3bfa2943c942cf8da319ab2346887f8757778c29c7f1822cd27b521f"
|
||||
checksum = "6d86722e5a1a615b198327d0d794cd9cbc8b9db4542276fc51fe078924de68ea"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-ap-rustc_macros"
|
||||
version = "671.0.0"
|
||||
version = "677.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b774df26c4ef513555b3a303cb209f44cf68a9e6a5481b41ac832301c6487cb"
|
||||
checksum = "b3fc8482e44cabdda7ac9a8e224aef62ebdf95274d629dac8db3b42321025fea"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -3071,12 +3163,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rustc-ap-rustc_parse"
|
||||
version = "671.0.0"
|
||||
version = "677.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "065e632101bdd57a271f38ee7a4d72b5a3d0467ec845104346c284b2c6c69960"
|
||||
checksum = "3716cdcd978a91dbd4a2788400e90e809527f841426fbeb92f882f9b8582f3ab"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"log",
|
||||
"rustc-ap-rustc_ast",
|
||||
"rustc-ap-rustc_ast_pretty",
|
||||
"rustc-ap-rustc_data_structures",
|
||||
|
@ -3085,14 +3176,16 @@ dependencies = [
|
|||
"rustc-ap-rustc_lexer",
|
||||
"rustc-ap-rustc_session",
|
||||
"rustc-ap-rustc_span",
|
||||
"smallvec 1.4.2",
|
||||
"tracing",
|
||||
"unicode-normalization",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-ap-rustc_serialize"
|
||||
version = "671.0.0"
|
||||
version = "677.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0e8c0b704e3dedb97cbb1ac566bbc0ab397ec4a4743098326a8f2230463fd9f9"
|
||||
checksum = "c68046d07988b349b2e1c8bc1c9664a1d06519354aa677b9df358c5c5c058da0"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"smallvec 1.4.2",
|
||||
|
@ -3100,32 +3193,32 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rustc-ap-rustc_session"
|
||||
version = "671.0.0"
|
||||
version = "677.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dda99ede4e6e260712754f8548b0a175b615686ad393653a3bd11f6c5e41a04e"
|
||||
checksum = "85735553501a4de0c8904e37b7ccef79cc1c585a7d7f2cfa02cc38e0d149f982"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"getopts",
|
||||
"log",
|
||||
"num_cpus",
|
||||
"rustc-ap-rustc_ast",
|
||||
"rustc-ap-rustc_data_structures",
|
||||
"rustc-ap-rustc_errors",
|
||||
"rustc-ap-rustc_feature",
|
||||
"rustc-ap-rustc_fs_util",
|
||||
"rustc-ap-rustc_macros",
|
||||
"rustc-ap-rustc_serialize",
|
||||
"rustc-ap-rustc_span",
|
||||
"rustc-ap-rustc_target",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-ap-rustc_span"
|
||||
version = "671.0.0"
|
||||
version = "677.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53453791c2c0b501a921927ce8e305a801eef130920873f8da92d83dad595236"
|
||||
checksum = "1c49ae8a0d3b9e27c6ffe8febeaa30f899294fff012de70625f9ee81c54fda85"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"log",
|
||||
"md-5",
|
||||
"rustc-ap-rustc_arena",
|
||||
"rustc-ap-rustc_data_structures",
|
||||
|
@ -3134,22 +3227,23 @@ dependencies = [
|
|||
"rustc-ap-rustc_serialize",
|
||||
"scoped-tls",
|
||||
"sha-1",
|
||||
"tracing",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-ap-rustc_target"
|
||||
version = "671.0.0"
|
||||
version = "677.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac82006fdb31ef44e24e1623f8b72ac2b404ef15ba20b7ebec0df35e5d20bbef"
|
||||
checksum = "1765f447594740c501c7b666b87639aa7c1dae2bf8c3166d5d2dca16646fd034"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"log",
|
||||
"rustc-ap-rustc_data_structures",
|
||||
"rustc-ap-rustc_index",
|
||||
"rustc-ap-rustc_macros",
|
||||
"rustc-ap-rustc_serialize",
|
||||
"rustc-ap-rustc_span",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3291,7 +3385,7 @@ dependencies = [
|
|||
name = "rustc_ast_passes"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"itertools 0.8.2",
|
||||
"itertools 0.9.0",
|
||||
"rustc_ast",
|
||||
"rustc_ast_pretty",
|
||||
"rustc_attr",
|
||||
|
@ -3415,6 +3509,7 @@ dependencies = [
|
|||
name = "rustc_data_structures"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"bitflags",
|
||||
"cfg-if",
|
||||
"crossbeam-utils 0.7.2",
|
||||
|
@ -3423,7 +3518,7 @@ dependencies = [
|
|||
"jobserver",
|
||||
"libc",
|
||||
"measureme",
|
||||
"parking_lot 0.10.2",
|
||||
"parking_lot 0.11.0",
|
||||
"rustc-hash",
|
||||
"rustc-rayon",
|
||||
"rustc-rayon-core",
|
||||
|
@ -3467,6 +3562,7 @@ dependencies = [
|
|||
"rustc_target",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
"tracing-tree",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
|
@ -3703,6 +3799,7 @@ dependencies = [
|
|||
"rustc_data_structures",
|
||||
"rustc_errors",
|
||||
"rustc_expand",
|
||||
"rustc_feature",
|
||||
"rustc_hir",
|
||||
"rustc_hir_pretty",
|
||||
"rustc_index",
|
||||
|
@ -3724,7 +3821,6 @@ name = "rustc_middle"
|
|||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"byteorder",
|
||||
"chalk-ir",
|
||||
"measureme",
|
||||
"polonius-engine",
|
||||
|
@ -3753,9 +3849,9 @@ name = "rustc_mir"
|
|||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"either",
|
||||
"itertools 0.8.2",
|
||||
"log_settings",
|
||||
"itertools 0.9.0",
|
||||
"polonius-engine",
|
||||
"regex",
|
||||
"rustc_apfloat",
|
||||
"rustc_ast",
|
||||
"rustc_attr",
|
||||
|
@ -3837,6 +3933,7 @@ dependencies = [
|
|||
"rustc_hir",
|
||||
"rustc_index",
|
||||
"rustc_middle",
|
||||
"rustc_serialize",
|
||||
"rustc_session",
|
||||
"rustc_span",
|
||||
"rustc_target",
|
||||
|
@ -3877,7 +3974,7 @@ dependencies = [
|
|||
name = "rustc_query_system"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"parking_lot 0.10.2",
|
||||
"parking_lot 0.11.0",
|
||||
"rustc-rayon-core",
|
||||
"rustc_arena",
|
||||
"rustc_data_structures",
|
||||
|
@ -4042,6 +4139,7 @@ dependencies = [
|
|||
name = "rustc_traits"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"chalk-engine",
|
||||
"chalk-ir",
|
||||
"chalk-solve",
|
||||
"rustc_ast",
|
||||
|
@ -4085,6 +4183,7 @@ dependencies = [
|
|||
"rustc_hir_pretty",
|
||||
"rustc_index",
|
||||
"rustc_infer",
|
||||
"rustc_macros",
|
||||
"rustc_middle",
|
||||
"rustc_session",
|
||||
"rustc_span",
|
||||
|
@ -4108,9 +4207,9 @@ name = "rustdoc"
|
|||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"expect-test",
|
||||
"itertools 0.8.2",
|
||||
"itertools 0.9.0",
|
||||
"minifier",
|
||||
"pulldown-cmark",
|
||||
"pulldown-cmark 0.8.0",
|
||||
"rustc-rayon",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
@ -4153,7 +4252,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rustfmt-nightly"
|
||||
version = "1.4.20"
|
||||
version = "1.4.21"
|
||||
dependencies = [
|
||||
"annotate-snippets 0.6.1",
|
||||
"anyhow",
|
||||
|
@ -4311,10 +4410,23 @@ version = "0.8.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"digest",
|
||||
"block-buffer 0.7.3",
|
||||
"digest 0.8.1",
|
||||
"fake-simd",
|
||||
"opaque-debug",
|
||||
"opaque-debug 0.2.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2933378ddfeda7ea26f48c555bdad8bb446bf8a3d17832dc83e380d444cfb8c1"
|
||||
dependencies = [
|
||||
"block-buffer 0.9.0",
|
||||
"cfg-if",
|
||||
"cpuid-bool",
|
||||
"digest 0.9.0",
|
||||
"opaque-debug 0.3.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4411,9 +4523,9 @@ checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
|
|||
|
||||
[[package]]
|
||||
name = "stacker"
|
||||
version = "0.1.11"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a92bc346006ae78c539d6ab2cf1a1532bc657b8339c464877a990ec82073c66f"
|
||||
checksum = "21ccb4c06ec57bc82d0f610f1a2963d7648700e43a6f513e564b9c89f7991786"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cfg-if",
|
||||
|
@ -4982,9 +5094,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tracing-attributes"
|
||||
version = "0.1.10"
|
||||
version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1fe233f4227389ab7df5b32649239da7ebe0b281824b4e84b342d04d3fd8c25e"
|
||||
checksum = "80e0ccfc3378da0cce270c946b676a376943f5cd16aeba64568e7939806f4ada"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -4993,13 +5105,34 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tracing-core"
|
||||
version = "0.1.14"
|
||||
version = "0.1.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db63662723c316b43ca36d833707cc93dff82a02ba3d7e354f342682cc8b3545"
|
||||
checksum = "4f0e00789804e99b20f12bc7003ca416309d28a6f495d6af58d1e2c2842461b5"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-log"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e0f8c7178e13481ff6765bd169b33e8d554c5d2bbede5e32c356194be02b9b9"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"log",
|
||||
"tracing-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-serde"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b6ccba2f8f16e0ed268fc765d9b7ff22e965e7185d32f8f1ec8294fe17d86e79"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"tracing-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-subscriber"
|
||||
version = "0.2.11"
|
||||
|
@ -5007,14 +5140,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "abd165311cc4d7a555ad11cc77a37756df836182db0d81aac908c8184c584f40"
|
||||
dependencies = [
|
||||
"ansi_term 0.12.1",
|
||||
"chrono",
|
||||
"lazy_static",
|
||||
"matchers",
|
||||
"parking_lot 0.11.0",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sharded-slab",
|
||||
"smallvec 1.4.2",
|
||||
"thread_local",
|
||||
"tracing-core",
|
||||
"tracing-log",
|
||||
"tracing-serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tracing-tree"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43aac8afb493b08e1e1904956f7407c1e671b9c83b26a17e1bd83d6a3520e350"
|
||||
dependencies = [
|
||||
"ansi_term 0.12.1",
|
||||
"atty",
|
||||
"chrono",
|
||||
"termcolor",
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
|
@ -10,6 +10,7 @@ members = [
|
|||
"src/tools/error_index_generator",
|
||||
"src/tools/install-git-hook",
|
||||
"src/tools/linkchecker",
|
||||
"src/tools/lint-docs",
|
||||
"src/tools/rustbook",
|
||||
"src/tools/unstable-book-gen",
|
||||
"src/tools/tidy",
|
||||
|
|
37
README.md
37
README.md
|
@ -7,7 +7,10 @@ standard library, and documentation.
|
|||
|
||||
[Rust]: https://www.rust-lang.org
|
||||
|
||||
**Note: this README is for _users_ rather than _contributors_.**
|
||||
**Note: this README is for _users_ rather than _contributors_.
|
||||
If you wish to _contribute_ to the compiler, you should read the
|
||||
[Getting Started][gettingstarted] of the rustc-dev-guide instead of this
|
||||
section.**
|
||||
|
||||
## Quick Start
|
||||
|
||||
|
@ -18,10 +21,6 @@ Read ["Installation"] from [The Book].
|
|||
|
||||
## Installing from Source
|
||||
|
||||
**Note: If you wish to _contribute_ to the compiler, you should read the
|
||||
[Getting Started][gettingstarted] of the rustc-dev-guide instead of this
|
||||
section.**
|
||||
|
||||
The Rust build system uses a Python script called `x.py` to build the compiler,
|
||||
which manages the bootstrapping process. More information about it can be found
|
||||
by running `./x.py --help` or reading the [rustc dev guide][rustcguidebuild].
|
||||
|
@ -45,8 +44,8 @@ by running `./x.py --help` or reading the [rustc dev guide][rustcguidebuild].
|
|||
2. Clone the [source] with `git`:
|
||||
|
||||
```sh
|
||||
$ git clone https://github.com/rust-lang/rust.git
|
||||
$ cd rust
|
||||
git clone https://github.com/rust-lang/rust.git
|
||||
cd rust
|
||||
```
|
||||
|
||||
[source]: https://github.com/rust-lang/rust
|
||||
|
@ -58,7 +57,7 @@ by running `./x.py --help` or reading the [rustc dev guide][rustcguidebuild].
|
|||
Copy the default `config.toml.example` to `config.toml` to get started.
|
||||
|
||||
```sh
|
||||
$ cp config.toml.example config.toml
|
||||
cp config.toml.example config.toml
|
||||
```
|
||||
|
||||
If you plan to use `x.py install` to create an installation, it is recommended
|
||||
|
@ -69,7 +68,7 @@ by running `./x.py --help` or reading the [rustc dev guide][rustcguidebuild].
|
|||
4. Build and install:
|
||||
|
||||
```sh
|
||||
$ ./x.py build && ./x.py install
|
||||
./x.py build && ./x.py install
|
||||
```
|
||||
|
||||
When complete, `./x.py install` will place several programs into
|
||||
|
@ -107,7 +106,7 @@ build.
|
|||
|
||||
```sh
|
||||
# Update package mirrors (may be needed if you have a fresh install of MSYS2)
|
||||
$ pacman -Sy pacman-mirrors
|
||||
pacman -Sy pacman-mirrors
|
||||
|
||||
# Install build tools needed for Rust. If you're building a 32-bit compiler,
|
||||
# then replace "x86_64" below with "i686". If you've already got git, python,
|
||||
|
@ -115,7 +114,7 @@ build.
|
|||
# that it is important that you do **not** use the 'python2', 'cmake' and 'ninja'
|
||||
# packages from the 'msys2' subsystem. The build has historically been known
|
||||
# to fail with these packages.
|
||||
$ pacman -S git \
|
||||
pacman -S git \
|
||||
make \
|
||||
diffutils \
|
||||
tar \
|
||||
|
@ -128,7 +127,7 @@ build.
|
|||
4. Navigate to Rust's source code (or clone it), then build it:
|
||||
|
||||
```sh
|
||||
$ ./x.py build && ./x.py install
|
||||
./x.py build && ./x.py install
|
||||
```
|
||||
|
||||
#### MSVC
|
||||
|
@ -146,7 +145,7 @@ With these dependencies installed, you can build the compiler in a `cmd.exe`
|
|||
shell with:
|
||||
|
||||
```sh
|
||||
> python x.py build
|
||||
python x.py build
|
||||
```
|
||||
|
||||
Currently, building Rust only works with some known versions of Visual Studio. If
|
||||
|
@ -155,8 +154,8 @@ you may need to force rustbuild to use an older version. This can be done
|
|||
by manually calling the appropriate vcvars file before running the bootstrap.
|
||||
|
||||
```batch
|
||||
> CALL "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat"
|
||||
> python x.py build
|
||||
CALL "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat"
|
||||
python x.py build
|
||||
```
|
||||
|
||||
#### Specifying an ABI
|
||||
|
@ -182,8 +181,8 @@ While it's not the recommended build system, this project also provides a
|
|||
configure script and makefile (the latter of which just invokes `x.py`).
|
||||
|
||||
```sh
|
||||
$ ./configure
|
||||
$ make && sudo make install
|
||||
./configure
|
||||
make && sudo make install
|
||||
```
|
||||
|
||||
When using the configure script, the generated `config.mk` file may override the
|
||||
|
@ -195,7 +194,7 @@ When using the configure script, the generated `config.mk` file may override the
|
|||
If you’d like to build the documentation, it’s almost the same:
|
||||
|
||||
```sh
|
||||
$ ./x.py doc
|
||||
./x.py doc
|
||||
```
|
||||
|
||||
The generated documentation will appear under `doc` in the `build` directory for
|
||||
|
@ -243,6 +242,8 @@ The Rust community congregates in a few places:
|
|||
If you are interested in contributing to the Rust project, please take a look
|
||||
at the [Getting Started][gettingstarted] guide in the [rustc-dev-guide].
|
||||
|
||||
[rustc-dev-guide]: https://rustc-dev-guide.rust-lang.org
|
||||
|
||||
## License
|
||||
|
||||
Rust is primarily distributed under the terms of both the MIT license
|
||||
|
|
135
RELEASES.md
135
RELEASES.md
|
@ -1,3 +1,138 @@
|
|||
Version 1.47.0 (2020-10-08)
|
||||
==========================
|
||||
|
||||
Language
|
||||
--------
|
||||
- [Closures will now warn when not used.][74869]
|
||||
|
||||
Compiler
|
||||
--------
|
||||
- [Stabilized the `-C control-flow-guard` codegen option][73893], which enables
|
||||
[Control Flow Guard][1.47.0-cfg] for Windows platforms, and is ignored on other
|
||||
platforms.
|
||||
- [Upgraded to LLVM 11.][73526]
|
||||
- [Added tier 3\* support for the `thumbv4t-none-eabi` target.][74419]
|
||||
- [Upgrade the FreeBSD toolchain to version 11.4][75204]
|
||||
- [`RUST_BACKTRACE`'s output is now more compact.][75048]
|
||||
|
||||
\* Refer to Rust's [platform support page][forge-platform-support] for more
|
||||
information on Rust's tiered platform support.
|
||||
|
||||
Libraries
|
||||
---------
|
||||
- [`CStr` now implements `Index<RangeFrom<usize>>`.][74021]
|
||||
- [Traits in `std`/`core` are now implemented for arrays of any length, not just
|
||||
those of length less than 33.][74060]
|
||||
- [`ops::RangeFull` and `ops::Range` now implement Default.][73197]
|
||||
- [`panic::Location` now implements `Copy`, `Clone`, `Eq`, `Hash`, `Ord`,
|
||||
`PartialEq`, and `PartialOrd`.][73583]
|
||||
|
||||
Stabilized APIs
|
||||
---------------
|
||||
- [`Ident::new_raw`]
|
||||
- [`Range::is_empty`]
|
||||
- [`RangeInclusive::is_empty`]
|
||||
- [`Result::as_deref`]
|
||||
- [`Result::as_deref_mut`]
|
||||
- [`Vec::leak`]
|
||||
- [`pointer::offset_from`]
|
||||
- [`f32::TAU`]
|
||||
- [`f64::TAU`]
|
||||
|
||||
The following previously stable APIs have now been made const.
|
||||
|
||||
- [The `new` method for all `NonZero` integers.][73858]
|
||||
- [The `checked_add`,`checked_sub`,`checked_mul`,`checked_neg`, `checked_shl`,
|
||||
`checked_shr`, `saturating_add`, `saturating_sub`, and `saturating_mul`
|
||||
methods for all integers.][73858]
|
||||
- [The `checked_abs`, `saturating_abs`, `saturating_neg`, and `signum` for all
|
||||
signed integers.][73858]
|
||||
- [The `is_ascii_alphabetic`, `is_ascii_uppercase`, `is_ascii_lowercase`,
|
||||
`is_ascii_alphanumeric`, `is_ascii_digit`, `is_ascii_hexdigit`,
|
||||
`is_ascii_punctuation`, `is_ascii_graphic`, `is_ascii_whitespace`, and
|
||||
`is_ascii_control` methods for `char` and `u8`.][73858]
|
||||
|
||||
Cargo
|
||||
-----
|
||||
- [`build-dependencies` are now built with opt-level 0 by default.][cargo/8500]
|
||||
You can override this by setting the following in your `Cargo.toml`.
|
||||
```toml
|
||||
[profile.release.build-override]
|
||||
opt-level = 3
|
||||
```
|
||||
- [`cargo-help` will now display man pages for commands rather just the
|
||||
`--help` text.][cargo/8456]
|
||||
- [`cargo-metadata` now emits a `test` field indicating if a target has
|
||||
tests enabled.][cargo/8478]
|
||||
- [`workspace.default-members` now respects `workspace.exclude`.][cargo/8485]
|
||||
- [`cargo-publish` will now use an alternative registry by default if it's the
|
||||
only registry specified in `package.publish`.][cargo/8571]
|
||||
|
||||
Misc
|
||||
----
|
||||
- [Added a help button beside Rustdoc's searchbar that explains rustdoc's
|
||||
type based search.][75366]
|
||||
- [Added the Ayu theme to rustdoc.][71237]
|
||||
|
||||
Compatibility Notes
|
||||
-------------------
|
||||
- [Bumped the minimum supported Emscripten version to 1.39.20.][75716]
|
||||
- [Fixed a regression parsing `{} && false` in tail expressions.][74650]
|
||||
- [Added changes to how proc-macros are expanded in `macro_rules!` that should
|
||||
help to preserve more span information.][73084] These changes may cause
|
||||
compiliation errors if your macro was unhygenic or didn't correctly handle
|
||||
`Delimiter::None`.
|
||||
- [Moved support for the CloudABI target to tier 3.][75568]
|
||||
- [`linux-gnu` targets now require minimum kernel 2.6.32 and glibc 2.11.][74163]
|
||||
- [Added the `rustc-docs` component.][75560] This allows you to install
|
||||
and read the documentation for the compiler internal APIs. (Currently only
|
||||
available for `x86_64-unknown-linux-gnu`.)
|
||||
|
||||
Internal Only
|
||||
--------
|
||||
- [Improved default settings for bootstrapping in `x.py`.][73964] You can read details about this change in the ["Changes to `x.py` defaults"](https://blog.rust-lang.org/inside-rust/2020/08/30/changes-to-x-py-defaults.html) post on the Inside Rust blog.
|
||||
|
||||
[1.47.0-cfg]: https://docs.microsoft.com/en-us/windows/win32/secbp/control-flow-guard
|
||||
[75048]: https://github.com/rust-lang/rust/pull/75048/
|
||||
[74163]: https://github.com/rust-lang/rust/pull/74163/
|
||||
[71237]: https://github.com/rust-lang/rust/pull/71237/
|
||||
[74869]: https://github.com/rust-lang/rust/pull/74869/
|
||||
[73858]: https://github.com/rust-lang/rust/pull/73858/
|
||||
[75716]: https://github.com/rust-lang/rust/pull/75716/
|
||||
[75908]: https://github.com/rust-lang/rust/pull/75908/
|
||||
[75516]: https://github.com/rust-lang/rust/pull/75516/
|
||||
[75560]: https://github.com/rust-lang/rust/pull/75560/
|
||||
[75568]: https://github.com/rust-lang/rust/pull/75568/
|
||||
[75366]: https://github.com/rust-lang/rust/pull/75366/
|
||||
[75204]: https://github.com/rust-lang/rust/pull/75204/
|
||||
[74650]: https://github.com/rust-lang/rust/pull/74650/
|
||||
[74419]: https://github.com/rust-lang/rust/pull/74419/
|
||||
[73964]: https://github.com/rust-lang/rust/pull/73964/
|
||||
[74021]: https://github.com/rust-lang/rust/pull/74021/
|
||||
[74060]: https://github.com/rust-lang/rust/pull/74060/
|
||||
[73893]: https://github.com/rust-lang/rust/pull/73893/
|
||||
[73526]: https://github.com/rust-lang/rust/pull/73526/
|
||||
[73583]: https://github.com/rust-lang/rust/pull/73583/
|
||||
[73084]: https://github.com/rust-lang/rust/pull/73084/
|
||||
[73197]: https://github.com/rust-lang/rust/pull/73197/
|
||||
[72488]: https://github.com/rust-lang/rust/pull/72488/
|
||||
[cargo/8456]: https://github.com/rust-lang/cargo/pull/8456/
|
||||
[cargo/8478]: https://github.com/rust-lang/cargo/pull/8478/
|
||||
[cargo/8485]: https://github.com/rust-lang/cargo/pull/8485/
|
||||
[cargo/8500]: https://github.com/rust-lang/cargo/pull/8500/
|
||||
[cargo/8571]: https://github.com/rust-lang/cargo/pull/8571/
|
||||
[`Ident::new_raw`]: https://doc.rust-lang.org/nightly/proc_macro/struct.Ident.html#method.new_raw
|
||||
[`Range::is_empty`]: https://doc.rust-lang.org/nightly/std/ops/struct.Range.html#method.is_empty
|
||||
[`RangeInclusive::is_empty`]: https://doc.rust-lang.org/nightly/std/ops/struct.RangeInclusive.html#method.is_empty
|
||||
[`Result::as_deref_mut`]: https://doc.rust-lang.org/nightly/std/result/enum.Result.html#method.as_deref_mut
|
||||
[`Result::as_deref`]: https://doc.rust-lang.org/nightly/std/result/enum.Result.html#method.as_deref
|
||||
[`TypeId::of`]: https://doc.rust-lang.org/nightly/std/any/struct.TypeId.html#method.of
|
||||
[`Vec::leak`]: https://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#method.leak
|
||||
[`f32::TAU`]: https://doc.rust-lang.org/nightly/std/f32/consts/constant.TAU.html
|
||||
[`f64::TAU`]: https://doc.rust-lang.org/nightly/std/f64/consts/constant.TAU.html
|
||||
[`pointer::offset_from`]: https://doc.rust-lang.org/nightly/std/primitive.pointer.html#method.offset_from
|
||||
|
||||
|
||||
Version 1.46.0 (2020-08-27)
|
||||
==========================
|
||||
|
||||
|
|
|
@ -19,3 +19,4 @@ features = ['unprefixed_malloc_on_supported_platforms']
|
|||
[features]
|
||||
jemalloc = ['jemalloc-sys']
|
||||
llvm = ['rustc_driver/llvm']
|
||||
max_level_info = ['rustc_driver/max_level_info']
|
||||
|
|
|
@ -1511,11 +1511,16 @@ impl<S: Semantics, T: Semantics> FloatConvert<IeeeFloat<T>> for IeeeFloat<S> {
|
|||
sig::set_bit(&mut r.sig, T::PRECISION - 1);
|
||||
}
|
||||
|
||||
// gcc forces the Quiet bit on, which means (float)(double)(float_sNan)
|
||||
// does not give you back the same bits. This is dubious, and we
|
||||
// don't currently do it. You're really supposed to get
|
||||
// an invalid operation signal at runtime, but nobody does that.
|
||||
status = Status::OK;
|
||||
// Convert of sNaN creates qNaN and raises an exception (invalid op).
|
||||
// This also guarantees that a sNaN does not become Inf on a truncation
|
||||
// that loses all payload bits.
|
||||
if self.is_signaling() {
|
||||
// Quiet signaling NaN.
|
||||
sig::set_bit(&mut r.sig, T::QNAN_BIT);
|
||||
status = Status::INVALID_OP;
|
||||
} else {
|
||||
status = Status::OK;
|
||||
}
|
||||
} else {
|
||||
*loses_info = false;
|
||||
status = Status::OK;
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
//!
|
||||
//! This API is completely unstable and subject to change.
|
||||
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![no_std]
|
||||
#![forbid(unsafe_code)]
|
||||
#![feature(nll)]
|
||||
|
|
|
@ -566,6 +566,17 @@ fn fma() {
|
|||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn issue_69532() {
|
||||
let f = Double::from_bits(0x7FF0_0000_0000_0001u64 as u128);
|
||||
let mut loses_info = false;
|
||||
let sta = f.convert(&mut loses_info);
|
||||
let r: Single = sta.value;
|
||||
assert!(loses_info);
|
||||
assert!(r.is_nan());
|
||||
assert_eq!(sta.status, Status::INVALID_OP);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn min_num() {
|
||||
let f1 = Double::from_f64(1.0);
|
||||
|
@ -1492,27 +1503,32 @@ fn convert() {
|
|||
assert_eq!(4294967295.0, test.to_f64());
|
||||
assert!(!loses_info);
|
||||
|
||||
let test = Single::snan(None);
|
||||
let x87_snan = X87DoubleExtended::snan(None);
|
||||
let test: X87DoubleExtended = test.convert(&mut loses_info).value;
|
||||
assert!(test.bitwise_eq(x87_snan));
|
||||
assert!(!loses_info);
|
||||
|
||||
let test = Single::qnan(None);
|
||||
let x87_qnan = X87DoubleExtended::qnan(None);
|
||||
let test: X87DoubleExtended = test.convert(&mut loses_info).value;
|
||||
assert!(test.bitwise_eq(x87_qnan));
|
||||
assert!(!loses_info);
|
||||
|
||||
let test = X87DoubleExtended::snan(None);
|
||||
let test: X87DoubleExtended = test.convert(&mut loses_info).value;
|
||||
assert!(test.bitwise_eq(x87_snan));
|
||||
let test = Single::snan(None);
|
||||
let sta = test.convert(&mut loses_info);
|
||||
let test: X87DoubleExtended = sta.value;
|
||||
assert!(test.is_nan());
|
||||
assert!(!test.is_signaling());
|
||||
assert!(!loses_info);
|
||||
assert_eq!(sta.status, Status::INVALID_OP);
|
||||
|
||||
let test = X87DoubleExtended::qnan(None);
|
||||
let test: X87DoubleExtended = test.convert(&mut loses_info).value;
|
||||
assert!(test.bitwise_eq(x87_qnan));
|
||||
assert!(!loses_info);
|
||||
|
||||
let test = X87DoubleExtended::snan(None);
|
||||
let sta = test.convert(&mut loses_info);
|
||||
let test: X87DoubleExtended = sta.value;
|
||||
assert!(test.is_nan());
|
||||
assert!(!test.is_signaling());
|
||||
assert!(!loses_info);
|
||||
assert_eq!(sta.status, Status::INVALID_OP);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -8,16 +8,13 @@
|
|||
//! This crate implements several kinds of arena.
|
||||
|
||||
#![doc(
|
||||
html_root_url = "https://doc.rust-lang.org/nightly/",
|
||||
html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/",
|
||||
test(no_crate_inject, attr(deny(warnings)))
|
||||
)]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(dropck_eyepatch)]
|
||||
#![feature(raw_vec_internals)]
|
||||
#![feature(new_uninit)]
|
||||
#![feature(maybe_uninit_slice)]
|
||||
#![cfg_attr(test, feature(test))]
|
||||
#![allow(deprecated)]
|
||||
|
||||
extern crate alloc;
|
||||
|
||||
use rustc_data_structures::cold_path;
|
||||
use smallvec::SmallVec;
|
||||
|
@ -25,14 +22,11 @@ use smallvec::SmallVec;
|
|||
use std::alloc::Layout;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::cmp;
|
||||
use std::intrinsics;
|
||||
use std::marker::{PhantomData, Send};
|
||||
use std::mem;
|
||||
use std::mem::{self, MaybeUninit};
|
||||
use std::ptr;
|
||||
use std::slice;
|
||||
|
||||
use alloc::raw_vec::RawVec;
|
||||
|
||||
/// An arena that can hold objects of only one type.
|
||||
pub struct TypedArena<T> {
|
||||
/// A pointer to the next object to be allocated.
|
||||
|
@ -52,7 +46,7 @@ pub struct TypedArena<T> {
|
|||
|
||||
struct TypedArenaChunk<T> {
|
||||
/// The raw storage for the arena chunk.
|
||||
storage: RawVec<T>,
|
||||
storage: Box<[MaybeUninit<T>]>,
|
||||
/// The number of valid entries in the chunk.
|
||||
entries: usize,
|
||||
}
|
||||
|
@ -60,7 +54,7 @@ struct TypedArenaChunk<T> {
|
|||
impl<T> TypedArenaChunk<T> {
|
||||
#[inline]
|
||||
unsafe fn new(capacity: usize) -> TypedArenaChunk<T> {
|
||||
TypedArenaChunk { storage: RawVec::with_capacity(capacity), entries: 0 }
|
||||
TypedArenaChunk { storage: Box::new_uninit_slice(capacity), entries: 0 }
|
||||
}
|
||||
|
||||
/// Destroys this arena chunk.
|
||||
|
@ -69,30 +63,25 @@ impl<T> TypedArenaChunk<T> {
|
|||
// The branch on needs_drop() is an -O1 performance optimization.
|
||||
// Without the branch, dropping TypedArena<u8> takes linear time.
|
||||
if mem::needs_drop::<T>() {
|
||||
let mut start = self.start();
|
||||
// Destroy all allocated objects.
|
||||
for _ in 0..len {
|
||||
ptr::drop_in_place(start);
|
||||
start = start.offset(1);
|
||||
}
|
||||
ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(&mut self.storage[..len]));
|
||||
}
|
||||
}
|
||||
|
||||
// Returns a pointer to the first allocated object.
|
||||
#[inline]
|
||||
fn start(&self) -> *mut T {
|
||||
self.storage.ptr()
|
||||
fn start(&mut self) -> *mut T {
|
||||
MaybeUninit::slice_as_mut_ptr(&mut self.storage)
|
||||
}
|
||||
|
||||
// Returns a pointer to the end of the allocated space.
|
||||
#[inline]
|
||||
fn end(&self) -> *mut T {
|
||||
fn end(&mut self) -> *mut T {
|
||||
unsafe {
|
||||
if mem::size_of::<T>() == 0 {
|
||||
// A pointer as large as possible for zero-sized elements.
|
||||
!0 as *mut T
|
||||
} else {
|
||||
self.start().add(self.storage.capacity())
|
||||
self.start().add(self.storage.len())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -130,7 +119,7 @@ impl<T> TypedArena<T> {
|
|||
|
||||
unsafe {
|
||||
if mem::size_of::<T>() == 0 {
|
||||
self.ptr.set(intrinsics::arith_offset(self.ptr.get() as *mut u8, 1) as *mut T);
|
||||
self.ptr.set((self.ptr.get() as *mut u8).wrapping_offset(1) as *mut T);
|
||||
let ptr = mem::align_of::<T>() as *mut T;
|
||||
// Don't drop the object. This `write` is equivalent to `forget`.
|
||||
ptr::write(ptr, object);
|
||||
|
@ -226,10 +215,10 @@ impl<T> TypedArena<T> {
|
|||
let used_bytes = self.ptr.get() as usize - last_chunk.start() as usize;
|
||||
last_chunk.entries = used_bytes / mem::size_of::<T>();
|
||||
|
||||
// If the previous chunk's capacity is less than HUGE_PAGE
|
||||
// If the previous chunk's len is less than HUGE_PAGE
|
||||
// bytes, then this chunk will be least double the previous
|
||||
// chunk's size.
|
||||
new_cap = last_chunk.storage.capacity();
|
||||
new_cap = last_chunk.storage.len();
|
||||
if new_cap < HUGE_PAGE / elem_size {
|
||||
new_cap = new_cap.checked_mul(2).unwrap();
|
||||
}
|
||||
|
@ -239,7 +228,7 @@ impl<T> TypedArena<T> {
|
|||
// Also ensure that this chunk can fit `additional`.
|
||||
new_cap = cmp::max(additional, new_cap);
|
||||
|
||||
let chunk = TypedArenaChunk::<T>::new(new_cap);
|
||||
let mut chunk = TypedArenaChunk::<T>::new(new_cap);
|
||||
self.ptr.set(chunk.start());
|
||||
self.end.set(chunk.end());
|
||||
chunks.push(chunk);
|
||||
|
@ -301,7 +290,7 @@ unsafe impl<#[may_dangle] T> Drop for TypedArena<T> {
|
|||
chunk.destroy(chunk.entries);
|
||||
}
|
||||
}
|
||||
// RawVec handles deallocation of `last_chunk` and `self.chunks`.
|
||||
// Box handles deallocation of `last_chunk` and `self.chunks`.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -309,11 +298,13 @@ unsafe impl<#[may_dangle] T> Drop for TypedArena<T> {
|
|||
unsafe impl<T: Send> Send for TypedArena<T> {}
|
||||
|
||||
pub struct DroplessArena {
|
||||
/// A pointer to the next object to be allocated.
|
||||
ptr: Cell<*mut u8>,
|
||||
/// A pointer to the start of the free space.
|
||||
start: Cell<*mut u8>,
|
||||
|
||||
/// A pointer to the end of the allocated area. When this pointer is
|
||||
/// reached, a new chunk is allocated.
|
||||
/// A pointer to the end of free space.
|
||||
///
|
||||
/// The allocation proceeds from the end of the chunk towards the start.
|
||||
/// When this pointer crosses the start pointer, a new chunk is allocated.
|
||||
end: Cell<*mut u8>,
|
||||
|
||||
/// A vector of arena chunks.
|
||||
|
@ -326,7 +317,7 @@ impl Default for DroplessArena {
|
|||
#[inline]
|
||||
fn default() -> DroplessArena {
|
||||
DroplessArena {
|
||||
ptr: Cell::new(ptr::null_mut()),
|
||||
start: Cell::new(ptr::null_mut()),
|
||||
end: Cell::new(ptr::null_mut()),
|
||||
chunks: Default::default(),
|
||||
}
|
||||
|
@ -344,10 +335,10 @@ impl DroplessArena {
|
|||
// There is no need to update `last_chunk.entries` because that
|
||||
// field isn't used by `DroplessArena`.
|
||||
|
||||
// If the previous chunk's capacity is less than HUGE_PAGE
|
||||
// If the previous chunk's len is less than HUGE_PAGE
|
||||
// bytes, then this chunk will be least double the previous
|
||||
// chunk's size.
|
||||
new_cap = last_chunk.storage.capacity();
|
||||
new_cap = last_chunk.storage.len();
|
||||
if new_cap < HUGE_PAGE {
|
||||
new_cap = new_cap.checked_mul(2).unwrap();
|
||||
}
|
||||
|
@ -357,8 +348,8 @@ impl DroplessArena {
|
|||
// Also ensure that this chunk can fit `additional`.
|
||||
new_cap = cmp::max(additional, new_cap);
|
||||
|
||||
let chunk = TypedArenaChunk::<u8>::new(new_cap);
|
||||
self.ptr.set(chunk.start());
|
||||
let mut chunk = TypedArenaChunk::<u8>::new(new_cap);
|
||||
self.start.set(chunk.start());
|
||||
self.end.set(chunk.end());
|
||||
chunks.push(chunk);
|
||||
}
|
||||
|
@ -369,24 +360,17 @@ impl DroplessArena {
|
|||
/// request.
|
||||
#[inline]
|
||||
fn alloc_raw_without_grow(&self, layout: Layout) -> Option<*mut u8> {
|
||||
let ptr = self.ptr.get() as usize;
|
||||
let start = self.start.get() as usize;
|
||||
let end = self.end.get() as usize;
|
||||
|
||||
let align = layout.align();
|
||||
let bytes = layout.size();
|
||||
// The allocation request fits into the current chunk iff:
|
||||
//
|
||||
// let aligned = align_to(ptr, align);
|
||||
// ptr <= aligned && aligned + bytes <= end
|
||||
//
|
||||
// Except that we work with fixed width integers and need to be careful
|
||||
// about potential overflow in the calcuation. If the overflow does
|
||||
// happen, then we definitely don't have enough free and need to grow
|
||||
// the arena.
|
||||
let aligned = ptr.checked_add(align - 1)? & !(align - 1);
|
||||
let new_ptr = aligned.checked_add(bytes)?;
|
||||
if new_ptr <= end {
|
||||
self.ptr.set(new_ptr as *mut u8);
|
||||
Some(aligned as *mut u8)
|
||||
|
||||
let new_end = end.checked_sub(bytes)? & !(align - 1);
|
||||
if start <= new_end {
|
||||
let new_end = new_end as *mut u8;
|
||||
self.end.set(new_end);
|
||||
Some(new_end)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
|
@ -121,6 +121,17 @@ pub fn bench_typed_arena_clear(b: &mut Bencher) {
|
|||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
pub fn bench_typed_arena_clear_100(b: &mut Bencher) {
|
||||
let mut arena = TypedArena::default();
|
||||
b.iter(|| {
|
||||
for _ in 0..100 {
|
||||
arena.alloc(Point { x: 1, y: 2, z: 3 });
|
||||
}
|
||||
arena.clear();
|
||||
})
|
||||
}
|
||||
|
||||
// Drop tests
|
||||
|
||||
struct DropCounter<'a> {
|
||||
|
|
|
@ -96,6 +96,7 @@ pub struct Path {
|
|||
/// The segments in the path: the things separated by `::`.
|
||||
/// Global paths begin with `kw::PathRoot`.
|
||||
pub segments: Vec<PathSegment>,
|
||||
pub tokens: Option<TokenStream>,
|
||||
}
|
||||
|
||||
impl PartialEq<Symbol> for Path {
|
||||
|
@ -117,7 +118,7 @@ impl Path {
|
|||
// Convert a span and an identifier to the corresponding
|
||||
// one-segment path.
|
||||
pub fn from_ident(ident: Ident) -> Path {
|
||||
Path { segments: vec![PathSegment::from_ident(ident)], span: ident.span }
|
||||
Path { segments: vec![PathSegment::from_ident(ident)], span: ident.span, tokens: None }
|
||||
}
|
||||
|
||||
pub fn is_global(&self) -> bool {
|
||||
|
@ -540,6 +541,7 @@ pub struct Block {
|
|||
/// Distinguishes between `unsafe { ... }` and `{ ... }`.
|
||||
pub rules: BlockCheckMode,
|
||||
pub span: Span,
|
||||
pub tokens: Option<TokenStream>,
|
||||
}
|
||||
|
||||
/// A match pattern.
|
||||
|
@ -586,7 +588,7 @@ impl Pat {
|
|||
_ => return None,
|
||||
};
|
||||
|
||||
Some(P(Ty { kind, id: self.id, span: self.span }))
|
||||
Some(P(Ty { kind, id: self.id, span: self.span, tokens: None }))
|
||||
}
|
||||
|
||||
/// Walk top-down and call `it` in each place where a pattern occurs
|
||||
|
@ -916,6 +918,7 @@ pub struct Stmt {
|
|||
pub id: NodeId,
|
||||
pub kind: StmtKind,
|
||||
pub span: Span,
|
||||
pub tokens: Option<TokenStream>,
|
||||
}
|
||||
|
||||
impl Stmt {
|
||||
|
@ -1068,7 +1071,7 @@ pub struct Expr {
|
|||
|
||||
// `Expr` is used a lot. Make sure it doesn't unintentionally get bigger.
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
rustc_data_structures::static_assert_size!(Expr, 104);
|
||||
rustc_data_structures::static_assert_size!(Expr, 112);
|
||||
|
||||
impl Expr {
|
||||
/// Returns `true` if this expression would be valid somewhere that expects a value;
|
||||
|
@ -1168,7 +1171,7 @@ impl Expr {
|
|||
_ => return None,
|
||||
};
|
||||
|
||||
Some(P(Ty { kind, id: self.id, span: self.span }))
|
||||
Some(P(Ty { kind, id: self.id, span: self.span, tokens: None }))
|
||||
}
|
||||
|
||||
pub fn precedence(&self) -> ExprPrecedence {
|
||||
|
@ -1866,6 +1869,7 @@ pub struct Ty {
|
|||
pub id: NodeId,
|
||||
pub kind: TyKind,
|
||||
pub span: Span,
|
||||
pub tokens: Option<TokenStream>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||
|
@ -1927,7 +1931,7 @@ pub enum TyKind {
|
|||
|
||||
impl TyKind {
|
||||
pub fn is_implicit_self(&self) -> bool {
|
||||
if let TyKind::ImplicitSelf = *self { true } else { false }
|
||||
matches!(self, TyKind::ImplicitSelf)
|
||||
}
|
||||
|
||||
pub fn is_unit(&self) -> bool {
|
||||
|
@ -2144,7 +2148,7 @@ impl Param {
|
|||
/// Builds a `Param` object from `ExplicitSelf`.
|
||||
pub fn from_self(attrs: AttrVec, eself: ExplicitSelf, eself_ident: Ident) -> Param {
|
||||
let span = eself.span.to(eself_ident.span);
|
||||
let infer_ty = P(Ty { id: DUMMY_NODE_ID, kind: TyKind::ImplicitSelf, span });
|
||||
let infer_ty = P(Ty { id: DUMMY_NODE_ID, kind: TyKind::ImplicitSelf, span, tokens: None });
|
||||
let param = |mutbl, ty| Param {
|
||||
attrs,
|
||||
pat: P(Pat {
|
||||
|
@ -2167,6 +2171,7 @@ impl Param {
|
|||
id: DUMMY_NODE_ID,
|
||||
kind: TyKind::Rptr(lt, MutTy { ty: infer_ty, mutbl }),
|
||||
span,
|
||||
tokens: None,
|
||||
}),
|
||||
),
|
||||
}
|
||||
|
@ -2222,7 +2227,7 @@ pub enum Async {
|
|||
|
||||
impl Async {
|
||||
pub fn is_async(self) -> bool {
|
||||
if let Async::Yes { .. } = self { true } else { false }
|
||||
matches!(self, Async::Yes { .. })
|
||||
}
|
||||
|
||||
/// In this case this is an `async` return, the `NodeId` for the generated `impl Trait` item.
|
||||
|
@ -2289,12 +2294,15 @@ impl FnRetTy {
|
|||
/// Module declaration.
|
||||
///
|
||||
/// E.g., `mod foo;` or `mod foo { .. }`.
|
||||
#[derive(Clone, Encodable, Decodable, Debug, Default)]
|
||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||
pub struct Mod {
|
||||
/// A span from the first token past `{` to the last token until `}`.
|
||||
/// For `mod foo;`, the inner span ranges from the first token
|
||||
/// to the last token in the external file.
|
||||
pub inner: Span,
|
||||
/// `unsafe` keyword accepted syntactically for macro DSLs, but not
|
||||
/// semantically by Rust.
|
||||
pub unsafety: Unsafe,
|
||||
pub items: Vec<P<Item>>,
|
||||
/// `true` for `mod foo { .. }`; `false` for `mod foo;`.
|
||||
pub inline: bool,
|
||||
|
@ -2302,9 +2310,12 @@ pub struct Mod {
|
|||
|
||||
/// Foreign module declaration.
|
||||
///
|
||||
/// E.g., `extern { .. }` or `extern C { .. }`.
|
||||
/// E.g., `extern { .. }` or `extern "C" { .. }`.
|
||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||
pub struct ForeignMod {
|
||||
/// `unsafe` keyword accepted syntactically for macro DSLs, but not
|
||||
/// semantically by Rust.
|
||||
pub unsafety: Unsafe,
|
||||
pub abi: Option<StrLit>,
|
||||
pub items: Vec<P<ForeignItem>>,
|
||||
}
|
||||
|
@ -2410,6 +2421,7 @@ impl<D: Decoder> rustc_serialize::Decodable<D> for AttrId {
|
|||
pub struct AttrItem {
|
||||
pub path: Path,
|
||||
pub args: MacArgs,
|
||||
pub tokens: Option<TokenStream>,
|
||||
}
|
||||
|
||||
/// A list of attributes.
|
||||
|
@ -2479,7 +2491,12 @@ pub enum CrateSugar {
|
|||
JustCrate,
|
||||
}
|
||||
|
||||
pub type Visibility = Spanned<VisibilityKind>;
|
||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||
pub struct Visibility {
|
||||
pub kind: VisibilityKind,
|
||||
pub span: Span,
|
||||
pub tokens: Option<TokenStream>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Encodable, Decodable, Debug)]
|
||||
pub enum VisibilityKind {
|
||||
|
@ -2491,7 +2508,7 @@ pub enum VisibilityKind {
|
|||
|
||||
impl VisibilityKind {
|
||||
pub fn is_pub(&self) -> bool {
|
||||
if let VisibilityKind::Public = *self { true } else { false }
|
||||
matches!(self, VisibilityKind::Public)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ use crate::ast::{Path, PathSegment};
|
|||
use crate::mut_visit::visit_clobber;
|
||||
use crate::ptr::P;
|
||||
use crate::token::{self, CommentKind, Token};
|
||||
use crate::tokenstream::{DelimSpan, TokenStream, TokenTree, TreeAndJoint};
|
||||
use crate::tokenstream::{DelimSpan, TokenStream, TokenTree, TreeAndSpacing};
|
||||
|
||||
use rustc_index::bit_set::GrowableBitSet;
|
||||
use rustc_span::source_map::{BytePos, Spanned};
|
||||
|
@ -330,7 +330,7 @@ crate fn mk_attr_id() -> AttrId {
|
|||
}
|
||||
|
||||
pub fn mk_attr(style: AttrStyle, path: Path, args: MacArgs, span: Span) -> Attribute {
|
||||
mk_attr_from_item(style, AttrItem { path, args }, span)
|
||||
mk_attr_from_item(style, AttrItem { path, args, tokens: None }, span)
|
||||
}
|
||||
|
||||
pub fn mk_attr_from_item(style: AttrStyle, item: AttrItem, span: Span) -> Attribute {
|
||||
|
@ -361,7 +361,7 @@ pub fn list_contains_name(items: &[NestedMetaItem], name: Symbol) -> bool {
|
|||
}
|
||||
|
||||
impl MetaItem {
|
||||
fn token_trees_and_joints(&self) -> Vec<TreeAndJoint> {
|
||||
fn token_trees_and_spacings(&self) -> Vec<TreeAndSpacing> {
|
||||
let mut idents = vec![];
|
||||
let mut last_pos = BytePos(0 as u32);
|
||||
for (i, segment) in self.path.segments.iter().enumerate() {
|
||||
|
@ -374,7 +374,7 @@ impl MetaItem {
|
|||
idents.push(TokenTree::Token(Token::from_ast_ident(segment.ident)).into());
|
||||
last_pos = segment.ident.span.hi();
|
||||
}
|
||||
idents.extend(self.kind.token_trees_and_joints(self.span));
|
||||
idents.extend(self.kind.token_trees_and_spacings(self.span));
|
||||
idents
|
||||
}
|
||||
|
||||
|
@ -415,7 +415,7 @@ impl MetaItem {
|
|||
}
|
||||
}
|
||||
let span = span.with_hi(segments.last().unwrap().ident.span.hi());
|
||||
Path { span, segments }
|
||||
Path { span, segments, tokens: None }
|
||||
}
|
||||
Some(TokenTree::Token(Token { kind: token::Interpolated(nt), .. })) => match *nt {
|
||||
token::Nonterminal::NtMeta(ref item) => return item.meta(item.path.span),
|
||||
|
@ -447,7 +447,7 @@ impl MetaItemKind {
|
|||
if i > 0 {
|
||||
tts.push(TokenTree::token(token::Comma, span).into());
|
||||
}
|
||||
tts.extend(item.token_trees_and_joints())
|
||||
tts.extend(item.token_trees_and_spacings())
|
||||
}
|
||||
MacArgs::Delimited(
|
||||
DelimSpan::from_single(span),
|
||||
|
@ -458,7 +458,7 @@ impl MetaItemKind {
|
|||
}
|
||||
}
|
||||
|
||||
fn token_trees_and_joints(&self, span: Span) -> Vec<TreeAndJoint> {
|
||||
fn token_trees_and_spacings(&self, span: Span) -> Vec<TreeAndSpacing> {
|
||||
match *self {
|
||||
MetaItemKind::Word => vec![],
|
||||
MetaItemKind::NameValue(ref lit) => {
|
||||
|
@ -470,7 +470,7 @@ impl MetaItemKind {
|
|||
if i > 0 {
|
||||
tokens.push(TokenTree::token(token::Comma, span).into());
|
||||
}
|
||||
tokens.extend(item.token_trees_and_joints())
|
||||
tokens.extend(item.token_trees_and_spacings())
|
||||
}
|
||||
vec![
|
||||
TokenTree::Delimited(
|
||||
|
@ -553,9 +553,9 @@ impl NestedMetaItem {
|
|||
}
|
||||
}
|
||||
|
||||
fn token_trees_and_joints(&self) -> Vec<TreeAndJoint> {
|
||||
fn token_trees_and_spacings(&self) -> Vec<TreeAndSpacing> {
|
||||
match *self {
|
||||
NestedMetaItem::MetaItem(ref item) => item.token_trees_and_joints(),
|
||||
NestedMetaItem::MetaItem(ref item) => item.token_trees_and_spacings(),
|
||||
NestedMetaItem::Literal(ref lit) => vec![lit.token_tree().into()],
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,18 +4,18 @@
|
|||
//!
|
||||
//! This API is completely unstable and subject to change.
|
||||
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/", test(attr(deny(warnings))))]
|
||||
#![feature(bool_to_option)]
|
||||
#![doc(
|
||||
html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/",
|
||||
test(attr(deny(warnings)))
|
||||
)]
|
||||
#![feature(box_syntax)]
|
||||
#![feature(const_fn)] // For the `transmute` in `P::new`
|
||||
#![feature(const_panic)]
|
||||
#![feature(const_fn_transmute)]
|
||||
#![feature(const_panic)]
|
||||
#![feature(crate_visibility_modifier)]
|
||||
#![feature(label_break_value)]
|
||||
#![feature(nll)]
|
||||
#![feature(or_patterns)]
|
||||
#![feature(try_trait)]
|
||||
#![feature(unicode_internals)]
|
||||
#![recursion_limit = "256"]
|
||||
|
||||
#[macro_use]
|
||||
|
|
|
@ -14,7 +14,7 @@ use crate::tokenstream::*;
|
|||
|
||||
use rustc_data_structures::map_in_place::MapInPlace;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_span::source_map::{respan, Spanned};
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::symbol::Ident;
|
||||
use rustc_span::Span;
|
||||
|
||||
|
@ -451,7 +451,7 @@ pub fn noop_visit_ty_constraint<T: MutVisitor>(
|
|||
}
|
||||
|
||||
pub fn noop_visit_ty<T: MutVisitor>(ty: &mut P<Ty>, vis: &mut T) {
|
||||
let Ty { id, kind, span } = ty.deref_mut();
|
||||
let Ty { id, kind, span, tokens: _ } = ty.deref_mut();
|
||||
vis.visit_id(id);
|
||||
match kind {
|
||||
TyKind::Infer | TyKind::ImplicitSelf | TyKind::Err | TyKind::Never | TyKind::CVarArgs => {}
|
||||
|
@ -490,7 +490,7 @@ pub fn noop_visit_ty<T: MutVisitor>(ty: &mut P<Ty>, vis: &mut T) {
|
|||
}
|
||||
|
||||
pub fn noop_visit_foreign_mod<T: MutVisitor>(foreign_mod: &mut ForeignMod, vis: &mut T) {
|
||||
let ForeignMod { abi: _, items } = foreign_mod;
|
||||
let ForeignMod { unsafety: _, abi: _, items } = foreign_mod;
|
||||
items.flat_map_in_place(|item| vis.flat_map_foreign_item(item));
|
||||
}
|
||||
|
||||
|
@ -513,7 +513,7 @@ pub fn noop_visit_ident<T: MutVisitor>(Ident { name: _, span }: &mut Ident, vis:
|
|||
vis.visit_span(span);
|
||||
}
|
||||
|
||||
pub fn noop_visit_path<T: MutVisitor>(Path { segments, span }: &mut Path, vis: &mut T) {
|
||||
pub fn noop_visit_path<T: MutVisitor>(Path { segments, span, tokens: _ }: &mut Path, vis: &mut T) {
|
||||
vis.visit_span(span);
|
||||
for PathSegment { ident, id, args } in segments {
|
||||
vis.visit_ident(ident);
|
||||
|
@ -579,7 +579,7 @@ pub fn noop_visit_local<T: MutVisitor>(local: &mut P<Local>, vis: &mut T) {
|
|||
pub fn noop_visit_attribute<T: MutVisitor>(attr: &mut Attribute, vis: &mut T) {
|
||||
let Attribute { kind, id: _, style: _, span } = attr;
|
||||
match kind {
|
||||
AttrKind::Normal(AttrItem { path, args }) => {
|
||||
AttrKind::Normal(AttrItem { path, args, tokens: _ }) => {
|
||||
vis.visit_path(path);
|
||||
visit_mac_args(args, vis);
|
||||
}
|
||||
|
@ -709,7 +709,7 @@ pub fn noop_visit_interpolated<T: MutVisitor>(nt: &mut token::Nonterminal, vis:
|
|||
token::NtLifetime(ident) => vis.visit_ident(ident),
|
||||
token::NtLiteral(expr) => vis.visit_expr(expr),
|
||||
token::NtMeta(item) => {
|
||||
let AttrItem { path, args } = item.deref_mut();
|
||||
let AttrItem { path, args, tokens: _ } = item.deref_mut();
|
||||
vis.visit_path(path);
|
||||
visit_mac_args(args, vis);
|
||||
}
|
||||
|
@ -871,7 +871,7 @@ pub fn noop_visit_mt<T: MutVisitor>(MutTy { ty, mutbl: _ }: &mut MutTy, vis: &mu
|
|||
}
|
||||
|
||||
pub fn noop_visit_block<T: MutVisitor>(block: &mut P<Block>, vis: &mut T) {
|
||||
let Block { id, stmts, rules: _, span } = block.deref_mut();
|
||||
let Block { id, stmts, rules: _, span, tokens: _ } = block.deref_mut();
|
||||
vis.visit_id(id);
|
||||
stmts.flat_map_in_place(|stmt| vis.flat_map_stmt(stmt));
|
||||
vis.visit_span(span);
|
||||
|
@ -970,18 +970,21 @@ pub fn noop_visit_fn_header<T: MutVisitor>(header: &mut FnHeader, vis: &mut T) {
|
|||
vis.visit_asyncness(asyncness);
|
||||
}
|
||||
|
||||
pub fn noop_visit_mod<T: MutVisitor>(Mod { inner, items, inline: _ }: &mut Mod, vis: &mut T) {
|
||||
pub fn noop_visit_mod<T: MutVisitor>(module: &mut Mod, vis: &mut T) {
|
||||
let Mod { inner, unsafety: _, items, inline: _ } = module;
|
||||
vis.visit_span(inner);
|
||||
items.flat_map_in_place(|item| vis.flat_map_item(item));
|
||||
}
|
||||
|
||||
pub fn noop_visit_crate<T: MutVisitor>(krate: &mut Crate, vis: &mut T) {
|
||||
visit_clobber(krate, |Crate { module, attrs, span, proc_macros }| {
|
||||
let item_vis =
|
||||
Visibility { kind: VisibilityKind::Public, span: span.shrink_to_lo(), tokens: None };
|
||||
let item = P(Item {
|
||||
ident: Ident::invalid(),
|
||||
attrs,
|
||||
id: DUMMY_NODE_ID,
|
||||
vis: respan(span.shrink_to_lo(), VisibilityKind::Public),
|
||||
vis: item_vis,
|
||||
span,
|
||||
kind: ItemKind::Mod(module),
|
||||
tokens: None,
|
||||
|
@ -990,7 +993,7 @@ pub fn noop_visit_crate<T: MutVisitor>(krate: &mut Crate, vis: &mut T) {
|
|||
|
||||
let len = items.len();
|
||||
if len == 0 {
|
||||
let module = Mod { inner: span, items: vec![], inline: true };
|
||||
let module = Mod { inner: span, unsafety: Unsafe::No, items: vec![], inline: true };
|
||||
Crate { module, attrs: vec![], span, proc_macros }
|
||||
} else if len == 1 {
|
||||
let Item { attrs, span, kind, .. } = items.into_iter().next().unwrap().into_inner();
|
||||
|
@ -1283,12 +1286,15 @@ pub fn noop_filter_map_expr<T: MutVisitor>(mut e: P<Expr>, vis: &mut T) -> Optio
|
|||
}
|
||||
|
||||
pub fn noop_flat_map_stmt<T: MutVisitor>(
|
||||
Stmt { kind, mut span, mut id }: Stmt,
|
||||
Stmt { kind, mut span, mut id, tokens }: Stmt,
|
||||
vis: &mut T,
|
||||
) -> SmallVec<[Stmt; 1]> {
|
||||
vis.visit_id(&mut id);
|
||||
vis.visit_span(&mut span);
|
||||
noop_flat_map_stmt_kind(kind, vis).into_iter().map(|kind| Stmt { id, kind, span }).collect()
|
||||
noop_flat_map_stmt_kind(kind, vis)
|
||||
.into_iter()
|
||||
.map(|kind| Stmt { id, kind, span, tokens: tokens.clone() })
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn noop_flat_map_stmt_kind<T: MutVisitor>(
|
||||
|
@ -1313,13 +1319,13 @@ pub fn noop_flat_map_stmt_kind<T: MutVisitor>(
|
|||
}
|
||||
}
|
||||
|
||||
pub fn noop_visit_vis<T: MutVisitor>(Spanned { node, span }: &mut Visibility, vis: &mut T) {
|
||||
match node {
|
||||
pub fn noop_visit_vis<T: MutVisitor>(visibility: &mut Visibility, vis: &mut T) {
|
||||
match &mut visibility.kind {
|
||||
VisibilityKind::Public | VisibilityKind::Crate(_) | VisibilityKind::Inherited => {}
|
||||
VisibilityKind::Restricted { path, id } => {
|
||||
vis.visit_path(path);
|
||||
vis.visit_id(id);
|
||||
}
|
||||
}
|
||||
vis.visit_span(span);
|
||||
vis.visit_span(&mut visibility.span);
|
||||
}
|
||||
|
|
|
@ -173,6 +173,7 @@ pub fn ident_can_begin_expr(name: Symbol, span: Span, is_raw: bool) -> bool {
|
|||
kw::Move,
|
||||
kw::Return,
|
||||
kw::True,
|
||||
kw::Try,
|
||||
kw::Unsafe,
|
||||
kw::While,
|
||||
kw::Yield,
|
||||
|
@ -699,7 +700,7 @@ pub enum Nonterminal {
|
|||
|
||||
// `Nonterminal` is used a lot. Make sure it doesn't unintentionally get bigger.
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
rustc_data_structures::static_assert_size!(Nonterminal, 40);
|
||||
rustc_data_structures::static_assert_size!(Nonterminal, 48);
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Encodable, Decodable)]
|
||||
pub enum NonterminalKind {
|
||||
|
@ -809,9 +810,19 @@ impl Nonterminal {
|
|||
if let ExpnKind::Macro(_, macro_name) = orig_span.ctxt().outer_expn_data().kind {
|
||||
let filename = source_map.span_to_filename(orig_span);
|
||||
if let FileName::Real(RealFileName::Named(path)) = filename {
|
||||
if (path.ends_with("time-macros-impl/src/lib.rs")
|
||||
&& macro_name == sym::impl_macros)
|
||||
|| (path.ends_with("js-sys/src/lib.rs") && macro_name == sym::arrays)
|
||||
let matches_prefix = |prefix| {
|
||||
// Check for a path that ends with 'prefix*/src/lib.rs'
|
||||
let mut iter = path.components().rev();
|
||||
iter.next().and_then(|p| p.as_os_str().to_str()) == Some("lib.rs")
|
||||
&& iter.next().and_then(|p| p.as_os_str().to_str()) == Some("src")
|
||||
&& iter
|
||||
.next()
|
||||
.and_then(|p| p.as_os_str().to_str())
|
||||
.map_or(false, |p| p.starts_with(prefix))
|
||||
};
|
||||
|
||||
if (macro_name == sym::impl_macros && matches_prefix("time-macros-impl"))
|
||||
|| (macro_name == sym::arrays && matches_prefix("js-sys"))
|
||||
{
|
||||
let snippet = source_map.span_to_snippet(orig_span);
|
||||
if snippet.as_deref() == Ok("$name") {
|
||||
|
|
|
@ -83,7 +83,7 @@ impl TokenTree {
|
|||
}
|
||||
|
||||
pub fn joint(self) -> TokenStream {
|
||||
TokenStream::new(vec![(self, Joint)])
|
||||
TokenStream::new(vec![(self, Spacing::Joint)])
|
||||
}
|
||||
|
||||
pub fn token(kind: TokenKind, span: Span) -> TokenTree {
|
||||
|
@ -125,22 +125,20 @@ where
|
|||
/// instead of a representation of the abstract syntax tree.
|
||||
/// Today's `TokenTree`s can still contain AST via `token::Interpolated` for back-compat.
|
||||
#[derive(Clone, Debug, Default, Encodable, Decodable)]
|
||||
pub struct TokenStream(pub Lrc<Vec<TreeAndJoint>>);
|
||||
pub struct TokenStream(pub Lrc<Vec<TreeAndSpacing>>);
|
||||
|
||||
pub type TreeAndJoint = (TokenTree, IsJoint);
|
||||
pub type TreeAndSpacing = (TokenTree, Spacing);
|
||||
|
||||
// `TokenStream` is used a lot. Make sure it doesn't unintentionally get bigger.
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
rustc_data_structures::static_assert_size!(TokenStream, 8);
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Encodable, Decodable)]
|
||||
pub enum IsJoint {
|
||||
pub enum Spacing {
|
||||
Alone,
|
||||
Joint,
|
||||
NonJoint,
|
||||
}
|
||||
|
||||
use IsJoint::*;
|
||||
|
||||
impl TokenStream {
|
||||
/// Given a `TokenStream` with a `Stream` of only two arguments, return a new `TokenStream`
|
||||
/// separating the two arguments with a comma for diagnostic suggestions.
|
||||
|
@ -153,7 +151,7 @@ impl TokenStream {
|
|||
let sp = match (&ts, &next) {
|
||||
(_, (TokenTree::Token(Token { kind: token::Comma, .. }), _)) => continue,
|
||||
(
|
||||
(TokenTree::Token(token_left), NonJoint),
|
||||
(TokenTree::Token(token_left), Spacing::Alone),
|
||||
(TokenTree::Token(token_right), _),
|
||||
) if ((token_left.is_ident() && !token_left.is_reserved_ident())
|
||||
|| token_left.is_lit())
|
||||
|
@ -162,11 +160,11 @@ impl TokenStream {
|
|||
{
|
||||
token_left.span
|
||||
}
|
||||
((TokenTree::Delimited(sp, ..), NonJoint), _) => sp.entire(),
|
||||
((TokenTree::Delimited(sp, ..), Spacing::Alone), _) => sp.entire(),
|
||||
_ => continue,
|
||||
};
|
||||
let sp = sp.shrink_to_hi();
|
||||
let comma = (TokenTree::token(token::Comma, sp), NonJoint);
|
||||
let comma = (TokenTree::token(token::Comma, sp), Spacing::Alone);
|
||||
suggestion = Some((pos, comma, sp));
|
||||
}
|
||||
}
|
||||
|
@ -184,19 +182,19 @@ impl TokenStream {
|
|||
|
||||
impl From<TokenTree> for TokenStream {
|
||||
fn from(tree: TokenTree) -> TokenStream {
|
||||
TokenStream::new(vec![(tree, NonJoint)])
|
||||
TokenStream::new(vec![(tree, Spacing::Alone)])
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TokenTree> for TreeAndJoint {
|
||||
fn from(tree: TokenTree) -> TreeAndJoint {
|
||||
(tree, NonJoint)
|
||||
impl From<TokenTree> for TreeAndSpacing {
|
||||
fn from(tree: TokenTree) -> TreeAndSpacing {
|
||||
(tree, Spacing::Alone)
|
||||
}
|
||||
}
|
||||
|
||||
impl iter::FromIterator<TokenTree> for TokenStream {
|
||||
fn from_iter<I: IntoIterator<Item = TokenTree>>(iter: I) -> Self {
|
||||
TokenStream::new(iter.into_iter().map(Into::into).collect::<Vec<TreeAndJoint>>())
|
||||
TokenStream::new(iter.into_iter().map(Into::into).collect::<Vec<TreeAndSpacing>>())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -209,7 +207,7 @@ impl PartialEq<TokenStream> for TokenStream {
|
|||
}
|
||||
|
||||
impl TokenStream {
|
||||
pub fn new(streams: Vec<TreeAndJoint>) -> TokenStream {
|
||||
pub fn new(streams: Vec<TreeAndSpacing>) -> TokenStream {
|
||||
TokenStream(Lrc::new(streams))
|
||||
}
|
||||
|
||||
|
@ -320,11 +318,11 @@ impl TokenStreamBuilder {
|
|||
// If `self` is not empty and the last tree within the last stream is a
|
||||
// token tree marked with `Joint`...
|
||||
if let Some(TokenStream(ref mut last_stream_lrc)) = self.0.last_mut() {
|
||||
if let Some((TokenTree::Token(last_token), Joint)) = last_stream_lrc.last() {
|
||||
if let Some((TokenTree::Token(last_token), Spacing::Joint)) = last_stream_lrc.last() {
|
||||
// ...and `stream` is not empty and the first tree within it is
|
||||
// a token tree...
|
||||
let TokenStream(ref mut stream_lrc) = stream;
|
||||
if let Some((TokenTree::Token(token), is_joint)) = stream_lrc.first() {
|
||||
if let Some((TokenTree::Token(token), spacing)) = stream_lrc.first() {
|
||||
// ...and the two tokens can be glued together...
|
||||
if let Some(glued_tok) = last_token.glue(&token) {
|
||||
// ...then do so, by overwriting the last token
|
||||
|
@ -337,8 +335,7 @@ impl TokenStreamBuilder {
|
|||
// Overwrite the last token tree with the merged
|
||||
// token.
|
||||
let last_vec_mut = Lrc::make_mut(last_stream_lrc);
|
||||
*last_vec_mut.last_mut().unwrap() =
|
||||
(TokenTree::Token(glued_tok), *is_joint);
|
||||
*last_vec_mut.last_mut().unwrap() = (TokenTree::Token(glued_tok), *spacing);
|
||||
|
||||
// Remove the first token tree from `stream`. (This
|
||||
// is almost always the only tree in `stream`.)
|
||||
|
@ -375,7 +372,7 @@ impl Iterator for Cursor {
|
|||
type Item = TokenTree;
|
||||
|
||||
fn next(&mut self) -> Option<TokenTree> {
|
||||
self.next_with_joint().map(|(tree, _)| tree)
|
||||
self.next_with_spacing().map(|(tree, _)| tree)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -384,7 +381,7 @@ impl Cursor {
|
|||
Cursor { stream, index: 0 }
|
||||
}
|
||||
|
||||
pub fn next_with_joint(&mut self) -> Option<TreeAndJoint> {
|
||||
pub fn next_with_spacing(&mut self) -> Option<TreeAndSpacing> {
|
||||
if self.index < self.stream.len() {
|
||||
self.index += 1;
|
||||
Some(self.stream.0[self.index - 1].clone())
|
||||
|
|
|
@ -103,6 +103,7 @@ fn find_match_by_sorted_words<'a>(iter_names: Vec<&'a Symbol>, lookup: &str) ->
|
|||
|
||||
fn sort_by_words(name: &str) -> String {
|
||||
let mut split_words: Vec<&str> = name.split('_').collect();
|
||||
split_words.sort();
|
||||
// We are sorting primitive &strs and can use unstable sort here
|
||||
split_words.sort_unstable();
|
||||
split_words.join("_")
|
||||
}
|
||||
|
|
|
@ -879,7 +879,7 @@ pub fn walk_arm<'a, V: Visitor<'a>>(visitor: &mut V, arm: &'a Arm) {
|
|||
}
|
||||
|
||||
pub fn walk_vis<'a, V: Visitor<'a>>(visitor: &mut V, vis: &'a Visibility) {
|
||||
if let VisibilityKind::Restricted { ref path, id } = vis.node {
|
||||
if let VisibilityKind::Restricted { ref path, id } = vis.kind {
|
||||
visitor.visit_path(path, id);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1121,7 +1121,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
// features. We check that at least one type is available for
|
||||
// the current target.
|
||||
let reg_class = reg.reg_class();
|
||||
let mut required_features = vec![];
|
||||
let mut required_features: Vec<&str> = vec![];
|
||||
for &(_, feature) in reg_class.supported_types(asm_arch) {
|
||||
if let Some(feature) = feature {
|
||||
if self.sess.target_features.contains(&Symbol::intern(feature)) {
|
||||
|
@ -1135,7 +1135,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
break;
|
||||
}
|
||||
}
|
||||
required_features.sort();
|
||||
// We are sorting primitive strs here and can use unstable sort here
|
||||
required_features.sort_unstable();
|
||||
required_features.dedup();
|
||||
match &required_features[..] {
|
||||
[] => {}
|
||||
|
|
|
@ -27,7 +27,7 @@ pub(super) struct ItemLowerer<'a, 'lowering, 'hir> {
|
|||
impl ItemLowerer<'_, '_, '_> {
|
||||
fn with_trait_impl_ref(&mut self, impl_ref: &Option<TraitRef>, f: impl FnOnce(&mut Self)) {
|
||||
let old = self.lctx.is_in_trait_impl;
|
||||
self.lctx.is_in_trait_impl = if let &None = impl_ref { false } else { true };
|
||||
self.lctx.is_in_trait_impl = impl_ref.is_some();
|
||||
f(self);
|
||||
self.lctx.is_in_trait_impl = old;
|
||||
}
|
||||
|
@ -251,7 +251,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
ItemKind::ExternCrate(orig_name) => hir::ItemKind::ExternCrate(orig_name),
|
||||
ItemKind::Use(ref use_tree) => {
|
||||
// Start with an empty prefix.
|
||||
let prefix = Path { segments: vec![], span: use_tree.span };
|
||||
let prefix = Path { segments: vec![], span: use_tree.span, tokens: None };
|
||||
|
||||
self.lower_use_tree(use_tree, &prefix, id, vis, ident, attrs)
|
||||
}
|
||||
|
@ -488,7 +488,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
*ident = tree.ident();
|
||||
|
||||
// First, apply the prefix to the path.
|
||||
let mut path = Path { segments, span: path.span };
|
||||
let mut path = Path { segments, span: path.span, tokens: None };
|
||||
|
||||
// Correctly resolve `self` imports.
|
||||
if path.segments.len() > 1
|
||||
|
@ -540,8 +540,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
hir::ItemKind::Use(path, hir::UseKind::Single)
|
||||
}
|
||||
UseTreeKind::Glob => {
|
||||
let path =
|
||||
self.lower_path(id, &Path { segments, span: path.span }, ParamMode::Explicit);
|
||||
let path = self.lower_path(
|
||||
id,
|
||||
&Path { segments, span: path.span, tokens: None },
|
||||
ParamMode::Explicit,
|
||||
);
|
||||
hir::ItemKind::Use(path, hir::UseKind::Glob)
|
||||
}
|
||||
UseTreeKind::Nested(ref trees) => {
|
||||
|
@ -569,7 +572,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
// for that we return the `{}` import (called the
|
||||
// `ListStem`).
|
||||
|
||||
let prefix = Path { segments, span: prefix.span.to(path.span) };
|
||||
let prefix = Path { segments, span: prefix.span.to(path.span), tokens: None };
|
||||
|
||||
// Add all the nested `PathListItem`s to the HIR.
|
||||
for &(ref use_tree, id) in trees {
|
||||
|
@ -927,7 +930,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
v: &Visibility,
|
||||
explicit_owner: Option<NodeId>,
|
||||
) -> hir::Visibility<'hir> {
|
||||
let node = match v.node {
|
||||
let node = match v.kind {
|
||||
VisibilityKind::Public => hir::VisibilityKind::Public,
|
||||
VisibilityKind::Crate(sugar) => hir::VisibilityKind::Crate(sugar),
|
||||
VisibilityKind::Restricted { ref path, id } => {
|
||||
|
|
|
@ -967,6 +967,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
AttrKind::Normal(ref item) => AttrKind::Normal(AttrItem {
|
||||
path: item.path.clone(),
|
||||
args: self.lower_mac_args(&item.args),
|
||||
tokens: None,
|
||||
}),
|
||||
AttrKind::DocComment(comment_kind, data) => AttrKind::DocComment(comment_kind, data),
|
||||
};
|
||||
|
@ -1106,6 +1107,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
id: node_id,
|
||||
kind: TyKind::ImplTrait(impl_trait_node_id, bounds.clone()),
|
||||
span: constraint.span,
|
||||
tokens: None,
|
||||
},
|
||||
itctx,
|
||||
);
|
||||
|
|
|
@ -5,7 +5,7 @@ version = "0.0.0"
|
|||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
itertools = "0.8"
|
||||
itertools = "0.9"
|
||||
tracing = "0.1"
|
||||
rustc_ast_pretty = { path = "../rustc_ast_pretty" }
|
||||
rustc_attr = { path = "../rustc_attr" }
|
||||
|
|
|
@ -198,13 +198,13 @@ impl<'a> AstValidator<'a> {
|
|||
}
|
||||
|
||||
fn invalid_visibility(&self, vis: &Visibility, note: Option<&str>) {
|
||||
if let VisibilityKind::Inherited = vis.node {
|
||||
if let VisibilityKind::Inherited = vis.kind {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut err =
|
||||
struct_span_err!(self.session, vis.span, E0449, "unnecessary visibility qualifier");
|
||||
if vis.node.is_pub() {
|
||||
if vis.kind.is_pub() {
|
||||
err.span_label(vis.span, "`pub` not permitted here because it's implied");
|
||||
}
|
||||
if let Some(note) = note {
|
||||
|
@ -868,10 +868,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
.emit();
|
||||
}
|
||||
|
||||
if !bounds
|
||||
.iter()
|
||||
.any(|b| if let GenericBound::Trait(..) = *b { true } else { false })
|
||||
{
|
||||
if !bounds.iter().any(|b| matches!(b, GenericBound::Trait(..))) {
|
||||
self.err_handler().span_err(ty.span, "at least one trait must be specified");
|
||||
}
|
||||
|
||||
|
@ -990,12 +987,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
self.error_item_without_body(item.span, "function", msg, " { <body> }");
|
||||
}
|
||||
}
|
||||
ItemKind::ForeignMod(_) => {
|
||||
ItemKind::ForeignMod(ForeignMod { unsafety, .. }) => {
|
||||
let old_item = mem::replace(&mut self.extern_mod, Some(item));
|
||||
self.invalid_visibility(
|
||||
&item.vis,
|
||||
Some("place qualifiers on individual foreign items instead"),
|
||||
);
|
||||
if let Unsafe::Yes(span) = unsafety {
|
||||
self.err_handler().span_err(span, "extern block cannot be declared unsafe");
|
||||
}
|
||||
visit::walk_item(self, item);
|
||||
self.extern_mod = old_item;
|
||||
return; // Avoid visiting again.
|
||||
|
@ -1029,7 +1029,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||
walk_list!(self, visit_attribute, &item.attrs);
|
||||
return;
|
||||
}
|
||||
ItemKind::Mod(Mod { inline, .. }) => {
|
||||
ItemKind::Mod(Mod { inline, unsafety, .. }) => {
|
||||
if let Unsafe::Yes(span) = unsafety {
|
||||
self.err_handler().span_err(span, "module cannot be declared unsafe");
|
||||
}
|
||||
// Ensure that `path` attributes on modules are recorded as used (cf. issue #35584).
|
||||
if !inline && !self.session.contains_name(&item.attrs, sym::path) {
|
||||
self.check_mod_file_item_asciionly(item.ident);
|
||||
|
|
|
@ -260,7 +260,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||
cfg => doc_cfg
|
||||
masked => doc_masked
|
||||
spotlight => doc_spotlight
|
||||
alias => doc_alias
|
||||
keyword => doc_keyword
|
||||
);
|
||||
}
|
||||
|
@ -594,7 +593,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||
}
|
||||
|
||||
fn visit_vis(&mut self, vis: &'a ast::Visibility) {
|
||||
if let ast::VisibilityKind::Crate(ast::CrateSugar::JustCrate) = vis.node {
|
||||
if let ast::VisibilityKind::Crate(ast::CrateSugar::JustCrate) = vis.kind {
|
||||
gate_feature_post!(
|
||||
&self,
|
||||
crate_visibility_modifier,
|
||||
|
@ -608,6 +607,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||
|
||||
pub fn check_crate(krate: &ast::Crate, sess: &Session) {
|
||||
maybe_stage_features(sess, krate);
|
||||
check_incompatible_features(sess);
|
||||
let mut visitor = PostExpansionVisitor { sess, features: &sess.features_untracked() };
|
||||
|
||||
let spans = sess.parse_sess.gated_spans.spans.borrow();
|
||||
|
@ -677,3 +677,36 @@ fn maybe_stage_features(sess: &Session, krate: &ast::Crate) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_incompatible_features(sess: &Session) {
|
||||
let features = sess.features_untracked();
|
||||
|
||||
let declared_features = features
|
||||
.declared_lang_features
|
||||
.iter()
|
||||
.copied()
|
||||
.map(|(name, span, _)| (name, span))
|
||||
.chain(features.declared_lib_features.iter().copied());
|
||||
|
||||
for (f1, f2) in rustc_feature::INCOMPATIBLE_FEATURES
|
||||
.iter()
|
||||
.filter(|&&(f1, f2)| features.enabled(f1) && features.enabled(f2))
|
||||
{
|
||||
if let Some((f1_name, f1_span)) = declared_features.clone().find(|(name, _)| name == f1) {
|
||||
if let Some((f2_name, f2_span)) = declared_features.clone().find(|(name, _)| name == f2)
|
||||
{
|
||||
let spans = vec![f1_span, f2_span];
|
||||
sess.struct_span_err(
|
||||
spans.clone(),
|
||||
&format!(
|
||||
"features `{}` and `{}` are incompatible, using them at the same time \
|
||||
is not allowed",
|
||||
f1_name, f2_name
|
||||
),
|
||||
)
|
||||
.help("remove one of these features")
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1139,7 +1139,11 @@ impl<'a> State<'a> {
|
|||
self.print_fn_full(sig, item.ident, gen, &item.vis, def, body, &item.attrs);
|
||||
}
|
||||
ast::ItemKind::Mod(ref _mod) => {
|
||||
self.head(visibility_qualified(&item.vis, "mod"));
|
||||
self.head(to_string(|s| {
|
||||
s.print_visibility(&item.vis);
|
||||
s.print_unsafety(_mod.unsafety);
|
||||
s.word("mod");
|
||||
}));
|
||||
self.print_ident(item.ident);
|
||||
|
||||
if _mod.inline || self.is_expanded {
|
||||
|
@ -1154,7 +1158,10 @@ impl<'a> State<'a> {
|
|||
}
|
||||
}
|
||||
ast::ItemKind::ForeignMod(ref nmod) => {
|
||||
self.head("extern");
|
||||
self.head(to_string(|s| {
|
||||
s.print_unsafety(nmod.unsafety);
|
||||
s.word("extern");
|
||||
}));
|
||||
if let Some(abi) = nmod.abi {
|
||||
self.print_literal(&abi.as_lit());
|
||||
self.nbsp();
|
||||
|
@ -1352,7 +1359,7 @@ impl<'a> State<'a> {
|
|||
}
|
||||
|
||||
crate fn print_visibility(&mut self, vis: &ast::Visibility) {
|
||||
match vis.node {
|
||||
match vis.kind {
|
||||
ast::VisibilityKind::Public => self.word_nbsp("pub"),
|
||||
ast::VisibilityKind::Crate(sugar) => match sugar {
|
||||
ast::CrateSugar::PubCrate => self.word_nbsp("pub(crate)"),
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use super::*;
|
||||
|
||||
use rustc_ast as ast;
|
||||
use rustc_span::source_map::respan;
|
||||
use rustc_span::symbol::Ident;
|
||||
use rustc_span::with_default_session_globals;
|
||||
|
||||
|
@ -45,7 +44,11 @@ fn test_variant_to_string() {
|
|||
|
||||
let var = ast::Variant {
|
||||
ident,
|
||||
vis: respan(rustc_span::DUMMY_SP, ast::VisibilityKind::Inherited),
|
||||
vis: ast::Visibility {
|
||||
span: rustc_span::DUMMY_SP,
|
||||
kind: ast::VisibilityKind::Inherited,
|
||||
tokens: None,
|
||||
},
|
||||
attrs: Vec::new(),
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
data: ast::VariantData::Unit(ast::DUMMY_NODE_ID),
|
||||
|
|
|
@ -145,8 +145,6 @@ pub struct ConstStability {
|
|||
pub feature: Symbol,
|
||||
/// whether the function has a `#[rustc_promotable]` attribute
|
||||
pub promotable: bool,
|
||||
/// whether the function has a `#[rustc_allow_const_fn_ptr]` attribute
|
||||
pub allow_const_fn_ptr: bool,
|
||||
}
|
||||
|
||||
/// The available stability levels.
|
||||
|
@ -160,10 +158,10 @@ pub enum StabilityLevel {
|
|||
|
||||
impl StabilityLevel {
|
||||
pub fn is_unstable(&self) -> bool {
|
||||
if let StabilityLevel::Unstable { .. } = *self { true } else { false }
|
||||
matches!(self, StabilityLevel::Unstable { .. })
|
||||
}
|
||||
pub fn is_stable(&self) -> bool {
|
||||
if let StabilityLevel::Stable { .. } = *self { true } else { false }
|
||||
matches!(self, StabilityLevel::Stable { .. })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -190,7 +188,6 @@ where
|
|||
let mut stab: Option<Stability> = None;
|
||||
let mut const_stab: Option<ConstStability> = None;
|
||||
let mut promotable = false;
|
||||
let mut allow_const_fn_ptr = false;
|
||||
let diagnostic = &sess.parse_sess.span_diagnostic;
|
||||
|
||||
'outer: for attr in attrs_iter {
|
||||
|
@ -200,7 +197,6 @@ where
|
|||
sym::unstable,
|
||||
sym::stable,
|
||||
sym::rustc_promotable,
|
||||
sym::rustc_allow_const_fn_ptr,
|
||||
]
|
||||
.iter()
|
||||
.any(|&s| attr.has_name(s))
|
||||
|
@ -215,9 +211,6 @@ where
|
|||
if attr.has_name(sym::rustc_promotable) {
|
||||
promotable = true;
|
||||
}
|
||||
if attr.has_name(sym::rustc_allow_const_fn_ptr) {
|
||||
allow_const_fn_ptr = true;
|
||||
}
|
||||
// attributes with data
|
||||
else if let Some(MetaItem { kind: MetaItemKind::List(ref metas), .. }) = meta {
|
||||
let meta = meta.as_ref().unwrap();
|
||||
|
@ -301,7 +294,7 @@ where
|
|||
.emit();
|
||||
};
|
||||
match issue.parse() {
|
||||
Ok(num) if num == 0 => {
|
||||
Ok(0) => {
|
||||
emit_diag(
|
||||
"`issue` must not be \"0\", \
|
||||
use \"none\" instead",
|
||||
|
@ -360,12 +353,8 @@ where
|
|||
if sym::unstable == meta_name {
|
||||
stab = Some(Stability { level, feature });
|
||||
} else {
|
||||
const_stab = Some(ConstStability {
|
||||
level,
|
||||
feature,
|
||||
promotable: false,
|
||||
allow_const_fn_ptr: false,
|
||||
});
|
||||
const_stab =
|
||||
Some(ConstStability { level, feature, promotable: false });
|
||||
}
|
||||
}
|
||||
(None, _, _) => {
|
||||
|
@ -440,12 +429,8 @@ where
|
|||
if sym::stable == meta_name {
|
||||
stab = Some(Stability { level, feature });
|
||||
} else {
|
||||
const_stab = Some(ConstStability {
|
||||
level,
|
||||
feature,
|
||||
promotable: false,
|
||||
allow_const_fn_ptr: false,
|
||||
});
|
||||
const_stab =
|
||||
Some(ConstStability { level, feature, promotable: false });
|
||||
}
|
||||
}
|
||||
(None, _) => {
|
||||
|
@ -464,18 +449,16 @@ where
|
|||
}
|
||||
|
||||
// Merge the const-unstable info into the stability info
|
||||
if promotable || allow_const_fn_ptr {
|
||||
if promotable {
|
||||
if let Some(ref mut stab) = const_stab {
|
||||
stab.promotable = promotable;
|
||||
stab.allow_const_fn_ptr = allow_const_fn_ptr;
|
||||
} else {
|
||||
struct_span_err!(
|
||||
diagnostic,
|
||||
item_sp,
|
||||
E0717,
|
||||
"rustc_promotable and rustc_allow_const_fn_ptr attributes \
|
||||
must be paired with either a rustc_const_unstable or a rustc_const_stable \
|
||||
attribute"
|
||||
"`rustc_promotable` attribute must be paired with either a `rustc_const_unstable` \
|
||||
or a `rustc_const_stable` attribute"
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
|
@ -1022,14 +1005,21 @@ pub fn find_transparency(
|
|||
|
||||
pub fn allow_internal_unstable<'a>(
|
||||
sess: &'a Session,
|
||||
attrs: &[Attribute],
|
||||
attrs: &'a [Attribute],
|
||||
) -> Option<impl Iterator<Item = Symbol> + 'a> {
|
||||
let attr = sess.find_by_name(attrs, sym::allow_internal_unstable)?;
|
||||
let list = attr.meta_item_list().or_else(|| {
|
||||
sess.diagnostic()
|
||||
.span_err(attr.span, "allow_internal_unstable expects list of feature names");
|
||||
None
|
||||
})?;
|
||||
let attrs = sess.filter_by_name(attrs, sym::allow_internal_unstable);
|
||||
let list = attrs
|
||||
.filter_map(move |attr| {
|
||||
attr.meta_item_list().or_else(|| {
|
||||
sess.diagnostic().span_err(
|
||||
attr.span,
|
||||
"`allow_internal_unstable` expects a list of feature names",
|
||||
);
|
||||
None
|
||||
})
|
||||
})
|
||||
.flatten();
|
||||
|
||||
Some(list.into_iter().filter_map(move |it| {
|
||||
let name = it.ident().map(|ident| ident.name);
|
||||
if name.is_none() {
|
||||
|
|
|
@ -368,7 +368,7 @@ fn parse_reg<'a>(
|
|||
explicit_reg: &mut bool,
|
||||
) -> Result<ast::InlineAsmRegOrRegClass, DiagnosticBuilder<'a>> {
|
||||
p.expect(&token::OpenDelim(token::DelimToken::Paren))?;
|
||||
let result = match p.token.kind {
|
||||
let result = match p.token.uninterpolate().kind {
|
||||
token::Ident(name, false) => ast::InlineAsmRegOrRegClass::RegClass(name),
|
||||
token::Literal(token::Lit { kind: token::LitKind::Str, symbol, suffix: _ }) => {
|
||||
*explicit_reg = true;
|
||||
|
|
|
@ -15,7 +15,7 @@ pub fn inject(mut krate: ast::Crate, parse_sess: &ParseSess, attrs: &[String]) -
|
|||
);
|
||||
|
||||
let start_span = parser.token.span;
|
||||
let AttrItem { path, args } = match parser.parse_attr_item() {
|
||||
let AttrItem { path, args, tokens: _ } = match parser.parse_attr_item() {
|
||||
Ok(ai) => ai,
|
||||
Err(mut err) => {
|
||||
err.emit();
|
||||
|
|
|
@ -27,15 +27,15 @@ pub fn expand_concat_idents<'cx>(
|
|||
}
|
||||
}
|
||||
} else {
|
||||
match e {
|
||||
TokenTree::Token(Token { kind: token::Ident(name, _), .. }) => {
|
||||
res_str.push_str(&name.as_str())
|
||||
}
|
||||
_ => {
|
||||
cx.span_err(sp, "concat_idents! requires ident args.");
|
||||
return DummyResult::any(sp);
|
||||
if let TokenTree::Token(token) = e {
|
||||
if let Some((ident, _)) = token.ident() {
|
||||
res_str.push_str(&ident.name.as_str());
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
cx.span_err(sp, "concat_idents! requires ident args.");
|
||||
return DummyResult::any(sp);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -61,6 +61,7 @@ pub fn expand_concat_idents<'cx>(
|
|||
id: ast::DUMMY_NODE_ID,
|
||||
kind: ast::TyKind::Path(None, ast::Path::from_ident(self.ident)),
|
||||
span: self.ident.span,
|
||||
tokens: None,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -133,5 +133,5 @@ fn stmt_let_underscore(cx: &mut ExtCtxt<'_>, sp: Span, expr: P<ast::Expr>) -> as
|
|||
span: sp,
|
||||
attrs: ast::AttrVec::new(),
|
||||
});
|
||||
ast::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Local(local), span: sp }
|
||||
ast::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Local(local), span: sp, tokens: None }
|
||||
}
|
||||
|
|
|
@ -187,7 +187,6 @@ use rustc_ast::{GenericArg, GenericParamKind, VariantData};
|
|||
use rustc_attr as attr;
|
||||
use rustc_data_structures::map_in_place::MapInPlace;
|
||||
use rustc_expand::base::{Annotatable, ExtCtxt};
|
||||
use rustc_span::source_map::respan;
|
||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||
use rustc_span::Span;
|
||||
|
||||
|
@ -532,7 +531,11 @@ impl<'a> TraitDef<'a> {
|
|||
id: ast::DUMMY_NODE_ID,
|
||||
span: self.span,
|
||||
ident,
|
||||
vis: respan(self.span.shrink_to_lo(), ast::VisibilityKind::Inherited),
|
||||
vis: ast::Visibility {
|
||||
span: self.span.shrink_to_lo(),
|
||||
kind: ast::VisibilityKind::Inherited,
|
||||
tokens: None,
|
||||
},
|
||||
attrs: Vec::new(),
|
||||
kind: ast::AssocItemKind::TyAlias(
|
||||
ast::Defaultness::Final,
|
||||
|
@ -933,7 +936,11 @@ impl<'a> MethodDef<'a> {
|
|||
id: ast::DUMMY_NODE_ID,
|
||||
attrs: self.attributes.clone(),
|
||||
span: trait_.span,
|
||||
vis: respan(trait_lo_sp, ast::VisibilityKind::Inherited),
|
||||
vis: ast::Visibility {
|
||||
span: trait_lo_sp,
|
||||
kind: ast::VisibilityKind::Inherited,
|
||||
tokens: None,
|
||||
},
|
||||
ident: method_ident,
|
||||
kind: ast::AssocItemKind::Fn(def, sig, fn_generics, Some(body_block)),
|
||||
tokens: None,
|
||||
|
@ -1522,7 +1529,7 @@ impl<'a> TraitDef<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
let is_tuple = if let ast::VariantData::Tuple(..) = struct_def { true } else { false };
|
||||
let is_tuple = matches!(struct_def, ast::VariantData::Tuple(..));
|
||||
match (just_spans.is_empty(), named_idents.is_empty()) {
|
||||
(false, false) => cx.span_bug(
|
||||
self.span,
|
||||
|
|
|
@ -75,6 +75,7 @@ fn call_intrinsic(
|
|||
id: ast::DUMMY_NODE_ID,
|
||||
rules: ast::BlockCheckMode::Unsafe(ast::CompilerGenerated),
|
||||
span,
|
||||
tokens: None,
|
||||
}))
|
||||
}
|
||||
|
||||
|
|
|
@ -543,9 +543,12 @@ impl<'a, 'b> Context<'a, 'b> {
|
|||
let idx = self.args.len();
|
||||
self.arg_types.push(Vec::new());
|
||||
self.arg_unique_types.push(Vec::new());
|
||||
self.args.push(
|
||||
self.ecx.expr_ident(self.fmtsp, Ident::new(name, self.fmtsp)),
|
||||
);
|
||||
let span = if self.is_literal {
|
||||
*self.arg_spans.get(self.curpiece).unwrap_or(&self.fmtsp)
|
||||
} else {
|
||||
self.fmtsp
|
||||
};
|
||||
self.args.push(self.ecx.expr_ident(span, Ident::new(name, span)));
|
||||
self.names.insert(name, idx);
|
||||
self.verify_arg_type(Exact(idx), ty)
|
||||
} else {
|
||||
|
|
|
@ -166,14 +166,14 @@ pub mod printf {
|
|||
let cap = self.span.len() + if has_options { 2 } else { 0 };
|
||||
let mut s = String::with_capacity(cap);
|
||||
|
||||
s.push_str("{");
|
||||
s.push('{');
|
||||
|
||||
if let Some(arg) = self.parameter {
|
||||
write!(s, "{}", arg.checked_sub(1)?).ok()?;
|
||||
}
|
||||
|
||||
if has_options {
|
||||
s.push_str(":");
|
||||
s.push(':');
|
||||
|
||||
let align = if let Some(fill) = fill {
|
||||
s.push_str(fill);
|
||||
|
@ -191,11 +191,11 @@ pub mod printf {
|
|||
}
|
||||
|
||||
if alt {
|
||||
s.push_str("#");
|
||||
s.push('#');
|
||||
}
|
||||
|
||||
if zero_fill {
|
||||
s.push_str("0");
|
||||
s.push('0');
|
||||
}
|
||||
|
||||
if let Some(width) = width {
|
||||
|
@ -203,7 +203,7 @@ pub mod printf {
|
|||
}
|
||||
|
||||
if let Some(precision) = precision {
|
||||
s.push_str(".");
|
||||
s.push('.');
|
||||
precision.translate(&mut s).ok()?;
|
||||
}
|
||||
|
||||
|
@ -212,7 +212,7 @@ pub mod printf {
|
|||
}
|
||||
}
|
||||
|
||||
s.push_str("}");
|
||||
s.push('}');
|
||||
Some(s)
|
||||
}
|
||||
}
|
||||
|
@ -518,8 +518,7 @@ pub mod printf {
|
|||
.and_then(|end| end.at_next_cp())
|
||||
.map(|end| (next.slice_between(end).unwrap(), end));
|
||||
let end = match end {
|
||||
Some(("32", end)) => end,
|
||||
Some(("64", end)) => end,
|
||||
Some(("32" | "64", end)) => end,
|
||||
_ => next,
|
||||
};
|
||||
state = Type;
|
||||
|
|
|
@ -14,7 +14,6 @@ use rustc_ast::token;
|
|||
use rustc_ast::tokenstream::TokenStream;
|
||||
use rustc_errors::DiagnosticBuilder;
|
||||
use rustc_expand::base::{self, *};
|
||||
use rustc_span::source_map::respan;
|
||||
use rustc_span::symbol::Ident;
|
||||
use rustc_span::Span;
|
||||
use smallvec::smallvec;
|
||||
|
@ -30,7 +29,11 @@ pub fn expand_global_asm<'cx>(
|
|||
attrs: Vec::new(),
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
kind: ast::ItemKind::GlobalAsm(P(global_asm)),
|
||||
vis: respan(sp.shrink_to_lo(), ast::VisibilityKind::Inherited),
|
||||
vis: ast::Visibility {
|
||||
span: sp.shrink_to_lo(),
|
||||
kind: ast::VisibilityKind::Inherited,
|
||||
tokens: None,
|
||||
},
|
||||
span: cx.with_def_site_ctxt(sp),
|
||||
tokens: None,
|
||||
})]),
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//! This crate contains implementations of built-in macros and other code generating facilities
|
||||
//! injecting code into the crate before it is lowered to HIR.
|
||||
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![feature(bool_to_option)]
|
||||
#![feature(crate_visibility_modifier)]
|
||||
#![feature(decl_macro)]
|
||||
|
|
|
@ -98,7 +98,7 @@ pub fn inject(
|
|||
|
||||
impl<'a> CollectProcMacros<'a> {
|
||||
fn check_not_pub_in_root(&self, vis: &ast::Visibility, sp: Span) {
|
||||
if self.is_proc_macro_crate && self.in_root && vis.node.is_pub() {
|
||||
if self.is_proc_macro_crate && self.in_root && vis.kind.is_pub() {
|
||||
self.handler.span_err(
|
||||
sp,
|
||||
"`proc-macro` crate types currently cannot export any items other \
|
||||
|
@ -184,7 +184,7 @@ impl<'a> CollectProcMacros<'a> {
|
|||
Vec::new()
|
||||
};
|
||||
|
||||
if self.in_root && item.vis.node.is_pub() {
|
||||
if self.in_root && item.vis.kind.is_pub() {
|
||||
self.macros.push(ProcMacro::Derive(ProcMacroDerive {
|
||||
id: item.id,
|
||||
span: item.span,
|
||||
|
@ -204,7 +204,7 @@ impl<'a> CollectProcMacros<'a> {
|
|||
}
|
||||
|
||||
fn collect_attr_proc_macro(&mut self, item: &'a ast::Item) {
|
||||
if self.in_root && item.vis.node.is_pub() {
|
||||
if self.in_root && item.vis.kind.is_pub() {
|
||||
self.macros.push(ProcMacro::Def(ProcMacroDef {
|
||||
id: item.id,
|
||||
span: item.span,
|
||||
|
@ -223,7 +223,7 @@ impl<'a> CollectProcMacros<'a> {
|
|||
}
|
||||
|
||||
fn collect_bang_proc_macro(&mut self, item: &'a ast::Item) {
|
||||
if self.in_root && item.vis.node.is_pub() {
|
||||
if self.in_root && item.vis.kind.is_pub() {
|
||||
self.macros.push(ProcMacro::Def(ProcMacroDef {
|
||||
id: item.id,
|
||||
span: item.span,
|
||||
|
|
|
@ -7,7 +7,6 @@ use rustc_ast::attr;
|
|||
use rustc_ast_pretty::pprust;
|
||||
use rustc_expand::base::*;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::source_map::respan;
|
||||
use rustc_span::symbol::{sym, Ident, Symbol};
|
||||
use rustc_span::Span;
|
||||
|
||||
|
@ -35,7 +34,11 @@ pub fn expand_test_case(
|
|||
let sp = ecx.with_def_site_ctxt(attr_sp);
|
||||
let mut item = anno_item.expect_item();
|
||||
item = item.map(|mut item| {
|
||||
item.vis = respan(item.vis.span, ast::VisibilityKind::Public);
|
||||
item.vis = ast::Visibility {
|
||||
span: item.vis.span,
|
||||
kind: ast::VisibilityKind::Public,
|
||||
tokens: None,
|
||||
};
|
||||
item.ident.span = item.ident.span.with_ctxt(sp.ctxt());
|
||||
item.attrs.push(ecx.attribute(ecx.meta_word(sp, sym::rustc_test_marker)));
|
||||
item
|
||||
|
@ -292,7 +295,7 @@ pub fn expand_test_or_bench(
|
|||
),
|
||||
);
|
||||
test_const = test_const.map(|mut tc| {
|
||||
tc.vis.node = ast::VisibilityKind::Public;
|
||||
tc.vis.kind = ast::VisibilityKind::Public;
|
||||
tc
|
||||
});
|
||||
|
||||
|
|
|
@ -10,7 +10,6 @@ use rustc_expand::expand::{AstFragment, ExpansionConfig};
|
|||
use rustc_feature::Features;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::hygiene::{AstPass, SyntaxContext, Transparency};
|
||||
use rustc_span::source_map::respan;
|
||||
use rustc_span::symbol::{sym, Ident, Symbol};
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
use rustc_target::spec::PanicStrategy;
|
||||
|
@ -333,7 +332,7 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
|
|||
attrs: vec![main_attr],
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
kind: main,
|
||||
vis: respan(sp, ast::VisibilityKind::Public),
|
||||
vis: ast::Visibility { span: sp, kind: ast::VisibilityKind::Public, tokens: None },
|
||||
span: sp,
|
||||
tokens: None,
|
||||
});
|
||||
|
|
|
@ -25,7 +25,7 @@ rustc_fs_util = { path = "../rustc_fs_util" }
|
|||
rustc_hir = { path = "../rustc_hir" }
|
||||
rustc_incremental = { path = "../rustc_incremental" }
|
||||
rustc_index = { path = "../rustc_index" }
|
||||
rustc_llvm = { path = "../../src/librustc_llvm" }
|
||||
rustc_llvm = { path = "../rustc_llvm" }
|
||||
rustc_session = { path = "../rustc_session" }
|
||||
rustc_serialize = { path = "../rustc_serialize" }
|
||||
rustc_target = { path = "../rustc_target" }
|
||||
|
|
|
@ -3,11 +3,17 @@ use libc::c_uint;
|
|||
use rustc_ast::expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_span::symbol::sym;
|
||||
|
||||
use crate::llvm::{self, False, True};
|
||||
use crate::ModuleLlvm;
|
||||
|
||||
pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut ModuleLlvm, kind: AllocatorKind) {
|
||||
pub(crate) unsafe fn codegen(
|
||||
tcx: TyCtxt<'_>,
|
||||
mods: &mut ModuleLlvm,
|
||||
kind: AllocatorKind,
|
||||
has_alloc_error_handler: bool,
|
||||
) {
|
||||
let llcx = &*mods.llcx;
|
||||
let llmod = mods.llmod();
|
||||
let usize = match &tcx.sess.target.target.target_pointer_width[..] {
|
||||
|
@ -82,4 +88,41 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut ModuleLlvm, kind: Alloc
|
|||
}
|
||||
llvm::LLVMDisposeBuilder(llbuilder);
|
||||
}
|
||||
|
||||
// rust alloc error handler
|
||||
let args = [usize, usize]; // size, align
|
||||
|
||||
let ty = llvm::LLVMFunctionType(void, args.as_ptr(), args.len() as c_uint, False);
|
||||
let name = format!("__rust_alloc_error_handler");
|
||||
let llfn = llvm::LLVMRustGetOrInsertFunction(llmod, name.as_ptr().cast(), name.len(), ty);
|
||||
// -> ! DIFlagNoReturn
|
||||
llvm::Attribute::NoReturn.apply_llfn(llvm::AttributePlace::Function, llfn);
|
||||
|
||||
if tcx.sess.target.target.options.default_hidden_visibility {
|
||||
llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden);
|
||||
}
|
||||
if tcx.sess.must_emit_unwind_tables() {
|
||||
attributes::emit_uwtable(llfn, true);
|
||||
}
|
||||
|
||||
let kind = if has_alloc_error_handler { AllocatorKind::Global } else { AllocatorKind::Default };
|
||||
let callee = kind.fn_name(sym::oom);
|
||||
let callee = llvm::LLVMRustGetOrInsertFunction(llmod, callee.as_ptr().cast(), callee.len(), ty);
|
||||
// -> ! DIFlagNoReturn
|
||||
llvm::Attribute::NoReturn.apply_llfn(llvm::AttributePlace::Function, callee);
|
||||
llvm::LLVMRustSetVisibility(callee, llvm::Visibility::Hidden);
|
||||
|
||||
let llbb = llvm::LLVMAppendBasicBlockInContext(llcx, llfn, "entry\0".as_ptr().cast());
|
||||
|
||||
let llbuilder = llvm::LLVMCreateBuilderInContext(llcx);
|
||||
llvm::LLVMPositionBuilderAtEnd(llbuilder, llbb);
|
||||
let args = args
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(i, _)| llvm::LLVMGetParam(llfn, i as c_uint))
|
||||
.collect::<Vec<_>>();
|
||||
let ret = llvm::LLVMRustBuildCall(llbuilder, callee, args.as_ptr(), args.len() as c_uint, None);
|
||||
llvm::LLVMSetTailCall(ret, True);
|
||||
llvm::LLVMBuildRetVoid(llbuilder);
|
||||
llvm::LLVMDisposeBuilder(llbuilder);
|
||||
}
|
||||
|
|
|
@ -259,6 +259,7 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => {}
|
||||
InlineAsmArch::Nvptx64 => {}
|
||||
InlineAsmArch::Hexagon => {}
|
||||
InlineAsmArch::Mips => {}
|
||||
}
|
||||
}
|
||||
if !options.contains(InlineAsmOptions::NOMEM) {
|
||||
|
@ -505,6 +506,8 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'tcx>>)
|
|||
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg)
|
||||
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg) => "w",
|
||||
InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => "r",
|
||||
InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => "r",
|
||||
InlineAsmRegClass::Mips(MipsInlineAsmRegClass::freg) => "f",
|
||||
InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg16) => "h",
|
||||
InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg32) => "r",
|
||||
InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg64) => "l",
|
||||
|
@ -551,6 +554,7 @@ fn modifier_to_llvm(
|
|||
}
|
||||
}
|
||||
InlineAsmRegClass::Hexagon(_) => None,
|
||||
InlineAsmRegClass::Mips(_) => None,
|
||||
InlineAsmRegClass::Nvptx(_) => None,
|
||||
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg)
|
||||
| InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => None,
|
||||
|
@ -603,6 +607,8 @@ fn dummy_output_type(cx: &CodegenCx<'ll, 'tcx>, reg: InlineAsmRegClass) -> &'ll
|
|||
cx.type_vector(cx.type_i64(), 2)
|
||||
}
|
||||
InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => cx.type_i32(),
|
||||
InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => cx.type_i32(),
|
||||
InlineAsmRegClass::Mips(MipsInlineAsmRegClass::freg) => cx.type_f32(),
|
||||
InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg16) => cx.type_i16(),
|
||||
InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg32) => cx.type_i32(),
|
||||
InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg64) => cx.type_i64(),
|
||||
|
@ -700,6 +706,12 @@ fn llvm_fixup_input(
|
|||
value
|
||||
}
|
||||
}
|
||||
(InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg), Abi::Scalar(s)) => match s.value {
|
||||
// MIPS only supports register-length arithmetics.
|
||||
Primitive::Int(Integer::I8 | Integer::I16, _) => bx.zext(value, bx.cx.type_i32()),
|
||||
Primitive::F32 => bx.bitcast(value, bx.cx.type_i32()),
|
||||
_ => value,
|
||||
},
|
||||
_ => value,
|
||||
}
|
||||
}
|
||||
|
@ -768,6 +780,13 @@ fn llvm_fixup_output(
|
|||
value
|
||||
}
|
||||
}
|
||||
(InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg), Abi::Scalar(s)) => match s.value {
|
||||
// MIPS only supports register-length arithmetics.
|
||||
Primitive::Int(Integer::I8, _) => bx.trunc(value, bx.cx.type_i8()),
|
||||
Primitive::Int(Integer::I16, _) => bx.trunc(value, bx.cx.type_i16()),
|
||||
Primitive::F32 => bx.bitcast(value, bx.cx.type_f32()),
|
||||
_ => value,
|
||||
},
|
||||
_ => value,
|
||||
}
|
||||
}
|
||||
|
@ -831,6 +850,12 @@ fn llvm_fixup_output_type(
|
|||
layout.llvm_type(cx)
|
||||
}
|
||||
}
|
||||
(InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg), Abi::Scalar(s)) => match s.value {
|
||||
// MIPS only supports register-length arithmetics.
|
||||
Primitive::Int(Integer::I8 | Integer::I16, _) => cx.type_i32(),
|
||||
Primitive::F32 => cx.type_i32(),
|
||||
_ => layout.llvm_type(cx),
|
||||
},
|
||||
_ => layout.llvm_type(cx),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -294,6 +294,9 @@ pub fn from_fn_attrs(cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, instance: ty::
|
|||
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::ALLOCATOR) {
|
||||
Attribute::NoAlias.apply_llfn(llvm::AttributePlace::ReturnValue, llfn);
|
||||
}
|
||||
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::CMSE_NONSECURE_ENTRY) {
|
||||
llvm::AddFunctionAttrString(llfn, Function, const_cstr!("cmse_nonsecure_entry"));
|
||||
}
|
||||
sanitize(cx, codegen_fn_attrs.no_sanitize, llfn);
|
||||
|
||||
// Always annotate functions with the target-cpu they are compiled for.
|
||||
|
@ -346,17 +349,15 @@ pub fn from_fn_attrs(cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, instance: ty::
|
|||
}
|
||||
|
||||
pub fn provide(providers: &mut Providers) {
|
||||
use rustc_codegen_ssa::target_features::{all_known_features, supported_target_features};
|
||||
providers.supported_target_features = |tcx, cnum| {
|
||||
assert_eq!(cnum, LOCAL_CRATE);
|
||||
if tcx.sess.opts.actually_rustdoc {
|
||||
// rustdoc needs to be able to document functions that use all the features, so
|
||||
// provide them all.
|
||||
llvm_util::all_known_features().map(|(a, b)| (a.to_string(), b)).collect()
|
||||
all_known_features().map(|(a, b)| (a.to_string(), b)).collect()
|
||||
} else {
|
||||
llvm_util::supported_target_features(tcx.sess)
|
||||
.iter()
|
||||
.map(|&(a, b)| (a.to_string(), b))
|
||||
.collect()
|
||||
supported_target_features(tcx.sess).iter().map(|&(a, b)| (a.to_string(), b)).collect()
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -346,14 +346,14 @@ fn fat_lto(
|
|||
Ok(LtoModuleCodegen::Fat { module: Some(module), _serialized_bitcode: serialized_bitcode })
|
||||
}
|
||||
|
||||
struct Linker<'a>(&'a mut llvm::Linker<'a>);
|
||||
crate struct Linker<'a>(&'a mut llvm::Linker<'a>);
|
||||
|
||||
impl Linker<'a> {
|
||||
fn new(llmod: &'a llvm::Module) -> Self {
|
||||
crate fn new(llmod: &'a llvm::Module) -> Self {
|
||||
unsafe { Linker(llvm::LLVMRustLinkerNew(llmod)) }
|
||||
}
|
||||
|
||||
fn add(&mut self, bytecode: &[u8]) -> Result<(), ()> {
|
||||
crate fn add(&mut self, bytecode: &[u8]) -> Result<(), ()> {
|
||||
unsafe {
|
||||
if llvm::LLVMRustLinkerAdd(
|
||||
self.0,
|
||||
|
|
|
@ -344,6 +344,13 @@ unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void
|
|||
.expect("non-UTF8 diagnostic");
|
||||
diag_handler.warn(&msg);
|
||||
}
|
||||
llvm::diagnostic::Unsupported(diagnostic_ref) => {
|
||||
let msg = llvm::build_string(|s| {
|
||||
llvm::LLVMRustWriteDiagnosticInfoToString(diagnostic_ref, s)
|
||||
})
|
||||
.expect("non-UTF8 diagnostic");
|
||||
diag_handler.err(&msg);
|
||||
}
|
||||
llvm::diagnostic::UnknownDiagnostic(..) => {}
|
||||
}
|
||||
}
|
||||
|
@ -617,6 +624,31 @@ unsafe fn add_sanitizer_passes(config: &ModuleConfig, passes: &mut Vec<&'static
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn link(
|
||||
cgcx: &CodegenContext<LlvmCodegenBackend>,
|
||||
diag_handler: &Handler,
|
||||
mut modules: Vec<ModuleCodegen<ModuleLlvm>>,
|
||||
) -> Result<ModuleCodegen<ModuleLlvm>, FatalError> {
|
||||
use super::lto::{Linker, ModuleBuffer};
|
||||
// Sort the modules by name to ensure to ensure deterministic behavior.
|
||||
modules.sort_by(|a, b| a.name.cmp(&b.name));
|
||||
let (first, elements) =
|
||||
modules.split_first().expect("Bug! modules must contain at least one module.");
|
||||
|
||||
let mut linker = Linker::new(first.module_llvm.llmod());
|
||||
for module in elements {
|
||||
let _timer =
|
||||
cgcx.prof.generic_activity_with_arg("LLVM_link_module", format!("{:?}", module.name));
|
||||
let buffer = ModuleBuffer::new(module.module_llvm.llmod());
|
||||
linker.add(&buffer.data()).map_err(|()| {
|
||||
let msg = format!("failed to serialize module {:?}", module.name);
|
||||
llvm_err(&diag_handler, &msg)
|
||||
})?;
|
||||
}
|
||||
drop(linker);
|
||||
Ok(modules.remove(0))
|
||||
}
|
||||
|
||||
pub(crate) unsafe fn codegen(
|
||||
cgcx: &CodegenContext<LlvmCodegenBackend>,
|
||||
diag_handler: &Handler,
|
||||
|
|
|
@ -108,7 +108,7 @@ pub fn compile_codegen_unit(
|
|||
|
||||
// We assume that the cost to run LLVM on a CGU is proportional to
|
||||
// the time we needed for codegenning it.
|
||||
let cost = time_to_codegen.as_secs() * 1_000_000_000 + time_to_codegen.subsec_nanos() as u64;
|
||||
let cost = time_to_codegen.as_nanos() as u64;
|
||||
|
||||
fn module_codegen(tcx: TyCtxt<'_>, cgu_name: Symbol) -> ModuleCodegen<ModuleLlvm> {
|
||||
let cgu = tcx.codegen_unit(cgu_name);
|
||||
|
|
|
@ -21,7 +21,6 @@ use rustc_target::abi::{self, Align, Size};
|
|||
use rustc_target::spec::{HasTargetSpec, Target};
|
||||
use std::borrow::Cow;
|
||||
use std::ffi::CStr;
|
||||
use std::iter::TrustedLen;
|
||||
use std::ops::{Deref, Range};
|
||||
use std::ptr;
|
||||
use tracing::debug;
|
||||
|
@ -179,7 +178,7 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
&mut self,
|
||||
v: &'ll Value,
|
||||
else_llbb: &'ll BasicBlock,
|
||||
cases: impl ExactSizeIterator<Item = (u128, &'ll BasicBlock)> + TrustedLen,
|
||||
cases: impl ExactSizeIterator<Item = (u128, &'ll BasicBlock)>,
|
||||
) {
|
||||
let switch =
|
||||
unsafe { llvm::LLVMBuildSwitch(self.llbuilder, v, else_llbb, cases.len() as c_uint) };
|
||||
|
@ -931,7 +930,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
unsafe { llvm::LLVMBuildSelect(self.llbuilder, cond, then_val, else_val, UNNAMED) }
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn va_arg(&mut self, list: &'ll Value, ty: &'ll Type) -> &'ll Value {
|
||||
unsafe { llvm::LLVMBuildVAArg(self.llbuilder, list, ty, UNNAMED) }
|
||||
}
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
#![allow(non_camel_case_types, non_snake_case)]
|
||||
|
||||
//! Code that is useful in various codegen modules.
|
||||
|
||||
use crate::consts::{self, const_alloc_to_llvm};
|
||||
|
|
|
@ -7,12 +7,13 @@ use crate::type_of::LayoutLlvmExt;
|
|||
use crate::value::Value;
|
||||
use libc::c_uint;
|
||||
use rustc_codegen_ssa::traits::*;
|
||||
use rustc_data_structures::const_cstr;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::Node;
|
||||
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
|
||||
use rustc_middle::mir::interpret::{
|
||||
read_target_uint, Allocation, ConstValue, ErrorHandled, GlobalAlloc, Pointer,
|
||||
read_target_uint, Allocation, ErrorHandled, GlobalAlloc, Pointer,
|
||||
};
|
||||
use rustc_middle::mir::mono::MonoItem;
|
||||
use rustc_middle::ty::{self, Instance, Ty};
|
||||
|
@ -22,8 +23,6 @@ use rustc_span::Span;
|
|||
use rustc_target::abi::{AddressSpace, Align, HasDataLayout, LayoutOf, Primitive, Scalar, Size};
|
||||
use tracing::debug;
|
||||
|
||||
use std::ffi::CStr;
|
||||
|
||||
pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll Value {
|
||||
let mut llvals = Vec::with_capacity(alloc.relocations().len() + 1);
|
||||
let dl = cx.data_layout();
|
||||
|
@ -85,10 +84,7 @@ pub fn codegen_static_initializer(
|
|||
cx: &CodegenCx<'ll, 'tcx>,
|
||||
def_id: DefId,
|
||||
) -> Result<(&'ll Value, &'tcx Allocation), ErrorHandled> {
|
||||
let alloc = match cx.tcx.const_eval_poly(def_id)? {
|
||||
ConstValue::ByRef { alloc, offset } if offset.bytes() == 0 => alloc,
|
||||
val => bug!("static const eval returned {:#?}", val),
|
||||
};
|
||||
let alloc = cx.tcx.eval_static_initializer(def_id)?;
|
||||
Ok((const_alloc_to_llvm(cx, alloc), alloc))
|
||||
}
|
||||
|
||||
|
@ -457,9 +453,9 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> {
|
|||
.all(|&byte| byte == 0);
|
||||
|
||||
let sect_name = if all_bytes_are_zero {
|
||||
CStr::from_bytes_with_nul_unchecked(b"__DATA,__thread_bss\0")
|
||||
const_cstr!("__DATA,__thread_bss")
|
||||
} else {
|
||||
CStr::from_bytes_with_nul_unchecked(b"__DATA,__thread_data\0")
|
||||
const_cstr!("__DATA,__thread_data")
|
||||
};
|
||||
llvm::LLVMSetSection(g, sect_name.as_ptr());
|
||||
}
|
||||
|
|
|
@ -433,6 +433,17 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
|||
llvm::LLVMSetSection(g, section.as_ptr());
|
||||
}
|
||||
}
|
||||
|
||||
fn declare_c_main(&self, fn_type: Self::Type) -> Option<Self::Function> {
|
||||
if self.get_declared_value("main").is_none() {
|
||||
Some(self.declare_cfn("main", fn_type))
|
||||
} else {
|
||||
// If the symbol already exists, it is an error: for example, the user wrote
|
||||
// #[no_mangle] extern "C" fn main(..) {..}
|
||||
// instead of #[start]
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl CodegenCx<'b, 'tcx> {
|
||||
|
|
|
@ -126,6 +126,7 @@ impl CoverageMapGenerator {
|
|||
let (filenames_index, _) = self.filenames.insert_full(c_filename);
|
||||
virtual_file_mapping.push(filenames_index as u32);
|
||||
}
|
||||
debug!("Adding counter {:?} to map for {:?}", counter, region,);
|
||||
mapping_regions.push(CounterMappingRegion::code_region(
|
||||
counter,
|
||||
current_file_id,
|
||||
|
|
|
@ -1845,7 +1845,6 @@ impl<'tcx> VariantInfo<'_, 'tcx> {
|
|||
None
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn is_artificial(&self) -> bool {
|
||||
match self {
|
||||
VariantInfo::Generator { .. } => true,
|
||||
|
|
|
@ -27,11 +27,18 @@ pub fn item_namespace(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll DIScope {
|
|||
.parent
|
||||
.map(|parent| item_namespace(cx, DefId { krate: def_id.krate, index: parent }));
|
||||
|
||||
let crate_name_as_str;
|
||||
let name_to_string;
|
||||
let namespace_name = match def_key.disambiguated_data.data {
|
||||
DefPathData::CrateRoot => cx.tcx.crate_name(def_id.krate),
|
||||
data => data.as_symbol(),
|
||||
DefPathData::CrateRoot => {
|
||||
crate_name_as_str = cx.tcx.crate_name(def_id.krate).as_str();
|
||||
&*crate_name_as_str
|
||||
}
|
||||
data => {
|
||||
name_to_string = data.to_string();
|
||||
&*name_to_string
|
||||
}
|
||||
};
|
||||
let namespace_name = namespace_name.as_str();
|
||||
|
||||
let scope = unsafe {
|
||||
llvm::LLVMRustDIBuilderCreateNameSpace(
|
||||
|
|
|
@ -51,17 +51,32 @@ fn declare_raw_fn(
|
|||
llfn
|
||||
}
|
||||
|
||||
impl DeclareMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||
fn declare_global(&self, name: &str, ty: &'ll Type) -> &'ll Value {
|
||||
impl CodegenCx<'ll, 'tcx> {
|
||||
/// Declare a global value.
|
||||
///
|
||||
/// If there’s a value with the same name already declared, the function will
|
||||
/// return its Value instead.
|
||||
pub fn declare_global(&self, name: &str, ty: &'ll Type) -> &'ll Value {
|
||||
debug!("declare_global(name={:?})", name);
|
||||
unsafe { llvm::LLVMRustGetOrInsertGlobal(self.llmod, name.as_ptr().cast(), name.len(), ty) }
|
||||
}
|
||||
|
||||
fn declare_cfn(&self, name: &str, fn_type: &'ll Type) -> &'ll Value {
|
||||
/// Declare a C ABI function.
|
||||
///
|
||||
/// Only use this for foreign function ABIs and glue. For Rust functions use
|
||||
/// `declare_fn` instead.
|
||||
///
|
||||
/// If there’s a value with the same name already declared, the function will
|
||||
/// update the declaration and return existing Value instead.
|
||||
pub fn declare_cfn(&self, name: &str, fn_type: &'ll Type) -> &'ll Value {
|
||||
declare_raw_fn(self, name, llvm::CCallConv, fn_type)
|
||||
}
|
||||
|
||||
fn declare_fn(&self, name: &str, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> &'ll Value {
|
||||
/// Declare a Rust function.
|
||||
///
|
||||
/// If there’s a value with the same name already declared, the function will
|
||||
/// update the declaration and return existing Value instead.
|
||||
pub fn declare_fn(&self, name: &str, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> &'ll Value {
|
||||
debug!("declare_rust_fn(name={:?}, fn_abi={:?})", name, fn_abi);
|
||||
|
||||
let llfn = declare_raw_fn(self, name, fn_abi.llvm_cconv(), fn_abi.llvm_type(self));
|
||||
|
@ -69,7 +84,13 @@ impl DeclareMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
|||
llfn
|
||||
}
|
||||
|
||||
fn define_global(&self, name: &str, ty: &'ll Type) -> Option<&'ll Value> {
|
||||
/// Declare a global with an intention to define it.
|
||||
///
|
||||
/// Use this function when you intend to define a global. This function will
|
||||
/// return `None` if the name already has a definition associated with it. In that
|
||||
/// case an error should be reported to the user, because it usually happens due
|
||||
/// to user’s fault (e.g., misuse of `#[no_mangle]` or `#[export_name]` attributes).
|
||||
pub fn define_global(&self, name: &str, ty: &'ll Type) -> Option<&'ll Value> {
|
||||
if self.get_defined_value(name).is_some() {
|
||||
None
|
||||
} else {
|
||||
|
@ -77,16 +98,22 @@ impl DeclareMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn define_private_global(&self, ty: &'ll Type) -> &'ll Value {
|
||||
/// Declare a private global
|
||||
///
|
||||
/// Use this function when you intend to define a global without a name.
|
||||
pub fn define_private_global(&self, ty: &'ll Type) -> &'ll Value {
|
||||
unsafe { llvm::LLVMRustInsertPrivateGlobal(self.llmod, ty) }
|
||||
}
|
||||
|
||||
fn get_declared_value(&self, name: &str) -> Option<&'ll Value> {
|
||||
/// Gets declared value by name.
|
||||
pub fn get_declared_value(&self, name: &str) -> Option<&'ll Value> {
|
||||
debug!("get_declared_value(name={:?})", name);
|
||||
unsafe { llvm::LLVMRustGetNamedValue(self.llmod, name.as_ptr().cast(), name.len()) }
|
||||
}
|
||||
|
||||
fn get_defined_value(&self, name: &str) -> Option<&'ll Value> {
|
||||
/// Gets defined or externally defined (AvailableExternally linkage) value by
|
||||
/// name.
|
||||
pub fn get_defined_value(&self, name: &str) -> Option<&'ll Value> {
|
||||
self.get_declared_value(name).and_then(|val| {
|
||||
let declaration = unsafe { llvm::LLVMIsDeclaration(val) != 0 };
|
||||
if !declaration { Some(val) } else { None }
|
||||
|
|
|
@ -7,15 +7,12 @@ use crate::type_of::LayoutLlvmExt;
|
|||
use crate::va_arg::emit_va_arg;
|
||||
use crate::value::Value;
|
||||
|
||||
use rustc_ast as ast;
|
||||
use rustc_codegen_ssa::base::{compare_simd_types, wants_msvc_seh};
|
||||
use rustc_codegen_ssa::common::span_invalid_monomorphization_error;
|
||||
use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
|
||||
use rustc_codegen_ssa::glue;
|
||||
use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
|
||||
use rustc_codegen_ssa::mir::operand::OperandRef;
|
||||
use rustc_codegen_ssa::mir::place::PlaceRef;
|
||||
use rustc_codegen_ssa::traits::*;
|
||||
use rustc_codegen_ssa::MemFlags;
|
||||
use rustc_hir as hir;
|
||||
use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt};
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
|
@ -71,8 +68,6 @@ fn get_simple_intrinsic(cx: &CodegenCx<'ll, '_>, name: Symbol) -> Option<&'ll Va
|
|||
sym::nearbyintf64 => "llvm.nearbyint.f64",
|
||||
sym::roundf32 => "llvm.round.f32",
|
||||
sym::roundf64 => "llvm.round.f64",
|
||||
sym::assume => "llvm.assume",
|
||||
sym::abort => "llvm.trap",
|
||||
_ => return None,
|
||||
};
|
||||
Some(cx.get_intrinsic(&llvm_name))
|
||||
|
@ -112,9 +107,6 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
&args.iter().map(|arg| arg.immediate()).collect::<Vec<_>>(),
|
||||
None,
|
||||
),
|
||||
sym::unreachable => {
|
||||
return;
|
||||
}
|
||||
sym::likely => {
|
||||
let expect = self.get_intrinsic(&("llvm.expect.i1"));
|
||||
self.call(expect, &[args[0].immediate(), self.const_bool(true)], None)
|
||||
|
@ -137,8 +129,6 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
let llfn = self.get_intrinsic(&("llvm.debugtrap"));
|
||||
self.call(llfn, &[], None)
|
||||
}
|
||||
sym::va_start => self.va_start(args[0].immediate()),
|
||||
sym::va_end => self.va_end(args[0].immediate()),
|
||||
sym::va_copy => {
|
||||
let intrinsic = self.cx().get_intrinsic(&("llvm.va_copy"));
|
||||
self.call(intrinsic, &[args[0].immediate(), args[1].immediate()], None)
|
||||
|
@ -169,123 +159,7 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
_ => bug!("the va_arg intrinsic does not work with non-scalar types"),
|
||||
}
|
||||
}
|
||||
sym::size_of_val => {
|
||||
let tp_ty = substs.type_at(0);
|
||||
if let OperandValue::Pair(_, meta) = args[0].val {
|
||||
let (llsize, _) = glue::size_and_align_of_dst(self, tp_ty, Some(meta));
|
||||
llsize
|
||||
} else {
|
||||
self.const_usize(self.size_of(tp_ty).bytes())
|
||||
}
|
||||
}
|
||||
sym::min_align_of_val => {
|
||||
let tp_ty = substs.type_at(0);
|
||||
if let OperandValue::Pair(_, meta) = args[0].val {
|
||||
let (_, llalign) = glue::size_and_align_of_dst(self, tp_ty, Some(meta));
|
||||
llalign
|
||||
} else {
|
||||
self.const_usize(self.align_of(tp_ty).bytes())
|
||||
}
|
||||
}
|
||||
sym::size_of
|
||||
| sym::pref_align_of
|
||||
| sym::min_align_of
|
||||
| sym::needs_drop
|
||||
| sym::type_id
|
||||
| sym::type_name
|
||||
| sym::variant_count => {
|
||||
let value = self
|
||||
.tcx
|
||||
.const_eval_instance(ty::ParamEnv::reveal_all(), instance, None)
|
||||
.unwrap();
|
||||
OperandRef::from_const(self, value, ret_ty).immediate_or_packed_pair(self)
|
||||
}
|
||||
// Effectively no-op
|
||||
sym::forget => {
|
||||
return;
|
||||
}
|
||||
sym::offset => {
|
||||
let ptr = args[0].immediate();
|
||||
let offset = args[1].immediate();
|
||||
self.inbounds_gep(ptr, &[offset])
|
||||
}
|
||||
sym::arith_offset => {
|
||||
let ptr = args[0].immediate();
|
||||
let offset = args[1].immediate();
|
||||
self.gep(ptr, &[offset])
|
||||
}
|
||||
|
||||
sym::copy_nonoverlapping => {
|
||||
copy_intrinsic(
|
||||
self,
|
||||
false,
|
||||
false,
|
||||
substs.type_at(0),
|
||||
args[1].immediate(),
|
||||
args[0].immediate(),
|
||||
args[2].immediate(),
|
||||
);
|
||||
return;
|
||||
}
|
||||
sym::copy => {
|
||||
copy_intrinsic(
|
||||
self,
|
||||
true,
|
||||
false,
|
||||
substs.type_at(0),
|
||||
args[1].immediate(),
|
||||
args[0].immediate(),
|
||||
args[2].immediate(),
|
||||
);
|
||||
return;
|
||||
}
|
||||
sym::write_bytes => {
|
||||
memset_intrinsic(
|
||||
self,
|
||||
false,
|
||||
substs.type_at(0),
|
||||
args[0].immediate(),
|
||||
args[1].immediate(),
|
||||
args[2].immediate(),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
sym::volatile_copy_nonoverlapping_memory => {
|
||||
copy_intrinsic(
|
||||
self,
|
||||
false,
|
||||
true,
|
||||
substs.type_at(0),
|
||||
args[0].immediate(),
|
||||
args[1].immediate(),
|
||||
args[2].immediate(),
|
||||
);
|
||||
return;
|
||||
}
|
||||
sym::volatile_copy_memory => {
|
||||
copy_intrinsic(
|
||||
self,
|
||||
true,
|
||||
true,
|
||||
substs.type_at(0),
|
||||
args[0].immediate(),
|
||||
args[1].immediate(),
|
||||
args[2].immediate(),
|
||||
);
|
||||
return;
|
||||
}
|
||||
sym::volatile_set_memory => {
|
||||
memset_intrinsic(
|
||||
self,
|
||||
true,
|
||||
substs.type_at(0),
|
||||
args[0].immediate(),
|
||||
args[1].immediate(),
|
||||
args[2].immediate(),
|
||||
);
|
||||
return;
|
||||
}
|
||||
sym::volatile_load | sym::unaligned_volatile_load => {
|
||||
let tp_ty = substs.type_at(0);
|
||||
let mut ptr = args[0].immediate();
|
||||
|
@ -343,20 +217,6 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
| sym::ctpop
|
||||
| sym::bswap
|
||||
| sym::bitreverse
|
||||
| sym::add_with_overflow
|
||||
| sym::sub_with_overflow
|
||||
| sym::mul_with_overflow
|
||||
| sym::wrapping_add
|
||||
| sym::wrapping_sub
|
||||
| sym::wrapping_mul
|
||||
| sym::unchecked_div
|
||||
| sym::unchecked_rem
|
||||
| sym::unchecked_shl
|
||||
| sym::unchecked_shr
|
||||
| sym::unchecked_add
|
||||
| sym::unchecked_sub
|
||||
| sym::unchecked_mul
|
||||
| sym::exact_div
|
||||
| sym::rotate_left
|
||||
| sym::rotate_right
|
||||
| sym::saturating_add
|
||||
|
@ -396,84 +256,6 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
&[args[0].immediate()],
|
||||
None,
|
||||
),
|
||||
sym::add_with_overflow
|
||||
| sym::sub_with_overflow
|
||||
| sym::mul_with_overflow => {
|
||||
let intrinsic = format!(
|
||||
"llvm.{}{}.with.overflow.i{}",
|
||||
if signed { 's' } else { 'u' },
|
||||
&name_str[..3],
|
||||
width
|
||||
);
|
||||
let llfn = self.get_intrinsic(&intrinsic);
|
||||
|
||||
// Convert `i1` to a `bool`, and write it to the out parameter
|
||||
let pair =
|
||||
self.call(llfn, &[args[0].immediate(), args[1].immediate()], None);
|
||||
let val = self.extract_value(pair, 0);
|
||||
let overflow = self.extract_value(pair, 1);
|
||||
let overflow = self.zext(overflow, self.type_bool());
|
||||
|
||||
let dest = result.project_field(self, 0);
|
||||
self.store(val, dest.llval, dest.align);
|
||||
let dest = result.project_field(self, 1);
|
||||
self.store(overflow, dest.llval, dest.align);
|
||||
|
||||
return;
|
||||
}
|
||||
sym::wrapping_add => self.add(args[0].immediate(), args[1].immediate()),
|
||||
sym::wrapping_sub => self.sub(args[0].immediate(), args[1].immediate()),
|
||||
sym::wrapping_mul => self.mul(args[0].immediate(), args[1].immediate()),
|
||||
sym::exact_div => {
|
||||
if signed {
|
||||
self.exactsdiv(args[0].immediate(), args[1].immediate())
|
||||
} else {
|
||||
self.exactudiv(args[0].immediate(), args[1].immediate())
|
||||
}
|
||||
}
|
||||
sym::unchecked_div => {
|
||||
if signed {
|
||||
self.sdiv(args[0].immediate(), args[1].immediate())
|
||||
} else {
|
||||
self.udiv(args[0].immediate(), args[1].immediate())
|
||||
}
|
||||
}
|
||||
sym::unchecked_rem => {
|
||||
if signed {
|
||||
self.srem(args[0].immediate(), args[1].immediate())
|
||||
} else {
|
||||
self.urem(args[0].immediate(), args[1].immediate())
|
||||
}
|
||||
}
|
||||
sym::unchecked_shl => self.shl(args[0].immediate(), args[1].immediate()),
|
||||
sym::unchecked_shr => {
|
||||
if signed {
|
||||
self.ashr(args[0].immediate(), args[1].immediate())
|
||||
} else {
|
||||
self.lshr(args[0].immediate(), args[1].immediate())
|
||||
}
|
||||
}
|
||||
sym::unchecked_add => {
|
||||
if signed {
|
||||
self.unchecked_sadd(args[0].immediate(), args[1].immediate())
|
||||
} else {
|
||||
self.unchecked_uadd(args[0].immediate(), args[1].immediate())
|
||||
}
|
||||
}
|
||||
sym::unchecked_sub => {
|
||||
if signed {
|
||||
self.unchecked_ssub(args[0].immediate(), args[1].immediate())
|
||||
} else {
|
||||
self.unchecked_usub(args[0].immediate(), args[1].immediate())
|
||||
}
|
||||
}
|
||||
sym::unchecked_mul => {
|
||||
if signed {
|
||||
self.unchecked_smul(args[0].immediate(), args[1].immediate())
|
||||
} else {
|
||||
self.unchecked_umul(args[0].immediate(), args[1].immediate())
|
||||
}
|
||||
}
|
||||
sym::rotate_left | sym::rotate_right => {
|
||||
let is_left = name == sym::rotate_left;
|
||||
let val = args[0].immediate();
|
||||
|
@ -513,75 +295,6 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
}
|
||||
}
|
||||
}
|
||||
sym::fadd_fast | sym::fsub_fast | sym::fmul_fast | sym::fdiv_fast | sym::frem_fast => {
|
||||
match float_type_width(arg_tys[0]) {
|
||||
Some(_width) => match name {
|
||||
sym::fadd_fast => self.fadd_fast(args[0].immediate(), args[1].immediate()),
|
||||
sym::fsub_fast => self.fsub_fast(args[0].immediate(), args[1].immediate()),
|
||||
sym::fmul_fast => self.fmul_fast(args[0].immediate(), args[1].immediate()),
|
||||
sym::fdiv_fast => self.fdiv_fast(args[0].immediate(), args[1].immediate()),
|
||||
sym::frem_fast => self.frem_fast(args[0].immediate(), args[1].immediate()),
|
||||
_ => bug!(),
|
||||
},
|
||||
None => {
|
||||
span_invalid_monomorphization_error(
|
||||
tcx.sess,
|
||||
span,
|
||||
&format!(
|
||||
"invalid monomorphization of `{}` intrinsic: \
|
||||
expected basic float type, found `{}`",
|
||||
name, arg_tys[0]
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sym::float_to_int_unchecked => {
|
||||
if float_type_width(arg_tys[0]).is_none() {
|
||||
span_invalid_monomorphization_error(
|
||||
tcx.sess,
|
||||
span,
|
||||
&format!(
|
||||
"invalid monomorphization of `float_to_int_unchecked` \
|
||||
intrinsic: expected basic float type, \
|
||||
found `{}`",
|
||||
arg_tys[0]
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
let (width, signed) = match int_type_width_signed(ret_ty, self.cx) {
|
||||
Some(pair) => pair,
|
||||
None => {
|
||||
span_invalid_monomorphization_error(
|
||||
tcx.sess,
|
||||
span,
|
||||
&format!(
|
||||
"invalid monomorphization of `float_to_int_unchecked` \
|
||||
intrinsic: expected basic integer type, \
|
||||
found `{}`",
|
||||
ret_ty
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
};
|
||||
if signed {
|
||||
self.fptosi(args[0].immediate(), self.cx.type_ix(width))
|
||||
} else {
|
||||
self.fptoui(args[0].immediate(), self.cx.type_ix(width))
|
||||
}
|
||||
}
|
||||
|
||||
sym::discriminant_value => {
|
||||
if ret_ty.is_integral() {
|
||||
args[0].deref(self.cx()).codegen_get_discr(self, ret_ty)
|
||||
} else {
|
||||
span_bug!(span, "Invalid discriminant type for `{:?}`", arg_tys[0])
|
||||
}
|
||||
}
|
||||
|
||||
_ if name_str.starts_with("simd_") => {
|
||||
match generic_simd_intrinsic(self, name, callee_ty, args, ret_ty, llret_ty, span) {
|
||||
|
@ -589,174 +302,6 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
Err(()) => return,
|
||||
}
|
||||
}
|
||||
// This requires that atomic intrinsics follow a specific naming pattern:
|
||||
// "atomic_<operation>[_<ordering>]", and no ordering means SeqCst
|
||||
name if name_str.starts_with("atomic_") => {
|
||||
use rustc_codegen_ssa::common::AtomicOrdering::*;
|
||||
use rustc_codegen_ssa::common::{AtomicRmwBinOp, SynchronizationScope};
|
||||
|
||||
let split: Vec<&str> = name_str.split('_').collect();
|
||||
|
||||
let is_cxchg = split[1] == "cxchg" || split[1] == "cxchgweak";
|
||||
let (order, failorder) = match split.len() {
|
||||
2 => (SequentiallyConsistent, SequentiallyConsistent),
|
||||
3 => match split[2] {
|
||||
"unordered" => (Unordered, Unordered),
|
||||
"relaxed" => (Monotonic, Monotonic),
|
||||
"acq" => (Acquire, Acquire),
|
||||
"rel" => (Release, Monotonic),
|
||||
"acqrel" => (AcquireRelease, Acquire),
|
||||
"failrelaxed" if is_cxchg => (SequentiallyConsistent, Monotonic),
|
||||
"failacq" if is_cxchg => (SequentiallyConsistent, Acquire),
|
||||
_ => self.sess().fatal("unknown ordering in atomic intrinsic"),
|
||||
},
|
||||
4 => match (split[2], split[3]) {
|
||||
("acq", "failrelaxed") if is_cxchg => (Acquire, Monotonic),
|
||||
("acqrel", "failrelaxed") if is_cxchg => (AcquireRelease, Monotonic),
|
||||
_ => self.sess().fatal("unknown ordering in atomic intrinsic"),
|
||||
},
|
||||
_ => self.sess().fatal("Atomic intrinsic not in correct format"),
|
||||
};
|
||||
|
||||
let invalid_monomorphization = |ty| {
|
||||
span_invalid_monomorphization_error(
|
||||
tcx.sess,
|
||||
span,
|
||||
&format!(
|
||||
"invalid monomorphization of `{}` intrinsic: \
|
||||
expected basic integer type, found `{}`",
|
||||
name, ty
|
||||
),
|
||||
);
|
||||
};
|
||||
|
||||
match split[1] {
|
||||
"cxchg" | "cxchgweak" => {
|
||||
let ty = substs.type_at(0);
|
||||
if int_type_width_signed(ty, self).is_some() {
|
||||
let weak = split[1] == "cxchgweak";
|
||||
let pair = self.atomic_cmpxchg(
|
||||
args[0].immediate(),
|
||||
args[1].immediate(),
|
||||
args[2].immediate(),
|
||||
order,
|
||||
failorder,
|
||||
weak,
|
||||
);
|
||||
let val = self.extract_value(pair, 0);
|
||||
let success = self.extract_value(pair, 1);
|
||||
let success = self.zext(success, self.type_bool());
|
||||
|
||||
let dest = result.project_field(self, 0);
|
||||
self.store(val, dest.llval, dest.align);
|
||||
let dest = result.project_field(self, 1);
|
||||
self.store(success, dest.llval, dest.align);
|
||||
return;
|
||||
} else {
|
||||
return invalid_monomorphization(ty);
|
||||
}
|
||||
}
|
||||
|
||||
"load" => {
|
||||
let ty = substs.type_at(0);
|
||||
if int_type_width_signed(ty, self).is_some() {
|
||||
let size = self.size_of(ty);
|
||||
self.atomic_load(args[0].immediate(), order, size)
|
||||
} else {
|
||||
return invalid_monomorphization(ty);
|
||||
}
|
||||
}
|
||||
|
||||
"store" => {
|
||||
let ty = substs.type_at(0);
|
||||
if int_type_width_signed(ty, self).is_some() {
|
||||
let size = self.size_of(ty);
|
||||
self.atomic_store(
|
||||
args[1].immediate(),
|
||||
args[0].immediate(),
|
||||
order,
|
||||
size,
|
||||
);
|
||||
return;
|
||||
} else {
|
||||
return invalid_monomorphization(ty);
|
||||
}
|
||||
}
|
||||
|
||||
"fence" => {
|
||||
self.atomic_fence(order, SynchronizationScope::CrossThread);
|
||||
return;
|
||||
}
|
||||
|
||||
"singlethreadfence" => {
|
||||
self.atomic_fence(order, SynchronizationScope::SingleThread);
|
||||
return;
|
||||
}
|
||||
|
||||
// These are all AtomicRMW ops
|
||||
op => {
|
||||
let atom_op = match op {
|
||||
"xchg" => AtomicRmwBinOp::AtomicXchg,
|
||||
"xadd" => AtomicRmwBinOp::AtomicAdd,
|
||||
"xsub" => AtomicRmwBinOp::AtomicSub,
|
||||
"and" => AtomicRmwBinOp::AtomicAnd,
|
||||
"nand" => AtomicRmwBinOp::AtomicNand,
|
||||
"or" => AtomicRmwBinOp::AtomicOr,
|
||||
"xor" => AtomicRmwBinOp::AtomicXor,
|
||||
"max" => AtomicRmwBinOp::AtomicMax,
|
||||
"min" => AtomicRmwBinOp::AtomicMin,
|
||||
"umax" => AtomicRmwBinOp::AtomicUMax,
|
||||
"umin" => AtomicRmwBinOp::AtomicUMin,
|
||||
_ => self.sess().fatal("unknown atomic operation"),
|
||||
};
|
||||
|
||||
let ty = substs.type_at(0);
|
||||
if int_type_width_signed(ty, self).is_some() {
|
||||
self.atomic_rmw(
|
||||
atom_op,
|
||||
args[0].immediate(),
|
||||
args[1].immediate(),
|
||||
order,
|
||||
)
|
||||
} else {
|
||||
return invalid_monomorphization(ty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sym::nontemporal_store => {
|
||||
let dst = args[0].deref(self.cx());
|
||||
args[1].val.nontemporal_store(self, dst);
|
||||
return;
|
||||
}
|
||||
|
||||
sym::ptr_guaranteed_eq | sym::ptr_guaranteed_ne => {
|
||||
let a = args[0].immediate();
|
||||
let b = args[1].immediate();
|
||||
if name == sym::ptr_guaranteed_eq {
|
||||
self.icmp(IntPredicate::IntEQ, a, b)
|
||||
} else {
|
||||
self.icmp(IntPredicate::IntNE, a, b)
|
||||
}
|
||||
}
|
||||
|
||||
sym::ptr_offset_from => {
|
||||
let ty = substs.type_at(0);
|
||||
let pointee_size = self.size_of(ty);
|
||||
|
||||
// This is the same sequence that Clang emits for pointer subtraction.
|
||||
// It can be neither `nsw` nor `nuw` because the input is treated as
|
||||
// unsigned but then the output is treated as signed, so neither works.
|
||||
let a = args[0].immediate();
|
||||
let b = args[1].immediate();
|
||||
let a = self.ptrtoint(a, self.type_isize());
|
||||
let b = self.ptrtoint(b, self.type_isize());
|
||||
let d = self.sub(a, b);
|
||||
let pointee_size = self.const_usize(pointee_size.bytes());
|
||||
// this is where the signed magic happens (notice the `s` in `exactsdiv`)
|
||||
self.exactsdiv(d, pointee_size)
|
||||
}
|
||||
|
||||
_ => bug!("unknown intrinsic '{}'", name),
|
||||
};
|
||||
|
@ -807,39 +352,6 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
fn copy_intrinsic(
|
||||
bx: &mut Builder<'a, 'll, 'tcx>,
|
||||
allow_overlap: bool,
|
||||
volatile: bool,
|
||||
ty: Ty<'tcx>,
|
||||
dst: &'ll Value,
|
||||
src: &'ll Value,
|
||||
count: &'ll Value,
|
||||
) {
|
||||
let (size, align) = bx.size_and_align_of(ty);
|
||||
let size = bx.mul(bx.const_usize(size.bytes()), count);
|
||||
let flags = if volatile { MemFlags::VOLATILE } else { MemFlags::empty() };
|
||||
if allow_overlap {
|
||||
bx.memmove(dst, align, src, align, size, flags);
|
||||
} else {
|
||||
bx.memcpy(dst, align, src, align, size, flags);
|
||||
}
|
||||
}
|
||||
|
||||
fn memset_intrinsic(
|
||||
bx: &mut Builder<'a, 'll, 'tcx>,
|
||||
volatile: bool,
|
||||
ty: Ty<'tcx>,
|
||||
dst: &'ll Value,
|
||||
val: &'ll Value,
|
||||
count: &'ll Value,
|
||||
) {
|
||||
let (size, align) = bx.size_and_align_of(ty);
|
||||
let size = bx.mul(bx.const_usize(size.bytes()), count);
|
||||
let flags = if volatile { MemFlags::VOLATILE } else { MemFlags::empty() };
|
||||
bx.memset(dst, val, size, align, flags);
|
||||
}
|
||||
|
||||
fn try_intrinsic(
|
||||
bx: &mut Builder<'a, 'll, 'tcx>,
|
||||
try_func: &'ll Value,
|
||||
|
@ -1281,14 +793,18 @@ fn generic_simd_intrinsic(
|
|||
require_simd!(arg_tys[1], "argument");
|
||||
let v_len = arg_tys[1].simd_size(tcx);
|
||||
require!(
|
||||
m_len == v_len,
|
||||
// Allow masks for vectors with fewer than 8 elements to be
|
||||
// represented with a u8 or i8.
|
||||
m_len == v_len || (m_len == 8 && v_len < 8),
|
||||
"mismatched lengths: mask length `{}` != other vector length `{}`",
|
||||
m_len,
|
||||
v_len
|
||||
);
|
||||
let i1 = bx.type_i1();
|
||||
let i1xn = bx.type_vector(i1, m_len);
|
||||
let m_i1s = bx.bitcast(args[0].immediate(), i1xn);
|
||||
let im = bx.type_ix(v_len);
|
||||
let i1xn = bx.type_vector(i1, v_len);
|
||||
let m_im = bx.trunc(args[0].immediate(), im);
|
||||
let m_i1s = bx.bitcast(m_im, i1xn);
|
||||
return Ok(bx.select(m_i1s, args[1].immediate(), args[2].immediate()));
|
||||
}
|
||||
|
||||
|
@ -2205,37 +1721,12 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
|
|||
// stuffs.
|
||||
fn int_type_width_signed(ty: Ty<'_>, cx: &CodegenCx<'_, '_>) -> Option<(u64, bool)> {
|
||||
match ty.kind() {
|
||||
ty::Int(t) => Some((
|
||||
match t {
|
||||
ast::IntTy::Isize => u64::from(cx.tcx.sess.target.ptr_width),
|
||||
ast::IntTy::I8 => 8,
|
||||
ast::IntTy::I16 => 16,
|
||||
ast::IntTy::I32 => 32,
|
||||
ast::IntTy::I64 => 64,
|
||||
ast::IntTy::I128 => 128,
|
||||
},
|
||||
true,
|
||||
)),
|
||||
ty::Uint(t) => Some((
|
||||
match t {
|
||||
ast::UintTy::Usize => u64::from(cx.tcx.sess.target.ptr_width),
|
||||
ast::UintTy::U8 => 8,
|
||||
ast::UintTy::U16 => 16,
|
||||
ast::UintTy::U32 => 32,
|
||||
ast::UintTy::U64 => 64,
|
||||
ast::UintTy::U128 => 128,
|
||||
},
|
||||
false,
|
||||
)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the width of a float Ty
|
||||
// Returns None if the type is not a float
|
||||
fn float_type_width(ty: Ty<'_>) -> Option<u64> {
|
||||
match ty.kind() {
|
||||
ty::Float(t) => Some(t.bit_width()),
|
||||
ty::Int(t) => {
|
||||
Some((t.bit_width().unwrap_or(u64::from(cx.tcx.sess.target.ptr_width)), true))
|
||||
}
|
||||
ty::Uint(t) => {
|
||||
Some((t.bit_width().unwrap_or(u64::from(cx.tcx.sess.target.ptr_width)), false))
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
//!
|
||||
//! This API is completely unstable and subject to change.
|
||||
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![feature(bool_to_option)]
|
||||
#![feature(const_cstr_unchecked)]
|
||||
#![feature(crate_visibility_modifier)]
|
||||
|
@ -12,7 +12,6 @@
|
|||
#![feature(in_band_lifetimes)]
|
||||
#![feature(nll)]
|
||||
#![feature(or_patterns)]
|
||||
#![feature(trusted_len)]
|
||||
#![recursion_limit = "256"]
|
||||
|
||||
use back::write::{create_informational_target_machine, create_target_machine};
|
||||
|
@ -96,8 +95,9 @@ impl ExtraBackendMethods for LlvmCodegenBackend {
|
|||
tcx: TyCtxt<'tcx>,
|
||||
mods: &mut ModuleLlvm,
|
||||
kind: AllocatorKind,
|
||||
has_alloc_error_handler: bool,
|
||||
) {
|
||||
unsafe { allocator::codegen(tcx, mods, kind) }
|
||||
unsafe { allocator::codegen(tcx, mods, kind, has_alloc_error_handler) }
|
||||
}
|
||||
fn compile_codegen_unit(
|
||||
&self,
|
||||
|
@ -130,6 +130,13 @@ impl WriteBackendMethods for LlvmCodegenBackend {
|
|||
llvm::LLVMRustPrintPassTimings();
|
||||
}
|
||||
}
|
||||
fn run_link(
|
||||
cgcx: &CodegenContext<Self>,
|
||||
diag_handler: &Handler,
|
||||
modules: Vec<ModuleCodegen<Self::Module>>,
|
||||
) -> Result<ModuleCodegen<Self::Module>, FatalError> {
|
||||
back::write::link(cgcx, diag_handler, modules)
|
||||
}
|
||||
fn run_fat_lto(
|
||||
cgcx: &CodegenContext<Self>,
|
||||
modules: Vec<FatLTOInput<Self>>,
|
||||
|
|
|
@ -118,6 +118,7 @@ pub enum Diagnostic<'ll> {
|
|||
InlineAsm(InlineAsmDiagnostic<'ll>),
|
||||
PGO(&'ll DiagnosticInfo),
|
||||
Linker(&'ll DiagnosticInfo),
|
||||
Unsupported(&'ll DiagnosticInfo),
|
||||
|
||||
/// LLVM has other types that we do not wrap here.
|
||||
UnknownDiagnostic(&'ll DiagnosticInfo),
|
||||
|
@ -159,6 +160,7 @@ impl Diagnostic<'ll> {
|
|||
|
||||
Dk::PGOProfile => PGO(di),
|
||||
Dk::Linker => Linker(di),
|
||||
Dk::Unsupported => Unsupported(di),
|
||||
|
||||
_ => UnknownDiagnostic(di),
|
||||
}
|
||||
|
|
|
@ -96,7 +96,7 @@ pub enum DLLStorageClass {
|
|||
DllExport = 2, // Function to be accessible from DLL.
|
||||
}
|
||||
|
||||
/// Matches LLVMRustAttribute in rustllvm.h
|
||||
/// Matches LLVMRustAttribute in LLVMWrapper.h
|
||||
/// Semantically a subset of the C++ enum llvm::Attribute::AttrKind,
|
||||
/// though it is not ABI compatible (since it's a C++ enum)
|
||||
#[repr(C)]
|
||||
|
@ -483,6 +483,7 @@ pub enum DiagnosticKind {
|
|||
OptimizationFailure,
|
||||
PGOProfile,
|
||||
Linker,
|
||||
Unsupported,
|
||||
}
|
||||
|
||||
/// LLVMRustDiagnosticLevel
|
||||
|
@ -948,7 +949,6 @@ extern "C" {
|
|||
|
||||
// Operations on other types
|
||||
pub fn LLVMVoidTypeInContext(C: &Context) -> &Type;
|
||||
pub fn LLVMX86MMXTypeInContext(C: &Context) -> &Type;
|
||||
pub fn LLVMRustMetadataTypeInContext(C: &Context) -> &Type;
|
||||
|
||||
// Operations on all values
|
||||
|
@ -1705,7 +1705,7 @@ extern "C" {
|
|||
PM: &PassManager<'_>,
|
||||
);
|
||||
|
||||
// Stuff that's in rustllvm/ because it's not upstream yet.
|
||||
// Stuff that's in llvm-wrapper/ because it's not upstream yet.
|
||||
|
||||
/// Opens an object file.
|
||||
pub fn LLVMCreateObjectFile(
|
||||
|
|
|
@ -37,6 +37,12 @@ pub fn AddFunctionAttrStringValue(llfn: &'a Value, idx: AttributePlace, attr: &C
|
|||
}
|
||||
}
|
||||
|
||||
pub fn AddFunctionAttrString(llfn: &'a Value, idx: AttributePlace, attr: &CStr) {
|
||||
unsafe {
|
||||
LLVMRustAddFunctionAttrStringValue(llfn, idx.as_uint(), attr.as_ptr(), std::ptr::null())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum AttributePlace {
|
||||
ReturnValue,
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
use crate::back::write::create_informational_target_machine;
|
||||
use crate::llvm;
|
||||
use libc::c_int;
|
||||
use rustc_codegen_ssa::target_features::supported_target_features;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_feature::UnstableFeatures;
|
||||
use rustc_middle::bug;
|
||||
use rustc_session::config::PrintRequest;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_target::spec::{MergeFunctions, PanicStrategy};
|
||||
use std::ffi::CString;
|
||||
|
@ -139,141 +139,6 @@ pub fn time_trace_profiler_finish(file_name: &str) {
|
|||
// WARNING: the features after applying `to_llvm_feature` must be known
|
||||
// to LLVM or the feature detection code will walk past the end of the feature
|
||||
// array, leading to crashes.
|
||||
|
||||
const ARM_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
|
||||
("aclass", Some(sym::arm_target_feature)),
|
||||
("mclass", Some(sym::arm_target_feature)),
|
||||
("rclass", Some(sym::arm_target_feature)),
|
||||
("dsp", Some(sym::arm_target_feature)),
|
||||
("neon", Some(sym::arm_target_feature)),
|
||||
("crc", Some(sym::arm_target_feature)),
|
||||
("crypto", Some(sym::arm_target_feature)),
|
||||
("v5te", Some(sym::arm_target_feature)),
|
||||
("v6", Some(sym::arm_target_feature)),
|
||||
("v6k", Some(sym::arm_target_feature)),
|
||||
("v6t2", Some(sym::arm_target_feature)),
|
||||
("v7", Some(sym::arm_target_feature)),
|
||||
("v8", Some(sym::arm_target_feature)),
|
||||
("vfp2", Some(sym::arm_target_feature)),
|
||||
("vfp3", Some(sym::arm_target_feature)),
|
||||
("vfp4", Some(sym::arm_target_feature)),
|
||||
// This is needed for inline assembly, but shouldn't be stabilized as-is
|
||||
// since it should be enabled per-function using #[instruction_set], not
|
||||
// #[target_feature].
|
||||
("thumb-mode", Some(sym::arm_target_feature)),
|
||||
];
|
||||
|
||||
const AARCH64_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
|
||||
("fp", Some(sym::aarch64_target_feature)),
|
||||
("neon", Some(sym::aarch64_target_feature)),
|
||||
("sve", Some(sym::aarch64_target_feature)),
|
||||
("crc", Some(sym::aarch64_target_feature)),
|
||||
("crypto", Some(sym::aarch64_target_feature)),
|
||||
("ras", Some(sym::aarch64_target_feature)),
|
||||
("lse", Some(sym::aarch64_target_feature)),
|
||||
("rdm", Some(sym::aarch64_target_feature)),
|
||||
("fp16", Some(sym::aarch64_target_feature)),
|
||||
("rcpc", Some(sym::aarch64_target_feature)),
|
||||
("dotprod", Some(sym::aarch64_target_feature)),
|
||||
("tme", Some(sym::aarch64_target_feature)),
|
||||
("v8.1a", Some(sym::aarch64_target_feature)),
|
||||
("v8.2a", Some(sym::aarch64_target_feature)),
|
||||
("v8.3a", Some(sym::aarch64_target_feature)),
|
||||
];
|
||||
|
||||
const X86_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
|
||||
("adx", Some(sym::adx_target_feature)),
|
||||
("aes", None),
|
||||
("avx", None),
|
||||
("avx2", None),
|
||||
("avx512bw", Some(sym::avx512_target_feature)),
|
||||
("avx512cd", Some(sym::avx512_target_feature)),
|
||||
("avx512dq", Some(sym::avx512_target_feature)),
|
||||
("avx512er", Some(sym::avx512_target_feature)),
|
||||
("avx512f", Some(sym::avx512_target_feature)),
|
||||
("avx512ifma", Some(sym::avx512_target_feature)),
|
||||
("avx512pf", Some(sym::avx512_target_feature)),
|
||||
("avx512vbmi", Some(sym::avx512_target_feature)),
|
||||
("avx512vl", Some(sym::avx512_target_feature)),
|
||||
("avx512vpopcntdq", Some(sym::avx512_target_feature)),
|
||||
("bmi1", None),
|
||||
("bmi2", None),
|
||||
("cmpxchg16b", Some(sym::cmpxchg16b_target_feature)),
|
||||
("f16c", Some(sym::f16c_target_feature)),
|
||||
("fma", None),
|
||||
("fxsr", None),
|
||||
("lzcnt", None),
|
||||
("mmx", Some(sym::mmx_target_feature)),
|
||||
("movbe", Some(sym::movbe_target_feature)),
|
||||
("pclmulqdq", None),
|
||||
("popcnt", None),
|
||||
("rdrand", None),
|
||||
("rdseed", None),
|
||||
("rtm", Some(sym::rtm_target_feature)),
|
||||
("sha", None),
|
||||
("sse", None),
|
||||
("sse2", None),
|
||||
("sse3", None),
|
||||
("sse4.1", None),
|
||||
("sse4.2", None),
|
||||
("sse4a", Some(sym::sse4a_target_feature)),
|
||||
("ssse3", None),
|
||||
("tbm", Some(sym::tbm_target_feature)),
|
||||
("xsave", None),
|
||||
("xsavec", None),
|
||||
("xsaveopt", None),
|
||||
("xsaves", None),
|
||||
];
|
||||
|
||||
const HEXAGON_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
|
||||
("hvx", Some(sym::hexagon_target_feature)),
|
||||
("hvx-length128b", Some(sym::hexagon_target_feature)),
|
||||
];
|
||||
|
||||
const POWERPC_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
|
||||
("altivec", Some(sym::powerpc_target_feature)),
|
||||
("power8-altivec", Some(sym::powerpc_target_feature)),
|
||||
("power9-altivec", Some(sym::powerpc_target_feature)),
|
||||
("power8-vector", Some(sym::powerpc_target_feature)),
|
||||
("power9-vector", Some(sym::powerpc_target_feature)),
|
||||
("vsx", Some(sym::powerpc_target_feature)),
|
||||
];
|
||||
|
||||
const MIPS_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] =
|
||||
&[("fp64", Some(sym::mips_target_feature)), ("msa", Some(sym::mips_target_feature))];
|
||||
|
||||
const RISCV_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
|
||||
("m", Some(sym::riscv_target_feature)),
|
||||
("a", Some(sym::riscv_target_feature)),
|
||||
("c", Some(sym::riscv_target_feature)),
|
||||
("f", Some(sym::riscv_target_feature)),
|
||||
("d", Some(sym::riscv_target_feature)),
|
||||
("e", Some(sym::riscv_target_feature)),
|
||||
];
|
||||
|
||||
const WASM_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
|
||||
("simd128", Some(sym::wasm_target_feature)),
|
||||
("atomics", Some(sym::wasm_target_feature)),
|
||||
("nontrapping-fptoint", Some(sym::wasm_target_feature)),
|
||||
];
|
||||
|
||||
/// When rustdoc is running, provide a list of all known features so that all their respective
|
||||
/// primitives may be documented.
|
||||
///
|
||||
/// IMPORTANT: If you're adding another feature list above, make sure to add it to this iterator!
|
||||
pub fn all_known_features() -> impl Iterator<Item = (&'static str, Option<Symbol>)> {
|
||||
std::iter::empty()
|
||||
.chain(ARM_ALLOWED_FEATURES.iter())
|
||||
.chain(AARCH64_ALLOWED_FEATURES.iter())
|
||||
.chain(X86_ALLOWED_FEATURES.iter())
|
||||
.chain(HEXAGON_ALLOWED_FEATURES.iter())
|
||||
.chain(POWERPC_ALLOWED_FEATURES.iter())
|
||||
.chain(MIPS_ALLOWED_FEATURES.iter())
|
||||
.chain(RISCV_ALLOWED_FEATURES.iter())
|
||||
.chain(WASM_ALLOWED_FEATURES.iter())
|
||||
.cloned()
|
||||
}
|
||||
|
||||
pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> &'a str {
|
||||
let arch = if sess.target.target.arch == "x86_64" { "x86" } else { &*sess.target.target.arch };
|
||||
match (arch, s) {
|
||||
|
@ -307,20 +172,6 @@ pub fn target_features(sess: &Session) -> Vec<Symbol> {
|
|||
.collect()
|
||||
}
|
||||
|
||||
pub fn supported_target_features(sess: &Session) -> &'static [(&'static str, Option<Symbol>)] {
|
||||
match &*sess.target.target.arch {
|
||||
"arm" => ARM_ALLOWED_FEATURES,
|
||||
"aarch64" => AARCH64_ALLOWED_FEATURES,
|
||||
"x86" | "x86_64" => X86_ALLOWED_FEATURES,
|
||||
"hexagon" => HEXAGON_ALLOWED_FEATURES,
|
||||
"mips" | "mips64" => MIPS_ALLOWED_FEATURES,
|
||||
"powerpc" | "powerpc64" => POWERPC_ALLOWED_FEATURES,
|
||||
"riscv32" | "riscv64" => RISCV_ALLOWED_FEATURES,
|
||||
"wasm32" => WASM_ALLOWED_FEATURES,
|
||||
_ => &[],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn print_version() {
|
||||
// Can be called without initializing LLVM
|
||||
unsafe {
|
||||
|
|
|
@ -62,10 +62,6 @@ impl CodegenCx<'ll, 'tcx> {
|
|||
unsafe { llvm::LLVMIntTypeInContext(self.llcx, num_bits as c_uint) }
|
||||
}
|
||||
|
||||
crate fn type_x86_mmx(&self) -> &'ll Type {
|
||||
unsafe { llvm::LLVMX86MMXTypeInContext(self.llcx) }
|
||||
}
|
||||
|
||||
crate fn type_vector(&self, ty: &'ll Type, len: u64) -> &'ll Type {
|
||||
unsafe { llvm::LLVMVectorType(ty, len as c_uint) }
|
||||
}
|
||||
|
|
|
@ -21,23 +21,8 @@ fn uncached_llvm_type<'a, 'tcx>(
|
|||
match layout.abi {
|
||||
Abi::Scalar(_) => bug!("handled elsewhere"),
|
||||
Abi::Vector { ref element, count } => {
|
||||
// LLVM has a separate type for 64-bit SIMD vectors on X86 called
|
||||
// `x86_mmx` which is needed for some SIMD operations. As a bit of a
|
||||
// hack (all SIMD definitions are super unstable anyway) we
|
||||
// recognize any one-element SIMD vector as "this should be an
|
||||
// x86_mmx" type. In general there shouldn't be a need for other
|
||||
// one-element SIMD vectors, so it's assumed this won't clash with
|
||||
// much else.
|
||||
let use_x86_mmx = count == 1
|
||||
&& layout.size.bits() == 64
|
||||
&& (cx.sess().target.target.arch == "x86"
|
||||
|| cx.sess().target.target.arch == "x86_64");
|
||||
if use_x86_mmx {
|
||||
return cx.type_x86_mmx();
|
||||
} else {
|
||||
let element = layout.scalar_llvm_type_at(cx, element, Size::ZERO);
|
||||
return cx.type_vector(element, count);
|
||||
}
|
||||
let element = layout.scalar_llvm_type_at(cx, element, Size::ZERO);
|
||||
return cx.type_vector(element, count);
|
||||
}
|
||||
Abi::ScalarPair(..) => {
|
||||
return cx.type_struct(
|
||||
|
|
|
@ -11,7 +11,6 @@ use rustc_middle::ty::layout::HasTyCtxt;
|
|||
use rustc_middle::ty::Ty;
|
||||
use rustc_target::abi::{Align, HasDataLayout, LayoutOf, Size};
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn round_pointer_up_to_alignment(
|
||||
bx: &mut Builder<'a, 'll, 'tcx>,
|
||||
addr: &'ll Value,
|
||||
|
|
|
@ -111,6 +111,12 @@ impl Command {
|
|||
LldFlavor::Link => "link",
|
||||
LldFlavor::Ld64 => "darwin",
|
||||
});
|
||||
if let LldFlavor::Wasm = flavor {
|
||||
// LLVM expects host-specific formatting for @file
|
||||
// arguments, but we always generate posix formatted files
|
||||
// at this time. Indicate as such.
|
||||
c.arg("--rsp-quoting=posix");
|
||||
}
|
||||
c
|
||||
}
|
||||
};
|
||||
|
|
|
@ -1076,7 +1076,7 @@ fn exec_linker(
|
|||
}
|
||||
.to_string(),
|
||||
);
|
||||
args.push_str("\n");
|
||||
args.push('\n');
|
||||
}
|
||||
let file = tmpdir.join("linker-arguments");
|
||||
let bytes = if sess.target.target.options.is_like_msvc {
|
||||
|
@ -1333,9 +1333,6 @@ fn add_late_link_args(
|
|||
crate_type: CrateType,
|
||||
codegen_results: &CodegenResults,
|
||||
) {
|
||||
if let Some(args) = sess.target.target.options.late_link_args.get(&flavor) {
|
||||
cmd.args(args);
|
||||
}
|
||||
let any_dynamic_crate = crate_type == CrateType::Dylib
|
||||
|| codegen_results.crate_info.dependency_formats.iter().any(|(ty, list)| {
|
||||
*ty == crate_type && list.iter().any(|&linkage| linkage == Linkage::Dynamic)
|
||||
|
@ -1349,6 +1346,9 @@ fn add_late_link_args(
|
|||
cmd.args(args);
|
||||
}
|
||||
}
|
||||
if let Some(args) = sess.target.target.options.late_link_args.get(&flavor) {
|
||||
cmd.args(args);
|
||||
}
|
||||
}
|
||||
|
||||
/// Add arbitrary "post-link" args defined by the target spec.
|
||||
|
@ -1524,6 +1524,9 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
|
|||
// NO-OPT-OUT, OBJECT-FILES-MAYBE, CUSTOMIZATION-POINT
|
||||
add_pre_link_args(cmd, sess, flavor);
|
||||
|
||||
// NO-OPT-OUT, OBJECT-FILES-NO
|
||||
add_apple_sdk(cmd, sess, flavor);
|
||||
|
||||
// NO-OPT-OUT
|
||||
add_link_script(cmd, sess, tmpdir, crate_type);
|
||||
|
||||
|
@ -2083,3 +2086,86 @@ fn are_upstream_rust_objects_already_included(sess: &Session) -> bool {
|
|||
config::Lto::No | config::Lto::ThinLocal => false,
|
||||
}
|
||||
}
|
||||
|
||||
fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
|
||||
let arch = &sess.target.target.arch;
|
||||
let os = &sess.target.target.target_os;
|
||||
let llvm_target = &sess.target.target.llvm_target;
|
||||
if sess.target.target.target_vendor != "apple"
|
||||
|| !matches!(os.as_str(), "ios" | "tvos")
|
||||
|| flavor != LinkerFlavor::Gcc
|
||||
{
|
||||
return;
|
||||
}
|
||||
let sdk_name = match (arch.as_str(), os.as_str()) {
|
||||
("aarch64", "tvos") => "appletvos",
|
||||
("x86_64", "tvos") => "appletvsimulator",
|
||||
("arm", "ios") => "iphoneos",
|
||||
("aarch64", "ios") => "iphoneos",
|
||||
("x86", "ios") => "iphonesimulator",
|
||||
("x86_64", "ios") if llvm_target.contains("macabi") => "macosx10.15",
|
||||
("x86_64", "ios") => "iphonesimulator",
|
||||
_ => {
|
||||
sess.err(&format!("unsupported arch `{}` for os `{}`", arch, os));
|
||||
return;
|
||||
}
|
||||
};
|
||||
let sdk_root = match get_apple_sdk_root(sdk_name) {
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
sess.err(&e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
let arch_name = llvm_target.split('-').next().expect("LLVM target must have a hyphen");
|
||||
cmd.args(&["-arch", arch_name, "-isysroot", &sdk_root, "-Wl,-syslibroot", &sdk_root]);
|
||||
}
|
||||
|
||||
fn get_apple_sdk_root(sdk_name: &str) -> Result<String, String> {
|
||||
// Following what clang does
|
||||
// (https://github.com/llvm/llvm-project/blob/
|
||||
// 296a80102a9b72c3eda80558fb78a3ed8849b341/clang/lib/Driver/ToolChains/Darwin.cpp#L1661-L1678)
|
||||
// to allow the SDK path to be set. (For clang, xcrun sets
|
||||
// SDKROOT; for rustc, the user or build system can set it, or we
|
||||
// can fall back to checking for xcrun on PATH.)
|
||||
if let Ok(sdkroot) = env::var("SDKROOT") {
|
||||
let p = Path::new(&sdkroot);
|
||||
match sdk_name {
|
||||
// Ignore `SDKROOT` if it's clearly set for the wrong platform.
|
||||
"appletvos"
|
||||
if sdkroot.contains("TVSimulator.platform")
|
||||
|| sdkroot.contains("MacOSX.platform") => {}
|
||||
"appletvsimulator"
|
||||
if sdkroot.contains("TVOS.platform") || sdkroot.contains("MacOSX.platform") => {}
|
||||
"iphoneos"
|
||||
if sdkroot.contains("iPhoneSimulator.platform")
|
||||
|| sdkroot.contains("MacOSX.platform") => {}
|
||||
"iphonesimulator"
|
||||
if sdkroot.contains("iPhoneOS.platform") || sdkroot.contains("MacOSX.platform") => {
|
||||
}
|
||||
"macosx10.15"
|
||||
if sdkroot.contains("iPhoneOS.platform")
|
||||
|| sdkroot.contains("iPhoneSimulator.platform") => {}
|
||||
// Ignore `SDKROOT` if it's not a valid path.
|
||||
_ if !p.is_absolute() || p == Path::new("/") || !p.exists() => {}
|
||||
_ => return Ok(sdkroot),
|
||||
}
|
||||
}
|
||||
let res =
|
||||
Command::new("xcrun").arg("--show-sdk-path").arg("-sdk").arg(sdk_name).output().and_then(
|
||||
|output| {
|
||||
if output.status.success() {
|
||||
Ok(String::from_utf8(output.stdout).unwrap())
|
||||
} else {
|
||||
let error = String::from_utf8(output.stderr);
|
||||
let error = format!("process exit with error: {}", error.unwrap());
|
||||
Err(io::Error::new(io::ErrorKind::Other, &error[..]))
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
match res {
|
||||
Ok(output) => Ok(output.trim().to_string()),
|
||||
Err(e) => Err(format!("failed to get {} SDK path: {}", sdk_name, e)),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -702,6 +702,7 @@ impl<B: WriteBackendMethods> WorkItem<B> {
|
|||
|
||||
enum WorkItemResult<B: WriteBackendMethods> {
|
||||
Compiled(CompiledModule),
|
||||
NeedsLink(ModuleCodegen<B::Module>),
|
||||
NeedsFatLTO(FatLTOInput<B>),
|
||||
NeedsThinLTO(String, B::ThinBuffer),
|
||||
}
|
||||
|
@ -801,11 +802,8 @@ fn execute_optimize_work_item<B: ExtraBackendMethods>(
|
|||
None
|
||||
};
|
||||
|
||||
Ok(match lto_type {
|
||||
ComputedLtoType::No => {
|
||||
let module = unsafe { B::codegen(cgcx, &diag_handler, module, module_config)? };
|
||||
WorkItemResult::Compiled(module)
|
||||
}
|
||||
match lto_type {
|
||||
ComputedLtoType::No => finish_intra_module_work(cgcx, module, module_config),
|
||||
ComputedLtoType::Thin => {
|
||||
let (name, thin_buffer) = B::prepare_thin(module);
|
||||
if let Some(path) = bitcode {
|
||||
|
@ -813,7 +811,7 @@ fn execute_optimize_work_item<B: ExtraBackendMethods>(
|
|||
panic!("Error writing pre-lto-bitcode file `{}`: {}", path.display(), e);
|
||||
});
|
||||
}
|
||||
WorkItemResult::NeedsThinLTO(name, thin_buffer)
|
||||
Ok(WorkItemResult::NeedsThinLTO(name, thin_buffer))
|
||||
}
|
||||
ComputedLtoType::Fat => match bitcode {
|
||||
Some(path) => {
|
||||
|
@ -821,11 +819,11 @@ fn execute_optimize_work_item<B: ExtraBackendMethods>(
|
|||
fs::write(&path, buffer.data()).unwrap_or_else(|e| {
|
||||
panic!("Error writing pre-lto-bitcode file `{}`: {}", path.display(), e);
|
||||
});
|
||||
WorkItemResult::NeedsFatLTO(FatLTOInput::Serialized { name, buffer })
|
||||
Ok(WorkItemResult::NeedsFatLTO(FatLTOInput::Serialized { name, buffer }))
|
||||
}
|
||||
None => WorkItemResult::NeedsFatLTO(FatLTOInput::InMemory(module)),
|
||||
None => Ok(WorkItemResult::NeedsFatLTO(FatLTOInput::InMemory(module))),
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>(
|
||||
|
@ -870,13 +868,26 @@ fn execute_lto_work_item<B: ExtraBackendMethods>(
|
|||
cgcx: &CodegenContext<B>,
|
||||
mut module: lto::LtoModuleCodegen<B>,
|
||||
module_config: &ModuleConfig,
|
||||
) -> Result<WorkItemResult<B>, FatalError> {
|
||||
let module = unsafe { module.optimize(cgcx)? };
|
||||
finish_intra_module_work(cgcx, module, module_config)
|
||||
}
|
||||
|
||||
fn finish_intra_module_work<B: ExtraBackendMethods>(
|
||||
cgcx: &CodegenContext<B>,
|
||||
module: ModuleCodegen<B::Module>,
|
||||
module_config: &ModuleConfig,
|
||||
) -> Result<WorkItemResult<B>, FatalError> {
|
||||
let diag_handler = cgcx.create_diag_handler();
|
||||
|
||||
unsafe {
|
||||
let module = module.optimize(cgcx)?;
|
||||
let module = B::codegen(cgcx, &diag_handler, module, module_config)?;
|
||||
if !cgcx.opts.debugging_opts.combine_cgu
|
||||
|| module.kind == ModuleKind::Metadata
|
||||
|| module.kind == ModuleKind::Allocator
|
||||
{
|
||||
let module = unsafe { B::codegen(cgcx, &diag_handler, module, module_config)? };
|
||||
Ok(WorkItemResult::Compiled(module))
|
||||
} else {
|
||||
Ok(WorkItemResult::NeedsLink(module))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -891,6 +902,10 @@ pub enum Message<B: WriteBackendMethods> {
|
|||
thin_buffer: B::ThinBuffer,
|
||||
worker_id: usize,
|
||||
},
|
||||
NeedsLink {
|
||||
module: ModuleCodegen<B::Module>,
|
||||
worker_id: usize,
|
||||
},
|
||||
Done {
|
||||
result: Result<CompiledModule, Option<WorkerFatalError>>,
|
||||
worker_id: usize,
|
||||
|
@ -1178,6 +1193,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
|
|||
let mut compiled_modules = vec![];
|
||||
let mut compiled_metadata_module = None;
|
||||
let mut compiled_allocator_module = None;
|
||||
let mut needs_link = Vec::new();
|
||||
let mut needs_fat_lto = Vec::new();
|
||||
let mut needs_thin_lto = Vec::new();
|
||||
let mut lto_import_only_modules = Vec::new();
|
||||
|
@ -1434,6 +1450,10 @@ fn start_executing_work<B: ExtraBackendMethods>(
|
|||
}
|
||||
}
|
||||
}
|
||||
Message::NeedsLink { module, worker_id } => {
|
||||
free_worker(worker_id);
|
||||
needs_link.push(module);
|
||||
}
|
||||
Message::NeedsFatLTO { result, worker_id } => {
|
||||
assert!(!started_lto);
|
||||
free_worker(worker_id);
|
||||
|
@ -1462,6 +1482,18 @@ fn start_executing_work<B: ExtraBackendMethods>(
|
|||
}
|
||||
}
|
||||
|
||||
let needs_link = mem::take(&mut needs_link);
|
||||
if !needs_link.is_empty() {
|
||||
assert!(compiled_modules.is_empty());
|
||||
let diag_handler = cgcx.create_diag_handler();
|
||||
let module = B::run_link(&cgcx, &diag_handler, needs_link).map_err(|_| ())?;
|
||||
let module = unsafe {
|
||||
B::codegen(&cgcx, &diag_handler, module, cgcx.config(ModuleKind::Regular))
|
||||
.map_err(|_| ())?
|
||||
};
|
||||
compiled_modules.push(module);
|
||||
}
|
||||
|
||||
// Drop to print timings
|
||||
drop(llvm_start_time);
|
||||
|
||||
|
@ -1521,6 +1553,9 @@ fn spawn_work<B: ExtraBackendMethods>(cgcx: CodegenContext<B>, work: WorkItem<B>
|
|||
Some(Ok(WorkItemResult::Compiled(m))) => {
|
||||
Message::Done::<B> { result: Ok(m), worker_id }
|
||||
}
|
||||
Some(Ok(WorkItemResult::NeedsLink(m))) => {
|
||||
Message::NeedsLink::<B> { module: m, worker_id }
|
||||
}
|
||||
Some(Ok(WorkItemResult::NeedsFatLTO(m))) => {
|
||||
Message::NeedsFatLTO::<B> { result: m, worker_id }
|
||||
}
|
||||
|
|
|
@ -407,16 +407,18 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
// listing.
|
||||
let main_ret_ty = cx.tcx().erase_regions(&main_ret_ty.no_bound_vars().unwrap());
|
||||
|
||||
if cx.get_declared_value("main").is_some() {
|
||||
// FIXME: We should be smart and show a better diagnostic here.
|
||||
cx.sess()
|
||||
.struct_span_err(sp, "entry symbol `main` declared multiple times")
|
||||
.help("did you use `#[no_mangle]` on `fn main`? Use `#[start]` instead")
|
||||
.emit();
|
||||
cx.sess().abort_if_errors();
|
||||
bug!();
|
||||
}
|
||||
let llfn = cx.declare_cfn("main", llfty);
|
||||
let llfn = match cx.declare_c_main(llfty) {
|
||||
Some(llfn) => llfn,
|
||||
None => {
|
||||
// FIXME: We should be smart and show a better diagnostic here.
|
||||
cx.sess()
|
||||
.struct_span_err(sp, "entry symbol `main` declared multiple times")
|
||||
.help("did you use `#[no_mangle]` on `fn main`? Use `#[start]` instead")
|
||||
.emit();
|
||||
cx.sess().abort_if_errors();
|
||||
bug!();
|
||||
}
|
||||
};
|
||||
|
||||
// `main` should respect same config for frame pointer elimination as rest of code
|
||||
cx.set_frame_pointer_elimination(llfn);
|
||||
|
@ -536,8 +538,9 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
|
|||
let llmod_id =
|
||||
cgu_name_builder.build_cgu_name(LOCAL_CRATE, &["crate"], Some("allocator")).to_string();
|
||||
let mut modules = backend.new_metadata(tcx, &llmod_id);
|
||||
tcx.sess
|
||||
.time("write_allocator_module", || backend.codegen_allocator(tcx, &mut modules, kind));
|
||||
tcx.sess.time("write_allocator_module", || {
|
||||
backend.codegen_allocator(tcx, &mut modules, kind, tcx.lang_items().oom().is_some())
|
||||
});
|
||||
|
||||
Some(ModuleCodegen { name: llmod_id, module_llvm: modules, kind: ModuleKind::Allocator })
|
||||
} else {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#![allow(non_camel_case_types, non_snake_case)]
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
use rustc_errors::struct_span_err;
|
||||
use rustc_hir as hir;
|
||||
|
@ -25,7 +25,6 @@ pub enum IntPredicate {
|
|||
IntSLE,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub enum RealPredicate {
|
||||
RealPredicateFalse,
|
||||
RealOEQ,
|
||||
|
@ -60,7 +59,6 @@ pub enum AtomicRmwBinOp {
|
|||
}
|
||||
|
||||
pub enum AtomicOrdering {
|
||||
#[allow(dead_code)]
|
||||
NotAtomic,
|
||||
Unordered,
|
||||
Monotonic,
|
||||
|
|
|
@ -143,7 +143,9 @@ impl FunctionCoverage {
|
|||
let id_to_counter =
|
||||
|new_indexes: &IndexVec<InjectedExpressionIndex, MappedExpressionIndex>,
|
||||
id: ExpressionOperandId| {
|
||||
if id.index() < self.counters.len() {
|
||||
if id == ExpressionOperandId::ZERO {
|
||||
Some(Counter::zero())
|
||||
} else if id.index() < self.counters.len() {
|
||||
let index = CounterValueReference::from(id.index());
|
||||
self.counters
|
||||
.get(index)
|
||||
|
@ -179,14 +181,19 @@ impl FunctionCoverage {
|
|||
// been assigned a `new_index`.
|
||||
let mapped_expression_index =
|
||||
MappedExpressionIndex::from(counter_expressions.len());
|
||||
counter_expressions.push(CounterExpression::new(
|
||||
let expression = CounterExpression::new(
|
||||
lhs_counter,
|
||||
match op {
|
||||
Op::Add => ExprKind::Add,
|
||||
Op::Subtract => ExprKind::Subtract,
|
||||
},
|
||||
rhs_counter,
|
||||
));
|
||||
);
|
||||
debug!(
|
||||
"Adding expression {:?} = {:?} at {:?}",
|
||||
mapped_expression_index, expression, region
|
||||
);
|
||||
counter_expressions.push(expression);
|
||||
new_indexes[original_index] = mapped_expression_index;
|
||||
expression_regions.push((Counter::expression(mapped_expression_index), region));
|
||||
}
|
||||
|
|
|
@ -5,6 +5,8 @@ use rustc_hir as hir;
|
|||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::ty::{self, subst::SubstsRef, Ty, TyCtxt};
|
||||
|
||||
use std::fmt::Write;
|
||||
|
||||
// Compute the name of the type as it should be stored in debuginfo. Does not do
|
||||
// any caching, i.e., calling the function twice with the same type will also do
|
||||
// the work twice. The `qualified` parameter only affects the first level of the
|
||||
|
@ -37,7 +39,7 @@ pub fn push_debuginfo_type_name<'tcx>(
|
|||
ty::Bool => output.push_str("bool"),
|
||||
ty::Char => output.push_str("char"),
|
||||
ty::Str => output.push_str("str"),
|
||||
ty::Never => output.push_str("!"),
|
||||
ty::Never => output.push('!'),
|
||||
ty::Int(int_ty) => output.push_str(int_ty.name_str()),
|
||||
ty::Uint(uint_ty) => output.push_str(uint_ty.name_str()),
|
||||
ty::Float(float_ty) => output.push_str(float_ty.name_str()),
|
||||
|
@ -228,8 +230,7 @@ pub fn push_debuginfo_type_name<'tcx>(
|
|||
if qualified {
|
||||
output.push_str(&tcx.crate_name(def_id.krate).as_str());
|
||||
for path_element in tcx.def_path(def_id).data {
|
||||
output.push_str("::");
|
||||
output.push_str(&path_element.data.as_symbol().as_str());
|
||||
write!(output, "::{}", path_element.data).unwrap();
|
||||
}
|
||||
} else {
|
||||
output.push_str(&tcx.item_name(def_id).as_str());
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![feature(bool_to_option)]
|
||||
#![feature(option_expect_none)]
|
||||
#![feature(box_patterns)]
|
||||
|
@ -6,10 +6,7 @@
|
|||
#![feature(in_band_lifetimes)]
|
||||
#![feature(nll)]
|
||||
#![feature(or_patterns)]
|
||||
#![feature(trusted_len)]
|
||||
#![feature(associated_type_bounds)]
|
||||
#![feature(const_fn)] // for rustc_index::newtype_index
|
||||
#![feature(const_panic)] // for rustc_index::newtype_index
|
||||
#![recursion_limit = "256"]
|
||||
|
||||
//! This crate contains codegen code that is used by all codegen backends (LLVM and others).
|
||||
|
@ -45,6 +42,7 @@ pub mod glue;
|
|||
pub mod meth;
|
||||
pub mod mir;
|
||||
pub mod mono_item;
|
||||
pub mod target_features;
|
||||
pub mod traits;
|
||||
|
||||
pub struct ModuleCodegen<M> {
|
||||
|
|
|
@ -13,7 +13,7 @@ use rustc_ast as ast;
|
|||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_index::vec::Idx;
|
||||
use rustc_middle::mir;
|
||||
use rustc_middle::mir::interpret::{AllocId, ConstValue, Pointer, Scalar};
|
||||
use rustc_middle::mir::interpret::ConstValue;
|
||||
use rustc_middle::mir::AssertKind;
|
||||
use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt};
|
||||
use rustc_middle::ty::print::with_no_trimmed_paths;
|
||||
|
@ -687,7 +687,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
})
|
||||
.collect();
|
||||
|
||||
bx.codegen_intrinsic_call(
|
||||
Self::codegen_intrinsic_call(
|
||||
&mut bx,
|
||||
*instance.as_ref().unwrap(),
|
||||
&fn_abi,
|
||||
&args,
|
||||
|
@ -867,24 +868,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
let ty = constant.literal.ty;
|
||||
let size = bx.layout_of(ty).size;
|
||||
let scalar = match const_value {
|
||||
// Promoted constants are evaluated into a ByRef instead of a Scalar,
|
||||
// but we want the scalar value here.
|
||||
ConstValue::ByRef { alloc, offset } => {
|
||||
let ptr = Pointer::new(AllocId(0), offset);
|
||||
alloc
|
||||
.read_scalar(&bx, ptr, size)
|
||||
.and_then(|s| s.check_init())
|
||||
.unwrap_or_else(|e| {
|
||||
bx.tcx().sess.span_err(
|
||||
span,
|
||||
&format!("Could not evaluate asm const: {}", e),
|
||||
);
|
||||
|
||||
// We are erroring out, just emit a dummy constant.
|
||||
Scalar::from_u64(0)
|
||||
})
|
||||
}
|
||||
_ => span_bug!(span, "expected ByRef for promoted asm const"),
|
||||
ConstValue::Scalar(s) => s,
|
||||
_ => span_bug!(
|
||||
span,
|
||||
"expected Scalar for promoted asm const, but got {:#?}",
|
||||
const_value
|
||||
),
|
||||
};
|
||||
let value = scalar.assert_bits(size);
|
||||
let string = match ty.kind() {
|
||||
|
|
|
@ -0,0 +1,596 @@
|
|||
use super::operand::{OperandRef, OperandValue};
|
||||
use super::place::PlaceRef;
|
||||
use super::FunctionCx;
|
||||
use crate::common::{span_invalid_monomorphization_error, IntPredicate};
|
||||
use crate::glue;
|
||||
use crate::traits::*;
|
||||
use crate::MemFlags;
|
||||
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt};
|
||||
use rustc_span::{sym, Span};
|
||||
use rustc_target::abi::call::{FnAbi, PassMode};
|
||||
|
||||
fn copy_intrinsic<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||
bx: &mut Bx,
|
||||
allow_overlap: bool,
|
||||
volatile: bool,
|
||||
ty: Ty<'tcx>,
|
||||
dst: Bx::Value,
|
||||
src: Bx::Value,
|
||||
count: Bx::Value,
|
||||
) {
|
||||
let layout = bx.layout_of(ty);
|
||||
let size = layout.size;
|
||||
let align = layout.align.abi;
|
||||
let size = bx.mul(bx.const_usize(size.bytes()), count);
|
||||
let flags = if volatile { MemFlags::VOLATILE } else { MemFlags::empty() };
|
||||
if allow_overlap {
|
||||
bx.memmove(dst, align, src, align, size, flags);
|
||||
} else {
|
||||
bx.memcpy(dst, align, src, align, size, flags);
|
||||
}
|
||||
}
|
||||
|
||||
fn memset_intrinsic<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||
bx: &mut Bx,
|
||||
volatile: bool,
|
||||
ty: Ty<'tcx>,
|
||||
dst: Bx::Value,
|
||||
val: Bx::Value,
|
||||
count: Bx::Value,
|
||||
) {
|
||||
let layout = bx.layout_of(ty);
|
||||
let size = layout.size;
|
||||
let align = layout.align.abi;
|
||||
let size = bx.mul(bx.const_usize(size.bytes()), count);
|
||||
let flags = if volatile { MemFlags::VOLATILE } else { MemFlags::empty() };
|
||||
bx.memset(dst, val, size, align, flags);
|
||||
}
|
||||
|
||||
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
pub fn codegen_intrinsic_call(
|
||||
bx: &mut Bx,
|
||||
instance: ty::Instance<'tcx>,
|
||||
fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
|
||||
args: &[OperandRef<'tcx, Bx::Value>],
|
||||
llresult: Bx::Value,
|
||||
span: Span,
|
||||
) {
|
||||
let callee_ty = instance.ty(bx.tcx(), ty::ParamEnv::reveal_all());
|
||||
|
||||
let (def_id, substs) = match *callee_ty.kind() {
|
||||
ty::FnDef(def_id, substs) => (def_id, substs),
|
||||
_ => bug!("expected fn item type, found {}", callee_ty),
|
||||
};
|
||||
|
||||
let sig = callee_ty.fn_sig(bx.tcx());
|
||||
let sig = bx.tcx().normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
|
||||
let arg_tys = sig.inputs();
|
||||
let ret_ty = sig.output();
|
||||
let name = bx.tcx().item_name(def_id);
|
||||
let name_str = &*name.as_str();
|
||||
|
||||
let llret_ty = bx.backend_type(bx.layout_of(ret_ty));
|
||||
let result = PlaceRef::new_sized(llresult, fn_abi.ret.layout);
|
||||
|
||||
let llval = match name {
|
||||
sym::assume => {
|
||||
bx.assume(args[0].immediate());
|
||||
return;
|
||||
}
|
||||
sym::abort => {
|
||||
bx.abort();
|
||||
return;
|
||||
}
|
||||
|
||||
sym::unreachable => {
|
||||
return;
|
||||
}
|
||||
sym::va_start => bx.va_start(args[0].immediate()),
|
||||
sym::va_end => bx.va_end(args[0].immediate()),
|
||||
sym::size_of_val => {
|
||||
let tp_ty = substs.type_at(0);
|
||||
if let OperandValue::Pair(_, meta) = args[0].val {
|
||||
let (llsize, _) = glue::size_and_align_of_dst(bx, tp_ty, Some(meta));
|
||||
llsize
|
||||
} else {
|
||||
bx.const_usize(bx.layout_of(tp_ty).size.bytes())
|
||||
}
|
||||
}
|
||||
sym::min_align_of_val => {
|
||||
let tp_ty = substs.type_at(0);
|
||||
if let OperandValue::Pair(_, meta) = args[0].val {
|
||||
let (_, llalign) = glue::size_and_align_of_dst(bx, tp_ty, Some(meta));
|
||||
llalign
|
||||
} else {
|
||||
bx.const_usize(bx.layout_of(tp_ty).align.abi.bytes())
|
||||
}
|
||||
}
|
||||
sym::size_of
|
||||
| sym::pref_align_of
|
||||
| sym::min_align_of
|
||||
| sym::needs_drop
|
||||
| sym::type_id
|
||||
| sym::type_name
|
||||
| sym::variant_count => {
|
||||
let value = bx
|
||||
.tcx()
|
||||
.const_eval_instance(ty::ParamEnv::reveal_all(), instance, None)
|
||||
.unwrap();
|
||||
OperandRef::from_const(bx, value, ret_ty).immediate_or_packed_pair(bx)
|
||||
}
|
||||
// Effectively no-op
|
||||
sym::forget => {
|
||||
return;
|
||||
}
|
||||
sym::offset => {
|
||||
let ptr = args[0].immediate();
|
||||
let offset = args[1].immediate();
|
||||
bx.inbounds_gep(ptr, &[offset])
|
||||
}
|
||||
sym::arith_offset => {
|
||||
let ptr = args[0].immediate();
|
||||
let offset = args[1].immediate();
|
||||
bx.gep(ptr, &[offset])
|
||||
}
|
||||
|
||||
sym::copy_nonoverlapping => {
|
||||
copy_intrinsic(
|
||||
bx,
|
||||
false,
|
||||
false,
|
||||
substs.type_at(0),
|
||||
args[1].immediate(),
|
||||
args[0].immediate(),
|
||||
args[2].immediate(),
|
||||
);
|
||||
return;
|
||||
}
|
||||
sym::copy => {
|
||||
copy_intrinsic(
|
||||
bx,
|
||||
true,
|
||||
false,
|
||||
substs.type_at(0),
|
||||
args[1].immediate(),
|
||||
args[0].immediate(),
|
||||
args[2].immediate(),
|
||||
);
|
||||
return;
|
||||
}
|
||||
sym::write_bytes => {
|
||||
memset_intrinsic(
|
||||
bx,
|
||||
false,
|
||||
substs.type_at(0),
|
||||
args[0].immediate(),
|
||||
args[1].immediate(),
|
||||
args[2].immediate(),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
sym::volatile_copy_nonoverlapping_memory => {
|
||||
copy_intrinsic(
|
||||
bx,
|
||||
false,
|
||||
true,
|
||||
substs.type_at(0),
|
||||
args[0].immediate(),
|
||||
args[1].immediate(),
|
||||
args[2].immediate(),
|
||||
);
|
||||
return;
|
||||
}
|
||||
sym::volatile_copy_memory => {
|
||||
copy_intrinsic(
|
||||
bx,
|
||||
true,
|
||||
true,
|
||||
substs.type_at(0),
|
||||
args[0].immediate(),
|
||||
args[1].immediate(),
|
||||
args[2].immediate(),
|
||||
);
|
||||
return;
|
||||
}
|
||||
sym::volatile_set_memory => {
|
||||
memset_intrinsic(
|
||||
bx,
|
||||
true,
|
||||
substs.type_at(0),
|
||||
args[0].immediate(),
|
||||
args[1].immediate(),
|
||||
args[2].immediate(),
|
||||
);
|
||||
return;
|
||||
}
|
||||
sym::volatile_store => {
|
||||
let dst = args[0].deref(bx.cx());
|
||||
args[1].val.volatile_store(bx, dst);
|
||||
return;
|
||||
}
|
||||
sym::unaligned_volatile_store => {
|
||||
let dst = args[0].deref(bx.cx());
|
||||
args[1].val.unaligned_volatile_store(bx, dst);
|
||||
return;
|
||||
}
|
||||
sym::add_with_overflow
|
||||
| sym::sub_with_overflow
|
||||
| sym::mul_with_overflow
|
||||
| sym::wrapping_add
|
||||
| sym::wrapping_sub
|
||||
| sym::wrapping_mul
|
||||
| sym::unchecked_div
|
||||
| sym::unchecked_rem
|
||||
| sym::unchecked_shl
|
||||
| sym::unchecked_shr
|
||||
| sym::unchecked_add
|
||||
| sym::unchecked_sub
|
||||
| sym::unchecked_mul
|
||||
| sym::exact_div => {
|
||||
let ty = arg_tys[0];
|
||||
match int_type_width_signed(ty, bx.tcx()) {
|
||||
Some((_width, signed)) => match name {
|
||||
sym::add_with_overflow
|
||||
| sym::sub_with_overflow
|
||||
| sym::mul_with_overflow => {
|
||||
let op = match name {
|
||||
sym::add_with_overflow => OverflowOp::Add,
|
||||
sym::sub_with_overflow => OverflowOp::Sub,
|
||||
sym::mul_with_overflow => OverflowOp::Mul,
|
||||
_ => bug!(),
|
||||
};
|
||||
let (val, overflow) =
|
||||
bx.checked_binop(op, ty, args[0].immediate(), args[1].immediate());
|
||||
// Convert `i1` to a `bool`, and write it to the out parameter
|
||||
let val = bx.from_immediate(val);
|
||||
let overflow = bx.from_immediate(overflow);
|
||||
|
||||
let dest = result.project_field(bx, 0);
|
||||
bx.store(val, dest.llval, dest.align);
|
||||
let dest = result.project_field(bx, 1);
|
||||
bx.store(overflow, dest.llval, dest.align);
|
||||
|
||||
return;
|
||||
}
|
||||
sym::wrapping_add => bx.add(args[0].immediate(), args[1].immediate()),
|
||||
sym::wrapping_sub => bx.sub(args[0].immediate(), args[1].immediate()),
|
||||
sym::wrapping_mul => bx.mul(args[0].immediate(), args[1].immediate()),
|
||||
sym::exact_div => {
|
||||
if signed {
|
||||
bx.exactsdiv(args[0].immediate(), args[1].immediate())
|
||||
} else {
|
||||
bx.exactudiv(args[0].immediate(), args[1].immediate())
|
||||
}
|
||||
}
|
||||
sym::unchecked_div => {
|
||||
if signed {
|
||||
bx.sdiv(args[0].immediate(), args[1].immediate())
|
||||
} else {
|
||||
bx.udiv(args[0].immediate(), args[1].immediate())
|
||||
}
|
||||
}
|
||||
sym::unchecked_rem => {
|
||||
if signed {
|
||||
bx.srem(args[0].immediate(), args[1].immediate())
|
||||
} else {
|
||||
bx.urem(args[0].immediate(), args[1].immediate())
|
||||
}
|
||||
}
|
||||
sym::unchecked_shl => bx.shl(args[0].immediate(), args[1].immediate()),
|
||||
sym::unchecked_shr => {
|
||||
if signed {
|
||||
bx.ashr(args[0].immediate(), args[1].immediate())
|
||||
} else {
|
||||
bx.lshr(args[0].immediate(), args[1].immediate())
|
||||
}
|
||||
}
|
||||
sym::unchecked_add => {
|
||||
if signed {
|
||||
bx.unchecked_sadd(args[0].immediate(), args[1].immediate())
|
||||
} else {
|
||||
bx.unchecked_uadd(args[0].immediate(), args[1].immediate())
|
||||
}
|
||||
}
|
||||
sym::unchecked_sub => {
|
||||
if signed {
|
||||
bx.unchecked_ssub(args[0].immediate(), args[1].immediate())
|
||||
} else {
|
||||
bx.unchecked_usub(args[0].immediate(), args[1].immediate())
|
||||
}
|
||||
}
|
||||
sym::unchecked_mul => {
|
||||
if signed {
|
||||
bx.unchecked_smul(args[0].immediate(), args[1].immediate())
|
||||
} else {
|
||||
bx.unchecked_umul(args[0].immediate(), args[1].immediate())
|
||||
}
|
||||
}
|
||||
_ => bug!(),
|
||||
},
|
||||
None => {
|
||||
span_invalid_monomorphization_error(
|
||||
bx.tcx().sess,
|
||||
span,
|
||||
&format!(
|
||||
"invalid monomorphization of `{}` intrinsic: \
|
||||
expected basic integer type, found `{}`",
|
||||
name, ty
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
sym::fadd_fast | sym::fsub_fast | sym::fmul_fast | sym::fdiv_fast | sym::frem_fast => {
|
||||
match float_type_width(arg_tys[0]) {
|
||||
Some(_width) => match name {
|
||||
sym::fadd_fast => bx.fadd_fast(args[0].immediate(), args[1].immediate()),
|
||||
sym::fsub_fast => bx.fsub_fast(args[0].immediate(), args[1].immediate()),
|
||||
sym::fmul_fast => bx.fmul_fast(args[0].immediate(), args[1].immediate()),
|
||||
sym::fdiv_fast => bx.fdiv_fast(args[0].immediate(), args[1].immediate()),
|
||||
sym::frem_fast => bx.frem_fast(args[0].immediate(), args[1].immediate()),
|
||||
_ => bug!(),
|
||||
},
|
||||
None => {
|
||||
span_invalid_monomorphization_error(
|
||||
bx.tcx().sess,
|
||||
span,
|
||||
&format!(
|
||||
"invalid monomorphization of `{}` intrinsic: \
|
||||
expected basic float type, found `{}`",
|
||||
name, arg_tys[0]
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sym::float_to_int_unchecked => {
|
||||
if float_type_width(arg_tys[0]).is_none() {
|
||||
span_invalid_monomorphization_error(
|
||||
bx.tcx().sess,
|
||||
span,
|
||||
&format!(
|
||||
"invalid monomorphization of `float_to_int_unchecked` \
|
||||
intrinsic: expected basic float type, \
|
||||
found `{}`",
|
||||
arg_tys[0]
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
let (_width, signed) = match int_type_width_signed(ret_ty, bx.tcx()) {
|
||||
Some(pair) => pair,
|
||||
None => {
|
||||
span_invalid_monomorphization_error(
|
||||
bx.tcx().sess,
|
||||
span,
|
||||
&format!(
|
||||
"invalid monomorphization of `float_to_int_unchecked` \
|
||||
intrinsic: expected basic integer type, \
|
||||
found `{}`",
|
||||
ret_ty
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
};
|
||||
if signed {
|
||||
bx.fptosi(args[0].immediate(), llret_ty)
|
||||
} else {
|
||||
bx.fptoui(args[0].immediate(), llret_ty)
|
||||
}
|
||||
}
|
||||
|
||||
sym::discriminant_value => {
|
||||
if ret_ty.is_integral() {
|
||||
args[0].deref(bx.cx()).codegen_get_discr(bx, ret_ty)
|
||||
} else {
|
||||
span_bug!(span, "Invalid discriminant type for `{:?}`", arg_tys[0])
|
||||
}
|
||||
}
|
||||
|
||||
// This requires that atomic intrinsics follow a specific naming pattern:
|
||||
// "atomic_<operation>[_<ordering>]", and no ordering means SeqCst
|
||||
name if name_str.starts_with("atomic_") => {
|
||||
use crate::common::AtomicOrdering::*;
|
||||
use crate::common::{AtomicRmwBinOp, SynchronizationScope};
|
||||
|
||||
let split: Vec<&str> = name_str.split('_').collect();
|
||||
|
||||
let is_cxchg = split[1] == "cxchg" || split[1] == "cxchgweak";
|
||||
let (order, failorder) = match split.len() {
|
||||
2 => (SequentiallyConsistent, SequentiallyConsistent),
|
||||
3 => match split[2] {
|
||||
"unordered" => (Unordered, Unordered),
|
||||
"relaxed" => (Monotonic, Monotonic),
|
||||
"acq" => (Acquire, Acquire),
|
||||
"rel" => (Release, Monotonic),
|
||||
"acqrel" => (AcquireRelease, Acquire),
|
||||
"failrelaxed" if is_cxchg => (SequentiallyConsistent, Monotonic),
|
||||
"failacq" if is_cxchg => (SequentiallyConsistent, Acquire),
|
||||
_ => bx.sess().fatal("unknown ordering in atomic intrinsic"),
|
||||
},
|
||||
4 => match (split[2], split[3]) {
|
||||
("acq", "failrelaxed") if is_cxchg => (Acquire, Monotonic),
|
||||
("acqrel", "failrelaxed") if is_cxchg => (AcquireRelease, Monotonic),
|
||||
_ => bx.sess().fatal("unknown ordering in atomic intrinsic"),
|
||||
},
|
||||
_ => bx.sess().fatal("Atomic intrinsic not in correct format"),
|
||||
};
|
||||
|
||||
let invalid_monomorphization = |ty| {
|
||||
span_invalid_monomorphization_error(
|
||||
bx.tcx().sess,
|
||||
span,
|
||||
&format!(
|
||||
"invalid monomorphization of `{}` intrinsic: \
|
||||
expected basic integer type, found `{}`",
|
||||
name, ty
|
||||
),
|
||||
);
|
||||
};
|
||||
|
||||
match split[1] {
|
||||
"cxchg" | "cxchgweak" => {
|
||||
let ty = substs.type_at(0);
|
||||
if int_type_width_signed(ty, bx.tcx()).is_some() {
|
||||
let weak = split[1] == "cxchgweak";
|
||||
let pair = bx.atomic_cmpxchg(
|
||||
args[0].immediate(),
|
||||
args[1].immediate(),
|
||||
args[2].immediate(),
|
||||
order,
|
||||
failorder,
|
||||
weak,
|
||||
);
|
||||
let val = bx.extract_value(pair, 0);
|
||||
let success = bx.extract_value(pair, 1);
|
||||
let val = bx.from_immediate(val);
|
||||
let success = bx.from_immediate(success);
|
||||
|
||||
let dest = result.project_field(bx, 0);
|
||||
bx.store(val, dest.llval, dest.align);
|
||||
let dest = result.project_field(bx, 1);
|
||||
bx.store(success, dest.llval, dest.align);
|
||||
return;
|
||||
} else {
|
||||
return invalid_monomorphization(ty);
|
||||
}
|
||||
}
|
||||
|
||||
"load" => {
|
||||
let ty = substs.type_at(0);
|
||||
if int_type_width_signed(ty, bx.tcx()).is_some() {
|
||||
let size = bx.layout_of(ty).size;
|
||||
bx.atomic_load(args[0].immediate(), order, size)
|
||||
} else {
|
||||
return invalid_monomorphization(ty);
|
||||
}
|
||||
}
|
||||
|
||||
"store" => {
|
||||
let ty = substs.type_at(0);
|
||||
if int_type_width_signed(ty, bx.tcx()).is_some() {
|
||||
let size = bx.layout_of(ty).size;
|
||||
bx.atomic_store(args[1].immediate(), args[0].immediate(), order, size);
|
||||
return;
|
||||
} else {
|
||||
return invalid_monomorphization(ty);
|
||||
}
|
||||
}
|
||||
|
||||
"fence" => {
|
||||
bx.atomic_fence(order, SynchronizationScope::CrossThread);
|
||||
return;
|
||||
}
|
||||
|
||||
"singlethreadfence" => {
|
||||
bx.atomic_fence(order, SynchronizationScope::SingleThread);
|
||||
return;
|
||||
}
|
||||
|
||||
// These are all AtomicRMW ops
|
||||
op => {
|
||||
let atom_op = match op {
|
||||
"xchg" => AtomicRmwBinOp::AtomicXchg,
|
||||
"xadd" => AtomicRmwBinOp::AtomicAdd,
|
||||
"xsub" => AtomicRmwBinOp::AtomicSub,
|
||||
"and" => AtomicRmwBinOp::AtomicAnd,
|
||||
"nand" => AtomicRmwBinOp::AtomicNand,
|
||||
"or" => AtomicRmwBinOp::AtomicOr,
|
||||
"xor" => AtomicRmwBinOp::AtomicXor,
|
||||
"max" => AtomicRmwBinOp::AtomicMax,
|
||||
"min" => AtomicRmwBinOp::AtomicMin,
|
||||
"umax" => AtomicRmwBinOp::AtomicUMax,
|
||||
"umin" => AtomicRmwBinOp::AtomicUMin,
|
||||
_ => bx.sess().fatal("unknown atomic operation"),
|
||||
};
|
||||
|
||||
let ty = substs.type_at(0);
|
||||
if int_type_width_signed(ty, bx.tcx()).is_some() {
|
||||
bx.atomic_rmw(atom_op, args[0].immediate(), args[1].immediate(), order)
|
||||
} else {
|
||||
return invalid_monomorphization(ty);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sym::nontemporal_store => {
|
||||
let dst = args[0].deref(bx.cx());
|
||||
args[1].val.nontemporal_store(bx, dst);
|
||||
return;
|
||||
}
|
||||
|
||||
sym::ptr_guaranteed_eq | sym::ptr_guaranteed_ne => {
|
||||
let a = args[0].immediate();
|
||||
let b = args[1].immediate();
|
||||
if name == sym::ptr_guaranteed_eq {
|
||||
bx.icmp(IntPredicate::IntEQ, a, b)
|
||||
} else {
|
||||
bx.icmp(IntPredicate::IntNE, a, b)
|
||||
}
|
||||
}
|
||||
|
||||
sym::ptr_offset_from => {
|
||||
let ty = substs.type_at(0);
|
||||
let pointee_size = bx.layout_of(ty).size;
|
||||
|
||||
// This is the same sequence that Clang emits for pointer subtraction.
|
||||
// It can be neither `nsw` nor `nuw` because the input is treated as
|
||||
// unsigned but then the output is treated as signed, so neither works.
|
||||
let a = args[0].immediate();
|
||||
let b = args[1].immediate();
|
||||
let a = bx.ptrtoint(a, bx.type_isize());
|
||||
let b = bx.ptrtoint(b, bx.type_isize());
|
||||
let d = bx.sub(a, b);
|
||||
let pointee_size = bx.const_usize(pointee_size.bytes());
|
||||
// this is where the signed magic happens (notice the `s` in `exactsdiv`)
|
||||
bx.exactsdiv(d, pointee_size)
|
||||
}
|
||||
|
||||
_ => {
|
||||
// Need to use backend-specific things in the implementation.
|
||||
bx.codegen_intrinsic_call(instance, fn_abi, args, llresult, span);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
if !fn_abi.ret.is_ignore() {
|
||||
if let PassMode::Cast(ty) = fn_abi.ret.mode {
|
||||
let ptr_llty = bx.type_ptr_to(bx.cast_backend_type(&ty));
|
||||
let ptr = bx.pointercast(result.llval, ptr_llty);
|
||||
bx.store(llval, ptr, result.align);
|
||||
} else {
|
||||
OperandRef::from_immediate_or_packed_pair(bx, llval, result.layout)
|
||||
.val
|
||||
.store(bx, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the width of an int Ty, and if it's signed or not
|
||||
// Returns None if the type is not an integer
|
||||
// FIXME: there’s multiple of this functions, investigate using some of the already existing
|
||||
// stuffs.
|
||||
fn int_type_width_signed(ty: Ty<'_>, tcx: TyCtxt<'_>) -> Option<(u64, bool)> {
|
||||
match ty.kind() {
|
||||
ty::Int(t) => Some((t.bit_width().unwrap_or(u64::from(tcx.sess.target.ptr_width)), true)),
|
||||
ty::Uint(t) => Some((t.bit_width().unwrap_or(u64::from(tcx.sess.target.ptr_width)), false)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
// Returns the width of a float Ty
|
||||
// Returns None if the type is not a float
|
||||
fn float_type_width(ty: Ty<'_>) -> Option<u64> {
|
||||
match ty.kind() {
|
||||
ty::Float(t) => Some(t.bit_width()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
|
@ -486,6 +486,7 @@ mod block;
|
|||
pub mod constant;
|
||||
pub mod coverageinfo;
|
||||
pub mod debuginfo;
|
||||
mod intrinsic;
|
||||
pub mod operand;
|
||||
pub mod place;
|
||||
mod rvalue;
|
||||
|
|
|
@ -93,15 +93,33 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
|
|||
let effective_field_align = self.align.restrict_for_offset(offset);
|
||||
|
||||
let mut simple = || {
|
||||
// Unions and newtypes only use an offset of 0.
|
||||
let llval = if offset.bytes() == 0 {
|
||||
self.llval
|
||||
} else if let Abi::ScalarPair(ref a, ref b) = self.layout.abi {
|
||||
// Offsets have to match either first or second field.
|
||||
assert_eq!(offset, a.value.size(bx.cx()).align_to(b.value.align(bx.cx()).abi));
|
||||
bx.struct_gep(self.llval, 1)
|
||||
} else {
|
||||
bx.struct_gep(self.llval, bx.cx().backend_field_index(self.layout, ix))
|
||||
let llval = match self.layout.abi {
|
||||
_ if offset.bytes() == 0 => {
|
||||
// Unions and newtypes only use an offset of 0.
|
||||
// Also handles the first field of Scalar, ScalarPair, and Vector layouts.
|
||||
self.llval
|
||||
}
|
||||
Abi::ScalarPair(ref a, ref b)
|
||||
if offset == a.value.size(bx.cx()).align_to(b.value.align(bx.cx()).abi) =>
|
||||
{
|
||||
// Offset matches second field.
|
||||
bx.struct_gep(self.llval, 1)
|
||||
}
|
||||
Abi::Scalar(_) | Abi::ScalarPair(..) | Abi::Vector { .. } if field.is_zst() => {
|
||||
// ZST fields are not included in Scalar, ScalarPair, and Vector layouts, so manually offset the pointer.
|
||||
let byte_ptr = bx.pointercast(self.llval, bx.cx().type_i8p());
|
||||
bx.gep(byte_ptr, &[bx.const_usize(offset.bytes())])
|
||||
}
|
||||
Abi::Scalar(_) | Abi::ScalarPair(..) => {
|
||||
// All fields of Scalar and ScalarPair layouts must have been handled by this point.
|
||||
// Vector layouts have additional fields for each element of the vector, so don't panic in that case.
|
||||
bug!(
|
||||
"offset of non-ZST field `{:?}` does not match layout `{:#?}`",
|
||||
field,
|
||||
self.layout
|
||||
);
|
||||
}
|
||||
_ => bx.struct_gep(self.llval, bx.cx().backend_field_index(self.layout, ix)),
|
||||
};
|
||||
PlaceRef {
|
||||
// HACK(eddyb): have to bitcast pointers until LLVM removes pointee types.
|
||||
|
|
|
@ -0,0 +1,150 @@
|
|||
use rustc_session::Session;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::symbol::Symbol;
|
||||
|
||||
const ARM_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
|
||||
("aclass", Some(sym::arm_target_feature)),
|
||||
("mclass", Some(sym::arm_target_feature)),
|
||||
("rclass", Some(sym::arm_target_feature)),
|
||||
("dsp", Some(sym::arm_target_feature)),
|
||||
("neon", Some(sym::arm_target_feature)),
|
||||
("crc", Some(sym::arm_target_feature)),
|
||||
("crypto", Some(sym::arm_target_feature)),
|
||||
("v5te", Some(sym::arm_target_feature)),
|
||||
("v6", Some(sym::arm_target_feature)),
|
||||
("v6k", Some(sym::arm_target_feature)),
|
||||
("v6t2", Some(sym::arm_target_feature)),
|
||||
("v7", Some(sym::arm_target_feature)),
|
||||
("v8", Some(sym::arm_target_feature)),
|
||||
("vfp2", Some(sym::arm_target_feature)),
|
||||
("vfp3", Some(sym::arm_target_feature)),
|
||||
("vfp4", Some(sym::arm_target_feature)),
|
||||
// This is needed for inline assembly, but shouldn't be stabilized as-is
|
||||
// since it should be enabled per-function using #[instruction_set], not
|
||||
// #[target_feature].
|
||||
("thumb-mode", Some(sym::arm_target_feature)),
|
||||
];
|
||||
|
||||
const AARCH64_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
|
||||
("fp", Some(sym::aarch64_target_feature)),
|
||||
("neon", Some(sym::aarch64_target_feature)),
|
||||
("sve", Some(sym::aarch64_target_feature)),
|
||||
("crc", Some(sym::aarch64_target_feature)),
|
||||
("crypto", Some(sym::aarch64_target_feature)),
|
||||
("ras", Some(sym::aarch64_target_feature)),
|
||||
("lse", Some(sym::aarch64_target_feature)),
|
||||
("rdm", Some(sym::aarch64_target_feature)),
|
||||
("fp16", Some(sym::aarch64_target_feature)),
|
||||
("rcpc", Some(sym::aarch64_target_feature)),
|
||||
("dotprod", Some(sym::aarch64_target_feature)),
|
||||
("tme", Some(sym::aarch64_target_feature)),
|
||||
("v8.1a", Some(sym::aarch64_target_feature)),
|
||||
("v8.2a", Some(sym::aarch64_target_feature)),
|
||||
("v8.3a", Some(sym::aarch64_target_feature)),
|
||||
];
|
||||
|
||||
const X86_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
|
||||
("adx", Some(sym::adx_target_feature)),
|
||||
("aes", None),
|
||||
("avx", None),
|
||||
("avx2", None),
|
||||
("avx512bw", Some(sym::avx512_target_feature)),
|
||||
("avx512cd", Some(sym::avx512_target_feature)),
|
||||
("avx512dq", Some(sym::avx512_target_feature)),
|
||||
("avx512er", Some(sym::avx512_target_feature)),
|
||||
("avx512f", Some(sym::avx512_target_feature)),
|
||||
("avx512ifma", Some(sym::avx512_target_feature)),
|
||||
("avx512pf", Some(sym::avx512_target_feature)),
|
||||
("avx512vbmi", Some(sym::avx512_target_feature)),
|
||||
("avx512vl", Some(sym::avx512_target_feature)),
|
||||
("avx512vpopcntdq", Some(sym::avx512_target_feature)),
|
||||
("bmi1", None),
|
||||
("bmi2", None),
|
||||
("cmpxchg16b", Some(sym::cmpxchg16b_target_feature)),
|
||||
("f16c", Some(sym::f16c_target_feature)),
|
||||
("fma", None),
|
||||
("fxsr", None),
|
||||
("lzcnt", None),
|
||||
("movbe", Some(sym::movbe_target_feature)),
|
||||
("pclmulqdq", None),
|
||||
("popcnt", None),
|
||||
("rdrand", None),
|
||||
("rdseed", None),
|
||||
("rtm", Some(sym::rtm_target_feature)),
|
||||
("sha", None),
|
||||
("sse", None),
|
||||
("sse2", None),
|
||||
("sse3", None),
|
||||
("sse4.1", None),
|
||||
("sse4.2", None),
|
||||
("sse4a", Some(sym::sse4a_target_feature)),
|
||||
("ssse3", None),
|
||||
("tbm", Some(sym::tbm_target_feature)),
|
||||
("xsave", None),
|
||||
("xsavec", None),
|
||||
("xsaveopt", None),
|
||||
("xsaves", None),
|
||||
];
|
||||
|
||||
const HEXAGON_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
|
||||
("hvx", Some(sym::hexagon_target_feature)),
|
||||
("hvx-length128b", Some(sym::hexagon_target_feature)),
|
||||
];
|
||||
|
||||
const POWERPC_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
|
||||
("altivec", Some(sym::powerpc_target_feature)),
|
||||
("power8-altivec", Some(sym::powerpc_target_feature)),
|
||||
("power9-altivec", Some(sym::powerpc_target_feature)),
|
||||
("power8-vector", Some(sym::powerpc_target_feature)),
|
||||
("power9-vector", Some(sym::powerpc_target_feature)),
|
||||
("vsx", Some(sym::powerpc_target_feature)),
|
||||
];
|
||||
|
||||
const MIPS_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] =
|
||||
&[("fp64", Some(sym::mips_target_feature)), ("msa", Some(sym::mips_target_feature))];
|
||||
|
||||
const RISCV_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
|
||||
("m", Some(sym::riscv_target_feature)),
|
||||
("a", Some(sym::riscv_target_feature)),
|
||||
("c", Some(sym::riscv_target_feature)),
|
||||
("f", Some(sym::riscv_target_feature)),
|
||||
("d", Some(sym::riscv_target_feature)),
|
||||
("e", Some(sym::riscv_target_feature)),
|
||||
];
|
||||
|
||||
const WASM_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
|
||||
("simd128", Some(sym::wasm_target_feature)),
|
||||
("atomics", Some(sym::wasm_target_feature)),
|
||||
("nontrapping-fptoint", Some(sym::wasm_target_feature)),
|
||||
];
|
||||
|
||||
/// When rustdoc is running, provide a list of all known features so that all their respective
|
||||
/// primitives may be documented.
|
||||
///
|
||||
/// IMPORTANT: If you're adding another feature list above, make sure to add it to this iterator!
|
||||
pub fn all_known_features() -> impl Iterator<Item = (&'static str, Option<Symbol>)> {
|
||||
std::iter::empty()
|
||||
.chain(ARM_ALLOWED_FEATURES.iter())
|
||||
.chain(AARCH64_ALLOWED_FEATURES.iter())
|
||||
.chain(X86_ALLOWED_FEATURES.iter())
|
||||
.chain(HEXAGON_ALLOWED_FEATURES.iter())
|
||||
.chain(POWERPC_ALLOWED_FEATURES.iter())
|
||||
.chain(MIPS_ALLOWED_FEATURES.iter())
|
||||
.chain(RISCV_ALLOWED_FEATURES.iter())
|
||||
.chain(WASM_ALLOWED_FEATURES.iter())
|
||||
.cloned()
|
||||
}
|
||||
|
||||
pub fn supported_target_features(sess: &Session) -> &'static [(&'static str, Option<Symbol>)] {
|
||||
match &*sess.target.target.arch {
|
||||
"arm" => ARM_ALLOWED_FEATURES,
|
||||
"aarch64" => AARCH64_ALLOWED_FEATURES,
|
||||
"x86" | "x86_64" => X86_ALLOWED_FEATURES,
|
||||
"hexagon" => HEXAGON_ALLOWED_FEATURES,
|
||||
"mips" | "mips64" => MIPS_ALLOWED_FEATURES,
|
||||
"powerpc" | "powerpc64" => POWERPC_ALLOWED_FEATURES,
|
||||
"riscv32" | "riscv64" => RISCV_ALLOWED_FEATURES,
|
||||
"wasm32" => WASM_ALLOWED_FEATURES,
|
||||
_ => &[],
|
||||
}
|
||||
}
|
|
@ -15,6 +15,7 @@ use rustc_session::{
|
|||
};
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_target::abi::LayoutOf;
|
||||
use rustc_target::spec::Target;
|
||||
|
||||
pub use rustc_data_structures::sync::MetadataRef;
|
||||
|
||||
|
@ -54,6 +55,12 @@ pub trait CodegenBackend {
|
|||
fn print_passes(&self) {}
|
||||
fn print_version(&self) {}
|
||||
|
||||
/// If this plugin provides additional builtin targets, provide the one enabled by the options here.
|
||||
/// Be careful: this is called *before* init() is called.
|
||||
fn target_override(&self, _opts: &config::Options) -> Option<Target> {
|
||||
None
|
||||
}
|
||||
|
||||
fn metadata_loader(&self) -> Box<MetadataLoaderDyn>;
|
||||
fn provide(&self, _providers: &mut Providers);
|
||||
fn provide_extern(&self, _providers: &mut Providers);
|
||||
|
@ -102,6 +109,7 @@ pub trait ExtraBackendMethods: CodegenBackend + WriteBackendMethods + Sized + Se
|
|||
tcx: TyCtxt<'tcx>,
|
||||
mods: &mut Self::Module,
|
||||
kind: AllocatorKind,
|
||||
has_alloc_error_handler: bool,
|
||||
);
|
||||
/// This generates the codegen unit and returns it along with
|
||||
/// a `u64` giving an estimate of the unit's processing cost.
|
||||
|
|
|
@ -18,7 +18,6 @@ use rustc_middle::ty::Ty;
|
|||
use rustc_target::abi::{Abi, Align, Scalar, Size};
|
||||
use rustc_target::spec::HasTargetSpec;
|
||||
|
||||
use std::iter::TrustedLen;
|
||||
use std::ops::Range;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
|
@ -60,7 +59,7 @@ pub trait BuilderMethods<'a, 'tcx>:
|
|||
&mut self,
|
||||
v: Self::Value,
|
||||
else_llbb: Self::BasicBlock,
|
||||
cases: impl ExactSizeIterator<Item = (u128, Self::BasicBlock)> + TrustedLen,
|
||||
cases: impl ExactSizeIterator<Item = (u128, Self::BasicBlock)>,
|
||||
);
|
||||
fn invoke(
|
||||
&mut self,
|
||||
|
|
|
@ -1,51 +1,7 @@
|
|||
use super::BackendTypes;
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_middle::mir::mono::{Linkage, Visibility};
|
||||
use rustc_middle::ty::{Instance, Ty};
|
||||
use rustc_target::abi::call::FnAbi;
|
||||
|
||||
pub trait DeclareMethods<'tcx>: BackendTypes {
|
||||
/// Declare a global value.
|
||||
///
|
||||
/// If there’s a value with the same name already declared, the function will
|
||||
/// return its Value instead.
|
||||
fn declare_global(&self, name: &str, ty: Self::Type) -> Self::Value;
|
||||
|
||||
/// Declare a C ABI function.
|
||||
///
|
||||
/// Only use this for foreign function ABIs and glue. For Rust functions use
|
||||
/// `declare_fn` instead.
|
||||
///
|
||||
/// If there’s a value with the same name already declared, the function will
|
||||
/// update the declaration and return existing Value instead.
|
||||
fn declare_cfn(&self, name: &str, fn_type: Self::Type) -> Self::Function;
|
||||
|
||||
/// Declare a Rust function.
|
||||
///
|
||||
/// If there’s a value with the same name already declared, the function will
|
||||
/// update the declaration and return existing Value instead.
|
||||
fn declare_fn(&self, name: &str, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Self::Function;
|
||||
|
||||
/// Declare a global with an intention to define it.
|
||||
///
|
||||
/// Use this function when you intend to define a global. This function will
|
||||
/// return `None` if the name already has a definition associated with it. In that
|
||||
/// case an error should be reported to the user, because it usually happens due
|
||||
/// to user’s fault (e.g., misuse of `#[no_mangle]` or `#[export_name]` attributes).
|
||||
fn define_global(&self, name: &str, ty: Self::Type) -> Option<Self::Value>;
|
||||
|
||||
/// Declare a private global
|
||||
///
|
||||
/// Use this function when you intend to define a global without a name.
|
||||
fn define_private_global(&self, ty: Self::Type) -> Self::Value;
|
||||
|
||||
/// Gets declared value by name.
|
||||
fn get_declared_value(&self, name: &str) -> Option<Self::Value>;
|
||||
|
||||
/// Gets defined or externally defined (AvailableExternally linkage) value by
|
||||
/// name.
|
||||
fn get_defined_value(&self, name: &str) -> Option<Self::Value>;
|
||||
}
|
||||
use rustc_middle::ty::Instance;
|
||||
|
||||
pub trait PreDefineMethods<'tcx>: BackendTypes {
|
||||
fn predefine_static(
|
||||
|
|
|
@ -5,9 +5,9 @@ use rustc_span::Span;
|
|||
use rustc_target::abi::call::FnAbi;
|
||||
|
||||
pub trait IntrinsicCallMethods<'tcx>: BackendTypes {
|
||||
/// Remember to add all intrinsics here, in librustc_typeck/check/mod.rs,
|
||||
/// and in libcore/intrinsics.rs; if you need access to any llvm intrinsics,
|
||||
/// add them to librustc_codegen_llvm/context.rs
|
||||
/// Remember to add all intrinsics here, in `compiler/rustc_typeck/src/check/mod.rs`,
|
||||
/// and in `library/core/src/intrinsics.rs`; if you need access to any LLVM intrinsics,
|
||||
/// add them to `compiler/rustc_codegen_llvm/src/context.rs`.
|
||||
fn codegen_intrinsic_call(
|
||||
&mut self,
|
||||
instance: ty::Instance<'tcx>,
|
||||
|
|
|
@ -19,4 +19,6 @@ pub trait MiscMethods<'tcx>: BackendTypes {
|
|||
fn set_frame_pointer_elimination(&self, llfn: Self::Function);
|
||||
fn apply_target_cpu_attr(&self, llfn: Self::Function);
|
||||
fn create_used_variable(&self);
|
||||
/// Declares the extern "C" main function for the entry point. Returns None if the symbol already exists.
|
||||
fn declare_c_main(&self, fn_type: Self::Type) -> Option<Self::Function>;
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ pub use self::builder::{BuilderMethods, OverflowOp};
|
|||
pub use self::consts::ConstMethods;
|
||||
pub use self::coverageinfo::{CoverageInfoBuilderMethods, CoverageInfoMethods};
|
||||
pub use self::debuginfo::{DebugInfoBuilderMethods, DebugInfoMethods};
|
||||
pub use self::declare::{DeclareMethods, PreDefineMethods};
|
||||
pub use self::declare::PreDefineMethods;
|
||||
pub use self::intrinsic::IntrinsicCallMethods;
|
||||
pub use self::misc::MiscMethods;
|
||||
pub use self::statics::{StaticBuilderMethods, StaticMethods};
|
||||
|
@ -60,7 +60,6 @@ pub trait CodegenMethods<'tcx>:
|
|||
+ StaticMethods
|
||||
+ CoverageInfoMethods
|
||||
+ DebugInfoMethods<'tcx>
|
||||
+ DeclareMethods<'tcx>
|
||||
+ AsmMethods
|
||||
+ PreDefineMethods<'tcx>
|
||||
+ HasParamEnv<'tcx>
|
||||
|
@ -77,7 +76,6 @@ impl<'tcx, T> CodegenMethods<'tcx> for T where
|
|||
+ StaticMethods
|
||||
+ CoverageInfoMethods
|
||||
+ DebugInfoMethods<'tcx>
|
||||
+ DeclareMethods<'tcx>
|
||||
+ AsmMethods
|
||||
+ PreDefineMethods<'tcx>
|
||||
+ HasParamEnv<'tcx>
|
||||
|
|
|
@ -13,6 +13,12 @@ pub trait WriteBackendMethods: 'static + Sized + Clone {
|
|||
type ThinData: Send + Sync;
|
||||
type ThinBuffer: ThinBufferMethods;
|
||||
|
||||
/// Merge all modules into main_module and returning it
|
||||
fn run_link(
|
||||
cgcx: &CodegenContext<Self>,
|
||||
diag_handler: &Handler,
|
||||
modules: Vec<ModuleCodegen<Self::Module>>,
|
||||
) -> Result<ModuleCodegen<Self::Module>, FatalError>;
|
||||
/// Performs fat LTO by merging all modules into a single one and returning it
|
||||
/// for further optimization.
|
||||
fn run_fat_lto(
|
||||
|
|
|
@ -8,6 +8,7 @@ edition = "2018"
|
|||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
arrayvec = { version = "0.5.1", default-features = false }
|
||||
ena = "0.14"
|
||||
indexmap = "1.5.1"
|
||||
tracing = "0.1"
|
||||
|
@ -26,11 +27,11 @@ rustc_index = { path = "../rustc_index", package = "rustc_index" }
|
|||
bitflags = "1.2.1"
|
||||
measureme = "0.7.1"
|
||||
libc = "0.2"
|
||||
stacker = "0.1.11"
|
||||
stacker = "0.1.12"
|
||||
tempfile = "3.0.5"
|
||||
|
||||
[dependencies.parking_lot]
|
||||
version = "0.10"
|
||||
version = "0.11"
|
||||
features = ["nightly"]
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
|
|
|
@ -9,6 +9,7 @@ use super::iterate::reverse_post_order;
|
|||
use super::ControlFlowGraph;
|
||||
use rustc_index::vec::{Idx, IndexVec};
|
||||
use std::borrow::BorrowMut;
|
||||
use std::cmp::Ordering;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
@ -108,6 +109,14 @@ impl<Node: Idx> Dominators<Node> {
|
|||
// FIXME -- could be optimized by using post-order-rank
|
||||
self.dominators(node).any(|n| n == dom)
|
||||
}
|
||||
|
||||
/// Provide deterministic ordering of nodes such that, if any two nodes have a dominator
|
||||
/// relationship, the dominator will always precede the dominated. (The relative ordering
|
||||
/// of two unrelated nodes will also be consistent, but otherwise the order has no
|
||||
/// meaning.) This method cannot be used to determine if either Node dominates the other.
|
||||
pub fn rank_partial_cmp(&self, lhs: Node, rhs: Node) -> Option<Ordering> {
|
||||
self.post_order_rank[lhs].partial_cmp(&self.post_order_rank[rhs])
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Iter<'dom, Node: Idx> {
|
||||
|
|
|
@ -87,11 +87,8 @@ where
|
|||
}
|
||||
|
||||
/// Allows searches to terminate early with a value.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum ControlFlow<T> {
|
||||
Break(T),
|
||||
Continue,
|
||||
}
|
||||
// FIXME (#75744): remove the alias once the generics are in a better order and `C=()`.
|
||||
pub type ControlFlow<T> = std::ops::ControlFlow<(), T>;
|
||||
|
||||
/// The status of a node in the depth-first search.
|
||||
///
|
||||
|
@ -260,12 +257,12 @@ where
|
|||
_node: G::Node,
|
||||
_prior_status: Option<NodeStatus>,
|
||||
) -> ControlFlow<Self::BreakVal> {
|
||||
ControlFlow::Continue
|
||||
ControlFlow::CONTINUE
|
||||
}
|
||||
|
||||
/// Called after all nodes reachable from this one have been examined.
|
||||
fn node_settled(&mut self, _node: G::Node) -> ControlFlow<Self::BreakVal> {
|
||||
ControlFlow::Continue
|
||||
ControlFlow::CONTINUE
|
||||
}
|
||||
|
||||
/// Behave as if no edges exist from `source` to `target`.
|
||||
|
@ -289,8 +286,8 @@ where
|
|||
prior_status: Option<NodeStatus>,
|
||||
) -> ControlFlow<Self::BreakVal> {
|
||||
match prior_status {
|
||||
Some(NodeStatus::Visited) => ControlFlow::Break(()),
|
||||
_ => ControlFlow::Continue,
|
||||
Some(NodeStatus::Visited) => ControlFlow::BREAK,
|
||||
_ => ControlFlow::CONTINUE,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,13 +6,14 @@
|
|||
//!
|
||||
//! This API is completely unstable and subject to change.
|
||||
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
|
||||
#![allow(incomplete_features)]
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![feature(array_windows)]
|
||||
#![feature(control_flow_enum)]
|
||||
#![feature(in_band_lifetimes)]
|
||||
#![feature(unboxed_closures)]
|
||||
#![feature(generators)]
|
||||
#![feature(generator_trait)]
|
||||
#![feature(fn_traits)]
|
||||
#![feature(int_bits_const)]
|
||||
#![feature(min_specialization)]
|
||||
#![feature(optin_builtin_traits)]
|
||||
#![feature(nll)]
|
||||
|
@ -25,7 +26,7 @@
|
|||
#![feature(thread_id_value)]
|
||||
#![feature(extend_one)]
|
||||
#![feature(const_panic)]
|
||||
#![feature(const_generics)]
|
||||
#![feature(min_const_generics)]
|
||||
#![feature(once_cell)]
|
||||
#![allow(rustc::default_hash_types)]
|
||||
|
||||
|
@ -86,25 +87,27 @@ pub mod sorted_map;
|
|||
pub mod stable_set;
|
||||
#[macro_use]
|
||||
pub mod stable_hasher;
|
||||
mod atomic_ref;
|
||||
pub mod fingerprint;
|
||||
pub mod profiling;
|
||||
pub mod sharded;
|
||||
pub mod stack;
|
||||
pub mod sync;
|
||||
pub mod thin_vec;
|
||||
pub mod tiny_list;
|
||||
pub mod transitive_relation;
|
||||
pub use ena::undo_log;
|
||||
pub use ena::unify;
|
||||
mod atomic_ref;
|
||||
pub mod fingerprint;
|
||||
pub mod profiling;
|
||||
pub mod vec_linked_list;
|
||||
pub mod work_queue;
|
||||
pub use atomic_ref::AtomicRef;
|
||||
pub mod frozen;
|
||||
pub mod sso;
|
||||
pub mod tagged_ptr;
|
||||
pub mod temp_dir;
|
||||
pub mod unhash;
|
||||
|
||||
pub use ena::undo_log;
|
||||
pub use ena::unify;
|
||||
|
||||
pub struct OnDrop<F: Fn()>(pub F);
|
||||
|
||||
impl<F: Fn()> OnDrop<F> {
|
||||
|
|
|
@ -1,15 +1,3 @@
|
|||
/// A simple static assertion macro.
|
||||
#[macro_export]
|
||||
#[allow_internal_unstable(type_ascription)]
|
||||
macro_rules! static_assert {
|
||||
($test:expr) => {
|
||||
// Use the bool to access an array such that if the bool is false, the access
|
||||
// is out-of-bounds.
|
||||
#[allow(dead_code)]
|
||||
const _: () = [()][!($test: bool) as usize];
|
||||
};
|
||||
}
|
||||
|
||||
/// Type size assertion. The first argument is a type and the second argument is its expected size.
|
||||
#[macro_export]
|
||||
macro_rules! static_assert_size {
|
||||
|
|
|
@ -600,10 +600,7 @@ pub fn print_time_passes_entry(do_it: bool, what: &str, dur: Duration) {
|
|||
// Hack up our own formatting for the duration to make it easier for scripts
|
||||
// to parse (always use the same number of decimal places and the same unit).
|
||||
pub fn duration_to_secs_str(dur: std::time::Duration) -> String {
|
||||
const NANOS_PER_SEC: f64 = 1_000_000_000.0;
|
||||
let secs = dur.as_secs() as f64 + dur.subsec_nanos() as f64 / NANOS_PER_SEC;
|
||||
|
||||
format!("{:.3}", secs)
|
||||
format!("{:.3}", dur.as_secs_f64())
|
||||
}
|
||||
|
||||
// Memory reporting
|
||||
|
|
|
@ -125,15 +125,28 @@ impl SipHasher128 {
|
|||
|
||||
// A specialized write function for values with size <= 8.
|
||||
//
|
||||
// The hashing of multi-byte integers depends on endianness. E.g.:
|
||||
// The input must be zero-extended to 64-bits by the caller. This extension
|
||||
// isn't hashed, but the implementation requires it for correctness.
|
||||
//
|
||||
// This function, given the same integer size and value, has the same effect
|
||||
// on both little- and big-endian hardware. It operates on values without
|
||||
// depending on their sequence in memory, so is independent of endianness.
|
||||
//
|
||||
// However, we want SipHasher128 to be platform-dependent, in order to be
|
||||
// consistent with the platform-dependent SipHasher in libstd. In other
|
||||
// words, we want:
|
||||
//
|
||||
// - little-endian: `write_u32(0xDDCCBBAA)` == `write([0xAA, 0xBB, 0xCC, 0xDD])`
|
||||
// - big-endian: `write_u32(0xDDCCBBAA)` == `write([0xDD, 0xCC, 0xBB, 0xAA])`
|
||||
//
|
||||
// This function does the right thing for little-endian hardware. On
|
||||
// big-endian hardware `x` must be byte-swapped first to give the right
|
||||
// behaviour. After any byte-swapping, the input must be zero-extended to
|
||||
// 64-bits. The caller is responsible for the byte-swapping and
|
||||
// zero-extension.
|
||||
// Therefore, in order to produce endian-dependent results, SipHasher128's
|
||||
// `write_xxx` Hasher trait methods byte-swap `x` prior to zero-extending.
|
||||
//
|
||||
// If clients of SipHasher128 itself want platform-independent results, they
|
||||
// *also* must byte-swap integer inputs before invoking the `write_xxx`
|
||||
// methods on big-endian hardware (that is, two byte-swaps must occur--one
|
||||
// in the client, and one in SipHasher128). Additionally, they must extend
|
||||
// `usize` and `isize` types to 64 bits on 32-bit systems.
|
||||
#[inline]
|
||||
fn short_write<T>(&mut self, _x: T, x: u64) {
|
||||
let size = mem::size_of::<T>();
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use super::*;
|
||||
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::{mem, slice};
|
||||
|
||||
// Hash just the bytes of the slice, without length prefix
|
||||
struct Bytes<'a>(&'a [u8]);
|
||||
|
@ -399,20 +398,55 @@ fn test_hash_no_concat_alias() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_write_short_works() {
|
||||
let test_usize = 0xd0c0b0a0usize;
|
||||
fn test_short_write_works() {
|
||||
let test_u8 = 0xFF_u8;
|
||||
let test_u16 = 0x1122_u16;
|
||||
let test_u32 = 0x22334455_u32;
|
||||
let test_u64 = 0x33445566_778899AA_u64;
|
||||
let test_u128 = 0x11223344_55667788_99AABBCC_DDEEFF77_u128;
|
||||
let test_usize = 0xD0C0B0A0_usize;
|
||||
|
||||
let test_i8 = -1_i8;
|
||||
let test_i16 = -2_i16;
|
||||
let test_i32 = -3_i32;
|
||||
let test_i64 = -4_i64;
|
||||
let test_i128 = -5_i128;
|
||||
let test_isize = -6_isize;
|
||||
|
||||
let mut h1 = SipHasher128::new_with_keys(0, 0);
|
||||
h1.write_usize(test_usize);
|
||||
h1.write(b"bytes");
|
||||
h1.write(b"string");
|
||||
h1.write_u8(0xFFu8);
|
||||
h1.write_u8(0x01u8);
|
||||
h1.write_u8(test_u8);
|
||||
h1.write_u16(test_u16);
|
||||
h1.write_u32(test_u32);
|
||||
h1.write_u64(test_u64);
|
||||
h1.write_u128(test_u128);
|
||||
h1.write_usize(test_usize);
|
||||
h1.write_i8(test_i8);
|
||||
h1.write_i16(test_i16);
|
||||
h1.write_i32(test_i32);
|
||||
h1.write_i64(test_i64);
|
||||
h1.write_i128(test_i128);
|
||||
h1.write_isize(test_isize);
|
||||
|
||||
let mut h2 = SipHasher128::new_with_keys(0, 0);
|
||||
h2.write(unsafe {
|
||||
slice::from_raw_parts(&test_usize as *const _ as *const u8, mem::size_of::<usize>())
|
||||
});
|
||||
h2.write(b"bytes");
|
||||
h2.write(b"string");
|
||||
h2.write(&[0xFFu8, 0x01u8]);
|
||||
assert_eq!(h1.finish128(), h2.finish128());
|
||||
h2.write(&test_u8.to_ne_bytes());
|
||||
h2.write(&test_u16.to_ne_bytes());
|
||||
h2.write(&test_u32.to_ne_bytes());
|
||||
h2.write(&test_u64.to_ne_bytes());
|
||||
h2.write(&test_u128.to_ne_bytes());
|
||||
h2.write(&test_usize.to_ne_bytes());
|
||||
h2.write(&test_i8.to_ne_bytes());
|
||||
h2.write(&test_i16.to_ne_bytes());
|
||||
h2.write(&test_i32.to_ne_bytes());
|
||||
h2.write(&test_i64.to_ne_bytes());
|
||||
h2.write(&test_i128.to_ne_bytes());
|
||||
h2.write(&test_isize.to_ne_bytes());
|
||||
|
||||
let h1_hash = h1.finish128();
|
||||
let h2_hash = h2.finish128();
|
||||
|
||||
assert_eq!(h1_hash, h2_hash);
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@ impl<K: Ord, V> SortedMap<K, V> {
|
|||
/// and that there are no duplicates.
|
||||
#[inline]
|
||||
pub fn from_presorted_elements(elements: Vec<(K, V)>) -> SortedMap<K, V> {
|
||||
debug_assert!(elements.windows(2).all(|w| w[0].0 < w[1].0));
|
||||
debug_assert!(elements.array_windows().all(|[fst, snd]| fst.0 < snd.0));
|
||||
|
||||
SortedMap { data: elements }
|
||||
}
|
||||
|
@ -159,7 +159,7 @@ impl<K: Ord, V> SortedMap<K, V> {
|
|||
return;
|
||||
}
|
||||
|
||||
debug_assert!(elements.windows(2).all(|w| w[0].0 < w[1].0));
|
||||
debug_assert!(elements.array_windows().all(|[fst, snd]| fst.0 < snd.0));
|
||||
|
||||
let start_index = self.lookup_index_for(&elements[0].0);
|
||||
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
use std::fmt;
|
||||
use std::iter::ExactSizeIterator;
|
||||
use std::iter::FusedIterator;
|
||||
use std::iter::Iterator;
|
||||
|
||||
/// Iterator which may contain instance of
|
||||
/// one of two specific implementations.
|
||||
///
|
||||
/// Note: For most methods providing custom
|
||||
/// implementation may margianlly
|
||||
/// improve performance by avoiding
|
||||
/// doing Left/Right match on every step
|
||||
/// and doing it only once instead.
|
||||
#[derive(Clone)]
|
||||
pub enum EitherIter<L, R> {
|
||||
Left(L),
|
||||
Right(R),
|
||||
}
|
||||
|
||||
impl<L, R> Iterator for EitherIter<L, R>
|
||||
where
|
||||
L: Iterator,
|
||||
R: Iterator<Item = L::Item>,
|
||||
{
|
||||
type Item = L::Item;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
match self {
|
||||
EitherIter::Left(l) => l.next(),
|
||||
EitherIter::Right(r) => r.next(),
|
||||
}
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
match self {
|
||||
EitherIter::Left(l) => l.size_hint(),
|
||||
EitherIter::Right(r) => r.size_hint(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<L, R> ExactSizeIterator for EitherIter<L, R>
|
||||
where
|
||||
L: ExactSizeIterator,
|
||||
R: ExactSizeIterator,
|
||||
EitherIter<L, R>: Iterator,
|
||||
{
|
||||
fn len(&self) -> usize {
|
||||
match self {
|
||||
EitherIter::Left(l) => l.len(),
|
||||
EitherIter::Right(r) => r.len(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<L, R> FusedIterator for EitherIter<L, R>
|
||||
where
|
||||
L: FusedIterator,
|
||||
R: FusedIterator,
|
||||
EitherIter<L, R>: Iterator,
|
||||
{
|
||||
}
|
||||
|
||||
impl<L, R> fmt::Debug for EitherIter<L, R>
|
||||
where
|
||||
L: fmt::Debug,
|
||||
R: fmt::Debug,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
EitherIter::Left(l) => l.fmt(f),
|
||||
EitherIter::Right(r) => r.fmt(f),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,560 @@
|
|||
use super::either_iter::EitherIter;
|
||||
use crate::fx::FxHashMap;
|
||||
use arrayvec::ArrayVec;
|
||||
use std::fmt;
|
||||
use std::hash::Hash;
|
||||
use std::iter::FromIterator;
|
||||
use std::ops::Index;
|
||||
|
||||
// For pointer-sized arguments arrays
|
||||
// are faster than set/map for up to 64
|
||||
// arguments.
|
||||
//
|
||||
// On the other hand such a big array
|
||||
// hurts cache performance, makes passing
|
||||
// sso structures around very expensive.
|
||||
//
|
||||
// Biggest performance benefit is gained
|
||||
// for reasonably small arrays that stay
|
||||
// small in vast majority of cases.
|
||||
//
|
||||
// '8' is choosen as a sane default, to be
|
||||
// reevaluated later.
|
||||
//
|
||||
// Note: As of now ArrayVec design prevents
|
||||
// us from making it user-customizable.
|
||||
const SSO_ARRAY_SIZE: usize = 8;
|
||||
|
||||
/// Small-storage-optimized implementation of a map.
|
||||
///
|
||||
/// Stores elements in a small array up to a certain length
|
||||
/// and switches to `HashMap` when that length is exceeded.
|
||||
//
|
||||
// FIXME: Implements subset of HashMap API.
|
||||
//
|
||||
// Missing HashMap API:
|
||||
// all hasher-related
|
||||
// try_reserve (unstable)
|
||||
// shrink_to (unstable)
|
||||
// drain_filter (unstable)
|
||||
// into_keys/into_values (unstable)
|
||||
// all raw_entry-related
|
||||
// PartialEq/Eq (requires sorting the array)
|
||||
// Entry::or_insert_with_key (unstable)
|
||||
// Vacant/Occupied entries and related
|
||||
//
|
||||
// FIXME: In HashMap most methods accepting key reference
|
||||
// accept reference to generic `Q` where `K: Borrow<Q>`.
|
||||
//
|
||||
// However, using this approach in `HashMap::get` apparently
|
||||
// breaks inlining and noticeably reduces performance.
|
||||
//
|
||||
// Performance *should* be the same given that borrow is
|
||||
// a NOP in most cases, but in practice that's not the case.
|
||||
//
|
||||
// Further investigation is required.
|
||||
//
|
||||
// Affected methods:
|
||||
// SsoHashMap::get
|
||||
// SsoHashMap::get_mut
|
||||
// SsoHashMap::get_entry
|
||||
// SsoHashMap::get_key_value
|
||||
// SsoHashMap::contains_key
|
||||
// SsoHashMap::remove
|
||||
// SsoHashMap::remove_entry
|
||||
// Index::index
|
||||
// SsoHashSet::take
|
||||
// SsoHashSet::get
|
||||
// SsoHashSet::remove
|
||||
// SsoHashSet::contains
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum SsoHashMap<K, V> {
|
||||
Array(ArrayVec<[(K, V); SSO_ARRAY_SIZE]>),
|
||||
Map(FxHashMap<K, V>),
|
||||
}
|
||||
|
||||
impl<K, V> SsoHashMap<K, V> {
|
||||
/// Creates an empty `SsoHashMap`.
|
||||
#[inline]
|
||||
pub fn new() -> Self {
|
||||
SsoHashMap::Array(ArrayVec::new())
|
||||
}
|
||||
|
||||
/// Creates an empty `SsoHashMap` with the specified capacity.
|
||||
pub fn with_capacity(cap: usize) -> Self {
|
||||
if cap <= SSO_ARRAY_SIZE {
|
||||
Self::new()
|
||||
} else {
|
||||
SsoHashMap::Map(FxHashMap::with_capacity_and_hasher(cap, Default::default()))
|
||||
}
|
||||
}
|
||||
|
||||
/// Clears the map, removing all key-value pairs. Keeps the allocated memory
|
||||
/// for reuse.
|
||||
pub fn clear(&mut self) {
|
||||
match self {
|
||||
SsoHashMap::Array(array) => array.clear(),
|
||||
SsoHashMap::Map(map) => map.clear(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the number of elements the map can hold without reallocating.
|
||||
pub fn capacity(&self) -> usize {
|
||||
match self {
|
||||
SsoHashMap::Array(_) => SSO_ARRAY_SIZE,
|
||||
SsoHashMap::Map(map) => map.capacity(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the number of elements in the map.
|
||||
pub fn len(&self) -> usize {
|
||||
match self {
|
||||
SsoHashMap::Array(array) => array.len(),
|
||||
SsoHashMap::Map(map) => map.len(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if the map contains no elements.
|
||||
pub fn is_empty(&self) -> bool {
|
||||
match self {
|
||||
SsoHashMap::Array(array) => array.is_empty(),
|
||||
SsoHashMap::Map(map) => map.is_empty(),
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator visiting all key-value pairs in arbitrary order.
|
||||
/// The iterator element type is `(&'a K, &'a V)`.
|
||||
#[inline]
|
||||
pub fn iter(&self) -> <&Self as IntoIterator>::IntoIter {
|
||||
self.into_iter()
|
||||
}
|
||||
|
||||
/// An iterator visiting all key-value pairs in arbitrary order,
|
||||
/// with mutable references to the values.
|
||||
/// The iterator element type is `(&'a K, &'a mut V)`.
|
||||
#[inline]
|
||||
pub fn iter_mut(&mut self) -> impl Iterator<Item = (&'_ K, &'_ mut V)> {
|
||||
self.into_iter()
|
||||
}
|
||||
|
||||
/// An iterator visiting all keys in arbitrary order.
|
||||
/// The iterator element type is `&'a K`.
|
||||
pub fn keys(&self) -> impl Iterator<Item = &'_ K> {
|
||||
match self {
|
||||
SsoHashMap::Array(array) => EitherIter::Left(array.iter().map(|(k, _v)| k)),
|
||||
SsoHashMap::Map(map) => EitherIter::Right(map.keys()),
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator visiting all values in arbitrary order.
|
||||
/// The iterator element type is `&'a V`.
|
||||
pub fn values(&self) -> impl Iterator<Item = &'_ V> {
|
||||
match self {
|
||||
SsoHashMap::Array(array) => EitherIter::Left(array.iter().map(|(_k, v)| v)),
|
||||
SsoHashMap::Map(map) => EitherIter::Right(map.values()),
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator visiting all values mutably in arbitrary order.
|
||||
/// The iterator element type is `&'a mut V`.
|
||||
pub fn values_mut(&mut self) -> impl Iterator<Item = &'_ mut V> {
|
||||
match self {
|
||||
SsoHashMap::Array(array) => EitherIter::Left(array.iter_mut().map(|(_k, v)| v)),
|
||||
SsoHashMap::Map(map) => EitherIter::Right(map.values_mut()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Clears the map, returning all key-value pairs as an iterator. Keeps the
|
||||
/// allocated memory for reuse.
|
||||
pub fn drain(&mut self) -> impl Iterator<Item = (K, V)> + '_ {
|
||||
match self {
|
||||
SsoHashMap::Array(array) => EitherIter::Left(array.drain(..)),
|
||||
SsoHashMap::Map(map) => EitherIter::Right(map.drain()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: Eq + Hash, V> SsoHashMap<K, V> {
|
||||
/// Changes underlying storage from array to hashmap
|
||||
/// if array is full.
|
||||
fn migrate_if_full(&mut self) {
|
||||
if let SsoHashMap::Array(array) = self {
|
||||
if array.is_full() {
|
||||
*self = SsoHashMap::Map(array.drain(..).collect());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Reserves capacity for at least `additional` more elements to be inserted
|
||||
/// in the `SsoHashMap`. The collection may reserve more space to avoid
|
||||
/// frequent reallocations.
|
||||
pub fn reserve(&mut self, additional: usize) {
|
||||
match self {
|
||||
SsoHashMap::Array(array) => {
|
||||
if SSO_ARRAY_SIZE < (array.len() + additional) {
|
||||
let mut map: FxHashMap<K, V> = array.drain(..).collect();
|
||||
map.reserve(additional);
|
||||
*self = SsoHashMap::Map(map);
|
||||
}
|
||||
}
|
||||
SsoHashMap::Map(map) => map.reserve(additional),
|
||||
}
|
||||
}
|
||||
|
||||
/// Shrinks the capacity of the map as much as possible. It will drop
|
||||
/// down as much as possible while maintaining the internal rules
|
||||
/// and possibly leaving some space in accordance with the resize policy.
|
||||
pub fn shrink_to_fit(&mut self) {
|
||||
if let SsoHashMap::Map(map) = self {
|
||||
if map.len() <= SSO_ARRAY_SIZE {
|
||||
*self = SsoHashMap::Array(map.drain().collect());
|
||||
} else {
|
||||
map.shrink_to_fit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Retains only the elements specified by the predicate.
|
||||
pub fn retain<F>(&mut self, mut f: F)
|
||||
where
|
||||
F: FnMut(&K, &mut V) -> bool,
|
||||
{
|
||||
match self {
|
||||
SsoHashMap::Array(array) => array.retain(|(k, v)| f(k, v)),
|
||||
SsoHashMap::Map(map) => map.retain(f),
|
||||
}
|
||||
}
|
||||
|
||||
/// Inserts a key-value pair into the map.
|
||||
///
|
||||
/// If the map did not have this key present, [`None`] is returned.
|
||||
///
|
||||
/// If the map did have this key present, the value is updated, and the old
|
||||
/// value is returned. The key is not updated, though; this matters for
|
||||
/// types that can be `==` without being identical. See the [module-level
|
||||
/// documentation] for more.
|
||||
pub fn insert(&mut self, key: K, value: V) -> Option<V> {
|
||||
match self {
|
||||
SsoHashMap::Array(array) => {
|
||||
for (k, v) in array.iter_mut() {
|
||||
if *k == key {
|
||||
let old_value = std::mem::replace(v, value);
|
||||
return Some(old_value);
|
||||
}
|
||||
}
|
||||
if let Err(error) = array.try_push((key, value)) {
|
||||
let mut map: FxHashMap<K, V> = array.drain(..).collect();
|
||||
let (key, value) = error.element();
|
||||
map.insert(key, value);
|
||||
*self = SsoHashMap::Map(map);
|
||||
}
|
||||
None
|
||||
}
|
||||
SsoHashMap::Map(map) => map.insert(key, value),
|
||||
}
|
||||
}
|
||||
|
||||
/// Removes a key from the map, returning the value at the key if the key
|
||||
/// was previously in the map.
|
||||
pub fn remove(&mut self, key: &K) -> Option<V> {
|
||||
match self {
|
||||
SsoHashMap::Array(array) => {
|
||||
if let Some(index) = array.iter().position(|(k, _v)| k == key) {
|
||||
Some(array.swap_remove(index).1)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
SsoHashMap::Map(map) => map.remove(key),
|
||||
}
|
||||
}
|
||||
|
||||
/// Removes a key from the map, returning the stored key and value if the
|
||||
/// key was previously in the map.
|
||||
pub fn remove_entry(&mut self, key: &K) -> Option<(K, V)> {
|
||||
match self {
|
||||
SsoHashMap::Array(array) => {
|
||||
if let Some(index) = array.iter().position(|(k, _v)| k == key) {
|
||||
Some(array.swap_remove(index))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
SsoHashMap::Map(map) => map.remove_entry(key),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a reference to the value corresponding to the key.
|
||||
pub fn get(&self, key: &K) -> Option<&V> {
|
||||
match self {
|
||||
SsoHashMap::Array(array) => {
|
||||
for (k, v) in array {
|
||||
if k == key {
|
||||
return Some(v);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
SsoHashMap::Map(map) => map.get(key),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the value corresponding to the key.
|
||||
pub fn get_mut(&mut self, key: &K) -> Option<&mut V> {
|
||||
match self {
|
||||
SsoHashMap::Array(array) => {
|
||||
for (k, v) in array {
|
||||
if k == key {
|
||||
return Some(v);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
SsoHashMap::Map(map) => map.get_mut(key),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the key-value pair corresponding to the supplied key.
|
||||
pub fn get_key_value(&self, key: &K) -> Option<(&K, &V)> {
|
||||
match self {
|
||||
SsoHashMap::Array(array) => {
|
||||
for (k, v) in array {
|
||||
if k == key {
|
||||
return Some((k, v));
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
SsoHashMap::Map(map) => map.get_key_value(key),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if the map contains a value for the specified key.
|
||||
pub fn contains_key(&self, key: &K) -> bool {
|
||||
match self {
|
||||
SsoHashMap::Array(array) => array.iter().any(|(k, _v)| k == key),
|
||||
SsoHashMap::Map(map) => map.contains_key(key),
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the given key's corresponding entry in the map for in-place manipulation.
|
||||
#[inline]
|
||||
pub fn entry(&mut self, key: K) -> Entry<'_, K, V> {
|
||||
Entry { ssomap: self, key }
|
||||
}
|
||||
}
|
||||
|
||||
impl<K, V> Default for SsoHashMap<K, V> {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: Eq + Hash, V> FromIterator<(K, V)> for SsoHashMap<K, V> {
|
||||
fn from_iter<I: IntoIterator<Item = (K, V)>>(iter: I) -> SsoHashMap<K, V> {
|
||||
let mut map: SsoHashMap<K, V> = Default::default();
|
||||
map.extend(iter);
|
||||
map
|
||||
}
|
||||
}
|
||||
|
||||
impl<K: Eq + Hash, V> Extend<(K, V)> for SsoHashMap<K, V> {
|
||||
fn extend<I>(&mut self, iter: I)
|
||||
where
|
||||
I: IntoIterator<Item = (K, V)>,
|
||||
{
|
||||
for (key, value) in iter.into_iter() {
|
||||
self.insert(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn extend_one(&mut self, (k, v): (K, V)) {
|
||||
self.insert(k, v);
|
||||
}
|
||||
|
||||
fn extend_reserve(&mut self, additional: usize) {
|
||||
match self {
|
||||
SsoHashMap::Array(array) => {
|
||||
if SSO_ARRAY_SIZE < (array.len() + additional) {
|
||||
let mut map: FxHashMap<K, V> = array.drain(..).collect();
|
||||
map.extend_reserve(additional);
|
||||
*self = SsoHashMap::Map(map);
|
||||
}
|
||||
}
|
||||
SsoHashMap::Map(map) => map.extend_reserve(additional),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, K, V> Extend<(&'a K, &'a V)> for SsoHashMap<K, V>
|
||||
where
|
||||
K: Eq + Hash + Copy,
|
||||
V: Copy,
|
||||
{
|
||||
fn extend<T: IntoIterator<Item = (&'a K, &'a V)>>(&mut self, iter: T) {
|
||||
self.extend(iter.into_iter().map(|(k, v)| (k.clone(), v.clone())))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn extend_one(&mut self, (&k, &v): (&'a K, &'a V)) {
|
||||
self.insert(k, v);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn extend_reserve(&mut self, additional: usize) {
|
||||
Extend::<(K, V)>::extend_reserve(self, additional)
|
||||
}
|
||||
}
|
||||
|
||||
impl<K, V> IntoIterator for SsoHashMap<K, V> {
|
||||
type IntoIter = EitherIter<
|
||||
<ArrayVec<[(K, V); 8]> as IntoIterator>::IntoIter,
|
||||
<FxHashMap<K, V> as IntoIterator>::IntoIter,
|
||||
>;
|
||||
type Item = <Self::IntoIter as Iterator>::Item;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
match self {
|
||||
SsoHashMap::Array(array) => EitherIter::Left(array.into_iter()),
|
||||
SsoHashMap::Map(map) => EitherIter::Right(map.into_iter()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// adapts Item of array reference iterator to Item of hashmap reference iterator.
|
||||
#[inline(always)]
|
||||
fn adapt_array_ref_it<K, V>(pair: &'a (K, V)) -> (&'a K, &'a V) {
|
||||
let (a, b) = pair;
|
||||
(a, b)
|
||||
}
|
||||
|
||||
/// adapts Item of array mut reference iterator to Item of hashmap mut reference iterator.
|
||||
#[inline(always)]
|
||||
fn adapt_array_mut_it<K, V>(pair: &'a mut (K, V)) -> (&'a K, &'a mut V) {
|
||||
let (a, b) = pair;
|
||||
(a, b)
|
||||
}
|
||||
|
||||
impl<'a, K, V> IntoIterator for &'a SsoHashMap<K, V> {
|
||||
type IntoIter = EitherIter<
|
||||
std::iter::Map<
|
||||
<&'a ArrayVec<[(K, V); 8]> as IntoIterator>::IntoIter,
|
||||
fn(&'a (K, V)) -> (&'a K, &'a V),
|
||||
>,
|
||||
<&'a FxHashMap<K, V> as IntoIterator>::IntoIter,
|
||||
>;
|
||||
type Item = <Self::IntoIter as Iterator>::Item;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
match self {
|
||||
SsoHashMap::Array(array) => EitherIter::Left(array.into_iter().map(adapt_array_ref_it)),
|
||||
SsoHashMap::Map(map) => EitherIter::Right(map.into_iter()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, K, V> IntoIterator for &'a mut SsoHashMap<K, V> {
|
||||
type IntoIter = EitherIter<
|
||||
std::iter::Map<
|
||||
<&'a mut ArrayVec<[(K, V); 8]> as IntoIterator>::IntoIter,
|
||||
fn(&'a mut (K, V)) -> (&'a K, &'a mut V),
|
||||
>,
|
||||
<&'a mut FxHashMap<K, V> as IntoIterator>::IntoIter,
|
||||
>;
|
||||
type Item = <Self::IntoIter as Iterator>::Item;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
match self {
|
||||
SsoHashMap::Array(array) => EitherIter::Left(array.into_iter().map(adapt_array_mut_it)),
|
||||
SsoHashMap::Map(map) => EitherIter::Right(map.into_iter()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<K, V> fmt::Debug for SsoHashMap<K, V>
|
||||
where
|
||||
K: fmt::Debug,
|
||||
V: fmt::Debug,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_map().entries(self.iter()).finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, K, V> Index<&'a K> for SsoHashMap<K, V>
|
||||
where
|
||||
K: Eq + Hash,
|
||||
{
|
||||
type Output = V;
|
||||
|
||||
#[inline]
|
||||
fn index(&self, key: &K) -> &V {
|
||||
self.get(key).expect("no entry found for key")
|
||||
}
|
||||
}
|
||||
|
||||
/// A view into a single entry in a map.
|
||||
pub struct Entry<'a, K, V> {
|
||||
ssomap: &'a mut SsoHashMap<K, V>,
|
||||
key: K,
|
||||
}
|
||||
|
||||
impl<'a, K: Eq + Hash, V> Entry<'a, K, V> {
|
||||
/// Provides in-place mutable access to an occupied entry before any
|
||||
/// potential inserts into the map.
|
||||
pub fn and_modify<F>(self, f: F) -> Self
|
||||
where
|
||||
F: FnOnce(&mut V),
|
||||
{
|
||||
if let Some(value) = self.ssomap.get_mut(&self.key) {
|
||||
f(value);
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// Ensures a value is in the entry by inserting the default if empty, and returns
|
||||
/// a mutable reference to the value in the entry.
|
||||
#[inline]
|
||||
pub fn or_insert(self, value: V) -> &'a mut V {
|
||||
self.or_insert_with(|| value)
|
||||
}
|
||||
|
||||
/// Ensures a value is in the entry by inserting the result of the default function if empty,
|
||||
/// and returns a mutable reference to the value in the entry.
|
||||
pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V {
|
||||
self.ssomap.migrate_if_full();
|
||||
match self.ssomap {
|
||||
SsoHashMap::Array(array) => {
|
||||
let key_ref = &self.key;
|
||||
let found_index = array.iter().position(|(k, _v)| k == key_ref);
|
||||
let index = if let Some(index) = found_index {
|
||||
index
|
||||
} else {
|
||||
let index = array.len();
|
||||
array.try_push((self.key, default())).unwrap();
|
||||
index
|
||||
};
|
||||
&mut array[index].1
|
||||
}
|
||||
SsoHashMap::Map(map) => map.entry(self.key).or_insert_with(default),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a reference to this entry's key.
|
||||
#[inline]
|
||||
pub fn key(&self) -> &K {
|
||||
&self.key
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, K: Eq + Hash, V: Default> Entry<'a, K, V> {
|
||||
/// Ensures a value is in the entry by inserting the default value if empty,
|
||||
/// and returns a mutable reference to the value in the entry.
|
||||
#[inline]
|
||||
pub fn or_default(self) -> &'a mut V {
|
||||
self.or_insert_with(Default::default)
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue