1
Fork 0

Merge commit '0969bc6dde' into sync_cg_clif-2021-03-29

This commit is contained in:
bjorn3 2021-03-29 10:45:09 +02:00
commit 5444b46234
49 changed files with 880 additions and 495 deletions

View file

@ -1,44 +0,0 @@
name: Bootstrap rustc using cg_clif
on:
- push
jobs:
bootstrap_rustc:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Cache cargo installed crates
uses: actions/cache@v2
with:
path: ~/.cargo/bin
key: ${{ runner.os }}-cargo-installed-crates
- name: Cache cargo registry and index
uses: actions/cache@v2
with:
path: |
~/.cargo/registry
~/.cargo/git
key: ${{ runner.os }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }}
- name: Cache cargo target dir
uses: actions/cache@v2
with:
path: target
key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
- name: Prepare dependencies
run: |
git config --global user.email "user@example.com"
git config --global user.name "User"
./prepare.sh
- name: Test
run: |
# Enable backtraces for easier debugging
export RUST_BACKTRACE=1
./scripts/test_bootstrap.sh

View file

@ -7,11 +7,18 @@ on:
jobs: jobs:
build: build:
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
timeout-minutes: 60
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
os: [ubuntu-latest, macos-latest] include:
- os: ubuntu-latest
- os: macos-latest
# cross-compile from Linux to Windows using mingw
- os: ubuntu-latest
env:
TARGET_TRIPLE: x86_64-pc-windows-gnu
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
@ -36,6 +43,12 @@ jobs:
path: target path: target
key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }} key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
- name: Install MinGW toolchain and wine
if: matrix.os == 'ubuntu-latest' && matrix.env.TARGET_TRIPLE == 'x86_64-pc-windows-gnu'
run: |
sudo apt-get install -y gcc-mingw-w64-x86-64 wine-stable
rustup target add x86_64-pc-windows-gnu
- name: Prepare dependencies - name: Prepare dependencies
run: | run: |
git config --global user.email "user@example.com" git config --global user.email "user@example.com"
@ -43,6 +56,8 @@ jobs:
./prepare.sh ./prepare.sh
- name: Test - name: Test
env:
TARGET_TRIPLE: ${{ matrix.env.TARGET_TRIPLE }}
run: | run: |
# Enable backtraces for easier debugging # Enable backtraces for easier debugging
export RUST_BACKTRACE=1 export RUST_BACKTRACE=1
@ -51,12 +66,16 @@ jobs:
export COMPILE_RUNS=2 export COMPILE_RUNS=2
export RUN_RUNS=2 export RUN_RUNS=2
# Enable extra checks
export CG_CLIF_ENABLE_VERIFIER=1
./test.sh ./test.sh
- name: Package prebuilt cg_clif - name: Package prebuilt cg_clif
run: tar cvfJ cg_clif.tar.xz build run: tar cvfJ cg_clif.tar.xz build
- name: Upload prebuilt cg_clif - name: Upload prebuilt cg_clif
if: matrix.env.TARGET_TRIPLE != 'x86_64-pc-windows-gnu'
uses: actions/upload-artifact@v2 uses: actions/upload-artifact@v2
with: with:
name: cg_clif-${{ runner.os }} name: cg_clif-${{ runner.os }}

View file

@ -0,0 +1,82 @@
name: Various rustc tests
on:
- push
jobs:
bootstrap_rustc:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Cache cargo installed crates
uses: actions/cache@v2
with:
path: ~/.cargo/bin
key: ${{ runner.os }}-cargo-installed-crates
- name: Cache cargo registry and index
uses: actions/cache@v2
with:
path: |
~/.cargo/registry
~/.cargo/git
key: ${{ runner.os }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }}
- name: Cache cargo target dir
uses: actions/cache@v2
with:
path: target
key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
- name: Prepare dependencies
run: |
git config --global user.email "user@example.com"
git config --global user.name "User"
./prepare.sh
- name: Test
run: |
# Enable backtraces for easier debugging
export RUST_BACKTRACE=1
./scripts/test_bootstrap.sh
rustc_test_suite:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Cache cargo installed crates
uses: actions/cache@v2
with:
path: ~/.cargo/bin
key: ${{ runner.os }}-cargo-installed-crates
- name: Cache cargo registry and index
uses: actions/cache@v2
with:
path: |
~/.cargo/registry
~/.cargo/git
key: ${{ runner.os }}-cargo-registry-and-index-${{ hashFiles('**/Cargo.lock') }}
- name: Cache cargo target dir
uses: actions/cache@v2
with:
path: target
key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain', '**/Cargo.lock') }}
- name: Prepare dependencies
run: |
git config --global user.email "user@example.com"
git config --global user.name "User"
./prepare.sh
- name: Test
run: |
# Enable backtraces for easier debugging
export RUST_BACKTRACE=1
./scripts/test_rustc_tests.sh

View file

