Merge branch 'master' into hooks

This commit is contained in:
Cassandra Fridkin 2020-10-05 18:49:51 -04:00
commit 44af74f6dd
No known key found for this signature in database
GPG Key ID: B06380CCA613333A
2455 changed files with 95596 additions and 42239 deletions

View File

@ -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.

View File

@ -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

1
.gitignore vendored
View File

@ -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:

2
.gitmodules vendored
View File

@ -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

View File

@ -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>

View File

@ -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]]

View File

@ -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",

View File

@ -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 youd like to build the documentation, its 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

View File

@ -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)
==========================

View File

@ -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']

View File

@ -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;

View File

@ -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)]

View File

@ -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]

View File

@ -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
}

View File

@ -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> {

View File

@ -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)
}
}

View File

@ -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()],
}
}

View File

@ -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]

View File

@ -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);
}

View File

@ -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") {

View File

@ -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())

View File

@ -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("_")
}

View File

@ -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);
}
}

View File

@ -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[..] {
[] => {}

View File

@ -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 } => {

View File

@ -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,
);

View File

@ -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" }

View File

@ -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);

View File

@ -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();
}
}
}
}

View File

@ -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)"),

View File

@ -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),

View File

@ -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() {

View File

@ -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;

View File

@ -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();

View File

@ -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,
}))
}
}

View File

@ -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 }
}

View File

@ -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,

View File

@ -75,6 +75,7 @@ fn call_intrinsic(
id: ast::DUMMY_NODE_ID,
rules: ast::BlockCheckMode::Unsafe(ast::CompilerGenerated),
span,
tokens: None,
}))
}

View File

@ -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 {

View File

@ -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;

View File

@ -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,
})]),

View File

@ -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)]

View File

@ -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,

View File

@ -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
});

View File

@ -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,
});

View File

@ -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" }

View File

@ -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);
}

View File

@ -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),
}
}

View File

@ -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()
}
};

View File

@ -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,

View File

@ -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,

View File

@ -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);

View File

@ -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) }
}

View File

@ -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};

View File

@ -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());
}

View File

@ -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> {

View File

@ -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,

View File

@ -1845,7 +1845,6 @@ impl<'tcx> VariantInfo<'_, 'tcx> {
None
}
#[allow(dead_code)]
fn is_artificial(&self) -> bool {
match self {
VariantInfo::Generator { .. } => true,

View File

@ -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(

View File

@ -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 theres 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 theres 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 theres 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 users 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 }

View File

@ -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,
}
}

View File

@ -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>>,

View File

@ -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),
}

View File

@ -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(

View File

@ -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,

View File

@ -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 {

View File

@ -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) }
}

View File

@ -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(

View File

@ -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,

View File

@ -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
}
};

View File

@ -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)),
}
}

View File

@ -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 }
}

View File

@ -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 {

View File

@ -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,

View File

@ -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));
}

View File

@ -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());

View File

@ -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> {

View File

@ -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() {

View File

@ -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: theres 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,
}
}

View File

@ -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;

View File

@ -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.

View File

@ -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,
_ => &[],
}
}

View File

@ -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.

View File

@ -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,

View File

@ -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 theres 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 theres 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 theres 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 users 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(

View File

@ -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>,

View File

@ -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>;
}

View File

@ -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>

View File

@ -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(

View File

@ -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]

View File

@ -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> {

View File

@ -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,
}
}
}

View File

@ -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> {

View File

@ -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 {

View File

@ -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

View File

@ -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>();

View File

@ -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);
}

View File

@ -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);

View File

@ -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),
}
}
}

View File

@ -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