mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-25 13:24:22 +00:00
Merge branch 'master' into stab_peek_mut
This commit is contained in:
commit
72796a7c36
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -9,6 +9,7 @@
|
||||
src/etc/installer/gfx/* binary
|
||||
src/vendor/** -text
|
||||
Cargo.lock linguist-generated=false
|
||||
config.toml.example linguist-language=TOML
|
||||
|
||||
# Older git versions try to fix line endings on images and fonts, this prevents it.
|
||||
*.png binary
|
||||
|
2
.mailmap
2
.mailmap
@ -286,7 +286,7 @@ Xuefeng Wu <benewu@gmail.com> Xuefeng Wu <xfwu@thoughtworks.com>
|
||||
Xuefeng Wu <benewu@gmail.com> XuefengWu <benewu@gmail.com>
|
||||
York Xiang <bombless@126.com>
|
||||
Youngsoo Son <ysson83@gmail.com> <ysoo.son@samsung.com>
|
||||
Yuki Okushi <huyuumi.dev@gmail.com>
|
||||
Yuki Okushi <jtitor@2k36.org> <huyuumi.dev@gmail.com>
|
||||
Zach Pomerantz <zmp@umich.edu>
|
||||
Zack Corr <zack@z0w0.me> <zackcorr95@gmail.com>
|
||||
Zack Slayton <zack.slayton@gmail.com>
|
||||
|
222
Cargo.lock
222
Cargo.lock
@ -1,5 +1,7 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "addr2line"
|
||||
version = "0.14.0"
|
||||
@ -252,11 +254,11 @@ checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7"
|
||||
|
||||
[[package]]
|
||||
name = "bytecount"
|
||||
version = "0.6.0"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0017894339f586ccb943b01b9555de56770c11cda818e7e3d8bd93f4ed7f46e"
|
||||
checksum = "72feb31ffc86498dacdbd0fcebb56138e7177a8cc5cea4516031d15ae85a742e"
|
||||
dependencies = [
|
||||
"packed_simd",
|
||||
"packed_simd_2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -279,7 +281,7 @@ checksum = "81a18687293a1546b67c246452202bbbf143d239cb43494cc163da14979082da"
|
||||
|
||||
[[package]]
|
||||
name = "cargo"
|
||||
version = "0.53.0"
|
||||
version = "0.54.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"atty",
|
||||
@ -287,11 +289,10 @@ dependencies = [
|
||||
"cargo-platform",
|
||||
"cargo-test-macro",
|
||||
"cargo-test-support",
|
||||
"cargo-util",
|
||||
"clap",
|
||||
"core-foundation",
|
||||
"crates-io",
|
||||
"crossbeam-utils 0.8.0",
|
||||
"crypto-hash",
|
||||
"curl",
|
||||
"curl-sys",
|
||||
"env_logger 0.8.1",
|
||||
@ -313,7 +314,6 @@ dependencies = [
|
||||
"libgit2-sys",
|
||||
"log",
|
||||
"memchr",
|
||||
"miow 0.3.6",
|
||||
"num_cpus",
|
||||
"opener",
|
||||
"openssl",
|
||||
@ -322,7 +322,6 @@ dependencies = [
|
||||
"rand 0.8.3",
|
||||
"rustc-workspace-hack",
|
||||
"rustfix",
|
||||
"same-file",
|
||||
"semver 0.10.0",
|
||||
"serde",
|
||||
"serde_ignored",
|
||||
@ -396,8 +395,9 @@ version = "0.1.0"
|
||||
name = "cargo-test-support"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"cargo",
|
||||
"anyhow",
|
||||
"cargo-test-macro",
|
||||
"cargo-util",
|
||||
"filetime",
|
||||
"flate2",
|
||||
"git2",
|
||||
@ -410,6 +410,26 @@ dependencies = [
|
||||
"url 2.1.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cargo-util"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"core-foundation",
|
||||
"crypto-hash",
|
||||
"filetime",
|
||||
"hex 0.4.2",
|
||||
"jobserver",
|
||||
"libc",
|
||||
"log",
|
||||
"miow 0.3.6",
|
||||
"same-file",
|
||||
"shell-escape",
|
||||
"tempfile",
|
||||
"walkdir",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cargo_metadata"
|
||||
version = "0.8.2"
|
||||
@ -562,7 +582,7 @@ dependencies = [
|
||||
"cargo_metadata 0.12.0",
|
||||
"clippy-mini-macro-test",
|
||||
"clippy_lints",
|
||||
"compiletest_rs 0.6.0",
|
||||
"compiletest_rs",
|
||||
"derive-new",
|
||||
"quote",
|
||||
"regex",
|
||||
@ -572,7 +592,7 @@ dependencies = [
|
||||
"serde",
|
||||
"syn",
|
||||
"tempfile",
|
||||
"tester 0.9.0",
|
||||
"tester",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -610,15 +630,6 @@ dependencies = [
|
||||
"unicode-normalization",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cloudabi"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4344512281c643ae7638bbabc3af17a11307803ec8f0fcad9fae512a8bf36467"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cmake"
|
||||
version = "0.1.44"
|
||||
@ -689,28 +700,6 @@ dependencies = [
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "compiletest_rs"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f737835bfbbe29ed1ff82d5137520338d7ed5bf1a1d4b9c1c7c58bb45b8fa29"
|
||||
dependencies = [
|
||||
"diff",
|
||||
"filetime",
|
||||
"getopts",
|
||||
"libc",
|
||||
"log",
|
||||
"miow 0.3.6",
|
||||
"regex",
|
||||
"rustfix",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"tempfile",
|
||||
"tester 0.7.0",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "compiletest_rs"
|
||||
version = "0.6.0"
|
||||
@ -730,7 +719,7 @@ dependencies = [
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"tempfile",
|
||||
"tester 0.9.0",
|
||||
"tester",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
|
||||
@ -1083,6 +1072,26 @@ dependencies = [
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "enum-iterator"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c79a6321a1197d7730510c7e3f6cb80432dfefecb32426de8cea0aa19b4bb8d7"
|
||||
dependencies = [
|
||||
"enum-iterator-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "enum-iterator-derive"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e94aa31f7c0dc764f57896dc615ddd76fc13b0d5dca7eb6cc5e018a5a09ec06"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "env_logger"
|
||||
version = "0.6.2"
|
||||
@ -1428,6 +1437,18 @@ dependencies = [
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getset"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24b328c01a4d71d2d8173daa93562a73ab0fe85616876f02500f53d82948c504"
|
||||
dependencies = [
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gimli"
|
||||
version = "0.23.0"
|
||||
@ -1721,17 +1742,6 @@ version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6"
|
||||
|
||||
[[package]]
|
||||
name = "jemalloc-sys"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d3b9f3f5c9b31aa0f5ed3260385ac205db665baa41d49bb8338008ae94ede45"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"fs_extra",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "jobserver"
|
||||
version = "0.1.21"
|
||||
@ -1920,6 +1930,12 @@ dependencies = [
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libm"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fc7aa29613bd6a620df431842069224d8bc9011086b1db4c0e0cd47fa03ec9a"
|
||||
|
||||
[[package]]
|
||||
name = "libnghttp2-sys"
|
||||
version = "0.1.4+1.41.0"
|
||||
@ -2298,13 +2314,13 @@ name = "miri"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"colored",
|
||||
"compiletest_rs 0.5.0",
|
||||
"env_logger 0.7.1",
|
||||
"compiletest_rs",
|
||||
"env_logger 0.8.1",
|
||||
"getrandom 0.2.0",
|
||||
"hex 0.4.2",
|
||||
"libc",
|
||||
"log",
|
||||
"rand 0.7.3",
|
||||
"rand 0.8.3",
|
||||
"rustc-workspace-hack",
|
||||
"rustc_version",
|
||||
"shell-escape",
|
||||
@ -2463,12 +2479,13 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "packed_simd"
|
||||
version = "0.3.3"
|
||||
name = "packed_simd_2"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a85ea9fc0d4ac0deb6fe7911d38786b32fc11119afd9e9d38b84ff691ce64220"
|
||||
checksum = "3278e0492f961fd4ae70909f56b2723a7e8d01a228427294e19cdfdebda89a17"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.10",
|
||||
"libm",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2511,9 +2528,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.11.0"
|
||||
version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a4893845fa2ca272e647da5d0e46660a314ead9c2fdd9a883aabc32e481a8733"
|
||||
checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb"
|
||||
dependencies = [
|
||||
"instant",
|
||||
"lock_api",
|
||||
@ -2522,15 +2539,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.8.0"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c361aa727dd08437f2f1447be8b59a33b0edd15e0fcee698f935613d9efbca9b"
|
||||
checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.10",
|
||||
"cloudabi",
|
||||
"cfg-if 1.0.0",
|
||||
"instant",
|
||||
"libc",
|
||||
"redox_syscall 0.1.57",
|
||||
"redox_syscall 0.2.5",
|
||||
"smallvec 1.6.1",
|
||||
"winapi 0.3.9",
|
||||
]
|
||||
@ -2769,9 +2785,9 @@ checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.19"
|
||||
version = "1.0.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04f5f085b5d71e2188cb8271e5da0161ad52c3f227a661a3c135fdf28e258b12"
|
||||
checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
@ -3569,9 +3585,10 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||
name = "rustc-main"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"jemalloc-sys",
|
||||
"rustc_codegen_ssa",
|
||||
"rustc_driver",
|
||||
"tikv-jemalloc-sys",
|
||||
"tikv-jemallocator",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3795,7 +3812,6 @@ dependencies = [
|
||||
"itertools 0.9.0",
|
||||
"jobserver",
|
||||
"libc",
|
||||
"memmap2",
|
||||
"pathdiff",
|
||||
"rustc_apfloat",
|
||||
"rustc_ast",
|
||||
@ -3830,6 +3846,7 @@ dependencies = [
|
||||
"jobserver",
|
||||
"libc",
|
||||
"measureme",
|
||||
"memmap2",
|
||||
"parking_lot",
|
||||
"rustc-hash",
|
||||
"rustc-rayon",
|
||||
@ -4129,7 +4146,6 @@ name = "rustc_metadata"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"memmap2",
|
||||
"rustc_ast",
|
||||
"rustc_attr",
|
||||
"rustc_data_structures",
|
||||
@ -4575,11 +4591,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.2.3"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
||||
checksum = "f0dfe2087c51c460008730de8b57e6a320782fbfb312e1f4d520e6c6fae155ee"
|
||||
dependencies = [
|
||||
"semver 0.9.0",
|
||||
"semver 0.11.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -4797,18 +4813,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.118"
|
||||
version = "1.0.125"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06c64263859d87aa2eb554587e2d23183398d617427327cf2b3d0ed8c69e4800"
|
||||
checksum = "558dc50e1a5a5fa7112ca2ce4effcb321b0300c0d4ccf0776a9f60cd89031171"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.118"
|
||||
version = "1.0.125"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c84d3526699cd55261af4b941e4e725444df67aa4f9e6a3564f18030d12672df"
|
||||
checksum = "b093b7a2bb58203b5da3056c05b4ec1fed827dcfdb37347a8841695263b3d06d"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -5104,9 +5120,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.38"
|
||||
version = "1.0.65"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e69abc24912995b3038597a7a593be5053eb0fb44f3cc5beec0deb421790c1f4"
|
||||
checksum = "f3a1d708c221c5a612956ef9f75b37e454e88d1f7b899fbd3a18d4252012d663"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -5225,17 +5241,6 @@ dependencies = [
|
||||
"term 0.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tester"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee72ec31009a42b53de9a6b7d8f462b493ab3b1e4767bda1fcdbb52127f13b6c"
|
||||
dependencies = [
|
||||
"getopts",
|
||||
"libc",
|
||||
"term 0.6.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tester"
|
||||
version = "0.9.0"
|
||||
@ -5292,6 +5297,7 @@ name = "tidy"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"cargo_metadata 0.11.1",
|
||||
"crossbeam-utils 0.8.0",
|
||||
"lazy_static",
|
||||
"regex",
|
||||
"walkdir",
|
||||
@ -5301,6 +5307,27 @@ dependencies = [
|
||||
name = "tier-check"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "tikv-jemalloc-sys"
|
||||
version = "0.4.1+5.2.1-patched"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8a26331b05179d4cb505c8d6814a7e18d298972f0a551b0e3cefccff927f86d3"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"fs_extra",
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tikv-jemallocator"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c14a5a604eb8715bc5785018a37d00739b180bcf609916ddf4393d33d49ccdf"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"tikv-jemalloc-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.1.43"
|
||||
@ -5648,12 +5675,17 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
|
||||
|
||||
[[package]]
|
||||
name = "vergen"
|
||||
version = "3.1.0"
|
||||
version = "5.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ce50d8996df1f85af15f2cd8d33daae6e479575123ef4314a51a70a230739cb"
|
||||
checksum = "dfbc87f9a7a9d61b15d51d1d3547284f67b6b4f1494ce3fc5814c101f35a5183"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"anyhow",
|
||||
"chrono",
|
||||
"enum-iterator",
|
||||
"getset",
|
||||
"git2",
|
||||
"rustversion",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
24
RELEASES.md
24
RELEASES.md
@ -35,7 +35,7 @@ Compiler
|
||||
- [Added tier 3 support for `i386-unknown-linux-gnu` and `i486-unknown-linux-gnu` targets.][80662]
|
||||
- [The `target-cpu=native` option will now detect individual features of CPUs.][80749]
|
||||
|
||||
\* Refer to Rust's [platform support page][forge-platform-support] for more
|
||||
\* Refer to Rust's [platform support page][platform-support-doc] for more
|
||||
information on Rust's tiered platform support.
|
||||
|
||||
Libraries
|
||||
@ -183,7 +183,7 @@ Compiler
|
||||
- [The `x86_64-unknown-freebsd` is now built with the full toolset.][79484]
|
||||
- [Dropped support for all cloudabi targets.][78439]
|
||||
|
||||
\* Refer to Rust's [platform support page][forge-platform-support] for more
|
||||
\* Refer to Rust's [platform support page][platform-support-doc] for more
|
||||
information on Rust's tiered platform support.
|
||||
|
||||
Libraries
|
||||
@ -360,7 +360,7 @@ Compiler
|
||||
- [Output from threads spawned in tests is now captured.][78227]
|
||||
- [Change os and vendor values to "none" and "unknown" for some targets][78951]
|
||||
|
||||
\* Refer to Rust's [platform support page][forge-platform-support] for more
|
||||
\* Refer to Rust's [platform support page][platform-support-doc] for more
|
||||
information on Rust's tiered platform support.
|
||||
|
||||
Libraries
|
||||
@ -465,7 +465,7 @@ Compiler
|
||||
Note: If you're using cargo you must explicitly pass the `--target` flag.
|
||||
- [Added tier 2\* support for `aarch64-unknown-linux-musl`.][76420]
|
||||
|
||||
\* Refer to Rust's [platform support page][forge-platform-support] for more
|
||||
\* Refer to Rust's [platform support page][platform-support-doc] for more
|
||||
information on Rust's tiered platform support.
|
||||
|
||||
Libraries
|
||||
@ -604,7 +604,7 @@ Compiler
|
||||
- [Upgrade the FreeBSD toolchain to version 11.4][75204]
|
||||
- [`RUST_BACKTRACE`'s output is now more compact.][75048]
|
||||
|
||||
\* Refer to Rust's [platform support page][forge-platform-support] for more
|
||||
\* Refer to Rust's [platform support page][platform-support-doc] for more
|
||||
information on Rust's tiered platform support.
|
||||
|
||||
Libraries
|
||||
@ -889,7 +889,7 @@ Compiler
|
||||
- [Added tier 3 support for the `thumbv7a-uwp-windows-msvc` target.][72133]
|
||||
- [Upgraded to LLVM 10.][67759]
|
||||
|
||||
\* Refer to Rust's [platform support page][forge-platform-support] for more
|
||||
\* Refer to Rust's [platform support page][platform-support-doc] for more
|
||||
information on Rust's tiered platform support.
|
||||
|
||||
|
||||
@ -1398,7 +1398,7 @@ Compiler
|
||||
pointing to the location where they were called, rather than
|
||||
`core`'s internals. ][67887]
|
||||
|
||||
\* Refer to Rust's [platform support page][forge-platform-support] for more
|
||||
\* Refer to Rust's [platform support page][platform-support-doc] for more
|
||||
information on Rust's tiered platform support.
|
||||
|
||||
Libraries
|
||||
@ -1496,7 +1496,7 @@ Compiler
|
||||
- [You can now provide `--extern` flag without a path, indicating that it is
|
||||
available from the search path or specified with an `-L` flag.][64882]
|
||||
|
||||
\* Refer to Rust's [platform support page][forge-platform-support] for more
|
||||
\* Refer to Rust's [platform support page][platform-support-doc] for more
|
||||
information on Rust's tiered platform support.
|
||||
|
||||
[argfile-docs]: https://doc.rust-lang.org/nightly/rustc/command-line-arguments.html#path-load-command-line-flags-from-a-path
|
||||
@ -1620,7 +1620,7 @@ Compiler
|
||||
- [Added tier 3 support for the `mips64-unknown-linux-muslabi64`, and
|
||||
`mips64el-unknown-linux-muslabi64` targets.][65843]
|
||||
|
||||
\* Refer to Rust's [platform support page][forge-platform-support] for more
|
||||
\* Refer to Rust's [platform support page][platform-support-doc] for more
|
||||
information on Rust's tiered platform support.
|
||||
|
||||
Libraries
|
||||
@ -1770,7 +1770,7 @@ Compiler
|
||||
output of successful tests.][62600]
|
||||
|
||||
|
||||
\* Refer to Rust's [platform support page][forge-platform-support] for more
|
||||
\* Refer to Rust's [platform support page][platform-support-doc] for more
|
||||
information on Rust's tiered platform support.
|
||||
|
||||
Libraries
|
||||
@ -1864,7 +1864,7 @@ Compiler
|
||||
- [Added tier 3 support for the `riscv32i-unknown-none-elf` target.][62784]
|
||||
- [Upgraded to LLVM 9.][62592]
|
||||
|
||||
\* Refer to Rust's [platform support page][forge-platform-support] for more
|
||||
\* Refer to Rust's [platform support page][platform-support-doc] for more
|
||||
information on Rust's tiered platform support.
|
||||
|
||||
Libraries
|
||||
@ -1951,7 +1951,7 @@ Compatibility Notes
|
||||
[`Duration::mul_f32`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.mul_f32
|
||||
[`Duration::mul_f64`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.mul_f64
|
||||
[`any::type_name`]: https://doc.rust-lang.org/std/any/fn.type_name.html
|
||||
[forge-platform-support]: https://forge.rust-lang.org/release/platform-support.html
|
||||
[platform-support-doc]: https://doc.rust-lang.org/nightly/rustc/platform-support.html
|
||||
[pipeline-internals]: https://internals.rust-lang.org/t/evaluating-pipelined-rustc-compilation/10199
|
||||
|
||||
Version 1.37.0 (2019-08-15)
|
||||
|
@ -11,12 +11,16 @@ rustc_driver = { path = "../rustc_driver" }
|
||||
# crate is intended to be used by codegen backends, which may not be in-tree.
|
||||
rustc_codegen_ssa = { path = "../rustc_codegen_ssa" }
|
||||
|
||||
[dependencies.jemalloc-sys]
|
||||
version = '0.3.0'
|
||||
[dependencies.tikv-jemalloc-sys]
|
||||
version = '0.4.0'
|
||||
optional = true
|
||||
features = ['unprefixed_malloc_on_supported_platforms']
|
||||
|
||||
[dependencies.tikv-jemallocator]
|
||||
version = '0.4.0'
|
||||
optional = true
|
||||
|
||||
[features]
|
||||
jemalloc = ['jemalloc-sys']
|
||||
jemalloc = ['tikv-jemalloc-sys', 'tikv-jemallocator']
|
||||
llvm = ['rustc_driver/llvm']
|
||||
max_level_info = ['rustc_driver/max_level_info']
|
||||
|
@ -1,3 +1,16 @@
|
||||
// Configure jemalloc as the `global_allocator` when configured. This is
|
||||
// so that we use the sized deallocation apis jemalloc provides
|
||||
// (namely `sdallocx`).
|
||||
//
|
||||
// The symbol overrides documented below are also performed so that we can
|
||||
// ensure that we use a consistent allocator across the rustc <-> llvm boundary
|
||||
#[cfg(feature = "jemalloc")]
|
||||
#[global_allocator]
|
||||
static ALLOC: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc;
|
||||
|
||||
#[cfg(feature = "tikv-jemalloc-sys")]
|
||||
use tikv_jemalloc_sys as jemalloc_sys;
|
||||
|
||||
fn main() {
|
||||
// Pull in jemalloc when enabled.
|
||||
//
|
||||
@ -7,7 +20,7 @@ fn main() {
|
||||
// dynamic libraries. That means to pull in jemalloc we actually need to
|
||||
// reference allocation symbols one way or another (as this file is the only
|
||||
// object code in the rustc executable).
|
||||
#[cfg(feature = "jemalloc-sys")]
|
||||
#[cfg(feature = "tikv-jemalloc-sys")]
|
||||
{
|
||||
use std::os::raw::{c_int, c_void};
|
||||
|
||||
|
@ -2273,6 +2273,7 @@ impl Loss {
|
||||
mod sig {
|
||||
use super::{limbs_for_bits, ExpInt, Limb, Loss, LIMB_BITS};
|
||||
use core::cmp::Ordering;
|
||||
use core::iter;
|
||||
use core::mem;
|
||||
|
||||
pub(super) fn is_all_zeros(limbs: &[Limb]) -> bool {
|
||||
@ -2483,7 +2484,7 @@ mod sig {
|
||||
pub(super) fn add(a: &mut [Limb], b: &[Limb], mut c: Limb) -> Limb {
|
||||
assert!(c <= 1);
|
||||
|
||||
for (a, &b) in a.iter_mut().zip(b) {
|
||||
for (a, &b) in iter::zip(a, b) {
|
||||
let (r, overflow) = a.overflowing_add(b);
|
||||
let (r, overflow2) = r.overflowing_add(c);
|
||||
*a = r;
|
||||
@ -2497,7 +2498,7 @@ mod sig {
|
||||
pub(super) fn sub(a: &mut [Limb], b: &[Limb], mut c: Limb) -> Limb {
|
||||
assert!(c <= 1);
|
||||
|
||||
for (a, &b) in a.iter_mut().zip(b) {
|
||||
for (a, &b) in iter::zip(a, b) {
|
||||
let (r, overflow) = a.overflowing_sub(b);
|
||||
let (r, overflow2) = r.overflowing_sub(c);
|
||||
*a = r;
|
||||
|
@ -33,6 +33,7 @@
|
||||
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
|
||||
#![no_std]
|
||||
#![forbid(unsafe_code)]
|
||||
#![feature(iter_zip)]
|
||||
#![feature(nll)]
|
||||
#![cfg_attr(bootstrap, feature(or_patterns))]
|
||||
|
||||
|
@ -236,26 +236,6 @@ impl<T> TypedArena<T> {
|
||||
start_ptr
|
||||
}
|
||||
|
||||
/// Allocates a slice of objects that are copied into the `TypedArena`, returning a mutable
|
||||
/// reference to it. Will panic if passed a zero-sized types.
|
||||
///
|
||||
/// Panics:
|
||||
///
|
||||
/// - Zero-sized types
|
||||
/// - Zero-length slices
|
||||
#[inline]
|
||||
pub fn alloc_slice(&self, slice: &[T]) -> &mut [T]
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
unsafe {
|
||||
let len = slice.len();
|
||||
let start_ptr = self.alloc_raw_slice(len);
|
||||
slice.as_ptr().copy_to_nonoverlapping(start_ptr, len);
|
||||
slice::from_raw_parts_mut(start_ptr, len)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn alloc_from_iter<I: IntoIterator<Item = T>>(&self, iter: I) -> &mut [T] {
|
||||
assert!(mem::size_of::<T>() != 0);
|
||||
|
@ -762,14 +762,6 @@ pub enum Mutability {
|
||||
}
|
||||
|
||||
impl Mutability {
|
||||
/// Returns `MutMutable` only if both `self` and `other` are mutable.
|
||||
pub fn and(self, other: Self) -> Self {
|
||||
match self {
|
||||
Mutability::Mut => other,
|
||||
Mutability::Not => Mutability::Not,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn invert(self) -> Self {
|
||||
match self {
|
||||
Mutability::Mut => Mutability::Not,
|
||||
@ -1722,13 +1714,6 @@ impl FloatTy {
|
||||
FloatTy::F64 => sym::f64,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bit_width(self) -> u64 {
|
||||
match self {
|
||||
FloatTy::F32 => 32,
|
||||
FloatTy::F64 => 64,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||
@ -1764,29 +1749,6 @@ impl IntTy {
|
||||
IntTy::I128 => sym::i128,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bit_width(&self) -> Option<u64> {
|
||||
Some(match *self {
|
||||
IntTy::Isize => return None,
|
||||
IntTy::I8 => 8,
|
||||
IntTy::I16 => 16,
|
||||
IntTy::I32 => 32,
|
||||
IntTy::I64 => 64,
|
||||
IntTy::I128 => 128,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn normalize(&self, target_width: u32) -> Self {
|
||||
match self {
|
||||
IntTy::Isize => match target_width {
|
||||
16 => IntTy::I16,
|
||||
32 => IntTy::I32,
|
||||
64 => IntTy::I64,
|
||||
_ => unreachable!(),
|
||||
},
|
||||
_ => *self,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, Debug)]
|
||||
@ -1822,29 +1784,6 @@ impl UintTy {
|
||||
UintTy::U128 => sym::u128,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bit_width(&self) -> Option<u64> {
|
||||
Some(match *self {
|
||||
UintTy::Usize => return None,
|
||||
UintTy::U8 => 8,
|
||||
UintTy::U16 => 16,
|
||||
UintTy::U32 => 32,
|
||||
UintTy::U64 => 64,
|
||||
UintTy::U128 => 128,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn normalize(&self, target_width: u32) -> Self {
|
||||
match self {
|
||||
UintTy::Usize => match target_width {
|
||||
16 => UintTy::U16,
|
||||
32 => UintTy::U32,
|
||||
64 => UintTy::U64,
|
||||
_ => unreachable!(),
|
||||
},
|
||||
_ => *self,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A constraint on an associated type (e.g., `A = Bar` in `Foo<A = Bar>` or
|
||||
@ -2215,9 +2154,6 @@ pub struct FnDecl {
|
||||
}
|
||||
|
||||
impl FnDecl {
|
||||
pub fn get_self(&self) -> Option<ExplicitSelf> {
|
||||
self.inputs.get(0).and_then(Param::to_self)
|
||||
}
|
||||
pub fn has_self(&self) -> bool {
|
||||
self.inputs.get(0).map_or(false, Param::is_self)
|
||||
}
|
||||
|
@ -100,16 +100,7 @@ impl NestedMetaItem {
|
||||
self.meta_item().map_or(false, |meta_item| meta_item.is_word())
|
||||
}
|
||||
|
||||
/// Returns `true` if `self` is a `MetaItem` and the meta item is a `ValueString`.
|
||||
pub fn is_value_str(&self) -> bool {
|
||||
self.value_str().is_some()
|
||||
}
|
||||
|
||||
/// Returns `true` if `self` is a `MetaItem` and the meta item is a list.
|
||||
pub fn is_meta_item_list(&self) -> bool {
|
||||
self.meta_item_list().is_some()
|
||||
}
|
||||
|
||||
/// See [`MetaItem::name_value_literal_span`].
|
||||
pub fn name_value_literal_span(&self) -> Option<Span> {
|
||||
self.meta_item()?.name_value_literal_span()
|
||||
}
|
||||
@ -165,31 +156,6 @@ impl Attribute {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_meta_item_list(&self) -> bool {
|
||||
self.meta_item_list().is_some()
|
||||
}
|
||||
|
||||
/// Indicates if the attribute is a `ValueString`.
|
||||
pub fn is_value_str(&self) -> bool {
|
||||
self.value_str().is_some()
|
||||
}
|
||||
|
||||
/// This is used in case you want the value span instead of the whole attribute. Example:
|
||||
///
|
||||
/// ```text
|
||||
/// #[doc(alias = "foo")]
|
||||
/// ```
|
||||
///
|
||||
/// In here, it'll return a span for `"foo"`.
|
||||
pub fn name_value_literal_span(&self) -> Option<Span> {
|
||||
match self.kind {
|
||||
AttrKind::Normal(ref item, _) => {
|
||||
item.meta(self.span).and_then(|meta| meta.name_value_literal_span())
|
||||
}
|
||||
AttrKind::DocComment(..) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MetaItem {
|
||||
@ -236,10 +202,6 @@ impl MetaItem {
|
||||
self.path == name
|
||||
}
|
||||
|
||||
pub fn is_value_str(&self) -> bool {
|
||||
self.value_str().is_some()
|
||||
}
|
||||
|
||||
/// This is used in case you want the value span instead of the whole attribute. Example:
|
||||
///
|
||||
/// ```text
|
||||
|
@ -14,6 +14,7 @@
|
||||
#![feature(const_fn_transmute)]
|
||||
#![feature(const_panic)]
|
||||
#![feature(crate_visibility_modifier)]
|
||||
#![feature(iter_zip)]
|
||||
#![feature(label_break_value)]
|
||||
#![feature(nll)]
|
||||
#![cfg_attr(bootstrap, feature(or_patterns))]
|
||||
|
@ -89,10 +89,6 @@ impl TokenTree {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn joint(self) -> TokenStream {
|
||||
TokenStream::new(vec![(self, Spacing::Joint)])
|
||||
}
|
||||
|
||||
pub fn token(kind: TokenKind, span: Span) -> TokenTree {
|
||||
TokenTree::Token(Token::new(kind, span))
|
||||
}
|
||||
@ -278,14 +274,6 @@ impl TokenStream {
|
||||
self.0.len()
|
||||
}
|
||||
|
||||
pub fn span(&self) -> Option<Span> {
|
||||
match &**self.0 {
|
||||
[] => None,
|
||||
[(tt, _)] => Some(tt.span()),
|
||||
[(tt_start, _), .., (tt_end, _)] => Some(tt_start.span().to(tt_end.span())),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_streams(mut streams: SmallVec<[TokenStream; 2]>) -> TokenStream {
|
||||
match streams.len() {
|
||||
0 => TokenStream::default(),
|
||||
@ -325,10 +313,6 @@ impl TokenStream {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn trees_ref(&self) -> CursorRef<'_> {
|
||||
CursorRef::new(self)
|
||||
}
|
||||
|
||||
pub fn trees(&self) -> Cursor {
|
||||
self.clone().into_trees()
|
||||
}
|
||||
@ -341,7 +325,7 @@ impl TokenStream {
|
||||
pub fn eq_unspanned(&self, other: &TokenStream) -> bool {
|
||||
let mut t1 = self.trees();
|
||||
let mut t2 = other.trees();
|
||||
for (t1, t2) in t1.by_ref().zip(t2.by_ref()) {
|
||||
for (t1, t2) in iter::zip(&mut t1, &mut t2) {
|
||||
if !t1.eq_unspanned(&t2) {
|
||||
return false;
|
||||
}
|
||||
@ -427,10 +411,6 @@ pub struct CursorRef<'t> {
|
||||
}
|
||||
|
||||
impl<'t> CursorRef<'t> {
|
||||
fn new(stream: &TokenStream) -> CursorRef<'_> {
|
||||
CursorRef { stream, index: 0 }
|
||||
}
|
||||
|
||||
fn next_with_spacing(&mut self) -> Option<&'t TreeAndSpacing> {
|
||||
self.stream.0.get(self.index).map(|tree| {
|
||||
self.index += 1;
|
||||
|
@ -1499,46 +1499,64 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
// previous iteration.
|
||||
required_features.clear();
|
||||
|
||||
// Validate register classes against currently enabled target
|
||||
// features. We check that at least one type is available for
|
||||
// the current target.
|
||||
let reg_class = reg.reg_class();
|
||||
if reg_class == asm::InlineAsmRegClass::Err {
|
||||
continue;
|
||||
}
|
||||
for &(_, feature) in reg_class.supported_types(asm_arch.unwrap()) {
|
||||
if let Some(feature) = feature {
|
||||
if self.sess.target_features.contains(&Symbol::intern(feature)) {
|
||||
|
||||
// We ignore target feature requirements for clobbers: if the
|
||||
// feature is disabled then the compiler doesn't care what we
|
||||
// do with the registers.
|
||||
//
|
||||
// Note that this is only possible for explicit register
|
||||
// operands, which cannot be used in the asm string.
|
||||
let is_clobber = matches!(
|
||||
op,
|
||||
hir::InlineAsmOperand::Out {
|
||||
reg: asm::InlineAsmRegOrRegClass::Reg(_),
|
||||
late: _,
|
||||
expr: None
|
||||
}
|
||||
);
|
||||
|
||||
if !is_clobber {
|
||||
// Validate register classes against currently enabled target
|
||||
// features. We check that at least one type is available for
|
||||
// the current target.
|
||||
for &(_, feature) in reg_class.supported_types(asm_arch.unwrap()) {
|
||||
if let Some(feature) = feature {
|
||||
if self.sess.target_features.contains(&Symbol::intern(feature)) {
|
||||
required_features.clear();
|
||||
break;
|
||||
} else {
|
||||
required_features.push(feature);
|
||||
}
|
||||
} else {
|
||||
required_features.clear();
|
||||
break;
|
||||
} else {
|
||||
required_features.push(feature);
|
||||
}
|
||||
} else {
|
||||
required_features.clear();
|
||||
break;
|
||||
}
|
||||
}
|
||||
// We are sorting primitive strs here and can use unstable sort here
|
||||
required_features.sort_unstable();
|
||||
required_features.dedup();
|
||||
match &required_features[..] {
|
||||
[] => {}
|
||||
[feature] => {
|
||||
let msg = format!(
|
||||
"register class `{}` requires the `{}` target feature",
|
||||
reg_class.name(),
|
||||
feature
|
||||
);
|
||||
sess.struct_span_err(op_sp, &msg).emit();
|
||||
}
|
||||
features => {
|
||||
let msg = format!(
|
||||
"register class `{}` requires at least one target feature: {}",
|
||||
reg_class.name(),
|
||||
features.join(", ")
|
||||
);
|
||||
sess.struct_span_err(op_sp, &msg).emit();
|
||||
// We are sorting primitive strs here and can use unstable sort here
|
||||
required_features.sort_unstable();
|
||||
required_features.dedup();
|
||||
match &required_features[..] {
|
||||
[] => {}
|
||||
[feature] => {
|
||||
let msg = format!(
|
||||
"register class `{}` requires the `{}` target feature",
|
||||
reg_class.name(),
|
||||
feature
|
||||
);
|
||||
sess.struct_span_err(op_sp, &msg).emit();
|
||||
}
|
||||
features => {
|
||||
let msg = format!(
|
||||
"register class `{}` requires at least one target feature: {}",
|
||||
reg_class.name(),
|
||||
features.join(", ")
|
||||
);
|
||||
sess.struct_span_err(op_sp, &msg).emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,7 @@ use rustc_target::spec::abi;
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
use tracing::debug;
|
||||
|
||||
use std::iter;
|
||||
use std::mem;
|
||||
|
||||
pub(super) struct ItemLowerer<'a, 'lowering, 'hir> {
|
||||
@ -206,7 +207,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
UseTreeKind::Glob => {}
|
||||
UseTreeKind::Simple(_, id1, id2) => {
|
||||
for (_, &id) in
|
||||
self.expect_full_res_from_use(base_id).skip(1).zip([id1, id2].iter())
|
||||
iter::zip(self.expect_full_res_from_use(base_id).skip(1), &[id1, id2])
|
||||
{
|
||||
vec.push(id);
|
||||
}
|
||||
@ -537,7 +538,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
// won't be dealing with macros in the rest of the compiler.
|
||||
// Essentially a single `use` which imports two names is desugared into
|
||||
// two imports.
|
||||
for (res, &new_node_id) in resolutions.zip([id1, id2].iter()) {
|
||||
for (res, &new_node_id) in iter::zip(resolutions, &[id1, id2]) {
|
||||
let ident = *ident;
|
||||
let mut path = path.clone();
|
||||
for seg in &mut path.segments {
|
||||
|
@ -33,6 +33,7 @@
|
||||
#![feature(crate_visibility_modifier)]
|
||||
#![cfg_attr(bootstrap, feature(or_patterns))]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(iter_zip)]
|
||||
#![recursion_limit = "256"]
|
||||
|
||||
use rustc_ast::node_id::NodeMap;
|
||||
@ -568,7 +569,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
}
|
||||
|
||||
hir::Crate {
|
||||
item: hir::CrateItem { module, span: c.span },
|
||||
item: module,
|
||||
exported_macros: self.arena.alloc_from_iter(self.exported_macros),
|
||||
non_exported_macro_attrs: self.arena.alloc_from_iter(self.non_exported_macro_attrs),
|
||||
items: self.items,
|
||||
|
@ -313,7 +313,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
||||
include => external_doc
|
||||
cfg => doc_cfg
|
||||
masked => doc_masked
|
||||
spotlight => doc_spotlight
|
||||
notable_trait => doc_notable_trait
|
||||
keyword => doc_keyword
|
||||
);
|
||||
}
|
||||
|
@ -22,10 +22,6 @@ pub fn token_to_string(token: &Token) -> String {
|
||||
State::new().token_to_string(token)
|
||||
}
|
||||
|
||||
pub fn token_to_string_ext(token: &Token, convert_dollar_crate: bool) -> String {
|
||||
State::new().token_to_string_ext(token, convert_dollar_crate)
|
||||
}
|
||||
|
||||
pub fn ty_to_string(ty: &ast::Ty) -> String {
|
||||
State::new().ty_to_string(ty)
|
||||
}
|
||||
@ -50,18 +46,10 @@ pub fn tts_to_string(tokens: &TokenStream) -> String {
|
||||
State::new().tts_to_string(tokens)
|
||||
}
|
||||
|
||||
pub fn stmt_to_string(stmt: &ast::Stmt) -> String {
|
||||
State::new().stmt_to_string(stmt)
|
||||
}
|
||||
|
||||
pub fn item_to_string(i: &ast::Item) -> String {
|
||||
State::new().item_to_string(i)
|
||||
}
|
||||
|
||||
pub fn generic_params_to_string(generic_params: &[ast::GenericParam]) -> String {
|
||||
State::new().generic_params_to_string(generic_params)
|
||||
}
|
||||
|
||||
pub fn path_to_string(p: &ast::Path) -> String {
|
||||
State::new().path_to_string(p)
|
||||
}
|
||||
@ -74,26 +62,14 @@ pub fn vis_to_string(v: &ast::Visibility) -> String {
|
||||
State::new().vis_to_string(v)
|
||||
}
|
||||
|
||||
pub fn block_to_string(blk: &ast::Block) -> String {
|
||||
State::new().block_to_string(blk)
|
||||
}
|
||||
|
||||
pub fn meta_list_item_to_string(li: &ast::NestedMetaItem) -> String {
|
||||
State::new().meta_list_item_to_string(li)
|
||||
}
|
||||
|
||||
pub fn attr_item_to_string(ai: &ast::AttrItem) -> String {
|
||||
State::new().attr_item_to_string(ai)
|
||||
}
|
||||
|
||||
pub fn attribute_to_string(attr: &ast::Attribute) -> String {
|
||||
State::new().attribute_to_string(attr)
|
||||
}
|
||||
|
||||
pub fn param_to_string(arg: &ast::Param) -> String {
|
||||
State::new().param_to_string(arg)
|
||||
}
|
||||
|
||||
pub fn to_string(f: impl FnOnce(&mut State<'_>)) -> String {
|
||||
State::new().to_string(f)
|
||||
}
|
||||
|
@ -2292,10 +2292,6 @@ impl<'a> State<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn print_usize(&mut self, i: usize) {
|
||||
self.s.word(i.to_string())
|
||||
}
|
||||
|
||||
crate fn print_name(&mut self, name: Symbol) {
|
||||
self.s.word(name.to_string());
|
||||
self.ann.post(self, AnnNode::Name(&name))
|
||||
|
@ -862,18 +862,6 @@ pub fn find_repr_attrs(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
|
||||
if let Some(items) = attr.meta_item_list() {
|
||||
sess.mark_attr_used(attr);
|
||||
for item in items {
|
||||
if !item.is_meta_item() {
|
||||
handle_errors(
|
||||
&sess.parse_sess,
|
||||
item.span(),
|
||||
AttrError::UnsupportedLiteral(
|
||||
"meta item in `repr` must be an identifier",
|
||||
false,
|
||||
),
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut recognised = false;
|
||||
if item.is_word() {
|
||||
let hint = match item.name_or_empty() {
|
||||
@ -890,23 +878,6 @@ pub fn find_repr_attrs(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
|
||||
acc.push(h);
|
||||
}
|
||||
} else if let Some((name, value)) = item.name_value_literal() {
|
||||
let parse_alignment = |node: &ast::LitKind| -> Result<u32, &'static str> {
|
||||
if let ast::LitKind::Int(literal, ast::LitIntType::Unsuffixed) = node {
|
||||
if literal.is_power_of_two() {
|
||||
// rustc_middle::ty::layout::Align restricts align to <= 2^29
|
||||
if *literal <= 1 << 29 {
|
||||
Ok(*literal as u32)
|
||||
} else {
|
||||
Err("larger than 2^29")
|
||||
}
|
||||
} else {
|
||||
Err("not a power of two")
|
||||
}
|
||||
} else {
|
||||
Err("not an unsuffixed integer")
|
||||
}
|
||||
};
|
||||
|
||||
let mut literal_error = None;
|
||||
if name == sym::align {
|
||||
recognised = true;
|
||||
@ -966,13 +937,7 @@ pub fn find_repr_attrs(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
|
||||
}
|
||||
if !recognised {
|
||||
// Not a word we recognize
|
||||
struct_span_err!(
|
||||
diagnostic,
|
||||
item.span(),
|
||||
E0552,
|
||||
"unrecognized representation hint"
|
||||
)
|
||||
.emit();
|
||||
diagnostic.delay_span_bug(item.span(), "unrecognized representation hint");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1080,3 +1045,16 @@ fn allow_unstable<'a>(
|
||||
name
|
||||
})
|
||||
}
|
||||
|
||||
pub fn parse_alignment(node: &ast::LitKind) -> Result<u32, &'static str> {
|
||||
if let ast::LitKind::Int(literal, ast::LitIntType::Unsuffixed) = node {
|
||||
if literal.is_power_of_two() {
|
||||
// rustc_middle::ty::layout::Align restricts align to <= 2^29
|
||||
if *literal <= 1 << 29 { Ok(*literal as u32) } else { Err("larger than 2^29") }
|
||||
} else {
|
||||
Err("not a power of two")
|
||||
}
|
||||
} else {
|
||||
Err("not an unsuffixed integer")
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::cfg_eval::cfg_eval;
|
||||
|
||||
use rustc_ast::{self as ast, token, ItemKind, MetaItemKind, NestedMetaItem, StmtKind};
|
||||
use rustc_ast::{self as ast, attr, token, ItemKind, MetaItemKind, NestedMetaItem, StmtKind};
|
||||
use rustc_errors::{struct_span_err, Applicability};
|
||||
use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, Indeterminate, MultiItemModifier};
|
||||
use rustc_feature::AttributeTemplate;
|
||||
@ -26,32 +26,39 @@ impl MultiItemModifier for Expander {
|
||||
return ExpandResult::Ready(vec![item]);
|
||||
}
|
||||
|
||||
let template =
|
||||
AttributeTemplate { list: Some("Trait1, Trait2, ..."), ..Default::default() };
|
||||
let attr = ecx.attribute(meta_item.clone());
|
||||
validate_attr::check_builtin_attribute(&sess.parse_sess, &attr, sym::derive, template);
|
||||
let result =
|
||||
ecx.resolver.resolve_derives(ecx.current_expansion.id, ecx.force_mode, &|| {
|
||||
let template =
|
||||
AttributeTemplate { list: Some("Trait1, Trait2, ..."), ..Default::default() };
|
||||
let attr = attr::mk_attr_outer(meta_item.clone());
|
||||
validate_attr::check_builtin_attribute(
|
||||
&sess.parse_sess,
|
||||
&attr,
|
||||
sym::derive,
|
||||
template,
|
||||
);
|
||||
|
||||
let derives: Vec<_> = attr
|
||||
.meta_item_list()
|
||||
.unwrap_or_default()
|
||||
.into_iter()
|
||||
.filter_map(|nested_meta| match nested_meta {
|
||||
NestedMetaItem::MetaItem(meta) => Some(meta),
|
||||
NestedMetaItem::Literal(lit) => {
|
||||
// Reject `#[derive("Debug")]`.
|
||||
report_unexpected_literal(sess, &lit);
|
||||
None
|
||||
}
|
||||
})
|
||||
.map(|meta| {
|
||||
// Reject `#[derive(Debug = "value", Debug(abc))]`, but recover the paths.
|
||||
report_path_args(sess, &meta);
|
||||
meta.path
|
||||
})
|
||||
.collect();
|
||||
attr.meta_item_list()
|
||||
.unwrap_or_default()
|
||||
.into_iter()
|
||||
.filter_map(|nested_meta| match nested_meta {
|
||||
NestedMetaItem::MetaItem(meta) => Some(meta),
|
||||
NestedMetaItem::Literal(lit) => {
|
||||
// Reject `#[derive("Debug")]`.
|
||||
report_unexpected_literal(sess, &lit);
|
||||
None
|
||||
}
|
||||
})
|
||||
.map(|meta| {
|
||||
// Reject `#[derive(Debug = "value", Debug(abc))]`, but recover the paths.
|
||||
report_path_args(sess, &meta);
|
||||
meta.path
|
||||
})
|
||||
.map(|path| (path, None))
|
||||
.collect()
|
||||
});
|
||||
|
||||
// FIXME: Try to cache intermediate results to avoid collecting same paths multiple times.
|
||||
match ecx.resolver.resolve_derives(ecx.current_expansion.id, derives, ecx.force_mode) {
|
||||
match result {
|
||||
Ok(()) => ExpandResult::Ready(cfg_eval(ecx, item)),
|
||||
Err(Indeterminate) => ExpandResult::Retry(item),
|
||||
}
|
||||
|
@ -1034,7 +1034,7 @@ impl<'a> MethodDef<'a> {
|
||||
// make a series of nested matches, to destructure the
|
||||
// structs. This is actually right-to-left, but it shouldn't
|
||||
// matter.
|
||||
for (arg_expr, pat) in self_args.iter().zip(patterns) {
|
||||
for (arg_expr, pat) in iter::zip(self_args, patterns) {
|
||||
body = cx.expr_match(
|
||||
trait_.span,
|
||||
arg_expr.clone(),
|
||||
@ -1351,7 +1351,7 @@ impl<'a> MethodDef<'a> {
|
||||
let mut discriminant_test = cx.expr_bool(sp, true);
|
||||
|
||||
let mut first_ident = None;
|
||||
for (&ident, self_arg) in vi_idents.iter().zip(&self_args) {
|
||||
for (&ident, self_arg) in iter::zip(&vi_idents, &self_args) {
|
||||
let self_addr = cx.expr_addr_of(sp, self_arg.clone());
|
||||
let variant_value =
|
||||
deriving::call_intrinsic(cx, sp, sym::discriminant_value, vec![self_addr]);
|
||||
@ -1571,9 +1571,7 @@ impl<'a> TraitDef<'a> {
|
||||
let subpats = self.create_subpatterns(cx, paths, mutbl, use_temporaries);
|
||||
let pattern = match *struct_def {
|
||||
VariantData::Struct(..) => {
|
||||
let field_pats = subpats
|
||||
.into_iter()
|
||||
.zip(&ident_exprs)
|
||||
let field_pats = iter::zip(subpats, &ident_exprs)
|
||||
.map(|(pat, &(sp, ident, ..))| {
|
||||
if ident.is_none() {
|
||||
cx.span_bug(sp, "a braced struct with unnamed fields in `derive`");
|
||||
|
@ -7,6 +7,7 @@
|
||||
#![feature(bool_to_option)]
|
||||
#![feature(crate_visibility_modifier)]
|
||||
#![feature(decl_macro)]
|
||||
#![feature(iter_zip)]
|
||||
#![feature(nll)]
|
||||
#![cfg_attr(bootstrap, feature(or_patterns))]
|
||||
#![feature(proc_macro_internals)]
|
||||
|
@ -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
|
@ -7,11 +7,18 @@ on:
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ${{ matrix.os }}
|
||||
timeout-minutes: 60
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
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:
|
||||
- uses: actions/checkout@v2
|
||||
@ -36,6 +43,12 @@ jobs:
|
||||
path: target
|
||||
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
|
||||
run: |
|
||||
git config --global user.email "user@example.com"
|
||||
@ -43,6 +56,8 @@ jobs:
|
||||
./prepare.sh
|
||||
|
||||
- name: Test
|
||||
env:
|
||||
TARGET_TRIPLE: ${{ matrix.env.TARGET_TRIPLE }}
|
||||
run: |
|
||||
# Enable backtraces for easier debugging
|
||||
export RUST_BACKTRACE=1
|
||||
@ -51,12 +66,16 @@ jobs:
|
||||
export COMPILE_RUNS=2
|
||||
export RUN_RUNS=2
|
||||
|
||||
# Enable extra checks
|
||||
export CG_CLIF_ENABLE_VERIFIER=1
|
||||
|
||||
./test.sh
|
||||
|
||||
- name: Package prebuilt cg_clif
|
||||
run: tar cvfJ cg_clif.tar.xz build
|
||||
|
||||
- name: Upload prebuilt cg_clif
|
||||
if: matrix.env.TARGET_TRIPLE != 'x86_64-pc-windows-gnu'
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: cg_clif-${{ runner.os }}
|
||||
|
82
compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml
vendored
Normal file
82
compiler/rustc_codegen_cranelift/.github/workflows/rustc.yml
vendored
Normal 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
|
@ -2,7 +2,7 @@
|
||||
// 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.assist.importMergeBehavior": "last",
|
||||
"rust-analyzer.cargo.loadOutDirsFromCheck": true,
|
||||
"rust-analyzer.cargo.runBuildScripts": true,
|
||||
"rust-analyzer.linkedProjects": [
|
||||
"./Cargo.toml",
|
||||
//"./build_sysroot/sysroot_src/src/libstd/Cargo.toml",
|
||||
|
@ -39,16 +39,16 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-bforest"
|
||||
version = "0.70.0"
|
||||
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058"
|
||||
version = "0.72.0"
|
||||
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#8e43e96410a14143d368273cf1e708f8094bb8e0"
|
||||
dependencies = [
|
||||
"cranelift-entity",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen"
|
||||
version = "0.70.0"
|
||||
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058"
|
||||
version = "0.72.0"
|
||||
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#8e43e96410a14143d368273cf1e708f8094bb8e0"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"cranelift-bforest",
|
||||
@ -65,8 +65,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen-meta"
|
||||
version = "0.70.0"
|
||||
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058"
|
||||
version = "0.72.0"
|
||||
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#8e43e96410a14143d368273cf1e708f8094bb8e0"
|
||||
dependencies = [
|
||||
"cranelift-codegen-shared",
|
||||
"cranelift-entity",
|
||||
@ -74,18 +74,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-codegen-shared"
|
||||
version = "0.70.0"
|
||||
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058"
|
||||
version = "0.72.0"
|
||||
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#8e43e96410a14143d368273cf1e708f8094bb8e0"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-entity"
|
||||
version = "0.70.0"
|
||||
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058"
|
||||
version = "0.72.0"
|
||||
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#8e43e96410a14143d368273cf1e708f8094bb8e0"
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-frontend"
|
||||
version = "0.70.0"
|
||||
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058"
|
||||
version = "0.72.0"
|
||||
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#8e43e96410a14143d368273cf1e708f8094bb8e0"
|
||||
dependencies = [
|
||||
"cranelift-codegen",
|
||||
"log",
|
||||
@ -95,8 +95,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-jit"
|
||||
version = "0.70.0"
|
||||
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058"
|
||||
version = "0.72.0"
|
||||
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#8e43e96410a14143d368273cf1e708f8094bb8e0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cranelift-codegen",
|
||||
@ -113,8 +113,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-module"
|
||||
version = "0.70.0"
|
||||
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058"
|
||||
version = "0.72.0"
|
||||
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#8e43e96410a14143d368273cf1e708f8094bb8e0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cranelift-codegen",
|
||||
@ -125,8 +125,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-native"
|
||||
version = "0.70.0"
|
||||
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058"
|
||||
version = "0.72.0"
|
||||
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#8e43e96410a14143d368273cf1e708f8094bb8e0"
|
||||
dependencies = [
|
||||
"cranelift-codegen",
|
||||
"target-lexicon",
|
||||
@ -134,8 +134,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cranelift-object"
|
||||
version = "0.70.0"
|
||||
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#cdb60ec5a9df087262ae8960a31067e88cd80058"
|
||||
version = "0.72.0"
|
||||
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#8e43e96410a14143d368273cf1e708f8094bb8e0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cranelift-codegen",
|
||||
|
@ -16,7 +16,7 @@ cranelift-jit = { git = "https://github.com/bytecodealliance/wasmtime/", branch
|
||||
cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime/", branch = "main" }
|
||||
target-lexicon = "0.11.0"
|
||||
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" }
|
||||
indexmap = "1.0.2"
|
||||
@ -75,3 +75,6 @@ debug = false
|
||||
[profile.release.package.syn]
|
||||
opt-level = 0
|
||||
debug = false
|
||||
|
||||
[package.metadata.rust-analyzer]
|
||||
rustc_private = true
|
||||
|
@ -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`).
|
||||
|
||||
### Cargo
|
||||
|
||||
In the directory with your project (where you can do the usual `cargo build`), run:
|
||||
|
||||
```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
|
||||
|
||||
> 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}", ' $@ ');';
|
||||
}
|
||||
```
|
||||
For additional ways to use rustc_codegen_cranelift like the JIT mode see [usage.md](docs/usage.md).
|
||||
|
||||
## 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
|
||||
|
||||
@ -106,3 +55,20 @@ function jit_calc() {
|
||||
`llvm_asm!` will remain unimplemented forever. `asm!` doesn't yet support reg classes. You
|
||||
have to specify specific registers instead.
|
||||
* 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.
|
||||
|
@ -55,6 +55,7 @@ ln target/$CHANNEL/*rustc_codegen_cranelift* "$target_dir"/lib
|
||||
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/$HOST_TRIPLE/lib/"
|
||||
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/"
|
||||
fi
|
||||
@ -64,12 +65,18 @@ case "$build_sysroot" in
|
||||
;;
|
||||
"llvm")
|
||||
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")
|
||||
echo "[BUILD] sysroot"
|
||||
dir=$(pwd)
|
||||
cd "$target_dir"
|
||||
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/
|
||||
;;
|
||||
*)
|
||||
|
@ -16,9 +16,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "adler"
|
||||
version = "0.2.3"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e"
|
||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-core",
|
||||
@ -110,9 +110,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.9.1"
|
||||
version = "0.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04"
|
||||
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
|
||||
dependencies = [
|
||||
"compiler_builtins",
|
||||
"rustc-std-workspace-alloc",
|
||||
@ -132,18 +132,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.86"
|
||||
version = "0.2.91"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c"
|
||||
checksum = "8916b1f6ca17130ec6568feccee27c156ad12037880833a3b842a823236502e7"
|
||||
dependencies = [
|
||||
"rustc-std-workspace-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.4.3"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0f2d26ec3309788e423cfbf68ad1800f061638098d76a83681af979dc4eda19d"
|
||||
checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b"
|
||||
dependencies = [
|
||||
"adler",
|
||||
"autocfg",
|
||||
|
@ -28,7 +28,7 @@ export __CARGO_DEFAULT_LIB_METADATA="cg_clif"
|
||||
if [[ "$1" != "--debug" ]]; then
|
||||
sysroot_channel='release'
|
||||
# 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
|
||||
sysroot_channel='debug'
|
||||
cargo build --target "$TARGET_TRIPLE"
|
||||
|
@ -8,5 +8,8 @@
|
||||
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>
|
||||
<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>
|
||||
|
66
compiler/rustc_codegen_cranelift/docs/usage.md
Normal file
66
compiler/rustc_codegen_cranelift/docs/usage.md
Normal 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}", ' $@ ');';
|
||||
}
|
||||
```
|
@ -621,6 +621,7 @@ struct PanicLocation {
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
#[cfg(not(windows))]
|
||||
pub fn get_tls() -> u8 {
|
||||
#[thread_local]
|
||||
static A: u8 = 42;
|
||||
|
@ -1,7 +1,4 @@
|
||||
#![feature(
|
||||
no_core, start, lang_items, box_syntax, never_type, linkage,
|
||||
extern_types, thread_local
|
||||
)]
|
||||
#![feature(no_core, lang_items, box_syntax, never_type, linkage, extern_types, thread_local)]
|
||||
#![no_core]
|
||||
#![allow(dead_code, non_camel_case_types)]
|
||||
|
||||
@ -239,7 +236,7 @@ fn main() {
|
||||
|
||||
assert_eq!(((|()| 42u8) as fn(()) -> u8)(()), 42);
|
||||
|
||||
#[cfg(not(jit))]
|
||||
#[cfg(not(any(jit, windows)))]
|
||||
{
|
||||
extern {
|
||||
#[linkage = "extern_weak"]
|
||||
@ -292,7 +289,7 @@ fn main() {
|
||||
|
||||
from_decimal_string();
|
||||
|
||||
#[cfg(not(jit))]
|
||||
#[cfg(not(any(jit, windows)))]
|
||||
test_tls();
|
||||
|
||||
#[cfg(all(not(jit), target_os = "linux"))]
|
||||
|
@ -1,7 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
|
||||
rustup component add rust-src rustc-dev llvm-tools-preview
|
||||
./build_sysroot/prepare_sysroot_src.sh
|
||||
cargo install hyperfine || echo "Skipping hyperfine install"
|
||||
|
||||
|
@ -1 +1,3 @@
|
||||
nightly-2021-03-05
|
||||
[toolchain]
|
||||
channel = "nightly-2021-03-29"
|
||||
components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
|
||||
|
@ -4,7 +4,7 @@ dir=$(dirname "$0")
|
||||
source "$dir/config.sh"
|
||||
|
||||
# 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
|
||||
shift || true
|
||||
|
@ -2,15 +2,7 @@
|
||||
|
||||
set -e
|
||||
|
||||
unamestr=$(uname)
|
||||
if [[ "$unamestr" == 'Linux' || "$unamestr" == 'FreeBSD' ]]; then
|
||||
dylib_ext='so'
|
||||
elif [[ "$unamestr" == 'Darwin' ]]; then
|
||||
dylib_ext='dylib'
|
||||
else
|
||||
echo "Unsupported os"
|
||||
exit 1
|
||||
fi
|
||||
dylib=$(echo "" | rustc --print file-names --crate-type dylib --crate-name rustc_codegen_cranelift -)
|
||||
|
||||
if echo "$RUSTC_WRAPPER" | grep sccache; then
|
||||
echo
|
||||
@ -24,10 +16,10 @@ dir=$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)
|
||||
export RUSTC=$dir"/bin/cg_clif"
|
||||
|
||||
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
|
||||
if [[ "$unamestr" == 'Darwin' ]]; then
|
||||
if [[ "$(uname)" == 'Darwin' ]]; then
|
||||
export RUSTFLAGS="$RUSTFLAGS -Clink-arg=-undefined -Clink-arg=dynamic_lookup"
|
||||
fi
|
||||
|
||||
|
@ -8,7 +8,7 @@ case $1 in
|
||||
|
||||
echo "=> Installing new nightly"
|
||||
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
|
||||
|
||||
echo "=> Uninstalling all old nighlies"
|
||||
|
68
compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh
Normal file
68
compiler/rustc_codegen_cranelift/scripts/setup_rust_fork.sh
Normal 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
|
@ -3,70 +3,10 @@ set -e
|
||||
|
||||
cd "$(dirname "$0")/../"
|
||||
|
||||
./build.sh
|
||||
source build/config.sh
|
||||
source ./scripts/setup_rust_fork.sh
|
||||
|
||||
echo "[TEST] Bootstrap of rustc"
|
||||
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"]
|
||||
EOF
|
||||
|
||||
rm -r compiler/rustc_codegen_cranelift/{Cargo.*,src}
|
||||
cp ../Cargo.* compiler/rustc_codegen_cranelift/
|
||||
cp -r ../src compiler/rustc_codegen_cranelift/src
|
||||
|
87
compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh
Executable file
87
compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh
Executable 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
|
@ -71,14 +71,20 @@ function base_sysroot_tests() {
|
||||
echo "[AOT] mod_bench"
|
||||
$MY_RUSTC example/mod_bench.rs --crate-type bin --target "$TARGET_TRIPLE"
|
||||
$RUN_WRAPPER ./target/out/mod_bench
|
||||
|
||||
pushd rand
|
||||
rm -r ./target || true
|
||||
../build/cargo.sh test --workspace
|
||||
popd
|
||||
}
|
||||
|
||||
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
|
||||
if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then
|
||||
echo "[BENCH COMPILE] ebobby/simple-raytracer"
|
||||
@ -92,27 +98,40 @@ function extended_sysroot_tests() {
|
||||
else
|
||||
echo "[BENCH COMPILE] ebobby/simple-raytracer (skipped)"
|
||||
echo "[COMPILE] ebobby/simple-raytracer"
|
||||
../cargo.sh build
|
||||
../build/cargo.sh build --target $TARGET_TRIPLE
|
||||
echo "[BENCH RUN] ebobby/simple-raytracer (skipped)"
|
||||
fi
|
||||
popd
|
||||
|
||||
pushd build_sysroot/sysroot_src/library/core/tests
|
||||
echo "[TEST] libcore"
|
||||
rm -r ./target || true
|
||||
../../../../../build/cargo.sh test
|
||||
cargo clean
|
||||
if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then
|
||||
../../../../../build/cargo.sh test
|
||||
else
|
||||
../../../../../build/cargo.sh build --target $TARGET_TRIPLE --tests
|
||||
fi
|
||||
popd
|
||||
|
||||
pushd regex
|
||||
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
|
||||
../build/cargo.sh build --example shootout-regex-dna
|
||||
cat examples/regexdna-input.txt | ../build/cargo.sh run --example shootout-regex-dna | grep -v "Spawned thread" > res.txt
|
||||
diff -u res.txt examples/regexdna-output.txt
|
||||
../build/cargo.sh build --example shootout-regex-dna --target $TARGET_TRIPLE
|
||||
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
|
||||
fi
|
||||
|
||||
echo "[TEST] rust-lang/regex tests"
|
||||
../build/cargo.sh test --tests -- --exclude-should-panic --test-threads 1 -Zunstable-options -q
|
||||
if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then
|
||||
echo "[TEST] rust-lang/regex tests"
|
||||
../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
|
||||
}
|
||||
|
||||
|
@ -11,9 +11,11 @@ use cranelift_codegen::entity::EntityRef;
|
||||
use crate::prelude::*;
|
||||
|
||||
pub(super) fn add_args_header_comment(fx: &mut FunctionCx<'_, '_, '_>) {
|
||||
fx.add_global_comment(
|
||||
"kind loc.idx param pass mode ty".to_string(),
|
||||
);
|
||||
if fx.clif_comments.enabled() {
|
||||
fx.add_global_comment(
|
||||
"kind loc.idx param pass mode ty".to_string(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn add_arg_comment<'tcx>(
|
||||
@ -25,6 +27,10 @@ pub(super) fn add_arg_comment<'tcx>(
|
||||
arg_abi_mode: PassMode,
|
||||
arg_layout: TyAndLayout<'tcx>,
|
||||
) {
|
||||
if !fx.clif_comments.enabled() {
|
||||
return;
|
||||
}
|
||||
|
||||
let local = if let Some(local) = local {
|
||||
Cow::Owned(format!("{:?}", local))
|
||||
} else {
|
||||
@ -59,10 +65,12 @@ pub(super) fn add_arg_comment<'tcx>(
|
||||
}
|
||||
|
||||
pub(super) fn add_locals_header_comment(fx: &mut FunctionCx<'_, '_, '_>) {
|
||||
fx.add_global_comment(String::new());
|
||||
fx.add_global_comment(
|
||||
"kind local ty size align (abi,pref)".to_string(),
|
||||
);
|
||||
if fx.clif_comments.enabled() {
|
||||
fx.add_global_comment(String::new());
|
||||
fx.add_global_comment(
|
||||
"kind local ty size align (abi,pref)".to_string(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn add_local_place_comments<'tcx>(
|
||||
@ -70,6 +78,9 @@ pub(super) fn add_local_place_comments<'tcx>(
|
||||
place: CPlace<'tcx>,
|
||||
local: Local,
|
||||
) {
|
||||
if !fx.clif_comments.enabled() {
|
||||
return;
|
||||
}
|
||||
let TyAndLayout { ty, layout } = place.layout();
|
||||
let rustc_target::abi::Layout { size, align, abi: _, variants: _, fields: _, largest_niche: _ } =
|
||||
layout;
|
||||
@ -90,7 +101,7 @@ pub(super) fn add_local_place_comments<'tcx>(
|
||||
} else {
|
||||
Cow::Borrowed("")
|
||||
};
|
||||
match ptr.base_and_offset() {
|
||||
match ptr.debug_base_and_offset() {
|
||||
(crate::pointer::PointerBase::Addr(addr), offset) => {
|
||||
("reuse", format!("storage={}{}{}", addr, offset, meta).into())
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
//! Handling of everything related to the calling convention. Also fills `fx.local_map`.
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
mod comments;
|
||||
mod pass_mode;
|
||||
mod returning;
|
||||
@ -75,8 +74,9 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
|
||||
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);
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
self.add_comment(func_ref, format!("{:?}", inst));
|
||||
if self.clif_comments.enabled() {
|
||||
self.add_comment(func_ref, format!("{:?}", inst));
|
||||
}
|
||||
|
||||
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_ref = self.cx.module.declare_func_in_func(func_id, &mut self.bcx.func);
|
||||
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));
|
||||
}
|
||||
let results = self.bcx.inst_results(call_inst);
|
||||
@ -149,7 +148,6 @@ fn make_local_place<'tcx>(
|
||||
CPlace::new_stack_slot(fx, layout)
|
||||
};
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
self::comments::add_local_place_comments(fx, place, local);
|
||||
|
||||
place
|
||||
@ -163,7 +161,6 @@ pub(crate) fn codegen_fn_prelude<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, start_
|
||||
|
||||
let ssa_analyzed = crate::analyze::analyze(fx);
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
self::comments::add_args_header_comment(fx);
|
||||
|
||||
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);
|
||||
assert!(block_params_iter.next().is_none(), "arg_value left behind");
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
self::comments::add_locals_header_comment(fx);
|
||||
|
||||
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())
|
||||
};
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
self::comments::add_local_place_comments(fx, 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 {
|
||||
// Trait object call
|
||||
Some(Instance { def: InstanceDef::Virtual(_, idx), .. }) => {
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
if fx.clif_comments.enabled() {
|
||||
let nop_inst = fx.bcx.ins().nop();
|
||||
fx.add_comment(
|
||||
nop_inst,
|
||||
@ -414,8 +408,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
|
||||
|
||||
// Indirect call
|
||||
None => {
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
if fx.clif_comments.enabled() {
|
||||
let nop_inst = fx.bcx.ins().nop();
|
||||
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
|
||||
if fn_sig.c_variadic {
|
||||
if !matches!(fn_sig.abi, Abi::C { .. }) {
|
||||
fx.tcx.sess.span_fatal(
|
||||
span,
|
||||
&format!("Variadic call for non-C abi {:?}", fn_sig.abi),
|
||||
);
|
||||
fx.tcx.sess.span_fatal(span, &format!("Variadic call for non-C abi {:?}", fn_sig.abi));
|
||||
}
|
||||
let sig_ref = fx.bcx.func.dfg.call_signature(call_inst).unwrap();
|
||||
let abi_params = call_args
|
||||
|
@ -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 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 {
|
||||
let val = ptr.offset_i64(fx, offset).store(
|
||||
fx,
|
||||
@ -248,8 +248,8 @@ pub(super) fn adjust_arg_for_abi<'tcx>(
|
||||
/// as necessary.
|
||||
pub(super) fn cvalue_for_param<'tcx>(
|
||||
fx: &mut FunctionCx<'_, '_, 'tcx>,
|
||||
#[cfg_attr(not(debug_assertions), allow(unused_variables))] local: Option<mir::Local>,
|
||||
#[cfg_attr(not(debug_assertions), allow(unused_variables))] local_field: Option<usize>,
|
||||
local: Option<mir::Local>,
|
||||
local_field: Option<usize>,
|
||||
arg_abi: &ArgAbi<'tcx, Ty<'tcx>>,
|
||||
block_params_iter: &mut impl Iterator<Item = Value>,
|
||||
) -> Option<CValue<'tcx>> {
|
||||
@ -263,7 +263,6 @@ pub(super) fn cvalue_for_param<'tcx>(
|
||||
})
|
||||
.collect::<SmallVec<[_; 2]>>();
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
crate::abi::comments::add_arg_comment(
|
||||
fx,
|
||||
"arg",
|
||||
|
@ -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(
|
||||
fx,
|
||||
"ret",
|
||||
@ -146,7 +142,7 @@ pub(super) fn codegen_with_call_return_arg<'tcx, T>(
|
||||
let results = fx
|
||||
.bcx
|
||||
.inst_results(call_inst)
|
||||
.into_iter()
|
||||
.iter()
|
||||
.copied()
|
||||
.collect::<SmallVec<[Value; 2]>>();
|
||||
let result =
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
use cranelift_codegen::binemit::{NullStackMapSink, NullTrapSink};
|
||||
use rustc_ast::expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS};
|
||||
use rustc_span::symbol::sym;
|
||||
|
||||
@ -92,7 +93,7 @@ fn codegen_inner(
|
||||
bcx.finalize();
|
||||
}
|
||||
module
|
||||
.define_function(func_id, &mut ctx, &mut cranelift_codegen::binemit::NullTrapSink {})
|
||||
.define_function(func_id, &mut ctx, &mut NullTrapSink {}, &mut NullStackMapSink {})
|
||||
.unwrap();
|
||||
unwind_context.add_function(func_id, &ctx, module.isa());
|
||||
}
|
||||
@ -132,7 +133,7 @@ fn codegen_inner(
|
||||
bcx.finalize();
|
||||
}
|
||||
module
|
||||
.define_function(func_id, &mut ctx, &mut cranelift_codegen::binemit::NullTrapSink {})
|
||||
.define_function(func_id, &mut ctx, &mut NullTrapSink {}, &mut NullStackMapSink {})
|
||||
.unwrap();
|
||||
unwind_context.add_function(func_id, &ctx, module.isa());
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
//! Codegen of a single function
|
||||
|
||||
use cranelift_codegen::binemit::{NullStackMapSink, NullTrapSink};
|
||||
use rustc_index::vec::IndexVec;
|
||||
use rustc_middle::ty::adjustment::PointerCast;
|
||||
use rustc_middle::ty::layout::FnAbiExt;
|
||||
@ -7,11 +8,7 @@ use rustc_target::abi::call::FnAbi;
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
pub(crate) fn codegen_fn<'tcx>(
|
||||
cx: &mut crate::CodegenCx<'_, 'tcx>,
|
||||
instance: Instance<'tcx>,
|
||||
linkage: Linkage,
|
||||
) {
|
||||
pub(crate) fn codegen_fn<'tcx>(cx: &mut crate::CodegenCx<'_, 'tcx>, instance: Instance<'tcx>) {
|
||||
let tcx = cx.tcx;
|
||||
|
||||
let _inst_guard =
|
||||
@ -23,7 +20,7 @@ pub(crate) fn codegen_fn<'tcx>(
|
||||
// Declare function
|
||||
let name = tcx.symbol_name(instance).name.to_string();
|
||||
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();
|
||||
|
||||
@ -131,7 +128,7 @@ pub(crate) fn codegen_fn<'tcx>(
|
||||
let module = &mut cx.module;
|
||||
tcx.sess.time("define function", || {
|
||||
module
|
||||
.define_function(func_id, context, &mut cranelift_codegen::binemit::NullTrapSink {})
|
||||
.define_function(func_id, context, &mut NullTrapSink {}, &mut NullStackMapSink {})
|
||||
.unwrap()
|
||||
});
|
||||
|
||||
@ -219,8 +216,7 @@ fn codegen_fn_content(fx: &mut FunctionCx<'_, '_, '_>) {
|
||||
codegen_stmt(fx, block, stmt);
|
||||
}
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
if fx.clif_comments.enabled() {
|
||||
let mut terminator_head = "\n".to_string();
|
||||
bb_data.terminator().kind.fmt_head(&mut terminator_head).unwrap();
|
||||
let inst = fx.bcx.func.layout.last_inst(block).unwrap();
|
||||
@ -433,12 +429,14 @@ fn codegen_stmt<'tcx>(
|
||||
|
||||
fx.set_debug_loc(stmt.source_info);
|
||||
|
||||
#[cfg(false_debug_assertions)]
|
||||
#[cfg(disabled)]
|
||||
match &stmt.kind {
|
||||
StatementKind::StorageLive(..) | StatementKind::StorageDead(..) => {} // Those are not very useful
|
||||
_ => {
|
||||
let inst = fx.bcx.func.layout.last_inst(cur_block).unwrap();
|
||||
fx.add_comment(inst, format!("{:?}", stmt));
|
||||
if fx.clif_comments.enabled() {
|
||||
let inst = fx.bcx.func.layout.last_inst(cur_block).unwrap();
|
||||
fx.add_comment(inst, format!("{:?}", stmt));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -464,16 +462,16 @@ fn codegen_stmt<'tcx>(
|
||||
let val = crate::constant::codegen_tls_ref(fx, def_id, lval.layout());
|
||||
lval.write_cvalue(fx, val);
|
||||
}
|
||||
Rvalue::BinaryOp(bin_op, box (ref lhs, ref rhs)) => {
|
||||
let lhs = codegen_operand(fx, lhs);
|
||||
let rhs = codegen_operand(fx, rhs);
|
||||
Rvalue::BinaryOp(bin_op, ref lhs_rhs) => {
|
||||
let lhs = codegen_operand(fx, &lhs_rhs.0);
|
||||
let rhs = codegen_operand(fx, &lhs_rhs.1);
|
||||
|
||||
let res = crate::num::codegen_binop(fx, bin_op, lhs, rhs);
|
||||
lval.write_cvalue(fx, res);
|
||||
}
|
||||
Rvalue::CheckedBinaryOp(bin_op, box (ref lhs, ref rhs)) => {
|
||||
let lhs = codegen_operand(fx, lhs);
|
||||
let rhs = codegen_operand(fx, rhs);
|
||||
Rvalue::CheckedBinaryOp(bin_op, ref lhs_rhs) => {
|
||||
let lhs = codegen_operand(fx, &lhs_rhs.0);
|
||||
let rhs = codegen_operand(fx, &lhs_rhs.1);
|
||||
|
||||
let res = if !fx.tcx.sess.overflow_checks() {
|
||||
let val =
|
||||
@ -659,7 +657,9 @@ fn codegen_stmt<'tcx>(
|
||||
.val
|
||||
.try_to_bits(fx.tcx.data_layout.pointer_size)
|
||||
.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);
|
||||
// FIXME use emit_small_memset where possible
|
||||
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::CopyNonOverlapping(box rustc_middle::mir::CopyNonOverlapping {
|
||||
src,
|
||||
dst,
|
||||
count,
|
||||
}) => {
|
||||
let dst = codegen_operand(fx, dst);
|
||||
StatementKind::CopyNonOverlapping(inner) => {
|
||||
let dst = codegen_operand(fx, &inner.dst);
|
||||
let pointee = dst
|
||||
.layout()
|
||||
.pointee_info_at(fx, rustc_target::abi::Size::ZERO)
|
||||
.expect("Expected pointer");
|
||||
.layout()
|
||||
.pointee_info_at(fx, rustc_target::abi::Size::ZERO)
|
||||
.expect("Expected pointer");
|
||||
let dst = dst.load_scalar(fx);
|
||||
let src = codegen_operand(fx, src).load_scalar(fx);
|
||||
let count = codegen_operand(fx, count).load_scalar(fx);
|
||||
let src = codegen_operand(fx, &inner.src).load_scalar(fx);
|
||||
let count = codegen_operand(fx, &inner.count).load_scalar(fx);
|
||||
let elem_size: u64 = pointee.size.bytes();
|
||||
let bytes = if elem_size != 1 {
|
||||
fx.bcx.ins().imul_imm(count, elem_size as i64)
|
||||
} else {
|
||||
count
|
||||
};
|
||||
let bytes =
|
||||
if elem_size != 1 { fx.bcx.ins().imul_imm(count, elem_size as i64) } else { count };
|
||||
fx.bcx.call_memcpy(fx.cx.module.target_config(), dst, src, bytes);
|
||||
}
|
||||
}
|
||||
|
@ -32,18 +32,56 @@ pub(crate) fn maybe_codegen<'tcx>(
|
||||
BinOp::Add | BinOp::Sub if !checked => None,
|
||||
BinOp::Mul if !checked => {
|
||||
let val_ty = if is_signed { fx.tcx.types.i128 } else { fx.tcx.types.u128 };
|
||||
Some(fx.easy_call("__multi3", &[lhs, rhs], val_ty))
|
||||
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))
|
||||
}
|
||||
}
|
||||
BinOp::Add | BinOp::Sub | BinOp::Mul => {
|
||||
assert!(checked);
|
||||
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 param_types = vec![
|
||||
AbiParam::special(pointer_ty(fx.tcx), ArgumentPurpose::StructReturn),
|
||||
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)];
|
||||
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::new(types::I128),
|
||||
AbiParam::new(types::I128),
|
||||
],
|
||||
[out_place.to_ptr().get_addr(fx), lhs.load_scalar(fx), rhs.load_scalar(fx)],
|
||||
)
|
||||
};
|
||||
let name = match (bin_op, is_signed) {
|
||||
(BinOp::Add, false) => "__rust_u128_addo",
|
||||
(BinOp::Add, true) => "__rust_i128_addo",
|
||||
@ -57,20 +95,33 @@ pub(crate) fn maybe_codegen<'tcx>(
|
||||
Some(out_place.to_cvalue(fx))
|
||||
}
|
||||
BinOp::Offset => unreachable!("offset should only be used on pointers, not 128bit ints"),
|
||||
BinOp::Div => {
|
||||
BinOp::Div | BinOp::Rem => {
|
||||
assert!(!checked);
|
||||
if is_signed {
|
||||
Some(fx.easy_call("__divti3", &[lhs, rhs], fx.tcx.types.i128))
|
||||
let name = match (bin_op, is_signed) {
|
||||
(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 {
|
||||
Some(fx.easy_call("__udivti3", &[lhs, rhs], fx.tcx.types.u128))
|
||||
}
|
||||
}
|
||||
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))
|
||||
Some(fx.easy_call(name, &[lhs, rhs], lhs.layout().ty))
|
||||
}
|
||||
}
|
||||
BinOp::Lt | BinOp::Le | BinOp::Eq | BinOp::Ge | BinOp::Gt | BinOp::Ne => {
|
||||
|
@ -361,8 +361,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
|
||||
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);
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
if self.clif_comments.enabled() {
|
||||
self.add_comment(local_msg_id, msg);
|
||||
}
|
||||
self.bcx.ins().global_value(self.pointer_type, local_msg_id)
|
||||
|
41
compiler/rustc_codegen_cranelift/src/compiler_builtins.rs
Normal file
41
compiler/rustc_codegen_cranelift/src/compiler_builtins.rs
Normal 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;
|
||||
}
|
@ -85,8 +85,9 @@ pub(crate) fn codegen_tls_ref<'tcx>(
|
||||
) -> CValue<'tcx> {
|
||||
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);
|
||||
#[cfg(debug_assertions)]
|
||||
fx.add_comment(local_data_id, format!("tls {:?}", def_id));
|
||||
if fx.clif_comments.enabled() {
|
||||
fx.add_comment(local_data_id, format!("tls {:?}", def_id));
|
||||
}
|
||||
let tls_ptr = fx.bcx.ins().tls_value(fx.pointer_type, local_data_id);
|
||||
CValue::by_val(tls_ptr, layout)
|
||||
}
|
||||
@ -98,8 +99,9 @@ fn codegen_static_ref<'tcx>(
|
||||
) -> CPlace<'tcx> {
|
||||
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);
|
||||
#[cfg(debug_assertions)]
|
||||
fx.add_comment(local_data_id, format!("{:?}", def_id));
|
||||
if fx.clif_comments.enabled() {
|
||||
fx.add_comment(local_data_id, format!("{:?}", def_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!(
|
||||
@ -122,7 +124,9 @@ pub(crate) fn codegen_constant<'tcx>(
|
||||
};
|
||||
let const_val = match 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!(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);
|
||||
let local_data_id =
|
||||
fx.cx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
|
||||
#[cfg(debug_assertions)]
|
||||
fx.add_comment(local_data_id, format!("{:?}", ptr.alloc_id));
|
||||
if fx.clif_comments.enabled() {
|
||||
fx.add_comment(local_data_id, format!("{:?}", ptr.alloc_id));
|
||||
}
|
||||
fx.bcx.ins().global_value(fx.pointer_type, local_data_id)
|
||||
}
|
||||
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 local_data_id =
|
||||
fx.cx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
|
||||
#[cfg(debug_assertions)]
|
||||
fx.add_comment(local_data_id, format!("{:?}", def_id));
|
||||
if fx.clif_comments.enabled() {
|
||||
fx.add_comment(local_data_id, format!("{:?}", def_id));
|
||||
}
|
||||
fx.bcx.ins().global_value(fx.pointer_type, local_data_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 local_data_id = fx.cx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
|
||||
#[cfg(debug_assertions)]
|
||||
fx.add_comment(local_data_id, format!("{:?}", alloc_id));
|
||||
if fx.clif_comments.enabled() {
|
||||
fx.add_comment(local_data_id, format!("{:?}", alloc_id));
|
||||
}
|
||||
let global_ptr = fx.bcx.ins().global_value(fx.pointer_type, local_data_id);
|
||||
crate::pointer::Pointer::new(global_ptr)
|
||||
}
|
||||
|
@ -39,11 +39,11 @@ fn osstr_as_utf8_bytes(path: &OsStr) -> &[u8] {
|
||||
#[cfg(unix)]
|
||||
{
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
return path.as_bytes();
|
||||
path.as_bytes()
|
||||
}
|
||||
#[cfg(not(unix))]
|
||||
{
|
||||
return path.to_str().unwrap().as_bytes();
|
||||
path.to_str().unwrap().as_bytes()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -119,11 +119,10 @@ fn module_codegen(
|
||||
tcx.sess.opts.debuginfo != DebugInfo::None,
|
||||
);
|
||||
super::predefine_mono_items(&mut cx, &mono_items);
|
||||
for (mono_item, (linkage, visibility)) in mono_items {
|
||||
let linkage = crate::linkage::get_clif_linkage(mono_item, linkage, visibility);
|
||||
for (mono_item, _) in mono_items {
|
||||
match mono_item {
|
||||
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) => {
|
||||
crate::constant::codegen_static(&mut cx.constants_cx, def_id)
|
||||
@ -163,6 +162,21 @@ pub(super) fn run_aot(
|
||||
metadata: EncodedMetadata,
|
||||
need_metadata_module: bool,
|
||||
) -> 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 cgus = if tcx.sess.opts.output_types.should_codegen() {
|
||||
@ -280,7 +294,7 @@ pub(super) fn run_aot(
|
||||
allocator_module,
|
||||
metadata_module,
|
||||
metadata,
|
||||
windows_subsystem: None, // Windows is not yet supported
|
||||
windows_subsystem,
|
||||
linker_info: LinkerInfo::new(tcx),
|
||||
crate_info: CrateInfo::new(tcx),
|
||||
},
|
||||
|
@ -5,8 +5,10 @@ use std::cell::RefCell;
|
||||
use std::ffi::CString;
|
||||
use std::os::raw::{c_char, c_int};
|
||||
|
||||
use cranelift_codegen::binemit::{NullStackMapSink, NullTrapSink};
|
||||
use rustc_codegen_ssa::CrateInfo;
|
||||
use rustc_middle::mir::mono::MonoItem;
|
||||
use rustc_session::config::EntryFnType;
|
||||
|
||||
use cranelift_jit::{JITBuilder, JITModule};
|
||||
|
||||
@ -28,20 +30,11 @@ pub(super) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! {
|
||||
let mut jit_builder =
|
||||
JITBuilder::with_isa(crate::build_isa(tcx.sess), cranelift_module::default_libcall_names());
|
||||
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);
|
||||
let mut jit_module = JITModule::new(jit_builder);
|
||||
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 mono_items = cgus
|
||||
.iter()
|
||||
@ -55,15 +48,12 @@ pub(super) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! {
|
||||
|
||||
super::time(tcx, "codegen mono items", || {
|
||||
super::predefine_mono_items(&mut cx, &mono_items);
|
||||
for (mono_item, (linkage, visibility)) in mono_items {
|
||||
let linkage = crate::linkage::get_clif_linkage(mono_item, linkage, visibility);
|
||||
for (mono_item, _) in mono_items {
|
||||
match mono_item {
|
||||
MonoItem::Fn(inst) => match backend_config.codegen_mode {
|
||||
CodegenMode::Aot => unreachable!(),
|
||||
CodegenMode::Jit => {
|
||||
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));
|
||||
}
|
||||
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");
|
||||
}
|
||||
|
||||
crate::main_shim::maybe_create_entry_wrapper(tcx, &mut jit_module, &mut unwind_context);
|
||||
crate::allocator::codegen(tcx, &mut jit_module, &mut unwind_context);
|
||||
|
||||
tcx.sess.abort_if_errors();
|
||||
|
||||
jit_module.finalize_definitions();
|
||||
|
||||
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!(
|
||||
"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::iter::once(&*tcx.crate_name(LOCAL_CRATE).as_str().to_string())
|
||||
.chain(args.split(' '))
|
||||
@ -118,12 +101,58 @@ pub(super) fn run_jit(tcx: TyCtxt<'_>, backend_config: BackendConfig) -> ! {
|
||||
BACKEND_CONFIG.with(|tls_backend_config| {
|
||||
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 ret = f(args.len() as c_int, argv.as_ptr());
|
||||
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);
|
||||
|
||||
std::process::exit(ret);
|
||||
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());
|
||||
std::process::exit(ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[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();
|
||||
|
||||
let mut cx = crate::CodegenCx::new(tcx, backend_config, jit_module, false);
|
||||
tcx.sess
|
||||
.time("codegen fn", || crate::base::codegen_fn(&mut cx, instance, Linkage::Export));
|
||||
tcx.sess.time("codegen fn", || crate::base::codegen_fn(&mut cx, instance));
|
||||
|
||||
let (global_asm, _debug_context, unwind_context) = cx.finalize();
|
||||
assert!(global_asm.is_empty());
|
||||
@ -220,7 +248,7 @@ fn load_imported_symbols_for_jit(tcx: TyCtxt<'_>) -> Vec<(String, *const u8)> {
|
||||
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 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(
|
||||
func_id,
|
||||
&mut Context::for_function(trampoline),
|
||||
&mut cranelift_codegen::binemit::NullTrapSink {},
|
||||
&mut NullTrapSink {},
|
||||
&mut NullStackMapSink {},
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
@ -44,13 +44,19 @@ fn predefine_mono_items<'tcx>(
|
||||
mono_items: &[(MonoItem<'tcx>, (RLinkage, Visibility))],
|
||||
) {
|
||||
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 {
|
||||
match mono_item {
|
||||
MonoItem::Fn(instance) => {
|
||||
let name = cx.tcx.symbol_name(instance).name.to_string();
|
||||
let _inst_guard = crate::PrintOnPanic(|| format!("{:?} {}", instance, name));
|
||||
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();
|
||||
}
|
||||
MonoItem::Static(_) | MonoItem::GlobalAsm(_) => {}
|
||||
|
@ -20,6 +20,10 @@ pub(crate) fn codegen_inline_asm<'tcx>(
|
||||
if template.is_empty() {
|
||||
// Black box
|
||||
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);
|
||||
@ -193,8 +197,9 @@ fn call_inline_asm<'tcx>(
|
||||
offset: None,
|
||||
size: u32::try_from(slot_size.bytes()).unwrap(),
|
||||
});
|
||||
#[cfg(debug_assertions)]
|
||||
fx.add_comment(stack_slot, "inline asm scratch slot");
|
||||
if fx.clif_comments.enabled() {
|
||||
fx.add_comment(stack_slot, "inline asm scratch slot");
|
||||
}
|
||||
|
||||
let inline_asm_func = fx
|
||||
.cx
|
||||
@ -210,8 +215,9 @@ fn call_inline_asm<'tcx>(
|
||||
)
|
||||
.unwrap();
|
||||
let inline_asm_func = fx.cx.module.declare_func_in_func(inline_asm_func, &mut fx.bcx.func);
|
||||
#[cfg(debug_assertions)]
|
||||
fx.add_comment(inline_asm_func, asm_name);
|
||||
if fx.clif_comments.enabled() {
|
||||
fx.add_comment(inline_asm_func, asm_name);
|
||||
}
|
||||
|
||||
for (_reg, offset, value) in inputs {
|
||||
fx.bcx.ins().stack_store(value, stack_slot, i32::try_from(offset.bytes()).unwrap());
|
||||
|
@ -88,7 +88,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
|
||||
let idx_bytes = match idx_const {
|
||||
ConstValue::ByRef { alloc, 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()
|
||||
}
|
||||
_ => unreachable!("{:?}", idx_const),
|
||||
|
@ -1,13 +1,4 @@
|
||||
#![feature(
|
||||
rustc_private,
|
||||
decl_macro,
|
||||
type_alias_impl_trait,
|
||||
associated_type_bounds,
|
||||
never_type,
|
||||
try_blocks,
|
||||
box_patterns,
|
||||
hash_drain_filter
|
||||
)]
|
||||
#![feature(rustc_private, decl_macro, never_type, hash_drain_filter)]
|
||||
#![warn(rust_2018_idioms)]
|
||||
#![warn(unused_lifetimes)]
|
||||
#![warn(unreachable_pub)]
|
||||
@ -57,6 +48,7 @@ mod base;
|
||||
mod cast;
|
||||
mod codegen_i128;
|
||||
mod common;
|
||||
mod compiler_builtins;
|
||||
mod constant;
|
||||
mod debuginfo;
|
||||
mod discriminant;
|
||||
@ -224,8 +216,10 @@ pub struct CraneliftCodegenBackend {
|
||||
|
||||
impl CodegenBackend for CraneliftCodegenBackend {
|
||||
fn init(&self, sess: &Session) {
|
||||
if sess.lto() != rustc_session::config::Lto::No && sess.opts.cg.embed_bitcode {
|
||||
sess.warn("LTO is not supported. You may get a linker error.");
|
||||
use rustc_session::config::Lto;
|
||||
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![]
|
||||
}
|
||||
|
||||
fn codegen_crate<'tcx>(
|
||||
fn codegen_crate(
|
||||
&self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
tcx: TyCtxt<'_>,
|
||||
metadata: EncodedMetadata,
|
||||
need_metadata_module: bool,
|
||||
) -> Box<dyn Any> {
|
||||
@ -252,9 +246,7 @@ impl CodegenBackend for CraneliftCodegenBackend {
|
||||
BackendConfig::from_opts(&tcx.sess.opts.cg.llvm_args)
|
||||
.unwrap_or_else(|err| tcx.sess.fatal(&err))
|
||||
};
|
||||
let res = driver::codegen_crate(tcx, metadata, need_metadata_module, config);
|
||||
|
||||
res
|
||||
driver::codegen_crate(tcx, metadata, need_metadata_module, config)
|
||||
}
|
||||
|
||||
fn join_codegen(
|
||||
@ -300,9 +292,9 @@ fn build_isa(sess: &Session) -> Box<dyn isa::TargetIsa + 'static> {
|
||||
let mut flags_builder = settings::builder();
|
||||
flags_builder.enable("is_pic").unwrap();
|
||||
flags_builder.set("enable_probestack", "false").unwrap(); // __cranelift_probestack is not provided
|
||||
flags_builder
|
||||
.set("enable_verifier", if cfg!(debug_assertions) { "true" } else { "false" })
|
||||
.unwrap();
|
||||
let enable_verifier =
|
||||
cfg!(debug_assertions) || std::env::var("CG_CLIF_ENABLE_VERIFIER").is_ok();
|
||||
flags_builder.set("enable_verifier", if enable_verifier { "true" } else { "false" }).unwrap();
|
||||
|
||||
let tls_model = match target_triple.binary_format {
|
||||
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_llvm_abi_extensions", "true").unwrap();
|
||||
|
||||
use rustc_session::config::OptLevel;
|
||||
match sess.opts.optimize {
|
||||
OptLevel::No => {
|
||||
flags_builder.set("opt_level", "none").unwrap();
|
||||
}
|
||||
OptLevel::Less | OptLevel::Default => {}
|
||||
OptLevel::Aggressive => {
|
||||
OptLevel::Size | OptLevel::SizeMin | OptLevel::Aggressive => {
|
||||
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);
|
||||
|
@ -6,8 +6,10 @@ pub(crate) fn get_clif_linkage(
|
||||
mono_item: MonoItem<'_>,
|
||||
linkage: RLinkage,
|
||||
visibility: Visibility,
|
||||
is_compiler_builtins: bool,
|
||||
) -> Linkage {
|
||||
match (linkage, visibility) {
|
||||
(RLinkage::External, Visibility::Default) if is_compiler_builtins => Linkage::Hidden,
|
||||
(RLinkage::External, Visibility::Default) => Linkage::Export,
|
||||
(RLinkage::Internal, Visibility::Default) => Linkage::Local,
|
||||
(RLinkage::External, Visibility::Hidden) => Linkage::Hidden,
|
||||
|
@ -1,3 +1,4 @@
|
||||
use cranelift_codegen::binemit::{NullStackMapSink, NullTrapSink};
|
||||
use rustc_hir::LangItem;
|
||||
use rustc_session::config::EntryFnType;
|
||||
|
||||
@ -100,12 +101,8 @@ pub(crate) fn maybe_create_entry_wrapper(
|
||||
bcx.seal_all_blocks();
|
||||
bcx.finalize();
|
||||
}
|
||||
m.define_function(
|
||||
cmain_func_id,
|
||||
&mut ctx,
|
||||
&mut cranelift_codegen::binemit::NullTrapSink {},
|
||||
)
|
||||
.unwrap();
|
||||
m.define_function(cmain_func_id, &mut ctx, &mut NullTrapSink {}, &mut NullStackMapSink {})
|
||||
.unwrap();
|
||||
unwind_context.add_function(cmain_func_id, &ctx, m.isa());
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
//! Reading and writing of the rustc metadata for rlibs and dylibs
|
||||
|
||||
use std::convert::TryFrom;
|
||||
use std::fs::File;
|
||||
use std::path::Path;
|
||||
|
||||
use rustc_codegen_ssa::METADATA_FILENAME;
|
||||
use rustc_data_structures::memmap::Mmap;
|
||||
use rustc_data_structures::owning_ref::OwningRef;
|
||||
use rustc_data_structures::rustc_erase_owner;
|
||||
use rustc_data_structures::sync::MetadataRef;
|
||||
@ -17,38 +17,43 @@ use crate::backend::WriteMetadata;
|
||||
|
||||
pub(crate) struct CraneliftMetadataLoader;
|
||||
|
||||
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 { Mmap::map(file) }.map_err(|e| format!("{:?}", e))?;
|
||||
let metadata = OwningRef::new(data).try_map(f)?;
|
||||
return Ok(rustc_erase_owner!(metadata.map_owner_box()));
|
||||
}
|
||||
|
||||
impl MetadataLoader for CraneliftMetadataLoader {
|
||||
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))?);
|
||||
// Iterate over all entries in the archive:
|
||||
while let Some(entry_result) = archive.next_entry() {
|
||||
let mut entry = entry_result.map_err(|e| format!("{:?}", e))?;
|
||||
if entry.header().identifier() == METADATA_FILENAME.as_bytes() {
|
||||
let mut buf = Vec::with_capacity(
|
||||
usize::try_from(entry.header().size())
|
||||
.expect("Rlib metadata file too big to load into memory."),
|
||||
);
|
||||
::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()));
|
||||
}
|
||||
}
|
||||
load_metadata_with(path, |data| {
|
||||
let archive = object::read::archive::ArchiveFile::parse(&*data)
|
||||
.map_err(|e| format!("{:?}", e))?;
|
||||
|
||||
Err("couldn't find metadata entry".to_string())
|
||||
for entry_result in archive.members() {
|
||||
let entry = entry_result.map_err(|e| format!("{:?}", e))?;
|
||||
if entry.name() == METADATA_FILENAME.as_bytes() {
|
||||
return Ok(entry.data());
|
||||
}
|
||||
}
|
||||
|
||||
Err("couldn't find metadata entry".to_string())
|
||||
})
|
||||
}
|
||||
|
||||
fn get_dylib_metadata(&self, _target: &Target, path: &Path) -> Result<MetadataRef, String> {
|
||||
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))?;
|
||||
let buf = file
|
||||
.section_by_name(".rustc")
|
||||
.ok_or("no .rustc section")?
|
||||
.data()
|
||||
.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()))
|
||||
|
||||
load_metadata_with(path, |data| {
|
||||
let file = object::File::parse(&data).map_err(|e| format!("parse: {:?}", e))?;
|
||||
file.section_by_name(".rustc")
|
||||
.ok_or("no .rustc section")?
|
||||
.data()
|
||||
.map_err(|e| format!("failed to read .rustc section: {:?}", e))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -166,13 +166,11 @@ pub(crate) fn codegen_int_binop<'tcx>(
|
||||
BinOp::Shl => {
|
||||
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 = clif_intcast(fx, actual_shift, types::I8, false);
|
||||
fx.bcx.ins().ishl(lhs, actual_shift)
|
||||
}
|
||||
BinOp::Shr => {
|
||||
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 = clif_intcast(fx, actual_shift, types::I8, false);
|
||||
if signed {
|
||||
fx.bcx.ins().sshr(lhs, actual_shift)
|
||||
} else {
|
||||
@ -387,7 +385,7 @@ pub(crate) fn codegen_ptr_binop<'tcx>(
|
||||
let lhs = in_lhs.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 => {
|
||||
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 base_val = base.load_scalar(fx);
|
||||
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),
|
||||
};
|
||||
}
|
||||
} else {
|
||||
let (lhs_ptr, lhs_extra) = in_lhs.load_scalar_pair(fx);
|
||||
let (rhs_ptr, rhs_extra) = in_rhs.load_scalar_pair(fx);
|
||||
|
@ -181,7 +181,6 @@ impl<'a> OptimizeContext<'a> {
|
||||
|
||||
pub(super) fn optimize_function(
|
||||
ctx: &mut Context,
|
||||
#[cfg_attr(not(debug_assertions), allow(unused_variables))]
|
||||
clif_comments: &mut crate::pretty_clif::CommentWriter,
|
||||
) {
|
||||
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);
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
if clif_comments.enabled() {
|
||||
for (&OrdStackSlot(stack_slot), usage) in &opt_ctx.stack_slot_usage_map {
|
||||
clif_comments.add_comment(stack_slot, format!("used by: {:?}", usage));
|
||||
}
|
||||
@ -209,25 +207,27 @@ pub(super) fn optimize_function(
|
||||
for load in users.stack_load.clone().into_iter() {
|
||||
let potential_stores = users.potential_stores_for_load(&opt_ctx.ctx, load);
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
for &store in &potential_stores {
|
||||
clif_comments.add_comment(
|
||||
load,
|
||||
format!(
|
||||
"Potential store -> load forwarding {} -> {} ({:?}, {:?})",
|
||||
opt_ctx.ctx.func.dfg.display_inst(store, None),
|
||||
opt_ctx.ctx.func.dfg.display_inst(load, None),
|
||||
spatial_overlap(&opt_ctx.ctx.func, store, load),
|
||||
temporal_order(&opt_ctx.ctx, store, load),
|
||||
),
|
||||
);
|
||||
if clif_comments.enabled() {
|
||||
for &store in &potential_stores {
|
||||
clif_comments.add_comment(
|
||||
load,
|
||||
format!(
|
||||
"Potential store -> load forwarding {} -> {} ({:?}, {:?})",
|
||||
opt_ctx.ctx.func.dfg.display_inst(store, None),
|
||||
opt_ctx.ctx.func.dfg.display_inst(load, None),
|
||||
spatial_overlap(&opt_ctx.ctx.func, store, load),
|
||||
temporal_order(&opt_ctx.ctx, store, load),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
match *potential_stores {
|
||||
[] => {
|
||||
#[cfg(debug_assertions)]
|
||||
clif_comments
|
||||
.add_comment(load, "[BUG?] Reading uninitialized memory".to_string());
|
||||
if clif_comments.enabled() {
|
||||
clif_comments
|
||||
.add_comment(load, "[BUG?] Reading uninitialized memory".to_string());
|
||||
}
|
||||
}
|
||||
[store]
|
||||
if spatial_overlap(&opt_ctx.ctx.func, store, load) == SpatialOverlap::Full
|
||||
@ -237,9 +237,12 @@ pub(super) fn optimize_function(
|
||||
// Only one store could have been the origin of the value.
|
||||
let stored_value = opt_ctx.ctx.func.dfg.inst_args(store)[0];
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
clif_comments
|
||||
.add_comment(load, format!("Store to load forward {} -> {}", store, load));
|
||||
if clif_comments.enabled() {
|
||||
clif_comments.add_comment(
|
||||
load,
|
||||
format!("Store to load forward {} -> {}", store, load),
|
||||
);
|
||||
}
|
||||
|
||||
users.change_load_to_alias(&mut opt_ctx.ctx.func, load, stored_value);
|
||||
}
|
||||
@ -250,33 +253,35 @@ pub(super) fn optimize_function(
|
||||
for store in users.stack_store.clone().into_iter() {
|
||||
let potential_loads = users.potential_loads_of_store(&opt_ctx.ctx, store);
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
for &load in &potential_loads {
|
||||
clif_comments.add_comment(
|
||||
store,
|
||||
format!(
|
||||
"Potential load from store {} <- {} ({:?}, {:?})",
|
||||
opt_ctx.ctx.func.dfg.display_inst(load, None),
|
||||
opt_ctx.ctx.func.dfg.display_inst(store, None),
|
||||
spatial_overlap(&opt_ctx.ctx.func, store, load),
|
||||
temporal_order(&opt_ctx.ctx, store, load),
|
||||
),
|
||||
);
|
||||
if clif_comments.enabled() {
|
||||
for &load in &potential_loads {
|
||||
clif_comments.add_comment(
|
||||
store,
|
||||
format!(
|
||||
"Potential load from store {} <- {} ({:?}, {:?})",
|
||||
opt_ctx.ctx.func.dfg.display_inst(load, None),
|
||||
opt_ctx.ctx.func.dfg.display_inst(store, None),
|
||||
spatial_overlap(&opt_ctx.ctx.func, store, load),
|
||||
temporal_order(&opt_ctx.ctx, store, load),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if potential_loads.is_empty() {
|
||||
// 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.
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
clif_comments.add_comment(
|
||||
store,
|
||||
format!(
|
||||
"Remove dead stack store {} of {}",
|
||||
opt_ctx.ctx.func.dfg.display_inst(store, None),
|
||||
stack_slot.0
|
||||
),
|
||||
);
|
||||
if clif_comments.enabled() {
|
||||
clif_comments.add_comment(
|
||||
store,
|
||||
format!(
|
||||
"Remove dead stack store {} of {}",
|
||||
opt_ctx.ctx.func.dfg.display_inst(store, None),
|
||||
stack_slot.0
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
users.remove_dead_store(&mut opt_ctx.ctx.func, store);
|
||||
}
|
||||
|
@ -39,8 +39,7 @@ impl Pointer {
|
||||
Pointer { base: PointerBase::Dangling(align), offset: Offset32::new(0) }
|
||||
}
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
pub(crate) fn base_and_offset(self) -> (PointerBase, Offset32) {
|
||||
pub(crate) fn debug_base_and_offset(self) -> (PointerBase, Offset32) {
|
||||
(self.base, self.offset)
|
||||
}
|
||||
|
||||
|
@ -69,13 +69,15 @@ use crate::prelude::*;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct CommentWriter {
|
||||
enabled: bool,
|
||||
global_comments: Vec<String>,
|
||||
entity_comments: FxHashMap<AnyEntity, String>,
|
||||
}
|
||||
|
||||
impl CommentWriter {
|
||||
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![
|
||||
format!("symbol {}", tcx.symbol_name(instance).name),
|
||||
format!("instance {:?}", instance),
|
||||
@ -86,13 +88,17 @@ impl CommentWriter {
|
||||
vec![]
|
||||
};
|
||||
|
||||
CommentWriter { global_comments, entity_comments: FxHashMap::default() }
|
||||
CommentWriter { enabled, global_comments, entity_comments: FxHashMap::default() }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
impl CommentWriter {
|
||||
pub(crate) fn enabled(&self) -> bool {
|
||||
self.enabled
|
||||
}
|
||||
|
||||
pub(crate) fn add_global_comment<S: Into<String>>(&mut self, comment: S) {
|
||||
debug_assert!(self.enabled);
|
||||
self.global_comments.push(comment.into());
|
||||
}
|
||||
|
||||
@ -101,6 +107,8 @@ impl CommentWriter {
|
||||
entity: E,
|
||||
comment: S,
|
||||
) {
|
||||
debug_assert!(self.enabled);
|
||||
|
||||
use std::collections::hash_map::Entry;
|
||||
match self.entity_comments.entry(entity.into()) {
|
||||
Entry::Occupied(mut occ) => {
|
||||
@ -179,7 +187,6 @@ impl FuncWriter for &'_ CommentWriter {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
impl FunctionCx<'_, '_, '_> {
|
||||
pub(crate) fn add_global_comment<S: Into<String>>(&mut self, comment: S) {
|
||||
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)
|
||||
}
|
||||
|
||||
pub(crate) fn write_ir_file<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
pub(crate) fn write_ir_file(
|
||||
tcx: TyCtxt<'_>,
|
||||
name: &str,
|
||||
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 res: std::io::Result<()> = try {
|
||||
let mut file = std::fs::File::create(clif_file_name)?;
|
||||
write(&mut file)?;
|
||||
};
|
||||
let res = std::fs::File::create(clif_file_name).and_then(|mut file| write(&mut file));
|
||||
if let Err(err) = res {
|
||||
tcx.sess.warn(&format!("error writing ir file: {}", err));
|
||||
}
|
||||
|
@ -17,8 +17,7 @@ fn codegen_print(fx: &mut FunctionCx<'_, '_, '_>, msg: &str) {
|
||||
)
|
||||
.unwrap();
|
||||
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");
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
use crate::prelude::*;
|
||||
|
||||
use cranelift_codegen::entity::EntityRef;
|
||||
use cranelift_codegen::ir::immediates::Offset32;
|
||||
|
||||
fn codegen_field<'tcx>(
|
||||
@ -414,7 +413,7 @@ impl<'tcx> CPlace<'tcx> {
|
||||
self,
|
||||
fx: &mut FunctionCx<'_, '_, 'tcx>,
|
||||
from: CValue<'tcx>,
|
||||
#[cfg_attr(not(debug_assertions), allow(unused_variables))] method: &'static str,
|
||||
method: &'static str,
|
||||
) {
|
||||
fn transmute_value<'tcx>(
|
||||
fx: &mut FunctionCx<'_, '_, 'tcx>,
|
||||
@ -462,8 +461,7 @@ impl<'tcx> CPlace<'tcx> {
|
||||
|
||||
assert_eq!(self.layout().size, from.layout().size);
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
if fx.clif_comments.enabled() {
|
||||
use cranelift_codegen::cursor::{Cursor, CursorPosition};
|
||||
let cur_block = match fx.bcx.cursor().position() {
|
||||
CursorPosition::After(block) => block,
|
||||
@ -707,6 +705,19 @@ pub(crate) fn assert_assignable<'tcx>(
|
||||
}
|
||||
// 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!(
|
||||
from_ty, to_ty,
|
||||
|
@ -14,7 +14,7 @@ use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_hir as hir;
|
||||
use rustc_middle::ty::layout::TyAndLayout;
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_span::{Pos, Span};
|
||||
use rustc_span::{Pos, Span, Symbol};
|
||||
use rustc_target::abi::*;
|
||||
use rustc_target::asm::*;
|
||||
|
||||
@ -125,15 +125,39 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
|
||||
|
||||
// Collect the types of output operands
|
||||
let mut constraints = vec![];
|
||||
let mut clobbers = vec![];
|
||||
let mut output_types = vec![];
|
||||
let mut op_idx = FxHashMap::default();
|
||||
for (idx, op) in operands.iter().enumerate() {
|
||||
match *op {
|
||||
InlineAsmOperandRef::Out { reg, late, place } => {
|
||||
let is_target_supported = |reg_class: InlineAsmRegClass| {
|
||||
for &(_, feature) in reg_class.supported_types(asm_arch) {
|
||||
if let Some(feature) = feature {
|
||||
if self.tcx.sess.target_features.contains(&Symbol::intern(feature))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
// Register class is unconditionally supported
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
};
|
||||
|
||||
let mut layout = None;
|
||||
let ty = if let Some(ref place) = place {
|
||||
layout = Some(&place.layout);
|
||||
llvm_fixup_output_type(self.cx, reg.reg_class(), &place.layout)
|
||||
} else if !is_target_supported(reg.reg_class()) {
|
||||
// We turn discarded outputs into clobber constraints
|
||||
// if the target feature needed by the register class is
|
||||
// disabled. This is necessary otherwise LLVM will try
|
||||
// to actually allocate a register for the dummy output.
|
||||
assert!(matches!(reg, InlineAsmRegOrRegClass::Reg(_)));
|
||||
clobbers.push(format!("~{}", reg_to_llvm(reg, None)));
|
||||
continue;
|
||||
} else {
|
||||
// If the output is discarded, we don't really care what
|
||||
// type is used. We're just using this to tell LLVM to
|
||||
@ -244,6 +268,7 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
constraints.append(&mut clobbers);
|
||||
if !options.contains(InlineAsmOptions::PRESERVES_FLAGS) {
|
||||
match asm_arch {
|
||||
InlineAsmArch::AArch64 | InlineAsmArch::Arm => {
|
||||
|
@ -11,9 +11,9 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
|
||||
use rustc_middle::ty::layout::HasTyCtxt;
|
||||
use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::ty::{self, TyCtxt};
|
||||
use rustc_session::config::{OptLevel, SanitizerSet};
|
||||
use rustc_session::config::OptLevel;
|
||||
use rustc_session::Session;
|
||||
use rustc_target::spec::StackProbeType;
|
||||
use rustc_target::spec::{SanitizerSet, StackProbeType};
|
||||
|
||||
use crate::attributes;
|
||||
use crate::llvm::AttributePlace::Function;
|
||||
@ -254,6 +254,7 @@ pub fn from_fn_attrs(cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, instance: ty::
|
||||
attributes::emit_uwtable(llfn, true);
|
||||
}
|
||||
|
||||
// FIXME: none of these three functions interact with source level attributes.
|
||||
set_frame_pointer_elimination(cx, llfn);
|
||||
set_instrument_function(cx, llfn);
|
||||
set_probestack(cx, llfn);
|
||||
@ -279,6 +280,9 @@ pub fn from_fn_attrs(cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, instance: ty::
|
||||
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::CMSE_NONSECURE_ENTRY) {
|
||||
llvm::AddFunctionAttrString(llfn, Function, cstr!("cmse_nonsecure_entry"));
|
||||
}
|
||||
if let Some(align) = codegen_fn_attrs.alignment {
|
||||
llvm::set_alignment(llfn, align as usize);
|
||||
}
|
||||
sanitize(cx, codegen_fn_attrs.no_sanitize, llfn);
|
||||
|
||||
// Always annotate functions with the target-cpu they are compiled for.
|
||||
@ -317,7 +321,7 @@ pub fn from_fn_attrs(cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, instance: ty::
|
||||
// Note that currently the `wasm-import-module` doesn't do anything, but
|
||||
// eventually LLVM 7 should read this and ferry the appropriate import
|
||||
// module to the output file.
|
||||
if cx.tcx.sess.target.arch == "wasm32" {
|
||||
if cx.tcx.sess.target.is_like_wasm {
|
||||
if let Some(module) = wasm_import_module(cx.tcx, instance.def_id()) {
|
||||
llvm::AddFunctionAttrStringValue(
|
||||
llfn,
|
||||
|
@ -24,6 +24,7 @@ use tracing::{debug, info};
|
||||
use std::ffi::{CStr, CString};
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
use std::iter;
|
||||
use std::path::Path;
|
||||
use std::ptr;
|
||||
use std::slice;
|
||||
@ -916,9 +917,7 @@ impl ThinLTOKeysMap {
|
||||
modules: &[llvm::ThinLTOModule],
|
||||
names: &[CString],
|
||||
) -> Self {
|
||||
let keys = modules
|
||||
.iter()
|
||||
.zip(names.iter())
|
||||
let keys = iter::zip(modules, names)
|
||||
.map(|(module, name)| {
|
||||
let key = build_string(|rust_str| unsafe {
|
||||
llvm::LLVMRustComputeLTOCacheKey(rust_str, module.identifier, data.0);
|
||||
|
@ -23,11 +23,11 @@ use rustc_fs_util::{link_or_copy, path_to_c_string};
|
||||
use rustc_hir::def_id::LOCAL_CRATE;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::config::{self, Lto, OutputType, Passes, SanitizerSet, SwitchWithOptPath};
|
||||
use rustc_session::config::{self, Lto, OutputType, Passes, SwitchWithOptPath};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::symbol::sym;
|
||||
use rustc_span::InnerSpan;
|
||||
use rustc_target::spec::{CodeModel, RelocModel, SplitDebuginfo};
|
||||
use rustc_target::spec::{CodeModel, RelocModel, SanitizerSet, SplitDebuginfo};
|
||||
use tracing::debug;
|
||||
|
||||
use libc::{c_char, c_int, c_uint, c_void, size_t};
|
||||
@ -170,10 +170,7 @@ pub fn target_machine_factory(
|
||||
// On the wasm target once the `atomics` feature is enabled that means that
|
||||
// we're no longer single-threaded, or otherwise we don't want LLVM to
|
||||
// lower atomic operations to single-threaded operations.
|
||||
if singlethread
|
||||
&& sess.target.llvm_target.contains("wasm32")
|
||||
&& sess.target_features.contains(&sym::atomics)
|
||||
{
|
||||
if singlethread && sess.target.is_like_wasm && sess.target_features.contains(&sym::atomics) {
|
||||
singlethread = false;
|
||||
}
|
||||
|
||||
@ -548,6 +545,15 @@ pub(crate) unsafe fn optimize(
|
||||
llvm::LLVMRustAddPass(fpm, find_pass("lint").unwrap());
|
||||
continue;
|
||||
}
|
||||
if pass_name == "insert-gcov-profiling" || pass_name == "instrprof" {
|
||||
// Instrumentation must be inserted before optimization,
|
||||
// otherwise LLVM may optimize some functions away which
|
||||
// breaks llvm-cov.
|
||||
//
|
||||
// This mirrors what Clang does in lib/CodeGen/BackendUtil.cpp.
|
||||
llvm::LLVMRustAddPass(mpm, find_pass(pass_name).unwrap());
|
||||
continue;
|
||||
}
|
||||
|
||||
if let Some(pass) = find_pass(pass_name) {
|
||||
extra_passes.push(pass);
|
||||
@ -1041,7 +1047,7 @@ pub unsafe fn with_llvm_pmb(
|
||||
// thresholds copied from clang.
|
||||
match (opt_level, opt_size, inline_threshold) {
|
||||
(.., Some(t)) => {
|
||||
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, t as u32);
|
||||
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, t);
|
||||
}
|
||||
(llvm::CodeGenOptLevel::Aggressive, ..) => {
|
||||
llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 275);
|
||||
|
@ -32,8 +32,9 @@ use rustc_middle::middle::cstore::EncodedMetadata;
|
||||
use rustc_middle::middle::exported_symbols;
|
||||
use rustc_middle::mir::mono::{Linkage, Visibility};
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::config::{DebugInfo, SanitizerSet};
|
||||
use rustc_session::config::DebugInfo;
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_target::spec::SanitizerSet;
|
||||
|
||||
use std::ffi::CString;
|
||||
use std::time::Instant;
|
||||
|
@ -21,6 +21,7 @@ use rustc_target::abi::{self, Align, Size};
|
||||
use rustc_target::spec::{HasTargetSpec, Target};
|
||||
use std::borrow::Cow;
|
||||
use std::ffi::CStr;
|
||||
use std::iter;
|
||||
use std::ops::{Deref, Range};
|
||||
use std::ptr;
|
||||
use tracing::debug;
|
||||
@ -1352,18 +1353,14 @@ impl Builder<'a, 'll, 'tcx> {
|
||||
|
||||
let param_tys = self.cx.func_params_types(fn_ty);
|
||||
|
||||
let all_args_match = param_tys
|
||||
.iter()
|
||||
.zip(args.iter().map(|&v| self.val_ty(v)))
|
||||
let all_args_match = iter::zip(¶m_tys, args.iter().map(|&v| self.val_ty(v)))
|
||||
.all(|(expected_ty, actual_ty)| *expected_ty == actual_ty);
|
||||
|
||||
if all_args_match {
|
||||
return Cow::Borrowed(args);
|
||||
}
|
||||
|
||||
let casted_args: Vec<_> = param_tys
|
||||
.into_iter()
|
||||
.zip(args.iter())
|
||||
let casted_args: Vec<_> = iter::zip(param_tys, args)
|
||||
.enumerate()
|
||||
.map(|(i, (expected_ty, &actual_val))| {
|
||||
let actual_ty = self.val_ty(actual_val);
|
||||
|
@ -14,6 +14,7 @@ use tracing::debug;
|
||||
|
||||
use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt};
|
||||
use rustc_middle::ty::{self, Instance, TypeFoldable};
|
||||
use rustc_target::spec::RelocModel;
|
||||
|
||||
/// Codegens a reference to a fn/method item, monomorphizing and
|
||||
/// inlining as it goes.
|
||||
@ -170,17 +171,19 @@ pub fn get_fn(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) -> &'ll Value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MinGW: For backward compatibility we rely on the linker to decide whether it
|
||||
// should use dllimport for functions.
|
||||
if cx.use_dll_storage_attrs
|
||||
&& tcx.is_dllimport_foreign_item(instance_def_id)
|
||||
&& tcx.sess.target.env != "gnu"
|
||||
{
|
||||
unsafe {
|
||||
// MinGW: For backward compatibility we rely on the linker to decide whether it
|
||||
// should use dllimport for functions.
|
||||
if cx.use_dll_storage_attrs
|
||||
&& tcx.is_dllimport_foreign_item(instance_def_id)
|
||||
&& tcx.sess.target.env != "gnu"
|
||||
{
|
||||
llvm::LLVMSetDLLStorageClass(llfn, llvm::DLLStorageClass::DllImport);
|
||||
}
|
||||
|
||||
if cx.tcx.sess.relocation_model() == RelocModel::Static {
|
||||
llvm::LLVMRustSetDSOLocal(llfn, true);
|
||||
}
|
||||
}
|
||||
|
||||
llfn
|
||||
|
@ -250,13 +250,9 @@ fn add_unused_function_coverage(
|
||||
// Insert at least one real counter so the LLVM CoverageMappingReader will find expected
|
||||
// definitions.
|
||||
function_coverage.add_counter(UNUSED_FUNCTION_COUNTER_ID, code_region.clone());
|
||||
} else {
|
||||
function_coverage.add_unreachable_region(code_region.clone());
|
||||
}
|
||||
// Add a Zero Counter for every code region.
|
||||
//
|
||||
// Even though the first coverage region already has an actual Counter, `llvm-cov` will not
|
||||
// always report it. Re-adding an unreachable region (zero counter) for the same region
|
||||
// seems to help produce the expected coverage.
|
||||
function_coverage.add_unreachable_region(code_region.clone());
|
||||
}
|
||||
|
||||
if let Some(coverage_context) = cx.coverage_context() {
|
||||
|
@ -1083,9 +1083,9 @@ pub fn compile_unit_metadata(
|
||||
);
|
||||
}
|
||||
|
||||
// Insert `llvm.ident` metadata on the wasm32 targets since that will
|
||||
// Insert `llvm.ident` metadata on the wasm targets since that will
|
||||
// get hooked up to the "producer" sections `processed-by` information.
|
||||
if tcx.sess.opts.target_triple.triple().starts_with("wasm32") {
|
||||
if tcx.sess.target.is_like_wasm {
|
||||
let name_metadata = llvm::LLVMMDStringInContext(
|
||||
debug_context.llcontext,
|
||||
rustc_producer.as_ptr().cast(),
|
||||
@ -1962,9 +1962,7 @@ fn prepare_enum_metadata(
|
||||
|
||||
let discriminant_type_metadata = |discr: Primitive| {
|
||||
let enumerators_metadata: Vec<_> = match enum_type.kind() {
|
||||
ty::Adt(def, _) => def
|
||||
.discriminants(tcx)
|
||||
.zip(&def.variants)
|
||||
ty::Adt(def, _) => iter::zip(def.discriminants(tcx), &def.variants)
|
||||
.map(|((_, discr), v)| {
|
||||
let name = v.ident.as_str();
|
||||
let is_unsigned = match discr.ty.kind() {
|
||||
@ -2336,9 +2334,7 @@ fn compute_type_parameters(cx: &CodegenCx<'ll, 'tcx>, ty: Ty<'tcx>) -> &'ll DIAr
|
||||
if substs.types().next().is_some() {
|
||||
let generics = cx.tcx.generics_of(def.did);
|
||||
let names = get_parameter_names(cx, generics);
|
||||
let template_params: Vec<_> = substs
|
||||
.iter()
|
||||
.zip(names)
|
||||
let template_params: Vec<_> = iter::zip(substs, names)
|
||||
.filter_map(|(kind, name)| {
|
||||
if let GenericArgKind::Type(ty) = kind.unpack() {
|
||||
let actual_type =
|
||||
|
@ -37,6 +37,7 @@ use rustc_target::abi::{LayoutOf, Primitive, Size};
|
||||
use libc::c_uint;
|
||||
use smallvec::SmallVec;
|
||||
use std::cell::RefCell;
|
||||
use std::iter;
|
||||
use tracing::debug;
|
||||
|
||||
mod create_scope_map;
|
||||
@ -448,9 +449,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||
// Again, only create type information if full debuginfo is enabled
|
||||
let template_params: Vec<_> = if cx.sess().opts.debuginfo == DebugInfo::Full {
|
||||
let names = get_parameter_names(cx, generics);
|
||||
substs
|
||||
.iter()
|
||||
.zip(names)
|
||||
iter::zip(substs, names)
|
||||
.filter_map(|(kind, name)| {
|
||||
if let GenericArgKind::Type(ty) = kind.unpack() {
|
||||
let actual_type =
|
||||
|
@ -11,6 +11,7 @@
|
||||
#![feature(extended_key_value_attributes)]
|
||||
#![feature(extern_types)]
|
||||
#![feature(in_band_lifetimes)]
|
||||
#![feature(iter_zip)]
|
||||
#![feature(nll)]
|
||||
#![cfg_attr(bootstrap, feature(or_patterns))]
|
||||
#![recursion_limit = "256"]
|
||||
|
@ -190,33 +190,6 @@ pub enum RealPredicate {
|
||||
RealPredicateTrue = 15,
|
||||
}
|
||||
|
||||
impl RealPredicate {
|
||||
pub fn from_generic(realpred: rustc_codegen_ssa::common::RealPredicate) -> Self {
|
||||
match realpred {
|
||||
rustc_codegen_ssa::common::RealPredicate::RealPredicateFalse => {
|
||||
RealPredicate::RealPredicateFalse
|
||||
}
|
||||
rustc_codegen_ssa::common::RealPredicate::RealOEQ => RealPredicate::RealOEQ,
|
||||
rustc_codegen_ssa::common::RealPredicate::RealOGT => RealPredicate::RealOGT,
|
||||
rustc_codegen_ssa::common::RealPredicate::RealOGE => RealPredicate::RealOGE,
|
||||
rustc_codegen_ssa::common::RealPredicate::RealOLT => RealPredicate::RealOLT,
|
||||
rustc_codegen_ssa::common::RealPredicate::RealOLE => RealPredicate::RealOLE,
|
||||
rustc_codegen_ssa::common::RealPredicate::RealONE => RealPredicate::RealONE,
|
||||
rustc_codegen_ssa::common::RealPredicate::RealORD => RealPredicate::RealORD,
|
||||
rustc_codegen_ssa::common::RealPredicate::RealUNO => RealPredicate::RealUNO,
|
||||
rustc_codegen_ssa::common::RealPredicate::RealUEQ => RealPredicate::RealUEQ,
|
||||
rustc_codegen_ssa::common::RealPredicate::RealUGT => RealPredicate::RealUGT,
|
||||
rustc_codegen_ssa::common::RealPredicate::RealUGE => RealPredicate::RealUGE,
|
||||
rustc_codegen_ssa::common::RealPredicate::RealULT => RealPredicate::RealULT,
|
||||
rustc_codegen_ssa::common::RealPredicate::RealULE => RealPredicate::RealULE,
|
||||
rustc_codegen_ssa::common::RealPredicate::RealUNE => RealPredicate::RealUNE,
|
||||
rustc_codegen_ssa::common::RealPredicate::RealPredicateTrue => {
|
||||
RealPredicate::RealPredicateTrue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// LLVMTypeKind
|
||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||
#[repr(C)]
|
||||
@ -711,7 +684,7 @@ pub mod coverageinfo {
|
||||
}
|
||||
|
||||
impl CounterMappingRegion {
|
||||
pub fn code_region(
|
||||
crate fn code_region(
|
||||
counter: coverage_map::Counter,
|
||||
file_id: u32,
|
||||
start_line: u32,
|
||||
@ -731,7 +704,10 @@ pub mod coverageinfo {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn expansion_region(
|
||||
// This function might be used in the future; the LLVM API is still evolving, as is coverage
|
||||
// support.
|
||||
#[allow(dead_code)]
|
||||
crate fn expansion_region(
|
||||
file_id: u32,
|
||||
expanded_file_id: u32,
|
||||
start_line: u32,
|
||||
@ -751,7 +727,10 @@ pub mod coverageinfo {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn skipped_region(
|
||||
// This function might be used in the future; the LLVM API is still evolving, as is coverage
|
||||
// support.
|
||||
#[allow(dead_code)]
|
||||
crate fn skipped_region(
|
||||
file_id: u32,
|
||||
start_line: u32,
|
||||
start_col: u32,
|
||||
@ -770,7 +749,10 @@ pub mod coverageinfo {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn gap_region(
|
||||
// This function might be used in the future; the LLVM API is still evolving, as is coverage
|
||||
// support.
|
||||
#[allow(dead_code)]
|
||||
crate fn gap_region(
|
||||
counter: coverage_map::Counter,
|
||||
file_id: u32,
|
||||
start_line: u32,
|
||||
@ -1031,6 +1013,7 @@ extern "C" {
|
||||
pub fn LLVMSetSection(Global: &Value, Section: *const c_char);
|
||||
pub fn LLVMRustGetVisibility(Global: &Value) -> Visibility;
|
||||
pub fn LLVMRustSetVisibility(Global: &Value, Viz: Visibility);
|
||||
pub fn LLVMRustSetDSOLocal(Global: &Value, is_dso_local: bool);
|
||||
pub fn LLVMGetAlignment(Global: &Value) -> c_uint;
|
||||
pub fn LLVMSetAlignment(Global: &Value, Bytes: c_uint);
|
||||
pub fn LLVMSetDLLStorageClass(V: &Value, C: DLLStorageClass);
|
||||
|
@ -10,7 +10,9 @@ pub use rustc_middle::mir::mono::MonoItem;
|
||||
use rustc_middle::mir::mono::{Linkage, Visibility};
|
||||
use rustc_middle::ty::layout::FnAbiExt;
|
||||
use rustc_middle::ty::{self, Instance, TypeFoldable};
|
||||
use rustc_session::config::CrateType;
|
||||
use rustc_target::abi::LayoutOf;
|
||||
use rustc_target::spec::RelocModel;
|
||||
use tracing::debug;
|
||||
|
||||
impl PreDefineMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||
@ -35,6 +37,9 @@ impl PreDefineMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||
unsafe {
|
||||
llvm::LLVMRustSetLinkage(g, base::linkage_to_llvm(linkage));
|
||||
llvm::LLVMRustSetVisibility(g, base::visibility_to_llvm(visibility));
|
||||
if self.should_assume_dso_local(linkage, visibility) {
|
||||
llvm::LLVMRustSetDSOLocal(g, true);
|
||||
}
|
||||
}
|
||||
|
||||
self.instances.borrow_mut().insert(instance, g);
|
||||
@ -79,6 +84,42 @@ impl PreDefineMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||
|
||||
attributes::from_fn_attrs(self, lldecl, instance);
|
||||
|
||||
unsafe {
|
||||
if self.should_assume_dso_local(linkage, visibility) {
|
||||
llvm::LLVMRustSetDSOLocal(lldecl, true);
|
||||
}
|
||||
}
|
||||
|
||||
self.instances.borrow_mut().insert(instance, lldecl);
|
||||
}
|
||||
}
|
||||
|
||||
impl CodegenCx<'ll, 'tcx> {
|
||||
/// Whether a definition (NB: not declaration!) can be assumed to be local to a group of
|
||||
/// libraries that form a single DSO or executable.
|
||||
pub(crate) unsafe fn should_assume_dso_local(
|
||||
&self,
|
||||
linkage: Linkage,
|
||||
visibility: Visibility,
|
||||
) -> bool {
|
||||
if matches!(linkage, Linkage::Internal | Linkage::Private) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if visibility != Visibility::Default && linkage != Linkage::ExternalWeak {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Static relocation model should force copy relocations everywhere.
|
||||
if self.tcx.sess.relocation_model() == RelocModel::Static {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Symbols from executables can't really be imported any further.
|
||||
if self.tcx.sess.crate_types().iter().all(|ty| *ty == CrateType::Executable) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,6 @@ test = false
|
||||
bitflags = "1.2.1"
|
||||
cc = "1.0.1"
|
||||
itertools = "0.9"
|
||||
memmap2 = "0.2.1"
|
||||
tracing = "0.1"
|
||||
libc = "0.2.50"
|
||||
jobserver = "0.1.11"
|
||||
|
@ -6,7 +6,7 @@ use rustc_hir::def_id::CrateNum;
|
||||
use rustc_middle::middle::cstore::{EncodedMetadata, LibSource};
|
||||
use rustc_middle::middle::dependency_format::Linkage;
|
||||
use rustc_session::config::{self, CFGuard, CrateType, DebugInfo};
|
||||
use rustc_session::config::{OutputFilenames, OutputType, PrintRequest, SanitizerSet};
|
||||
use rustc_session::config::{OutputFilenames, OutputType, PrintRequest};
|
||||
use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename};
|
||||
use rustc_session::search_paths::PathKind;
|
||||
use rustc_session::utils::NativeLibKind;
|
||||
@ -16,7 +16,7 @@ use rustc_session::{filesearch, Session};
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_target::spec::crt_objects::{CrtObjects, CrtObjectsFallback};
|
||||
use rustc_target::spec::{LinkOutputKind, LinkerFlavor, LldFlavor, SplitDebuginfo};
|
||||
use rustc_target::spec::{PanicStrategy, RelocModel, RelroLevel, Target};
|
||||
use rustc_target::spec::{PanicStrategy, RelocModel, RelroLevel, SanitizerSet, Target};
|
||||
|
||||
use super::archive::ArchiveBuilder;
|
||||
use super::command::Command;
|
||||
@ -922,28 +922,20 @@ fn link_sanitizer_runtime(sess: &Session, linker: &mut dyn Linker, name: &str) {
|
||||
.map(|channel| format!("-{}", channel))
|
||||
.unwrap_or_default();
|
||||
|
||||
match sess.opts.target_triple.triple() {
|
||||
"aarch64-apple-darwin" | "x86_64-apple-darwin" => {
|
||||
// On Apple platforms, the sanitizer is always built as a dylib, and
|
||||
// LLVM will link to `@rpath/*.dylib`, so we need to specify an
|
||||
// rpath to the library as well (the rpath should be absolute, see
|
||||
// PR #41352 for details).
|
||||
let filename = format!("rustc{}_rt.{}", channel, name);
|
||||
let path = find_sanitizer_runtime(&sess, &filename);
|
||||
let rpath = path.to_str().expect("non-utf8 component in path");
|
||||
linker.args(&["-Wl,-rpath", "-Xlinker", rpath]);
|
||||
linker.link_dylib(Symbol::intern(&filename));
|
||||
}
|
||||
"aarch64-fuchsia"
|
||||
| "aarch64-unknown-linux-gnu"
|
||||
| "x86_64-fuchsia"
|
||||
| "x86_64-unknown-freebsd"
|
||||
| "x86_64-unknown-linux-gnu" => {
|
||||
let filename = format!("librustc{}_rt.{}.a", channel, name);
|
||||
let path = find_sanitizer_runtime(&sess, &filename).join(&filename);
|
||||
linker.link_whole_rlib(&path);
|
||||
}
|
||||
_ => {}
|
||||
if sess.target.is_like_osx {
|
||||
// On Apple platforms, the sanitizer is always built as a dylib, and
|
||||
// LLVM will link to `@rpath/*.dylib`, so we need to specify an
|
||||
// rpath to the library as well (the rpath should be absolute, see
|
||||
// PR #41352 for details).
|
||||
let filename = format!("rustc{}_rt.{}", channel, name);
|
||||
let path = find_sanitizer_runtime(&sess, &filename);
|
||||
let rpath = path.to_str().expect("non-utf8 component in path");
|
||||
linker.args(&["-Wl,-rpath", "-Xlinker", rpath]);
|
||||
linker.link_dylib(Symbol::intern(&filename));
|
||||
} else {
|
||||
let filename = format!("librustc{}_rt.{}.a", channel, name);
|
||||
let path = find_sanitizer_runtime(&sess, &filename).join(&filename);
|
||||
linker.link_whole_rlib(&path);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1419,15 +1411,10 @@ fn add_link_script(cmd: &mut dyn Linker, sess: &Session, tmpdir: &Path, crate_ty
|
||||
}
|
||||
}
|
||||
|
||||
/// Add arbitrary "user defined" args defined from command line and by `#[link_args]` attributes.
|
||||
/// Add arbitrary "user defined" args defined from command line.
|
||||
/// FIXME: Determine where exactly these args need to be inserted.
|
||||
fn add_user_defined_link_args(
|
||||
cmd: &mut dyn Linker,
|
||||
sess: &Session,
|
||||
codegen_results: &CodegenResults,
|
||||
) {
|
||||
fn add_user_defined_link_args(cmd: &mut dyn Linker, sess: &Session) {
|
||||
cmd.args(&sess.opts.cg.link_args);
|
||||
cmd.args(&*codegen_results.crate_info.link_args);
|
||||
}
|
||||
|
||||
/// Add arbitrary "late link" args defined by the target spec.
|
||||
@ -1651,6 +1638,16 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
|
||||
cmd.add_eh_frame_header();
|
||||
}
|
||||
|
||||
// NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER
|
||||
// Make the binary compatible with data execution prevention schemes.
|
||||
cmd.add_no_exec();
|
||||
|
||||
// NO-OPT-OUT, OBJECT-FILES-NO
|
||||
// Avoid linking to dynamic libraries unless they satisfy some undefined symbols
|
||||
// at the point at which they are specified on the command line.
|
||||
// Must be passed before any dynamic libraries.
|
||||
cmd.add_as_needed();
|
||||
|
||||
// NO-OPT-OUT, OBJECT-FILES-NO
|
||||
if crt_objects_fallback {
|
||||
cmd.no_crt_objects();
|
||||
@ -1759,7 +1756,7 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
|
||||
add_rpath_args(cmd, sess, codegen_results, out_filename);
|
||||
|
||||
// OBJECT-FILES-MAYBE, CUSTOMIZATION-POINT
|
||||
add_user_defined_link_args(cmd, sess, codegen_results);
|
||||
add_user_defined_link_args(cmd, sess);
|
||||
|
||||
// NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER
|
||||
cmd.finalize();
|
||||
|
@ -130,6 +130,8 @@ pub trait Linker {
|
||||
fn group_end(&mut self);
|
||||
fn linker_plugin_lto(&mut self);
|
||||
fn add_eh_frame_header(&mut self) {}
|
||||
fn add_no_exec(&mut self) {}
|
||||
fn add_as_needed(&mut self) {}
|
||||
fn finalize(&mut self);
|
||||
}
|
||||
|
||||
@ -184,7 +186,7 @@ impl<'a> GccLinker<'a> {
|
||||
// * On OSX they have their own linker, not binutils'
|
||||
// * For WebAssembly the only functional linker is LLD, which doesn't
|
||||
// support hint flags
|
||||
!self.sess.target.is_like_osx && self.sess.target.arch != "wasm32"
|
||||
!self.sess.target.is_like_osx && !self.sess.target.is_like_wasm
|
||||
}
|
||||
|
||||
// Some platforms take hints about whether a library is static or dynamic.
|
||||
@ -641,6 +643,20 @@ impl<'a> Linker for GccLinker<'a> {
|
||||
fn add_eh_frame_header(&mut self) {
|
||||
self.linker_arg("--eh-frame-hdr");
|
||||
}
|
||||
|
||||
fn add_no_exec(&mut self) {
|
||||
if self.sess.target.is_like_windows {
|
||||
self.linker_arg("--nxcompat");
|
||||
} else if self.sess.target.linker_is_gnu {
|
||||
self.linker_arg("-znoexecstack");
|
||||
}
|
||||
}
|
||||
|
||||
fn add_as_needed(&mut self) {
|
||||
if self.sess.target.linker_is_gnu {
|
||||
self.linker_arg("--as-needed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MsvcLinker<'a> {
|
||||
@ -878,6 +894,10 @@ impl<'a> Linker for MsvcLinker<'a> {
|
||||
fn linker_plugin_lto(&mut self) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
fn add_no_exec(&mut self) {
|
||||
self.cmd.arg("/NXCOMPAT");
|
||||
}
|
||||
}
|
||||
|
||||
pub struct EmLinker<'a> {
|
||||
|
@ -2,6 +2,7 @@ use super::write::CodegenContext;
|
||||
use crate::traits::*;
|
||||
use crate::ModuleCodegen;
|
||||
|
||||
use rustc_data_structures::memmap::Mmap;
|
||||
use rustc_errors::FatalError;
|
||||
|
||||
use std::ffi::CString;
|
||||
@ -93,7 +94,7 @@ impl<B: WriteBackendMethods> LtoModuleCodegen<B> {
|
||||
pub enum SerializedModule<M: ModuleBufferMethods> {
|
||||
Local(M),
|
||||
FromRlib(Vec<u8>),
|
||||
FromUncompressedFile(memmap2::Mmap),
|
||||
FromUncompressedFile(Mmap),
|
||||
}
|
||||
|
||||
impl<M: ModuleBufferMethods> SerializedModule<M> {
|
||||
|
@ -15,7 +15,8 @@ use rustc_middle::ty::query::Providers;
|
||||
use rustc_middle::ty::subst::{GenericArgKind, SubstsRef};
|
||||
use rustc_middle::ty::Instance;
|
||||
use rustc_middle::ty::{SymbolName, TyCtxt};
|
||||
use rustc_session::config::{CrateType, SanitizerSet};
|
||||
use rustc_session::config::CrateType;
|
||||
use rustc_target::spec::SanitizerSet;
|
||||
|
||||
pub fn threshold(tcx: TyCtxt<'_>) -> SymbolExportLevel {
|
||||
crates_export_threshold(&tcx.sess.crate_types())
|
||||
|
@ -10,6 +10,7 @@ use crate::{
|
||||
use crate::traits::*;
|
||||
use jobserver::{Acquired, Client};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::memmap::Mmap;
|
||||
use rustc_data_structures::profiling::SelfProfilerRef;
|
||||
use rustc_data_structures::profiling::TimingGuard;
|
||||
use rustc_data_structures::profiling::VerboseTimingGuard;
|
||||
@ -27,12 +28,12 @@ use rustc_middle::middle::exported_symbols::SymbolExportLevel;
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::cgu_reuse_tracker::CguReuseTracker;
|
||||
use rustc_session::config::{self, CrateType, Lto, OutputFilenames, OutputType};
|
||||
use rustc_session::config::{Passes, SanitizerSet, SwitchWithOptPath};
|
||||
use rustc_session::config::{Passes, SwitchWithOptPath};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::source_map::SourceMap;
|
||||
use rustc_span::symbol::{sym, Symbol};
|
||||
use rustc_span::{BytePos, FileName, InnerSpan, Pos, Span};
|
||||
use rustc_target::spec::{MergeFunctions, PanicStrategy};
|
||||
use rustc_target::spec::{MergeFunctions, PanicStrategy, SanitizerSet};
|
||||
|
||||
use std::any::Any;
|
||||
use std::fs;
|
||||
@ -106,7 +107,7 @@ pub struct ModuleConfig {
|
||||
pub vectorize_loop: bool,
|
||||
pub vectorize_slp: bool,
|
||||
pub merge_functions: bool,
|
||||
pub inline_threshold: Option<usize>,
|
||||
pub inline_threshold: Option<u32>,
|
||||
pub new_llvm_pass_manager: bool,
|
||||
pub emit_lifetime_markers: bool,
|
||||
}
|
||||
@ -1958,7 +1959,7 @@ pub fn submit_pre_lto_module_to_llvm<B: ExtraBackendMethods>(
|
||||
.unwrap_or_else(|e| panic!("failed to open bitcode file `{}`: {}", bc_path.display(), e));
|
||||
|
||||
let mmap = unsafe {
|
||||
memmap2::Mmap::map(&file).unwrap_or_else(|e| {
|
||||
Mmap::map(file).unwrap_or_else(|e| {
|
||||
panic!("failed to mmap bitcode file `{}`: {}", bc_path.display(), e)
|
||||
})
|
||||
};
|
||||
|
@ -754,7 +754,6 @@ impl CrateInfo {
|
||||
is_no_builtins: Default::default(),
|
||||
native_libraries: Default::default(),
|
||||
used_libraries: tcx.native_libraries(LOCAL_CRATE).iter().map(Into::into).collect(),
|
||||
link_args: tcx.link_args(LOCAL_CRATE),
|
||||
crate_name: Default::default(),
|
||||
used_crates_dynamic: cstore::used_crates(tcx, LinkagePreference::RequireDynamic),
|
||||
used_crates_static: cstore::used_crates(tcx, LinkagePreference::RequireStatic),
|
||||
|
@ -24,21 +24,39 @@ pub enum CounterKind {
|
||||
pub struct Counter {
|
||||
// Important: The layout (order and types of fields) must match its C++ counterpart.
|
||||
pub kind: CounterKind,
|
||||
pub id: u32,
|
||||
id: u32,
|
||||
}
|
||||
|
||||
impl Counter {
|
||||
/// Constructs a new `Counter` of kind `Zero`. For this `CounterKind`, the
|
||||
/// `id` is not used.
|
||||
pub fn zero() -> Self {
|
||||
Self { kind: CounterKind::Zero, id: 0 }
|
||||
}
|
||||
|
||||
/// Constructs a new `Counter` of kind `CounterValueReference`, and converts
|
||||
/// the given 1-based counter_id to the required 0-based equivalent for
|
||||
/// the `Counter` encoding.
|
||||
pub fn counter_value_reference(counter_id: CounterValueReference) -> Self {
|
||||
Self { kind: CounterKind::CounterValueReference, id: counter_id.into() }
|
||||
Self { kind: CounterKind::CounterValueReference, id: counter_id.zero_based_index() }
|
||||
}
|
||||
|
||||
/// Constructs a new `Counter` of kind `Expression`.
|
||||
pub fn expression(mapped_expression_index: MappedExpressionIndex) -> Self {
|
||||
Self { kind: CounterKind::Expression, id: mapped_expression_index.into() }
|
||||
}
|
||||
|
||||
/// Returns true if the `Counter` kind is `Zero`.
|
||||
pub fn is_zero(&self) -> bool {
|
||||
matches!(self.kind, CounterKind::Zero)
|
||||
}
|
||||
|
||||
/// An explicitly-named function to get the ID value, making it more obvious
|
||||
/// that the stored value is now 0-based.
|
||||
pub fn zero_based_id(&self) -> u32 {
|
||||
debug_assert!(!self.is_zero(), "`id` is undefined for CounterKind::Zero");
|
||||
self.id
|
||||
}
|
||||
}
|
||||
|
||||
/// Aligns with [llvm::coverage::CounterExpression::ExprKind](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L147)
|
||||
|
@ -163,9 +163,7 @@ impl<'tcx> FunctionCoverage<'tcx> {
|
||||
self.counters.iter_enumerated().filter_map(|(index, entry)| {
|
||||
// Option::map() will return None to filter out missing counters. This may happen
|
||||
// if, for example, a MIR-instrumented counter is removed during an optimization.
|
||||
entry.as_ref().map(|region| {
|
||||
(Counter::counter_value_reference(index as CounterValueReference), region)
|
||||
})
|
||||
entry.as_ref().map(|region| (Counter::counter_value_reference(index), region))
|
||||
})
|
||||
}
|
||||
|
||||
@ -206,9 +204,15 @@ impl<'tcx> FunctionCoverage<'tcx> {
|
||||
if id == ExpressionOperandId::ZERO {
|
||||
Some(Counter::zero())
|
||||
} else if id.index() < self.counters.len() {
|
||||
debug_assert!(
|
||||
id.index() > 0,
|
||||
"ExpressionOperandId indexes for counters are 1-based, but this id={}",
|
||||
id.index()
|
||||
);
|
||||
// Note: Some codegen-injected Counters may be only referenced by `Expression`s,
|
||||
// and may not have their own `CodeRegion`s,
|
||||
let index = CounterValueReference::from(id.index());
|
||||
// Note, the conversion to LLVM `Counter` adjusts the index to be zero-based.
|
||||
Some(Counter::counter_value_reference(index))
|
||||
} else {
|
||||
let index = self.expression_index(u32::from(id));
|
||||
@ -233,19 +237,60 @@ impl<'tcx> FunctionCoverage<'tcx> {
|
||||
let optional_region = &expression.region;
|
||||
let Expression { lhs, op, rhs, .. } = *expression;
|
||||
|
||||
if let Some(Some((lhs_counter, rhs_counter))) =
|
||||
id_to_counter(&new_indexes, lhs).map(|lhs_counter| {
|
||||
if let Some(Some((lhs_counter, mut rhs_counter))) = id_to_counter(&new_indexes, lhs)
|
||||
.map(|lhs_counter| {
|
||||
id_to_counter(&new_indexes, rhs).map(|rhs_counter| (lhs_counter, rhs_counter))
|
||||
})
|
||||
{
|
||||
if lhs_counter.is_zero() && op.is_subtract() {
|
||||
// The left side of a subtraction was probably optimized out. As an example,
|
||||
// a branch condition might be evaluated as a constant expression, and the
|
||||
// branch could be removed, dropping unused counters in the process.
|
||||
//
|
||||
// Since counters are unsigned, we must assume the result of the expression
|
||||
// can be no more and no less than zero. An expression known to evaluate to zero
|
||||
// does not need to be added to the coverage map.
|
||||
//
|
||||
// Coverage test `loops_branches.rs` includes multiple variations of branches
|
||||
// based on constant conditional (literal `true` or `false`), and demonstrates
|
||||
// that the expected counts are still correct.
|
||||
debug!(
|
||||
"Expression subtracts from zero (assume unreachable): \
|
||||
original_index={:?}, lhs={:?}, op={:?}, rhs={:?}, region={:?}",
|
||||
original_index, lhs, op, rhs, optional_region,
|
||||
);
|
||||
rhs_counter = Counter::zero();
|
||||
}
|
||||
debug_assert!(
|
||||
(lhs_counter.id as usize)
|
||||
< usize::max(self.counters.len(), self.expressions.len())
|
||||
lhs_counter.is_zero()
|
||||
// Note: with `as usize` the ID _could_ overflow/wrap if `usize = u16`
|
||||
|| ((lhs_counter.zero_based_id() as usize)
|
||||
<= usize::max(self.counters.len(), self.expressions.len())),
|
||||
"lhs id={} > both counters.len()={} and expressions.len()={}
|
||||
({:?} {:?} {:?})",
|
||||
lhs_counter.zero_based_id(),
|
||||
self.counters.len(),
|
||||
self.expressions.len(),
|
||||
lhs_counter,
|
||||
op,
|
||||
rhs_counter,
|
||||
);
|
||||
|
||||
debug_assert!(
|
||||
(rhs_counter.id as usize)
|
||||
< usize::max(self.counters.len(), self.expressions.len())
|
||||
rhs_counter.is_zero()
|
||||
// Note: with `as usize` the ID _could_ overflow/wrap if `usize = u16`
|
||||
|| ((rhs_counter.zero_based_id() as usize)
|
||||
<= usize::max(self.counters.len(), self.expressions.len())),
|
||||
"rhs id={} > both counters.len()={} and expressions.len()={}
|
||||
({:?} {:?} {:?})",
|
||||
rhs_counter.zero_based_id(),
|
||||
self.counters.len(),
|
||||
self.expressions.len(),
|
||||
lhs_counter,
|
||||
op,
|
||||
rhs_counter,
|
||||
);
|
||||
|
||||
// Both operands exist. `Expression` operands exist in `self.expressions` and have
|
||||
// been assigned a `new_index`.
|
||||
let mapped_expression_index =
|
||||
@ -268,11 +313,15 @@ impl<'tcx> FunctionCoverage<'tcx> {
|
||||
expression_regions.push((Counter::expression(mapped_expression_index), region));
|
||||
}
|
||||
} else {
|
||||
debug!(
|
||||
"Ignoring expression with one or more missing operands: \
|
||||
original_index={:?}, lhs={:?}, op={:?}, rhs={:?}, region={:?}",
|
||||
original_index, lhs, op, rhs, optional_region,
|
||||
)
|
||||
bug!(
|
||||
"expression has one or more missing operands \
|
||||
original_index={:?}, lhs={:?}, op={:?}, rhs={:?}, region={:?}",
|
||||
original_index,
|
||||
lhs,
|
||||
op,
|
||||
rhs,
|
||||
optional_region,
|
||||
);
|
||||
}
|
||||
}
|
||||
(counter_expressions, expression_regions.into_iter())
|
||||
|
@ -8,6 +8,7 @@
|
||||
#![feature(nll)]
|
||||
#![cfg_attr(bootstrap, feature(or_patterns))]
|
||||
#![feature(associated_type_bounds)]
|
||||
#![feature(iter_zip)]
|
||||
#![recursion_limit = "256"]
|
||||
#![feature(box_syntax)]
|
||||
|
||||
@ -138,7 +139,6 @@ pub struct CrateInfo {
|
||||
pub native_libraries: FxHashMap<CrateNum, Vec<NativeLib>>,
|
||||
pub crate_name: FxHashMap<CrateNum, String>,
|
||||
pub used_libraries: Vec<NativeLib>,
|
||||
pub link_args: Lrc<Vec<String>>,
|
||||
pub used_crate_source: FxHashMap<CrateNum, Lrc<CrateSource>>,
|
||||
pub used_crates_static: Vec<(CrateNum, LibSource)>,
|
||||
pub used_crates_dynamic: Vec<(CrateNum, LibSource)>,
|
||||
|
@ -36,7 +36,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
let fn_name = bx.get_pgo_func_name_var(instance);
|
||||
let hash = bx.const_u64(function_source_hash);
|
||||
let num_counters = bx.const_u32(coverageinfo.num_counters);
|
||||
let index = bx.const_u32(u32::from(id));
|
||||
let index = bx.const_u32(id.zero_based_index());
|
||||
debug!(
|
||||
"codegen intrinsic instrprof.increment(fn_name={:?}, hash={:?}, num_counters={:?}, index={:?})",
|
||||
fn_name, hash, num_counters, index,
|
||||
|
@ -282,9 +282,7 @@ fn create_funclets<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||
IndexVec<mir::BasicBlock, Option<Bx::BasicBlock>>,
|
||||
IndexVec<mir::BasicBlock, Option<Bx::Funclet>>,
|
||||
) {
|
||||
block_bxs
|
||||
.iter_enumerated()
|
||||
.zip(cleanup_kinds)
|
||||
iter::zip(block_bxs.iter_enumerated(), cleanup_kinds)
|
||||
.map(|((bb, &llbb), cleanup_kind)| {
|
||||
match *cleanup_kind {
|
||||
CleanupKind::Funclet if base::wants_msvc_seh(bx.sess()) => {}
|
||||
|
@ -26,6 +26,7 @@ const ARM_ALLOWED_FEATURES: &[(&str, Option<Symbol>)] = &[
|
||||
("vfp2", Some(sym::arm_target_feature)),
|
||||
("vfp3", Some(sym::arm_target_feature)),
|
||||
("vfp4", Some(sym::arm_target_feature)),
|
||||
("fp-armv8", Some(sym::arm_target_feature)),
|
||||
// This is needed for inline assembly, but shouldn't be stabilized as-is
|
||||
// since it should be enabled per-function using #[instruction_set], not
|
||||
// #[target_feature].
|
||||
@ -160,7 +161,7 @@ pub fn supported_target_features(sess: &Session) -> &'static [(&'static str, Opt
|
||||
"mips" | "mips64" => MIPS_ALLOWED_FEATURES,
|
||||
"powerpc" | "powerpc64" => POWERPC_ALLOWED_FEATURES,
|
||||
"riscv32" | "riscv64" => RISCV_ALLOWED_FEATURES,
|
||||
"wasm32" => WASM_ALLOWED_FEATURES,
|
||||
"wasm32" | "wasm64" => WASM_ALLOWED_FEATURES,
|
||||
_ => &[],
|
||||
}
|
||||
}
|
||||
|
@ -36,3 +36,6 @@ features = ["nightly"]
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
winapi = { version = "0.3", features = ["fileapi", "psapi"] }
|
||||
|
||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||
memmap2 = "0.2.1"
|
||||
|
@ -84,6 +84,7 @@ pub mod snapshot_map;
|
||||
pub mod stable_map;
|
||||
pub mod svh;
|
||||
pub use ena::snapshot_vec;
|
||||
pub mod memmap;
|
||||
pub mod sorted_map;
|
||||
pub mod stable_set;
|
||||
#[macro_use]
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user