@ -2,7 +2,7 @@
// source for rustc_* is not included in the rust-src component; disable the errors about this // source for rustc_* is not included in the rust-src component; disable the errors about this
"rust-analyzer.diagnostics.disabled": ["unresolved-extern-crate", "macro-error"], "rust-analyzer.diagnostics.disabled": ["unresolved-extern-crate", "macro-error"],
"rust-analyzer.assist.importMergeBehavior": "last", "rust-analyzer.assist.importMergeBehavior": "last",
"rust-analyzer.cargo.loadOutDirsFromCheck": true, "rust-analyzer.cargo.runBuildScripts": true,
"rust-analyzer.linkedProjects": [ "rust-analyzer.linkedProjects": [
"./Cargo.toml", "./Cargo.toml",
//"./build_sysroot/sysroot_src/src/libstd/Cargo.toml", //"./build_sysroot/sysroot_src/src/libstd/Cargo.toml",

View file

@ -39,16 +39,16 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]] [[package]]
name = "cranelift-bforest" name = "cranelift-bforest"
version = "0.70.0" version = "0.72.0"
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058" source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#8e43e96410a14143d368273cf1e708f8094bb8e0"
dependencies = [ dependencies = [
"cranelift-entity", "cranelift-entity",
] ]
[[package]] [[package]]
name = "cranelift-codegen" name = "cranelift-codegen"
version = "0.70.0" version = "0.72.0"
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058" source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#8e43e96410a14143d368273cf1e708f8094bb8e0"
dependencies = [ dependencies = [
"byteorder", "byteorder",
"cranelift-bforest", "cranelift-bforest",
@ -65,8 +65,8 @@ dependencies = [
[[package]] [[package]]
name = "cranelift-codegen-meta" name = "cranelift-codegen-meta"
version = "0.70.0" version = "0.72.0"
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058" source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#8e43e96410a14143d368273cf1e708f8094bb8e0"
dependencies = [ dependencies = [
"cranelift-codegen-shared", "cranelift-codegen-shared",
"cranelift-entity", "cranelift-entity",
@ -74,18 +74,18 @@ dependencies = [
[[package]] [[package]]
name = "cranelift-codegen-shared" name = "cranelift-codegen-shared"
version = "0.70.0" version = "0.72.0"
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058" source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#8e43e96410a14143d368273cf1e708f8094bb8e0"
[[package]] [[package]]
name = "cranelift-entity" name = "cranelift-entity"
version = "0.70.0" version = "0.72.0"
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058" source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#8e43e96410a14143d368273cf1e708f8094bb8e0"
[[package]] [[package]]
name = "cranelift-frontend" name = "cranelift-frontend"
version = "0.70.0" version = "0.72.0"
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058" source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#8e43e96410a14143d368273cf1e708f8094bb8e0"
dependencies = [ dependencies = [
"cranelift-codegen", "cranelift-codegen",
"log", "log",
@ -95,8 +95,8 @@ dependencies = [
[[package]] [[package]]
name = "cranelift-jit" name = "cranelift-jit"
version = "0.70.0" version = "0.72.0"
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058" source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#8e43e96410a14143d368273cf1e708f8094bb8e0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"cranelift-codegen", "cranelift-codegen",
@ -113,8 +113,8 @@ dependencies = [
[[package]] [[package]]
name = "cranelift-module" name = "cranelift-module"
version = "0.70.0" version = "0.72.0"
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058" source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#8e43e96410a14143d368273cf1e708f8094bb8e0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"cranelift-codegen", "cranelift-codegen",
@ -125,8 +125,8 @@ dependencies = [
[[package]] [[package]]
name = "cranelift-native" name = "cranelift-native"
version = "0.70.0" version = "0.72.0"
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058" source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#8e43e96410a14143d368273cf1e708f8094bb8e0"
dependencies = [ dependencies = [
"cranelift-codegen", "cranelift-codegen",
"target-lexicon", "target-lexicon",
@ -134,8 +134,8 @@ dependencies = [
[[package]] [[package]]
name = "cranelift-object" name = "cranelift-object"
version = "0.70.0" version = "0.72.0"
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058" source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#8e43e96410a14143d368273cf1e708f8094bb8e0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"cranelift-codegen", "cranelift-codegen",
@ -240,6 +240,15 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "memmap2"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04e3e85b970d650e2ae6d70592474087051c11c54da7f7b4949725c5735fbcc6"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "object" name = "object"
version = "0.23.0" version = "0.23.0"
@ -310,6 +319,7 @@ dependencies = [
"gimli", "gimli",
"indexmap", "indexmap",
"libloading", "libloading",
"memmap2",
"object", "object",
"smallvec", "smallvec",
"target-lexicon", "target-lexicon",

View file

@ -16,12 +16,13 @@ cranelift-jit = { git = "https://github.com/bytecodealliance/wasmtime/", branch
cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime/", branch = "main" } cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime/", branch = "main" }
target-lexicon = "0.11.0" target-lexicon = "0.11.0"
gimli = { version = "0.23.0", default-features = false, features = ["write"]} gimli = { version = "0.23.0", default-features = false, features = ["write"]}
object = { version = "0.23.0", default-features = false, features = ["std", "read_core", "write", "coff", "elf", "macho", "pe"] } object = { version = "0.23.0", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }
ar = { git = "https://github.com/bjorn3/rust-ar.git", branch = "do_not_remove_cg_clif_ranlib" } ar = { git = "https://github.com/bjorn3/rust-ar.git", branch = "do_not_remove_cg_clif_ranlib" }
indexmap = "1.0.2" indexmap = "1.0.2"
libloading = { version = "0.6.0", optional = true } libloading = { version = "0.6.0", optional = true }
smallvec = "1.6.1" smallvec = "1.6.1"
memmap2 = "0.2.1"
# Uncomment to use local checkout of cranelift # Uncomment to use local checkout of cranelift
#[patch."https://github.com/bytecodealliance/wasmtime/"] #[patch."https://github.com/bytecodealliance/wasmtime/"]
@ -75,3 +76,6 @@ debug = false
[profile.release.package.syn] [profile.release.package.syn]
opt-level = 0 opt-level = 0
debug = false debug = false
[package.metadata.rust-analyzer]
rustc_private = true

View file

@ -34,70 +34,19 @@ rustc_codegen_cranelift can be used as a near-drop-in replacement for `cargo bui
Assuming `$cg_clif_dir` is the directory you cloned this repo into and you followed the instructions (`prepare.sh` and `build.sh` or `test.sh`). Assuming `$cg_clif_dir` is the directory you cloned this repo into and you followed the instructions (`prepare.sh` and `build.sh` or `test.sh`).
### Cargo
In the directory with your project (where you can do the usual `cargo build`), run: In the directory with your project (where you can do the usual `cargo build`), run:
```bash ```bash
$ $cg_clif_dir/build/cargo.sh run $ $cg_clif_dir/build/cargo.sh build
``` ```
This should build and run your project with rustc_codegen_cranelift instead of the usual LLVM backend. This will build your project with rustc_codegen_cranelift instead of the usual LLVM backend.
### Rustc For additional ways to use rustc_codegen_cranelift like the JIT mode see [usage.md](docs/usage.md).
> You should prefer using the Cargo method.
```bash
$ $cg_clif_dir/build/bin/cg_clif my_crate.rs
```
### Jit mode
In jit mode cg_clif will immediately execute your code without creating an executable file.
> This requires all dependencies to be available as dynamic library.
> The jit mode will probably need cargo integration to make this possible.
```bash
$ $cg_clif_dir/build/cargo.sh jit
```
or
```bash
$ $cg_clif_dir/build/bin/cg_clif -Cllvm-args=mode=jit -Cprefer-dynamic my_crate.rs
```
There is also an experimental lazy jit mode. In this mode functions are only compiled once they are
first called. It currently does not work with multi-threaded programs. When a not yet compiled
function is called from another thread than the main thread, you will get an ICE.
```bash
$ $cg_clif_dir/build/cargo.sh lazy-jit
```
### Shell
These are a few functions that allow you to easily run rust code from the shell using cg_clif as jit.
```bash
function jit_naked() {
echo "$@" | $cg_clif_dir/build/bin/cg_clif - -Cllvm-args=mode=jit -Cprefer-dynamic
}
function jit() {
jit_naked "fn main() { $@ }"
}
function jit_calc() {
jit 'println!("0x{:x}", ' $@ ');';
}
```
## Env vars ## Env vars
[see env_vars.md](docs/env_vars.md) See [env_vars.md](docs/env_vars.md) for all env vars used by rustc_codegen_cranelift.
## Not yet supported ## Not yet supported
@ -106,3 +55,20 @@ function jit_calc() {
`llvm_asm!` will remain unimplemented forever. `asm!` doesn't yet support reg classes. You `llvm_asm!` will remain unimplemented forever. `asm!` doesn't yet support reg classes. You
have to specify specific registers instead. have to specify specific registers instead.
* SIMD ([tracked here](https://github.com/bjorn3/rustc_codegen_cranelift/issues/171), some basic things work) * SIMD ([tracked here](https://github.com/bjorn3/rustc_codegen_cranelift/issues/171), some basic things work)
## License
Licensed under either of
* Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or
http://www.apache.org/licenses/LICENSE-2.0)
* MIT license ([LICENSE-MIT](LICENSE-MIT) or
http://opensource.org/licenses/MIT)
at your option.
### Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in the work by you shall be dual licensed as above, without any
additional terms or conditions.

View file

@ -55,6 +55,7 @@ ln target/$CHANNEL/*rustc_codegen_cranelift* "$target_dir"/lib
ln rust-toolchain scripts/config.sh scripts/cargo.sh "$target_dir" ln rust-toolchain scripts/config.sh scripts/cargo.sh "$target_dir"
mkdir -p "$target_dir/lib/rustlib/$TARGET_TRIPLE/lib/" mkdir -p "$target_dir/lib/rustlib/$TARGET_TRIPLE/lib/"
mkdir -p "$target_dir/lib/rustlib/$HOST_TRIPLE/lib/"
if [[ "$TARGET_TRIPLE" == "x86_64-pc-windows-gnu" ]]; then if [[ "$TARGET_TRIPLE" == "x86_64-pc-windows-gnu" ]]; then
cp $(rustc --print sysroot)/lib/rustlib/$TARGET_TRIPLE/lib/*.o "$target_dir/lib/rustlib/$TARGET_TRIPLE/lib/" cp $(rustc --print sysroot)/lib/rustlib/$TARGET_TRIPLE/lib/*.o "$target_dir/lib/rustlib/$TARGET_TRIPLE/lib/"
fi fi
@ -64,12 +65,18 @@ case "$build_sysroot" in
;; ;;
"llvm") "llvm")
cp -r $(rustc --print sysroot)/lib/rustlib/$TARGET_TRIPLE/lib "$target_dir/lib/rustlib/$TARGET_TRIPLE/" cp -r $(rustc --print sysroot)/lib/rustlib/$TARGET_TRIPLE/lib "$target_dir/lib/rustlib/$TARGET_TRIPLE/"
if [[ "$HOST_TRIPLE" != "$TARGET_TRIPLE" ]]; then
cp -r $(rustc --print sysroot)/lib/rustlib/$HOST_TRIPLE/lib "$target_dir/lib/rustlib/$HOST_TRIPLE/"
fi
;; ;;
"clif") "clif")
echo "[BUILD] sysroot" echo "[BUILD] sysroot"
dir=$(pwd) dir=$(pwd)
cd "$target_dir" cd "$target_dir"
time "$dir/build_sysroot/build_sysroot.sh" time "$dir/build_sysroot/build_sysroot.sh"
if [[ "$HOST_TRIPLE" != "$TARGET_TRIPLE" ]]; then
time TARGET_TRIPLE="$HOST_TRIPLE" "$dir/build_sysroot/build_sysroot.sh"
fi
cp lib/rustlib/*/lib/libstd-* lib/ cp lib/rustlib/*/lib/libstd-* lib/
;; ;;
*) *)

View file

@ -16,9 +16,9 @@ dependencies = [
[[package]] [[package]]
name = "adler" name = "adler"
version = "0.2.3" version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
dependencies = [ dependencies = [
"compiler_builtins", "compiler_builtins",
"rustc-std-workspace-core", "rustc-std-workspace-core",
@ -110,9 +110,9 @@ dependencies = [
[[package]] [[package]]
name = "hashbrown" name = "hashbrown"
version = "0.9.1" version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
dependencies = [ dependencies = [
"compiler_builtins", "compiler_builtins",
"rustc-std-workspace-alloc", "rustc-std-workspace-alloc",
@ -132,18 +132,18 @@ dependencies = [
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.86" version = "0.2.91"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c" checksum = "8916b1f6ca17130ec6568feccee27c156ad12037880833a3b842a823236502e7"
dependencies = [ dependencies = [
"rustc-std-workspace-core", "rustc-std-workspace-core",
] ]
[[package]] [[package]]
name = "miniz_oxide" name = "miniz_oxide"
version = "0.4.3" version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f2d26ec3309788e423cfbf68ad1800f061638098d76a83681af979dc4eda19d" checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b"
dependencies = [ dependencies = [
"adler", "adler",
"autocfg", "autocfg",

View file

@ -28,7 +28,7 @@ export __CARGO_DEFAULT_LIB_METADATA="cg_clif"
if [[ "$1" != "--debug" ]]; then if [[ "$1" != "--debug" ]]; then
sysroot_channel='release' sysroot_channel='release'
# FIXME Enable incremental again once rust-lang/rust#74946 is fixed # FIXME Enable incremental again once rust-lang/rust#74946 is fixed
CARGO_INCREMENTAL=0 RUSTFLAGS="$RUSTFLAGS -Zmir-opt-level=2" cargo build --target "$TARGET_TRIPLE" --release CARGO_INCREMENTAL=0 RUSTFLAGS="$RUSTFLAGS -Zmir-opt-level=3" cargo build --target "$TARGET_TRIPLE" --release
else else
sysroot_channel='debug' sysroot_channel='debug'
cargo build --target "$TARGET_TRIPLE" cargo build --target "$TARGET_TRIPLE"

View file

@ -8,5 +8,8 @@
to make it possible to use incremental mode for all analyses performed by rustc without caching to make it possible to use incremental mode for all analyses performed by rustc without caching
object files when their content should have been changed by a change to cg_clif.</dd> object files when their content should have been changed by a change to cg_clif.</dd>
<dt>CG_CLIF_DISPLAY_CG_TIME</dt> <dt>CG_CLIF_DISPLAY_CG_TIME</dt>
<dd>If "1", display the time it took to perform codegen for a crate</dd> <dd>If "1", display the time it took to perform codegen for a crate.</dd>
<dt>CG_CLIF_ENABLE_VERIFIER</dt>
<dd>Enable the Cranelift ir verifier for all compilation passes. If not set it will only run once
before passing the clif ir to Cranelift for compilation.</dt>
</dl> </dl>

View file

@ -0,0 +1,66 @@
# Usage
rustc_codegen_cranelift can be used as a near-drop-in replacement for `cargo build` or `cargo run` for existing projects.
Assuming `$cg_clif_dir` is the directory you cloned this repo into and you followed the instructions (`prepare.sh` and `build.sh` or `test.sh`).
## Cargo
In the directory with your project (where you can do the usual `cargo build`), run:
```bash
$ $cg_clif_dir/build/cargo.sh build
```
This will build your project with rustc_codegen_cranelift instead of the usual LLVM backend.
## Rustc
> You should prefer using the Cargo method.
```bash
$ $cg_clif_dir/build/bin/cg_clif my_crate.rs
```
## Jit mode
In jit mode cg_clif will immediately execute your code without creating an executable file.
> This requires all dependencies to be available as dynamic library.
> The jit mode will probably need cargo integration to make this possible.
```bash
$ $cg_clif_dir/build/cargo.sh jit
```
or
```bash
$ $cg_clif_dir/build/bin/cg_clif -Cllvm-args=mode=jit -Cprefer-dynamic my_crate.rs
```
There is also an experimental lazy jit mode. In this mode functions are only compiled once they are
first called. It currently does not work with multi-threaded programs. When a not yet compiled
function is called from another thread than the main thread, you will get an ICE.
```bash
$ $cg_clif_dir/build/cargo.sh lazy-jit
```
## Shell
These are a few functions that allow you to easily run rust code from the shell using cg_clif as jit.
```bash
function jit_naked() {
echo "$@" | $cg_clif_dir/build/bin/cg_clif - -Cllvm-args=mode=jit -Cprefer-dynamic
}
function jit() {
jit_naked "fn main() { $@ }"
}
function jit_calc() {
jit 'println!("0x{:x}", ' $@ ');';
}
```

View file

@ -621,6 +621,7 @@ struct PanicLocation {
} }
#[no_mangle] #[no_mangle]
#[cfg(not(windows))]
pub fn get_tls() -> u8 { pub fn get_tls() -> u8 {
#[thread_local] #[thread_local]
static A: u8 = 42; static A: u8 = 42;

View file

@ -1,7 +1,4 @@
#![feature( #![feature(no_core, lang_items, box_syntax, never_type, linkage, extern_types, thread_local)]
no_core, start, lang_items, box_syntax, never_type, linkage,
extern_types, thread_local
)]
#![no_core] #![no_core]
#![allow(dead_code, non_camel_case_types)] #![allow(dead_code, non_camel_case_types)]
@ -239,7 +236,7 @@ fn main() {
assert_eq!(((|()| 42u8) as fn(()) -> u8)(()), 42); assert_eq!(((|()| 42u8) as fn(()) -> u8)(()), 42);
#[cfg(not(jit))] #[cfg(not(any(jit, windows)))]
{ {
extern { extern {
#[linkage = "extern_weak"] #[linkage = "extern_weak"]
@ -292,7 +289,7 @@ fn main() {
from_decimal_string(); from_decimal_string();
#[cfg(not(jit))] #[cfg(not(any(jit, windows)))]
test_tls(); test_tls();
#[cfg(all(not(jit), target_os = "linux"))] #[cfg(all(not(jit), target_os = "linux"))]

View file

@ -1,7 +1,6 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -e set -e
rustup component add rust-src rustc-dev llvm-tools-preview
./build_sysroot/prepare_sysroot_src.sh ./build_sysroot/prepare_sysroot_src.sh
cargo install hyperfine || echo "Skipping hyperfine install" cargo install hyperfine || echo "Skipping hyperfine install"

View file

@ -1 +1,3 @@
nightly-2021-03-05 [toolchain]
channel = "nightly-2021-03-29"
components = ["rust-src", "rustc-dev", "llvm-tools-preview"]

View file

@ -4,7 +4,7 @@ dir=$(dirname "$0")
source "$dir/config.sh" source "$dir/config.sh"
# read nightly compiler from rust-toolchain file # read nightly compiler from rust-toolchain file
TOOLCHAIN=$(cat "$dir/rust-toolchain") TOOLCHAIN=$(cat "$dir/rust-toolchain" | grep channel | sed "s/channel = \"\(.*\)\"/\1/")
cmd=$1 cmd=$1
shift || true shift || true

View file

@ -2,15 +2,7 @@
set -e set -e
unamestr=$(uname) dylib=$(echo "" | rustc --print file-names --crate-type dylib --crate-name rustc_codegen_cranelift -)
if [[ "$unamestr" == 'Linux' || "$unamestr" == 'FreeBSD' ]]; then
dylib_ext='so'
elif [[ "$unamestr" == 'Darwin' ]]; then
dylib_ext='dylib'
else
echo "Unsupported os"
exit 1
fi
if echo "$RUSTC_WRAPPER" | grep sccache; then if echo "$RUSTC_WRAPPER" | grep sccache; then
echo echo
@ -24,10 +16,10 @@ dir=$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)
export RUSTC=$dir"/bin/cg_clif" export RUSTC=$dir"/bin/cg_clif"
export RUSTDOCFLAGS=$linker' -Cpanic=abort -Zpanic-abort-tests '\ export RUSTDOCFLAGS=$linker' -Cpanic=abort -Zpanic-abort-tests '\
'-Zcodegen-backend='$dir'/lib/librustc_codegen_cranelift.'$dylib_ext' --sysroot '$dir '-Zcodegen-backend='$dir'/lib/'$dylib' --sysroot '$dir
# FIXME fix `#[linkage = "extern_weak"]` without this # FIXME fix `#[linkage = "extern_weak"]` without this
if [[ "$unamestr" == 'Darwin' ]]; then if [[ "$(uname)" == 'Darwin' ]]; then
export RUSTFLAGS="$RUSTFLAGS -Clink-arg=-undefined -Clink-arg=dynamic_lookup" export RUSTFLAGS="$RUSTFLAGS -Clink-arg=-undefined -Clink-arg=dynamic_lookup"
fi fi

View file

@ -8,7 +8,7 @@ case $1 in
echo "=> Installing new nightly" echo "=> Installing new nightly"
rustup toolchain install --profile minimal "nightly-${TOOLCHAIN}" # Sanity check to see if the nightly exists rustup toolchain install --profile minimal "nightly-${TOOLCHAIN}" # Sanity check to see if the nightly exists
echo "nightly-${TOOLCHAIN}" > rust-toolchain sed -i "s/\"nightly-.*\"/\"nightly-${TOOLCHAIN}\"/" rust-toolchain
rustup component add rustfmt || true rustup component add rustfmt || true
echo "=> Uninstalling all old nighlies" echo "=> Uninstalling all old nighlies"

View file

@ -0,0 +1,68 @@
#!/bin/bash
set -e
./build.sh
source build/config.sh
echo "[SETUP] Rust fork"
git clone https://github.com/rust-lang/rust.git || true
pushd rust
git fetch
git checkout -- .
git checkout "$(rustc -V | cut -d' ' -f3 | tr -d '(')"
git apply - <<EOF
diff --git a/Cargo.toml b/Cargo.toml
index 5bd1147cad5..10d68a2ff14 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -111,5 +111,7 @@ rustc-std-workspace-std = { path = 'library/rustc-std-workspace-std' }
rustc-std-workspace-alloc = { path = 'library/rustc-std-workspace-alloc' }
rustc-std-workspace-std = { path = 'library/rustc-std-workspace-std' }
+compiler_builtins = { path = "../build_sysroot/compiler-builtins" }
+
[patch."https://github.com/rust-lang/rust-clippy"]
clippy_lints = { path = "src/tools/clippy/clippy_lints" }
diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml
index 23e689fcae7..5f077b765b6 100644
--- a/compiler/rustc_data_structures/Cargo.toml
+++ b/compiler/rustc_data_structures/Cargo.toml
@@ -32,7 +32,6 @@ tempfile = "3.0.5"
[dependencies.parking_lot]
version = "0.11"
-features = ["nightly"]
[target.'cfg(windows)'.dependencies]
winapi = { version = "0.3", features = ["fileapi", "psapi"] }
diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml
index d95b5b7f17f..00b6f0e3635 100644
--- a/library/alloc/Cargo.toml
+++ b/library/alloc/Cargo.toml
@@ -8,7 +8,7 @@ edition = "2018"
[dependencies]
core = { path = "../core" }
-compiler_builtins = { version = "0.1.39", features = ['rustc-dep-of-std'] }
+compiler_builtins = { version = "0.1.39", features = ['rustc-dep-of-std', 'no-asm'] }
[dev-dependencies]
rand = "0.7"
EOF
cat > config.toml <<EOF
[llvm]
ninja = false
[build]
rustc = "$(pwd)/../build/bin/cg_clif"
cargo = "$(rustup which cargo)"
full-bootstrap = true
local-rebuild = true
[rust]
codegen-backends = ["cranelift"]
deny-warnings = false
EOF
popd

View file

@ -3,70 +3,10 @@ set -e
cd "$(dirname "$0")/../" cd "$(dirname "$0")/../"
./build.sh source ./scripts/setup_rust_fork.sh
source build/config.sh
echo "[TEST] Bootstrap of rustc" echo "[TEST] Bootstrap of rustc"
git clone https://github.com/rust-lang/rust.git || true
pushd rust pushd rust
git fetch
git checkout -- .
git checkout "$(rustc -V | cut -d' ' -f3 | tr -d '(')"
git apply - <<EOF
diff --git a/Cargo.toml b/Cargo.toml
index 5bd1147cad5..10d68a2ff14 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -111,5 +111,7 @@ rustc-std-workspace-std = { path = 'library/rustc-std-workspace-std' }
rustc-std-workspace-alloc = { path = 'library/rustc-std-workspace-alloc' }
rustc-std-workspace-std = { path = 'library/rustc-std-workspace-std' }
+compiler_builtins = { path = "../build_sysroot/compiler-builtins" }
+
[patch."https://github.com/rust-lang/rust-clippy"]
clippy_lints = { path = "src/tools/clippy/clippy_lints" }
diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml
index 23e689fcae7..5f077b765b6 100644
--- a/compiler/rustc_data_structures/Cargo.toml
+++ b/compiler/rustc_data_structures/Cargo.toml
@@ -32,7 +32,6 @@ tempfile = "3.0.5"
[dependencies.parking_lot]
version = "0.11"
-features = ["nightly"]
[target.'cfg(windows)'.dependencies]
winapi = { version = "0.3", features = ["fileapi", "psapi"] }
diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml
index d95b5b7f17f..00b6f0e3635 100644
--- a/library/alloc/Cargo.toml
+++ b/library/alloc/Cargo.toml
@@ -8,7 +8,7 @@ edition = "2018"
[dependencies]
core = { path = "../core" }
-compiler_builtins = { version = "0.1.39", features = ['rustc-dep-of-std'] }
+compiler_builtins = { version = "0.1.39", features = ['rustc-dep-of-std', 'no-asm'] }
[dev-dependencies]
rand = "0.7"
EOF
cat > config.toml <<EOF
[llvm]
ninja = false
[build]
rustc = "$(pwd)/../build/bin/cg_clif"
cargo = "$(rustup which cargo)"
full-bootstrap = true
local-rebuild = true
[rust]
codegen-backends = ["cranelift"]
EOF
rm -r compiler/rustc_codegen_cranelift/{Cargo.*,src} rm -r compiler/rustc_codegen_cranelift/{Cargo.*,src}
cp ../Cargo.* compiler/rustc_codegen_cranelift/ cp ../Cargo.* compiler/rustc_codegen_cranelift/
cp -r ../src compiler/rustc_codegen_cranelift/src cp -r ../src compiler/rustc_codegen_cranelift/src

View file

@ -0,0 +1,87 @@
#!/bin/bash
set -e
cd $(dirname "$0")/../
source ./scripts/setup_rust_fork.sh
echo "[TEST] Test suite of rustc"
pushd rust
cargo install ripgrep
rm -r src/test/ui/{extern/,panics/,unsized-locals/,thinlto/,simd*,*lto*.rs,linkage*,unwind-*.rs} || true
for test in $(rg --files-with-matches "asm!|catch_unwind|should_panic|lto" src/test/ui); do
rm $test
done
for test in $(rg -i --files-with-matches "//(\[\w+\])?~|// error-pattern:|// build-fail|// run-fail|-Cllvm-args" src/test/ui); do
rm $test
done
git checkout -- src/test/ui/issues/auxiliary/issue-3136-a.rs # contains //~ERROR, but shouldn't be removed
# these all depend on unwinding support
rm src/test/ui/backtrace.rs
rm src/test/ui/array-slice-vec/box-of-array-of-drop-*.rs
rm src/test/ui/array-slice-vec/slice-panic-*.rs
rm src/test/ui/array-slice-vec/nested-vec-3.rs
rm src/test/ui/cleanup-rvalue-temp-during-incomplete-alloc.rs
rm src/test/ui/issues/issue-26655.rs
rm src/test/ui/issues/issue-29485.rs
rm src/test/ui/issues/issue-30018-panic.rs
rm src/test/ui/multi-panic.rs
rm src/test/ui/sepcomp/sepcomp-unwind.rs
rm src/test/ui/structs-enums/unit-like-struct-drop-run.rs
rm src/test/ui/terminate-in-initializer.rs
rm src/test/ui/threads-sendsync/task-stderr.rs
rm src/test/ui/numbers-arithmetic/int-abs-overflow.rs
rm src/test/ui/drop/drop-trait-enum.rs
rm src/test/ui/numbers-arithmetic/issue-8460.rs
rm src/test/ui/issues/issue-28950.rs # depends on stack size optimizations
rm src/test/ui/init-large-type.rs # same
rm src/test/ui/sse2.rs # cpuid not supported, so sse2 not detected
rm src/test/ui/issues/issue-33992.rs # unsupported linkages
rm src/test/ui/issues/issue-51947.rs # same
rm src/test/ui/numbers-arithmetic/saturating-float-casts.rs # intrinsic gives different but valid result
rm src/test/ui/mir/mir_misc_casts.rs # depends on deduplication of constants
rm src/test/ui/mir/mir_raw_fat_ptr.rs # same
rm src/test/ui/async-await/async-fn-size-moved-locals.rs # -Cpanic=abort shrinks some generator by one byte
rm src/test/ui/async-await/async-fn-size-uninit-locals.rs # same
rm src/test/ui/generator/size-moved-locals.rs # same
rm src/test/ui/fn/dyn-fn-alignment.rs # wants a 256 byte alignment
rm src/test/ui/test-attrs/test-fn-signature-verification-for-explicit-return-type.rs # "Cannot run dynamic test fn out-of-process"
rm src/test/ui/intrinsics/intrinsic-nearby.rs # unimplemented nearbyintf32 and nearbyintf64 intrinsics
rm src/test/incremental/hashes/inline_asm.rs # inline asm
rm src/test/incremental/issue-72386.rs # same
rm src/test/incremental/change_crate_dep_kind.rs # requires -Cpanic=unwind
rm src/test/incremental/issue-49482.rs # same
rm src/test/incremental/issue-54059.rs # same
rm src/test/incremental/lto.rs # requires lto
rm src/test/pretty/asm.rs # inline asm
rm src/test/pretty/raw-str-nonexpr.rs # same
rm -r src/test/run-pass-valgrind/unsized-locals
rm src/test/ui/json-bom-plus-crlf-multifile.rs # differing warning
rm src/test/ui/json-bom-plus-crlf.rs # same
rm src/test/ui/type-alias-impl-trait/cross_crate_ice*.rs # requires removed aux dep
rm src/test/ui/allocator/no_std-alloc-error-handler-default.rs # missing rust_oom definition
rm src/test/ui/cfg/cfg-panic.rs
rm src/test/ui/default-alloc-error-hook.rs
rm -r src/test/ui/hygiene/
rm -r src/test/ui/polymorphization/ # polymorphization not yet supported
rm src/test/codegen-units/polymorphization/unused_type_parameters.rs # same
rm -r src/test/run-make/fmt-write-bloat/ # tests an optimization
rm src/test/ui/abi/mir/mir_codegen_calls_variadic.rs # requires float varargs
rm src/test/ui/abi/variadic-ffi.rs # requires callee side vararg support
echo "[TEST] rustc test suite"
RUST_TEST_NOCAPTURE=1 COMPILETEST_FORCE_STAGE0=1 ./x.py test --stage 0 src/test/{codegen-units,run-make,run-pass-valgrind,ui}
popd

View file

@ -71,14 +71,20 @@ function base_sysroot_tests() {
echo "[AOT] mod_bench" echo "[AOT] mod_bench"
$MY_RUSTC example/mod_bench.rs --crate-type bin --target "$TARGET_TRIPLE" $MY_RUSTC example/mod_bench.rs --crate-type bin --target "$TARGET_TRIPLE"
$RUN_WRAPPER ./target/out/mod_bench $RUN_WRAPPER ./target/out/mod_bench
pushd rand
rm -r ./target || true
../build/cargo.sh test --workspace
popd
} }
function extended_sysroot_tests() { function extended_sysroot_tests() {
pushd rand
cargo clean
if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then
echo "[TEST] rust-random/rand"
../build/cargo.sh test --workspace
else
echo "[AOT] rust-random/rand"
../build/cargo.sh build --workspace --target $TARGET_TRIPLE --tests
fi
popd
pushd simple-raytracer pushd simple-raytracer
if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then
echo "[BENCH COMPILE] ebobby/simple-raytracer" echo "[BENCH COMPILE] ebobby/simple-raytracer"
@ -92,27 +98,40 @@ function extended_sysroot_tests() {
else else
echo "[BENCH COMPILE] ebobby/simple-raytracer (skipped)" echo "[BENCH COMPILE] ebobby/simple-raytracer (skipped)"
echo "[COMPILE] ebobby/simple-raytracer" echo "[COMPILE] ebobby/simple-raytracer"
../cargo.sh build ../build/cargo.sh build --target $TARGET_TRIPLE
echo "[BENCH RUN] ebobby/simple-raytracer (skipped)" echo "[BENCH RUN] ebobby/simple-raytracer (skipped)"
fi fi
popd popd
pushd build_sysroot/sysroot_src/library/core/tests pushd build_sysroot/sysroot_src/library/core/tests
echo "[TEST] libcore" echo "[TEST] libcore"
rm -r ./target || true cargo clean
if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then
../../../../../build/cargo.sh test ../../../../../build/cargo.sh test
else
../../../../../build/cargo.sh build --target $TARGET_TRIPLE --tests
fi
popd popd
pushd regex pushd regex
echo "[TEST] rust-lang/regex example shootout-regex-dna" echo "[TEST] rust-lang/regex example shootout-regex-dna"
../build/cargo.sh clean cargo clean
# Make sure `[codegen mono items] start` doesn't poison the diff # Make sure `[codegen mono items] start` doesn't poison the diff
../build/cargo.sh build --example shootout-regex-dna ../build/cargo.sh build --example shootout-regex-dna --target $TARGET_TRIPLE
cat examples/regexdna-input.txt | ../build/cargo.sh run --example shootout-regex-dna | grep -v "Spawned thread" > res.txt if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then
cat examples/regexdna-input.txt \
| ../build/cargo.sh run --example shootout-regex-dna --target $TARGET_TRIPLE \
| grep -v "Spawned thread" > res.txt
diff -u res.txt examples/regexdna-output.txt diff -u res.txt examples/regexdna-output.txt
fi
if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then
echo "[TEST] rust-lang/regex tests" echo "[TEST] rust-lang/regex tests"
../build/cargo.sh test --tests -- --exclude-should-panic --test-threads 1 -Zunstable-options -q ../build/cargo.sh test --tests -- --exclude-should-panic --test-threads 1 -Zunstable-options -q
else
echo "[AOT] rust-lang/regex tests"
../build/cargo.sh build --tests --target $TARGET_TRIPLE
fi
popd popd
} }

View file

@ -11,9 +11,11 @@ use cranelift_codegen::entity::EntityRef;
use crate::prelude::*; use crate::prelude::*;
pub(super) fn add_args_header_comment(fx: &mut FunctionCx<'_, '_, '_>) { pub(super) fn add_args_header_comment(fx: &mut FunctionCx<'_, '_, '_>) {
if fx.clif_comments.enabled() {
fx.add_global_comment( fx.add_global_comment(
"kind loc.idx param pass mode ty".to_string(), "kind loc.idx param pass mode ty".to_string(),
); );
}
} }
pub(super) fn add_arg_comment<'tcx>( pub(super) fn add_arg_comment<'tcx>(
@ -25,6 +27,10 @@ pub(super) fn add_arg_comment<'tcx>(
arg_abi_mode: PassMode, arg_abi_mode: PassMode,
arg_layout: TyAndLayout<'tcx>, arg_layout: TyAndLayout<'tcx>,
) { ) {
if !fx.clif_comments.enabled() {
return;
}
let local = if let Some(local) = local { let local = if let Some(local) = local {
Cow::Owned(format!("{:?}", local)) Cow::Owned(format!("{:?}", local))
} else { } else {
@ -59,10 +65,12 @@ pub(super) fn add_arg_comment<'tcx>(
} }
pub(super) fn add_locals_header_comment(fx: &mut FunctionCx<'_, '_, '_>) { pub(super) fn add_locals_header_comment(fx: &mut FunctionCx<'_, '_, '_>) {
if fx.clif_comments.enabled() {
fx.add_global_comment(String::new()); fx.add_global_comment(String::new());
fx.add_global_comment( fx.add_global_comment(
"kind local ty size align (abi,pref)".to_string(), "kind local ty size align (abi,pref)".to_string(),
); );
}
} }
pub(super) fn add_local_place_comments<'tcx>( pub(super) fn add_local_place_comments<'tcx>(
@ -70,6 +78,9 @@ pub(super) fn add_local_place_comments<'tcx>(
place: CPlace<'tcx>, place: CPlace<'tcx>,
local: Local, local: Local,
) { ) {
if !fx.clif_comments.enabled() {
return;
}
let TyAndLayout { ty, layout } = place.layout(); let TyAndLayout { ty, layout } = place.layout();
let rustc_target::abi::Layout { size, align, abi: _, variants: _, fields: _, largest_niche: _ } = let rustc_target::abi::Layout { size, align, abi: _, variants: _, fields: _, largest_niche: _ } =
layout; layout;
@ -90,7 +101,7 @@ pub(super) fn add_local_place_comments<'tcx>(
} else { } else {
Cow::Borrowed("") Cow::Borrowed("")
}; };
match ptr.base_and_offset() { match ptr.debug_base_and_offset() {
(crate::pointer::PointerBase::Addr(addr), offset) => { (crate::pointer::PointerBase::Addr(addr), offset) => {
("reuse", format!("storage={}{}{}", addr, offset, meta).into()) ("reuse", format!("storage={}{}{}", addr, offset, meta).into())
} }

View file

@ -1,6 +1,5 @@
//! Handling of everything related to the calling convention. Also fills `fx.local_map`. //! Handling of everything related to the calling convention. Also fills `fx.local_map`.
#[cfg(debug_assertions)]
mod comments; mod comments;
mod pass_mode; mod pass_mode;
mod returning; mod returning;
@ -75,8 +74,9 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
let func_id = import_function(self.tcx, self.cx.module, inst); let func_id = import_function(self.tcx, self.cx.module, inst);
let func_ref = self.cx.module.declare_func_in_func(func_id, &mut self.bcx.func); let func_ref = self.cx.module.declare_func_in_func(func_id, &mut self.bcx.func);
#[cfg(debug_assertions)] if self.clif_comments.enabled() {
self.add_comment(func_ref, format!("{:?}", inst)); self.add_comment(func_ref, format!("{:?}", inst));
}
func_ref func_ref
} }
@ -92,8 +92,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
let func_id = self.cx.module.declare_function(&name, Linkage::Import, &sig).unwrap(); let func_id = self.cx.module.declare_function(&name, Linkage::Import, &sig).unwrap();
let func_ref = self.cx.module.declare_func_in_func(func_id, &mut self.bcx.func); let func_ref = self.cx.module.declare_func_in_func(func_id, &mut self.bcx.func);
let call_inst = self.bcx.ins().call(func_ref, args); let call_inst = self.bcx.ins().call(func_ref, args);
#[cfg(debug_assertions)] if self.clif_comments.enabled() {
{
self.add_comment(call_inst, format!("easy_call {}", name)); self.add_comment(call_inst, format!("easy_call {}", name));
} }
let results = self.bcx.inst_results(call_inst); let results = self.bcx.inst_results(call_inst);
@ -149,7 +148,6 @@ fn make_local_place<'tcx>(
CPlace::new_stack_slot(fx, layout) CPlace::new_stack_slot(fx, layout)
}; };
#[cfg(debug_assertions)]
self::comments::add_local_place_comments(fx, place, local); self::comments::add_local_place_comments(fx, place, local);
place place
@ -163,7 +161,6 @@ pub(crate) fn codegen_fn_prelude<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, start_
let ssa_analyzed = crate::analyze::analyze(fx); let ssa_analyzed = crate::analyze::analyze(fx);
#[cfg(debug_assertions)]
self::comments::add_args_header_comment(fx); self::comments::add_args_header_comment(fx);
let mut block_params_iter = fx.bcx.func.dfg.block_params(start_block).to_vec().into_iter(); let mut block_params_iter = fx.bcx.func.dfg.block_params(start_block).to_vec().into_iter();
@ -228,7 +225,6 @@ pub(crate) fn codegen_fn_prelude<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, start_
fx.fn_abi = Some(fn_abi); fx.fn_abi = Some(fn_abi);
assert!(block_params_iter.next().is_none(), "arg_value left behind"); assert!(block_params_iter.next().is_none(), "arg_value left behind");
#[cfg(debug_assertions)]
self::comments::add_locals_header_comment(fx); self::comments::add_locals_header_comment(fx);
for (local, arg_kind, ty) in func_params { for (local, arg_kind, ty) in func_params {
@ -256,7 +252,6 @@ pub(crate) fn codegen_fn_prelude<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, start_
CPlace::for_ptr(addr, val.layout()) CPlace::for_ptr(addr, val.layout())
}; };
#[cfg(debug_assertions)]
self::comments::add_local_place_comments(fx, place, local); self::comments::add_local_place_comments(fx, place, local);
assert_eq!(fx.local_map.push(place), local); assert_eq!(fx.local_map.push(place), local);
@ -392,8 +387,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
let (func_ref, first_arg) = match instance { let (func_ref, first_arg) = match instance {
// Trait object call // Trait object call
Some(Instance { def: InstanceDef::Virtual(_, idx), .. }) => { Some(Instance { def: InstanceDef::Virtual(_, idx), .. }) => {
#[cfg(debug_assertions)] if fx.clif_comments.enabled() {
{
let nop_inst = fx.bcx.ins().nop(); let nop_inst = fx.bcx.ins().nop();
fx.add_comment( fx.add_comment(
nop_inst, nop_inst,
@ -414,8 +408,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
// Indirect call // Indirect call
None => { None => {
#[cfg(debug_assertions)] if fx.clif_comments.enabled() {
{
let nop_inst = fx.bcx.ins().nop(); let nop_inst = fx.bcx.ins().nop();
fx.add_comment(nop_inst, "indirect call"); fx.add_comment(nop_inst, "indirect call");
} }
@ -477,10 +470,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
// FIXME find a cleaner way to support varargs // FIXME find a cleaner way to support varargs
if fn_sig.c_variadic { if fn_sig.c_variadic {
if !matches!(fn_sig.abi, Abi::C { .. }) { if !matches!(fn_sig.abi, Abi::C { .. }) {
fx.tcx.sess.span_fatal( fx.tcx.sess.span_fatal(span, &format!("Variadic call for non-C abi {:?}", fn_sig.abi));
span,
&format!("Variadic call for non-C abi {:?}", fn_sig.abi),
);
} }
let sig_ref = fx.bcx.func.dfg.call_signature(call_inst).unwrap(); let sig_ref = fx.bcx.func.dfg.call_signature(call_inst).unwrap();
let abi_params = call_args let abi_params = call_args

View file

@ -208,7 +208,7 @@ pub(super) fn from_casted_value<'tcx>(
}); });
let ptr = Pointer::new(fx.bcx.ins().stack_addr(pointer_ty(fx.tcx), stack_slot, 0)); let ptr = Pointer::new(fx.bcx.ins().stack_addr(pointer_ty(fx.tcx), stack_slot, 0));
let mut offset = 0; let mut offset = 0;
let mut block_params_iter = block_params.into_iter().copied(); let mut block_params_iter = block_params.iter().copied();
for param in abi_params { for param in abi_params {
let val = ptr.offset_i64(fx, offset).store( let val = ptr.offset_i64(fx, offset).store(
fx, fx,
@ -248,8 +248,8 @@ pub(super) fn adjust_arg_for_abi<'tcx>(
/// as necessary. /// as necessary.
pub(super) fn cvalue_for_param<'tcx>( pub(super) fn cvalue_for_param<'tcx>(
fx: &mut FunctionCx<'_, '_, 'tcx>, fx: &mut FunctionCx<'_, '_, 'tcx>,
#[cfg_attr(not(debug_assertions), allow(unused_variables))] local: Option<mir::Local>, local: Option<mir::Local>,
#[cfg_attr(not(debug_assertions), allow(unused_variables))] local_field: Option<usize>, local_field: Option<usize>,
arg_abi: &ArgAbi<'tcx, Ty<'tcx>>, arg_abi: &ArgAbi<'tcx, Ty<'tcx>>,
block_params_iter: &mut impl Iterator<Item = Value>, block_params_iter: &mut impl Iterator<Item = Value>,
) -> Option<CValue<'tcx>> { ) -> Option<CValue<'tcx>> {
@ -263,7 +263,6 @@ pub(super) fn cvalue_for_param<'tcx>(
}) })
.collect::<SmallVec<[_; 2]>>(); .collect::<SmallVec<[_; 2]>>();
#[cfg(debug_assertions)]
crate::abi::comments::add_arg_comment( crate::abi::comments::add_arg_comment(
fx, fx,
"arg", "arg",

View file

@ -84,10 +84,6 @@ pub(super) fn codegen_return_param<'tcx>(
} }
}; };
#[cfg(not(debug_assertions))]
let _ = ret_param;
#[cfg(debug_assertions)]
crate::abi::comments::add_arg_comment( crate::abi::comments::add_arg_comment(
fx, fx,
"ret", "ret",
@ -146,7 +142,7 @@ pub(super) fn codegen_with_call_return_arg<'tcx, T>(
let results = fx let results = fx
.bcx .bcx
.inst_results(call_inst) .inst_results(call_inst)
.into_iter() .iter()
.copied() .copied()
.collect::<SmallVec<[Value; 2]>>(); .collect::<SmallVec<[Value; 2]>>();
let result = let result =

View file

@ -3,6 +3,7 @@
use crate::prelude::*; use crate::prelude::*;
use cranelift_codegen::binemit::{NullStackMapSink, NullTrapSink};
use rustc_ast::expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS}; use rustc_ast::expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS};
use rustc_span::symbol::sym; use rustc_span::symbol::sym;
@ -92,7 +93,7 @@ fn codegen_inner(
bcx.finalize(); bcx.finalize();
} }
module module
.define_function(func_id, &mut ctx, &mut cranelift_codegen::binemit::NullTrapSink {}) .define_function(func_id, &mut ctx, &mut NullTrapSink {}, &mut NullStackMapSink {})
.unwrap(); .unwrap();
unwind_context.add_function(func_id, &ctx, module.isa()); unwind_context.add_function(func_id, &ctx, module.isa());
} }
@ -132,7 +133,7 @@ fn codegen_inner(
bcx.finalize(); bcx.finalize();
} }
module module
.define_function(func_id, &mut ctx, &mut cranelift_codegen::binemit::NullTrapSink {}) .define_function(func_id, &mut ctx, &mut NullTrapSink {}, &mut NullStackMapSink {})
.unwrap(); .unwrap();
unwind_context.add_function(func_id, &ctx, module.isa()); unwind_context.add_function(func_id, &ctx, module.isa());
} }

View file

@ -1,5 +1,6 @@
//! Codegen of a single function //! Codegen of a single function
use cranelift_codegen::binemit::{NullStackMapSink, NullTrapSink};
use rustc_index::vec::IndexVec; use rustc_index::vec::IndexVec;
use rustc_middle::ty::adjustment::PointerCast; use rustc_middle::ty::adjustment::PointerCast;
use rustc_middle::ty::layout::FnAbiExt; use rustc_middle::ty::layout::FnAbiExt;
@ -7,11 +8,7 @@ use rustc_target::abi::call::FnAbi;
use crate::prelude::*; use crate::prelude::*;
pub(crate) fn codegen_fn<'tcx>( pub(crate) fn codegen_fn<'tcx>(cx: &mut crate::CodegenCx<'_, 'tcx>, instance: Instance<'tcx>) {
cx: &mut crate::CodegenCx<'_, 'tcx>,
instance: Instance<'tcx>,
linkage: Linkage,
) {
let tcx = cx.tcx; let tcx = cx.tcx;
let _inst_guard = let _inst_guard =
@ -23,7 +20,7 @@ pub(crate) fn codegen_fn<'tcx>(
// Declare function // Declare function
let name = tcx.symbol_name(instance).name.to_string(); let name = tcx.symbol_name(instance).name.to_string();
let sig = get_function_sig(tcx, cx.module.isa().triple(), instance); let sig = get_function_sig(tcx, cx.module.isa().triple(), instance);
let func_id = cx.module.declare_function(&name, linkage, &sig).unwrap(); let func_id = cx.module.declare_function(&name, Linkage::Local, &sig).unwrap();
cx.cached_context.clear(); cx.cached_context.clear();
@ -131,7 +128,7 @@ pub(crate) fn codegen_fn<'tcx>(
let module = &mut cx.module; let module = &mut cx.module;
tcx.sess.time("define function", || { tcx.sess.time("define function", || {
module module
.define_function(func_id, context, &mut cranelift_codegen::binemit::NullTrapSink {}) .define_function(func_id, context, &mut NullTrapSink {}, &mut NullStackMapSink {})
.unwrap() .unwrap()
}); });
@ -219,8 +216,7 @@ fn codegen_fn_content(fx: &mut FunctionCx<'_, '_, '_>) {
codegen_stmt(fx, block, stmt); codegen_stmt(fx, block, stmt);
} }
#[cfg(debug_assertions)] if fx.clif_comments.enabled() {
{
let mut terminator_head = "\n".to_string(); let mut terminator_head = "\n".to_string();
bb_data.terminator().kind.fmt_head(&mut terminator_head).unwrap(); bb_data.terminator().kind.fmt_head(&mut terminator_head).unwrap();
let inst = fx.bcx.func.layout.last_inst(block).unwrap(); let inst = fx.bcx.func.layout.last_inst(block).unwrap();
@ -433,14 +429,16 @@ fn codegen_stmt<'tcx>(
fx.set_debug_loc(stmt.source_info); fx.set_debug_loc(stmt.source_info);
#[cfg(false_debug_assertions)] #[cfg(disabled)]
match &stmt.kind { match &stmt.kind {
StatementKind::StorageLive(..) | StatementKind::StorageDead(..) => {} // Those are not very useful StatementKind::StorageLive(..) | StatementKind::StorageDead(..) => {} // Those are not very useful
_ => { _ => {
if fx.clif_comments.enabled() {
let inst = fx.bcx.func.layout.last_inst(cur_block).unwrap(); let inst = fx.bcx.func.layout.last_inst(cur_block).unwrap();
fx.add_comment(inst, format!("{:?}", stmt)); fx.add_comment(inst, format!("{:?}", stmt));
} }
} }
}
match &stmt.kind { match &stmt.kind {
StatementKind::SetDiscriminant { place, variant_index } => { StatementKind::SetDiscriminant { place, variant_index } => {
@ -464,16 +462,16 @@ fn codegen_stmt<'tcx>(
let val = crate::constant::codegen_tls_ref(fx, def_id, lval.layout()); let val = crate::constant::codegen_tls_ref(fx, def_id, lval.layout());
lval.write_cvalue(fx, val); lval.write_cvalue(fx, val);
} }
Rvalue::BinaryOp(bin_op, box (ref lhs, ref rhs)) => { Rvalue::BinaryOp(bin_op, ref lhs_rhs) => {
let lhs = codegen_operand(fx, lhs); let lhs = codegen_operand(fx, &lhs_rhs.0);
let rhs = codegen_operand(fx, rhs); let rhs = codegen_operand(fx, &lhs_rhs.1);
let res = crate::num::codegen_binop(fx, bin_op, lhs, rhs); let res = crate::num::codegen_binop(fx, bin_op, lhs, rhs);
lval.write_cvalue(fx, res); lval.write_cvalue(fx, res);
} }
Rvalue::CheckedBinaryOp(bin_op, box (ref lhs, ref rhs)) => { Rvalue::CheckedBinaryOp(bin_op, ref lhs_rhs) => {
let lhs = codegen_operand(fx, lhs); let lhs = codegen_operand(fx, &lhs_rhs.0);
let rhs = codegen_operand(fx, rhs); let rhs = codegen_operand(fx, &lhs_rhs.1);
let res = if !fx.tcx.sess.overflow_checks() { let res = if !fx.tcx.sess.overflow_checks() {
let val = let val =
@ -659,7 +657,9 @@ fn codegen_stmt<'tcx>(
.val .val
.try_to_bits(fx.tcx.data_layout.pointer_size) .try_to_bits(fx.tcx.data_layout.pointer_size)
.unwrap(); .unwrap();
if fx.clif_type(operand.layout().ty) == Some(types::I8) { if operand.layout().size.bytes() == 0 {
// Do nothing for ZST's
} else if fx.clif_type(operand.layout().ty) == Some(types::I8) {
let times = fx.bcx.ins().iconst(fx.pointer_type, times as i64); let times = fx.bcx.ins().iconst(fx.pointer_type, times as i64);
// FIXME use emit_small_memset where possible // FIXME use emit_small_memset where possible
let addr = lval.to_ptr().get_addr(fx); let addr = lval.to_ptr().get_addr(fx);
@ -832,25 +832,18 @@ fn codegen_stmt<'tcx>(
} }
} }
StatementKind::Coverage { .. } => fx.tcx.sess.fatal("-Zcoverage is unimplemented"), StatementKind::Coverage { .. } => fx.tcx.sess.fatal("-Zcoverage is unimplemented"),
StatementKind::CopyNonOverlapping(box rustc_middle::mir::CopyNonOverlapping { StatementKind::CopyNonOverlapping(inner) => {
src, let dst = codegen_operand(fx, &inner.dst);
dst,
count,
}) => {
let dst = codegen_operand(fx, dst);
let pointee = dst let pointee = dst
.layout() .layout()
.pointee_info_at(fx, rustc_target::abi::Size::ZERO) .pointee_info_at(fx, rustc_target::abi::Size::ZERO)
.expect("Expected pointer"); .expect("Expected pointer");
let dst = dst.load_scalar(fx); let dst = dst.load_scalar(fx);
let src = codegen_operand(fx, src).load_scalar(fx); let src = codegen_operand(fx, &inner.src).load_scalar(fx);
let count = codegen_operand(fx, count).load_scalar(fx); let count = codegen_operand(fx, &inner.count).load_scalar(fx);
let elem_size: u64 = pointee.size.bytes(); let elem_size: u64 = pointee.size.bytes();
let bytes = if elem_size != 1 { let bytes =
fx.bcx.ins().imul_imm(count, elem_size as i64) if elem_size != 1 { fx.bcx.ins().imul_imm(count, elem_size as i64) } else { count };
} else {
count
};
fx.bcx.call_memcpy(fx.cx.module.target_config(), dst, src, bytes); fx.bcx.call_memcpy(fx.cx.module.target_config(), dst, src, bytes);
} }
} }

View file

@ -32,18 +32,56 @@ pub(crate) fn maybe_codegen<'tcx>(
BinOp::Add | BinOp::Sub if !checked => None, BinOp::Add | BinOp::Sub if !checked => None,
BinOp::Mul if !checked => { BinOp::Mul if !checked => {
let val_ty = if is_signed { fx.tcx.types.i128 } else { fx.tcx.types.u128 }; let val_ty = if is_signed { fx.tcx.types.i128 } else { fx.tcx.types.u128 };
if fx.tcx.sess.target.is_like_windows {
let ret_place = CPlace::new_stack_slot(fx, lhs.layout());
let (lhs_ptr, lhs_extra) = lhs.force_stack(fx);
let (rhs_ptr, rhs_extra) = rhs.force_stack(fx);
assert!(lhs_extra.is_none());
assert!(rhs_extra.is_none());
let args =
[ret_place.to_ptr().get_addr(fx), lhs_ptr.get_addr(fx), rhs_ptr.get_addr(fx)];
fx.lib_call(
"__multi3",
vec![
AbiParam::special(pointer_ty(fx.tcx), ArgumentPurpose::StructReturn),
AbiParam::new(pointer_ty(fx.tcx)),
AbiParam::new(pointer_ty(fx.tcx)),
],
vec![],
&args,
);
Some(ret_place.to_cvalue(fx))
} else {
Some(fx.easy_call("__multi3", &[lhs, rhs], val_ty)) Some(fx.easy_call("__multi3", &[lhs, rhs], val_ty))
} }
}
BinOp::Add | BinOp::Sub | BinOp::Mul => { BinOp::Add | BinOp::Sub | BinOp::Mul => {
assert!(checked); assert!(checked);
let out_ty = fx.tcx.mk_tup([lhs.layout().ty, fx.tcx.types.bool].iter()); let out_ty = fx.tcx.mk_tup([lhs.layout().ty, fx.tcx.types.bool].iter());
let out_place = CPlace::new_stack_slot(fx, fx.layout_of(out_ty)); let out_place = CPlace::new_stack_slot(fx, fx.layout_of(out_ty));
let param_types = vec![ let (param_types, args) = if fx.tcx.sess.target.is_like_windows {
let (lhs_ptr, lhs_extra) = lhs.force_stack(fx);
let (rhs_ptr, rhs_extra) = rhs.force_stack(fx);
assert!(lhs_extra.is_none());
assert!(rhs_extra.is_none());
(
vec![
AbiParam::special(pointer_ty(fx.tcx), ArgumentPurpose::StructReturn),
AbiParam::new(pointer_ty(fx.tcx)),
AbiParam::new(pointer_ty(fx.tcx)),
],
[out_place.to_ptr().get_addr(fx), lhs_ptr.get_addr(fx), rhs_ptr.get_addr(fx)],
)
} else {
(
vec![
AbiParam::special(pointer_ty(fx.tcx), ArgumentPurpose::StructReturn), AbiParam::special(pointer_ty(fx.tcx), ArgumentPurpose::StructReturn),
AbiParam::new(types::I128), AbiParam::new(types::I128),
AbiParam::new(types::I128), AbiParam::new(types::I128),
]; ],
let args = [out_place.to_ptr().get_addr(fx), lhs.load_scalar(fx), rhs.load_scalar(fx)]; [out_place.to_ptr().get_addr(fx), lhs.load_scalar(fx), rhs.load_scalar(fx)],
)
};
let name = match (bin_op, is_signed) { let name = match (bin_op, is_signed) {
(BinOp::Add, false) => "__rust_u128_addo", (BinOp::Add, false) => "__rust_u128_addo",
(BinOp::Add, true) => "__rust_i128_addo", (BinOp::Add, true) => "__rust_i128_addo",
@ -57,20 +95,33 @@ pub(crate) fn maybe_codegen<'tcx>(
Some(out_place.to_cvalue(fx)) Some(out_place.to_cvalue(fx))
} }
BinOp::Offset => unreachable!("offset should only be used on pointers, not 128bit ints"), BinOp::Offset => unreachable!("offset should only be used on pointers, not 128bit ints"),
BinOp::Div => { BinOp::Div | BinOp::Rem => {
assert!(!checked); assert!(!checked);
if is_signed { let name = match (bin_op, is_signed) {
Some(fx.easy_call("__divti3", &[lhs, rhs], fx.tcx.types.i128)) (BinOp::Div, false) => "__udivti3",
(BinOp::Div, true) => "__divti3",
(BinOp::Rem, false) => "__umodti3",
(BinOp::Rem, true) => "__modti3",
_ => unreachable!(),
};
if fx.tcx.sess.target.is_like_windows {
let (lhs_ptr, lhs_extra) = lhs.force_stack(fx);
let (rhs_ptr, rhs_extra) = rhs.force_stack(fx);
assert!(lhs_extra.is_none());
assert!(rhs_extra.is_none());
let args = [lhs_ptr.get_addr(fx), rhs_ptr.get_addr(fx)];
let ret = fx.lib_call(
name,
vec![AbiParam::new(pointer_ty(fx.tcx)), AbiParam::new(pointer_ty(fx.tcx))],
vec![AbiParam::new(types::I64X2)],
&args,
)[0];
// FIXME use bitcast instead of store to get from i64x2 to i128
let ret_place = CPlace::new_stack_slot(fx, lhs.layout());
ret_place.to_ptr().store(fx, ret, MemFlags::trusted());
Some(ret_place.to_cvalue(fx))
} else { } else {
Some(fx.easy_call("__udivti3", &[lhs, rhs], fx.tcx.types.u128)) Some(fx.easy_call(name, &[lhs, rhs], lhs.layout().ty))
}
}
BinOp::Rem => {
assert!(!checked);
if is_signed {
Some(fx.easy_call("__modti3", &[lhs, rhs], fx.tcx.types.i128))
} else {
Some(fx.easy_call("__umodti3", &[lhs, rhs], fx.tcx.types.u128))
} }
} }
BinOp::Lt | BinOp::Le | BinOp::Eq | BinOp::Ge | BinOp::Gt | BinOp::Ne => { BinOp::Lt | BinOp::Le | BinOp::Eq | BinOp::Ge | BinOp::Gt | BinOp::Ne => {

View file

@ -361,8 +361,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
let _ = self.cx.module.define_data(msg_id, &data_ctx); let _ = self.cx.module.define_data(msg_id, &data_ctx);
let local_msg_id = self.cx.module.declare_data_in_func(msg_id, self.bcx.func); let local_msg_id = self.cx.module.declare_data_in_func(msg_id, self.bcx.func);
#[cfg(debug_assertions)] if self.clif_comments.enabled() {
{
self.add_comment(local_msg_id, msg); self.add_comment(local_msg_id, msg);
} }
self.bcx.ins().global_value(self.pointer_type, local_msg_id) self.bcx.ins().global_value(self.pointer_type, local_msg_id)

View file

@ -0,0 +1,41 @@
macro builtin_functions($register:ident; $(fn $name:ident($($arg_name:ident: $arg_ty:ty),*) -> $ret_ty:ty;)*) {
#[cfg(feature = "jit")]
#[allow(improper_ctypes)]
extern "C" {
$(fn $name($($arg_name: $arg_ty),*) -> $ret_ty;)*
}
#[cfg(feature = "jit")]
pub(crate) fn $register(builder: &mut cranelift_jit::JITBuilder) {
for &(name, val) in &[$((stringify!($name), $name as *const u8)),*] {
builder.symbol(name, val);
}
}
}
builtin_functions! {
register_functions_for_jit;
// integers
fn __multi3(a: i128, b: i128) -> i128;
fn __udivti3(n: u128, d: u128) -> u128;
fn __divti3(n: i128, d: i128) -> i128;
fn __umodti3(n: u128, d: u128) -> u128;
fn __modti3(n: i128, d: i128) -> i128;
fn __rust_u128_addo(a: u128, b: u128) -> (u128, bool);
fn __rust_i128_addo(a: i128, b: i128) -> (i128, bool);
fn __rust_u128_subo(a: u128, b: u128) -> (u128, bool);
fn __rust_i128_subo(a: i128, b: i128) -> (i128, bool);
fn __rust_u128_mulo(a: u128, b: u128) -> (u128, bool);
fn __rust_i128_mulo(a: i128, b: i128) -> (i128, bool);
// floats
fn __floattisf(i: i128) -> f32;
fn __floattidf(i: i128) -> f64;
fn __floatuntisf(i: u128) -> f32;
fn __floatuntidf(i: u128) -> f64;
fn __fixsfti(f: f32) -> i128;
fn __fixdfti(f: f64) -> i128;
fn __fixunssfti(f: f32) -> u128;
fn __fixunsdfti(f: f64) -> u128;
}

View file

@ -85,8 +85,9 @@ pub(crate) fn codegen_tls_ref<'tcx>(
) -> CValue<'tcx> { ) -> CValue<'tcx> {
let data_id = data_id_for_static(fx.tcx, fx.cx.module, def_id, false); let data_id = data_id_for_static(fx.tcx, fx.cx.module, def_id, false);
let local_data_id = fx.cx.module.declare_data_in_func(data_id, &mut fx.bcx.func); let local_data_id = fx.cx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
#[cfg(debug_assertions)] if fx.clif_comments.enabled() {
fx.add_comment(local_data_id, format!("tls {:?}", def_id)); fx.add_comment(local_data_id, format!("tls {:?}", def_id));
}
let tls_ptr = fx.bcx.ins().tls_value(fx.pointer_type, local_data_id); let tls_ptr = fx.bcx.ins().tls_value(fx.pointer_type, local_data_id);
CValue::by_val(tls_ptr, layout) CValue::by_val(tls_ptr, layout)
} }
@ -98,8 +99,9 @@ fn codegen_static_ref<'tcx>(
) -> CPlace<'tcx> { ) -> CPlace<'tcx> {
let data_id = data_id_for_static(fx.tcx, fx.cx.module, def_id, false); let data_id = data_id_for_static(fx.tcx, fx.cx.module, def_id, false);
let local_data_id = fx.cx.module.declare_data_in_func(data_id, &mut fx.bcx.func); let local_data_id = fx.cx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
#[cfg(debug_assertions)] if fx.clif_comments.enabled() {
fx.add_comment(local_data_id, format!("{:?}", def_id)); fx.add_comment(local_data_id, format!("{:?}", def_id));
}
let global_ptr = fx.bcx.ins().global_value(fx.pointer_type, local_data_id); let global_ptr = fx.bcx.ins().global_value(fx.pointer_type, local_data_id);
assert!(!layout.is_unsized(), "unsized statics aren't supported"); assert!(!layout.is_unsized(), "unsized statics aren't supported");
assert!( assert!(
@ -122,7 +124,9 @@ pub(crate) fn codegen_constant<'tcx>(
}; };
let const_val = match const_.val { let const_val = match const_.val {
ConstKind::Value(const_val) => const_val, ConstKind::Value(const_val) => const_val,
ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) if fx.tcx.is_static(def.did) => { ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted })
if fx.tcx.is_static(def.did) =>
{
assert!(substs.is_empty()); assert!(substs.is_empty());
assert!(promoted.is_none()); assert!(promoted.is_none());
@ -183,8 +187,9 @@ pub(crate) fn codegen_const_value<'tcx>(
data_id_for_alloc_id(fx.cx.module, ptr.alloc_id, alloc.mutability); data_id_for_alloc_id(fx.cx.module, ptr.alloc_id, alloc.mutability);
let local_data_id = let local_data_id =
fx.cx.module.declare_data_in_func(data_id, &mut fx.bcx.func); fx.cx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
#[cfg(debug_assertions)] if fx.clif_comments.enabled() {
fx.add_comment(local_data_id, format!("{:?}", ptr.alloc_id)); fx.add_comment(local_data_id, format!("{:?}", ptr.alloc_id));
}
fx.bcx.ins().global_value(fx.pointer_type, local_data_id) fx.bcx.ins().global_value(fx.pointer_type, local_data_id)
} }
Some(GlobalAlloc::Function(instance)) => { Some(GlobalAlloc::Function(instance)) => {
@ -199,8 +204,9 @@ pub(crate) fn codegen_const_value<'tcx>(
let data_id = data_id_for_static(fx.tcx, fx.cx.module, def_id, false); let data_id = data_id_for_static(fx.tcx, fx.cx.module, def_id, false);
let local_data_id = let local_data_id =
fx.cx.module.declare_data_in_func(data_id, &mut fx.bcx.func); fx.cx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
#[cfg(debug_assertions)] if fx.clif_comments.enabled() {
fx.add_comment(local_data_id, format!("{:?}", def_id)); fx.add_comment(local_data_id, format!("{:?}", def_id));
}
fx.bcx.ins().global_value(fx.pointer_type, local_data_id) fx.bcx.ins().global_value(fx.pointer_type, local_data_id)
} }
None => bug!("missing allocation {:?}", ptr.alloc_id), None => bug!("missing allocation {:?}", ptr.alloc_id),
@ -241,8 +247,9 @@ fn pointer_for_allocation<'tcx>(
let data_id = data_id_for_alloc_id(fx.cx.module, alloc_id, alloc.mutability); let data_id = data_id_for_alloc_id(fx.cx.module, alloc_id, alloc.mutability);
let local_data_id = fx.cx.module.declare_data_in_func(data_id, &mut fx.bcx.func); let local_data_id = fx.cx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
#[cfg(debug_assertions)] if fx.clif_comments.enabled() {
fx.add_comment(local_data_id, format!("{:?}", alloc_id)); fx.add_comment(local_data_id, format!("{:?}", alloc_id));
}
let global_ptr = fx.bcx.ins().global_value(fx.pointer_type, local_data_id); let global_ptr = fx.bcx.ins().global_value(fx.pointer_type, local_data_id);
crate::pointer::Pointer::new(global_ptr) crate::pointer::Pointer::new(global_ptr)
} }

View file

@ -39,11 +39,11 @@ fn osstr_as_utf8_bytes(path: &OsStr) -> &[u8] {
#[cfg(unix)] #[cfg(unix)]
{ {
use std::os::unix::ffi::OsStrExt; use std::os::unix::ffi::OsStrExt;
return path.as_bytes(); path.as_bytes()
} }
#[cfg(not(unix))] #[cfg(not(unix))]
{ {
return path.to_str().unwrap().as_bytes(); path.to_str().unwrap().as_bytes()
} }
} }

View file

@ -119,11 +119,10 @@ fn module_codegen(
tcx.sess.opts.debuginfo != DebugInfo::None, tcx.sess.opts.debuginfo != DebugInfo::None,
); );
super::predefine_mono_items(&mut cx, &mono_items); super::predefine_mono_items(&mut cx, &mono_items);
for (mono_item, (linkage, visibility)) in mono_items { for (mono_item, _) in mono_items {
let linkage = crate::linkage::get_clif_linkage(mono_item, linkage, visibility);
match mono_item { match mono_item {
MonoItem::Fn(inst) => { MonoItem::Fn(inst) => {
cx.tcx.sess.time("codegen fn", || crate::base::codegen_fn(&mut cx, inst, linkage)); cx.tcx.sess.time("codegen fn", || crate::base::codegen_fn(&mut cx, inst));
} }
MonoItem::Static(def_id) => { MonoItem::Static(def_id) => {
crate::constant::codegen_static(&mut cx.constants_cx, def_id) crate::constant::codegen_static(&mut cx.constants_cx, def_id)
@ -163,6 +162,21 @@ pub(super) fn run_aot(
metadata: EncodedMetadata, metadata: EncodedMetadata,
need_metadata_module: bool, need_metadata_module: bool,
) -> Box<(CodegenResults, FxHashMap<WorkProductId, WorkProduct>)> { ) -> Box<(CodegenResults, FxHashMap<WorkProductId, WorkProduct>)> {
use rustc_span::symbol::sym;
let crate_attrs = tcx.hir().attrs(rustc_hir::CRATE_HIR_ID);
let subsystem = tcx.sess.first_attr_value_str_by_name(crate_attrs, sym::windows_subsystem);
let windows_subsystem = subsystem.map(|subsystem| {
if subsystem != sym::windows && subsystem != sym::console {
tcx.sess.fatal(&format!(
"invalid windows subsystem `{}`, only \
`windows` and `console` are allowed",
subsystem
));
}
subsystem.to_string()
});
let mut work_products = FxHashMap::default(); let mut work_products = FxHashMap::default();
let cgus = if tcx.sess.opts.output_types.should_codegen() { let cgus = if tcx.sess.opts.output_types.should_codegen() {
@ -280,7 +294,7 @@ pub(super) fn run_aot(
allocator_module, allocator_module,
metadata_module, metadata_module,
metadata, metadata,
windows_subsystem: None, // Windows is not yet supported windows_subsystem,
linker_info: LinkerInfo::new(tcx), linker_info: LinkerInfo::new(tcx),
crate_info: CrateInfo::new(tcx), crate_info: CrateInfo::new(tcx),
}, },

View file

@ -5,8 +5,10 @@ use std::cell::RefCell;
use std::ffi::CString; use std::ffi::CString;
use std::os::raw::{c_char, c_int}; use std::os::raw::{c_char, c_int};
use cranelift_codegen::binemit::{NullStackMapSink, NullTrapSink};
use rustc_codegen_ssa::CrateInfo; use rustc_codegen_ssa::CrateInfo;
use rustc_middle::mir::mono::MonoItem; use rustc_middle::mir::mono::MonoItem;
use rustc_session::config::EntryFnType;
use cranelift_jit::{JITBuilder, JITModule}; use cranelift_jit::{JITBuilder, JITModule};
@ -28,20 +30,11 @@ pub(super) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! {
let mut jit_builder = let mut jit_builder =
JITBuilder::with_isa(crate::build_isa(tcx.sess), cranelift_module::default_libcall_names()); JITBuilder::with_isa(crate::build_isa(tcx.sess), cranelift_module::default_libcall_names());
jit_builder.hotswap(matches!(backend_config.codegen_mode, CodegenMode::JitLazy)); jit_builder.hotswap(matches!(backend_config.codegen_mode, CodegenMode::JitLazy));
crate::compiler_builtins::register_functions_for_jit(&mut jit_builder);
jit_builder.symbols(imported_symbols); jit_builder.symbols(imported_symbols);
let mut jit_module = JITModule::new(jit_builder); let mut jit_module = JITModule::new(jit_builder);
assert_eq!(pointer_ty(tcx), jit_module.target_config().pointer_type()); assert_eq!(pointer_ty(tcx), jit_module.target_config().pointer_type());
let sig = Signature {
params: vec![
AbiParam::new(jit_module.target_config().pointer_type()),
AbiParam::new(jit_module.target_config().pointer_type()),
],
returns: vec![AbiParam::new(jit_module.target_config().pointer_type() /*isize*/)],
call_conv: CallConv::triple_default(&crate::target_triple(tcx.sess)),
};
let main_func_id = jit_module.declare_function("main", Linkage::Import, &sig).unwrap();
let (_, cgus) = tcx.collect_and_partition_mono_items(LOCAL_CRATE); let (_, cgus) = tcx.collect_and_partition_mono_items(LOCAL_CRATE);
let mono_items = cgus let mono_items = cgus
.iter() .iter()
@ -55,15 +48,12 @@ pub(super) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! {
super::time(tcx, "codegen mono items", || { super::time(tcx, "codegen mono items", || {
super::predefine_mono_items(&mut cx, &mono_items); super::predefine_mono_items(&mut cx, &mono_items);
for (mono_item, (linkage, visibility)) in mono_items { for (mono_item, _) in mono_items {
let linkage = crate::linkage::get_clif_linkage(mono_item, linkage, visibility);
match mono_item { match mono_item {
MonoItem::Fn(inst) => match backend_config.codegen_mode { MonoItem::Fn(inst) => match backend_config.codegen_mode {
CodegenMode::Aot => unreachable!(), CodegenMode::Aot => unreachable!(),
CodegenMode::Jit => { CodegenMode::Jit => {
cx.tcx cx.tcx.sess.time("codegen fn", || crate::base::codegen_fn(&mut cx, inst));
.sess
.time("codegen fn", || crate::base::codegen_fn(&mut cx, inst, linkage));
} }
CodegenMode::JitLazy => codegen_shim(&mut cx, inst), CodegenMode::JitLazy => codegen_shim(&mut cx, inst),
}, },
@ -86,24 +76,17 @@ pub(super) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! {
tcx.sess.fatal("Inline asm is not supported in JIT mode"); tcx.sess.fatal("Inline asm is not supported in JIT mode");
} }
crate::main_shim::maybe_create_entry_wrapper(tcx, &mut jit_module, &mut unwind_context);
crate::allocator::codegen(tcx, &mut jit_module, &mut unwind_context); crate::allocator::codegen(tcx, &mut jit_module, &mut unwind_context);
tcx.sess.abort_if_errors(); tcx.sess.abort_if_errors();
jit_module.finalize_definitions(); jit_module.finalize_definitions();
let _unwind_register_guard = unsafe { unwind_context.register_jit(&jit_module) }; let _unwind_register_guard = unsafe { unwind_context.register_jit(&jit_module) };
let finalized_main: *const u8 = jit_module.get_finalized_function(main_func_id);
println!( println!(
"Rustc codegen cranelift will JIT run the executable, because -Cllvm-args=mode=jit was passed" "Rustc codegen cranelift will JIT run the executable, because -Cllvm-args=mode=jit was passed"
); );
let f: extern "C" fn(c_int, *const *const c_char) -> c_int =
unsafe { ::std::mem::transmute(finalized_main) };
let args = ::std::env::var("CG_CLIF_JIT_ARGS").unwrap_or_else(|_| String::new()); let args = ::std::env::var("CG_CLIF_JIT_ARGS").unwrap_or_else(|_| String::new());
let args = std::iter::once(&*tcx.crate_name(LOCAL_CRATE).as_str().to_string()) let args = std::iter::once(&*tcx.crate_name(LOCAL_CRATE).as_str().to_string())
.chain(args.split(' ')) .chain(args.split(' '))
@ -118,12 +101,58 @@ pub(super) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! {
BACKEND_CONFIG.with(|tls_backend_config| { BACKEND_CONFIG.with(|tls_backend_config| {
assert!(tls_backend_config.borrow_mut().replace(backend_config).is_none()) assert!(tls_backend_config.borrow_mut().replace(backend_config).is_none())
}); });
CURRENT_MODULE
.with(|current_module| assert!(current_module.borrow_mut().replace(jit_module).is_none()));
let (main_def_id, entry_ty) = tcx.entry_fn(LOCAL_CRATE).unwrap();
let instance = Instance::mono(tcx, main_def_id.to_def_id()).polymorphize(tcx);
match entry_ty {
EntryFnType::Main => {
// FIXME set program arguments somehow
let main_sig = Signature {
params: vec![],
returns: vec![],
call_conv: CallConv::triple_default(&crate::target_triple(tcx.sess)),
};
let main_func_id = jit_module
.declare_function(tcx.symbol_name(instance).name, Linkage::Import, &main_sig)
.unwrap();
let finalized_main: *const u8 = jit_module.get_finalized_function(main_func_id);
CURRENT_MODULE.with(|current_module| {
assert!(current_module.borrow_mut().replace(jit_module).is_none())
});
let f: extern "C" fn() = unsafe { ::std::mem::transmute(finalized_main) };
f();
std::process::exit(0);
}
EntryFnType::Start => {
let start_sig = Signature {
params: vec![
AbiParam::new(jit_module.target_config().pointer_type()),
AbiParam::new(jit_module.target_config().pointer_type()),
],
returns: vec![AbiParam::new(
jit_module.target_config().pointer_type(), /*isize*/
)],
call_conv: CallConv::triple_default(&crate::target_triple(tcx.sess)),
};
let start_func_id = jit_module
.declare_function(tcx.symbol_name(instance).name, Linkage::Import, &start_sig)
.unwrap();
let finalized_start: *const u8 = jit_module.get_finalized_function(start_func_id);
CURRENT_MODULE.with(|current_module| {
assert!(current_module.borrow_mut().replace(jit_module).is_none())
});
let f: extern "C" fn(c_int, *const *const c_char) -> c_int =
unsafe { ::std::mem::transmute(finalized_start) };
let ret = f(args.len() as c_int, argv.as_ptr()); let ret = f(args.len() as c_int, argv.as_ptr());
std::process::exit(ret); std::process::exit(ret);
}
}
} }
#[no_mangle] #[no_mangle]
@ -144,8 +173,7 @@ extern "C" fn __clif_jit_fn(instance_ptr: *const Instance<'static>) -> *const u8
jit_module.prepare_for_function_redefine(func_id).unwrap(); jit_module.prepare_for_function_redefine(func_id).unwrap();
let mut cx = crate::CodegenCx::new(tcx, backend_config, jit_module, false); let mut cx = crate::CodegenCx::new(tcx, backend_config, jit_module, false);
tcx.sess tcx.sess.time("codegen fn", || crate::base::codegen_fn(&mut cx, instance));
.time("codegen fn", || crate::base::codegen_fn(&mut cx, instance, Linkage::Export));
let (global_asm, _debug_context, unwind_context) = cx.finalize(); let (global_asm, _debug_context, unwind_context) = cx.finalize();
assert!(global_asm.is_empty()); assert!(global_asm.is_empty());
@ -220,7 +248,7 @@ fn load_imported_symbols_for_jit(tcx: TyCtxt<'_>) -> Vec<(String, *const u8)> {
imported_symbols imported_symbols
} }
pub(super) fn codegen_shim<'tcx>(cx: &mut CodegenCx<'_, 'tcx>, inst: Instance<'tcx>) { fn codegen_shim<'tcx>(cx: &mut CodegenCx<'_, 'tcx>, inst: Instance<'tcx>) {
let tcx = cx.tcx; let tcx = cx.tcx;
let pointer_type = cx.module.target_config().pointer_type(); let pointer_type = cx.module.target_config().pointer_type();
@ -267,7 +295,8 @@ pub(super) fn codegen_shim<'tcx>(cx: &mut CodegenCx<'_, 'tcx>, inst: Instance<'t
.define_function( .define_function(
func_id, func_id,
&mut Context::for_function(trampoline), &mut Context::for_function(trampoline),
&mut cranelift_codegen::binemit::NullTrapSink {}, &mut NullTrapSink {},
&mut NullStackMapSink {},
) )
.unwrap(); .unwrap();
} }

View file

@ -44,13 +44,19 @@ fn predefine_mono_items<'tcx>(
mono_items: &[(MonoItem<'tcx>, (RLinkage, Visibility))], mono_items: &[(MonoItem<'tcx>, (RLinkage, Visibility))],
) { ) {
cx.tcx.sess.time("predefine functions", || { cx.tcx.sess.time("predefine functions", || {
let is_compiler_builtins = cx.tcx.is_compiler_builtins(LOCAL_CRATE);
for &(mono_item, (linkage, visibility)) in mono_items { for &(mono_item, (linkage, visibility)) in mono_items {
match mono_item { match mono_item {
MonoItem::Fn(instance) => { MonoItem::Fn(instance) => {
let name = cx.tcx.symbol_name(instance).name.to_string(); let name = cx.tcx.symbol_name(instance).name.to_string();
let _inst_guard = crate::PrintOnPanic(|| format!("{:?} {}", instance, name)); let _inst_guard = crate::PrintOnPanic(|| format!("{:?} {}", instance, name));
let sig = get_function_sig(cx.tcx, cx.module.isa().triple(), instance); let sig = get_function_sig(cx.tcx, cx.module.isa().triple(), instance);
let linkage = crate::linkage::get_clif_linkage(mono_item, linkage, visibility); let linkage = crate::linkage::get_clif_linkage(
mono_item,
linkage,
visibility,
is_compiler_builtins,
);
cx.module.declare_function(&name, linkage, &sig).unwrap(); cx.module.declare_function(&name, linkage, &sig).unwrap();
} }
MonoItem::Static(_) | MonoItem::GlobalAsm(_) => {} MonoItem::Static(_) | MonoItem::GlobalAsm(_) => {}

View file

@ -20,6 +20,10 @@ pub(crate) fn codegen_inline_asm<'tcx>(
if template.is_empty() { if template.is_empty() {
// Black box // Black box
return; return;
} else if template[0] == InlineAsmTemplatePiece::String("int $$0x29".to_string()) {
let true_ = fx.bcx.ins().iconst(types::I32, 1);
fx.bcx.ins().trapnz(true_, TrapCode::User(1));
return;
} }
let mut slot_size = Size::from_bytes(0); let mut slot_size = Size::from_bytes(0);
@ -193,8 +197,9 @@ fn call_inline_asm<'tcx>(
offset: None, offset: None,
size: u32::try_from(slot_size.bytes()).unwrap(), size: u32::try_from(slot_size.bytes()).unwrap(),
}); });
#[cfg(debug_assertions)] if fx.clif_comments.enabled() {
fx.add_comment(stack_slot, "inline asm scratch slot"); fx.add_comment(stack_slot, "inline asm scratch slot");
}
let inline_asm_func = fx let inline_asm_func = fx
.cx .cx
@ -210,8 +215,9 @@ fn call_inline_asm<'tcx>(
) )
.unwrap(); .unwrap();
let inline_asm_func = fx.cx.module.declare_func_in_func(inline_asm_func, &mut fx.bcx.func); let inline_asm_func = fx.cx.module.declare_func_in_func(inline_asm_func, &mut fx.bcx.func);
#[cfg(debug_assertions)] if fx.clif_comments.enabled() {
fx.add_comment(inline_asm_func, asm_name); fx.add_comment(inline_asm_func, asm_name);
}
for (_reg, offset, value) in inputs { for (_reg, offset, value) in inputs {
fx.bcx.ins().stack_store(value, stack_slot, i32::try_from(offset.bytes()).unwrap()); fx.bcx.ins().stack_store(value, stack_slot, i32::try_from(offset.bytes()).unwrap());

View file

@ -88,7 +88,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
let idx_bytes = match idx_const { let idx_bytes = match idx_const {
ConstValue::ByRef { alloc, offset } => { ConstValue::ByRef { alloc, offset } => {
let ptr = Pointer::new(AllocId(0 /* dummy */), offset); let ptr = Pointer::new(AllocId(0 /* dummy */), offset);
let size = Size::from_bytes(4 * u64::from(ret_lane_count) /* size_of([u32; ret_lane_count]) */); let size = Size::from_bytes(4 * ret_lane_count /* size_of([u32; ret_lane_count]) */);
alloc.get_bytes(fx, ptr, size).unwrap() alloc.get_bytes(fx, ptr, size).unwrap()
} }
_ => unreachable!("{:?}", idx_const), _ => unreachable!("{:?}", idx_const),

View file

@ -1,13 +1,4 @@
#![feature( #![feature(rustc_private, decl_macro, never_type, hash_drain_filter)]
rustc_private,
decl_macro,
type_alias_impl_trait,
associated_type_bounds,
never_type,
try_blocks,
box_patterns,
hash_drain_filter
)]
#![warn(rust_2018_idioms)] #![warn(rust_2018_idioms)]
#![warn(unused_lifetimes)] #![warn(unused_lifetimes)]
#![warn(unreachable_pub)] #![warn(unreachable_pub)]
@ -57,6 +48,7 @@ mod base;
mod cast; mod cast;
mod codegen_i128; mod codegen_i128;
mod common; mod common;
mod compiler_builtins;
mod constant; mod constant;
mod debuginfo; mod debuginfo;
mod discriminant; mod discriminant;
@ -224,8 +216,10 @@ pub struct CraneliftCodegenBackend {
impl CodegenBackend for CraneliftCodegenBackend { impl CodegenBackend for CraneliftCodegenBackend {
fn init(&self, sess: &Session) { fn init(&self, sess: &Session) {
if sess.lto() != rustc_session::config::Lto::No && sess.opts.cg.embed_bitcode { use rustc_session::config::Lto;
sess.warn("LTO is not supported. You may get a linker error."); match sess.lto() {
Lto::No | Lto::ThinLocal => {}
Lto::Thin | Lto::Fat => sess.warn("LTO is not supported. You may get a linker error."),
} }
} }
@ -240,9 +234,9 @@ impl CodegenBackend for CraneliftCodegenBackend {
vec![] vec![]
} }
fn codegen_crate<'tcx>( fn codegen_crate(
&self, &self,
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'_>,
metadata: EncodedMetadata, metadata: EncodedMetadata,
need_metadata_module: bool, need_metadata_module: bool,
) -> Box<dyn Any> { ) -> Box<dyn Any> {
@ -252,9 +246,7 @@ impl CodegenBackend for CraneliftCodegenBackend {
BackendConfig::from_opts(&tcx.sess.opts.cg.llvm_args) BackendConfig::from_opts(&tcx.sess.opts.cg.llvm_args)
.unwrap_or_else(|err| tcx.sess.fatal(&err)) .unwrap_or_else(|err| tcx.sess.fatal(&err))
}; };
let res = driver::codegen_crate(tcx, metadata, need_metadata_module, config); driver::codegen_crate(tcx, metadata, need_metadata_module, config)
res
} }
fn join_codegen( fn join_codegen(
@ -300,9 +292,9 @@ fn build_isa(sess: &Session) -> Box<dyn isa::TargetIsa + 'static> {
let mut flags_builder = settings::builder(); let mut flags_builder = settings::builder();
flags_builder.enable("is_pic").unwrap(); flags_builder.enable("is_pic").unwrap();
flags_builder.set("enable_probestack", "false").unwrap(); // __cranelift_probestack is not provided flags_builder.set("enable_probestack", "false").unwrap(); // __cranelift_probestack is not provided
flags_builder let enable_verifier =
.set("enable_verifier", if cfg!(debug_assertions) { "true" } else { "false" }) cfg!(debug_assertions) || std::env::var("CG_CLIF_ENABLE_VERIFIER").is_ok();
.unwrap(); flags_builder.set("enable_verifier", if enable_verifier { "true" } else { "false" }).unwrap();
let tls_model = match target_triple.binary_format { let tls_model = match target_triple.binary_format {
BinaryFormat::Elf => "elf_gd", BinaryFormat::Elf => "elf_gd",
@ -314,18 +306,17 @@ fn build_isa(sess: &Session) -> Box<dyn isa::TargetIsa + 'static> {
flags_builder.set("enable_simd", "true").unwrap(); flags_builder.set("enable_simd", "true").unwrap();
flags_builder.set("enable_llvm_abi_extensions", "true").unwrap();
use rustc_session::config::OptLevel; use rustc_session::config::OptLevel;
match sess.opts.optimize { match sess.opts.optimize {
OptLevel::No => { OptLevel::No => {
flags_builder.set("opt_level", "none").unwrap(); flags_builder.set("opt_level", "none").unwrap();
} }
OptLevel::Less | OptLevel::Default => {} OptLevel::Less | OptLevel::Default => {}
OptLevel::Aggressive => { OptLevel::Size | OptLevel::SizeMin | OptLevel::Aggressive => {
flags_builder.set("opt_level", "speed_and_size").unwrap(); flags_builder.set("opt_level", "speed_and_size").unwrap();
} }
OptLevel::Size | OptLevel::SizeMin => {
sess.warn("Optimizing for size is not supported. Just ignoring the request");
}
} }
let flags = settings::Flags::new(flags_builder); let flags = settings::Flags::new(flags_builder);

View file

@ -6,8 +6,10 @@ pub(crate) fn get_clif_linkage(
mono_item: MonoItem<'_>, mono_item: MonoItem<'_>,
linkage: RLinkage, linkage: RLinkage,
visibility: Visibility, visibility: Visibility,
is_compiler_builtins: bool,
) -> Linkage { ) -> Linkage {
match (linkage, visibility) { match (linkage, visibility) {
(RLinkage::External, Visibility::Default) if is_compiler_builtins => Linkage::Hidden,
(RLinkage::External, Visibility::Default) => Linkage::Export, (RLinkage::External, Visibility::Default) => Linkage::Export,
(RLinkage::Internal, Visibility::Default) => Linkage::Local, (RLinkage::Internal, Visibility::Default) => Linkage::Local,
(RLinkage::External, Visibility::Hidden) => Linkage::Hidden, (RLinkage::External, Visibility::Hidden) => Linkage::Hidden,

View file

@ -1,3 +1,4 @@
use cranelift_codegen::binemit::{NullStackMapSink, NullTrapSink};
use rustc_hir::LangItem; use rustc_hir::LangItem;
use rustc_session::config::EntryFnType; use rustc_session::config::EntryFnType;
@ -100,11 +101,7 @@ pub(crate) fn maybe_create_entry_wrapper(
bcx.seal_all_blocks(); bcx.seal_all_blocks();
bcx.finalize(); bcx.finalize();
} }
m.define_function( m.define_function(cmain_func_id, &mut ctx, &mut NullTrapSink {}, &mut NullStackMapSink {})
cmain_func_id,
&mut ctx,
&mut cranelift_codegen::binemit::NullTrapSink {},
)
.unwrap(); .unwrap();
unwind_context.add_function(cmain_func_id, &ctx, m.isa()); unwind_context.add_function(cmain_func_id, &ctx, m.isa());
} }

View file

@ -1,11 +1,11 @@
//! Reading and writing of the rustc metadata for rlibs and dylibs //! Reading and writing of the rustc metadata for rlibs and dylibs
use std::convert::TryFrom;
use std::fs::File; use std::fs::File;
use std::ops::Deref;
use std::path::Path; use std::path::Path;
use rustc_codegen_ssa::METADATA_FILENAME; use rustc_codegen_ssa::METADATA_FILENAME;
use rustc_data_structures::owning_ref::OwningRef; use rustc_data_structures::owning_ref::{OwningRef, StableAddress};
use rustc_data_structures::rustc_erase_owner; use rustc_data_structures::rustc_erase_owner;
use rustc_data_structures::sync::MetadataRef; use rustc_data_structures::sync::MetadataRef;
use rustc_middle::middle::cstore::{EncodedMetadata, MetadataLoader}; use rustc_middle::middle::cstore::{EncodedMetadata, MetadataLoader};
@ -17,38 +17,56 @@ use crate::backend::WriteMetadata;
pub(crate) struct CraneliftMetadataLoader; pub(crate) struct CraneliftMetadataLoader;
struct StableMmap(memmap2::Mmap);
impl Deref for StableMmap {
type Target = [u8];
fn deref(&self) -> &[u8] {
&*self.0
}
}
unsafe impl StableAddress for StableMmap {}
fn load_metadata_with(
path: &Path,
f: impl for<'a> FnOnce(&'a [u8]) -> Result<&'a [u8], String>,
) -> Result<MetadataRef, String> {
let file = File::open(path).map_err(|e| format!("{:?}", e))?;
let data = unsafe { memmap2::MmapOptions::new().map_copy_read_only(&file) }
.map_err(|e| format!("{:?}", e))?;
let metadata = OwningRef::new(StableMmap(data)).try_map(f)?;
return Ok(rustc_erase_owner!(metadata.map_owner_box()));
}
impl MetadataLoader for CraneliftMetadataLoader { impl MetadataLoader for CraneliftMetadataLoader {
fn get_rlib_metadata(&self, _target: &Target, path: &Path) -> Result<MetadataRef, String> { fn get_rlib_metadata(&self, _target: &Target, path: &Path) -> Result<MetadataRef, String> {
let mut archive = ar::Archive::new(File::open(path).map_err(|e| format!("{:?}", e))?); load_metadata_with(path, |data| {
// Iterate over all entries in the archive: let archive = object::read::archive::ArchiveFile::parse(&*data)
while let Some(entry_result) = archive.next_entry() { .map_err(|e| format!("{:?}", e))?;
let mut entry = entry_result.map_err(|e| format!("{:?}", e))?;
if entry.header().identifier() == METADATA_FILENAME.as_bytes() { for entry_result in archive.members() {
let mut buf = Vec::with_capacity( let entry = entry_result.map_err(|e| format!("{:?}", e))?;
usize::try_from(entry.header().size()) if entry.name() == METADATA_FILENAME.as_bytes() {
.expect("Rlib metadata file too big to load into memory."), return Ok(entry.data());
);
::std::io::copy(&mut entry, &mut buf).map_err(|e| format!("{:?}", e))?;
let buf: OwningRef<Vec<u8>, [u8]> = OwningRef::new(buf);
return Ok(rustc_erase_owner!(buf.map_owner_box()));
} }
} }
Err("couldn't find metadata entry".to_string()) Err("couldn't find metadata entry".to_string())
})
} }
fn get_dylib_metadata(&self, _target: &Target, path: &Path) -> Result<MetadataRef, String> { fn get_dylib_metadata(&self, _target: &Target, path: &Path) -> Result<MetadataRef, String> {
use object::{Object, ObjectSection}; use object::{Object, ObjectSection};
let file = std::fs::read(path).map_err(|e| format!("read:{:?}", e))?;
let file = object::File::parse(&file).map_err(|e| format!("parse: {:?}", e))?; load_metadata_with(path, |data| {
let buf = file let file = object::File::parse(&data).map_err(|e| format!("parse: {:?}", e))?;
.section_by_name(".rustc") file.section_by_name(".rustc")
.ok_or("no .rustc section")? .ok_or("no .rustc section")?
.data() .data()
.map_err(|e| format!("failed to read .rustc section: {:?}", e))? .map_err(|e| format!("failed to read .rustc section: {:?}", e))
.to_owned(); })
let buf: OwningRef<Vec<u8>, [u8]> = OwningRef::new(buf);
Ok(rustc_erase_owner!(buf.map_owner_box()))
} }
} }

View file

@ -166,13 +166,11 @@ pub(crate) fn codegen_int_binop<'tcx>(
BinOp::Shl => { BinOp::Shl => {
let lhs_ty = fx.bcx.func.dfg.value_type(lhs); let lhs_ty = fx.bcx.func.dfg.value_type(lhs);
let actual_shift = fx.bcx.ins().band_imm(rhs, i64::from(lhs_ty.bits() - 1)); let actual_shift = fx.bcx.ins().band_imm(rhs, i64::from(lhs_ty.bits() - 1));
let actual_shift = clif_intcast(fx, actual_shift, types::I8, false);
fx.bcx.ins().ishl(lhs, actual_shift) fx.bcx.ins().ishl(lhs, actual_shift)
} }
BinOp::Shr => { BinOp::Shr => {
let lhs_ty = fx.bcx.func.dfg.value_type(lhs); let lhs_ty = fx.bcx.func.dfg.value_type(lhs);
let actual_shift = fx.bcx.ins().band_imm(rhs, i64::from(lhs_ty.bits() - 1)); let actual_shift = fx.bcx.ins().band_imm(rhs, i64::from(lhs_ty.bits() - 1));
let actual_shift = clif_intcast(fx, actual_shift, types::I8, false);
if signed { if signed {
fx.bcx.ins().sshr(lhs, actual_shift) fx.bcx.ins().sshr(lhs, actual_shift)
} else { } else {
@ -387,7 +385,7 @@ pub(crate) fn codegen_ptr_binop<'tcx>(
let lhs = in_lhs.load_scalar(fx); let lhs = in_lhs.load_scalar(fx);
let rhs = in_rhs.load_scalar(fx); let rhs = in_rhs.load_scalar(fx);
return codegen_compare_bin_op(fx, bin_op, false, lhs, rhs); codegen_compare_bin_op(fx, bin_op, false, lhs, rhs)
} }
BinOp::Offset => { BinOp::Offset => {
let pointee_ty = in_lhs.layout().ty.builtin_deref(true).unwrap().ty; let pointee_ty = in_lhs.layout().ty.builtin_deref(true).unwrap().ty;
@ -396,10 +394,10 @@ pub(crate) fn codegen_ptr_binop<'tcx>(
let ptr_diff = fx.bcx.ins().imul_imm(offset, pointee_size as i64); let ptr_diff = fx.bcx.ins().imul_imm(offset, pointee_size as i64);
let base_val = base.load_scalar(fx); let base_val = base.load_scalar(fx);
let res = fx.bcx.ins().iadd(base_val, ptr_diff); let res = fx.bcx.ins().iadd(base_val, ptr_diff);
return CValue::by_val(res, base.layout()); CValue::by_val(res, base.layout())
} }
_ => unreachable!("{:?}({:?}, {:?})", bin_op, in_lhs, in_rhs), _ => unreachable!("{:?}({:?}, {:?})", bin_op, in_lhs, in_rhs),
}; }
} else { } else {
let (lhs_ptr, lhs_extra) = in_lhs.load_scalar_pair(fx); let (lhs_ptr, lhs_extra) = in_lhs.load_scalar_pair(fx);
let (rhs_ptr, rhs_extra) = in_rhs.load_scalar_pair(fx); let (rhs_ptr, rhs_extra) = in_rhs.load_scalar_pair(fx);

View file

@ -181,7 +181,6 @@ impl<'a> OptimizeContext<'a> {
pub(super) fn optimize_function( pub(super) fn optimize_function(
ctx: &mut Context, ctx: &mut Context,
#[cfg_attr(not(debug_assertions), allow(unused_variables))]
clif_comments: &mut crate::pretty_clif::CommentWriter, clif_comments: &mut crate::pretty_clif::CommentWriter,
) { ) {
combine_stack_addr_with_load_store(&mut ctx.func); combine_stack_addr_with_load_store(&mut ctx.func);
@ -192,8 +191,7 @@ pub(super) fn optimize_function(
remove_unused_stack_addr_and_stack_load(&mut opt_ctx); remove_unused_stack_addr_and_stack_load(&mut opt_ctx);
#[cfg(debug_assertions)] if clif_comments.enabled() {
{
for (&OrdStackSlot(stack_slot), usage) in &opt_ctx.stack_slot_usage_map { for (&OrdStackSlot(stack_slot), usage) in &opt_ctx.stack_slot_usage_map {
clif_comments.add_comment(stack_slot, format!("used by: {:?}", usage)); clif_comments.add_comment(stack_slot, format!("used by: {:?}", usage));
} }
@ -209,7 +207,7 @@ pub(super) fn optimize_function(
for load in users.stack_load.clone().into_iter() { for load in users.stack_load.clone().into_iter() {
let potential_stores = users.potential_stores_for_load(&opt_ctx.ctx, load); let potential_stores = users.potential_stores_for_load(&opt_ctx.ctx, load);
#[cfg(debug_assertions)] if clif_comments.enabled() {
for &store in &potential_stores { for &store in &potential_stores {
clif_comments.add_comment( clif_comments.add_comment(
load, load,
@ -222,13 +220,15 @@ pub(super) fn optimize_function(
), ),
); );
} }
}
match *potential_stores { match *potential_stores {
[] => { [] => {
#[cfg(debug_assertions)] if clif_comments.enabled() {
clif_comments clif_comments
.add_comment(load, "[BUG?] Reading uninitialized memory".to_string()); .add_comment(load, "[BUG?] Reading uninitialized memory".to_string());
} }
}
[store] [store]
if spatial_overlap(&opt_ctx.ctx.func, store, load) == SpatialOverlap::Full if spatial_overlap(&opt_ctx.ctx.func, store, load) == SpatialOverlap::Full
&& temporal_order(&opt_ctx.ctx, store, load) && temporal_order(&opt_ctx.ctx, store, load)
@ -237,9 +237,12 @@ pub(super) fn optimize_function(
// Only one store could have been the origin of the value. // Only one store could have been the origin of the value.
let stored_value = opt_ctx.ctx.func.dfg.inst_args(store)[0]; let stored_value = opt_ctx.ctx.func.dfg.inst_args(store)[0];
#[cfg(debug_assertions)] if clif_comments.enabled() {
clif_comments clif_comments.add_comment(
.add_comment(load, format!("Store to load forward {} -> {}", store, load)); load,
format!("Store to load forward {} -> {}", store, load),
);
}
users.change_load_to_alias(&mut opt_ctx.ctx.func, load, stored_value); users.change_load_to_alias(&mut opt_ctx.ctx.func, load, stored_value);
} }
@ -250,7 +253,7 @@ pub(super) fn optimize_function(
for store in users.stack_store.clone().into_iter() { for store in users.stack_store.clone().into_iter() {
let potential_loads = users.potential_loads_of_store(&opt_ctx.ctx, store); let potential_loads = users.potential_loads_of_store(&opt_ctx.ctx, store);
#[cfg(debug_assertions)] if clif_comments.enabled() {
for &load in &potential_loads { for &load in &potential_loads {
clif_comments.add_comment( clif_comments.add_comment(
store, store,
@ -263,12 +266,13 @@ pub(super) fn optimize_function(
), ),
); );
} }
}
if potential_loads.is_empty() { if potential_loads.is_empty() {
// Never loaded; can safely remove all stores and the stack slot. // Never loaded; can safely remove all stores and the stack slot.
// FIXME also remove stores when there is always a next store before a load. // FIXME also remove stores when there is always a next store before a load.
#[cfg(debug_assertions)] if clif_comments.enabled() {
clif_comments.add_comment( clif_comments.add_comment(
store, store,
format!( format!(
@ -277,6 +281,7 @@ pub(super) fn optimize_function(
stack_slot.0 stack_slot.0
), ),
); );
}
users.remove_dead_store(&mut opt_ctx.ctx.func, store); users.remove_dead_store(&mut opt_ctx.ctx.func, store);
} }

View file

@ -39,8 +39,7 @@ impl Pointer {
Pointer { base: PointerBase::Dangling(align), offset: Offset32::new(0) } Pointer { base: PointerBase::Dangling(align), offset: Offset32::new(0) }
} }
#[cfg(debug_assertions)] pub(crate) fn debug_base_and_offset(self) -> (PointerBase, Offset32) {
pub(crate) fn base_and_offset(self) -> (PointerBase, Offset32) {
(self.base, self.offset) (self.base, self.offset)
} }

View file

@ -69,13 +69,15 @@ use crate::prelude::*;
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct CommentWriter { pub(crate) struct CommentWriter {
enabled: bool,
global_comments: Vec<String>, global_comments: Vec<String>,
entity_comments: FxHashMap<AnyEntity, String>, entity_comments: FxHashMap<AnyEntity, String>,
} }
impl CommentWriter { impl CommentWriter {
pub(crate) fn new<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Self { pub(crate) fn new<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Self {
let global_comments = if cfg!(debug_assertions) { let enabled = should_write_ir(tcx);
let global_comments = if enabled {
vec![ vec![
format!("symbol {}", tcx.symbol_name(instance).name), format!("symbol {}", tcx.symbol_name(instance).name),
format!("instance {:?}", instance), format!("instance {:?}", instance),
@ -86,13 +88,17 @@ impl CommentWriter {
vec![] vec![]
}; };
CommentWriter { global_comments, entity_comments: FxHashMap::default() } CommentWriter { enabled, global_comments, entity_comments: FxHashMap::default() }
} }
} }
#[cfg(debug_assertions)]
impl CommentWriter { impl CommentWriter {
pub(crate) fn enabled(&self) -> bool {
self.enabled
}
pub(crate) fn add_global_comment<S: Into<String>>(&mut self, comment: S) { pub(crate) fn add_global_comment<S: Into<String>>(&mut self, comment: S) {
debug_assert!(self.enabled);
self.global_comments.push(comment.into()); self.global_comments.push(comment.into());
} }
@ -101,6 +107,8 @@ impl CommentWriter {
entity: E, entity: E,
comment: S, comment: S,
) { ) {
debug_assert!(self.enabled);
use std::collections::hash_map::Entry; use std::collections::hash_map::Entry;
match self.entity_comments.entry(entity.into()) { match self.entity_comments.entry(entity.into()) {
Entry::Occupied(mut occ) => { Entry::Occupied(mut occ) => {
@ -179,7 +187,6 @@ impl FuncWriter for &'_ CommentWriter {
} }
} }
#[cfg(debug_assertions)]
impl FunctionCx<'_, '_, '_> { impl FunctionCx<'_, '_, '_> {
pub(crate) fn add_global_comment<S: Into<String>>(&mut self, comment: S) { pub(crate) fn add_global_comment<S: Into<String>>(&mut self, comment: S) {
self.clif_comments.add_global_comment(comment); self.clif_comments.add_global_comment(comment);
@ -198,8 +205,8 @@ pub(crate) fn should_write_ir(tcx: TyCtxt<'_>) -> bool {
tcx.sess.opts.output_types.contains_key(&OutputType::LlvmAssembly) tcx.sess.opts.output_types.contains_key(&OutputType::LlvmAssembly)
} }
pub(crate) fn write_ir_file<'tcx>( pub(crate) fn write_ir_file(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'_>,
name: &str, name: &str,
write: impl FnOnce(&mut dyn Write) -> std::io::Result<()>, write: impl FnOnce(&mut dyn Write) -> std::io::Result<()>,
) { ) {
@ -217,10 +224,7 @@ pub(crate) fn write_ir_file<'tcx>(
let clif_file_name = clif_output_dir.join(name); let clif_file_name = clif_output_dir.join(name);
let res: std::io::Result<()> = try { let res = std::fs::File::create(clif_file_name).and_then(|mut file| write(&mut file));
let mut file = std::fs::File::create(clif_file_name)?;
write(&mut file)?;
};
if let Err(err) = res { if let Err(err) = res {
tcx.sess.warn(&format!("error writing ir file: {}", err)); tcx.sess.warn(&format!("error writing ir file: {}", err));
} }

View file

@ -17,8 +17,7 @@ fn codegen_print(fx: &mut FunctionCx<'_, '_, '_>, msg: &str) {
) )
.unwrap(); .unwrap();
let puts = fx.cx.module.declare_func_in_func(puts, &mut fx.bcx.func); let puts = fx.cx.module.declare_func_in_func(puts, &mut fx.bcx.func);
#[cfg(debug_assertions)] if fx.clif_comments.enabled() {
{
fx.add_comment(puts, "puts"); fx.add_comment(puts, "puts");
} }

View file

@ -2,7 +2,6 @@
use crate::prelude::*; use crate::prelude::*;
use cranelift_codegen::entity::EntityRef;
use cranelift_codegen::ir::immediates::Offset32; use cranelift_codegen::ir::immediates::Offset32;
fn codegen_field<'tcx>( fn codegen_field<'tcx>(
@ -414,7 +413,7 @@ impl<'tcx> CPlace<'tcx> {
self, self,
fx: &mut FunctionCx<'_, '_, 'tcx>, fx: &mut FunctionCx<'_, '_, 'tcx>,
from: CValue<'tcx>, from: CValue<'tcx>,
#[cfg_attr(not(debug_assertions), allow(unused_variables))] method: &'static str, method: &'static str,
) { ) {
fn transmute_value<'tcx>( fn transmute_value<'tcx>(
fx: &mut FunctionCx<'_, '_, 'tcx>, fx: &mut FunctionCx<'_, '_, 'tcx>,
@ -462,8 +461,7 @@ impl<'tcx> CPlace<'tcx> {
assert_eq!(self.layout().size, from.layout().size); assert_eq!(self.layout().size, from.layout().size);
#[cfg(debug_assertions)] if fx.clif_comments.enabled() {
{
use cranelift_codegen::cursor::{Cursor, CursorPosition}; use cranelift_codegen::cursor::{Cursor, CursorPosition};
let cur_block = match fx.bcx.cursor().position() { let cur_block = match fx.bcx.cursor().position() {
CursorPosition::After(block) => block, CursorPosition::After(block) => block,
@ -707,6 +705,19 @@ pub(crate) fn assert_assignable<'tcx>(
} }
// dyn for<'r> Trait<'r> -> dyn Trait<'_> is allowed // dyn for<'r> Trait<'r> -> dyn Trait<'_> is allowed
} }
(&ty::Adt(adt_def_a, substs_a), &ty::Adt(adt_def_b, substs_b))
if adt_def_a.did == adt_def_b.did =>
{
let mut types_a = substs_a.types();
let mut types_b = substs_b.types();
loop {
match (types_a.next(), types_b.next()) {
(Some(a), Some(b)) => assert_assignable(fx, a, b),
(None, None) => return,
(Some(_), None) | (None, Some(_)) => panic!("{:#?}/{:#?}", from_ty, to_ty),
}
}
}
_ => { _ => {
assert_eq!( assert_eq!(
from_ty, to_ty, from_ty, to_ty,