mirror of
https://git.proxmox.com/git/rustc
synced 2025-07-17 22:47:48 +00:00
New upstream version 1.50.0+dfsg1
This commit is contained in:
parent
b985613438
commit
fc51201451
303
Cargo.lock
generated
303
Cargo.lock
generated
@ -2,9 +2,9 @@
|
|||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "addr2line"
|
name = "addr2line"
|
||||||
version = "0.13.0"
|
version = "0.14.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1b6a2d3371669ab3ca9797670853d61402b03d0b4b9ebf33d677dfa720203072"
|
checksum = "7c0929d69e78dd9bf5408269919fcbcaeb2e35e5d43e5815517cdc6a8e11a423"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"compiler_builtins",
|
"compiler_builtins",
|
||||||
"gimli",
|
"gimli",
|
||||||
@ -132,13 +132,13 @@ checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "backtrace"
|
name = "backtrace"
|
||||||
version = "0.3.53"
|
version = "0.3.55"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"addr2line",
|
"addr2line",
|
||||||
"cfg-if 1.0.0",
|
"cfg-if 1.0.0",
|
||||||
"libc",
|
"libc",
|
||||||
"miniz_oxide",
|
"miniz_oxide",
|
||||||
"object 0.21.1",
|
"object",
|
||||||
"rustc-demangle",
|
"rustc-demangle",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -295,7 +295,7 @@ checksum = "81a18687293a1546b67c246452202bbbf143d239cb43494cc163da14979082da"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cargo"
|
name = "cargo"
|
||||||
version = "0.50.0"
|
version = "0.51.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"atty",
|
"atty",
|
||||||
@ -329,7 +329,7 @@ dependencies = [
|
|||||||
"libgit2-sys",
|
"libgit2-sys",
|
||||||
"log",
|
"log",
|
||||||
"memchr",
|
"memchr",
|
||||||
"miow 0.3.5",
|
"miow 0.3.6",
|
||||||
"num_cpus",
|
"num_cpus",
|
||||||
"opener",
|
"opener",
|
||||||
"openssl",
|
"openssl",
|
||||||
@ -355,6 +355,35 @@ dependencies = [
|
|||||||
"winapi 0.3.9",
|
"winapi 0.3.9",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cargo-credential"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cargo-credential-1password"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"cargo-credential",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cargo-credential-macos-keychain"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"cargo-credential",
|
||||||
|
"security-framework",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cargo-credential-wincred"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"cargo-credential",
|
||||||
|
"winapi 0.3.9",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cargo-miri"
|
name = "cargo-miri"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@ -569,6 +598,7 @@ dependencies = [
|
|||||||
"quine-mc_cluskey",
|
"quine-mc_cluskey",
|
||||||
"quote",
|
"quote",
|
||||||
"regex-syntax",
|
"regex-syntax",
|
||||||
|
"rustc-semver",
|
||||||
"semver 0.11.0",
|
"semver 0.11.0",
|
||||||
"serde",
|
"serde",
|
||||||
"smallvec 1.4.2",
|
"smallvec 1.4.2",
|
||||||
@ -653,7 +683,7 @@ dependencies = [
|
|||||||
"glob",
|
"glob",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"libc",
|
"libc",
|
||||||
"miow 0.3.5",
|
"miow 0.3.6",
|
||||||
"regex",
|
"regex",
|
||||||
"rustfix",
|
"rustfix",
|
||||||
"serde",
|
"serde",
|
||||||
@ -675,7 +705,7 @@ dependencies = [
|
|||||||
"getopts",
|
"getopts",
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
"miow 0.3.5",
|
"miow 0.3.6",
|
||||||
"regex",
|
"regex",
|
||||||
"rustfix",
|
"rustfix",
|
||||||
"serde",
|
"serde",
|
||||||
@ -721,6 +751,10 @@ version = "0.8.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9a21fa21941700a3cd8fcb4091f361a6a712fac632f85d9f487cc892045d55c6"
|
checksum = "9a21fa21941700a3cd8fcb4091f361a6a712fac632f85d9f487cc892045d55c6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "coverage_test_macros"
|
||||||
|
version = "0.0.0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cpuid-bool"
|
name = "cpuid-bool"
|
||||||
version = "0.1.2"
|
version = "0.1.2"
|
||||||
@ -861,9 +895,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "curl"
|
name = "curl"
|
||||||
version = "0.4.31"
|
version = "0.4.34"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9447ad28eee2a5cfb031c329d46bef77487244fff6a724b378885b8691a35f78"
|
checksum = "e268162af1a5fe89917ae25ba3b0a77c8da752bdc58e7dbb4f15b91fbd33756e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"curl-sys",
|
"curl-sys",
|
||||||
"libc",
|
"libc",
|
||||||
@ -876,9 +910,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "curl-sys"
|
name = "curl-sys"
|
||||||
version = "0.4.34+curl-7.71.1"
|
version = "0.4.39+curl-7.74.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ad4eff0be6985b7e709f64b5a541f700e9ad1407190a29f4884319eb663ed1d6"
|
checksum = "07a8ce861e7b68a0b394e814d7ee9f1b2750ff8bd10372c6ad3bacc10e86f874"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"libc",
|
"libc",
|
||||||
@ -980,9 +1014,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dlmalloc"
|
name = "dlmalloc"
|
||||||
version = "0.1.4"
|
version = "0.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "35055b1021724f4eb5262eb49130eebff23fc59fc5a14160e05faad8eeb36673"
|
checksum = "332570860c2edf2d57914987bf9e24835425f75825086b6ba7d1e6a3e4f1f254"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"compiler_builtins",
|
"compiler_builtins",
|
||||||
"libc",
|
"libc",
|
||||||
@ -1285,9 +1319,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gimli"
|
name = "gimli"
|
||||||
version = "0.22.0"
|
version = "0.23.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "aaf91faf136cb47367fa430cd46e37a788775e7fa104f8b4bcb3861dc389b724"
|
checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"compiler_builtins",
|
"compiler_builtins",
|
||||||
"rustc-std-workspace-alloc",
|
"rustc-std-workspace-alloc",
|
||||||
@ -1296,9 +1330,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "git2"
|
name = "git2"
|
||||||
version = "0.13.12"
|
version = "0.13.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ca6f1a0238d7f8f8fd5ee642f4ebac4dbc03e03d1f78fbe7a3ede35dcf7e2224"
|
checksum = "186dd99cc77576e58344ad614fa9bb27bad9d048f85de3ca850c1f4e8b048260"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"libc",
|
"libc",
|
||||||
@ -1311,9 +1345,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "git2-curl"
|
name = "git2-curl"
|
||||||
version = "0.14.0"
|
version = "0.14.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "502d532a2d06184beb3bc869d4d90236e60934e3382c921b203fa3c33e212bd7"
|
checksum = "883539cb0ea94bab3f8371a98cd8e937bbe9ee7c044499184aa4c17deb643a50"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"curl",
|
"curl",
|
||||||
"git2",
|
"git2",
|
||||||
@ -1340,6 +1374,15 @@ dependencies = [
|
|||||||
"regex",
|
"regex",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gsgdt"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a0d876ce7262df96262a2a19531da6ff9a86048224d49580a585fc5c04617825"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "handlebars"
|
name = "handlebars"
|
||||||
version = "3.4.0"
|
version = "3.4.0"
|
||||||
@ -1716,9 +1759,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libgit2-sys"
|
name = "libgit2-sys"
|
||||||
version = "0.12.14+1.1.0"
|
version = "0.12.16+1.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8f25af58e6495f7caf2919d08f212de550cfa3ed2f5e744988938ea292b9f549"
|
checksum = "9f91b2f931ee975a98155195be8cd82d02e8e029d7d793d2bac1b8181ac97020"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cc",
|
"cc",
|
||||||
"libc",
|
"libc",
|
||||||
@ -1917,17 +1960,6 @@ version = "2.0.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
|
checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "md-5"
|
|
||||||
version = "0.8.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a18af3dcaf2b0219366cdb4e2af65a6101457b415c3d1a5c71dd9c2b7c77b9c8"
|
|
||||||
dependencies = [
|
|
||||||
"block-buffer 0.7.3",
|
|
||||||
"digest 0.8.1",
|
|
||||||
"opaque-debug 0.2.3",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "md-5"
|
name = "md-5"
|
||||||
version = "0.9.1"
|
version = "0.9.1"
|
||||||
@ -1941,9 +1973,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mdbook"
|
name = "mdbook"
|
||||||
version = "0.4.3"
|
version = "0.4.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "29be448fcafb00c5a8966c4020c2a5ffbbc333e5b96d0bb5ef54b5bd0524d9ff"
|
checksum = "21251d3eb9ca5e8ac5b73384ddaa483a9bbc7d7dcd656b1fa8f266634810334a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ammonia",
|
"ammonia",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
@ -2058,7 +2090,7 @@ dependencies = [
|
|||||||
"kernel32-sys",
|
"kernel32-sys",
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
"miow 0.2.1",
|
"miow 0.2.2",
|
||||||
"net2",
|
"net2",
|
||||||
"slab",
|
"slab",
|
||||||
"winapi 0.2.8",
|
"winapi 0.2.8",
|
||||||
@ -2072,7 +2104,7 @@ checksum = "0840c1c50fd55e521b247f949c241c9997709f23bd7f023b9762cd561e935656"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"mio",
|
"mio",
|
||||||
"miow 0.3.5",
|
"miow 0.3.6",
|
||||||
"winapi 0.3.9",
|
"winapi 0.3.9",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -2089,9 +2121,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "miow"
|
name = "miow"
|
||||||
version = "0.2.1"
|
version = "0.2.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919"
|
checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"kernel32-sys",
|
"kernel32-sys",
|
||||||
"net2",
|
"net2",
|
||||||
@ -2101,9 +2133,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "miow"
|
name = "miow"
|
||||||
version = "0.3.5"
|
version = "0.3.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "07b88fb9795d4d36d62a012dfbf49a8f5cf12751f36d31a9dbe66d528e58979e"
|
checksum = "5a33c1b55807fbed163481b5ba66db4b2fa6cde694a5027be10fb724206c5897"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"socket2",
|
"socket2",
|
||||||
"winapi 0.3.9",
|
"winapi 0.3.9",
|
||||||
@ -2124,13 +2156,14 @@ dependencies = [
|
|||||||
"rustc-workspace-hack",
|
"rustc-workspace-hack",
|
||||||
"rustc_version",
|
"rustc_version",
|
||||||
"shell-escape",
|
"shell-escape",
|
||||||
|
"smallvec 1.4.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "net2"
|
name = "net2"
|
||||||
version = "0.2.34"
|
version = "0.2.36"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2ba7c918ac76704fb42afcbbb43891e72731f3dcca3bef2a19786297baf14af7"
|
checksum = "d7cf75f38f16cb05ea017784dc6dbfd354f76c223dba37701734c4f5a9337d02"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 0.1.10",
|
"cfg-if 0.1.10",
|
||||||
"libc",
|
"libc",
|
||||||
@ -2174,21 +2207,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "object"
|
name = "object"
|
||||||
version = "0.20.0"
|
version = "0.22.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1ab52be62400ca80aa00285d25253d7f7c437b7375c4de678f5405d3afe82ca5"
|
checksum = "8d3b63360ec3cb337817c2dbd47ab4a0f170d285d8e5a2064600f3def1402397"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"compiler_builtins",
|
"compiler_builtins",
|
||||||
"rustc-std-workspace-alloc",
|
"rustc-std-workspace-alloc",
|
||||||
"rustc-std-workspace-core",
|
"rustc-std-workspace-core",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "object"
|
|
||||||
version = "0.21.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "37fd5004feb2ce328a52b0b3d01dbf4ffff72583493900ed15f22d4111c51693"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "once_cell"
|
name = "once_cell"
|
||||||
version = "1.4.1"
|
version = "1.4.1"
|
||||||
@ -2324,7 +2351,7 @@ dependencies = [
|
|||||||
"futures",
|
"futures",
|
||||||
"log",
|
"log",
|
||||||
"mio-named-pipes",
|
"mio-named-pipes",
|
||||||
"miow 0.3.5",
|
"miow 0.3.6",
|
||||||
"rand",
|
"rand",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-named-pipes",
|
"tokio-named-pipes",
|
||||||
@ -2693,9 +2720,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "racer"
|
name = "racer"
|
||||||
version = "2.1.40"
|
version = "2.1.41"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "68c5fb83bc092c10e12ca863ab8922b1833382d5d248aaafca779886d3396a44"
|
checksum = "a2f1a4baaaf5c4a9aa30c708c339ae293d02976d2b7f1575a59f44558d25bfea"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"clap",
|
"clap",
|
||||||
@ -3016,23 +3043,24 @@ name = "rustbook"
|
|||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
|
"env_logger 0.7.1",
|
||||||
"mdbook",
|
"mdbook",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-ap-rustc_arena"
|
name = "rustc-ap-rustc_arena"
|
||||||
version = "686.0.0"
|
version = "691.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "477085eefed2f12085c68577cc3827c8c39a31a4a750978aacb9af10f7903174"
|
checksum = "81f7b9bc5a6f79b1f230833cb4c8f8928d48c129b21df5b372c202fb826c0b5e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"smallvec 1.4.2",
|
"smallvec 1.4.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-ap-rustc_ast"
|
name = "rustc-ap-rustc_ast"
|
||||||
version = "686.0.0"
|
version = "691.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4d4ad5ec25f6b3d122354595be0d1b513f37fca3299d9b448b1db28f4a9e4b12"
|
checksum = "3d77f313e9f30af93f2737f1a99d6552e26b702c5cef3bb65e35f5b4fe5191f1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"rustc-ap-rustc_data_structures",
|
"rustc-ap-rustc_data_structures",
|
||||||
@ -3047,9 +3075,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-ap-rustc_ast_passes"
|
name = "rustc-ap-rustc_ast_passes"
|
||||||
version = "686.0.0"
|
version = "691.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0c6d8635298d7736decdb3c6e92e784d3eccde557462a9c10ac11a34fec3d756"
|
checksum = "30408fbf42fa6fbeb383d3fce0f24d2490c3d12527beb2f48e6e728765bc8695"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itertools 0.9.0",
|
"itertools 0.9.0",
|
||||||
"rustc-ap-rustc_ast",
|
"rustc-ap-rustc_ast",
|
||||||
@ -3066,9 +3094,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-ap-rustc_ast_pretty"
|
name = "rustc-ap-rustc_ast_pretty"
|
||||||
version = "686.0.0"
|
version = "691.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7a61bdb5252e1a95b7715038949e10f07ce770a436fcd497cdd9bc7255471de9"
|
checksum = "d47b8a3adcccc204578b0ee9cd2f9952921fa43977f58343913cca04cce87043"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rustc-ap-rustc_ast",
|
"rustc-ap-rustc_ast",
|
||||||
"rustc-ap-rustc_span",
|
"rustc-ap-rustc_span",
|
||||||
@ -3078,9 +3106,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-ap-rustc_attr"
|
name = "rustc-ap-rustc_attr"
|
||||||
version = "686.0.0"
|
version = "691.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "84520a16cb61bd31e9c27e87eca5d933a9c94ac84f25649bddcc19989275ab2a"
|
checksum = "66f5f53ecdbf7d8b47905936f93eb1fdae496137e94b7e4023a0b866b0e1a92d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rustc-ap-rustc_ast",
|
"rustc-ap-rustc_ast",
|
||||||
"rustc-ap-rustc_ast_pretty",
|
"rustc-ap-rustc_ast_pretty",
|
||||||
@ -3097,9 +3125,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-ap-rustc_data_structures"
|
name = "rustc-ap-rustc_data_structures"
|
||||||
version = "686.0.0"
|
version = "691.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b1cb2b6a38759cf7c0c1434c8b4cbfcab9cd24970d05f960f2ca01226ddb4d68"
|
checksum = "3aa913fa40b90157067b17dd7ddfd5df0d8566e339ffa8351a638bdf3fc7ee81"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayvec",
|
"arrayvec",
|
||||||
"bitflags",
|
"bitflags",
|
||||||
@ -3128,13 +3156,14 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-ap-rustc_errors"
|
name = "rustc-ap-rustc_errors"
|
||||||
version = "686.0.0"
|
version = "691.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "46cfb19536426bf9252827a78552d635be207a4be74f4e92832aad82d7f2135c"
|
checksum = "5d4b4956287d7c4996409b8362aa69c0c9a6853751ff00ee0a6f78223c5ef3ad"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"annotate-snippets 0.8.0",
|
"annotate-snippets 0.8.0",
|
||||||
"atty",
|
"atty",
|
||||||
"rustc-ap-rustc_data_structures",
|
"rustc-ap-rustc_data_structures",
|
||||||
|
"rustc-ap-rustc_lint_defs",
|
||||||
"rustc-ap-rustc_macros",
|
"rustc-ap-rustc_macros",
|
||||||
"rustc-ap-rustc_serialize",
|
"rustc-ap-rustc_serialize",
|
||||||
"rustc-ap-rustc_span",
|
"rustc-ap-rustc_span",
|
||||||
@ -3147,9 +3176,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-ap-rustc_expand"
|
name = "rustc-ap-rustc_expand"
|
||||||
version = "686.0.0"
|
version = "691.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6273e60042a0ef31f6cfe783c519873993eb426f055be2bc058a48b6ca3934d0"
|
checksum = "3fa908bb1b67230dd4309e93edefc6a6c2f3d8b6a195f77c47743c882114a22e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rustc-ap-rustc_ast",
|
"rustc-ap-rustc_ast",
|
||||||
"rustc-ap-rustc_ast_passes",
|
"rustc-ap-rustc_ast_passes",
|
||||||
@ -3170,9 +3199,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-ap-rustc_feature"
|
name = "rustc-ap-rustc_feature"
|
||||||
version = "686.0.0"
|
version = "691.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2936e8346157e2848305e509f38aa3ed4e97697975ef68027587f5db6a38703f"
|
checksum = "d9b7a1db115893ed7ed0db80f70d2246c1709de7854238acde76471495930f2a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rustc-ap-rustc_data_structures",
|
"rustc-ap-rustc_data_structures",
|
||||||
"rustc-ap-rustc_span",
|
"rustc-ap-rustc_span",
|
||||||
@ -3180,21 +3209,21 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-ap-rustc_fs_util"
|
name = "rustc-ap-rustc_fs_util"
|
||||||
version = "686.0.0"
|
version = "691.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9b4c3ae17776b5a5aa441ca510a650f75805e1f5569edd231caa8378552195a4"
|
checksum = "55937887cb606cc72193ea3c5feb8bbbb810d812aa233b9a1e7749155c4a3501"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-ap-rustc_graphviz"
|
name = "rustc-ap-rustc_graphviz"
|
||||||
version = "686.0.0"
|
version = "691.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5611bf0ac0ac49c2a22c959c7d8b17f85f69959293f0e8c4f753eca832fe7ad0"
|
checksum = "e39e179e616356927f0c4eda43e3a35d88476f91e1ac8e4a0a09661dbab44a6e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-ap-rustc_index"
|
name = "rustc-ap-rustc_index"
|
||||||
version = "686.0.0"
|
version = "691.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ca67cf37c427057192e451c7f912e94ae9a8ca5ad69fd481c011fad3f86982cb"
|
checksum = "572d3962d6999f3b1a71d335308e939e204339d4ad36e6ebe7a591c9d4329f5d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayvec",
|
"arrayvec",
|
||||||
"rustc-ap-rustc_macros",
|
"rustc-ap-rustc_macros",
|
||||||
@ -3203,18 +3232,32 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-ap-rustc_lexer"
|
name = "rustc-ap-rustc_lexer"
|
||||||
version = "686.0.0"
|
version = "691.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a5b04cd2159495584d976d501c5394498470c2e94e4f0cebb8186562d407a678"
|
checksum = "44bc89d9ca7a78fb82e103b389362c55f03800745f8ba14e068b805cfaf783ec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-xid",
|
"unicode-xid",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-ap-rustc_macros"
|
name = "rustc-ap-rustc_lint_defs"
|
||||||
version = "686.0.0"
|
version = "691.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "61ec6d623853449acd3c65050d249d3674edab5f6e4d9f074c7bac183269f9c8"
|
checksum = "7d39bda92aabd77e49ac8ad5e24fccf9d7245b8ff2bf1249ab98733e2e5a2863"
|
||||||
|
dependencies = [
|
||||||
|
"rustc-ap-rustc_ast",
|
||||||
|
"rustc-ap-rustc_data_structures",
|
||||||
|
"rustc-ap-rustc_macros",
|
||||||
|
"rustc-ap-rustc_serialize",
|
||||||
|
"rustc-ap-rustc_span",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc-ap-rustc_macros"
|
||||||
|
version = "691.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a3295fbc9625197494e356e92d8ac08370eddafa60189861c7b2f084b3b5a6b8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -3224,9 +3267,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-ap-rustc_parse"
|
name = "rustc-ap-rustc_parse"
|
||||||
version = "686.0.0"
|
version = "691.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ca524bafce4b04d2b49fee2d40b4b26c3ebab9f1a4f731fdf561f00617862f02"
|
checksum = "9ff5d0094396844efead43303a6eb25b8a4962e2c80fb0ea4a86e4101fbfd404"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"rustc-ap-rustc_ast",
|
"rustc-ap-rustc_ast",
|
||||||
@ -3244,9 +3287,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-ap-rustc_serialize"
|
name = "rustc-ap-rustc_serialize"
|
||||||
version = "686.0.0"
|
version = "691.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c67920561e58f98c4de864407c92b2dd05ace5d5e5301e17444f10f742c005b7"
|
checksum = "2d5cff6709a8b51a3730288a9ead17cabe8146b1c787db52298447ef7890140a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"smallvec 1.4.2",
|
"smallvec 1.4.2",
|
||||||
@ -3254,9 +3297,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-ap-rustc_session"
|
name = "rustc-ap-rustc_session"
|
||||||
version = "686.0.0"
|
version = "691.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0762fd855792e06ef639327237898e4e092ad68150e6a8e19aeb7dc06276ad7a"
|
checksum = "36bb15ef12174b5ed6419a7e4260a899ce8927e8c8fd1f0cddf178818737dcdf"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"getopts",
|
"getopts",
|
||||||
@ -3266,6 +3309,7 @@ dependencies = [
|
|||||||
"rustc-ap-rustc_errors",
|
"rustc-ap-rustc_errors",
|
||||||
"rustc-ap-rustc_feature",
|
"rustc-ap-rustc_feature",
|
||||||
"rustc-ap-rustc_fs_util",
|
"rustc-ap-rustc_fs_util",
|
||||||
|
"rustc-ap-rustc_lint_defs",
|
||||||
"rustc-ap-rustc_macros",
|
"rustc-ap-rustc_macros",
|
||||||
"rustc-ap-rustc_serialize",
|
"rustc-ap-rustc_serialize",
|
||||||
"rustc-ap-rustc_span",
|
"rustc-ap-rustc_span",
|
||||||
@ -3275,28 +3319,29 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-ap-rustc_span"
|
name = "rustc-ap-rustc_span"
|
||||||
version = "686.0.0"
|
version = "691.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0bf3db7b4ca5d21c14c45475df155e5e020c9a3760346945a662c9a9053b49c8"
|
checksum = "104d349a32be9cfd3d39a5a70ad6c5e682ce262fc5cc8717d35a01e980c0d8b2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 0.1.10",
|
"cfg-if 0.1.10",
|
||||||
"md-5 0.8.0",
|
"md-5",
|
||||||
"rustc-ap-rustc_arena",
|
"rustc-ap-rustc_arena",
|
||||||
"rustc-ap-rustc_data_structures",
|
"rustc-ap-rustc_data_structures",
|
||||||
"rustc-ap-rustc_index",
|
"rustc-ap-rustc_index",
|
||||||
"rustc-ap-rustc_macros",
|
"rustc-ap-rustc_macros",
|
||||||
"rustc-ap-rustc_serialize",
|
"rustc-ap-rustc_serialize",
|
||||||
"scoped-tls",
|
"scoped-tls",
|
||||||
"sha-1 0.8.2",
|
"sha-1 0.9.1",
|
||||||
|
"sha2",
|
||||||
"tracing",
|
"tracing",
|
||||||
"unicode-width",
|
"unicode-width",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-ap-rustc_target"
|
name = "rustc-ap-rustc_target"
|
||||||
version = "686.0.0"
|
version = "691.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3aa6560bb9742b276064d67ab9edb5766ecb303f8ae3854835ad3fad4b432188"
|
checksum = "9d7ac4ded9a6aecb534744c836a160497985f0d53b272581e95e7890d31b9e17"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"rustc-ap-rustc_data_structures",
|
"rustc-ap-rustc_data_structures",
|
||||||
@ -3356,6 +3401,12 @@ dependencies = [
|
|||||||
"num_cpus",
|
"num_cpus",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc-semver"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5be1bdc7edf596692617627bbfeaba522131b18e06ca4df2b6b689e3c5d5ce84"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-std-workspace-alloc"
|
name = "rustc-std-workspace-alloc"
|
||||||
version = "1.99.0"
|
version = "1.99.0"
|
||||||
@ -3383,6 +3434,8 @@ version = "1.0.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"crossbeam-utils 0.7.2",
|
"crossbeam-utils 0.7.2",
|
||||||
|
"libc",
|
||||||
|
"libz-sys",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"serde",
|
"serde",
|
||||||
@ -3794,7 +3847,7 @@ dependencies = [
|
|||||||
"rustc_target",
|
"rustc_target",
|
||||||
"rustc_trait_selection",
|
"rustc_trait_selection",
|
||||||
"rustc_traits",
|
"rustc_traits",
|
||||||
"rustc_ty",
|
"rustc_ty_utils",
|
||||||
"rustc_typeck",
|
"rustc_typeck",
|
||||||
"smallvec 1.4.2",
|
"smallvec 1.4.2",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
@ -3823,6 +3876,7 @@ dependencies = [
|
|||||||
"rustc_hir",
|
"rustc_hir",
|
||||||
"rustc_index",
|
"rustc_index",
|
||||||
"rustc_middle",
|
"rustc_middle",
|
||||||
|
"rustc_parse_format",
|
||||||
"rustc_session",
|
"rustc_session",
|
||||||
"rustc_span",
|
"rustc_span",
|
||||||
"rustc_target",
|
"rustc_target",
|
||||||
@ -3914,6 +3968,7 @@ dependencies = [
|
|||||||
"rustc_session",
|
"rustc_session",
|
||||||
"rustc_span",
|
"rustc_span",
|
||||||
"rustc_target",
|
"rustc_target",
|
||||||
|
"rustc_type_ir",
|
||||||
"smallvec 1.4.2",
|
"smallvec 1.4.2",
|
||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
@ -3922,7 +3977,9 @@ dependencies = [
|
|||||||
name = "rustc_mir"
|
name = "rustc_mir"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"coverage_test_macros",
|
||||||
"either",
|
"either",
|
||||||
|
"gsgdt",
|
||||||
"itertools 0.9.0",
|
"itertools 0.9.0",
|
||||||
"polonius-engine",
|
"polonius-engine",
|
||||||
"regex",
|
"regex",
|
||||||
@ -4006,6 +4063,7 @@ dependencies = [
|
|||||||
"rustc_errors",
|
"rustc_errors",
|
||||||
"rustc_hir",
|
"rustc_hir",
|
||||||
"rustc_index",
|
"rustc_index",
|
||||||
|
"rustc_lexer",
|
||||||
"rustc_middle",
|
"rustc_middle",
|
||||||
"rustc_serialize",
|
"rustc_serialize",
|
||||||
"rustc_session",
|
"rustc_session",
|
||||||
@ -4138,7 +4196,7 @@ name = "rustc_span"
|
|||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 0.1.10",
|
"cfg-if 0.1.10",
|
||||||
"md-5 0.9.1",
|
"md-5",
|
||||||
"rustc_arena",
|
"rustc_arena",
|
||||||
"rustc_data_structures",
|
"rustc_data_structures",
|
||||||
"rustc_index",
|
"rustc_index",
|
||||||
@ -4231,7 +4289,7 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc_ty"
|
name = "rustc_ty_utils"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rustc_data_structures",
|
"rustc_data_structures",
|
||||||
@ -4246,6 +4304,16 @@ dependencies = [
|
|||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc_type_ir"
|
||||||
|
version = "0.0.0"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"rustc_data_structures",
|
||||||
|
"rustc_index",
|
||||||
|
"rustc_serialize",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc_typeck"
|
name = "rustc_typeck"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
@ -4329,7 +4397,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustfmt-nightly"
|
name = "rustfmt-nightly"
|
||||||
version = "1.4.25"
|
version = "1.4.30"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"annotate-snippets 0.6.1",
|
"annotate-snippets 0.6.1",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
@ -4404,6 +4472,29 @@ version = "1.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "security-framework"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c1759c2e3c8580017a484a7ac56d3abc5a6c1feadf88db2f3633f12ae4268c69"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"core-foundation",
|
||||||
|
"core-foundation-sys",
|
||||||
|
"libc",
|
||||||
|
"security-framework-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "security-framework-sys"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f99b9d5e26d2a71633cc4f2ebae7cc9f874044e0c351a27e17892d76dce5678b"
|
||||||
|
dependencies = [
|
||||||
|
"core-foundation-sys",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "semver"
|
name = "semver"
|
||||||
version = "0.9.0"
|
version = "0.9.0"
|
||||||
@ -4451,18 +4542,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.115"
|
version = "1.0.118"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e54c9a88f2da7238af84b5101443f0c0d0a3bbdc455e34a5c9497b1903ed55d5"
|
checksum = "06c64263859d87aa2eb554587e2d23183398d617427327cf2b3d0ed8c69e4800"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.115"
|
version = "1.0.118"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "609feed1d0a73cc36a0182a840a9b37b4a82f0b1150369f0536a9e3f2a31dc48"
|
checksum = "c84d3526699cd55261af4b941e4e725444df67aa4f9e6a3564f18030d12672df"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -4614,9 +4705,9 @@ checksum = "da73c8f77aebc0e40c300b93f0a5f1bece7a248a36eee287d4e095f35c7b7d6e"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "socket2"
|
name = "socket2"
|
||||||
version = "0.3.12"
|
version = "0.3.16"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "03088793f677dce356f3ccc2edb1b314ad191ab702a5de3faf49304f7e104918"
|
checksum = "7fd8b795c389288baa5f355489c65e71fd48a02104600d15c4cfbc561e9e429d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if 0.1.10",
|
"cfg-if 0.1.10",
|
||||||
"libc",
|
"libc",
|
||||||
@ -4658,7 +4749,7 @@ dependencies = [
|
|||||||
"hermit-abi",
|
"hermit-abi",
|
||||||
"libc",
|
"libc",
|
||||||
"miniz_oxide",
|
"miniz_oxide",
|
||||||
"object 0.20.0",
|
"object",
|
||||||
"panic_abort",
|
"panic_abort",
|
||||||
"panic_unwind",
|
"panic_unwind",
|
||||||
"profiler_builtins",
|
"profiler_builtins",
|
||||||
|
@ -20,6 +20,9 @@ members = [
|
|||||||
"src/tools/rust-installer",
|
"src/tools/rust-installer",
|
||||||
"src/tools/rust-demangler",
|
"src/tools/rust-demangler",
|
||||||
"src/tools/cargo",
|
"src/tools/cargo",
|
||||||
|
"src/tools/cargo/crates/credential/cargo-credential-1password",
|
||||||
|
"src/tools/cargo/crates/credential/cargo-credential-macos-keychain",
|
||||||
|
"src/tools/cargo/crates/credential/cargo-credential-wincred",
|
||||||
"src/tools/rustdoc",
|
"src/tools/rustdoc",
|
||||||
"src/tools/rls",
|
"src/tools/rls",
|
||||||
"src/tools/rustfmt",
|
"src/tools/rustfmt",
|
||||||
|
122
RELEASES.md
122
RELEASES.md
@ -1,3 +1,123 @@
|
|||||||
|
Version 1.50.0 (2021-02-11)
|
||||||
|
============================
|
||||||
|
|
||||||
|
Language
|
||||||
|
-----------------------
|
||||||
|
- [You can now use `const` values for `x` in `[x; N]` array expressions.][79270]
|
||||||
|
This has been technically possible since 1.38.0, as it was unintentionally stabilized.
|
||||||
|
- [Assignments to `ManuallyDrop<T>` union fields are now considered safe.][78068]
|
||||||
|
|
||||||
|
Compiler
|
||||||
|
-----------------------
|
||||||
|
- [Added tier 3\* support for the `armv5te-unknown-linux-uclibceabi` target.][78142]
|
||||||
|
- [Added tier 3 support for the `aarch64-apple-ios-macabi` target.][77484]
|
||||||
|
- [The `x86_64-unknown-freebsd` is now built with the full toolset.][79484]
|
||||||
|
|
||||||
|
\* Refer to Rust's [platform support page][forge-platform-support] for more
|
||||||
|
information on Rust's tiered platform support.
|
||||||
|
|
||||||
|
Libraries
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
- [`proc_macro::Punct` now implements `PartialEq<char>`.][78636]
|
||||||
|
- [`ops::{Index, IndexMut}` are now implemented for fixed sized arrays of any length.][74989]
|
||||||
|
- [On Unix platforms, the `std::fs::File` type now has a "niche" of `-1`.][74699]
|
||||||
|
This value cannot be a valid file descriptor, and now means `Option<File>` takes
|
||||||
|
up the same amount of space as `File`.
|
||||||
|
|
||||||
|
Stabilized APIs
|
||||||
|
---------------
|
||||||
|
|
||||||
|
- [`bool::then`]
|
||||||
|
- [`btree_map::Entry::or_insert_with_key`]
|
||||||
|
- [`f32::clamp`]
|
||||||
|
- [`f64::clamp`]
|
||||||
|
- [`hash_map::Entry::or_insert_with_key`]
|
||||||
|
- [`Ord::clamp`]
|
||||||
|
- [`RefCell::take`]
|
||||||
|
- [`slice::fill`]
|
||||||
|
- [`UnsafeCell::get_mut`]
|
||||||
|
|
||||||
|
The following previously stable methods are now `const`.
|
||||||
|
|
||||||
|
- [`IpAddr::is_ipv4`]
|
||||||
|
- [`IpAddr::is_ipv6`]
|
||||||
|
- [`Layout::size`]
|
||||||
|
- [`Layout::align`]
|
||||||
|
- [`Layout::from_size_align`]
|
||||||
|
- `pow` for all integer types.
|
||||||
|
- `checked_pow` for all integer types.
|
||||||
|
- `saturating_pow` for all integer types.
|
||||||
|
- `wrapping_pow` for all integer types.
|
||||||
|
- `next_power_of_two` for all unsigned integer types.
|
||||||
|
- `checked_power_of_two` for all unsigned integer types.
|
||||||
|
|
||||||
|
Cargo
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
- [Added the `[build.rustc-workspace-wrapper]` option.][cargo/8976]
|
||||||
|
This option sets a wrapper to execute instead of `rustc`, for workspace members only.
|
||||||
|
- [`cargo:rerun-if-changed` will now, if provided a directory, scan the entire
|
||||||
|
contents of that directory for changes.][cargo/8973]
|
||||||
|
- [Added the `--workspace` flag to the `cargo update` command.][cargo/8725]
|
||||||
|
|
||||||
|
Misc
|
||||||
|
----
|
||||||
|
|
||||||
|
- [The search results tab and the help button are focusable with keyboard in rustdoc.][79896]
|
||||||
|
- [Running tests will now print the total time taken to execute.][75752]
|
||||||
|
|
||||||
|
Compatibility Notes
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
- [The `compare_and_swap` method on atomics has been deprecated.][79261] It's
|
||||||
|
recommended to use the `compare_exchange` and `compare_exchange_weak` methods instead.
|
||||||
|
- [Changes in how `TokenStream`s are checked have fixed some cases where you could write
|
||||||
|
unhygenic `macro_rules!` macros.][79472]
|
||||||
|
- [`#![test]` as an inner attribute is now considered unstable like other inner macro
|
||||||
|
attributes, and reports an error by default through the `soft_unstable` lint.][79003]
|
||||||
|
- [Overriding a `forbid` lint at the same level that it was set is now a hard error.][78864]
|
||||||
|
- [Dropped support for all cloudabi targets.][78439]
|
||||||
|
- [You can no longer intercept `panic!` calls by supplying your own macro.][78343] It's
|
||||||
|
recommended to use the `#[panic_handler]` attribute to provide your own implementation.
|
||||||
|
- [Semi-colons after item statements (e.g. `struct Foo {};`) now produce a warning.][78296]
|
||||||
|
|
||||||
|
[74989]: https://github.com/rust-lang/rust/pull/74989
|
||||||
|
[79261]: https://github.com/rust-lang/rust/pull/79261
|
||||||
|
[79896]: https://github.com/rust-lang/rust/pull/79896
|
||||||
|
[79484]: https://github.com/rust-lang/rust/pull/79484
|
||||||
|
[79472]: https://github.com/rust-lang/rust/pull/79472
|
||||||
|
[79270]: https://github.com/rust-lang/rust/pull/79270
|
||||||
|
[79003]: https://github.com/rust-lang/rust/pull/79003
|
||||||
|
[78864]: https://github.com/rust-lang/rust/pull/78864
|
||||||
|
[78636]: https://github.com/rust-lang/rust/pull/78636
|
||||||
|
[78439]: https://github.com/rust-lang/rust/pull/78439
|
||||||
|
[78343]: https://github.com/rust-lang/rust/pull/78343
|
||||||
|
[78296]: https://github.com/rust-lang/rust/pull/78296
|
||||||
|
[78068]: https://github.com/rust-lang/rust/pull/78068
|
||||||
|
[75752]: https://github.com/rust-lang/rust/pull/75752
|
||||||
|
[74699]: https://github.com/rust-lang/rust/pull/74699
|
||||||
|
[78142]: https://github.com/rust-lang/rust/pull/78142
|
||||||
|
[77484]: https://github.com/rust-lang/rust/pull/77484
|
||||||
|
[cargo/8976]: https://github.com/rust-lang/cargo/pull/8976
|
||||||
|
[cargo/8973]: https://github.com/rust-lang/cargo/pull/8973
|
||||||
|
[cargo/8725]: https://github.com/rust-lang/cargo/pull/8725
|
||||||
|
[`IpAddr::is_ipv4`]: https://doc.rust-lang.org/stable/std/net/enum.IpAddr.html#method.is_ipv4
|
||||||
|
[`IpAddr::is_ipv6`]: https://doc.rust-lang.org/stable/std/net/enum.IpAddr.html#method.is_ipv6
|
||||||
|
[`Layout::align`]: https://doc.rust-lang.org/stable/std/alloc/struct.Layout.html#method.align
|
||||||
|
[`Layout::from_size_align`]: https://doc.rust-lang.org/stable/std/alloc/struct.Layout.html#method.from_size_align
|
||||||
|
[`Layout::size`]: https://doc.rust-lang.org/stable/std/alloc/struct.Layout.html#method.size
|
||||||
|
[`Ord::clamp`]: https://doc.rust-lang.org/stable/std/cmp/trait.Ord.html#method.clamp
|
||||||
|
[`RefCell::take`]: https://doc.rust-lang.org/stable/std/cell/struct.RefCell.html#method.take
|
||||||
|
[`UnsafeCell::get_mut`]: https://doc.rust-lang.org/stable/std/cell/struct.UnsafeCell.html#method.get_mut
|
||||||
|
[`bool::then`]: https://doc.rust-lang.org/stable/std/primitive.bool.html#method.then
|
||||||
|
[`btree_map::Entry::or_insert_with_key`]: https://doc.rust-lang.org/stable/std/collections/btree_map/enum.Entry.html#method.or_insert_with_key
|
||||||
|
[`f32::clamp`]: https://doc.rust-lang.org/stable/std/primitive.f32.html#method.clamp
|
||||||
|
[`f64::clamp`]: https://doc.rust-lang.org/stable/std/primitive.f64.html#method.clamp
|
||||||
|
[`hash_map::Entry::or_insert_with_key`]: https://doc.rust-lang.org/stable/std/collections/hash_map/enum.Entry.html#method.or_insert_with_key
|
||||||
|
[`slice::fill`]: https://doc.rust-lang.org/stable/std/primitive.slice.html#method.fill
|
||||||
|
|
||||||
|
|
||||||
Version 1.49.0 (2020-12-31)
|
Version 1.49.0 (2020-12-31)
|
||||||
============================
|
============================
|
||||||
|
|
||||||
@ -45,7 +165,6 @@ Libraries
|
|||||||
|
|
||||||
- [`RangeInclusive` now checks for exhaustion when calling `contains` and indexing.][78109]
|
- [`RangeInclusive` now checks for exhaustion when calling `contains` and indexing.][78109]
|
||||||
- [`ToString::to_string` now no longer shrinks the internal buffer in the default implementation.][77997]
|
- [`ToString::to_string` now no longer shrinks the internal buffer in the default implementation.][77997]
|
||||||
- [`ops::{Index, IndexMut}` are now implemented for fixed sized arrays of any length.][74989]
|
|
||||||
|
|
||||||
Stabilized APIs
|
Stabilized APIs
|
||||||
---------------
|
---------------
|
||||||
@ -110,7 +229,6 @@ related tools.
|
|||||||
[76199]: https://github.com/rust-lang/rust/pull/76199
|
[76199]: https://github.com/rust-lang/rust/pull/76199
|
||||||
[76119]: https://github.com/rust-lang/rust/pull/76119
|
[76119]: https://github.com/rust-lang/rust/pull/76119
|
||||||
[75914]: https://github.com/rust-lang/rust/pull/75914
|
[75914]: https://github.com/rust-lang/rust/pull/75914
|
||||||
[74989]: https://github.com/rust-lang/rust/pull/74989
|
|
||||||
[79004]: https://github.com/rust-lang/rust/pull/79004
|
[79004]: https://github.com/rust-lang/rust/pull/79004
|
||||||
[78676]: https://github.com/rust-lang/rust/pull/78676
|
[78676]: https://github.com/rust-lang/rust/pull/78676
|
||||||
[79904]: https://github.com/rust-lang/rust/issues/79904
|
[79904]: https://github.com/rust-lang/rust/issues/79904
|
||||||
|
@ -11,9 +11,13 @@
|
|||||||
html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/",
|
html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/",
|
||||||
test(no_crate_inject, attr(deny(warnings)))
|
test(no_crate_inject, attr(deny(warnings)))
|
||||||
)]
|
)]
|
||||||
|
#![feature(array_value_iter_slice)]
|
||||||
#![feature(dropck_eyepatch)]
|
#![feature(dropck_eyepatch)]
|
||||||
#![feature(new_uninit)]
|
#![feature(new_uninit)]
|
||||||
#![feature(maybe_uninit_slice)]
|
#![feature(maybe_uninit_slice)]
|
||||||
|
#![feature(array_value_iter)]
|
||||||
|
#![feature(min_const_generics)]
|
||||||
|
#![feature(min_specialization)]
|
||||||
#![cfg_attr(test, feature(test))]
|
#![cfg_attr(test, feature(test))]
|
||||||
|
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
@ -114,6 +118,72 @@ impl<T> Default for TypedArena<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trait IterExt<T> {
|
||||||
|
fn alloc_from_iter(self, arena: &TypedArena<T>) -> &mut [T];
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I, T> IterExt<T> for I
|
||||||
|
where
|
||||||
|
I: IntoIterator<Item = T>,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
default fn alloc_from_iter(self, arena: &TypedArena<T>) -> &mut [T] {
|
||||||
|
let vec: SmallVec<[_; 8]> = self.into_iter().collect();
|
||||||
|
vec.alloc_from_iter(arena)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, const N: usize> IterExt<T> for std::array::IntoIter<T, N> {
|
||||||
|
#[inline]
|
||||||
|
fn alloc_from_iter(self, arena: &TypedArena<T>) -> &mut [T] {
|
||||||
|
let len = self.len();
|
||||||
|
if len == 0 {
|
||||||
|
return &mut [];
|
||||||
|
}
|
||||||
|
// Move the content to the arena by copying and then forgetting it
|
||||||
|
unsafe {
|
||||||
|
let start_ptr = arena.alloc_raw_slice(len);
|
||||||
|
self.as_slice().as_ptr().copy_to_nonoverlapping(start_ptr, len);
|
||||||
|
mem::forget(self);
|
||||||
|
slice::from_raw_parts_mut(start_ptr, len)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> IterExt<T> for Vec<T> {
|
||||||
|
#[inline]
|
||||||
|
fn alloc_from_iter(mut self, arena: &TypedArena<T>) -> &mut [T] {
|
||||||
|
let len = self.len();
|
||||||
|
if len == 0 {
|
||||||
|
return &mut [];
|
||||||
|
}
|
||||||
|
// Move the content to the arena by copying and then forgetting it
|
||||||
|
unsafe {
|
||||||
|
let start_ptr = arena.alloc_raw_slice(len);
|
||||||
|
self.as_ptr().copy_to_nonoverlapping(start_ptr, len);
|
||||||
|
self.set_len(0);
|
||||||
|
slice::from_raw_parts_mut(start_ptr, len)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<A: smallvec::Array> IterExt<A::Item> for SmallVec<A> {
|
||||||
|
#[inline]
|
||||||
|
fn alloc_from_iter(mut self, arena: &TypedArena<A::Item>) -> &mut [A::Item] {
|
||||||
|
let len = self.len();
|
||||||
|
if len == 0 {
|
||||||
|
return &mut [];
|
||||||
|
}
|
||||||
|
// Move the content to the arena by copying and then forgetting it
|
||||||
|
unsafe {
|
||||||
|
let start_ptr = arena.alloc_raw_slice(len);
|
||||||
|
self.as_ptr().copy_to_nonoverlapping(start_ptr, len);
|
||||||
|
self.set_len(0);
|
||||||
|
slice::from_raw_parts_mut(start_ptr, len)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T> TypedArena<T> {
|
impl<T> TypedArena<T> {
|
||||||
/// Allocates an object in the `TypedArena`, returning a reference to it.
|
/// Allocates an object in the `TypedArena`, returning a reference to it.
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -191,19 +261,7 @@ impl<T> TypedArena<T> {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn alloc_from_iter<I: IntoIterator<Item = T>>(&self, iter: I) -> &mut [T] {
|
pub fn alloc_from_iter<I: IntoIterator<Item = T>>(&self, iter: I) -> &mut [T] {
|
||||||
assert!(mem::size_of::<T>() != 0);
|
assert!(mem::size_of::<T>() != 0);
|
||||||
let mut vec: SmallVec<[_; 8]> = iter.into_iter().collect();
|
iter.alloc_from_iter(self)
|
||||||
if vec.is_empty() {
|
|
||||||
return &mut [];
|
|
||||||
}
|
|
||||||
// Move the content to the arena by copying it and then forgetting
|
|
||||||
// the content of the SmallVec
|
|
||||||
unsafe {
|
|
||||||
let len = vec.len();
|
|
||||||
let start_ptr = self.alloc_raw_slice(len);
|
|
||||||
vec.as_ptr().copy_to_nonoverlapping(start_ptr, len);
|
|
||||||
vec.set_len(0);
|
|
||||||
slice::from_raw_parts_mut(start_ptr, len)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Grows the arena.
|
/// Grows the arena.
|
||||||
|
@ -24,7 +24,7 @@ pub use UnsafeSource::*;
|
|||||||
|
|
||||||
use crate::ptr::P;
|
use crate::ptr::P;
|
||||||
use crate::token::{self, CommentKind, DelimToken};
|
use crate::token::{self, CommentKind, DelimToken};
|
||||||
use crate::tokenstream::{DelimSpan, LazyTokenStream, TokenStream, TokenTree};
|
use crate::tokenstream::{DelimSpan, LazyTokenStream, TokenStream};
|
||||||
|
|
||||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||||
use rustc_data_structures::stack::ensure_sufficient_stack;
|
use rustc_data_structures::stack::ensure_sufficient_stack;
|
||||||
@ -39,7 +39,6 @@ use rustc_span::{Span, DUMMY_SP};
|
|||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::iter;
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
@ -901,10 +900,39 @@ pub struct Stmt {
|
|||||||
pub id: NodeId,
|
pub id: NodeId,
|
||||||
pub kind: StmtKind,
|
pub kind: StmtKind,
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub tokens: Option<LazyTokenStream>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Stmt {
|
impl Stmt {
|
||||||
|
pub fn tokens(&self) -> Option<&LazyTokenStream> {
|
||||||
|
match self.kind {
|
||||||
|
StmtKind::Local(ref local) => local.tokens.as_ref(),
|
||||||
|
StmtKind::Item(ref item) => item.tokens.as_ref(),
|
||||||
|
StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => expr.tokens.as_ref(),
|
||||||
|
StmtKind::Empty => None,
|
||||||
|
StmtKind::MacCall(ref mac) => mac.tokens.as_ref(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn tokens_mut(&mut self) -> Option<&mut LazyTokenStream> {
|
||||||
|
match self.kind {
|
||||||
|
StmtKind::Local(ref mut local) => local.tokens.as_mut(),
|
||||||
|
StmtKind::Item(ref mut item) => item.tokens.as_mut(),
|
||||||
|
StmtKind::Expr(ref mut expr) | StmtKind::Semi(ref mut expr) => expr.tokens.as_mut(),
|
||||||
|
StmtKind::Empty => None,
|
||||||
|
StmtKind::MacCall(ref mut mac) => mac.tokens.as_mut(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_tokens(&mut self, tokens: Option<LazyTokenStream>) {
|
||||||
|
match self.kind {
|
||||||
|
StmtKind::Local(ref mut local) => local.tokens = tokens,
|
||||||
|
StmtKind::Item(ref mut item) => item.tokens = tokens,
|
||||||
|
StmtKind::Expr(ref mut expr) | StmtKind::Semi(ref mut expr) => expr.tokens = tokens,
|
||||||
|
StmtKind::Empty => {}
|
||||||
|
StmtKind::MacCall(ref mut mac) => mac.tokens = tokens,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn has_trailing_semicolon(&self) -> bool {
|
pub fn has_trailing_semicolon(&self) -> bool {
|
||||||
match &self.kind {
|
match &self.kind {
|
||||||
StmtKind::Semi(_) => true,
|
StmtKind::Semi(_) => true,
|
||||||
@ -912,18 +940,25 @@ impl Stmt {
|
|||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Converts a parsed `Stmt` to a `Stmt` with
|
||||||
|
/// a trailing semicolon.
|
||||||
|
///
|
||||||
|
/// This only modifies the parsed AST struct, not the attached
|
||||||
|
/// `LazyTokenStream`. The parser is responsible for calling
|
||||||
|
/// `CreateTokenStream::add_trailing_semi` when there is actually
|
||||||
|
/// a semicolon in the tokenstream.
|
||||||
pub fn add_trailing_semicolon(mut self) -> Self {
|
pub fn add_trailing_semicolon(mut self) -> Self {
|
||||||
self.kind = match self.kind {
|
self.kind = match self.kind {
|
||||||
StmtKind::Expr(expr) => StmtKind::Semi(expr),
|
StmtKind::Expr(expr) => StmtKind::Semi(expr),
|
||||||
StmtKind::MacCall(mac) => {
|
StmtKind::MacCall(mac) => {
|
||||||
StmtKind::MacCall(mac.map(|MacCallStmt { mac, style: _, attrs }| MacCallStmt {
|
StmtKind::MacCall(mac.map(|MacCallStmt { mac, style: _, attrs, tokens }| {
|
||||||
mac,
|
MacCallStmt { mac, style: MacStmtStyle::Semicolon, attrs, tokens }
|
||||||
style: MacStmtStyle::Semicolon,
|
|
||||||
attrs,
|
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
kind => kind,
|
kind => kind,
|
||||||
};
|
};
|
||||||
|
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -963,6 +998,7 @@ pub struct MacCallStmt {
|
|||||||
pub mac: MacCall,
|
pub mac: MacCall,
|
||||||
pub style: MacStmtStyle,
|
pub style: MacStmtStyle,
|
||||||
pub attrs: AttrVec,
|
pub attrs: AttrVec,
|
||||||
|
pub tokens: Option<LazyTokenStream>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug)]
|
#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug)]
|
||||||
@ -988,6 +1024,7 @@ pub struct Local {
|
|||||||
pub init: Option<P<Expr>>,
|
pub init: Option<P<Expr>>,
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub attrs: AttrVec,
|
pub attrs: AttrVec,
|
||||||
|
pub tokens: Option<LazyTokenStream>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An arm of a 'match'.
|
/// An arm of a 'match'.
|
||||||
@ -1192,6 +1229,7 @@ impl Expr {
|
|||||||
ExprKind::Field(..) => ExprPrecedence::Field,
|
ExprKind::Field(..) => ExprPrecedence::Field,
|
||||||
ExprKind::Index(..) => ExprPrecedence::Index,
|
ExprKind::Index(..) => ExprPrecedence::Index,
|
||||||
ExprKind::Range(..) => ExprPrecedence::Range,
|
ExprKind::Range(..) => ExprPrecedence::Range,
|
||||||
|
ExprKind::Underscore => ExprPrecedence::Path,
|
||||||
ExprKind::Path(..) => ExprPrecedence::Path,
|
ExprKind::Path(..) => ExprPrecedence::Path,
|
||||||
ExprKind::AddrOf(..) => ExprPrecedence::AddrOf,
|
ExprKind::AddrOf(..) => ExprPrecedence::AddrOf,
|
||||||
ExprKind::Break(..) => ExprPrecedence::Break,
|
ExprKind::Break(..) => ExprPrecedence::Break,
|
||||||
@ -1324,6 +1362,8 @@ pub enum ExprKind {
|
|||||||
Index(P<Expr>, P<Expr>),
|
Index(P<Expr>, P<Expr>),
|
||||||
/// A range (e.g., `1..2`, `1..`, `..2`, `1..=2`, `..=2`; and `..` in destructuring assingment).
|
/// A range (e.g., `1..2`, `1..`, `..2`, `1..=2`, `..=2`; and `..` in destructuring assingment).
|
||||||
Range(Option<P<Expr>>, Option<P<Expr>>, RangeLimits),
|
Range(Option<P<Expr>>, Option<P<Expr>>, RangeLimits),
|
||||||
|
/// An underscore, used in destructuring assignment to ignore a value.
|
||||||
|
Underscore,
|
||||||
|
|
||||||
/// Variable reference, possibly containing `::` and/or type
|
/// Variable reference, possibly containing `::` and/or type
|
||||||
/// parameters (e.g., `foo::bar::<baz>`).
|
/// parameters (e.g., `foo::bar::<baz>`).
|
||||||
@ -1473,20 +1513,6 @@ impl MacArgs {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tokens together with the delimiters or `=`.
|
|
||||||
/// Use of this method generally means that something suboptimal or hacky is happening.
|
|
||||||
pub fn outer_tokens(&self) -> TokenStream {
|
|
||||||
match *self {
|
|
||||||
MacArgs::Empty => TokenStream::default(),
|
|
||||||
MacArgs::Delimited(dspan, delim, ref tokens) => {
|
|
||||||
TokenTree::Delimited(dspan, delim.to_token(), tokens.clone()).into()
|
|
||||||
}
|
|
||||||
MacArgs::Eq(eq_span, ref tokens) => {
|
|
||||||
iter::once(TokenTree::token(token::Eq, eq_span)).chain(tokens.trees()).collect()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Whether a macro with these arguments needs a semicolon
|
/// Whether a macro with these arguments needs a semicolon
|
||||||
/// when used as a standalone item or statement.
|
/// when used as a standalone item or statement.
|
||||||
pub fn need_semicolon(&self) -> bool {
|
pub fn need_semicolon(&self) -> bool {
|
||||||
@ -1842,6 +1868,7 @@ impl UintTy {
|
|||||||
pub struct AssocTyConstraint {
|
pub struct AssocTyConstraint {
|
||||||
pub id: NodeId,
|
pub id: NodeId,
|
||||||
pub ident: Ident,
|
pub ident: Ident,
|
||||||
|
pub gen_args: Option<GenericArgs>,
|
||||||
pub kind: AssocTyConstraintKind,
|
pub kind: AssocTyConstraintKind,
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
@ -115,6 +115,10 @@ impl NestedMetaItem {
|
|||||||
pub fn is_meta_item_list(&self) -> bool {
|
pub fn is_meta_item_list(&self) -> bool {
|
||||||
self.meta_item_list().is_some()
|
self.meta_item_list().is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn name_value_literal_span(&self) -> Option<Span> {
|
||||||
|
self.meta_item()?.name_value_literal_span()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Attribute {
|
impl Attribute {
|
||||||
@ -175,6 +179,22 @@ impl Attribute {
|
|||||||
pub fn is_value_str(&self) -> bool {
|
pub fn is_value_str(&self) -> bool {
|
||||||
self.value_str().is_some()
|
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 {
|
impl MetaItem {
|
||||||
@ -227,6 +247,17 @@ impl MetaItem {
|
|||||||
pub fn is_value_str(&self) -> bool {
|
pub fn is_value_str(&self) -> bool {
|
||||||
self.value_str().is_some()
|
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> {
|
||||||
|
Some(self.name_value_literal()?.span)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AttrItem {
|
impl AttrItem {
|
||||||
|
@ -34,7 +34,6 @@ macro_rules! unwrap_or {
|
|||||||
pub mod util {
|
pub mod util {
|
||||||
pub mod classify;
|
pub mod classify;
|
||||||
pub mod comments;
|
pub mod comments;
|
||||||
pub mod lev_distance;
|
|
||||||
pub mod literal;
|
pub mod literal;
|
||||||
pub mod parser;
|
pub mod parser;
|
||||||
}
|
}
|
||||||
|
@ -371,9 +371,6 @@ pub fn visit_mac_args<T: MutVisitor>(args: &mut MacArgs, vis: &mut T) {
|
|||||||
// The value in `#[key = VALUE]` must be visited as an expression for backward
|
// The value in `#[key = VALUE]` must be visited as an expression for backward
|
||||||
// compatibility, so that macros can be expanded in that position.
|
// compatibility, so that macros can be expanded in that position.
|
||||||
if !vis.token_visiting_enabled() {
|
if !vis.token_visiting_enabled() {
|
||||||
if let Some(TokenTree::Token(token)) = tokens.trees_ref().next() {
|
|
||||||
if let token::Interpolated(..) = token.kind {
|
|
||||||
// ^^ Do not `make_mut` unless we have to.
|
|
||||||
match Lrc::make_mut(&mut tokens.0).get_mut(0) {
|
match Lrc::make_mut(&mut tokens.0).get_mut(0) {
|
||||||
Some((TokenTree::Token(token), _spacing)) => match &mut token.kind {
|
Some((TokenTree::Token(token), _spacing)) => match &mut token.kind {
|
||||||
token::Interpolated(nt) => match Lrc::make_mut(nt) {
|
token::Interpolated(nt) => match Lrc::make_mut(nt) {
|
||||||
@ -388,8 +385,6 @@ pub fn visit_mac_args<T: MutVisitor>(args: &mut MacArgs, vis: &mut T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn visit_delim_span<T: MutVisitor>(dspan: &mut DelimSpan, vis: &mut T) {
|
pub fn visit_delim_span<T: MutVisitor>(dspan: &mut DelimSpan, vis: &mut T) {
|
||||||
vis.visit_span(&mut dspan.open);
|
vis.visit_span(&mut dspan.open);
|
||||||
@ -441,11 +436,14 @@ pub fn noop_flat_map_arm<T: MutVisitor>(mut arm: Arm, vis: &mut T) -> SmallVec<[
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn noop_visit_ty_constraint<T: MutVisitor>(
|
pub fn noop_visit_ty_constraint<T: MutVisitor>(
|
||||||
AssocTyConstraint { id, ident, kind, span }: &mut AssocTyConstraint,
|
AssocTyConstraint { id, ident, gen_args, kind, span }: &mut AssocTyConstraint,
|
||||||
vis: &mut T,
|
vis: &mut T,
|
||||||
) {
|
) {
|
||||||
vis.visit_id(id);
|
vis.visit_id(id);
|
||||||
vis.visit_ident(ident);
|
vis.visit_ident(ident);
|
||||||
|
if let Some(ref mut gen_args) = gen_args {
|
||||||
|
vis.visit_generic_args(gen_args);
|
||||||
|
}
|
||||||
match kind {
|
match kind {
|
||||||
AssocTyConstraintKind::Equality { ref mut ty } => {
|
AssocTyConstraintKind::Equality { ref mut ty } => {
|
||||||
vis.visit_ty(ty);
|
vis.visit_ty(ty);
|
||||||
@ -576,13 +574,14 @@ pub fn noop_visit_parenthesized_parameter_data<T: MutVisitor>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn noop_visit_local<T: MutVisitor>(local: &mut P<Local>, vis: &mut T) {
|
pub fn noop_visit_local<T: MutVisitor>(local: &mut P<Local>, vis: &mut T) {
|
||||||
let Local { id, pat, ty, init, span, attrs } = local.deref_mut();
|
let Local { id, pat, ty, init, span, attrs, tokens } = local.deref_mut();
|
||||||
vis.visit_id(id);
|
vis.visit_id(id);
|
||||||
vis.visit_pat(pat);
|
vis.visit_pat(pat);
|
||||||
visit_opt(ty, |ty| vis.visit_ty(ty));
|
visit_opt(ty, |ty| vis.visit_ty(ty));
|
||||||
visit_opt(init, |init| vis.visit_expr(init));
|
visit_opt(init, |init| vis.visit_expr(init));
|
||||||
vis.visit_span(span);
|
vis.visit_span(span);
|
||||||
visit_thin_attrs(attrs, vis);
|
visit_thin_attrs(attrs, vis);
|
||||||
|
visit_lazy_tts(tokens, vis);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn noop_visit_attribute<T: MutVisitor>(attr: &mut Attribute, vis: &mut T) {
|
pub fn noop_visit_attribute<T: MutVisitor>(attr: &mut Attribute, vis: &mut T) {
|
||||||
@ -1232,6 +1231,7 @@ pub fn noop_visit_expr<T: MutVisitor>(
|
|||||||
visit_opt(e1, |e1| vis.visit_expr(e1));
|
visit_opt(e1, |e1| vis.visit_expr(e1));
|
||||||
visit_opt(e2, |e2| vis.visit_expr(e2));
|
visit_opt(e2, |e2| vis.visit_expr(e2));
|
||||||
}
|
}
|
||||||
|
ExprKind::Underscore => {}
|
||||||
ExprKind::Path(qself, path) => {
|
ExprKind::Path(qself, path) => {
|
||||||
vis.visit_qself(qself);
|
vis.visit_qself(qself);
|
||||||
vis.visit_path(path);
|
vis.visit_path(path);
|
||||||
@ -1324,16 +1324,12 @@ pub fn noop_filter_map_expr<T: MutVisitor>(mut e: P<Expr>, vis: &mut T) -> Optio
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn noop_flat_map_stmt<T: MutVisitor>(
|
pub fn noop_flat_map_stmt<T: MutVisitor>(
|
||||||
Stmt { kind, mut span, mut id, mut tokens }: Stmt,
|
Stmt { kind, mut span, mut id }: Stmt,
|
||||||
vis: &mut T,
|
vis: &mut T,
|
||||||
) -> SmallVec<[Stmt; 1]> {
|
) -> SmallVec<[Stmt; 1]> {
|
||||||
vis.visit_id(&mut id);
|
vis.visit_id(&mut id);
|
||||||
vis.visit_span(&mut span);
|
vis.visit_span(&mut span);
|
||||||
visit_lazy_tts(&mut tokens, vis);
|
noop_flat_map_stmt_kind(kind, vis).into_iter().map(|kind| Stmt { id, kind, span }).collect()
|
||||||
noop_flat_map_stmt_kind(kind, vis)
|
|
||||||
.into_iter()
|
|
||||||
.map(|kind| Stmt { id, kind, span, tokens: tokens.clone() })
|
|
||||||
.collect()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn noop_flat_map_stmt_kind<T: MutVisitor>(
|
pub fn noop_flat_map_stmt_kind<T: MutVisitor>(
|
||||||
@ -1350,9 +1346,10 @@ pub fn noop_flat_map_stmt_kind<T: MutVisitor>(
|
|||||||
StmtKind::Semi(expr) => vis.filter_map_expr(expr).into_iter().map(StmtKind::Semi).collect(),
|
StmtKind::Semi(expr) => vis.filter_map_expr(expr).into_iter().map(StmtKind::Semi).collect(),
|
||||||
StmtKind::Empty => smallvec![StmtKind::Empty],
|
StmtKind::Empty => smallvec![StmtKind::Empty],
|
||||||
StmtKind::MacCall(mut mac) => {
|
StmtKind::MacCall(mut mac) => {
|
||||||
let MacCallStmt { mac: mac_, style: _, attrs } = mac.deref_mut();
|
let MacCallStmt { mac: mac_, style: _, attrs, tokens } = mac.deref_mut();
|
||||||
vis.visit_mac_call(mac_);
|
vis.visit_mac_call(mac_);
|
||||||
visit_thin_attrs(attrs, vis);
|
visit_thin_attrs(attrs, vis);
|
||||||
|
visit_lazy_tts(tokens, vis);
|
||||||
smallvec![StmtKind::MacCall(mac)]
|
smallvec![StmtKind::MacCall(mac)]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -434,7 +434,7 @@ impl Token {
|
|||||||
|| self == &OpenDelim(Paren)
|
|| self == &OpenDelim(Paren)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if the token is any literal
|
/// Returns `true` if the token is any literal.
|
||||||
pub fn is_lit(&self) -> bool {
|
pub fn is_lit(&self) -> bool {
|
||||||
match self.kind {
|
match self.kind {
|
||||||
Literal(..) => true,
|
Literal(..) => true,
|
||||||
@ -785,7 +785,15 @@ impl Nonterminal {
|
|||||||
/// See issue #73345 for more details.
|
/// See issue #73345 for more details.
|
||||||
/// FIXME(#73933): Remove this eventually.
|
/// FIXME(#73933): Remove this eventually.
|
||||||
pub fn pretty_printing_compatibility_hack(&self) -> bool {
|
pub fn pretty_printing_compatibility_hack(&self) -> bool {
|
||||||
if let NtItem(item) = self {
|
let item = match self {
|
||||||
|
NtItem(item) => item,
|
||||||
|
NtStmt(stmt) => match &stmt.kind {
|
||||||
|
ast::StmtKind::Item(item) => item,
|
||||||
|
_ => return false,
|
||||||
|
},
|
||||||
|
_ => return false,
|
||||||
|
};
|
||||||
|
|
||||||
let name = item.ident.name;
|
let name = item.ident.name;
|
||||||
if name == sym::ProceduralMasqueradeDummyType || name == sym::ProcMacroHack {
|
if name == sym::ProceduralMasqueradeDummyType || name == sym::ProcMacroHack {
|
||||||
if let ast::ItemKind::Enum(enum_def, _) = &item.kind {
|
if let ast::ItemKind::Enum(enum_def, _) = &item.kind {
|
||||||
@ -794,7 +802,6 @@ impl Nonterminal {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,10 +121,14 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub trait CreateTokenStream: sync::Send + sync::Sync {
|
pub trait CreateTokenStream: sync::Send + sync::Sync {
|
||||||
|
fn add_trailing_semi(&self) -> Box<dyn CreateTokenStream>;
|
||||||
fn create_token_stream(&self) -> TokenStream;
|
fn create_token_stream(&self) -> TokenStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CreateTokenStream for TokenStream {
|
impl CreateTokenStream for TokenStream {
|
||||||
|
fn add_trailing_semi(&self) -> Box<dyn CreateTokenStream> {
|
||||||
|
panic!("Cannot call `add_trailing_semi` on a `TokenStream`!");
|
||||||
|
}
|
||||||
fn create_token_stream(&self) -> TokenStream {
|
fn create_token_stream(&self) -> TokenStream {
|
||||||
self.clone()
|
self.clone()
|
||||||
}
|
}
|
||||||
@ -141,6 +145,13 @@ impl LazyTokenStream {
|
|||||||
LazyTokenStream(Lrc::new(Box::new(inner)))
|
LazyTokenStream(Lrc::new(Box::new(inner)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Extends the captured stream by one token,
|
||||||
|
/// which must be a trailing semicolon. This
|
||||||
|
/// affects the `TokenStream` created by `make_tokenstream`.
|
||||||
|
pub fn add_trailing_semi(&self) -> LazyTokenStream {
|
||||||
|
LazyTokenStream(Lrc::new(self.0.add_trailing_semi()))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn create_token_stream(&self) -> TokenStream {
|
pub fn create_token_stream(&self) -> TokenStream {
|
||||||
self.0.create_token_stream()
|
self.0.create_token_stream()
|
||||||
}
|
}
|
||||||
@ -221,7 +232,7 @@ impl TokenStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some((pos, comma, sp)) = suggestion {
|
if let Some((pos, comma, sp)) = suggestion {
|
||||||
let mut new_stream = vec![];
|
let mut new_stream = Vec::with_capacity(self.0.len() + 1);
|
||||||
let parts = self.0.split_at(pos + 1);
|
let parts = self.0.split_at(pos + 1);
|
||||||
new_stream.extend_from_slice(parts.0);
|
new_stream.extend_from_slice(parts.0);
|
||||||
new_stream.push(comma);
|
new_stream.push(comma);
|
||||||
|
@ -25,9 +25,8 @@ pub struct Comment {
|
|||||||
|
|
||||||
/// Makes a doc string more presentable to users.
|
/// Makes a doc string more presentable to users.
|
||||||
/// Used by rustdoc and perhaps other tools, but not by rustc.
|
/// Used by rustdoc and perhaps other tools, but not by rustc.
|
||||||
pub fn beautify_doc_string(data: Symbol) -> String {
|
pub fn beautify_doc_string(data: Symbol) -> Symbol {
|
||||||
/// remove whitespace-only lines from the start/end of lines
|
fn get_vertical_trim(lines: &[&str]) -> Option<(usize, usize)> {
|
||||||
fn vertical_trim(lines: Vec<String>) -> Vec<String> {
|
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
let mut j = lines.len();
|
let mut j = lines.len();
|
||||||
// first line of all-stars should be omitted
|
// first line of all-stars should be omitted
|
||||||
@ -47,56 +46,59 @@ pub fn beautify_doc_string(data: Symbol) -> String {
|
|||||||
j -= 1;
|
j -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
lines[i..j].to_vec()
|
if i != 0 || j != lines.len() { Some((i, j)) } else { None }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// remove a "[ \t]*\*" block from each line, if possible
|
fn get_horizontal_trim(lines: &[&str]) -> Option<usize> {
|
||||||
fn horizontal_trim(lines: Vec<String>) -> Vec<String> {
|
|
||||||
let mut i = usize::MAX;
|
let mut i = usize::MAX;
|
||||||
let mut can_trim = true;
|
|
||||||
let mut first = true;
|
let mut first = true;
|
||||||
|
|
||||||
for line in &lines {
|
for line in lines {
|
||||||
for (j, c) in line.chars().enumerate() {
|
for (j, c) in line.chars().enumerate() {
|
||||||
if j > i || !"* \t".contains(c) {
|
if j > i || !"* \t".contains(c) {
|
||||||
can_trim = false;
|
return None;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if c == '*' {
|
if c == '*' {
|
||||||
if first {
|
if first {
|
||||||
i = j;
|
i = j;
|
||||||
first = false;
|
first = false;
|
||||||
} else if i != j {
|
} else if i != j {
|
||||||
can_trim = false;
|
return None;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if i >= line.len() {
|
if i >= line.len() {
|
||||||
can_trim = false;
|
return None;
|
||||||
}
|
}
|
||||||
if !can_trim {
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
Some(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
if can_trim {
|
let data_s = data.as_str();
|
||||||
lines.iter().map(|line| (&line[i + 1..line.len()]).to_string()).collect()
|
if data_s.contains('\n') {
|
||||||
|
let mut lines = data_s.lines().collect::<Vec<&str>>();
|
||||||
|
let mut changes = false;
|
||||||
|
let lines = if let Some((i, j)) = get_vertical_trim(&lines) {
|
||||||
|
changes = true;
|
||||||
|
// remove whitespace-only lines from the start/end of lines
|
||||||
|
&mut lines[i..j]
|
||||||
} else {
|
} else {
|
||||||
lines
|
&mut lines
|
||||||
|
};
|
||||||
|
if let Some(horizontal) = get_horizontal_trim(&lines) {
|
||||||
|
changes = true;
|
||||||
|
// remove a "[ \t]*\*" block from each line, if possible
|
||||||
|
for line in lines.iter_mut() {
|
||||||
|
*line = &line[horizontal + 1..];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if changes {
|
||||||
let data = data.as_str();
|
return Symbol::intern(&lines.join("\n"));
|
||||||
if data.contains('\n') {
|
|
||||||
let lines = data.lines().map(|s| s.to_string()).collect::<Vec<String>>();
|
|
||||||
let lines = vertical_trim(lines);
|
|
||||||
let lines = horizontal_trim(lines);
|
|
||||||
lines.join("\n")
|
|
||||||
} else {
|
|
||||||
data.to_string()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
data
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns `None` if the first `col` chars of `s` contain a non-whitespace char.
|
/// Returns `None` if the first `col` chars of `s` contain a non-whitespace char.
|
||||||
/// Otherwise returns `Some(k)` where `k` is first char offset after that leading
|
/// Otherwise returns `Some(k)` where `k` is first char offset after that leading
|
||||||
|
@ -6,7 +6,7 @@ fn test_block_doc_comment_1() {
|
|||||||
with_default_session_globals(|| {
|
with_default_session_globals(|| {
|
||||||
let comment = "\n * Test \n ** Test\n * Test\n";
|
let comment = "\n * Test \n ** Test\n * Test\n";
|
||||||
let stripped = beautify_doc_string(Symbol::intern(comment));
|
let stripped = beautify_doc_string(Symbol::intern(comment));
|
||||||
assert_eq!(stripped, " Test \n* Test\n Test");
|
assert_eq!(stripped.as_str(), " Test \n* Test\n Test");
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -15,7 +15,7 @@ fn test_block_doc_comment_2() {
|
|||||||
with_default_session_globals(|| {
|
with_default_session_globals(|| {
|
||||||
let comment = "\n * Test\n * Test\n";
|
let comment = "\n * Test\n * Test\n";
|
||||||
let stripped = beautify_doc_string(Symbol::intern(comment));
|
let stripped = beautify_doc_string(Symbol::intern(comment));
|
||||||
assert_eq!(stripped, " Test\n Test");
|
assert_eq!(stripped.as_str(), " Test\n Test");
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -24,7 +24,7 @@ fn test_block_doc_comment_3() {
|
|||||||
with_default_session_globals(|| {
|
with_default_session_globals(|| {
|
||||||
let comment = "\n let a: *i32;\n *a = 5;\n";
|
let comment = "\n let a: *i32;\n *a = 5;\n";
|
||||||
let stripped = beautify_doc_string(Symbol::intern(comment));
|
let stripped = beautify_doc_string(Symbol::intern(comment));
|
||||||
assert_eq!(stripped, " let a: *i32;\n *a = 5;");
|
assert_eq!(stripped.as_str(), " let a: *i32;\n *a = 5;");
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -32,12 +32,12 @@ fn test_block_doc_comment_3() {
|
|||||||
fn test_line_doc_comment() {
|
fn test_line_doc_comment() {
|
||||||
with_default_session_globals(|| {
|
with_default_session_globals(|| {
|
||||||
let stripped = beautify_doc_string(Symbol::intern(" test"));
|
let stripped = beautify_doc_string(Symbol::intern(" test"));
|
||||||
assert_eq!(stripped, " test");
|
assert_eq!(stripped.as_str(), " test");
|
||||||
let stripped = beautify_doc_string(Symbol::intern("! test"));
|
let stripped = beautify_doc_string(Symbol::intern("! test"));
|
||||||
assert_eq!(stripped, "! test");
|
assert_eq!(stripped.as_str(), "! test");
|
||||||
let stripped = beautify_doc_string(Symbol::intern("test"));
|
let stripped = beautify_doc_string(Symbol::intern("test"));
|
||||||
assert_eq!(stripped, "test");
|
assert_eq!(stripped.as_str(), "test");
|
||||||
let stripped = beautify_doc_string(Symbol::intern("!test"));
|
let stripped = beautify_doc_string(Symbol::intern("!test"));
|
||||||
assert_eq!(stripped, "!test");
|
assert_eq!(stripped.as_str(), "!test");
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -485,6 +485,9 @@ pub fn walk_assoc_ty_constraint<'a, V: Visitor<'a>>(
|
|||||||
constraint: &'a AssocTyConstraint,
|
constraint: &'a AssocTyConstraint,
|
||||||
) {
|
) {
|
||||||
visitor.visit_ident(constraint.ident);
|
visitor.visit_ident(constraint.ident);
|
||||||
|
if let Some(ref gen_args) = constraint.gen_args {
|
||||||
|
visitor.visit_generic_args(gen_args.span(), gen_args);
|
||||||
|
}
|
||||||
match constraint.kind {
|
match constraint.kind {
|
||||||
AssocTyConstraintKind::Equality { ref ty } => {
|
AssocTyConstraintKind::Equality { ref ty } => {
|
||||||
visitor.visit_ty(ty);
|
visitor.visit_ty(ty);
|
||||||
@ -686,7 +689,7 @@ pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) {
|
|||||||
StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => visitor.visit_expr(expr),
|
StmtKind::Expr(ref expr) | StmtKind::Semi(ref expr) => visitor.visit_expr(expr),
|
||||||
StmtKind::Empty => {}
|
StmtKind::Empty => {}
|
||||||
StmtKind::MacCall(ref mac) => {
|
StmtKind::MacCall(ref mac) => {
|
||||||
let MacCallStmt { ref mac, style: _, ref attrs } = **mac;
|
let MacCallStmt { ref mac, style: _, ref attrs, tokens: _ } = **mac;
|
||||||
visitor.visit_mac_call(mac);
|
visitor.visit_mac_call(mac);
|
||||||
for attr in attrs.iter() {
|
for attr in attrs.iter() {
|
||||||
visitor.visit_attribute(attr);
|
visitor.visit_attribute(attr);
|
||||||
@ -806,6 +809,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) {
|
|||||||
walk_list!(visitor, visit_expr, start);
|
walk_list!(visitor, visit_expr, start);
|
||||||
walk_list!(visitor, visit_expr, end);
|
walk_list!(visitor, visit_expr, end);
|
||||||
}
|
}
|
||||||
|
ExprKind::Underscore => {}
|
||||||
ExprKind::Path(ref maybe_qself, ref path) => {
|
ExprKind::Path(ref maybe_qself, ref path) => {
|
||||||
if let Some(ref qself) = *maybe_qself {
|
if let Some(ref qself) = *maybe_qself {
|
||||||
visitor.visit_ty(&qself.ty);
|
visitor.visit_ty(&qself.ty);
|
||||||
@ -902,7 +906,6 @@ pub fn walk_mac_args<'a, V: Visitor<'a>>(visitor: &mut V, args: &'a MacArgs) {
|
|||||||
token::NtExpr(expr) => visitor.visit_expr(expr),
|
token::NtExpr(expr) => visitor.visit_expr(expr),
|
||||||
t => panic!("unexpected token in key-value attribute: {:?}", t),
|
t => panic!("unexpected token in key-value attribute: {:?}", t),
|
||||||
},
|
},
|
||||||
token::Literal(..) | token::Ident(..) => {}
|
|
||||||
t => panic!("unexpected token in key-value attribute: {:?}", t),
|
t => panic!("unexpected token in key-value attribute: {:?}", t),
|
||||||
},
|
},
|
||||||
t => panic!("unexpected token in key-value attribute: {:?}", t),
|
t => panic!("unexpected token in key-value attribute: {:?}", t),
|
||||||
|
@ -164,6 +164,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
ExprKind::Range(ref e1, ref e2, lims) => {
|
ExprKind::Range(ref e1, ref e2, lims) => {
|
||||||
self.lower_expr_range(e.span, e1.as_deref(), e2.as_deref(), lims)
|
self.lower_expr_range(e.span, e1.as_deref(), e2.as_deref(), lims)
|
||||||
}
|
}
|
||||||
|
ExprKind::Underscore => {
|
||||||
|
self.sess
|
||||||
|
.struct_span_err(
|
||||||
|
e.span,
|
||||||
|
"in expressions, `_` can only be used on the left-hand side of an assignment",
|
||||||
|
)
|
||||||
|
.span_label(e.span, "`_` not allowed here")
|
||||||
|
.emit();
|
||||||
|
hir::ExprKind::Err
|
||||||
|
}
|
||||||
ExprKind::Path(ref qself, ref path) => {
|
ExprKind::Path(ref qself, ref path) => {
|
||||||
let qpath = self.lower_qpath(
|
let qpath = self.lower_qpath(
|
||||||
e.id,
|
e.id,
|
||||||
@ -337,13 +347,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
// `_ => else_block` where `else_block` is `{}` if there's `None`:
|
// `_ => else_block` where `else_block` is `{}` if there's `None`:
|
||||||
let else_pat = self.pat_wild(span);
|
let else_pat = self.pat_wild(span);
|
||||||
let (else_expr, contains_else_clause) = match else_opt {
|
let (else_expr, contains_else_clause) = match else_opt {
|
||||||
None => (self.expr_block_empty(span), false),
|
None => (self.expr_block_empty(span.shrink_to_hi()), false),
|
||||||
Some(els) => (self.lower_expr(els), true),
|
Some(els) => (self.lower_expr(els), true),
|
||||||
};
|
};
|
||||||
let else_arm = self.arm(else_pat, else_expr);
|
let else_arm = self.arm(else_pat, else_expr);
|
||||||
|
|
||||||
// Handle then + scrutinee:
|
// Handle then + scrutinee:
|
||||||
let then_expr = self.lower_block_expr(then);
|
|
||||||
let (then_pat, scrutinee, desugar) = match cond.kind {
|
let (then_pat, scrutinee, desugar) = match cond.kind {
|
||||||
// `<pat> => <then>`:
|
// `<pat> => <then>`:
|
||||||
ExprKind::Let(ref pat, ref scrutinee) => {
|
ExprKind::Let(ref pat, ref scrutinee) => {
|
||||||
@ -365,6 +374,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
(pat, cond, hir::MatchSource::IfDesugar { contains_else_clause })
|
(pat, cond, hir::MatchSource::IfDesugar { contains_else_clause })
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
let then_expr = self.lower_block_expr(then);
|
||||||
let then_arm = self.arm(then_pat, self.arena.alloc(then_expr));
|
let then_arm = self.arm(then_pat, self.arena.alloc(then_expr));
|
||||||
|
|
||||||
hir::ExprKind::Match(scrutinee, arena_vec![self; then_arm, else_arm], desugar)
|
hir::ExprKind::Match(scrutinee, arena_vec![self; then_arm, else_arm], desugar)
|
||||||
@ -390,7 +400,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Handle then + scrutinee:
|
// Handle then + scrutinee:
|
||||||
let then_expr = self.lower_block_expr(body);
|
|
||||||
let (then_pat, scrutinee, desugar, source) = match cond.kind {
|
let (then_pat, scrutinee, desugar, source) = match cond.kind {
|
||||||
ExprKind::Let(ref pat, ref scrutinee) => {
|
ExprKind::Let(ref pat, ref scrutinee) => {
|
||||||
// to:
|
// to:
|
||||||
@ -430,6 +439,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
(pat, cond, hir::MatchSource::WhileDesugar, hir::LoopSource::While)
|
(pat, cond, hir::MatchSource::WhileDesugar, hir::LoopSource::While)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
let then_expr = self.lower_block_expr(body);
|
||||||
let then_arm = self.arm(then_pat, self.arena.alloc(then_expr));
|
let then_arm = self.arm(then_pat, self.arena.alloc(then_expr));
|
||||||
|
|
||||||
// `match <scrutinee> { ... }`
|
// `match <scrutinee> { ... }`
|
||||||
@ -495,14 +505,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn lower_arm(&mut self, arm: &Arm) -> hir::Arm<'hir> {
|
fn lower_arm(&mut self, arm: &Arm) -> hir::Arm<'hir> {
|
||||||
|
let pat = self.lower_pat(&arm.pat);
|
||||||
|
let guard = arm.guard.as_ref().map(|cond| {
|
||||||
|
if let ExprKind::Let(ref pat, ref scrutinee) = cond.kind {
|
||||||
|
hir::Guard::IfLet(self.lower_pat(pat), self.lower_expr(scrutinee))
|
||||||
|
} else {
|
||||||
|
hir::Guard::If(self.lower_expr(cond))
|
||||||
|
}
|
||||||
|
});
|
||||||
hir::Arm {
|
hir::Arm {
|
||||||
hir_id: self.next_id(),
|
hir_id: self.next_id(),
|
||||||
attrs: self.lower_attrs(&arm.attrs),
|
attrs: self.lower_attrs(&arm.attrs),
|
||||||
pat: self.lower_pat(&arm.pat),
|
pat,
|
||||||
guard: match arm.guard {
|
guard,
|
||||||
Some(ref x) => Some(hir::Guard::If(self.lower_expr(x))),
|
|
||||||
_ => None,
|
|
||||||
},
|
|
||||||
body: self.lower_expr(&arm.body),
|
body: self.lower_expr(&arm.body),
|
||||||
span: arm.span,
|
span: arm.span,
|
||||||
}
|
}
|
||||||
@ -863,7 +878,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
// Return early in case of an ordinary assignment.
|
// Return early in case of an ordinary assignment.
|
||||||
fn is_ordinary(lower_ctx: &mut LoweringContext<'_, '_>, lhs: &Expr) -> bool {
|
fn is_ordinary(lower_ctx: &mut LoweringContext<'_, '_>, lhs: &Expr) -> bool {
|
||||||
match &lhs.kind {
|
match &lhs.kind {
|
||||||
ExprKind::Array(..) | ExprKind::Struct(..) | ExprKind::Tup(..) => false,
|
ExprKind::Array(..)
|
||||||
|
| ExprKind::Struct(..)
|
||||||
|
| ExprKind::Tup(..)
|
||||||
|
| ExprKind::Underscore => false,
|
||||||
// Check for tuple struct constructor.
|
// Check for tuple struct constructor.
|
||||||
ExprKind::Call(callee, ..) => lower_ctx.extract_tuple_struct_path(callee).is_none(),
|
ExprKind::Call(callee, ..) => lower_ctx.extract_tuple_struct_path(callee).is_none(),
|
||||||
ExprKind::Paren(e) => {
|
ExprKind::Paren(e) => {
|
||||||
@ -943,6 +961,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
assignments: &mut Vec<hir::Stmt<'hir>>,
|
assignments: &mut Vec<hir::Stmt<'hir>>,
|
||||||
) -> &'hir hir::Pat<'hir> {
|
) -> &'hir hir::Pat<'hir> {
|
||||||
match &lhs.kind {
|
match &lhs.kind {
|
||||||
|
// Underscore pattern.
|
||||||
|
ExprKind::Underscore => {
|
||||||
|
return self.pat_without_dbm(lhs.span, hir::PatKind::Wild);
|
||||||
|
}
|
||||||
// Slice patterns.
|
// Slice patterns.
|
||||||
ExprKind::Array(elements) => {
|
ExprKind::Array(elements) => {
|
||||||
let (pats, rest) =
|
let (pats, rest) =
|
||||||
@ -1290,7 +1312,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
hir::InlineAsmOperand::Sym { expr: self.lower_expr_mut(expr) }
|
hir::InlineAsmOperand::Sym { expr: self.lower_expr_mut(expr) }
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Some(op)
|
Some((op, *op_sp))
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
@ -1309,7 +1331,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
} = *p
|
} = *p
|
||||||
{
|
{
|
||||||
let op_sp = asm.operands[operand_idx].1;
|
let op_sp = asm.operands[operand_idx].1;
|
||||||
match &operands[operand_idx] {
|
match &operands[operand_idx].0 {
|
||||||
hir::InlineAsmOperand::In { reg, .. }
|
hir::InlineAsmOperand::In { reg, .. }
|
||||||
| hir::InlineAsmOperand::Out { reg, .. }
|
| hir::InlineAsmOperand::Out { reg, .. }
|
||||||
| hir::InlineAsmOperand::InOut { reg, .. }
|
| hir::InlineAsmOperand::InOut { reg, .. }
|
||||||
@ -1367,14 +1389,17 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
|
|
||||||
let mut used_input_regs = FxHashMap::default();
|
let mut used_input_regs = FxHashMap::default();
|
||||||
let mut used_output_regs = FxHashMap::default();
|
let mut used_output_regs = FxHashMap::default();
|
||||||
for (idx, op) in operands.iter().enumerate() {
|
let mut required_features: Vec<&str> = vec![];
|
||||||
let op_sp = asm.operands[idx].1;
|
for (idx, &(ref op, op_sp)) in operands.iter().enumerate() {
|
||||||
if let Some(reg) = op.reg() {
|
if let Some(reg) = op.reg() {
|
||||||
|
// Make sure we don't accidentally carry features from the
|
||||||
|
// previous iteration.
|
||||||
|
required_features.clear();
|
||||||
|
|
||||||
// Validate register classes against currently enabled target
|
// Validate register classes against currently enabled target
|
||||||
// features. We check that at least one type is available for
|
// features. We check that at least one type is available for
|
||||||
// the current target.
|
// the current target.
|
||||||
let reg_class = reg.reg_class();
|
let reg_class = reg.reg_class();
|
||||||
let mut required_features: Vec<&str> = vec![];
|
|
||||||
for &(_, feature) in reg_class.supported_types(asm_arch) {
|
for &(_, feature) in reg_class.supported_types(asm_arch) {
|
||||||
if let Some(feature) = feature {
|
if let Some(feature) = feature {
|
||||||
if self.sess.target_features.contains(&Symbol::intern(feature)) {
|
if self.sess.target_features.contains(&Symbol::intern(feature)) {
|
||||||
@ -1437,8 +1462,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
skip = true;
|
skip = true;
|
||||||
|
|
||||||
let idx2 = *o.get();
|
let idx2 = *o.get();
|
||||||
let op2 = &operands[idx2];
|
let &(ref op2, op_sp2) = &operands[idx2];
|
||||||
let op_sp2 = asm.operands[idx2].1;
|
|
||||||
let reg2 = match op2.reg() {
|
let reg2 = match op2.reg() {
|
||||||
Some(asm::InlineAsmRegOrRegClass::Reg(r)) => r,
|
Some(asm::InlineAsmRegOrRegClass::Reg(r)) => r,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
|
@ -43,6 +43,7 @@ impl<'a> Visitor<'a> for ItemLowerer<'a, '_, '_> {
|
|||||||
items: BTreeSet::new(),
|
items: BTreeSet::new(),
|
||||||
trait_items: BTreeSet::new(),
|
trait_items: BTreeSet::new(),
|
||||||
impl_items: BTreeSet::new(),
|
impl_items: BTreeSet::new(),
|
||||||
|
foreign_items: BTreeSet::new(),
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -105,6 +106,18 @@ impl<'a> Visitor<'a> for ItemLowerer<'a, '_, '_> {
|
|||||||
|
|
||||||
visit::walk_assoc_item(self, item, ctxt);
|
visit::walk_assoc_item(self, item, ctxt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_foreign_item(&mut self, item: &'a ForeignItem) {
|
||||||
|
self.lctx.allocate_hir_id_counter(item.id);
|
||||||
|
self.lctx.with_hir_id_owner(item.id, |lctx| {
|
||||||
|
let hir_item = lctx.lower_foreign_item(item);
|
||||||
|
let id = hir::ForeignItemId { hir_id: hir_item.hir_id };
|
||||||
|
lctx.foreign_items.insert(id, hir_item);
|
||||||
|
lctx.modules.get_mut(&lctx.current_module).unwrap().foreign_items.insert(id);
|
||||||
|
});
|
||||||
|
|
||||||
|
visit::walk_foreign_item(self, item);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'hir> LoweringContext<'_, 'hir> {
|
impl<'hir> LoweringContext<'_, 'hir> {
|
||||||
@ -304,7 +317,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
ItemKind::Mod(ref m) => hir::ItemKind::Mod(self.lower_mod(m)),
|
ItemKind::Mod(ref m) => hir::ItemKind::Mod(self.lower_mod(m)),
|
||||||
ItemKind::ForeignMod(ref nm) => hir::ItemKind::ForeignMod(self.lower_foreign_mod(nm)),
|
ItemKind::ForeignMod(ref fm) => hir::ItemKind::ForeignMod {
|
||||||
|
abi: fm.abi.map_or(abi::Abi::C, |abi| self.lower_abi(abi)),
|
||||||
|
items: self
|
||||||
|
.arena
|
||||||
|
.alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item_ref(x))),
|
||||||
|
},
|
||||||
ItemKind::GlobalAsm(ref ga) => hir::ItemKind::GlobalAsm(self.lower_global_asm(ga)),
|
ItemKind::GlobalAsm(ref ga) => hir::ItemKind::GlobalAsm(self.lower_global_asm(ga)),
|
||||||
ItemKind::TyAlias(_, ref gen, _, Some(ref ty)) => {
|
ItemKind::TyAlias(_, ref gen, _, Some(ref ty)) => {
|
||||||
// We lower
|
// We lower
|
||||||
@ -704,10 +722,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lower_foreign_mod(&mut self, fm: &ForeignMod) -> hir::ForeignMod<'hir> {
|
fn lower_foreign_item_ref(&mut self, i: &ForeignItem) -> hir::ForeignItemRef<'hir> {
|
||||||
hir::ForeignMod {
|
hir::ForeignItemRef {
|
||||||
abi: fm.abi.map_or(abi::Abi::C, |abi| self.lower_abi(abi)),
|
id: hir::ForeignItemId { hir_id: self.lower_node_id(i.id) },
|
||||||
items: self.arena.alloc_from_iter(fm.items.iter().map(|x| self.lower_foreign_item(x))),
|
ident: i.ident,
|
||||||
|
span: i.span,
|
||||||
|
vis: self.lower_visibility(&i.vis, Some(i.id)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +53,6 @@ use rustc_hir::definitions::{DefKey, DefPathData, Definitions};
|
|||||||
use rustc_hir::intravisit;
|
use rustc_hir::intravisit;
|
||||||
use rustc_hir::{ConstArg, GenericArg, ParamName};
|
use rustc_hir::{ConstArg, GenericArg, ParamName};
|
||||||
use rustc_index::vec::{Idx, IndexVec};
|
use rustc_index::vec::{Idx, IndexVec};
|
||||||
use rustc_session::config::nightly_options;
|
|
||||||
use rustc_session::lint::{builtin::BARE_TRAIT_OBJECTS, BuiltinLintDiagnostics, LintBuffer};
|
use rustc_session::lint::{builtin::BARE_TRAIT_OBJECTS, BuiltinLintDiagnostics, LintBuffer};
|
||||||
use rustc_session::parse::ParseSess;
|
use rustc_session::parse::ParseSess;
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
@ -102,6 +101,7 @@ struct LoweringContext<'a, 'hir: 'a> {
|
|||||||
|
|
||||||
trait_items: BTreeMap<hir::TraitItemId, hir::TraitItem<'hir>>,
|
trait_items: BTreeMap<hir::TraitItemId, hir::TraitItem<'hir>>,
|
||||||
impl_items: BTreeMap<hir::ImplItemId, hir::ImplItem<'hir>>,
|
impl_items: BTreeMap<hir::ImplItemId, hir::ImplItem<'hir>>,
|
||||||
|
foreign_items: BTreeMap<hir::ForeignItemId, hir::ForeignItem<'hir>>,
|
||||||
bodies: BTreeMap<hir::BodyId, hir::Body<'hir>>,
|
bodies: BTreeMap<hir::BodyId, hir::Body<'hir>>,
|
||||||
exported_macros: Vec<hir::MacroDef<'hir>>,
|
exported_macros: Vec<hir::MacroDef<'hir>>,
|
||||||
non_exported_macro_attrs: Vec<ast::Attribute>,
|
non_exported_macro_attrs: Vec<ast::Attribute>,
|
||||||
@ -299,6 +299,7 @@ pub fn lower_crate<'a, 'hir>(
|
|||||||
items: BTreeMap::new(),
|
items: BTreeMap::new(),
|
||||||
trait_items: BTreeMap::new(),
|
trait_items: BTreeMap::new(),
|
||||||
impl_items: BTreeMap::new(),
|
impl_items: BTreeMap::new(),
|
||||||
|
foreign_items: BTreeMap::new(),
|
||||||
bodies: BTreeMap::new(),
|
bodies: BTreeMap::new(),
|
||||||
trait_impls: BTreeMap::new(),
|
trait_impls: BTreeMap::new(),
|
||||||
modules: BTreeMap::new(),
|
modules: BTreeMap::new(),
|
||||||
@ -426,7 +427,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
/// declared for every type and trait definition.
|
/// declared for every type and trait definition.
|
||||||
struct MiscCollector<'tcx, 'lowering, 'hir> {
|
struct MiscCollector<'tcx, 'lowering, 'hir> {
|
||||||
lctx: &'tcx mut LoweringContext<'lowering, 'hir>,
|
lctx: &'tcx mut LoweringContext<'lowering, 'hir>,
|
||||||
hir_id_owner: Option<NodeId>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MiscCollector<'_, '_, '_> {
|
impl MiscCollector<'_, '_, '_> {
|
||||||
@ -453,30 +453,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_hir_id_owner<T>(
|
|
||||||
&mut self,
|
|
||||||
owner: Option<NodeId>,
|
|
||||||
f: impl FnOnce(&mut Self) -> T,
|
|
||||||
) -> T {
|
|
||||||
let old = mem::replace(&mut self.hir_id_owner, owner);
|
|
||||||
let r = f(self);
|
|
||||||
self.hir_id_owner = old;
|
|
||||||
r
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Visitor<'tcx> for MiscCollector<'tcx, '_, '_> {
|
impl<'tcx> Visitor<'tcx> for MiscCollector<'tcx, '_, '_> {
|
||||||
fn visit_pat(&mut self, p: &'tcx Pat) {
|
|
||||||
if let PatKind::Paren(..) | PatKind::Rest = p.kind {
|
|
||||||
// Doesn't generate a HIR node
|
|
||||||
} else if let Some(owner) = self.hir_id_owner {
|
|
||||||
self.lctx.lower_node_id_with_owner(p.id, owner);
|
|
||||||
}
|
|
||||||
|
|
||||||
visit::walk_pat(self, p)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_item(&mut self, item: &'tcx Item) {
|
fn visit_item(&mut self, item: &'tcx Item) {
|
||||||
let hir_id = self.lctx.allocate_hir_id_counter(item.id);
|
let hir_id = self.lctx.allocate_hir_id_counter(item.id);
|
||||||
|
|
||||||
@ -500,24 +479,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.with_hir_id_owner(Some(item.id), |this| {
|
visit::walk_item(self, item);
|
||||||
visit::walk_item(this, item);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_assoc_item(&mut self, item: &'tcx AssocItem, ctxt: AssocCtxt) {
|
fn visit_assoc_item(&mut self, item: &'tcx AssocItem, ctxt: AssocCtxt) {
|
||||||
self.lctx.allocate_hir_id_counter(item.id);
|
self.lctx.allocate_hir_id_counter(item.id);
|
||||||
let owner = match (&item.kind, ctxt) {
|
visit::walk_assoc_item(self, item, ctxt);
|
||||||
// Ignore patterns in trait methods without bodies.
|
|
||||||
(AssocItemKind::Fn(_, _, _, None), AssocCtxt::Trait) => None,
|
|
||||||
_ => Some(item.id),
|
|
||||||
};
|
|
||||||
self.with_hir_id_owner(owner, |this| visit::walk_assoc_item(this, item, ctxt));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_foreign_item(&mut self, i: &'tcx ForeignItem) {
|
fn visit_foreign_item(&mut self, item: &'tcx ForeignItem) {
|
||||||
// Ignore patterns in foreign items
|
self.lctx.allocate_hir_id_counter(item.id);
|
||||||
self.with_hir_id_owner(None, |this| visit::walk_foreign_item(this, i));
|
visit::walk_foreign_item(self, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_ty(&mut self, t: &'tcx Ty) {
|
fn visit_ty(&mut self, t: &'tcx Ty) {
|
||||||
@ -528,18 +500,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
// Mirrors visit::walk_fn_decl
|
// Mirrors visit::walk_fn_decl
|
||||||
for parameter in &f.decl.inputs {
|
for parameter in &f.decl.inputs {
|
||||||
// We don't lower the ids of argument patterns
|
// We don't lower the ids of argument patterns
|
||||||
self.with_hir_id_owner(None, |this| {
|
self.visit_pat(¶meter.pat);
|
||||||
this.visit_pat(¶meter.pat);
|
|
||||||
});
|
|
||||||
self.visit_ty(¶meter.ty)
|
self.visit_ty(¶meter.ty)
|
||||||
}
|
}
|
||||||
self.visit_fn_ret_ty(&f.decl.output)
|
self.visit_fn_ret_ty(&f.decl.output)
|
||||||
}
|
}
|
||||||
TyKind::ImplTrait(def_node_id, _) => {
|
TyKind::ImplTrait(def_node_id, _) => {
|
||||||
self.lctx.allocate_hir_id_counter(def_node_id);
|
self.lctx.allocate_hir_id_counter(def_node_id);
|
||||||
self.with_hir_id_owner(Some(def_node_id), |this| {
|
visit::walk_ty(self, t);
|
||||||
visit::walk_ty(this, t);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
_ => visit::walk_ty(self, t),
|
_ => visit::walk_ty(self, t),
|
||||||
}
|
}
|
||||||
@ -549,7 +517,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
self.lower_node_id(CRATE_NODE_ID);
|
self.lower_node_id(CRATE_NODE_ID);
|
||||||
debug_assert!(self.node_id_to_hir_id[CRATE_NODE_ID] == Some(hir::CRATE_HIR_ID));
|
debug_assert!(self.node_id_to_hir_id[CRATE_NODE_ID] == Some(hir::CRATE_HIR_ID));
|
||||||
|
|
||||||
visit::walk_crate(&mut MiscCollector { lctx: &mut self, hir_id_owner: None }, c);
|
visit::walk_crate(&mut MiscCollector { lctx: &mut self }, c);
|
||||||
visit::walk_crate(&mut item::ItemLowerer { lctx: &mut self }, c);
|
visit::walk_crate(&mut item::ItemLowerer { lctx: &mut self }, c);
|
||||||
|
|
||||||
let module = self.lower_mod(&c.module);
|
let module = self.lower_mod(&c.module);
|
||||||
@ -587,6 +555,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
items: self.items,
|
items: self.items,
|
||||||
trait_items: self.trait_items,
|
trait_items: self.trait_items,
|
||||||
impl_items: self.impl_items,
|
impl_items: self.impl_items,
|
||||||
|
foreign_items: self.foreign_items,
|
||||||
bodies: self.bodies,
|
bodies: self.bodies,
|
||||||
body_ids,
|
body_ids,
|
||||||
trait_impls: self.trait_impls,
|
trait_impls: self.trait_impls,
|
||||||
@ -1039,6 +1008,13 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
) -> hir::TypeBinding<'hir> {
|
) -> hir::TypeBinding<'hir> {
|
||||||
debug!("lower_assoc_ty_constraint(constraint={:?}, itctx={:?})", constraint, itctx);
|
debug!("lower_assoc_ty_constraint(constraint={:?}, itctx={:?})", constraint, itctx);
|
||||||
|
|
||||||
|
if let Some(ref gen_args) = constraint.gen_args {
|
||||||
|
self.sess.span_fatal(
|
||||||
|
gen_args.span(),
|
||||||
|
"generic associated types in trait paths are currently not implemented",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let kind = match constraint.kind {
|
let kind = match constraint.kind {
|
||||||
AssocTyConstraintKind::Equality { ref ty } => {
|
AssocTyConstraintKind::Equality { ref ty } => {
|
||||||
hir::TypeBindingKind::Equality { ty: self.lower_ty(ty, itctx) }
|
hir::TypeBindingKind::Equality { ty: self.lower_ty(ty, itctx) }
|
||||||
@ -1398,8 +1374,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
"`impl Trait` not allowed outside of {}",
|
"`impl Trait` not allowed outside of {}",
|
||||||
allowed_in,
|
allowed_in,
|
||||||
);
|
);
|
||||||
if pos == ImplTraitPosition::Binding && nightly_options::is_nightly_build()
|
if pos == ImplTraitPosition::Binding && self.sess.is_nightly_build() {
|
||||||
{
|
|
||||||
err.help(
|
err.help(
|
||||||
"add `#![feature(impl_trait_in_bindings)]` to the crate \
|
"add `#![feature(impl_trait_in_bindings)]` to the crate \
|
||||||
attributes to enable",
|
attributes to enable",
|
||||||
@ -2011,17 +1986,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
//
|
//
|
||||||
// For the "output" lifetime parameters, we just want to
|
// For the "output" lifetime parameters, we just want to
|
||||||
// generate `'_`.
|
// generate `'_`.
|
||||||
let mut generic_args: Vec<_> = lifetime_params[..input_lifetimes_count]
|
let mut generic_args = Vec::with_capacity(lifetime_params.len());
|
||||||
.iter()
|
generic_args.extend(lifetime_params[..input_lifetimes_count].iter().map(
|
||||||
.map(|&(span, hir_name)| {
|
|&(span, hir_name)| {
|
||||||
// Input lifetime like `'a` or `'1`:
|
// Input lifetime like `'a` or `'1`:
|
||||||
GenericArg::Lifetime(hir::Lifetime {
|
GenericArg::Lifetime(hir::Lifetime {
|
||||||
hir_id: self.next_id(),
|
hir_id: self.next_id(),
|
||||||
span,
|
span,
|
||||||
name: hir::LifetimeName::Param(hir_name),
|
name: hir::LifetimeName::Param(hir_name),
|
||||||
})
|
})
|
||||||
})
|
},
|
||||||
.collect();
|
));
|
||||||
generic_args.extend(lifetime_params[input_lifetimes_count..].iter().map(|&(span, _)|
|
generic_args.extend(lifetime_params[input_lifetimes_count..].iter().map(|&(span, _)|
|
||||||
// Output lifetime like `'_`.
|
// Output lifetime like `'_`.
|
||||||
GenericArg::Lifetime(hir::Lifetime {
|
GenericArg::Lifetime(hir::Lifetime {
|
||||||
@ -2312,29 +2287,30 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn lower_block_noalloc(&mut self, b: &Block, targeted_by_break: bool) -> hir::Block<'hir> {
|
fn lower_block_noalloc(&mut self, b: &Block, targeted_by_break: bool) -> hir::Block<'hir> {
|
||||||
let mut stmts = vec![];
|
|
||||||
let mut expr: Option<&'hir _> = None;
|
let mut expr: Option<&'hir _> = None;
|
||||||
|
|
||||||
for (index, stmt) in b.stmts.iter().enumerate() {
|
let stmts = self.arena.alloc_from_iter(
|
||||||
|
b.stmts
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.filter_map(|(index, stmt)| {
|
||||||
if index == b.stmts.len() - 1 {
|
if index == b.stmts.len() - 1 {
|
||||||
if let StmtKind::Expr(ref e) = stmt.kind {
|
if let StmtKind::Expr(ref e) = stmt.kind {
|
||||||
expr = Some(self.lower_expr(e));
|
expr = Some(self.lower_expr(e));
|
||||||
|
None
|
||||||
} else {
|
} else {
|
||||||
stmts.extend(self.lower_stmt(stmt));
|
Some(self.lower_stmt(stmt))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
stmts.extend(self.lower_stmt(stmt));
|
Some(self.lower_stmt(stmt))
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
.flatten(),
|
||||||
|
);
|
||||||
|
let rules = self.lower_block_check_mode(&b.rules);
|
||||||
|
let hir_id = self.lower_node_id(b.id);
|
||||||
|
|
||||||
hir::Block {
|
hir::Block { hir_id, stmts, expr, rules, span: b.span, targeted_by_break }
|
||||||
hir_id: self.lower_node_id(b.id),
|
|
||||||
stmts: self.arena.alloc_from_iter(stmts),
|
|
||||||
expr,
|
|
||||||
rules: self.lower_block_check_mode(&b.rules),
|
|
||||||
span: b.span,
|
|
||||||
targeted_by_break,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Lowers a block directly to an expression, presuming that it
|
/// Lowers a block directly to an expression, presuming that it
|
||||||
|
@ -400,7 +400,7 @@ impl<'a> AstValidator<'a> {
|
|||||||
if let Defaultness::Default(def_span) = defaultness {
|
if let Defaultness::Default(def_span) = defaultness {
|
||||||
let span = self.session.source_map().guess_head_span(span);
|
let span = self.session.source_map().guess_head_span(span);
|
||||||
self.err_handler()
|
self.err_handler()
|
||||||
.struct_span_err(span, "`default` is only allowed on items in `impl` definitions")
|
.struct_span_err(span, "`default` is only allowed on items in trait impls")
|
||||||
.span_label(def_span, "`default` because of this")
|
.span_label(def_span, "`default` because of this")
|
||||||
.emit();
|
.emit();
|
||||||
}
|
}
|
||||||
@ -522,7 +522,7 @@ impl<'a> AstValidator<'a> {
|
|||||||
self.err_handler()
|
self.err_handler()
|
||||||
.struct_span_err(ident.span, "functions in `extern` blocks cannot have qualifiers")
|
.struct_span_err(ident.span, "functions in `extern` blocks cannot have qualifiers")
|
||||||
.span_label(self.current_extern_span(), "in this `extern` block")
|
.span_label(self.current_extern_span(), "in this `extern` block")
|
||||||
.span_suggestion(
|
.span_suggestion_verbose(
|
||||||
span.until(ident.span.shrink_to_lo()),
|
span.until(ident.span.shrink_to_lo()),
|
||||||
"remove the qualifiers",
|
"remove the qualifiers",
|
||||||
"fn ".to_string(),
|
"fn ".to_string(),
|
||||||
@ -1372,16 +1372,18 @@ fn deny_equality_constraints(
|
|||||||
if param.ident == *ident {
|
if param.ident == *ident {
|
||||||
let param = ident;
|
let param = ident;
|
||||||
match &full_path.segments[qself.position..] {
|
match &full_path.segments[qself.position..] {
|
||||||
[PathSegment { ident, .. }] => {
|
[PathSegment { ident, args, .. }] => {
|
||||||
// Make a new `Path` from `foo::Bar` to `Foo<Bar = RhsTy>`.
|
// Make a new `Path` from `foo::Bar` to `Foo<Bar = RhsTy>`.
|
||||||
let mut assoc_path = full_path.clone();
|
let mut assoc_path = full_path.clone();
|
||||||
// Remove `Bar` from `Foo::Bar`.
|
// Remove `Bar` from `Foo::Bar`.
|
||||||
assoc_path.segments.pop();
|
assoc_path.segments.pop();
|
||||||
let len = assoc_path.segments.len() - 1;
|
let len = assoc_path.segments.len() - 1;
|
||||||
|
let gen_args = args.as_ref().map(|p| (**p).clone());
|
||||||
// Build `<Bar = RhsTy>`.
|
// Build `<Bar = RhsTy>`.
|
||||||
let arg = AngleBracketedArg::Constraint(AssocTyConstraint {
|
let arg = AngleBracketedArg::Constraint(AssocTyConstraint {
|
||||||
id: rustc_ast::node_id::DUMMY_NODE_ID,
|
id: rustc_ast::node_id::DUMMY_NODE_ID,
|
||||||
ident: *ident,
|
ident: *ident,
|
||||||
|
gen_args,
|
||||||
kind: AssocTyConstraintKind::Equality {
|
kind: AssocTyConstraintKind::Equality {
|
||||||
ty: predicate.rhs_ty.clone(),
|
ty: predicate.rhs_ty.clone(),
|
||||||
},
|
},
|
||||||
|
@ -370,7 +370,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
|
|||||||
ast::ItemKind::Trait(ast::IsAuto::Yes, ..) => {
|
ast::ItemKind::Trait(ast::IsAuto::Yes, ..) => {
|
||||||
gate_feature_post!(
|
gate_feature_post!(
|
||||||
&self,
|
&self,
|
||||||
optin_builtin_traits,
|
auto_traits,
|
||||||
i.span,
|
i.span,
|
||||||
"auto traits are experimental and possibly buggy"
|
"auto traits are experimental and possibly buggy"
|
||||||
);
|
);
|
||||||
@ -620,7 +620,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
gate_all!(if_let_guard, "`if let` guard is not implemented");
|
gate_all!(if_let_guard, "`if let` guards are experimental");
|
||||||
gate_all!(let_chains, "`let` expressions in this position are experimental");
|
gate_all!(let_chains, "`let` expressions in this position are experimental");
|
||||||
gate_all!(async_closure, "async closures are unstable");
|
gate_all!(async_closure, "async closures are unstable");
|
||||||
gate_all!(generators, "yield syntax is experimental");
|
gate_all!(generators, "yield syntax is experimental");
|
||||||
@ -630,7 +630,15 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
|
|||||||
gate_all!(const_trait_impl, "const trait impls are experimental");
|
gate_all!(const_trait_impl, "const trait impls are experimental");
|
||||||
gate_all!(half_open_range_patterns, "half-open range patterns are unstable");
|
gate_all!(half_open_range_patterns, "half-open range patterns are unstable");
|
||||||
gate_all!(inline_const, "inline-const is experimental");
|
gate_all!(inline_const, "inline-const is experimental");
|
||||||
|
gate_all!(
|
||||||
|
extended_key_value_attributes,
|
||||||
|
"arbitrary expressions in key-value attributes are unstable"
|
||||||
|
);
|
||||||
|
if sess.parse_sess.span_diagnostic.err_count() == 0 {
|
||||||
|
// Errors for `destructuring_assignment` can get quite noisy, especially where `_` is
|
||||||
|
// involved, so we only emit errors where there are no other parsing errors.
|
||||||
gate_all!(destructuring_assignment, "destructuring assignments are unstable");
|
gate_all!(destructuring_assignment, "destructuring assignments are unstable");
|
||||||
|
}
|
||||||
|
|
||||||
// All uses of `gate_all!` below this point were added in #65742,
|
// All uses of `gate_all!` below this point were added in #65742,
|
||||||
// and subsequently disabled (with the non-early gating readded).
|
// and subsequently disabled (with the non-early gating readded).
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#![feature(bindings_after_at)]
|
#![feature(bindings_after_at)]
|
||||||
#![feature(iter_is_partitioned)]
|
#![feature(iter_is_partitioned)]
|
||||||
|
#![recursion_limit = "256"]
|
||||||
|
|
||||||
pub mod ast_validation;
|
pub mod ast_validation;
|
||||||
pub mod feature_gate;
|
pub mod feature_gate;
|
||||||
|
@ -109,7 +109,6 @@ pub fn print_crate<'a>(
|
|||||||
ann: &'a dyn PpAnn,
|
ann: &'a dyn PpAnn,
|
||||||
is_expanded: bool,
|
is_expanded: bool,
|
||||||
edition: Edition,
|
edition: Edition,
|
||||||
has_injected_crate: bool,
|
|
||||||
) -> String {
|
) -> String {
|
||||||
let mut s = State {
|
let mut s = State {
|
||||||
s: pp::mk_printer(),
|
s: pp::mk_printer(),
|
||||||
@ -119,7 +118,7 @@ pub fn print_crate<'a>(
|
|||||||
insert_extra_parens: true,
|
insert_extra_parens: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
if is_expanded && has_injected_crate {
|
if is_expanded && !krate.attrs.iter().any(|attr| attr.has_name(sym::no_core)) {
|
||||||
// We need to print `#![no_std]` (and its feature gate) so that
|
// We need to print `#![no_std]` (and its feature gate) so that
|
||||||
// compiling pretty-printed source won't inject libstd again.
|
// compiling pretty-printed source won't inject libstd again.
|
||||||
// However, we don't want these attributes in the AST because
|
// However, we don't want these attributes in the AST because
|
||||||
@ -2068,6 +2067,7 @@ impl<'a> State<'a> {
|
|||||||
self.print_expr_maybe_paren(e, fake_prec);
|
self.print_expr_maybe_paren(e, fake_prec);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ast::ExprKind::Underscore => self.s.word("_"),
|
||||||
ast::ExprKind::Path(None, ref path) => self.print_path(path, true, 0),
|
ast::ExprKind::Path(None, ref path) => self.print_path(path, true, 0),
|
||||||
ast::ExprKind::Path(Some(ref qself), ref path) => self.print_qpath(path, qself, true),
|
ast::ExprKind::Path(Some(ref qself), ref path) => self.print_qpath(path, qself, true),
|
||||||
ast::ExprKind::Break(opt_label, ref opt_expr) => {
|
ast::ExprKind::Break(opt_label, ref opt_expr) => {
|
||||||
@ -2327,13 +2327,14 @@ impl<'a> State<'a> {
|
|||||||
self.print_path(path, false, depth);
|
self.print_path(path, false, depth);
|
||||||
}
|
}
|
||||||
self.s.word(">");
|
self.s.word(">");
|
||||||
|
for item_segment in &path.segments[qself.position..] {
|
||||||
self.s.word("::");
|
self.s.word("::");
|
||||||
let item_segment = path.segments.last().unwrap();
|
|
||||||
self.print_ident(item_segment.ident);
|
self.print_ident(item_segment.ident);
|
||||||
if let Some(ref args) = item_segment.args {
|
if let Some(ref args) = item_segment.args {
|
||||||
self.print_generic_args(args, colons_before_params)
|
self.print_generic_args(args, colons_before_params)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
crate fn print_pat(&mut self, pat: &ast::Pat) {
|
crate fn print_pat(&mut self, pat: &ast::Pat) {
|
||||||
self.maybe_print_comment(pat.span.lo());
|
self.maybe_print_comment(pat.span.lo());
|
||||||
@ -2419,7 +2420,15 @@ impl<'a> State<'a> {
|
|||||||
if mutbl == ast::Mutability::Mut {
|
if mutbl == ast::Mutability::Mut {
|
||||||
self.s.word("mut ");
|
self.s.word("mut ");
|
||||||
}
|
}
|
||||||
|
if let PatKind::Ident(ast::BindingMode::ByValue(ast::Mutability::Mut), ..) =
|
||||||
|
inner.kind
|
||||||
|
{
|
||||||
|
self.popen();
|
||||||
self.print_pat(inner);
|
self.print_pat(inner);
|
||||||
|
self.pclose();
|
||||||
|
} else {
|
||||||
|
self.print_pat(inner);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
PatKind::Lit(ref e) => self.print_expr(&**e),
|
PatKind::Lit(ref e) => self.print_expr(&**e),
|
||||||
PatKind::Range(ref begin, ref end, Spanned { node: ref end_kind, .. }) => {
|
PatKind::Range(ref begin, ref end, Spanned { node: ref end_kind, .. }) => {
|
||||||
|
@ -67,7 +67,7 @@ fn handle_errors(sess: &ParseSess, span: Span, error: AttrError) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Encodable, Decodable)]
|
#[derive(Copy, Clone, PartialEq, Encodable, Decodable)]
|
||||||
pub enum InlineAttr {
|
pub enum InlineAttr {
|
||||||
None,
|
None,
|
||||||
Hint,
|
Hint,
|
||||||
@ -294,7 +294,7 @@ where
|
|||||||
or \"none\"",
|
or \"none\"",
|
||||||
)
|
)
|
||||||
.span_label(
|
.span_label(
|
||||||
mi.name_value_literal().unwrap().span,
|
mi.name_value_literal_span().unwrap(),
|
||||||
msg,
|
msg,
|
||||||
)
|
)
|
||||||
.emit();
|
.emit();
|
||||||
@ -621,7 +621,7 @@ pub fn eval_condition(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Encodable, Decodable, Clone, HashStable_Generic)]
|
#[derive(Debug, Encodable, Decodable, Clone, HashStable_Generic)]
|
||||||
pub struct Deprecation {
|
pub struct Deprecation {
|
||||||
pub since: Option<Symbol>,
|
pub since: Option<Symbol>,
|
||||||
/// The note to issue a reason.
|
/// The note to issue a reason.
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
use rustc_errors::{Applicability, DiagnosticBuilder};
|
use rustc_errors::{Applicability, DiagnosticBuilder};
|
||||||
|
|
||||||
use rustc_ast::ptr::P;
|
use rustc_ast::ptr::P;
|
||||||
use rustc_ast::token::{self, TokenKind};
|
use rustc_ast::token;
|
||||||
use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree};
|
use rustc_ast::tokenstream::{DelimSpan, TokenStream};
|
||||||
use rustc_ast::{self as ast, *};
|
use rustc_ast::{self as ast, *};
|
||||||
use rustc_ast_pretty::pprust;
|
use rustc_ast_pretty::pprust;
|
||||||
use rustc_expand::base::*;
|
use rustc_expand::base::*;
|
||||||
@ -26,31 +26,39 @@ pub fn expand_assert<'cx>(
|
|||||||
// `core::panic` and `std::panic` are different macros, so we use call-site
|
// `core::panic` and `std::panic` are different macros, so we use call-site
|
||||||
// context to pick up whichever is currently in scope.
|
// context to pick up whichever is currently in scope.
|
||||||
let sp = cx.with_call_site_ctxt(sp);
|
let sp = cx.with_call_site_ctxt(sp);
|
||||||
let tokens = custom_message.unwrap_or_else(|| {
|
|
||||||
TokenStream::from(TokenTree::token(
|
let panic_call = if let Some(tokens) = custom_message {
|
||||||
TokenKind::lit(
|
// Pass the custom message to panic!().
|
||||||
token::Str,
|
cx.expr(
|
||||||
|
sp,
|
||||||
|
ExprKind::MacCall(MacCall {
|
||||||
|
path: Path::from_ident(Ident::new(sym::panic, sp)),
|
||||||
|
args: P(MacArgs::Delimited(
|
||||||
|
DelimSpan::from_single(sp),
|
||||||
|
MacDelimiter::Parenthesis,
|
||||||
|
tokens,
|
||||||
|
)),
|
||||||
|
prior_type_ascription: None,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
// Pass our own message directly to $crate::panicking::panic(),
|
||||||
|
// because it might contain `{` and `}` that should always be
|
||||||
|
// passed literally.
|
||||||
|
cx.expr_call_global(
|
||||||
|
sp,
|
||||||
|
cx.std_path(&[sym::panicking, sym::panic]),
|
||||||
|
vec![cx.expr_str(
|
||||||
|
DUMMY_SP,
|
||||||
Symbol::intern(&format!(
|
Symbol::intern(&format!(
|
||||||
"assertion failed: {}",
|
"assertion failed: {}",
|
||||||
pprust::expr_to_string(&cond_expr).escape_debug()
|
pprust::expr_to_string(&cond_expr).escape_debug()
|
||||||
)),
|
)),
|
||||||
None,
|
)],
|
||||||
),
|
)
|
||||||
DUMMY_SP,
|
|
||||||
))
|
|
||||||
});
|
|
||||||
let args = P(MacArgs::Delimited(DelimSpan::from_single(sp), MacDelimiter::Parenthesis, tokens));
|
|
||||||
let panic_call = MacCall {
|
|
||||||
path: Path::from_ident(Ident::new(sym::panic, sp)),
|
|
||||||
args,
|
|
||||||
prior_type_ascription: None,
|
|
||||||
};
|
};
|
||||||
let if_expr = cx.expr_if(
|
let if_expr =
|
||||||
sp,
|
cx.expr_if(sp, cx.expr(sp, ExprKind::Unary(UnOp::Not, cond_expr)), panic_call, None);
|
||||||
cx.expr(sp, ExprKind::Unary(UnOp::Not, cond_expr)),
|
|
||||||
cx.expr(sp, ExprKind::MacCall(panic_call)),
|
|
||||||
None,
|
|
||||||
);
|
|
||||||
MacEager::expr(if_expr)
|
MacEager::expr(if_expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
//! Implementation of the `#[cfg_accessible(path)]` attribute macro.
|
//! Implementation of the `#[cfg_accessible(path)]` attribute macro.
|
||||||
|
|
||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, MultiItemModifier};
|
use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, Indeterminate, MultiItemModifier};
|
||||||
use rustc_feature::AttributeTemplate;
|
use rustc_feature::AttributeTemplate;
|
||||||
use rustc_parse::validate_attr;
|
use rustc_parse::validate_attr;
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
@ -31,7 +31,7 @@ impl MultiItemModifier for Expander {
|
|||||||
fn expand(
|
fn expand(
|
||||||
&self,
|
&self,
|
||||||
ecx: &mut ExtCtxt<'_>,
|
ecx: &mut ExtCtxt<'_>,
|
||||||
_span: Span,
|
span: Span,
|
||||||
meta_item: &ast::MetaItem,
|
meta_item: &ast::MetaItem,
|
||||||
item: Annotatable,
|
item: Annotatable,
|
||||||
) -> ExpandResult<Vec<Annotatable>, Annotatable> {
|
) -> ExpandResult<Vec<Annotatable>, Annotatable> {
|
||||||
@ -49,11 +49,14 @@ impl MultiItemModifier for Expander {
|
|||||||
None => return ExpandResult::Ready(Vec::new()),
|
None => return ExpandResult::Ready(Vec::new()),
|
||||||
};
|
};
|
||||||
|
|
||||||
let failure_msg = "cannot determine whether the path is accessible or not";
|
|
||||||
match ecx.resolver.cfg_accessible(ecx.current_expansion.id, path) {
|
match ecx.resolver.cfg_accessible(ecx.current_expansion.id, path) {
|
||||||
Ok(true) => ExpandResult::Ready(vec![item]),
|
Ok(true) => ExpandResult::Ready(vec![item]),
|
||||||
Ok(false) => ExpandResult::Ready(Vec::new()),
|
Ok(false) => ExpandResult::Ready(Vec::new()),
|
||||||
Err(_) => ExpandResult::Retry(item, failure_msg.into()),
|
Err(Indeterminate) if ecx.force_mode => {
|
||||||
|
ecx.span_err(span, "cannot determine whether the path is accessible or not");
|
||||||
|
ExpandResult::Ready(vec![item])
|
||||||
|
}
|
||||||
|
Err(Indeterminate) => ExpandResult::Retry(item),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ fn show_substructure(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>
|
|||||||
|
|
||||||
let fmt = substr.nonself_args[0].clone();
|
let fmt = substr.nonself_args[0].clone();
|
||||||
|
|
||||||
let mut stmts = vec![];
|
let mut stmts = Vec::with_capacity(fields.len() + 2);
|
||||||
match vdata {
|
match vdata {
|
||||||
ast::VariantData::Tuple(..) | ast::VariantData::Unit(..) => {
|
ast::VariantData::Tuple(..) | ast::VariantData::Unit(..) => {
|
||||||
// tuple struct/"normal" variant
|
// tuple struct/"normal" variant
|
||||||
@ -132,6 +132,7 @@ fn stmt_let_underscore(cx: &mut ExtCtxt<'_>, sp: Span, expr: P<ast::Expr>) -> as
|
|||||||
id: ast::DUMMY_NODE_ID,
|
id: ast::DUMMY_NODE_ID,
|
||||||
span: sp,
|
span: sp,
|
||||||
attrs: ast::AttrVec::new(),
|
attrs: ast::AttrVec::new(),
|
||||||
|
tokens: None,
|
||||||
});
|
});
|
||||||
ast::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Local(local), span: sp, tokens: None }
|
ast::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Local(local), span: sp }
|
||||||
}
|
}
|
||||||
|
@ -257,7 +257,10 @@ pub struct Substructure<'a> {
|
|||||||
pub type_ident: Ident,
|
pub type_ident: Ident,
|
||||||
/// ident of the method
|
/// ident of the method
|
||||||
pub method_ident: Ident,
|
pub method_ident: Ident,
|
||||||
/// dereferenced access to any `Self_` or `Ptr(Self_, _)` arguments
|
/// dereferenced access to any [`Self_`] or [`Ptr(Self_, _)][ptr]` arguments
|
||||||
|
///
|
||||||
|
/// [`Self_`]: ty::Ty::Self_
|
||||||
|
/// [ptr]: ty::Ty::Ptr
|
||||||
pub self_args: &'a [P<Expr>],
|
pub self_args: &'a [P<Expr>],
|
||||||
/// verbatim access to any other arguments
|
/// verbatim access to any other arguments
|
||||||
pub nonself_args: &'a [P<Expr>],
|
pub nonself_args: &'a [P<Expr>],
|
||||||
@ -407,13 +410,7 @@ impl<'a> TraitDef<'a> {
|
|||||||
_ => false,
|
_ => false,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
_ => {
|
_ => unreachable!(),
|
||||||
// Non-ADT derive is an error, but it should have been
|
|
||||||
// set earlier; see
|
|
||||||
// librustc_expand/expand.rs:MacroExpander::fully_expand_fragment()
|
|
||||||
// librustc_expand/base.rs:Annotatable::derive_allowed()
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
let container_id = cx.current_expansion.id.expn_data().parent;
|
let container_id = cx.current_expansion.id.expn_data().parent;
|
||||||
let always_copy = has_no_type_params && cx.resolver.has_derive_copy(container_id);
|
let always_copy = has_no_type_params && cx.resolver.has_derive_copy(container_id);
|
||||||
@ -475,12 +472,7 @@ impl<'a> TraitDef<'a> {
|
|||||||
);
|
);
|
||||||
push(Annotatable::Item(P(ast::Item { attrs, ..(*newitem).clone() })))
|
push(Annotatable::Item(P(ast::Item { attrs, ..(*newitem).clone() })))
|
||||||
}
|
}
|
||||||
_ => {
|
_ => unreachable!(),
|
||||||
// Non-Item derive is an error, but it should have been
|
|
||||||
// set earlier; see
|
|
||||||
// librustc_expand/expand.rs:MacroExpander::fully_expand_fragment()
|
|
||||||
// librustc_expand/base.rs:Annotatable::derive_allowed()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -608,10 +600,7 @@ impl<'a> TraitDef<'a> {
|
|||||||
|
|
||||||
let mut ty_params = params
|
let mut ty_params = params
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|param| match param.kind {
|
.filter(|param| matches!(param.kind, ast::GenericParamKind::Type{..}))
|
||||||
ast::GenericParamKind::Type { .. } => Some(param),
|
|
||||||
_ => None,
|
|
||||||
})
|
|
||||||
.peekable();
|
.peekable();
|
||||||
|
|
||||||
if ty_params.peek().is_some() {
|
if ty_params.peek().is_some() {
|
||||||
|
@ -54,7 +54,26 @@ impl MultiItemModifier for BuiltinDerive {
|
|||||||
// so we are doing it here in a centralized way.
|
// so we are doing it here in a centralized way.
|
||||||
let span = ecx.with_def_site_ctxt(span);
|
let span = ecx.with_def_site_ctxt(span);
|
||||||
let mut items = Vec::new();
|
let mut items = Vec::new();
|
||||||
|
match item {
|
||||||
|
Annotatable::Stmt(stmt) => {
|
||||||
|
if let ast::StmtKind::Item(item) = stmt.into_inner().kind {
|
||||||
|
(self.0)(ecx, span, meta_item, &Annotatable::Item(item), &mut |a| {
|
||||||
|
// Cannot use 'ecx.stmt_item' here, because we need to pass 'ecx'
|
||||||
|
// to the function
|
||||||
|
items.push(Annotatable::Stmt(P(ast::Stmt {
|
||||||
|
id: ast::DUMMY_NODE_ID,
|
||||||
|
kind: ast::StmtKind::Item(a.expect_item()),
|
||||||
|
span,
|
||||||
|
})));
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
unreachable!("should have already errored on non-item statement")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
(self.0)(ecx, span, meta_item, &item, &mut |a| items.push(a));
|
(self.0)(ecx, span, meta_item, &item, &mut |a| items.push(a));
|
||||||
|
}
|
||||||
|
}
|
||||||
ExpandResult::Ready(items)
|
ExpandResult::Ready(items)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -98,13 +117,7 @@ fn inject_impl_of_structural_trait(
|
|||||||
) {
|
) {
|
||||||
let item = match *item {
|
let item = match *item {
|
||||||
Annotatable::Item(ref item) => item,
|
Annotatable::Item(ref item) => item,
|
||||||
_ => {
|
_ => unreachable!(),
|
||||||
// Non-Item derive is an error, but it should have been
|
|
||||||
// set earlier; see
|
|
||||||
// librustc_expand/expand.rs:MacroExpander::fully_expand_fragment()
|
|
||||||
// librustc_expand/base.rs:Annotatable::derive_allowed()
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let generics = match item.kind {
|
let generics = match item.kind {
|
||||||
|
@ -649,8 +649,7 @@ pub mod shell {
|
|||||||
impl<'a> Iterator for Substitutions<'a> {
|
impl<'a> Iterator for Substitutions<'a> {
|
||||||
type Item = Substitution<'a>;
|
type Item = Substitution<'a>;
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
match parse_next_substitution(self.s) {
|
let (mut sub, tail) = parse_next_substitution(self.s)?;
|
||||||
Some((mut sub, tail)) => {
|
|
||||||
self.s = tail;
|
self.s = tail;
|
||||||
if let Some(InnerSpan { start, end }) = sub.position() {
|
if let Some(InnerSpan { start, end }) = sub.position() {
|
||||||
sub.set_position(start + self.pos, end + self.pos);
|
sub.set_position(start + self.pos, end + self.pos);
|
||||||
@ -658,9 +657,6 @@ pub mod shell {
|
|||||||
}
|
}
|
||||||
Some(sub)
|
Some(sub)
|
||||||
}
|
}
|
||||||
None => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
(0, Some(self.s.len()))
|
(0, Some(self.s.len()))
|
||||||
|
@ -4,7 +4,7 @@ use rustc_ast::expand::allocator::{
|
|||||||
AllocatorKind, AllocatorMethod, AllocatorTy, ALLOCATOR_METHODS,
|
AllocatorKind, AllocatorMethod, AllocatorTy, ALLOCATOR_METHODS,
|
||||||
};
|
};
|
||||||
use rustc_ast::ptr::P;
|
use rustc_ast::ptr::P;
|
||||||
use rustc_ast::{self as ast, Attribute, Expr, FnHeader, FnSig, Generics, Param};
|
use rustc_ast::{self as ast, Attribute, Expr, FnHeader, FnSig, Generics, Param, StmtKind};
|
||||||
use rustc_ast::{ItemKind, Mutability, Stmt, Ty, TyKind, Unsafe};
|
use rustc_ast::{ItemKind, Mutability, Stmt, Ty, TyKind, Unsafe};
|
||||||
use rustc_expand::base::{Annotatable, ExtCtxt};
|
use rustc_expand::base::{Annotatable, ExtCtxt};
|
||||||
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
use rustc_span::symbol::{kw, sym, Ident, Symbol};
|
||||||
@ -14,7 +14,7 @@ pub fn expand(
|
|||||||
ecx: &mut ExtCtxt<'_>,
|
ecx: &mut ExtCtxt<'_>,
|
||||||
_span: Span,
|
_span: Span,
|
||||||
meta_item: &ast::MetaItem,
|
meta_item: &ast::MetaItem,
|
||||||
item: Annotatable,
|
mut item: Annotatable,
|
||||||
) -> Vec<Annotatable> {
|
) -> Vec<Annotatable> {
|
||||||
check_builtin_macro_attribute(ecx, meta_item, sym::global_allocator);
|
check_builtin_macro_attribute(ecx, meta_item, sym::global_allocator);
|
||||||
|
|
||||||
@ -22,6 +22,17 @@ pub fn expand(
|
|||||||
ecx.sess.parse_sess.span_diagnostic.span_err(item.span(), "allocators must be statics");
|
ecx.sess.parse_sess.span_diagnostic.span_err(item.span(), "allocators must be statics");
|
||||||
vec![item]
|
vec![item]
|
||||||
};
|
};
|
||||||
|
let orig_item = item.clone();
|
||||||
|
let mut is_stmt = false;
|
||||||
|
|
||||||
|
// Allow using `#[global_allocator]` on an item statement
|
||||||
|
if let Annotatable::Stmt(stmt) = &item {
|
||||||
|
if let StmtKind::Item(item_) = &stmt.kind {
|
||||||
|
item = Annotatable::Item(item_.clone());
|
||||||
|
is_stmt = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let item = match item {
|
let item = match item {
|
||||||
Annotatable::Item(item) => match item.kind {
|
Annotatable::Item(item) => match item.kind {
|
||||||
ItemKind::Static(..) => item,
|
ItemKind::Static(..) => item,
|
||||||
@ -41,9 +52,14 @@ pub fn expand(
|
|||||||
let const_ty = ecx.ty(span, TyKind::Tup(Vec::new()));
|
let const_ty = ecx.ty(span, TyKind::Tup(Vec::new()));
|
||||||
let const_body = ecx.expr_block(ecx.block(span, stmts));
|
let const_body = ecx.expr_block(ecx.block(span, stmts));
|
||||||
let const_item = ecx.item_const(span, Ident::new(kw::Underscore, span), const_ty, const_body);
|
let const_item = ecx.item_const(span, Ident::new(kw::Underscore, span), const_ty, const_body);
|
||||||
|
let const_item = if is_stmt {
|
||||||
|
Annotatable::Stmt(P(ecx.stmt_item(span, const_item)))
|
||||||
|
} else {
|
||||||
|
Annotatable::Item(const_item)
|
||||||
|
};
|
||||||
|
|
||||||
// Return the original item and the new methods.
|
// Return the original item and the new methods.
|
||||||
vec![Annotatable::Item(item), Annotatable::Item(const_item)]
|
vec![orig_item, const_item]
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AllocFnFactory<'a, 'b> {
|
struct AllocFnFactory<'a, 'b> {
|
||||||
|
@ -13,12 +13,12 @@ pub fn inject(
|
|||||||
resolver: &mut dyn ResolverExpand,
|
resolver: &mut dyn ResolverExpand,
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
alt_std_name: Option<Symbol>,
|
alt_std_name: Option<Symbol>,
|
||||||
) -> (ast::Crate, Option<Symbol>) {
|
) -> ast::Crate {
|
||||||
let rust_2018 = sess.parse_sess.edition >= Edition::Edition2018;
|
let rust_2018 = sess.parse_sess.edition >= Edition::Edition2018;
|
||||||
|
|
||||||
// the first name in this list is the crate name of the crate with the prelude
|
// the first name in this list is the crate name of the crate with the prelude
|
||||||
let names: &[Symbol] = if sess.contains_name(&krate.attrs, sym::no_core) {
|
let names: &[Symbol] = if sess.contains_name(&krate.attrs, sym::no_core) {
|
||||||
return (krate, None);
|
return krate;
|
||||||
} else if sess.contains_name(&krate.attrs, sym::no_std) {
|
} else if sess.contains_name(&krate.attrs, sym::no_std) {
|
||||||
if sess.contains_name(&krate.attrs, sym::compiler_builtins) {
|
if sess.contains_name(&krate.attrs, sym::compiler_builtins) {
|
||||||
&[sym::core]
|
&[sym::core]
|
||||||
@ -81,5 +81,5 @@ pub fn inject(
|
|||||||
|
|
||||||
krate.module.items.insert(0, use_item);
|
krate.module.items.insert(0, use_item);
|
||||||
|
|
||||||
(krate, Some(name))
|
krate
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ use crate::util::check_builtin_macro_attribute;
|
|||||||
|
|
||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
use rustc_ast::attr;
|
use rustc_ast::attr;
|
||||||
|
use rustc_ast::ptr::P;
|
||||||
use rustc_ast_pretty::pprust;
|
use rustc_ast_pretty::pprust;
|
||||||
use rustc_expand::base::*;
|
use rustc_expand::base::*;
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
@ -78,8 +79,16 @@ pub fn expand_test_or_bench(
|
|||||||
return vec![];
|
return vec![];
|
||||||
}
|
}
|
||||||
|
|
||||||
let item = match item {
|
let (item, is_stmt) = match item {
|
||||||
Annotatable::Item(i) => i,
|
Annotatable::Item(i) => (i, false),
|
||||||
|
Annotatable::Stmt(stmt) if matches!(stmt.kind, ast::StmtKind::Item(_)) => {
|
||||||
|
// FIXME: Use an 'if let' guard once they are implemented
|
||||||
|
if let ast::StmtKind::Item(i) = stmt.into_inner().kind {
|
||||||
|
(i, true)
|
||||||
|
} else {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
other => {
|
other => {
|
||||||
cx.struct_span_err(
|
cx.struct_span_err(
|
||||||
other.span(),
|
other.span(),
|
||||||
@ -304,6 +313,16 @@ pub fn expand_test_or_bench(
|
|||||||
|
|
||||||
tracing::debug!("synthetic test item:\n{}\n", pprust::item_to_string(&test_const));
|
tracing::debug!("synthetic test item:\n{}\n", pprust::item_to_string(&test_const));
|
||||||
|
|
||||||
|
if is_stmt {
|
||||||
|
vec![
|
||||||
|
// Access to libtest under a hygienic name
|
||||||
|
Annotatable::Stmt(P(cx.stmt_item(sp, test_extern))),
|
||||||
|
// The generated test case
|
||||||
|
Annotatable::Stmt(P(cx.stmt_item(sp, test_const))),
|
||||||
|
// The original item
|
||||||
|
Annotatable::Stmt(P(cx.stmt_item(sp, item))),
|
||||||
|
]
|
||||||
|
} else {
|
||||||
vec![
|
vec![
|
||||||
// Access to libtest under a hygienic name
|
// Access to libtest under a hygienic name
|
||||||
Annotatable::Item(test_extern),
|
Annotatable::Item(test_extern),
|
||||||
@ -313,6 +332,7 @@ pub fn expand_test_or_bench(
|
|||||||
Annotatable::Item(item),
|
Annotatable::Item(item),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn item_path(mod_path: &[Ident], item_ident: &Ident) -> String {
|
fn item_path(mod_path: &[Ident], item_ident: &Ident) -> String {
|
||||||
mod_path
|
mod_path
|
||||||
|
104
compiler/rustc_codegen_cranelift/Cargo.lock
generated
104
compiler/rustc_codegen_cranelift/Cargo.lock
generated
@ -2,9 +2,9 @@
|
|||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.33"
|
version = "1.0.34"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a1fd36ffbb1fb7c834eac128ea8d0e310c5aeb635548f9d58861e1308d46e71c"
|
checksum = "bf8dcb5b4bbaa28653b647d8c77bd4ed40183b48882e130c1f1ffb73de069fd7"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ar"
|
name = "ar"
|
||||||
@ -31,9 +31,9 @@ checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.0.61"
|
version = "1.0.62"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ed67cbde08356238e75fc4656be4749481eeffb09e19f320a25237d5221c985d"
|
checksum = "f1770ced377336a88a67c473594ccc14eca6f4559217c34f64aac8f83d641b40"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
@ -41,18 +41,24 @@ version = "0.1.10"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cranelift-bforest"
|
name = "cranelift-bforest"
|
||||||
version = "0.67.0"
|
version = "0.68.0"
|
||||||
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#44cbdecea03c360ea82e6482f0cf6c614effef21"
|
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#19640367dbf0da7093e61add3306c8d092644fb3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cranelift-entity",
|
"cranelift-entity",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cranelift-codegen"
|
name = "cranelift-codegen"
|
||||||
version = "0.67.0"
|
version = "0.68.0"
|
||||||
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#44cbdecea03c360ea82e6482f0cf6c614effef21"
|
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#19640367dbf0da7093e61add3306c8d092644fb3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"cranelift-bforest",
|
"cranelift-bforest",
|
||||||
@ -69,8 +75,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cranelift-codegen-meta"
|
name = "cranelift-codegen-meta"
|
||||||
version = "0.67.0"
|
version = "0.68.0"
|
||||||
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#44cbdecea03c360ea82e6482f0cf6c614effef21"
|
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#19640367dbf0da7093e61add3306c8d092644fb3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cranelift-codegen-shared",
|
"cranelift-codegen-shared",
|
||||||
"cranelift-entity",
|
"cranelift-entity",
|
||||||
@ -78,18 +84,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cranelift-codegen-shared"
|
name = "cranelift-codegen-shared"
|
||||||
version = "0.67.0"
|
version = "0.68.0"
|
||||||
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#44cbdecea03c360ea82e6482f0cf6c614effef21"
|
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#19640367dbf0da7093e61add3306c8d092644fb3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cranelift-entity"
|
name = "cranelift-entity"
|
||||||
version = "0.67.0"
|
version = "0.68.0"
|
||||||
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#44cbdecea03c360ea82e6482f0cf6c614effef21"
|
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#19640367dbf0da7093e61add3306c8d092644fb3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cranelift-frontend"
|
name = "cranelift-frontend"
|
||||||
version = "0.67.0"
|
version = "0.68.0"
|
||||||
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#44cbdecea03c360ea82e6482f0cf6c614effef21"
|
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#19640367dbf0da7093e61add3306c8d092644fb3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cranelift-codegen",
|
"cranelift-codegen",
|
||||||
"log",
|
"log",
|
||||||
@ -99,8 +105,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cranelift-module"
|
name = "cranelift-module"
|
||||||
version = "0.67.0"
|
version = "0.68.0"
|
||||||
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#44cbdecea03c360ea82e6482f0cf6c614effef21"
|
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#19640367dbf0da7093e61add3306c8d092644fb3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"cranelift-codegen",
|
"cranelift-codegen",
|
||||||
@ -111,8 +117,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cranelift-native"
|
name = "cranelift-native"
|
||||||
version = "0.67.0"
|
version = "0.68.0"
|
||||||
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#44cbdecea03c360ea82e6482f0cf6c614effef21"
|
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#19640367dbf0da7093e61add3306c8d092644fb3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cranelift-codegen",
|
"cranelift-codegen",
|
||||||
"raw-cpuid",
|
"raw-cpuid",
|
||||||
@ -121,8 +127,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cranelift-object"
|
name = "cranelift-object"
|
||||||
version = "0.67.0"
|
version = "0.68.0"
|
||||||
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#44cbdecea03c360ea82e6482f0cf6c614effef21"
|
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#19640367dbf0da7093e61add3306c8d092644fb3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"cranelift-codegen",
|
"cranelift-codegen",
|
||||||
@ -134,8 +140,8 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cranelift-simplejit"
|
name = "cranelift-simplejit"
|
||||||
version = "0.67.0"
|
version = "0.68.0"
|
||||||
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#44cbdecea03c360ea82e6482f0cf6c614effef21"
|
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#19640367dbf0da7093e61add3306c8d092644fb3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cranelift-codegen",
|
"cranelift-codegen",
|
||||||
"cranelift-entity",
|
"cranelift-entity",
|
||||||
@ -151,18 +157,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crc32fast"
|
name = "crc32fast"
|
||||||
version = "1.2.0"
|
version = "1.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1"
|
checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if 1.0.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "errno"
|
name = "errno"
|
||||||
version = "0.2.6"
|
version = "0.2.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6eab5ee3df98a279d9b316b1af6ac95422127b1290317e6d18c1743c99418b01"
|
checksum = "fa68f2fb9cae9d37c9b2b3584aba698a2e97f72d7aef7b9f7aa71d8b54ce46fe"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"errno-dragonfly",
|
"errno-dragonfly",
|
||||||
"libc",
|
"libc",
|
||||||
@ -187,9 +193,9 @@ checksum = "8f5f3913fa0bfe7ee1fd8248b6b9f42a5af4b9d65ec2dd2c3c26132b950ecfc2"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gimli"
|
name = "gimli"
|
||||||
version = "0.22.0"
|
version = "0.23.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "aaf91faf136cb47367fa430cd46e37a788775e7fa104f8b4bcb3861dc389b724"
|
checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap",
|
"indexmap",
|
||||||
]
|
]
|
||||||
@ -212,17 +218,17 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.79"
|
version = "0.2.80"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2448f6066e80e3bfc792e9c98bf705b4b0fc6e8ef5b43e5889aff0eaa9c58743"
|
checksum = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libloading"
|
name = "libloading"
|
||||||
version = "0.6.4"
|
version = "0.6.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3557c9384f7f757f6d139cd3a4c62ef4e850696c16bf27924a5538c8a09717a1"
|
checksum = "1090080fe06ec2648d0da3881d9453d97e71a45f00eb179af7fdd7e3f686fdb0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if 1.0.0",
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -232,7 +238,7 @@ version = "0.4.11"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b"
|
checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if 0.1.10",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -246,9 +252,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "object"
|
name = "object"
|
||||||
version = "0.21.1"
|
version = "0.22.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "37fd5004feb2ce328a52b0b3d01dbf4ffff72583493900ed15f22d4111c51693"
|
checksum = "8d3b63360ec3cb337817c2dbd47ab4a0f170d285d8e5a2064600f3def1402397"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crc32fast",
|
"crc32fast",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
@ -274,9 +280,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "raw-cpuid"
|
name = "raw-cpuid"
|
||||||
version = "7.0.3"
|
version = "8.1.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b4a349ca83373cfa5d6dbb66fd76e58b2cca08da71a5f6400de0a0a6a9bceeaf"
|
checksum = "1fdf7d9dbd43f3d81d94a49c1c3df73cc2b3827995147e6cf7f89d4ec5483e73"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"cc",
|
"cc",
|
||||||
@ -361,9 +367,9 @@ checksum = "fbee7696b84bbf3d89a1c2eccff0850e3047ed46bfcd2e92c29a2d074d57e252"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "1.0.44"
|
version = "1.0.48"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e03e57e4fcbfe7749842d53e24ccb9aa12b7252dbe5e91d2acad31834c8b8fdd"
|
checksum = "cc371affeffc477f42a221a1e4297aedcea33d47d19b61455588bd9d8f6b19ac"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -372,24 +378,24 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "target-lexicon"
|
name = "target-lexicon"
|
||||||
version = "0.11.0"
|
version = "0.11.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fe2635952a442a01fd4cb53d98858b5e4bb461b02c0d111f22f31772e3e7a8b2"
|
checksum = "4ee5a98e506fb7231a304c3a1bd7c132a55016cf65001e0282480665870dfcb9"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "1.0.21"
|
version = "1.0.22"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "318234ffa22e0920fe9a40d7b8369b5f649d490980cf7aadcf1eb91594869b42"
|
checksum = "0e9ae34b84616eedaaf1e9dd6026dbe00dcafa92aa0c8077cb69df1fcfe5e53e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"thiserror-impl",
|
"thiserror-impl",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror-impl"
|
name = "thiserror-impl"
|
||||||
version = "1.0.21"
|
version = "1.0.22"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cae2447b6282786c3493999f40a9be2a6ad20cb8bd268b0a0dbf5a065535c0ab"
|
checksum = "9ba20f23e85b10754cd195504aebf6a27e2e6cbe28c17778a0c930724628dd56"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -15,8 +15,8 @@ cranelift-module = { git = "https://github.com/bytecodealliance/wasmtime/", bran
|
|||||||
cranelift-simplejit = { git = "https://github.com/bytecodealliance/wasmtime/", branch = "main", optional = true }
|
cranelift-simplejit = { git = "https://github.com/bytecodealliance/wasmtime/", branch = "main", optional = true }
|
||||||
cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime/", branch = "main" }
|
cranelift-object = { git = "https://github.com/bytecodealliance/wasmtime/", branch = "main" }
|
||||||
target-lexicon = "0.11.0"
|
target-lexicon = "0.11.0"
|
||||||
gimli = { version = "0.22.0", default-features = false, features = ["write"]}
|
gimli = { version = "0.23.0", default-features = false, features = ["write"]}
|
||||||
object = { version = "0.21.1", default-features = false, features = ["std", "read_core", "write", "coff", "elf", "macho", "pe"] }
|
object = { version = "0.22.0", default-features = false, features = ["std", "read_core", "write", "coff", "elf", "macho", "pe"] }
|
||||||
|
|
||||||
ar = { git = "https://github.com/bjorn3/rust-ar.git", branch = "do_not_remove_cg_clif_ranlib" }
|
ar = { git = "https://github.com/bjorn3/rust-ar.git", branch = "do_not_remove_cg_clif_ranlib" }
|
||||||
indexmap = "1.0.2"
|
indexmap = "1.0.2"
|
||||||
|
@ -51,7 +51,7 @@ This should build and run your project with rustc_codegen_cranelift instead of t
|
|||||||
> You should prefer using the Cargo method.
|
> You should prefer using the Cargo method.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ $cg_clif_dir/build/cg_clif my_crate.rs
|
$ $cg_clif_dir/build/bin/cg_clif my_crate.rs
|
||||||
```
|
```
|
||||||
|
|
||||||
### Jit mode
|
### Jit mode
|
||||||
@ -68,7 +68,7 @@ $ $cg_clif_dir/build/cargo.sh jit
|
|||||||
or
|
or
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ $cg_clif_dir/build/cg_clif --jit my_crate.rs
|
$ $cg_clif_dir/build/bin/cg_clif --jit my_crate.rs
|
||||||
```
|
```
|
||||||
|
|
||||||
### Shell
|
### Shell
|
||||||
@ -77,7 +77,7 @@ These are a few functions that allow you to easily run rust code from the shell
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
function jit_naked() {
|
function jit_naked() {
|
||||||
echo "$@" | $cg_clif_dir/build/cg_clif - --jit
|
echo "$@" | $cg_clif_dir/build/bin/cg_clif - --jit
|
||||||
}
|
}
|
||||||
|
|
||||||
function jit() {
|
function jit() {
|
||||||
|
@ -26,22 +26,35 @@ while [[ $# != 0 ]]; do
|
|||||||
done
|
done
|
||||||
|
|
||||||
# Build cg_clif
|
# Build cg_clif
|
||||||
|
unset CARGO_TARGET_DIR
|
||||||
export RUSTFLAGS="-Zrun_dsymutil=no"
|
export RUSTFLAGS="-Zrun_dsymutil=no"
|
||||||
|
unamestr=$(uname)
|
||||||
|
if [[ "$unamestr" == 'Linux' ]]; then
|
||||||
|
export RUSTFLAGS='-Clink-arg=-Wl,-rpath=$ORIGIN/../lib '$RUSTFLAGS
|
||||||
|
elif [[ "$unamestr" == 'Darwin' ]]; then
|
||||||
|
export RUSTFLAGS='-Clink-arg=-Wl,-rpath,@loader_path/../lib -Zosx-rpath-install-name '$RUSTFLAGS
|
||||||
|
dylib_ext='dylib'
|
||||||
|
else
|
||||||
|
echo "Unsupported os"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
if [[ "$CHANNEL" == "release" ]]; then
|
if [[ "$CHANNEL" == "release" ]]; then
|
||||||
cargo build --release
|
cargo build --release
|
||||||
else
|
else
|
||||||
cargo build
|
cargo build
|
||||||
fi
|
fi
|
||||||
|
|
||||||
rm -rf $target_dir
|
rm -rf "$target_dir"
|
||||||
mkdir $target_dir
|
mkdir "$target_dir"
|
||||||
cp -a target/$CHANNEL/cg_clif{,_build_sysroot} target/$CHANNEL/*rustc_codegen_cranelift* $target_dir/
|
mkdir "$target_dir"/bin "$target_dir"/lib
|
||||||
cp -a rust-toolchain scripts/config.sh scripts/cargo.sh $target_dir
|
ln target/$CHANNEL/cg_clif{,_build_sysroot} "$target_dir"/bin
|
||||||
|
ln target/$CHANNEL/*rustc_codegen_cranelift* "$target_dir"/lib
|
||||||
|
ln rust-toolchain scripts/config.sh scripts/cargo.sh "$target_dir"
|
||||||
|
|
||||||
if [[ "$build_sysroot" == "1" ]]; then
|
if [[ "$build_sysroot" == "1" ]]; then
|
||||||
echo "[BUILD] sysroot"
|
echo "[BUILD] sysroot"
|
||||||
export CG_CLIF_INCR_CACHE_DISABLED=1
|
export CG_CLIF_INCR_CACHE_DISABLED=1
|
||||||
dir=$(pwd)
|
dir=$(pwd)
|
||||||
cd $target_dir
|
cd "$target_dir"
|
||||||
time $dir/build_sysroot/build_sysroot.sh
|
time "$dir/build_sysroot/build_sysroot.sh"
|
||||||
fi
|
fi
|
||||||
|
@ -2,9 +2,9 @@
|
|||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "addr2line"
|
name = "addr2line"
|
||||||
version = "0.13.0"
|
version = "0.14.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1b6a2d3371669ab3ca9797670853d61402b03d0b4b9ebf33d677dfa720203072"
|
checksum = "7c0929d69e78dd9bf5408269919fcbcaeb2e35e5d43e5815517cdc6a8e11a423"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"compiler_builtins",
|
"compiler_builtins",
|
||||||
"gimli",
|
"gimli",
|
||||||
@ -47,9 +47,9 @@ checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.0.61"
|
version = "1.0.65"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ed67cbde08356238e75fc4656be4749481eeffb09e19f320a25237d5221c985d"
|
checksum = "95752358c8f7552394baf48cd82695b345628ad3f170d607de3ca03b8dacca15"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
@ -76,9 +76,9 @@ version = "0.0.0"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dlmalloc"
|
name = "dlmalloc"
|
||||||
version = "0.1.4"
|
version = "0.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "35055b1021724f4eb5262eb49130eebff23fc59fc5a14160e05faad8eeb36673"
|
checksum = "332570860c2edf2d57914987bf9e24835425f75825086b6ba7d1e6a3e4f1f254"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"compiler_builtins",
|
"compiler_builtins",
|
||||||
"libc",
|
"libc",
|
||||||
@ -108,9 +108,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gimli"
|
name = "gimli"
|
||||||
version = "0.22.0"
|
version = "0.23.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "aaf91faf136cb47367fa430cd46e37a788775e7fa104f8b4bcb3861dc389b724"
|
checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"compiler_builtins",
|
"compiler_builtins",
|
||||||
"rustc-std-workspace-alloc",
|
"rustc-std-workspace-alloc",
|
||||||
@ -163,9 +163,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "object"
|
name = "object"
|
||||||
version = "0.20.0"
|
version = "0.22.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1ab52be62400ca80aa00285d25253d7f7c437b7375c4de678f5405d3afe82ca5"
|
checksum = "8d3b63360ec3cb337817c2dbd47ab4a0f170d285d8e5a2064600f3def1402397"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"compiler_builtins",
|
"compiler_builtins",
|
||||||
"rustc-std-workspace-alloc",
|
"rustc-std-workspace-alloc",
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
all(target_arch = "wasm32", not(target_os = "emscripten")),
|
all(target_arch = "wasm32", not(target_os = "emscripten")),
|
||||||
feature(integer_atomics, stdsimd)
|
feature(integer_atomics, stdsimd)
|
||||||
)]
|
)]
|
||||||
#![cfg_attr(any(unix, target_os = "cloudabi", target_os = "redox"), feature(libc))]
|
#![cfg_attr(any(unix, target_os = "redox"), feature(libc))]
|
||||||
// The minimum alignment guaranteed by the architecture. This value is used to
|
// The minimum alignment guaranteed by the architecture. This value is used to
|
||||||
// add fast paths for low alignment values.
|
// add fast paths for low alignment values.
|
||||||
#[cfg(all(any(target_arch = "x86",
|
#[cfg(all(any(target_arch = "x86",
|
||||||
@ -69,7 +69,7 @@ const MIN_ALIGN: usize = 16;
|
|||||||
/// independently of the standard library’s global allocator.
|
/// independently of the standard library’s global allocator.
|
||||||
#[stable(feature = "alloc_system_type", since = "1.28.0")]
|
#[stable(feature = "alloc_system_type", since = "1.28.0")]
|
||||||
pub struct System;
|
pub struct System;
|
||||||
#[cfg(any(windows, unix, target_os = "cloudabi", target_os = "redox"))]
|
#[cfg(any(windows, unix, target_os = "redox"))]
|
||||||
mod realloc_fallback {
|
mod realloc_fallback {
|
||||||
use core::alloc::{GlobalAlloc, Layout};
|
use core::alloc::{GlobalAlloc, Layout};
|
||||||
use core::cmp;
|
use core::cmp;
|
||||||
@ -89,7 +89,7 @@ mod realloc_fallback {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(any(unix, target_os = "cloudabi", target_os = "redox"))]
|
#[cfg(any(unix, target_os = "redox"))]
|
||||||
mod platform {
|
mod platform {
|
||||||
extern crate libc;
|
extern crate libc;
|
||||||
use core::ptr;
|
use core::ptr;
|
||||||
|
@ -10,10 +10,10 @@ dir=$(pwd)
|
|||||||
|
|
||||||
# Use rustc with cg_clif as hotpluggable backend instead of the custom cg_clif driver so that
|
# Use rustc with cg_clif as hotpluggable backend instead of the custom cg_clif driver so that
|
||||||
# build scripts are still compiled using cg_llvm.
|
# build scripts are still compiled using cg_llvm.
|
||||||
export RUSTC=$dir"/cg_clif_build_sysroot"
|
export RUSTC=$dir"/bin/cg_clif_build_sysroot"
|
||||||
export RUSTFLAGS=$RUSTFLAGS" --clif"
|
export RUSTFLAGS=$RUSTFLAGS" --clif"
|
||||||
|
|
||||||
cd $(dirname "$0")
|
cd "$(dirname "$0")"
|
||||||
|
|
||||||
# Cleanup for previous run
|
# Cleanup for previous run
|
||||||
# v Clean target dir except for build scripts and incremental cache
|
# v Clean target dir except for build scripts and incremental cache
|
||||||
@ -28,12 +28,13 @@ if [[ "$1" != "--debug" ]]; then
|
|||||||
sysroot_channel='release'
|
sysroot_channel='release'
|
||||||
# FIXME Enable incremental again once rust-lang/rust#74946 is fixed
|
# FIXME Enable incremental again once rust-lang/rust#74946 is fixed
|
||||||
# FIXME Enable -Zmir-opt-level=2 again once it doesn't ice anymore
|
# FIXME Enable -Zmir-opt-level=2 again once it doesn't ice anymore
|
||||||
CARGO_INCREMENTAL=0 RUSTFLAGS="$RUSTFLAGS" cargo build --target $TARGET_TRIPLE --release
|
CARGO_INCREMENTAL=0 RUSTFLAGS="$RUSTFLAGS" cargo build --target "$TARGET_TRIPLE" --release
|
||||||
else
|
else
|
||||||
sysroot_channel='debug'
|
sysroot_channel='debug'
|
||||||
cargo build --target $TARGET_TRIPLE
|
cargo build --target "$TARGET_TRIPLE"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Copy files to sysroot
|
# Copy files to sysroot
|
||||||
mkdir -p $dir/sysroot/lib/rustlib/$TARGET_TRIPLE/lib/
|
mkdir -p "$dir/lib/rustlib/$TARGET_TRIPLE/lib/"
|
||||||
cp -a target/$TARGET_TRIPLE/$sysroot_channel/deps/* $dir/sysroot/lib/rustlib/$TARGET_TRIPLE/lib/
|
ln "target/$TARGET_TRIPLE/$sysroot_channel/deps/"* "$dir/lib/rustlib/$TARGET_TRIPLE/lib/"
|
||||||
|
rm "$dir/lib/rustlib/$TARGET_TRIPLE/lib/"*.{rmeta,d}
|
||||||
|
@ -1,18 +1,18 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
set -e
|
set -e
|
||||||
cd $(dirname "$0")
|
cd "$(dirname "$0")"
|
||||||
|
|
||||||
SRC_DIR=$(dirname $(rustup which rustc))"/../lib/rustlib/src/rust/"
|
SRC_DIR="$(dirname "$(rustup which rustc)")/../lib/rustlib/src/rust/"
|
||||||
DST_DIR="sysroot_src"
|
DST_DIR="sysroot_src"
|
||||||
|
|
||||||
if [ ! -e $SRC_DIR ]; then
|
if [ ! -e "$SRC_DIR" ]; then
|
||||||
echo "Please install rust-src component"
|
echo "Please install rust-src component"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
rm -rf $DST_DIR
|
rm -rf $DST_DIR
|
||||||
mkdir -p $DST_DIR/library
|
mkdir -p $DST_DIR/library
|
||||||
cp -a $SRC_DIR/library $DST_DIR/
|
cp -a "$SRC_DIR/library" $DST_DIR/
|
||||||
|
|
||||||
pushd $DST_DIR
|
pushd $DST_DIR
|
||||||
echo "[GIT] init"
|
echo "[GIT] init"
|
||||||
@ -22,8 +22,8 @@ git add .
|
|||||||
echo "[GIT] commit"
|
echo "[GIT] commit"
|
||||||
git commit -m "Initial commit" -q
|
git commit -m "Initial commit" -q
|
||||||
for file in $(ls ../../patches/ | grep -v patcha); do
|
for file in $(ls ../../patches/ | grep -v patcha); do
|
||||||
echo "[GIT] apply" $file
|
echo "[GIT] apply" "$file"
|
||||||
git apply ../../patches/$file
|
git apply ../../patches/"$file"
|
||||||
git add -A
|
git add -A
|
||||||
git commit --no-gpg-sign -m "Patch $file"
|
git commit --no-gpg-sign -m "Patch $file"
|
||||||
done
|
done
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#![feature(
|
#![feature(
|
||||||
no_core, lang_items, intrinsics, unboxed_closures, type_ascription, extern_types,
|
no_core, lang_items, intrinsics, unboxed_closures, type_ascription, extern_types,
|
||||||
untagged_unions, decl_macro, rustc_attrs, transparent_unions, optin_builtin_traits,
|
untagged_unions, decl_macro, rustc_attrs, transparent_unions, auto_traits,
|
||||||
thread_local,
|
thread_local,
|
||||||
)]
|
)]
|
||||||
#![no_core]
|
#![no_core]
|
||||||
|
@ -53,6 +53,7 @@ fn main() {
|
|||||||
|
|
||||||
assert_eq!(0b0000000000000000000000000010000010000000000000000000000000000000_0000000000100000000000000000000000001000000000000100000000000000u128.leading_zeros(), 26);
|
assert_eq!(0b0000000000000000000000000010000010000000000000000000000000000000_0000000000100000000000000000000000001000000000000100000000000000u128.leading_zeros(), 26);
|
||||||
assert_eq!(0b0000000000000000000000000010000000000000000000000000000000000000_0000000000000000000000000000000000001000000000000000000010000000u128.trailing_zeros(), 7);
|
assert_eq!(0b0000000000000000000000000010000000000000000000000000000000000000_0000000000000000000000000000000000001000000000000000000010000000u128.trailing_zeros(), 7);
|
||||||
|
assert_eq!(core::intrinsics::saturating_sub(0, -170141183460469231731687303715884105728i128), 170141183460469231731687303715884105727i128);
|
||||||
|
|
||||||
let _d = 0i128.checked_div(2i128);
|
let _d = 0i128.checked_div(2i128);
|
||||||
let _d = 0u128.checked_div(2u128);
|
let _d = 0u128.checked_div(2u128);
|
||||||
|
@ -52,8 +52,8 @@ index 0475aeb..9558198 100644
|
|||||||
fn test_rotate() {
|
fn test_rotate() {
|
||||||
assert_eq!(A.rotate_left(6).rotate_right(2).rotate_right(4), A);
|
assert_eq!(A.rotate_left(6).rotate_right(2).rotate_right(4), A);
|
||||||
@@ -112,6 +113,7 @@ mod tests {
|
@@ -112,6 +113,7 @@ mod tests {
|
||||||
assert_eq!(B.rotate_left(64), B);
|
assert_eq!(B.rotate_left(128), B);
|
||||||
assert_eq!(C.rotate_left(64), C);
|
assert_eq!(C.rotate_left(128), C);
|
||||||
}
|
}
|
||||||
+ */
|
+ */
|
||||||
|
|
||||||
@ -72,8 +72,8 @@ index 04ed14f..a6e372e 100644
|
|||||||
fn test_rotate() {
|
fn test_rotate() {
|
||||||
assert_eq!(A.rotate_left(6).rotate_right(2).rotate_right(4), A);
|
assert_eq!(A.rotate_left(6).rotate_right(2).rotate_right(4), A);
|
||||||
@@ -76,6 +77,7 @@ mod tests {
|
@@ -76,6 +77,7 @@ mod tests {
|
||||||
assert_eq!(B.rotate_left(64), B);
|
assert_eq!(B.rotate_left(128), B);
|
||||||
assert_eq!(C.rotate_left(64), C);
|
assert_eq!(C.rotate_left(128), C);
|
||||||
}
|
}
|
||||||
+ */
|
+ */
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@ git checkout -- .
|
|||||||
git checkout 804a7a21b9e673a482797aa289a18ed480e4d813
|
git checkout 804a7a21b9e673a482797aa289a18ed480e4d813
|
||||||
|
|
||||||
# build with cg_llvm for perf comparison
|
# build with cg_llvm for perf comparison
|
||||||
|
unset CARGO_TARGET_DIR
|
||||||
cargo build
|
cargo build
|
||||||
mv target/debug/main raytracer_cg_llvm
|
mv target/debug/main raytracer_cg_llvm
|
||||||
popd
|
popd
|
||||||
|
@ -1 +1 @@
|
|||||||
nightly-2020-10-31
|
nightly-2020-11-27
|
||||||
|
@ -1,16 +1,16 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
dir=$(dirname "$0")
|
dir=$(dirname "$0")
|
||||||
source $dir/config.sh
|
source "$dir/config.sh"
|
||||||
|
|
||||||
# read nightly compiler from rust-toolchain file
|
# read nightly compiler from rust-toolchain file
|
||||||
TOOLCHAIN=$(cat $dir/rust-toolchain)
|
TOOLCHAIN=$(cat "$dir/rust-toolchain")
|
||||||
|
|
||||||
cmd=$1
|
cmd=$1
|
||||||
shift || true
|
shift || true
|
||||||
|
|
||||||
if [[ "$cmd" = "jit" ]]; then
|
if [[ "$cmd" = "jit" ]]; then
|
||||||
cargo +${TOOLCHAIN} rustc "$@" -- --jit
|
cargo "+${TOOLCHAIN}" rustc "$@" -- --jit
|
||||||
else
|
else
|
||||||
cargo +${TOOLCHAIN} $cmd "$@"
|
cargo "+${TOOLCHAIN}" "$cmd" "$@"
|
||||||
fi
|
fi
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
#!/usr/bin/env bash
|
# Note to people running shellcheck: this file should only be sourced, not executed directly.
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
unamestr=`uname`
|
unamestr=$(uname)
|
||||||
if [[ "$unamestr" == 'Linux' ]]; then
|
if [[ "$unamestr" == 'Linux' ]]; then
|
||||||
dylib_ext='so'
|
dylib_ext='so'
|
||||||
elif [[ "$unamestr" == 'Darwin' ]]; then
|
elif [[ "$unamestr" == 'Darwin' ]]; then
|
||||||
@ -40,19 +41,19 @@ echo
|
|||||||
export RUSTC_WRAPPER=
|
export RUSTC_WRAPPER=
|
||||||
fi
|
fi
|
||||||
|
|
||||||
dir=$(cd $(dirname "$BASH_SOURCE"); pwd)
|
dir=$(cd "$(dirname "${BASH_SOURCE[0]}")"; pwd)
|
||||||
|
|
||||||
export RUSTC=$dir"/cg_clif"
|
export RUSTC=$dir"/bin/cg_clif"
|
||||||
export RUSTFLAGS=$linker
|
export RUSTFLAGS=$linker" "$RUSTFLAGS
|
||||||
export RUSTDOCFLAGS=$linker' -Ztrim-diagnostic-paths=no -Cpanic=abort -Zpanic-abort-tests '\
|
export RUSTDOCFLAGS=$linker' -Cpanic=abort -Zpanic-abort-tests '\
|
||||||
'-Zcodegen-backend='$dir'/librustc_codegen_cranelift.'$dylib_ext' --sysroot '$dir'/sysroot'
|
'-Zcodegen-backend='$dir'/lib/librustc_codegen_cranelift.'$dylib_ext' --sysroot '$dir
|
||||||
|
|
||||||
# FIXME remove once the atomic shim is gone
|
# FIXME remove once the atomic shim is gone
|
||||||
if [[ `uname` == 'Darwin' ]]; then
|
if [[ $(uname) == 'Darwin' ]]; then
|
||||||
export RUSTFLAGS="$RUSTFLAGS -Clink-arg=-undefined -Clink-arg=dynamic_lookup"
|
export RUSTFLAGS="$RUSTFLAGS -Clink-arg=-undefined -Clink-arg=dynamic_lookup"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
export LD_LIBRARY_PATH="$dir:$(rustc --print sysroot)/lib:$dir/target/out:$dir/sysroot/lib/rustlib/"$TARGET_TRIPLE"/lib"
|
export LD_LIBRARY_PATH="$(rustc --print sysroot)/lib"
|
||||||
export DYLD_LIBRARY_PATH=$LD_LIBRARY_PATH
|
export DYLD_LIBRARY_PATH=$LD_LIBRARY_PATH
|
||||||
|
|
||||||
export CG_CLIF_DISPLAY_CG_TIME=1
|
export CG_CLIF_DISPLAY_CG_TIME=1
|
||||||
|
@ -7,13 +7,13 @@ case $1 in
|
|||||||
TOOLCHAIN=$(date +%Y-%m-%d)
|
TOOLCHAIN=$(date +%Y-%m-%d)
|
||||||
|
|
||||||
echo "=> Installing new nightly"
|
echo "=> Installing new nightly"
|
||||||
rustup toolchain install --profile minimal nightly-${TOOLCHAIN} # Sanity check to see if the nightly exists
|
rustup toolchain install --profile minimal "nightly-${TOOLCHAIN}" # Sanity check to see if the nightly exists
|
||||||
echo nightly-${TOOLCHAIN} > rust-toolchain
|
echo "nightly-${TOOLCHAIN}" > rust-toolchain
|
||||||
rustup component add rustfmt || true
|
rustup component add rustfmt || true
|
||||||
|
|
||||||
echo "=> Uninstalling all old nighlies"
|
echo "=> Uninstalling all old nighlies"
|
||||||
for nightly in $(rustup toolchain list | grep nightly | grep -v $TOOLCHAIN | grep -v nightly-x86_64); do
|
for nightly in $(rustup toolchain list | grep nightly | grep -v "$TOOLCHAIN" | grep -v nightly-x86_64); do
|
||||||
rustup toolchain uninstall $nightly
|
rustup toolchain uninstall "$nightly"
|
||||||
done
|
done
|
||||||
|
|
||||||
./clean_all.sh
|
./clean_all.sh
|
||||||
@ -29,11 +29,27 @@ case $1 in
|
|||||||
"push")
|
"push")
|
||||||
cg_clif=$(pwd)
|
cg_clif=$(pwd)
|
||||||
pushd ../rust
|
pushd ../rust
|
||||||
branch=update_cg_clif-$(date +%Y-%m-%d)
|
git pull origin master
|
||||||
git checkout -b $branch
|
branch=sync_cg_clif-$(date +%Y-%m-%d)
|
||||||
|
git checkout -b "$branch"
|
||||||
git subtree pull --prefix=compiler/rustc_codegen_cranelift/ https://github.com/bjorn3/rustc_codegen_cranelift.git master
|
git subtree pull --prefix=compiler/rustc_codegen_cranelift/ https://github.com/bjorn3/rustc_codegen_cranelift.git master
|
||||||
git push -u my $branch
|
git push -u my "$branch"
|
||||||
|
|
||||||
|
# immediately merge the merge commit into cg_clif to prevent merge conflicts when syncing
|
||||||
|
# from rust-lang/rust later
|
||||||
|
git subtree push --prefix=compiler/rustc_codegen_cranelift/ "$cg_clif" sync_from_rust
|
||||||
popd
|
popd
|
||||||
|
git merge sync_from_rust
|
||||||
|
;;
|
||||||
|
"pull")
|
||||||
|
cg_clif=$(pwd)
|
||||||
|
pushd ../rust
|
||||||
|
git pull origin master
|
||||||
|
rust_vers="$(git rev-parse HEAD)"
|
||||||
|
git subtree push --prefix=compiler/rustc_codegen_cranelift/ "$cg_clif" sync_from_rust
|
||||||
|
popd
|
||||||
|
git merge sync_from_rust -m "Sync from rust $rust_vers"
|
||||||
|
git branch -d sync_from_rust
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "Unknown command '$1'"
|
echo "Unknown command '$1'"
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
cd $(dirname "$0")/../
|
cd "$(dirname "$0")/../"
|
||||||
|
|
||||||
./build.sh
|
./build.sh
|
||||||
source build/config.sh
|
source build/config.sh
|
||||||
@ -11,7 +11,7 @@ git clone https://github.com/rust-lang/rust.git || true
|
|||||||
pushd rust
|
pushd rust
|
||||||
git fetch
|
git fetch
|
||||||
git checkout -- .
|
git checkout -- .
|
||||||
git checkout $(rustc -V | cut -d' ' -f3 | tr -d '(')
|
git checkout "$(rustc -V | cut -d' ' -f3 | tr -d '(')"
|
||||||
|
|
||||||
git apply - <<EOF
|
git apply - <<EOF
|
||||||
diff --git a/.gitmodules b/.gitmodules
|
diff --git a/.gitmodules b/.gitmodules
|
||||||
@ -48,7 +48,7 @@ cat > config.toml <<EOF
|
|||||||
ninja = false
|
ninja = false
|
||||||
|
|
||||||
[build]
|
[build]
|
||||||
rustc = "$(pwd)/../build/cg_clif"
|
rustc = "$(pwd)/../build/bin/cg_clif"
|
||||||
cargo = "$(rustup which cargo)"
|
cargo = "$(rustup which cargo)"
|
||||||
full-bootstrap = true
|
full-bootstrap = true
|
||||||
local-rebuild = true
|
local-rebuild = true
|
||||||
|
@ -4,63 +4,63 @@ set -e
|
|||||||
|
|
||||||
source build/config.sh
|
source build/config.sh
|
||||||
export CG_CLIF_INCR_CACHE_DISABLED=1
|
export CG_CLIF_INCR_CACHE_DISABLED=1
|
||||||
MY_RUSTC=$RUSTC" "$RUSTFLAGS" -L crate=target/out --out-dir target/out -Cdebuginfo=2"
|
MY_RUSTC="$RUSTC $RUSTFLAGS -L crate=target/out --out-dir target/out -Cdebuginfo=2"
|
||||||
|
|
||||||
function no_sysroot_tests() {
|
function no_sysroot_tests() {
|
||||||
echo "[BUILD] mini_core"
|
echo "[BUILD] mini_core"
|
||||||
$MY_RUSTC example/mini_core.rs --crate-name mini_core --crate-type lib,dylib --target $TARGET_TRIPLE
|
$MY_RUSTC example/mini_core.rs --crate-name mini_core --crate-type lib,dylib --target "$TARGET_TRIPLE"
|
||||||
|
|
||||||
echo "[BUILD] example"
|
echo "[BUILD] example"
|
||||||
$MY_RUSTC example/example.rs --crate-type lib --target $TARGET_TRIPLE
|
$MY_RUSTC example/example.rs --crate-type lib --target "$TARGET_TRIPLE"
|
||||||
|
|
||||||
if [[ "$JIT_SUPPORTED" = "1" ]]; then
|
if [[ "$JIT_SUPPORTED" = "1" ]]; then
|
||||||
echo "[JIT] mini_core_hello_world"
|
echo "[JIT] mini_core_hello_world"
|
||||||
CG_CLIF_JIT_ARGS="abc bcd" $MY_RUSTC --jit example/mini_core_hello_world.rs --cfg jit --target $HOST_TRIPLE
|
CG_CLIF_JIT_ARGS="abc bcd" $MY_RUSTC --jit example/mini_core_hello_world.rs --cfg jit --target "$HOST_TRIPLE"
|
||||||
else
|
else
|
||||||
echo "[JIT] mini_core_hello_world (skipped)"
|
echo "[JIT] mini_core_hello_world (skipped)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "[AOT] mini_core_hello_world"
|
echo "[AOT] mini_core_hello_world"
|
||||||
$MY_RUSTC example/mini_core_hello_world.rs --crate-name mini_core_hello_world --crate-type bin -g --target $TARGET_TRIPLE
|
$MY_RUSTC example/mini_core_hello_world.rs --crate-name mini_core_hello_world --crate-type bin -g --target "$TARGET_TRIPLE"
|
||||||
$RUN_WRAPPER ./target/out/mini_core_hello_world abc bcd
|
$RUN_WRAPPER ./target/out/mini_core_hello_world abc bcd
|
||||||
# (echo "break set -n main"; echo "run"; sleep 1; echo "si -c 10"; sleep 1; echo "frame variable") | lldb -- ./target/out/mini_core_hello_world abc bcd
|
# (echo "break set -n main"; echo "run"; sleep 1; echo "si -c 10"; sleep 1; echo "frame variable") | lldb -- ./target/out/mini_core_hello_world abc bcd
|
||||||
|
|
||||||
echo "[AOT] arbitrary_self_types_pointers_and_wrappers"
|
echo "[AOT] arbitrary_self_types_pointers_and_wrappers"
|
||||||
$MY_RUSTC example/arbitrary_self_types_pointers_and_wrappers.rs --crate-name arbitrary_self_types_pointers_and_wrappers --crate-type bin --target $TARGET_TRIPLE
|
$MY_RUSTC example/arbitrary_self_types_pointers_and_wrappers.rs --crate-name arbitrary_self_types_pointers_and_wrappers --crate-type bin --target "$TARGET_TRIPLE"
|
||||||
$RUN_WRAPPER ./target/out/arbitrary_self_types_pointers_and_wrappers
|
$RUN_WRAPPER ./target/out/arbitrary_self_types_pointers_and_wrappers
|
||||||
}
|
}
|
||||||
|
|
||||||
function base_sysroot_tests() {
|
function base_sysroot_tests() {
|
||||||
echo "[AOT] alloc_example"
|
echo "[AOT] alloc_example"
|
||||||
$MY_RUSTC example/alloc_example.rs --crate-type bin --target $TARGET_TRIPLE
|
$MY_RUSTC example/alloc_example.rs --crate-type bin --target "$TARGET_TRIPLE"
|
||||||
$RUN_WRAPPER ./target/out/alloc_example
|
$RUN_WRAPPER ./target/out/alloc_example
|
||||||
|
|
||||||
if [[ "$JIT_SUPPORTED" = "1" ]]; then
|
if [[ "$JIT_SUPPORTED" = "1" ]]; then
|
||||||
echo "[JIT] std_example"
|
echo "[JIT] std_example"
|
||||||
$MY_RUSTC --jit example/std_example.rs --target $HOST_TRIPLE
|
$MY_RUSTC --jit example/std_example.rs --target "$HOST_TRIPLE"
|
||||||
else
|
else
|
||||||
echo "[JIT] std_example (skipped)"
|
echo "[JIT] std_example (skipped)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "[AOT] dst_field_align"
|
echo "[AOT] dst_field_align"
|
||||||
# FIXME Re-add -Zmir-opt-level=2 once rust-lang/rust#67529 is fixed.
|
# FIXME Re-add -Zmir-opt-level=2 once rust-lang/rust#67529 is fixed.
|
||||||
$MY_RUSTC example/dst-field-align.rs --crate-name dst_field_align --crate-type bin --target $TARGET_TRIPLE
|
$MY_RUSTC example/dst-field-align.rs --crate-name dst_field_align --crate-type bin --target "$TARGET_TRIPLE"
|
||||||
$RUN_WRAPPER ./target/out/dst_field_align || (echo $?; false)
|
$RUN_WRAPPER ./target/out/dst_field_align || (echo $?; false)
|
||||||
|
|
||||||
echo "[AOT] std_example"
|
echo "[AOT] std_example"
|
||||||
$MY_RUSTC example/std_example.rs --crate-type bin --target $TARGET_TRIPLE
|
$MY_RUSTC example/std_example.rs --crate-type bin --target "$TARGET_TRIPLE"
|
||||||
$RUN_WRAPPER ./target/out/std_example arg
|
$RUN_WRAPPER ./target/out/std_example arg
|
||||||
|
|
||||||
echo "[AOT] subslice-patterns-const-eval"
|
echo "[AOT] subslice-patterns-const-eval"
|
||||||
$MY_RUSTC example/subslice-patterns-const-eval.rs --crate-type bin -Cpanic=abort --target $TARGET_TRIPLE
|
$MY_RUSTC example/subslice-patterns-const-eval.rs --crate-type bin -Cpanic=abort --target "$TARGET_TRIPLE"
|
||||||
$RUN_WRAPPER ./target/out/subslice-patterns-const-eval
|
$RUN_WRAPPER ./target/out/subslice-patterns-const-eval
|
||||||
|
|
||||||
echo "[AOT] track-caller-attribute"
|
echo "[AOT] track-caller-attribute"
|
||||||
$MY_RUSTC example/track-caller-attribute.rs --crate-type bin -Cpanic=abort --target $TARGET_TRIPLE
|
$MY_RUSTC example/track-caller-attribute.rs --crate-type bin -Cpanic=abort --target "$TARGET_TRIPLE"
|
||||||
$RUN_WRAPPER ./target/out/track-caller-attribute
|
$RUN_WRAPPER ./target/out/track-caller-attribute
|
||||||
|
|
||||||
echo "[AOT] mod_bench"
|
echo "[AOT] mod_bench"
|
||||||
$MY_RUSTC example/mod_bench.rs --crate-type bin --target $TARGET_TRIPLE
|
$MY_RUSTC example/mod_bench.rs --crate-type bin --target "$TARGET_TRIPLE"
|
||||||
$RUN_WRAPPER ./target/out/mod_bench
|
$RUN_WRAPPER ./target/out/mod_bench
|
||||||
|
|
||||||
pushd rand
|
pushd rand
|
||||||
@ -73,13 +73,13 @@ function extended_sysroot_tests() {
|
|||||||
pushd simple-raytracer
|
pushd simple-raytracer
|
||||||
if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then
|
if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then
|
||||||
echo "[BENCH COMPILE] ebobby/simple-raytracer"
|
echo "[BENCH COMPILE] ebobby/simple-raytracer"
|
||||||
hyperfine --runs ${RUN_RUNS:-10} --warmup 1 --prepare "cargo clean" \
|
hyperfine --runs "${RUN_RUNS:-10}" --warmup 1 --prepare "cargo clean" \
|
||||||
"RUSTC=rustc RUSTFLAGS='' cargo build" \
|
"RUSTC=rustc RUSTFLAGS='' cargo build" \
|
||||||
"../build/cargo.sh build"
|
"../build/cargo.sh build"
|
||||||
|
|
||||||
echo "[BENCH RUN] ebobby/simple-raytracer"
|
echo "[BENCH RUN] ebobby/simple-raytracer"
|
||||||
cp ./target/debug/main ./raytracer_cg_clif
|
cp ./target/debug/main ./raytracer_cg_clif
|
||||||
hyperfine --runs ${RUN_RUNS:-10} ./raytracer_cg_llvm ./raytracer_cg_clif
|
hyperfine --runs "${RUN_RUNS:-10}" ./raytracer_cg_llvm ./raytracer_cg_clif
|
||||||
else
|
else
|
||||||
echo "[BENCH COMPILE] ebobby/simple-raytracer (skipped)"
|
echo "[BENCH COMPILE] ebobby/simple-raytracer (skipped)"
|
||||||
echo "[COMPILE] ebobby/simple-raytracer"
|
echo "[COMPILE] ebobby/simple-raytracer"
|
||||||
|
@ -64,7 +64,7 @@ pub(crate) fn fn_sig_for_fn_abi<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx
|
|||||||
ty::Generator(_, substs, _) => {
|
ty::Generator(_, substs, _) => {
|
||||||
let sig = substs.as_generator().poly_sig();
|
let sig = substs.as_generator().poly_sig();
|
||||||
|
|
||||||
let env_region = ty::ReLateBound(ty::INNERMOST, ty::BrEnv);
|
let env_region = ty::ReLateBound(ty::INNERMOST, ty::BoundRegion { kind: ty::BrEnv });
|
||||||
let env_ty = tcx.mk_mut_ref(tcx.mk_region(env_region), ty);
|
let env_ty = tcx.mk_mut_ref(tcx.mk_region(env_region), ty);
|
||||||
|
|
||||||
let pin_did = tcx.require_lang_item(rustc_hir::LangItem::Pin, None);
|
let pin_did = tcx.require_lang_item(rustc_hir::LangItem::Pin, None);
|
||||||
@ -214,10 +214,8 @@ pub(crate) fn get_function_name_and_sig<'tcx>(
|
|||||||
support_vararg: bool,
|
support_vararg: bool,
|
||||||
) -> (String, Signature) {
|
) -> (String, Signature) {
|
||||||
assert!(!inst.substs.needs_infer());
|
assert!(!inst.substs.needs_infer());
|
||||||
let fn_sig = tcx.normalize_erasing_late_bound_regions(
|
let fn_sig = tcx
|
||||||
ParamEnv::reveal_all(),
|
.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), fn_sig_for_fn_abi(tcx, inst));
|
||||||
&fn_sig_for_fn_abi(tcx, inst),
|
|
||||||
);
|
|
||||||
if fn_sig.c_variadic && !support_vararg {
|
if fn_sig.c_variadic && !support_vararg {
|
||||||
tcx.sess.span_fatal(
|
tcx.sess.span_fatal(
|
||||||
tcx.def_span(inst.def_id()),
|
tcx.def_span(inst.def_id()),
|
||||||
@ -372,7 +370,7 @@ pub(crate) fn codegen_fn_prelude<'tcx>(
|
|||||||
.mir
|
.mir
|
||||||
.args_iter()
|
.args_iter()
|
||||||
.map(|local| {
|
.map(|local| {
|
||||||
let arg_ty = fx.monomorphize(&fx.mir.local_decls[local].ty);
|
let arg_ty = fx.monomorphize(fx.mir.local_decls[local].ty);
|
||||||
|
|
||||||
// Adapted from https://github.com/rust-lang/rust/blob/145155dc96757002c7b2e9de8489416e2fdbbd57/src/librustc_codegen_llvm/mir/mod.rs#L442-L482
|
// Adapted from https://github.com/rust-lang/rust/blob/145155dc96757002c7b2e9de8489416e2fdbbd57/src/librustc_codegen_llvm/mir/mod.rs#L442-L482
|
||||||
if Some(local) == fx.mir.spread_arg {
|
if Some(local) == fx.mir.spread_arg {
|
||||||
@ -470,7 +468,7 @@ pub(crate) fn codegen_fn_prelude<'tcx>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
for local in fx.mir.vars_and_temps_iter() {
|
for local in fx.mir.vars_and_temps_iter() {
|
||||||
let ty = fx.monomorphize(&fx.mir.local_decls[local].ty);
|
let ty = fx.monomorphize(fx.mir.local_decls[local].ty);
|
||||||
let layout = fx.layout_of(ty);
|
let layout = fx.layout_of(ty);
|
||||||
|
|
||||||
let is_ssa = ssa_analyzed[local] == crate::analyze::SsaKind::Ssa;
|
let is_ssa = ssa_analyzed[local] == crate::analyze::SsaKind::Ssa;
|
||||||
@ -492,10 +490,10 @@ pub(crate) fn codegen_terminator_call<'tcx>(
|
|||||||
args: &[Operand<'tcx>],
|
args: &[Operand<'tcx>],
|
||||||
destination: Option<(Place<'tcx>, BasicBlock)>,
|
destination: Option<(Place<'tcx>, BasicBlock)>,
|
||||||
) {
|
) {
|
||||||
let fn_ty = fx.monomorphize(&func.ty(fx.mir, fx.tcx));
|
let fn_ty = fx.monomorphize(func.ty(fx.mir, fx.tcx));
|
||||||
let fn_sig = fx
|
let fn_sig = fx
|
||||||
.tcx
|
.tcx
|
||||||
.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), &fn_ty.fn_sig(fx.tcx));
|
.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), fn_ty.fn_sig(fx.tcx));
|
||||||
|
|
||||||
let destination = destination.map(|(place, bb)| (codegen_place(fx, place), bb));
|
let destination = destination.map(|(place, bb)| (codegen_place(fx, place), bb));
|
||||||
|
|
||||||
@ -711,7 +709,7 @@ pub(crate) fn codegen_drop<'tcx>(
|
|||||||
let drop_fn_ty = drop_fn.ty(fx.tcx, ParamEnv::reveal_all());
|
let drop_fn_ty = drop_fn.ty(fx.tcx, ParamEnv::reveal_all());
|
||||||
let fn_sig = fx.tcx.normalize_erasing_late_bound_regions(
|
let fn_sig = fx.tcx.normalize_erasing_late_bound_regions(
|
||||||
ParamEnv::reveal_all(),
|
ParamEnv::reveal_all(),
|
||||||
&drop_fn_ty.fn_sig(fx.tcx),
|
drop_fn_ty.fn_sig(fx.tcx),
|
||||||
);
|
);
|
||||||
assert_eq!(fn_sig.output(), fx.tcx.mk_unit());
|
assert_eq!(fn_sig.output(), fx.tcx.mk_unit());
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ pub(crate) fn analyze(fx: &FunctionCx<'_, '_, impl Module>) -> IndexVec<Local, S
|
|||||||
.local_decls
|
.local_decls
|
||||||
.iter()
|
.iter()
|
||||||
.map(|local_decl| {
|
.map(|local_decl| {
|
||||||
let ty = fx.monomorphize(&local_decl.ty);
|
let ty = fx.monomorphize(local_decl.ty);
|
||||||
if fx.clif_type(ty).is_some() || fx.clif_pair_type(ty).is_some() {
|
if fx.clif_type(ty).is_some() || fx.clif_pair_type(ty).is_some() {
|
||||||
SsaKind::Ssa
|
SsaKind::Ssa
|
||||||
} else {
|
} else {
|
||||||
|
@ -8,7 +8,7 @@ use rustc_codegen_ssa::back::archive::{find_library, ArchiveBuilder};
|
|||||||
use rustc_codegen_ssa::METADATA_FILENAME;
|
use rustc_codegen_ssa::METADATA_FILENAME;
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
|
|
||||||
use object::{Object, SymbolKind};
|
use object::{Object, ObjectSymbol, SymbolKind};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum ArchiveEntry {
|
enum ArchiveEntry {
|
||||||
@ -184,7 +184,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
|
|||||||
entry_name.as_bytes().to_vec(),
|
entry_name.as_bytes().to_vec(),
|
||||||
object
|
object
|
||||||
.symbols()
|
.symbols()
|
||||||
.filter_map(|(_index, symbol)| {
|
.filter_map(|symbol| {
|
||||||
if symbol.is_undefined()
|
if symbol.is_undefined()
|
||||||
|| symbol.is_local()
|
|| symbol.is_local()
|
||||||
|| symbol.kind() != SymbolKind::Data
|
|| symbol.kind() != SymbolKind::Data
|
||||||
@ -193,7 +193,7 @@ impl<'a> ArchiveBuilder<'a> for ArArchiveBuilder<'a> {
|
|||||||
{
|
{
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
symbol.name().map(|name| name.as_bytes().to_vec())
|
symbol.name().map(|name| name.as_bytes().to_vec()).ok()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
|
@ -7,8 +7,7 @@ use crate::prelude::*;
|
|||||||
|
|
||||||
#[cfg(all(feature = "jit", unix))]
|
#[cfg(all(feature = "jit", unix))]
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
static mut __cg_clif_global_atomic_mutex: libc::pthread_mutex_t =
|
static mut __cg_clif_global_atomic_mutex: libc::pthread_mutex_t = libc::PTHREAD_MUTEX_INITIALIZER;
|
||||||
libc::PTHREAD_MUTEX_INITIALIZER;
|
|
||||||
|
|
||||||
pub(crate) fn init_global_lock(
|
pub(crate) fn init_global_lock(
|
||||||
module: &mut impl Module,
|
module: &mut impl Module,
|
||||||
|
@ -12,6 +12,10 @@ pub(crate) fn codegen_fn<'tcx>(
|
|||||||
) {
|
) {
|
||||||
let tcx = cx.tcx;
|
let tcx = cx.tcx;
|
||||||
|
|
||||||
|
let _inst_guard =
|
||||||
|
crate::PrintOnPanic(|| format!("{:?} {}", instance, tcx.symbol_name(instance).name));
|
||||||
|
debug_assert!(!instance.substs.needs_infer());
|
||||||
|
|
||||||
let mir = tcx.instance_mir(instance.def);
|
let mir = tcx.instance_mir(instance.def);
|
||||||
|
|
||||||
// Declare function
|
// Declare function
|
||||||
@ -445,43 +449,43 @@ fn codegen_stmt<'tcx>(
|
|||||||
StatementKind::Assign(to_place_and_rval) => {
|
StatementKind::Assign(to_place_and_rval) => {
|
||||||
let lval = codegen_place(fx, to_place_and_rval.0);
|
let lval = codegen_place(fx, to_place_and_rval.0);
|
||||||
let dest_layout = lval.layout();
|
let dest_layout = lval.layout();
|
||||||
match &to_place_and_rval.1 {
|
match to_place_and_rval.1 {
|
||||||
Rvalue::Use(operand) => {
|
Rvalue::Use(ref operand) => {
|
||||||
let val = codegen_operand(fx, operand);
|
let val = codegen_operand(fx, operand);
|
||||||
lval.write_cvalue(fx, val);
|
lval.write_cvalue(fx, val);
|
||||||
}
|
}
|
||||||
Rvalue::Ref(_, _, place) | Rvalue::AddressOf(_, place) => {
|
Rvalue::Ref(_, _, place) | Rvalue::AddressOf(_, place) => {
|
||||||
let place = codegen_place(fx, *place);
|
let place = codegen_place(fx, place);
|
||||||
let ref_ = place.place_ref(fx, lval.layout());
|
let ref_ = place.place_ref(fx, lval.layout());
|
||||||
lval.write_cvalue(fx, ref_);
|
lval.write_cvalue(fx, ref_);
|
||||||
}
|
}
|
||||||
Rvalue::ThreadLocalRef(def_id) => {
|
Rvalue::ThreadLocalRef(def_id) => {
|
||||||
let val = crate::constant::codegen_tls_ref(fx, *def_id, lval.layout());
|
let val = crate::constant::codegen_tls_ref(fx, def_id, lval.layout());
|
||||||
lval.write_cvalue(fx, val);
|
lval.write_cvalue(fx, val);
|
||||||
}
|
}
|
||||||
Rvalue::BinaryOp(bin_op, lhs, rhs) => {
|
Rvalue::BinaryOp(bin_op, ref lhs, ref rhs) => {
|
||||||
let lhs = codegen_operand(fx, lhs);
|
let lhs = codegen_operand(fx, lhs);
|
||||||
let rhs = codegen_operand(fx, rhs);
|
let rhs = codegen_operand(fx, rhs);
|
||||||
|
|
||||||
let res = crate::num::codegen_binop(fx, *bin_op, lhs, rhs);
|
let res = crate::num::codegen_binop(fx, bin_op, lhs, rhs);
|
||||||
lval.write_cvalue(fx, res);
|
lval.write_cvalue(fx, res);
|
||||||
}
|
}
|
||||||
Rvalue::CheckedBinaryOp(bin_op, lhs, rhs) => {
|
Rvalue::CheckedBinaryOp(bin_op, ref lhs, ref rhs) => {
|
||||||
let lhs = codegen_operand(fx, lhs);
|
let lhs = codegen_operand(fx, lhs);
|
||||||
let rhs = codegen_operand(fx, rhs);
|
let rhs = codegen_operand(fx, rhs);
|
||||||
|
|
||||||
let res = if !fx.tcx.sess.overflow_checks() {
|
let res = if !fx.tcx.sess.overflow_checks() {
|
||||||
let val =
|
let val =
|
||||||
crate::num::codegen_int_binop(fx, *bin_op, lhs, rhs).load_scalar(fx);
|
crate::num::codegen_int_binop(fx, bin_op, lhs, rhs).load_scalar(fx);
|
||||||
let is_overflow = fx.bcx.ins().iconst(types::I8, 0);
|
let is_overflow = fx.bcx.ins().iconst(types::I8, 0);
|
||||||
CValue::by_val_pair(val, is_overflow, lval.layout())
|
CValue::by_val_pair(val, is_overflow, lval.layout())
|
||||||
} else {
|
} else {
|
||||||
crate::num::codegen_checked_int_binop(fx, *bin_op, lhs, rhs)
|
crate::num::codegen_checked_int_binop(fx, bin_op, lhs, rhs)
|
||||||
};
|
};
|
||||||
|
|
||||||
lval.write_cvalue(fx, res);
|
lval.write_cvalue(fx, res);
|
||||||
}
|
}
|
||||||
Rvalue::UnaryOp(un_op, operand) => {
|
Rvalue::UnaryOp(un_op, ref operand) => {
|
||||||
let operand = codegen_operand(fx, operand);
|
let operand = codegen_operand(fx, operand);
|
||||||
let layout = operand.layout();
|
let layout = operand.layout();
|
||||||
let val = operand.load_scalar(fx);
|
let val = operand.load_scalar(fx);
|
||||||
@ -499,7 +503,8 @@ fn codegen_stmt<'tcx>(
|
|||||||
UnOp::Neg => match layout.ty.kind() {
|
UnOp::Neg => match layout.ty.kind() {
|
||||||
ty::Int(IntTy::I128) => {
|
ty::Int(IntTy::I128) => {
|
||||||
// FIXME remove this case once ineg.i128 works
|
// FIXME remove this case once ineg.i128 works
|
||||||
let zero = CValue::const_val(fx, layout, ty::ScalarInt::null(layout.size));
|
let zero =
|
||||||
|
CValue::const_val(fx, layout, ty::ScalarInt::null(layout.size));
|
||||||
crate::num::codegen_int_binop(fx, BinOp::Sub, zero, operand)
|
crate::num::codegen_int_binop(fx, BinOp::Sub, zero, operand)
|
||||||
}
|
}
|
||||||
ty::Int(_) => CValue::by_val(fx.bcx.ins().ineg(val), layout),
|
ty::Int(_) => CValue::by_val(fx.bcx.ins().ineg(val), layout),
|
||||||
@ -509,8 +514,12 @@ fn codegen_stmt<'tcx>(
|
|||||||
};
|
};
|
||||||
lval.write_cvalue(fx, res);
|
lval.write_cvalue(fx, res);
|
||||||
}
|
}
|
||||||
Rvalue::Cast(CastKind::Pointer(PointerCast::ReifyFnPointer), operand, to_ty) => {
|
Rvalue::Cast(
|
||||||
let from_ty = fx.monomorphize(&operand.ty(&fx.mir.local_decls, fx.tcx));
|
CastKind::Pointer(PointerCast::ReifyFnPointer),
|
||||||
|
ref operand,
|
||||||
|
to_ty,
|
||||||
|
) => {
|
||||||
|
let from_ty = fx.monomorphize(operand.ty(&fx.mir.local_decls, fx.tcx));
|
||||||
let to_layout = fx.layout_of(fx.monomorphize(to_ty));
|
let to_layout = fx.layout_of(fx.monomorphize(to_ty));
|
||||||
match *from_ty.kind() {
|
match *from_ty.kind() {
|
||||||
ty::FnDef(def_id, substs) => {
|
ty::FnDef(def_id, substs) => {
|
||||||
@ -530,14 +539,26 @@ fn codegen_stmt<'tcx>(
|
|||||||
_ => bug!("Trying to ReifyFnPointer on non FnDef {:?}", from_ty),
|
_ => bug!("Trying to ReifyFnPointer on non FnDef {:?}", from_ty),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Rvalue::Cast(CastKind::Pointer(PointerCast::UnsafeFnPointer), operand, to_ty)
|
Rvalue::Cast(
|
||||||
| Rvalue::Cast(CastKind::Pointer(PointerCast::MutToConstPointer), operand, to_ty)
|
CastKind::Pointer(PointerCast::UnsafeFnPointer),
|
||||||
| Rvalue::Cast(CastKind::Pointer(PointerCast::ArrayToPointer), operand, to_ty) => {
|
ref operand,
|
||||||
|
to_ty,
|
||||||
|
)
|
||||||
|
| Rvalue::Cast(
|
||||||
|
CastKind::Pointer(PointerCast::MutToConstPointer),
|
||||||
|
ref operand,
|
||||||
|
to_ty,
|
||||||
|
)
|
||||||
|
| Rvalue::Cast(
|
||||||
|
CastKind::Pointer(PointerCast::ArrayToPointer),
|
||||||
|
ref operand,
|
||||||
|
to_ty,
|
||||||
|
) => {
|
||||||
let to_layout = fx.layout_of(fx.monomorphize(to_ty));
|
let to_layout = fx.layout_of(fx.monomorphize(to_ty));
|
||||||
let operand = codegen_operand(fx, operand);
|
let operand = codegen_operand(fx, operand);
|
||||||
lval.write_cvalue(fx, operand.cast_pointer_to(to_layout));
|
lval.write_cvalue(fx, operand.cast_pointer_to(to_layout));
|
||||||
}
|
}
|
||||||
Rvalue::Cast(CastKind::Misc, operand, to_ty) => {
|
Rvalue::Cast(CastKind::Misc, ref operand, to_ty) => {
|
||||||
let operand = codegen_operand(fx, operand);
|
let operand = codegen_operand(fx, operand);
|
||||||
let from_ty = operand.layout().ty;
|
let from_ty = operand.layout().ty;
|
||||||
let to_ty = fx.monomorphize(to_ty);
|
let to_ty = fx.monomorphize(to_ty);
|
||||||
@ -577,12 +598,12 @@ fn codegen_stmt<'tcx>(
|
|||||||
|
|
||||||
use rustc_target::abi::{Int, TagEncoding, Variants};
|
use rustc_target::abi::{Int, TagEncoding, Variants};
|
||||||
|
|
||||||
match &operand.layout().variants {
|
match operand.layout().variants {
|
||||||
Variants::Single { index } => {
|
Variants::Single { index } => {
|
||||||
let discr = operand
|
let discr = operand
|
||||||
.layout()
|
.layout()
|
||||||
.ty
|
.ty
|
||||||
.discriminant_for_variant(fx.tcx, *index)
|
.discriminant_for_variant(fx.tcx, index)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let discr = if discr.ty.is_signed() {
|
let discr = if discr.ty.is_signed() {
|
||||||
fx.layout_of(discr.ty).size.sign_extend(discr.val)
|
fx.layout_of(discr.ty).size.sign_extend(discr.val)
|
||||||
@ -595,7 +616,7 @@ fn codegen_stmt<'tcx>(
|
|||||||
lval.write_cvalue(fx, discr);
|
lval.write_cvalue(fx, discr);
|
||||||
}
|
}
|
||||||
Variants::Multiple {
|
Variants::Multiple {
|
||||||
tag,
|
ref tag,
|
||||||
tag_field,
|
tag_field,
|
||||||
tag_encoding: TagEncoding::Direct,
|
tag_encoding: TagEncoding::Direct,
|
||||||
variants: _,
|
variants: _,
|
||||||
@ -604,7 +625,7 @@ fn codegen_stmt<'tcx>(
|
|||||||
|
|
||||||
// Read the tag/niche-encoded discriminant from memory.
|
// Read the tag/niche-encoded discriminant from memory.
|
||||||
let encoded_discr =
|
let encoded_discr =
|
||||||
operand.value_field(fx, mir::Field::new(*tag_field));
|
operand.value_field(fx, mir::Field::new(tag_field));
|
||||||
let encoded_discr = encoded_discr.load_scalar(fx);
|
let encoded_discr = encoded_discr.load_scalar(fx);
|
||||||
|
|
||||||
// Decode the discriminant (specifically if it's niche-encoded).
|
// Decode the discriminant (specifically if it's niche-encoded).
|
||||||
@ -634,7 +655,7 @@ fn codegen_stmt<'tcx>(
|
|||||||
}
|
}
|
||||||
Rvalue::Cast(
|
Rvalue::Cast(
|
||||||
CastKind::Pointer(PointerCast::ClosureFnPointer(_)),
|
CastKind::Pointer(PointerCast::ClosureFnPointer(_)),
|
||||||
operand,
|
ref operand,
|
||||||
_to_ty,
|
_to_ty,
|
||||||
) => {
|
) => {
|
||||||
let operand = codegen_operand(fx, operand);
|
let operand = codegen_operand(fx, operand);
|
||||||
@ -654,18 +675,18 @@ fn codegen_stmt<'tcx>(
|
|||||||
_ => bug!("{} cannot be cast to a fn ptr", operand.layout().ty),
|
_ => bug!("{} cannot be cast to a fn ptr", operand.layout().ty),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Rvalue::Cast(CastKind::Pointer(PointerCast::Unsize), operand, _to_ty) => {
|
Rvalue::Cast(CastKind::Pointer(PointerCast::Unsize), ref operand, _to_ty) => {
|
||||||
let operand = codegen_operand(fx, operand);
|
let operand = codegen_operand(fx, operand);
|
||||||
operand.unsize_value(fx, lval);
|
operand.unsize_value(fx, lval);
|
||||||
}
|
}
|
||||||
Rvalue::Discriminant(place) => {
|
Rvalue::Discriminant(place) => {
|
||||||
let place = codegen_place(fx, *place);
|
let place = codegen_place(fx, place);
|
||||||
let value = place.to_cvalue(fx);
|
let value = place.to_cvalue(fx);
|
||||||
let discr =
|
let discr =
|
||||||
crate::discriminant::codegen_get_discriminant(fx, value, dest_layout);
|
crate::discriminant::codegen_get_discriminant(fx, value, dest_layout);
|
||||||
lval.write_cvalue(fx, discr);
|
lval.write_cvalue(fx, discr);
|
||||||
}
|
}
|
||||||
Rvalue::Repeat(operand, times) => {
|
Rvalue::Repeat(ref operand, times) => {
|
||||||
let operand = codegen_operand(fx, operand);
|
let operand = codegen_operand(fx, operand);
|
||||||
let times = fx
|
let times = fx
|
||||||
.monomorphize(times)
|
.monomorphize(times)
|
||||||
@ -704,7 +725,7 @@ fn codegen_stmt<'tcx>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Rvalue::Len(place) => {
|
Rvalue::Len(place) => {
|
||||||
let place = codegen_place(fx, *place);
|
let place = codegen_place(fx, place);
|
||||||
let usize_layout = fx.layout_of(fx.tcx.types.usize);
|
let usize_layout = fx.layout_of(fx.tcx.types.usize);
|
||||||
let len = codegen_array_len(fx, place);
|
let len = codegen_array_len(fx, place);
|
||||||
lval.write_cvalue(fx, CValue::by_val(len, usize_layout));
|
lval.write_cvalue(fx, CValue::by_val(len, usize_layout));
|
||||||
@ -749,7 +770,7 @@ fn codegen_stmt<'tcx>(
|
|||||||
CValue::const_val(fx, fx.layout_of(fx.tcx.types.usize), ty_size.into());
|
CValue::const_val(fx, fx.layout_of(fx.tcx.types.usize), ty_size.into());
|
||||||
lval.write_cvalue(fx, val);
|
lval.write_cvalue(fx, val);
|
||||||
}
|
}
|
||||||
Rvalue::Aggregate(kind, operands) => match **kind {
|
Rvalue::Aggregate(ref kind, ref operands) => match kind.as_ref() {
|
||||||
AggregateKind::Array(_ty) => {
|
AggregateKind::Array(_ty) => {
|
||||||
for (i, operand) in operands.iter().enumerate() {
|
for (i, operand) in operands.iter().enumerate() {
|
||||||
let operand = codegen_operand(fx, operand);
|
let operand = codegen_operand(fx, operand);
|
||||||
@ -877,8 +898,7 @@ fn codegen_array_len<'tcx>(
|
|||||||
match *place.layout().ty.kind() {
|
match *place.layout().ty.kind() {
|
||||||
ty::Array(_elem_ty, len) => {
|
ty::Array(_elem_ty, len) => {
|
||||||
let len = fx
|
let len = fx
|
||||||
.monomorphize(&len)
|
.monomorphize(len)
|
||||||
.eval(fx.tcx, ParamEnv::reveal_all())
|
|
||||||
.eval_usize(fx.tcx, ParamEnv::reveal_all()) as i64;
|
.eval_usize(fx.tcx, ParamEnv::reveal_all()) as i64;
|
||||||
fx.bcx.ins().iconst(fx.pointer_type, len)
|
fx.bcx.ins().iconst(fx.pointer_type, len)
|
||||||
}
|
}
|
||||||
|
@ -26,15 +26,15 @@ impl rustc_driver::Callbacks for CraneliftPassesCallbacks {
|
|||||||
|
|
||||||
config.opts.cg.panic = Some(PanicStrategy::Abort);
|
config.opts.cg.panic = Some(PanicStrategy::Abort);
|
||||||
config.opts.debugging_opts.panic_abort_tests = true;
|
config.opts.debugging_opts.panic_abort_tests = true;
|
||||||
config.opts.maybe_sysroot = Some(
|
config.opts.maybe_sysroot = Some(config.opts.maybe_sysroot.clone().unwrap_or_else(|| {
|
||||||
config.opts.maybe_sysroot.clone().unwrap_or_else(
|
std::env::current_exe()
|
||||||
|| std::env::current_exe()
|
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.parent()
|
.parent()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.join("sysroot"),
|
.parent()
|
||||||
),
|
.unwrap()
|
||||||
);
|
.to_owned()
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,7 +233,7 @@ pub(crate) fn type_min_max_value(
|
|||||||
let min_msb = bcx.ins().iconst(types::I64, (min >> 64) as u64 as i64);
|
let min_msb = bcx.ins().iconst(types::I64, (min >> 64) as u64 as i64);
|
||||||
let min = bcx.ins().iconcat(min_lsb, min_msb);
|
let min = bcx.ins().iconcat(min_lsb, min_msb);
|
||||||
|
|
||||||
let max = i128::MIN as u128;
|
let max = i128::MAX as u128;
|
||||||
let max_lsb = bcx.ins().iconst(types::I64, max as u64 as i64);
|
let max_lsb = bcx.ins().iconst(types::I64, max as u64 as i64);
|
||||||
let max_msb = bcx.ins().iconst(types::I64, (max >> 64) as u64 as i64);
|
let max_msb = bcx.ins().iconst(types::I64, (max >> 64) as u64 as i64);
|
||||||
let max = bcx.ins().iconcat(max_lsb, max_msb);
|
let max = bcx.ins().iconcat(max_lsb, max_msb);
|
||||||
@ -357,14 +357,14 @@ impl<'tcx, M: Module> HasTargetSpec for FunctionCx<'_, 'tcx, M> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx, M: Module> FunctionCx<'_, 'tcx, M> {
|
impl<'tcx, M: Module> FunctionCx<'_, 'tcx, M> {
|
||||||
pub(crate) fn monomorphize<T>(&self, value: &T) -> T
|
pub(crate) fn monomorphize<T>(&self, value: T) -> T
|
||||||
where
|
where
|
||||||
T: TypeFoldable<'tcx> + Copy,
|
T: TypeFoldable<'tcx> + Copy,
|
||||||
{
|
{
|
||||||
self.instance.subst_mir_and_normalize_erasing_regions(
|
self.instance.subst_mir_and_normalize_erasing_regions(
|
||||||
self.tcx,
|
self.tcx,
|
||||||
ty::ParamEnv::reveal_all(),
|
ty::ParamEnv::reveal_all(),
|
||||||
value
|
value,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ impl ConstantCx {
|
|||||||
|
|
||||||
pub(crate) fn check_constants(fx: &mut FunctionCx<'_, '_, impl Module>) {
|
pub(crate) fn check_constants(fx: &mut FunctionCx<'_, '_, impl Module>) {
|
||||||
for constant in &fx.mir.required_consts {
|
for constant in &fx.mir.required_consts {
|
||||||
let const_ = fx.monomorphize(&constant.literal);
|
let const_ = fx.monomorphize(constant.literal);
|
||||||
match const_.val {
|
match const_.val {
|
||||||
ConstKind::Value(_) => {}
|
ConstKind::Value(_) => {}
|
||||||
ConstKind::Unevaluated(def, ref substs, promoted) => {
|
ConstKind::Unevaluated(def, ref substs, promoted) => {
|
||||||
@ -110,7 +110,7 @@ pub(crate) fn codegen_constant<'tcx>(
|
|||||||
fx: &mut FunctionCx<'_, 'tcx, impl Module>,
|
fx: &mut FunctionCx<'_, 'tcx, impl Module>,
|
||||||
constant: &Constant<'tcx>,
|
constant: &Constant<'tcx>,
|
||||||
) -> CValue<'tcx> {
|
) -> CValue<'tcx> {
|
||||||
let const_ = fx.monomorphize(&constant.literal);
|
let const_ = fx.monomorphize(constant.literal);
|
||||||
let const_val = match const_.val {
|
let const_val = match const_.val {
|
||||||
ConstKind::Value(const_val) => const_val,
|
ConstKind::Value(const_val) => const_val,
|
||||||
ConstKind::Unevaluated(def, ref substs, promoted) if fx.tcx.is_static(def.did) => {
|
ConstKind::Unevaluated(def, ref substs, promoted) if fx.tcx.is_static(def.did) => {
|
||||||
@ -163,10 +163,7 @@ pub(crate) fn codegen_const_value<'tcx>(
|
|||||||
assert!(!layout.is_unsized(), "sized const value");
|
assert!(!layout.is_unsized(), "sized const value");
|
||||||
|
|
||||||
if layout.is_zst() {
|
if layout.is_zst() {
|
||||||
return CValue::by_ref(
|
return CValue::by_ref(crate::Pointer::dangling(layout.align.pref), layout);
|
||||||
crate::Pointer::dangling(layout.align.pref),
|
|
||||||
layout,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
match const_val {
|
match const_val {
|
||||||
@ -186,9 +183,7 @@ pub(crate) fn codegen_const_value<'tcx>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
match x {
|
match x {
|
||||||
Scalar::Int(int) => {
|
Scalar::Int(int) => CValue::const_val(fx, layout, int),
|
||||||
CValue::const_val(fx, layout, int)
|
|
||||||
}
|
|
||||||
Scalar::Ptr(ptr) => {
|
Scalar::Ptr(ptr) => {
|
||||||
let alloc_kind = fx.tcx.get_global_alloc(ptr.alloc_id);
|
let alloc_kind = fx.tcx.get_global_alloc(ptr.alloc_id);
|
||||||
let base_addr = match alloc_kind {
|
let base_addr = match alloc_kind {
|
||||||
@ -466,7 +461,7 @@ pub(crate) fn mir_operand_get_const_val<'tcx>(
|
|||||||
match operand {
|
match operand {
|
||||||
Operand::Copy(_) | Operand::Move(_) => None,
|
Operand::Copy(_) | Operand::Move(_) => None,
|
||||||
Operand::Constant(const_) => Some(
|
Operand::Constant(const_) => Some(
|
||||||
fx.monomorphize(&const_.literal)
|
fx.monomorphize(const_.literal)
|
||||||
.eval(fx.tcx, ParamEnv::reveal_all()),
|
.eval(fx.tcx, ParamEnv::reveal_all()),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,7 @@ impl WriterRelocate {
|
|||||||
#[cfg(feature = "jit")]
|
#[cfg(feature = "jit")]
|
||||||
pub(super) fn relocate_for_jit(
|
pub(super) fn relocate_for_jit(
|
||||||
mut self,
|
mut self,
|
||||||
jit_product: &cranelift_simplejit::SimpleJITProduct,
|
jit_module: &cranelift_simplejit::SimpleJITModule,
|
||||||
) -> Vec<u8> {
|
) -> Vec<u8> {
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
|
||||||
@ -84,8 +84,9 @@ impl WriterRelocate {
|
|||||||
match reloc.name {
|
match reloc.name {
|
||||||
super::DebugRelocName::Section(_) => unreachable!(),
|
super::DebugRelocName::Section(_) => unreachable!(),
|
||||||
super::DebugRelocName::Symbol(sym) => {
|
super::DebugRelocName::Symbol(sym) => {
|
||||||
let addr = jit_product
|
let addr = jit_module.get_finalized_function(
|
||||||
.lookup_func(cranelift_module::FuncId::from_u32(sym.try_into().unwrap()));
|
cranelift_module::FuncId::from_u32(sym.try_into().unwrap()),
|
||||||
|
);
|
||||||
let val = (addr as u64 as i64 + reloc.addend) as u64;
|
let val = (addr as u64 as i64 + reloc.addend) as u64;
|
||||||
self.writer
|
self.writer
|
||||||
.write_udata_at(reloc.offset as usize, val, reloc.size)
|
.write_udata_at(reloc.offset as usize, val, reloc.size)
|
||||||
|
@ -365,7 +365,7 @@ impl<'tcx> DebugContext<'tcx> {
|
|||||||
let ty = self.tcx.subst_and_normalize_erasing_regions(
|
let ty = self.tcx.subst_and_normalize_erasing_regions(
|
||||||
instance.substs,
|
instance.substs,
|
||||||
ty::ParamEnv::reveal_all(),
|
ty::ParamEnv::reveal_all(),
|
||||||
&mir.local_decls[local].ty,
|
mir.local_decls[local].ty,
|
||||||
);
|
);
|
||||||
let var_id = self.define_local(entry_id, format!("{:?}", local), ty);
|
let var_id = self.define_local(entry_id, format!("{:?}", local), ty);
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ impl<'tcx> UnwindContext<'tcx> {
|
|||||||
#[cfg(feature = "jit")]
|
#[cfg(feature = "jit")]
|
||||||
pub(crate) unsafe fn register_jit(
|
pub(crate) unsafe fn register_jit(
|
||||||
self,
|
self,
|
||||||
jit_product: &cranelift_simplejit::SimpleJITProduct,
|
jit_module: &cranelift_simplejit::SimpleJITModule,
|
||||||
) -> Option<UnwindRegistry> {
|
) -> Option<UnwindRegistry> {
|
||||||
let mut eh_frame = EhFrame::from(super::emit::WriterRelocate::new(super::target_endian(
|
let mut eh_frame = EhFrame::from(super::emit::WriterRelocate::new(super::target_endian(
|
||||||
self.tcx,
|
self.tcx,
|
||||||
@ -91,7 +91,7 @@ impl<'tcx> UnwindContext<'tcx> {
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut eh_frame = eh_frame.0.relocate_for_jit(jit_product);
|
let mut eh_frame = eh_frame.0.relocate_for_jit(jit_module);
|
||||||
|
|
||||||
// GCC expects a terminating "empty" length, so write a 0 length at the end of the table.
|
// GCC expects a terminating "empty" length, so write a 0 length at the end of the table.
|
||||||
eh_frame.extend(&[0, 0, 0, 0]);
|
eh_frame.extend(&[0, 0, 0, 0]);
|
||||||
|
@ -30,8 +30,16 @@ pub(crate) fn codegen_set_discriminant<'tcx>(
|
|||||||
.ty
|
.ty
|
||||||
.discriminant_for_variant(fx.tcx, variant_index)
|
.discriminant_for_variant(fx.tcx, variant_index)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.val
|
.val;
|
||||||
.into();
|
let to = if ptr.layout().abi.is_signed() {
|
||||||
|
ty::ScalarInt::try_from_int(
|
||||||
|
ptr.layout().size.sign_extend(to) as i128,
|
||||||
|
ptr.layout().size,
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
} else {
|
||||||
|
ty::ScalarInt::try_from_uint(to, ptr.layout().size).unwrap()
|
||||||
|
};
|
||||||
let discr = CValue::const_val(fx, ptr.layout(), to);
|
let discr = CValue::const_val(fx, ptr.layout(), to);
|
||||||
ptr.write_cvalue(fx, discr);
|
ptr.write_cvalue(fx, discr);
|
||||||
}
|
}
|
||||||
@ -49,8 +57,12 @@ pub(crate) fn codegen_set_discriminant<'tcx>(
|
|||||||
if variant_index != dataful_variant {
|
if variant_index != dataful_variant {
|
||||||
let niche = place.place_field(fx, mir::Field::new(tag_field));
|
let niche = place.place_field(fx, mir::Field::new(tag_field));
|
||||||
let niche_value = variant_index.as_u32() - niche_variants.start().as_u32();
|
let niche_value = variant_index.as_u32() - niche_variants.start().as_u32();
|
||||||
let niche_value = u128::from(niche_value).wrapping_add(niche_start);
|
let niche_value = ty::ScalarInt::try_from_uint(
|
||||||
let niche_llval = CValue::const_val(fx, niche.layout(), niche_value.into());
|
u128::from(niche_value).wrapping_add(niche_start),
|
||||||
|
niche.layout().size,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
let niche_llval = CValue::const_val(fx, niche.layout(), niche_value);
|
||||||
niche.write_cvalue(fx, niche_llval);
|
niche.write_cvalue(fx, niche_llval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -78,7 +90,16 @@ pub(crate) fn codegen_get_discriminant<'tcx>(
|
|||||||
.ty
|
.ty
|
||||||
.discriminant_for_variant(fx.tcx, *index)
|
.discriminant_for_variant(fx.tcx, *index)
|
||||||
.map_or(u128::from(index.as_u32()), |discr| discr.val);
|
.map_or(u128::from(index.as_u32()), |discr| discr.val);
|
||||||
return CValue::const_val(fx, dest_layout, discr_val.into());
|
let discr_val = if dest_layout.abi.is_signed() {
|
||||||
|
ty::ScalarInt::try_from_int(
|
||||||
|
dest_layout.size.sign_extend(discr_val) as i128,
|
||||||
|
dest_layout.size,
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
} else {
|
||||||
|
ty::ScalarInt::try_from_uint(discr_val, dest_layout.size).unwrap()
|
||||||
|
};
|
||||||
|
return CValue::const_val(fx, dest_layout, discr_val);
|
||||||
}
|
}
|
||||||
Variants::Multiple {
|
Variants::Multiple {
|
||||||
tag,
|
tag,
|
||||||
|
@ -75,6 +75,7 @@ fn emit_module(
|
|||||||
name,
|
name,
|
||||||
kind,
|
kind,
|
||||||
object: Some(tmp_file),
|
object: Some(tmp_file),
|
||||||
|
dwarf_object: None,
|
||||||
bytecode: None,
|
bytecode: None,
|
||||||
},
|
},
|
||||||
work_product,
|
work_product,
|
||||||
@ -111,6 +112,7 @@ fn reuse_workproduct_for_cgu(
|
|||||||
name: cgu.name().to_string(),
|
name: cgu.name().to_string(),
|
||||||
kind: ModuleKind::Regular,
|
kind: ModuleKind::Regular,
|
||||||
object,
|
object,
|
||||||
|
dwarf_object: None,
|
||||||
bytecode: None,
|
bytecode: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -145,7 +147,11 @@ fn module_codegen(tcx: TyCtxt<'_>, cgu_name: rustc_span::Symbol) -> ModuleCodege
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut cx = crate::CodegenCx::new(tcx, module, tcx.sess.opts.debuginfo != DebugInfo::None);
|
let mut cx = crate::CodegenCx::new(tcx, module, tcx.sess.opts.debuginfo != DebugInfo::None);
|
||||||
super::codegen_mono_items(&mut cx, 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);
|
||||||
|
super::codegen_mono_item(&mut cx, mono_item, linkage);
|
||||||
|
}
|
||||||
let (mut module, global_asm, debug, mut unwind_context) =
|
let (mut module, global_asm, debug, mut unwind_context) =
|
||||||
tcx.sess.time("finalize CodegenCx", || cx.finalize());
|
tcx.sess.time("finalize CodegenCx", || cx.finalize());
|
||||||
crate::main_shim::maybe_create_entry_wrapper(tcx, &mut module, &mut unwind_context, false);
|
crate::main_shim::maybe_create_entry_wrapper(tcx, &mut module, &mut unwind_context, false);
|
||||||
@ -286,6 +292,7 @@ pub(super) fn run_aot(
|
|||||||
name: metadata_cgu_name,
|
name: metadata_cgu_name,
|
||||||
kind: ModuleKind::Metadata,
|
kind: ModuleKind::Metadata,
|
||||||
object: Some(tmp_file),
|
object: Some(tmp_file),
|
||||||
|
dwarf_object: None,
|
||||||
bytecode: None,
|
bytecode: None,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
|
@ -70,7 +70,11 @@ pub(super) fn run_jit(tcx: TyCtxt<'_>) -> ! {
|
|||||||
|
|
||||||
let (mut jit_module, global_asm, _debug, mut unwind_context) =
|
let (mut jit_module, global_asm, _debug, mut unwind_context) =
|
||||||
super::time(tcx, "codegen mono items", || {
|
super::time(tcx, "codegen mono items", || {
|
||||||
super::codegen_mono_items(&mut cx, 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);
|
||||||
|
super::codegen_mono_item(&mut cx, mono_item, linkage);
|
||||||
|
}
|
||||||
tcx.sess.time("finalize CodegenCx", || cx.finalize())
|
tcx.sess.time("finalize CodegenCx", || cx.finalize())
|
||||||
});
|
});
|
||||||
if !global_asm.is_empty() {
|
if !global_asm.is_empty() {
|
||||||
@ -81,11 +85,11 @@ pub(super) fn run_jit(tcx: TyCtxt<'_>) -> ! {
|
|||||||
|
|
||||||
tcx.sess.abort_if_errors();
|
tcx.sess.abort_if_errors();
|
||||||
|
|
||||||
let jit_product = jit_module.finish();
|
jit_module.finalize_definitions();
|
||||||
|
|
||||||
let _unwind_register_guard = unsafe { unwind_context.register_jit(&jit_product) };
|
let _unwind_register_guard = unsafe { unwind_context.register_jit(&jit_module) };
|
||||||
|
|
||||||
let finalized_main: *const u8 = jit_product.lookup_func(main_func_id);
|
let finalized_main: *const u8 = jit_module.get_finalized_function(main_func_id);
|
||||||
|
|
||||||
println!("Rustc codegen cranelift will JIT run the executable, because --jit was passed");
|
println!("Rustc codegen cranelift will JIT run the executable, because --jit was passed");
|
||||||
|
|
||||||
@ -140,11 +144,11 @@ fn load_imported_symbols_for_jit(tcx: TyCtxt<'_>) -> Vec<(String, *const u8)> {
|
|||||||
|
|
||||||
let mut imported_symbols = Vec::new();
|
let mut imported_symbols = Vec::new();
|
||||||
for path in dylib_paths {
|
for path in dylib_paths {
|
||||||
use object::Object;
|
use object::{Object, ObjectSymbol};
|
||||||
let lib = libloading::Library::new(&path).unwrap();
|
let lib = libloading::Library::new(&path).unwrap();
|
||||||
let obj = std::fs::read(path).unwrap();
|
let obj = std::fs::read(path).unwrap();
|
||||||
let obj = object::File::parse(&obj).unwrap();
|
let obj = object::File::parse(&obj).unwrap();
|
||||||
imported_symbols.extend(obj.dynamic_symbols().filter_map(|(_idx, symbol)| {
|
imported_symbols.extend(obj.dynamic_symbols().filter_map(|symbol| {
|
||||||
let name = symbol.name().unwrap().to_string();
|
let name = symbol.name().unwrap().to_string();
|
||||||
if name.is_empty() || !symbol.is_global() || symbol.is_undefined() {
|
if name.is_empty() || !symbol.is_global() || symbol.is_undefined() {
|
||||||
return None;
|
return None;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
//! Drivers are responsible for calling [`codegen_mono_items`] and performing any further actions
|
//! Drivers are responsible for calling [`codegen_mono_item`] and performing any further actions
|
||||||
//! like JIT executing or writing object files.
|
//! like JIT executing or writing object files.
|
||||||
|
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
@ -40,12 +40,12 @@ pub(crate) fn codegen_crate(
|
|||||||
aot::run_aot(tcx, metadata, need_metadata_module)
|
aot::run_aot(tcx, metadata, need_metadata_module)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn codegen_mono_items<'tcx>(
|
fn predefine_mono_items<'tcx>(
|
||||||
cx: &mut crate::CodegenCx<'tcx, impl Module>,
|
cx: &mut crate::CodegenCx<'tcx, impl Module>,
|
||||||
mono_items: Vec<(MonoItem<'tcx>, (RLinkage, Visibility))>,
|
mono_items: &[(MonoItem<'tcx>, (RLinkage, Visibility))],
|
||||||
) {
|
) {
|
||||||
cx.tcx.sess.time("predefine functions", || {
|
cx.tcx.sess.time("predefine functions", || {
|
||||||
for &(mono_item, (linkage, visibility)) in &mono_items {
|
for &(mono_item, (linkage, visibility)) in mono_items {
|
||||||
match mono_item {
|
match mono_item {
|
||||||
MonoItem::Fn(instance) => {
|
MonoItem::Fn(instance) => {
|
||||||
let (name, sig) = get_function_name_and_sig(
|
let (name, sig) = get_function_name_and_sig(
|
||||||
@ -61,11 +61,6 @@ fn codegen_mono_items<'tcx>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
for (mono_item, (linkage, visibility)) in mono_items {
|
|
||||||
let linkage = crate::linkage::get_clif_linkage(mono_item, linkage, visibility);
|
|
||||||
codegen_mono_item(cx, mono_item, linkage);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn codegen_mono_item<'tcx, M: Module>(
|
fn codegen_mono_item<'tcx, M: Module>(
|
||||||
@ -73,20 +68,15 @@ fn codegen_mono_item<'tcx, M: Module>(
|
|||||||
mono_item: MonoItem<'tcx>,
|
mono_item: MonoItem<'tcx>,
|
||||||
linkage: Linkage,
|
linkage: Linkage,
|
||||||
) {
|
) {
|
||||||
let tcx = cx.tcx;
|
|
||||||
match mono_item {
|
match mono_item {
|
||||||
MonoItem::Fn(inst) => {
|
MonoItem::Fn(inst) => {
|
||||||
let _inst_guard =
|
cx.tcx
|
||||||
crate::PrintOnPanic(|| format!("{:?} {}", inst, tcx.symbol_name(inst).name));
|
.sess
|
||||||
debug_assert!(!inst.substs.needs_infer());
|
|
||||||
tcx.sess
|
|
||||||
.time("codegen fn", || crate::base::codegen_fn(cx, inst, linkage));
|
.time("codegen fn", || crate::base::codegen_fn(cx, inst, linkage));
|
||||||
}
|
}
|
||||||
MonoItem::Static(def_id) => {
|
MonoItem::Static(def_id) => crate::constant::codegen_static(&mut cx.constants_cx, def_id),
|
||||||
crate::constant::codegen_static(&mut cx.constants_cx, def_id);
|
|
||||||
}
|
|
||||||
MonoItem::GlobalAsm(hir_id) => {
|
MonoItem::GlobalAsm(hir_id) => {
|
||||||
let item = tcx.hir().expect_item(hir_id);
|
let item = cx.tcx.hir().expect_item(hir_id);
|
||||||
if let rustc_hir::ItemKind::GlobalAsm(rustc_hir::GlobalAsm { asm }) = item.kind {
|
if let rustc_hir::ItemKind::GlobalAsm(rustc_hir::GlobalAsm { asm }) = item.kind {
|
||||||
cx.global_asm.push_str(&*asm.as_str());
|
cx.global_asm.push_str(&*asm.as_str());
|
||||||
cx.global_asm.push_str("\n\n");
|
cx.global_asm.push_str("\n\n");
|
||||||
|
@ -146,12 +146,12 @@ macro atomic_minmax($fx:expr, $cc:expr, <$T:ident> ($ptr:ident, $src:ident) -> $
|
|||||||
|
|
||||||
macro validate_atomic_type($fx:ident, $intrinsic:ident, $span:ident, $ty:expr) {
|
macro validate_atomic_type($fx:ident, $intrinsic:ident, $span:ident, $ty:expr) {
|
||||||
match $ty.kind() {
|
match $ty.kind() {
|
||||||
ty::Uint(_) | ty::Int(_) => {}
|
ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {}
|
||||||
_ => {
|
_ => {
|
||||||
$fx.tcx.sess.span_err(
|
$fx.tcx.sess.span_err(
|
||||||
$span,
|
$span,
|
||||||
&format!(
|
&format!(
|
||||||
"`{}` intrinsic: expected basic integer type, found `{:?}`",
|
"`{}` intrinsic: expected basic integer or raw pointer type, found `{:?}`",
|
||||||
$intrinsic, $ty
|
$intrinsic, $ty
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -263,6 +263,48 @@ fn simd_pair_for_each_lane<'tcx, M: Module>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn simd_reduce<'tcx, M: Module>(
|
||||||
|
fx: &mut FunctionCx<'_, 'tcx, M>,
|
||||||
|
val: CValue<'tcx>,
|
||||||
|
ret: CPlace<'tcx>,
|
||||||
|
f: impl Fn(&mut FunctionCx<'_, 'tcx, M>, TyAndLayout<'tcx>, Value, Value) -> Value,
|
||||||
|
) {
|
||||||
|
let (lane_layout, lane_count) = lane_type_and_count(fx.tcx, val.layout());
|
||||||
|
assert_eq!(lane_layout, ret.layout());
|
||||||
|
|
||||||
|
let mut res_val = val.value_field(fx, mir::Field::new(0)).load_scalar(fx);
|
||||||
|
for lane_idx in 1..lane_count {
|
||||||
|
let lane = val
|
||||||
|
.value_field(fx, mir::Field::new(lane_idx.into()))
|
||||||
|
.load_scalar(fx);
|
||||||
|
res_val = f(fx, lane_layout, res_val, lane);
|
||||||
|
}
|
||||||
|
let res = CValue::by_val(res_val, lane_layout);
|
||||||
|
ret.write_cvalue(fx, res);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn simd_reduce_bool<'tcx, M: Module>(
|
||||||
|
fx: &mut FunctionCx<'_, 'tcx, M>,
|
||||||
|
val: CValue<'tcx>,
|
||||||
|
ret: CPlace<'tcx>,
|
||||||
|
f: impl Fn(&mut FunctionCx<'_, 'tcx, M>, Value, Value) -> Value,
|
||||||
|
) {
|
||||||
|
let (_lane_layout, lane_count) = lane_type_and_count(fx.tcx, val.layout());
|
||||||
|
assert!(ret.layout().ty.is_bool());
|
||||||
|
|
||||||
|
let res_val = val.value_field(fx, mir::Field::new(0)).load_scalar(fx);
|
||||||
|
let mut res_val = fx.bcx.ins().band_imm(res_val, 1); // mask to boolean
|
||||||
|
for lane_idx in 1..lane_count {
|
||||||
|
let lane = val
|
||||||
|
.value_field(fx, mir::Field::new(lane_idx.into()))
|
||||||
|
.load_scalar(fx);
|
||||||
|
let lane = fx.bcx.ins().band_imm(lane, 1); // mask to boolean
|
||||||
|
res_val = f(fx, res_val, lane);
|
||||||
|
}
|
||||||
|
let res = CValue::by_val(res_val, ret.layout());
|
||||||
|
ret.write_cvalue(fx, res);
|
||||||
|
}
|
||||||
|
|
||||||
fn bool_to_zero_or_max_uint<'tcx>(
|
fn bool_to_zero_or_max_uint<'tcx>(
|
||||||
fx: &mut FunctionCx<'_, 'tcx, impl Module>,
|
fx: &mut FunctionCx<'_, 'tcx, impl Module>,
|
||||||
layout: TyAndLayout<'tcx>,
|
layout: TyAndLayout<'tcx>,
|
||||||
@ -287,7 +329,7 @@ fn bool_to_zero_or_max_uint<'tcx>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
macro simd_cmp {
|
macro simd_cmp {
|
||||||
($fx:expr, $cc:ident($x:ident, $y:ident) -> $ret:ident) => {
|
($fx:expr, $cc:ident|$cc_f:ident($x:ident, $y:ident) -> $ret:ident) => {
|
||||||
let vector_ty = clif_vector_type($fx.tcx, $x.layout());
|
let vector_ty = clif_vector_type($fx.tcx, $x.layout());
|
||||||
|
|
||||||
if let Some(vector_ty) = vector_ty {
|
if let Some(vector_ty) = vector_ty {
|
||||||
@ -308,6 +350,7 @@ macro simd_cmp {
|
|||||||
|fx, lane_layout, res_lane_layout, x_lane, y_lane| {
|
|fx, lane_layout, res_lane_layout, x_lane, y_lane| {
|
||||||
let res_lane = match lane_layout.ty.kind() {
|
let res_lane = match lane_layout.ty.kind() {
|
||||||
ty::Uint(_) | ty::Int(_) => fx.bcx.ins().icmp(IntCC::$cc, x_lane, y_lane),
|
ty::Uint(_) | ty::Int(_) => fx.bcx.ins().icmp(IntCC::$cc, x_lane, y_lane),
|
||||||
|
ty::Float(_) => fx.bcx.ins().fcmp(FloatCC::$cc_f, x_lane, y_lane),
|
||||||
_ => unreachable!("{:?}", lane_layout.ty),
|
_ => unreachable!("{:?}", lane_layout.ty),
|
||||||
};
|
};
|
||||||
bool_to_zero_or_max_uint(fx, res_lane_layout, res_lane)
|
bool_to_zero_or_max_uint(fx, res_lane_layout, res_lane)
|
||||||
@ -315,7 +358,7 @@ macro simd_cmp {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
($fx:expr, $cc_u:ident|$cc_s:ident($x:ident, $y:ident) -> $ret:ident) => {
|
($fx:expr, $cc_u:ident|$cc_s:ident|$cc_f:ident($x:ident, $y:ident) -> $ret:ident) => {
|
||||||
// FIXME use vector icmp when possible
|
// FIXME use vector icmp when possible
|
||||||
simd_pair_for_each_lane(
|
simd_pair_for_each_lane(
|
||||||
$fx,
|
$fx,
|
||||||
@ -326,6 +369,7 @@ macro simd_cmp {
|
|||||||
let res_lane = match lane_layout.ty.kind() {
|
let res_lane = match lane_layout.ty.kind() {
|
||||||
ty::Uint(_) => fx.bcx.ins().icmp(IntCC::$cc_u, x_lane, y_lane),
|
ty::Uint(_) => fx.bcx.ins().icmp(IntCC::$cc_u, x_lane, y_lane),
|
||||||
ty::Int(_) => fx.bcx.ins().icmp(IntCC::$cc_s, x_lane, y_lane),
|
ty::Int(_) => fx.bcx.ins().icmp(IntCC::$cc_s, x_lane, y_lane),
|
||||||
|
ty::Float(_) => fx.bcx.ins().fcmp(FloatCC::$cc_f, x_lane, y_lane),
|
||||||
_ => unreachable!("{:?}", lane_layout.ty),
|
_ => unreachable!("{:?}", lane_layout.ty),
|
||||||
};
|
};
|
||||||
bool_to_zero_or_max_uint(fx, res_lane_layout, res_lane)
|
bool_to_zero_or_max_uint(fx, res_lane_layout, res_lane)
|
||||||
@ -497,12 +541,12 @@ pub(crate) fn codegen_intrinsic_call<'tcx>(
|
|||||||
};
|
};
|
||||||
copy | copy_nonoverlapping, <elem_ty> (v src, v dst, v count) {
|
copy | copy_nonoverlapping, <elem_ty> (v src, v dst, v count) {
|
||||||
let elem_size: u64 = fx.layout_of(elem_ty).size.bytes();
|
let elem_size: u64 = fx.layout_of(elem_ty).size.bytes();
|
||||||
let elem_size = fx
|
|
||||||
.bcx
|
|
||||||
.ins()
|
|
||||||
.iconst(fx.pointer_type, elem_size as i64);
|
|
||||||
assert_eq!(args.len(), 3);
|
assert_eq!(args.len(), 3);
|
||||||
let byte_amount = fx.bcx.ins().imul(count, elem_size);
|
let byte_amount = if elem_size != 1 {
|
||||||
|
fx.bcx.ins().imul_imm(count, elem_size as i64)
|
||||||
|
} else {
|
||||||
|
count
|
||||||
|
};
|
||||||
|
|
||||||
if intrinsic.contains("nonoverlapping") {
|
if intrinsic.contains("nonoverlapping") {
|
||||||
// FIXME emit_small_memcpy
|
// FIXME emit_small_memcpy
|
||||||
@ -515,12 +559,12 @@ pub(crate) fn codegen_intrinsic_call<'tcx>(
|
|||||||
// NOTE: the volatile variants have src and dst swapped
|
// NOTE: the volatile variants have src and dst swapped
|
||||||
volatile_copy_memory | volatile_copy_nonoverlapping_memory, <elem_ty> (v dst, v src, v count) {
|
volatile_copy_memory | volatile_copy_nonoverlapping_memory, <elem_ty> (v dst, v src, v count) {
|
||||||
let elem_size: u64 = fx.layout_of(elem_ty).size.bytes();
|
let elem_size: u64 = fx.layout_of(elem_ty).size.bytes();
|
||||||
let elem_size = fx
|
|
||||||
.bcx
|
|
||||||
.ins()
|
|
||||||
.iconst(fx.pointer_type, elem_size as i64);
|
|
||||||
assert_eq!(args.len(), 3);
|
assert_eq!(args.len(), 3);
|
||||||
let byte_amount = fx.bcx.ins().imul(count, elem_size);
|
let byte_amount = if elem_size != 1 {
|
||||||
|
fx.bcx.ins().imul_imm(count, elem_size as i64)
|
||||||
|
} else {
|
||||||
|
count
|
||||||
|
};
|
||||||
|
|
||||||
// FIXME make the copy actually volatile when using emit_small_mem{cpy,move}
|
// FIXME make the copy actually volatile when using emit_small_mem{cpy,move}
|
||||||
if intrinsic.contains("nonoverlapping") {
|
if intrinsic.contains("nonoverlapping") {
|
||||||
@ -676,7 +720,11 @@ pub(crate) fn codegen_intrinsic_call<'tcx>(
|
|||||||
offset | arith_offset, (c base, v offset) {
|
offset | arith_offset, (c base, v offset) {
|
||||||
let pointee_ty = base.layout().ty.builtin_deref(true).unwrap().ty;
|
let pointee_ty = base.layout().ty.builtin_deref(true).unwrap().ty;
|
||||||
let pointee_size = fx.layout_of(pointee_ty).size.bytes();
|
let pointee_size = fx.layout_of(pointee_ty).size.bytes();
|
||||||
let ptr_diff = fx.bcx.ins().imul_imm(offset, pointee_size as i64);
|
let ptr_diff = if pointee_size != 1 {
|
||||||
|
fx.bcx.ins().imul_imm(offset, pointee_size as i64)
|
||||||
|
} else {
|
||||||
|
offset
|
||||||
|
};
|
||||||
let base_val = base.load_scalar(fx);
|
let base_val = base.load_scalar(fx);
|
||||||
let res = fx.bcx.ins().iadd(base_val, ptr_diff);
|
let res = fx.bcx.ins().iadd(base_val, ptr_diff);
|
||||||
ret.write_cvalue(fx, CValue::by_val(res, base.layout()));
|
ret.write_cvalue(fx, CValue::by_val(res, base.layout()));
|
||||||
@ -688,7 +736,11 @@ pub(crate) fn codegen_intrinsic_call<'tcx>(
|
|||||||
write_bytes | volatile_set_memory, (c dst, v val, v count) {
|
write_bytes | volatile_set_memory, (c dst, v val, v count) {
|
||||||
let pointee_ty = dst.layout().ty.builtin_deref(true).unwrap().ty;
|
let pointee_ty = dst.layout().ty.builtin_deref(true).unwrap().ty;
|
||||||
let pointee_size = fx.layout_of(pointee_ty).size.bytes();
|
let pointee_size = fx.layout_of(pointee_ty).size.bytes();
|
||||||
let count = fx.bcx.ins().imul_imm(count, pointee_size as i64);
|
let count = if pointee_size != 1 {
|
||||||
|
fx.bcx.ins().imul_imm(count, pointee_size as i64)
|
||||||
|
} else {
|
||||||
|
count
|
||||||
|
};
|
||||||
let dst_ptr = dst.load_scalar(fx);
|
let dst_ptr = dst.load_scalar(fx);
|
||||||
// FIXME make the memset actually volatile when switching to emit_small_memset
|
// FIXME make the memset actually volatile when switching to emit_small_memset
|
||||||
// FIXME use emit_small_memset
|
// FIXME use emit_small_memset
|
||||||
|
@ -35,30 +35,33 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// FIXME support float comparisons
|
|
||||||
simd_eq, (c x, c y) {
|
simd_eq, (c x, c y) {
|
||||||
validate_simd_type!(fx, intrinsic, span, x.layout().ty);
|
validate_simd_type!(fx, intrinsic, span, x.layout().ty);
|
||||||
simd_cmp!(fx, Equal(x, y) -> ret);
|
simd_cmp!(fx, Equal|Equal(x, y) -> ret);
|
||||||
};
|
};
|
||||||
simd_ne, (c x, c y) {
|
simd_ne, (c x, c y) {
|
||||||
validate_simd_type!(fx, intrinsic, span, x.layout().ty);
|
validate_simd_type!(fx, intrinsic, span, x.layout().ty);
|
||||||
simd_cmp!(fx, NotEqual(x, y) -> ret);
|
simd_cmp!(fx, NotEqual|NotEqual(x, y) -> ret);
|
||||||
};
|
};
|
||||||
simd_lt, (c x, c y) {
|
simd_lt, (c x, c y) {
|
||||||
validate_simd_type!(fx, intrinsic, span, x.layout().ty);
|
validate_simd_type!(fx, intrinsic, span, x.layout().ty);
|
||||||
simd_cmp!(fx, UnsignedLessThan|SignedLessThan(x, y) -> ret);
|
simd_cmp!(fx, UnsignedLessThan|SignedLessThan|LessThan(x, y) -> ret);
|
||||||
};
|
};
|
||||||
simd_le, (c x, c y) {
|
simd_le, (c x, c y) {
|
||||||
validate_simd_type!(fx, intrinsic, span, x.layout().ty);
|
validate_simd_type!(fx, intrinsic, span, x.layout().ty);
|
||||||
simd_cmp!(fx, UnsignedLessThanOrEqual|SignedLessThanOrEqual(x, y) -> ret);
|
simd_cmp!(fx, UnsignedLessThanOrEqual|SignedLessThanOrEqual|LessThanOrEqual(x, y) -> ret);
|
||||||
};
|
};
|
||||||
simd_gt, (c x, c y) {
|
simd_gt, (c x, c y) {
|
||||||
validate_simd_type!(fx, intrinsic, span, x.layout().ty);
|
validate_simd_type!(fx, intrinsic, span, x.layout().ty);
|
||||||
simd_cmp!(fx, UnsignedGreaterThan|SignedGreaterThan(x, y) -> ret);
|
simd_cmp!(fx, UnsignedGreaterThan|SignedGreaterThan|GreaterThan(x, y) -> ret);
|
||||||
};
|
};
|
||||||
simd_ge, (c x, c y) {
|
simd_ge, (c x, c y) {
|
||||||
validate_simd_type!(fx, intrinsic, span, x.layout().ty);
|
validate_simd_type!(fx, intrinsic, span, x.layout().ty);
|
||||||
simd_cmp!(fx, UnsignedGreaterThanOrEqual|SignedGreaterThanOrEqual(x, y) -> ret);
|
simd_cmp!(
|
||||||
|
fx,
|
||||||
|
UnsignedGreaterThanOrEqual|SignedGreaterThanOrEqual|GreaterThanOrEqual
|
||||||
|
(x, y) -> ret
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
// simd_shuffle32<T, U>(x: T, y: T, idx: [u32; 32]) -> U
|
// simd_shuffle32<T, U>(x: T, y: T, idx: [u32; 32]) -> U
|
||||||
@ -107,9 +110,9 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
|
|||||||
|
|
||||||
for (out_idx, in_idx) in indexes.into_iter().enumerate() {
|
for (out_idx, in_idx) in indexes.into_iter().enumerate() {
|
||||||
let in_lane = if in_idx < lane_count {
|
let in_lane = if in_idx < lane_count {
|
||||||
x.value_field(fx, mir::Field::new(in_idx.try_into().unwrap()))
|
x.value_field(fx, mir::Field::new(in_idx.into()))
|
||||||
} else {
|
} else {
|
||||||
y.value_field(fx, mir::Field::new((in_idx - lane_count).try_into().unwrap()))
|
y.value_field(fx, mir::Field::new((in_idx - lane_count).into()))
|
||||||
};
|
};
|
||||||
let out_lane = ret.place_field(fx, mir::Field::new(out_idx));
|
let out_lane = ret.place_field(fx, mir::Field::new(out_idx));
|
||||||
out_lane.write_cvalue(fx, in_lane);
|
out_lane.write_cvalue(fx, in_lane);
|
||||||
@ -143,10 +146,17 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
|
|||||||
let idx_const = if let Some(idx_const) = crate::constant::mir_operand_get_const_val(fx, idx) {
|
let idx_const = if let Some(idx_const) = crate::constant::mir_operand_get_const_val(fx, idx) {
|
||||||
idx_const
|
idx_const
|
||||||
} else {
|
} else {
|
||||||
fx.tcx.sess.span_fatal(
|
fx.tcx.sess.span_warn(
|
||||||
span,
|
span,
|
||||||
"Index argument for `simd_extract` is not a constant",
|
"Index argument for `simd_extract` is not a constant",
|
||||||
);
|
);
|
||||||
|
let res = crate::trap::trap_unimplemented_ret_value(
|
||||||
|
fx,
|
||||||
|
ret.layout(),
|
||||||
|
"Index argument for `simd_extract` is not a constant",
|
||||||
|
);
|
||||||
|
ret.write_cvalue(fx, res);
|
||||||
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
let idx = idx_const.val.try_to_bits(Size::from_bytes(4 /* u32*/)).unwrap_or_else(|| panic!("kind not scalar: {:?}", idx_const));
|
let idx = idx_const.val.try_to_bits(Size::from_bytes(4 /* u32*/)).unwrap_or_else(|| panic!("kind not scalar: {:?}", idx_const));
|
||||||
@ -207,7 +217,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
|
|||||||
assert_eq!(lane_count, ret_lane_count);
|
assert_eq!(lane_count, ret_lane_count);
|
||||||
|
|
||||||
for lane in 0..lane_count {
|
for lane in 0..lane_count {
|
||||||
let lane = mir::Field::new(lane.try_into().unwrap());
|
let lane = mir::Field::new(lane.into());
|
||||||
let a_lane = a.value_field(fx, lane).load_scalar(fx);
|
let a_lane = a.value_field(fx, lane).load_scalar(fx);
|
||||||
let b_lane = b.value_field(fx, lane).load_scalar(fx);
|
let b_lane = b.value_field(fx, lane).load_scalar(fx);
|
||||||
let c_lane = c.value_field(fx, lane).load_scalar(fx);
|
let c_lane = c.value_field(fx, lane).load_scalar(fx);
|
||||||
@ -228,11 +238,42 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
|
|||||||
simd_flt_binop!(fx, fmax(x, y) -> ret);
|
simd_flt_binop!(fx, fmax(x, y) -> ret);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
simd_reduce_add_ordered | simd_reduce_add_unordered, (c v) {
|
||||||
|
validate_simd_type!(fx, intrinsic, span, v.layout().ty);
|
||||||
|
simd_reduce(fx, v, ret, |fx, lane_layout, a, b| {
|
||||||
|
if lane_layout.ty.is_floating_point() {
|
||||||
|
fx.bcx.ins().fadd(a, b)
|
||||||
|
} else {
|
||||||
|
fx.bcx.ins().iadd(a, b)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
simd_reduce_mul_ordered | simd_reduce_mul_unordered, (c v) {
|
||||||
|
validate_simd_type!(fx, intrinsic, span, v.layout().ty);
|
||||||
|
simd_reduce(fx, v, ret, |fx, lane_layout, a, b| {
|
||||||
|
if lane_layout.ty.is_floating_point() {
|
||||||
|
fx.bcx.ins().fmul(a, b)
|
||||||
|
} else {
|
||||||
|
fx.bcx.ins().imul(a, b)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
simd_reduce_all, (c v) {
|
||||||
|
validate_simd_type!(fx, intrinsic, span, v.layout().ty);
|
||||||
|
simd_reduce_bool(fx, v, ret, |fx, a, b| fx.bcx.ins().band(a, b));
|
||||||
|
};
|
||||||
|
|
||||||
|
simd_reduce_any, (c v) {
|
||||||
|
validate_simd_type!(fx, intrinsic, span, v.layout().ty);
|
||||||
|
simd_reduce_bool(fx, v, ret, |fx, a, b| fx.bcx.ins().bor(a, b));
|
||||||
|
};
|
||||||
|
|
||||||
// simd_fabs
|
// simd_fabs
|
||||||
// simd_saturating_add
|
// simd_saturating_add
|
||||||
// simd_bitmask
|
// simd_bitmask
|
||||||
// simd_select
|
// simd_select
|
||||||
// simd_reduce_add_{,un}ordered
|
|
||||||
// simd_rem
|
// simd_rem
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ pub(crate) fn maybe_create_entry_wrapper(
|
|||||||
// late-bound regions, since late-bound
|
// late-bound regions, since late-bound
|
||||||
// regions must appear in the argument
|
// regions must appear in the argument
|
||||||
// listing.
|
// listing.
|
||||||
let main_ret_ty = tcx.erase_regions(&main_ret_ty.no_bound_vars().unwrap());
|
let main_ret_ty = tcx.erase_regions(main_ret_ty.no_bound_vars().unwrap());
|
||||||
|
|
||||||
let cmain_sig = Signature {
|
let cmain_sig = Signature {
|
||||||
params: vec![
|
params: vec![
|
||||||
|
@ -80,7 +80,7 @@ impl CommentWriter {
|
|||||||
"sig {:?}",
|
"sig {:?}",
|
||||||
tcx.normalize_erasing_late_bound_regions(
|
tcx.normalize_erasing_late_bound_regions(
|
||||||
ParamEnv::reveal_all(),
|
ParamEnv::reveal_all(),
|
||||||
&crate::abi::fn_sig_for_fn_abi(tcx, instance)
|
crate::abi::fn_sig_for_fn_abi(tcx, instance)
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
String::new(),
|
String::new(),
|
||||||
|
@ -67,3 +67,15 @@ pub(crate) fn trap_unimplemented(fx: &mut FunctionCx<'_, '_, impl Module>, msg:
|
|||||||
let true_ = fx.bcx.ins().iconst(types::I32, 1);
|
let true_ = fx.bcx.ins().iconst(types::I32, 1);
|
||||||
fx.bcx.ins().trapnz(true_, TrapCode::User(!0));
|
fx.bcx.ins().trapnz(true_, TrapCode::User(!0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Like `trap_unimplemented` but returns a fake value of the specified type.
|
||||||
|
///
|
||||||
|
/// Trap code: user65535
|
||||||
|
pub(crate) fn trap_unimplemented_ret_value<'tcx>(
|
||||||
|
fx: &mut FunctionCx<'_, 'tcx, impl Module>,
|
||||||
|
dest_layout: TyAndLayout<'tcx>,
|
||||||
|
msg: impl AsRef<str>,
|
||||||
|
) -> CValue<'tcx> {
|
||||||
|
trap_unimplemented(fx, msg);
|
||||||
|
CValue::by_ref(Pointer::const_addr(fx, 0), dest_layout)
|
||||||
|
}
|
||||||
|
@ -455,7 +455,7 @@ impl<'tcx> CPlace<'tcx> {
|
|||||||
from_ty: Ty<'tcx>,
|
from_ty: Ty<'tcx>,
|
||||||
to_ty: Ty<'tcx>,
|
to_ty: Ty<'tcx>,
|
||||||
) {
|
) {
|
||||||
match (&from_ty.kind(), &to_ty.kind()) {
|
match (from_ty.kind(), to_ty.kind()) {
|
||||||
(ty::Ref(_, a, _), ty::Ref(_, b, _))
|
(ty::Ref(_, a, _), ty::Ref(_, b, _))
|
||||||
| (
|
| (
|
||||||
ty::RawPtr(TypeAndMut { ty: a, mutbl: _ }),
|
ty::RawPtr(TypeAndMut { ty: a, mutbl: _ }),
|
||||||
@ -466,11 +466,11 @@ impl<'tcx> CPlace<'tcx> {
|
|||||||
(ty::FnPtr(_), ty::FnPtr(_)) => {
|
(ty::FnPtr(_), ty::FnPtr(_)) => {
|
||||||
let from_sig = fx.tcx.normalize_erasing_late_bound_regions(
|
let from_sig = fx.tcx.normalize_erasing_late_bound_regions(
|
||||||
ParamEnv::reveal_all(),
|
ParamEnv::reveal_all(),
|
||||||
&from_ty.fn_sig(fx.tcx),
|
from_ty.fn_sig(fx.tcx),
|
||||||
);
|
);
|
||||||
let to_sig = fx.tcx.normalize_erasing_late_bound_regions(
|
let to_sig = fx.tcx.normalize_erasing_late_bound_regions(
|
||||||
ParamEnv::reveal_all(),
|
ParamEnv::reveal_all(),
|
||||||
&to_ty.fn_sig(fx.tcx),
|
to_ty.fn_sig(fx.tcx),
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
from_sig, to_sig,
|
from_sig, to_sig,
|
||||||
@ -479,18 +479,20 @@ impl<'tcx> CPlace<'tcx> {
|
|||||||
);
|
);
|
||||||
// fn(&T) -> for<'l> fn(&'l T) is allowed
|
// fn(&T) -> for<'l> fn(&'l T) is allowed
|
||||||
}
|
}
|
||||||
(ty::Dynamic(from_traits, _), ty::Dynamic(to_traits, _)) => {
|
(&ty::Dynamic(from_traits, _), &ty::Dynamic(to_traits, _)) => {
|
||||||
let from_traits = fx
|
for (from, to) in from_traits.iter().zip(to_traits) {
|
||||||
|
let from = fx
|
||||||
.tcx
|
.tcx
|
||||||
.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), from_traits);
|
.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), from);
|
||||||
let to_traits = fx
|
let to = fx
|
||||||
.tcx
|
.tcx
|
||||||
.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), to_traits);
|
.normalize_erasing_late_bound_regions(ParamEnv::reveal_all(), to);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
from_traits, to_traits,
|
from, to,
|
||||||
"Can't write trait object of incompatible traits {:?} to place with traits {:?}\n\n{:#?}",
|
"Can't write trait object of incompatible traits {:?} to place with traits {:?}\n\n{:#?}",
|
||||||
from_traits, to_traits, fx,
|
from_traits, to_traits, fx,
|
||||||
);
|
);
|
||||||
|
}
|
||||||
// dyn for<'r> Trait<'r> -> dyn Trait<'_> is allowed
|
// dyn for<'r> Trait<'r> -> dyn Trait<'_> is allowed
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -36,17 +36,17 @@ impl ArgAttributeExt for ArgAttribute {
|
|||||||
where
|
where
|
||||||
F: FnMut(llvm::Attribute),
|
F: FnMut(llvm::Attribute),
|
||||||
{
|
{
|
||||||
for_each_kind!(self, f, NoAlias, NoCapture, NonNull, ReadOnly, SExt, StructRet, ZExt, InReg)
|
for_each_kind!(self, f, NoAlias, NoCapture, NonNull, ReadOnly, InReg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ArgAttributesExt {
|
pub trait ArgAttributesExt {
|
||||||
fn apply_llfn(&self, idx: AttributePlace, llfn: &Value, ty: Option<&Type>);
|
fn apply_attrs_to_llfn(&self, idx: AttributePlace, llfn: &Value);
|
||||||
fn apply_callsite(&self, idx: AttributePlace, callsite: &Value, ty: Option<&Type>);
|
fn apply_attrs_to_callsite(&self, idx: AttributePlace, callsite: &Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ArgAttributesExt for ArgAttributes {
|
impl ArgAttributesExt for ArgAttributes {
|
||||||
fn apply_llfn(&self, idx: AttributePlace, llfn: &Value, ty: Option<&Type>) {
|
fn apply_attrs_to_llfn(&self, idx: AttributePlace, llfn: &Value) {
|
||||||
let mut regular = self.regular;
|
let mut regular = self.regular;
|
||||||
unsafe {
|
unsafe {
|
||||||
let deref = self.pointee_size.bytes();
|
let deref = self.pointee_size.bytes();
|
||||||
@ -61,14 +61,20 @@ impl ArgAttributesExt for ArgAttributes {
|
|||||||
if let Some(align) = self.pointee_align {
|
if let Some(align) = self.pointee_align {
|
||||||
llvm::LLVMRustAddAlignmentAttr(llfn, idx.as_uint(), align.bytes() as u32);
|
llvm::LLVMRustAddAlignmentAttr(llfn, idx.as_uint(), align.bytes() as u32);
|
||||||
}
|
}
|
||||||
if regular.contains(ArgAttribute::ByVal) {
|
|
||||||
llvm::LLVMRustAddByValAttr(llfn, idx.as_uint(), ty.unwrap());
|
|
||||||
}
|
|
||||||
regular.for_each_kind(|attr| attr.apply_llfn(idx, llfn));
|
regular.for_each_kind(|attr| attr.apply_llfn(idx, llfn));
|
||||||
|
match self.arg_ext {
|
||||||
|
ArgExtension::None => {}
|
||||||
|
ArgExtension::Zext => {
|
||||||
|
llvm::Attribute::ZExt.apply_llfn(idx, llfn);
|
||||||
|
}
|
||||||
|
ArgExtension::Sext => {
|
||||||
|
llvm::Attribute::SExt.apply_llfn(idx, llfn);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply_callsite(&self, idx: AttributePlace, callsite: &Value, ty: Option<&Type>) {
|
fn apply_attrs_to_callsite(&self, idx: AttributePlace, callsite: &Value) {
|
||||||
let mut regular = self.regular;
|
let mut regular = self.regular;
|
||||||
unsafe {
|
unsafe {
|
||||||
let deref = self.pointee_size.bytes();
|
let deref = self.pointee_size.bytes();
|
||||||
@ -91,10 +97,16 @@ impl ArgAttributesExt for ArgAttributes {
|
|||||||
align.bytes() as u32,
|
align.bytes() as u32,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if regular.contains(ArgAttribute::ByVal) {
|
|
||||||
llvm::LLVMRustAddByValCallSiteAttr(callsite, idx.as_uint(), ty.unwrap());
|
|
||||||
}
|
|
||||||
regular.for_each_kind(|attr| attr.apply_callsite(idx, callsite));
|
regular.for_each_kind(|attr| attr.apply_callsite(idx, callsite));
|
||||||
|
match self.arg_ext {
|
||||||
|
ArgExtension::None => {}
|
||||||
|
ArgExtension::Zext => {
|
||||||
|
llvm::Attribute::ZExt.apply_callsite(idx, callsite);
|
||||||
|
}
|
||||||
|
ArgExtension::Sext => {
|
||||||
|
llvm::Attribute::SExt.apply_callsite(idx, callsite);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -146,7 +158,7 @@ impl LlvmType for CastTarget {
|
|||||||
.prefix
|
.prefix
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|option_kind| {
|
.flat_map(|option_kind| {
|
||||||
option_kind.map(|kind| Reg { kind, size: self.prefix_chunk }.llvm_type(cx))
|
option_kind.map(|kind| Reg { kind, size: self.prefix_chunk_size }.llvm_type(cx))
|
||||||
})
|
})
|
||||||
.chain((0..rest_count).map(|_| rest_ll_unit))
|
.chain((0..rest_count).map(|_| rest_ll_unit))
|
||||||
.collect();
|
.collect();
|
||||||
@ -267,10 +279,12 @@ impl ArgAbiExt<'ll, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
|
|||||||
PassMode::Pair(..) => {
|
PassMode::Pair(..) => {
|
||||||
OperandValue::Pair(next(), next()).store(bx, dst);
|
OperandValue::Pair(next(), next()).store(bx, dst);
|
||||||
}
|
}
|
||||||
PassMode::Indirect(_, Some(_)) => {
|
PassMode::Indirect { attrs: _, extra_attrs: Some(_), on_stack: _ } => {
|
||||||
OperandValue::Ref(next(), Some(next()), self.layout.align.abi).store(bx, dst);
|
OperandValue::Ref(next(), Some(next()), self.layout.align.abi).store(bx, dst);
|
||||||
}
|
}
|
||||||
PassMode::Direct(_) | PassMode::Indirect(_, None) | PassMode::Cast(_) => {
|
PassMode::Direct(_)
|
||||||
|
| PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ }
|
||||||
|
| PassMode::Cast(_) => {
|
||||||
let next_arg = next();
|
let next_arg = next();
|
||||||
self.store(bx, next_arg, dst);
|
self.store(bx, next_arg, dst);
|
||||||
}
|
}
|
||||||
@ -315,14 +329,14 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> {
|
|||||||
if let PassMode::Pair(_, _) = arg.mode { 2 } else { 1 }
|
if let PassMode::Pair(_, _) = arg.mode { 2 } else { 1 }
|
||||||
).sum();
|
).sum();
|
||||||
let mut llargument_tys = Vec::with_capacity(
|
let mut llargument_tys = Vec::with_capacity(
|
||||||
if let PassMode::Indirect(..) = self.ret.mode { 1 } else { 0 } + args_capacity,
|
if let PassMode::Indirect { .. } = self.ret.mode { 1 } else { 0 } + args_capacity,
|
||||||
);
|
);
|
||||||
|
|
||||||
let llreturn_ty = match self.ret.mode {
|
let llreturn_ty = match self.ret.mode {
|
||||||
PassMode::Ignore => cx.type_void(),
|
PassMode::Ignore => cx.type_void(),
|
||||||
PassMode::Direct(_) | PassMode::Pair(..) => self.ret.layout.immediate_llvm_type(cx),
|
PassMode::Direct(_) | PassMode::Pair(..) => self.ret.layout.immediate_llvm_type(cx),
|
||||||
PassMode::Cast(cast) => cast.llvm_type(cx),
|
PassMode::Cast(cast) => cast.llvm_type(cx),
|
||||||
PassMode::Indirect(..) => {
|
PassMode::Indirect { .. } => {
|
||||||
llargument_tys.push(cx.type_ptr_to(self.ret.memory_ty(cx)));
|
llargument_tys.push(cx.type_ptr_to(self.ret.memory_ty(cx)));
|
||||||
cx.type_void()
|
cx.type_void()
|
||||||
}
|
}
|
||||||
@ -342,7 +356,7 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> {
|
|||||||
llargument_tys.push(arg.layout.scalar_pair_element_llvm_type(cx, 1, true));
|
llargument_tys.push(arg.layout.scalar_pair_element_llvm_type(cx, 1, true));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
PassMode::Indirect(_, Some(_)) => {
|
PassMode::Indirect { attrs: _, extra_attrs: Some(_), on_stack: _ } => {
|
||||||
let ptr_ty = cx.tcx.mk_mut_ptr(arg.layout.ty);
|
let ptr_ty = cx.tcx.mk_mut_ptr(arg.layout.ty);
|
||||||
let ptr_layout = cx.layout_of(ptr_ty);
|
let ptr_layout = cx.layout_of(ptr_ty);
|
||||||
llargument_tys.push(ptr_layout.scalar_pair_element_llvm_type(cx, 0, true));
|
llargument_tys.push(ptr_layout.scalar_pair_element_llvm_type(cx, 0, true));
|
||||||
@ -350,7 +364,9 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
PassMode::Cast(cast) => cast.llvm_type(cx),
|
PassMode::Cast(cast) => cast.llvm_type(cx),
|
||||||
PassMode::Indirect(_, None) => cx.type_ptr_to(arg.memory_ty(cx)),
|
PassMode::Indirect { attrs: _, extra_attrs: None, on_stack: _ } => {
|
||||||
|
cx.type_ptr_to(arg.memory_ty(cx))
|
||||||
|
}
|
||||||
};
|
};
|
||||||
llargument_tys.push(llarg_ty);
|
llargument_tys.push(llarg_ty);
|
||||||
}
|
}
|
||||||
@ -402,35 +418,54 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
let mut apply = |attrs: &ArgAttributes, ty: Option<&Type>| {
|
let mut apply = |attrs: &ArgAttributes| {
|
||||||
attrs.apply_llfn(llvm::AttributePlace::Argument(i), llfn, ty);
|
attrs.apply_attrs_to_llfn(llvm::AttributePlace::Argument(i), llfn);
|
||||||
i += 1;
|
i += 1;
|
||||||
|
i - 1
|
||||||
};
|
};
|
||||||
match self.ret.mode {
|
match self.ret.mode {
|
||||||
PassMode::Direct(ref attrs) => {
|
PassMode::Direct(ref attrs) => {
|
||||||
attrs.apply_llfn(llvm::AttributePlace::ReturnValue, llfn, None);
|
attrs.apply_attrs_to_llfn(llvm::AttributePlace::ReturnValue, llfn);
|
||||||
|
}
|
||||||
|
PassMode::Indirect { ref attrs, extra_attrs: _, on_stack } => {
|
||||||
|
assert!(!on_stack);
|
||||||
|
let i = apply(attrs);
|
||||||
|
llvm::Attribute::StructRet.apply_llfn(llvm::AttributePlace::Argument(i), llfn);
|
||||||
}
|
}
|
||||||
PassMode::Indirect(ref attrs, _) => apply(attrs, Some(self.ret.layout.llvm_type(cx))),
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
for arg in &self.args {
|
for arg in &self.args {
|
||||||
if arg.pad.is_some() {
|
if arg.pad.is_some() {
|
||||||
apply(&ArgAttributes::new(), None);
|
apply(&ArgAttributes::new());
|
||||||
}
|
}
|
||||||
match arg.mode {
|
match arg.mode {
|
||||||
PassMode::Ignore => {}
|
PassMode::Ignore => {}
|
||||||
PassMode::Direct(ref attrs) | PassMode::Indirect(ref attrs, None) => {
|
PassMode::Indirect { ref attrs, extra_attrs: None, on_stack: true } => {
|
||||||
apply(attrs, Some(arg.layout.llvm_type(cx)))
|
let i = apply(attrs);
|
||||||
|
unsafe {
|
||||||
|
llvm::LLVMRustAddByValAttr(
|
||||||
|
llfn,
|
||||||
|
llvm::AttributePlace::Argument(i).as_uint(),
|
||||||
|
arg.layout.llvm_type(cx),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
PassMode::Indirect(ref attrs, Some(ref extra_attrs)) => {
|
}
|
||||||
apply(attrs, None);
|
PassMode::Direct(ref attrs)
|
||||||
apply(extra_attrs, None);
|
| PassMode::Indirect { ref attrs, extra_attrs: None, on_stack: false } => {
|
||||||
|
apply(attrs);
|
||||||
|
}
|
||||||
|
PassMode::Indirect { ref attrs, extra_attrs: Some(ref extra_attrs), on_stack } => {
|
||||||
|
assert!(!on_stack);
|
||||||
|
apply(attrs);
|
||||||
|
apply(extra_attrs);
|
||||||
}
|
}
|
||||||
PassMode::Pair(ref a, ref b) => {
|
PassMode::Pair(ref a, ref b) => {
|
||||||
apply(a, None);
|
apply(a);
|
||||||
apply(b, None);
|
apply(b);
|
||||||
|
}
|
||||||
|
PassMode::Cast(_) => {
|
||||||
|
apply(&ArgAttributes::new());
|
||||||
}
|
}
|
||||||
PassMode::Cast(_) => apply(&ArgAttributes::new(), None),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -439,15 +474,21 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> {
|
|||||||
// FIXME(wesleywiser, eddyb): We should apply `nounwind` and `noreturn` as appropriate to this callsite.
|
// FIXME(wesleywiser, eddyb): We should apply `nounwind` and `noreturn` as appropriate to this callsite.
|
||||||
|
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
let mut apply = |attrs: &ArgAttributes, ty: Option<&Type>| {
|
let mut apply = |attrs: &ArgAttributes| {
|
||||||
attrs.apply_callsite(llvm::AttributePlace::Argument(i), callsite, ty);
|
attrs.apply_attrs_to_callsite(llvm::AttributePlace::Argument(i), callsite);
|
||||||
i += 1;
|
i += 1;
|
||||||
|
i - 1
|
||||||
};
|
};
|
||||||
match self.ret.mode {
|
match self.ret.mode {
|
||||||
PassMode::Direct(ref attrs) => {
|
PassMode::Direct(ref attrs) => {
|
||||||
attrs.apply_callsite(llvm::AttributePlace::ReturnValue, callsite, None);
|
attrs.apply_attrs_to_callsite(llvm::AttributePlace::ReturnValue, callsite);
|
||||||
|
}
|
||||||
|
PassMode::Indirect { ref attrs, extra_attrs: _, on_stack } => {
|
||||||
|
assert!(!on_stack);
|
||||||
|
let i = apply(attrs);
|
||||||
|
llvm::Attribute::StructRet
|
||||||
|
.apply_callsite(llvm::AttributePlace::Argument(i), callsite);
|
||||||
}
|
}
|
||||||
PassMode::Indirect(ref attrs, _) => apply(attrs, Some(self.ret.layout.llvm_type(bx))),
|
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
if let abi::Abi::Scalar(ref scalar) = self.ret.layout.abi {
|
if let abi::Abi::Scalar(ref scalar) = self.ret.layout.abi {
|
||||||
@ -465,22 +506,39 @@ impl<'tcx> FnAbiLlvmExt<'tcx> for FnAbi<'tcx, Ty<'tcx>> {
|
|||||||
}
|
}
|
||||||
for arg in &self.args {
|
for arg in &self.args {
|
||||||
if arg.pad.is_some() {
|
if arg.pad.is_some() {
|
||||||
apply(&ArgAttributes::new(), None);
|
apply(&ArgAttributes::new());
|
||||||
}
|
}
|
||||||
match arg.mode {
|
match arg.mode {
|
||||||
PassMode::Ignore => {}
|
PassMode::Ignore => {}
|
||||||
PassMode::Direct(ref attrs) | PassMode::Indirect(ref attrs, None) => {
|
PassMode::Indirect { ref attrs, extra_attrs: None, on_stack: true } => {
|
||||||
apply(attrs, Some(arg.layout.llvm_type(bx)))
|
let i = apply(attrs);
|
||||||
|
unsafe {
|
||||||
|
llvm::LLVMRustAddByValCallSiteAttr(
|
||||||
|
callsite,
|
||||||
|
llvm::AttributePlace::Argument(i).as_uint(),
|
||||||
|
arg.layout.llvm_type(bx),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
PassMode::Indirect(ref attrs, Some(ref extra_attrs)) => {
|
}
|
||||||
apply(attrs, None);
|
PassMode::Direct(ref attrs)
|
||||||
apply(extra_attrs, None);
|
| PassMode::Indirect { ref attrs, extra_attrs: None, on_stack: false } => {
|
||||||
|
apply(attrs);
|
||||||
|
}
|
||||||
|
PassMode::Indirect {
|
||||||
|
ref attrs,
|
||||||
|
extra_attrs: Some(ref extra_attrs),
|
||||||
|
on_stack: _,
|
||||||
|
} => {
|
||||||
|
apply(attrs);
|
||||||
|
apply(extra_attrs);
|
||||||
}
|
}
|
||||||
PassMode::Pair(ref a, ref b) => {
|
PassMode::Pair(ref a, ref b) => {
|
||||||
apply(a, None);
|
apply(a);
|
||||||
apply(b, None);
|
apply(b);
|
||||||
|
}
|
||||||
|
PassMode::Cast(_) => {
|
||||||
|
apply(&ArgAttributes::new());
|
||||||
}
|
}
|
||||||
PassMode::Cast(_) => apply(&ArgAttributes::new(), None),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -261,6 +261,7 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
|
|||||||
InlineAsmArch::Hexagon => {}
|
InlineAsmArch::Hexagon => {}
|
||||||
InlineAsmArch::Mips | InlineAsmArch::Mips64 => {}
|
InlineAsmArch::Mips | InlineAsmArch::Mips64 => {}
|
||||||
InlineAsmArch::SpirV => {}
|
InlineAsmArch::SpirV => {}
|
||||||
|
InlineAsmArch::Wasm32 => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !options.contains(InlineAsmOptions::NOMEM) {
|
if !options.contains(InlineAsmOptions::NOMEM) {
|
||||||
@ -519,6 +520,7 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'tcx>>)
|
|||||||
| InlineAsmRegClass::X86(X86InlineAsmRegClass::ymm_reg) => "x",
|
| InlineAsmRegClass::X86(X86InlineAsmRegClass::ymm_reg) => "x",
|
||||||
InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => "v",
|
InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => "v",
|
||||||
InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => "^Yk",
|
InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => "^Yk",
|
||||||
|
InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => "r",
|
||||||
InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
|
InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
|
||||||
bug!("LLVM backend does not support SPIR-V")
|
bug!("LLVM backend does not support SPIR-V")
|
||||||
}
|
}
|
||||||
@ -584,6 +586,7 @@ fn modifier_to_llvm(
|
|||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
},
|
},
|
||||||
InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => None,
|
InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => None,
|
||||||
|
InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => None,
|
||||||
InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
|
InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
|
||||||
bug!("LLVM backend does not support SPIR-V")
|
bug!("LLVM backend does not support SPIR-V")
|
||||||
}
|
}
|
||||||
@ -626,6 +629,7 @@ fn dummy_output_type(cx: &CodegenCx<'ll, 'tcx>, reg: InlineAsmRegClass) -> &'ll
|
|||||||
| InlineAsmRegClass::X86(X86InlineAsmRegClass::ymm_reg)
|
| InlineAsmRegClass::X86(X86InlineAsmRegClass::ymm_reg)
|
||||||
| InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => cx.type_f32(),
|
| InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => cx.type_f32(),
|
||||||
InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => cx.type_i16(),
|
InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => cx.type_i16(),
|
||||||
|
InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => cx.type_i32(),
|
||||||
InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
|
InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
|
||||||
bug!("LLVM backend does not support SPIR-V")
|
bug!("LLVM backend does not support SPIR-V")
|
||||||
}
|
}
|
||||||
|
@ -35,11 +35,7 @@ fn inline(cx: &CodegenCx<'ll, '_>, val: &'ll Value, inline: InlineAttr) {
|
|||||||
Attribute::NoInline.apply_llfn(Function, val);
|
Attribute::NoInline.apply_llfn(Function, val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {}
|
||||||
Attribute::InlineHint.unapply_llfn(Function, val);
|
|
||||||
Attribute::AlwaysInline.unapply_llfn(Function, val);
|
|
||||||
Attribute::NoInline.unapply_llfn(Function, val);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,9 +127,6 @@ fn set_probestack(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME(richkadel): Make sure probestack plays nice with `-Z instrument-coverage`
|
|
||||||
// or disable it if not, similar to above early exits.
|
|
||||||
|
|
||||||
// Flag our internal `__rust_probestack` function as the stack probe symbol.
|
// Flag our internal `__rust_probestack` function as the stack probe symbol.
|
||||||
// This is defined in the `compiler-builtins` crate for each architecture.
|
// This is defined in the `compiler-builtins` crate for each architecture.
|
||||||
llvm::AddFunctionAttrStringValue(
|
llvm::AddFunctionAttrStringValue(
|
||||||
@ -144,25 +137,6 @@ fn set_probestack(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn translate_obsolete_target_features(feature: &str) -> &str {
|
|
||||||
const LLVM9_FEATURE_CHANGES: &[(&str, &str)] =
|
|
||||||
&[("+fp-only-sp", "-fp64"), ("-fp-only-sp", "+fp64"), ("+d16", "-d32"), ("-d16", "+d32")];
|
|
||||||
if llvm_util::get_major_version() >= 9 {
|
|
||||||
for &(old, new) in LLVM9_FEATURE_CHANGES {
|
|
||||||
if feature == old {
|
|
||||||
return new;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for &(old, new) in LLVM9_FEATURE_CHANGES {
|
|
||||||
if feature == new {
|
|
||||||
return old;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
feature
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn llvm_target_features(sess: &Session) -> impl Iterator<Item = &str> {
|
pub fn llvm_target_features(sess: &Session) -> impl Iterator<Item = &str> {
|
||||||
const RUSTC_SPECIFIC_FEATURES: &[&str] = &["crt-static"];
|
const RUSTC_SPECIFIC_FEATURES: &[&str] = &["crt-static"];
|
||||||
|
|
||||||
@ -172,12 +146,7 @@ pub fn llvm_target_features(sess: &Session) -> impl Iterator<Item = &str> {
|
|||||||
.target_feature
|
.target_feature
|
||||||
.split(',')
|
.split(',')
|
||||||
.filter(|f| !RUSTC_SPECIFIC_FEATURES.iter().any(|s| f.contains(s)));
|
.filter(|f| !RUSTC_SPECIFIC_FEATURES.iter().any(|s| f.contains(s)));
|
||||||
sess.target
|
sess.target.features.split(',').chain(cmdline).filter(|l| !l.is_empty())
|
||||||
.features
|
|
||||||
.split(',')
|
|
||||||
.chain(cmdline)
|
|
||||||
.filter(|l| !l.is_empty())
|
|
||||||
.map(translate_obsolete_target_features)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn apply_target_cpu_attr(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
|
pub fn apply_target_cpu_attr(cx: &CodegenCx<'ll, '_>, llfn: &'ll Value) {
|
||||||
@ -253,12 +222,14 @@ pub fn from_fn_attrs(cx: &CodegenCx<'ll, 'tcx>, llfn: &'ll Value, instance: ty::
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME(eddyb) consolidate these two `inline` calls (and avoid overwrites).
|
let inline_attr = if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
|
||||||
if instance.def.requires_inline(cx.tcx) {
|
InlineAttr::Never
|
||||||
inline(cx, llfn, attributes::InlineAttr::Hint);
|
} else if codegen_fn_attrs.inline == InlineAttr::None && instance.def.requires_inline(cx.tcx) {
|
||||||
}
|
InlineAttr::Hint
|
||||||
|
} else {
|
||||||
inline(cx, llfn, codegen_fn_attrs.inline.clone());
|
codegen_fn_attrs.inline
|
||||||
|
};
|
||||||
|
inline(cx, llfn, inline_attr);
|
||||||
|
|
||||||
// The `uwtable` attribute according to LLVM is:
|
// The `uwtable` attribute according to LLVM is:
|
||||||
//
|
//
|
||||||
|
@ -6,7 +6,9 @@ use crate::llvm::{self, build_string, False, True};
|
|||||||
use crate::{LlvmCodegenBackend, ModuleLlvm};
|
use crate::{LlvmCodegenBackend, ModuleLlvm};
|
||||||
use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule, ThinShared};
|
use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule, ThinShared};
|
||||||
use rustc_codegen_ssa::back::symbol_export;
|
use rustc_codegen_ssa::back::symbol_export;
|
||||||
use rustc_codegen_ssa::back::write::{CodegenContext, FatLTOInput, ModuleConfig};
|
use rustc_codegen_ssa::back::write::{
|
||||||
|
CodegenContext, FatLTOInput, ModuleConfig, TargetMachineFactoryConfig,
|
||||||
|
};
|
||||||
use rustc_codegen_ssa::traits::*;
|
use rustc_codegen_ssa::traits::*;
|
||||||
use rustc_codegen_ssa::{looks_like_rust_object_file, ModuleCodegen, ModuleKind};
|
use rustc_codegen_ssa::{looks_like_rust_object_file, ModuleCodegen, ModuleKind};
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
@ -728,7 +730,14 @@ pub unsafe fn optimize_thin_module(
|
|||||||
cgcx: &CodegenContext<LlvmCodegenBackend>,
|
cgcx: &CodegenContext<LlvmCodegenBackend>,
|
||||||
) -> Result<ModuleCodegen<ModuleLlvm>, FatalError> {
|
) -> Result<ModuleCodegen<ModuleLlvm>, FatalError> {
|
||||||
let diag_handler = cgcx.create_diag_handler();
|
let diag_handler = cgcx.create_diag_handler();
|
||||||
let tm = (cgcx.tm_factory.0)().map_err(|e| write::llvm_err(&diag_handler, &e))?;
|
|
||||||
|
let module_name = &thin_module.shared.module_names[thin_module.idx];
|
||||||
|
let split_dwarf_file = cgcx
|
||||||
|
.output_filenames
|
||||||
|
.split_dwarf_filename(cgcx.split_dwarf_kind, Some(module_name.to_str().unwrap()));
|
||||||
|
let tm_factory_config = TargetMachineFactoryConfig { split_dwarf_file };
|
||||||
|
let tm =
|
||||||
|
(cgcx.tm_factory)(tm_factory_config).map_err(|e| write::llvm_err(&diag_handler, &e))?;
|
||||||
|
|
||||||
// Right now the implementation we've got only works over serialized
|
// Right now the implementation we've got only works over serialized
|
||||||
// modules, so we create a fresh new LLVM context and parse the module
|
// modules, so we create a fresh new LLVM context and parse the module
|
||||||
@ -736,12 +745,8 @@ pub unsafe fn optimize_thin_module(
|
|||||||
// crates but for locally codegened modules we may be able to reuse
|
// crates but for locally codegened modules we may be able to reuse
|
||||||
// that LLVM Context and Module.
|
// that LLVM Context and Module.
|
||||||
let llcx = llvm::LLVMRustContextCreate(cgcx.fewer_names);
|
let llcx = llvm::LLVMRustContextCreate(cgcx.fewer_names);
|
||||||
let llmod_raw = parse_module(
|
let llmod_raw =
|
||||||
llcx,
|
parse_module(llcx, &module_name, thin_module.data(), &diag_handler)? as *const _;
|
||||||
&thin_module.shared.module_names[thin_module.idx],
|
|
||||||
thin_module.data(),
|
|
||||||
&diag_handler,
|
|
||||||
)? as *const _;
|
|
||||||
let module = ModuleCodegen {
|
let module = ModuleCodegen {
|
||||||
module_llvm: ModuleLlvm { llmod_raw, llcx, tm },
|
module_llvm: ModuleLlvm { llmod_raw, llcx, tm },
|
||||||
name: thin_module.name().to_string(),
|
name: thin_module.name().to_string(),
|
||||||
|
@ -11,7 +11,10 @@ use crate::llvm_util;
|
|||||||
use crate::type_::Type;
|
use crate::type_::Type;
|
||||||
use crate::LlvmCodegenBackend;
|
use crate::LlvmCodegenBackend;
|
||||||
use crate::ModuleLlvm;
|
use crate::ModuleLlvm;
|
||||||
use rustc_codegen_ssa::back::write::{BitcodeSection, CodegenContext, EmitObj, ModuleConfig};
|
use rustc_codegen_ssa::back::write::{
|
||||||
|
BitcodeSection, CodegenContext, EmitObj, ModuleConfig, TargetMachineFactoryConfig,
|
||||||
|
TargetMachineFactoryFn,
|
||||||
|
};
|
||||||
use rustc_codegen_ssa::traits::*;
|
use rustc_codegen_ssa::traits::*;
|
||||||
use rustc_codegen_ssa::{CompiledModule, ModuleCodegen};
|
use rustc_codegen_ssa::{CompiledModule, ModuleCodegen};
|
||||||
use rustc_data_structures::small_c_str::SmallCStr;
|
use rustc_data_structures::small_c_str::SmallCStr;
|
||||||
@ -20,7 +23,9 @@ use rustc_fs_util::{link_or_copy, path_to_c_string};
|
|||||||
use rustc_hir::def_id::LOCAL_CRATE;
|
use rustc_hir::def_id::LOCAL_CRATE;
|
||||||
use rustc_middle::bug;
|
use rustc_middle::bug;
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_session::config::{self, Lto, OutputType, Passes, SanitizerSet, SwitchWithOptPath};
|
use rustc_session::config::{
|
||||||
|
self, Lto, OutputType, Passes, SanitizerSet, SplitDwarfKind, SwitchWithOptPath,
|
||||||
|
};
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
use rustc_span::InnerSpan;
|
use rustc_span::InnerSpan;
|
||||||
@ -49,11 +54,31 @@ pub fn write_output_file(
|
|||||||
pm: &llvm::PassManager<'ll>,
|
pm: &llvm::PassManager<'ll>,
|
||||||
m: &'ll llvm::Module,
|
m: &'ll llvm::Module,
|
||||||
output: &Path,
|
output: &Path,
|
||||||
|
dwo_output: Option<&Path>,
|
||||||
file_type: llvm::FileType,
|
file_type: llvm::FileType,
|
||||||
) -> Result<(), FatalError> {
|
) -> Result<(), FatalError> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let output_c = path_to_c_string(output);
|
let output_c = path_to_c_string(output);
|
||||||
let result = llvm::LLVMRustWriteOutputFile(target, pm, m, output_c.as_ptr(), file_type);
|
let result = if let Some(dwo_output) = dwo_output {
|
||||||
|
let dwo_output_c = path_to_c_string(dwo_output);
|
||||||
|
llvm::LLVMRustWriteOutputFile(
|
||||||
|
target,
|
||||||
|
pm,
|
||||||
|
m,
|
||||||
|
output_c.as_ptr(),
|
||||||
|
dwo_output_c.as_ptr(),
|
||||||
|
file_type,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
llvm::LLVMRustWriteOutputFile(
|
||||||
|
target,
|
||||||
|
pm,
|
||||||
|
m,
|
||||||
|
output_c.as_ptr(),
|
||||||
|
std::ptr::null(),
|
||||||
|
file_type,
|
||||||
|
)
|
||||||
|
};
|
||||||
result.into_result().map_err(|()| {
|
result.into_result().map_err(|()| {
|
||||||
let msg = format!("could not write output to {}", output.display());
|
let msg = format!("could not write output to {}", output.display());
|
||||||
llvm_err(handler, &msg)
|
llvm_err(handler, &msg)
|
||||||
@ -62,12 +87,17 @@ pub fn write_output_file(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_informational_target_machine(sess: &Session) -> &'static mut llvm::TargetMachine {
|
pub fn create_informational_target_machine(sess: &Session) -> &'static mut llvm::TargetMachine {
|
||||||
target_machine_factory(sess, config::OptLevel::No)()
|
let config = TargetMachineFactoryConfig { split_dwarf_file: None };
|
||||||
|
target_machine_factory(sess, config::OptLevel::No)(config)
|
||||||
.unwrap_or_else(|err| llvm_err(sess.diagnostic(), &err).raise())
|
.unwrap_or_else(|err| llvm_err(sess.diagnostic(), &err).raise())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_target_machine(tcx: TyCtxt<'_>) -> &'static mut llvm::TargetMachine {
|
pub fn create_target_machine(tcx: TyCtxt<'_>, mod_name: &str) -> &'static mut llvm::TargetMachine {
|
||||||
target_machine_factory(&tcx.sess, tcx.backend_optimization_level(LOCAL_CRATE))()
|
let split_dwarf_file = tcx
|
||||||
|
.output_filenames(LOCAL_CRATE)
|
||||||
|
.split_dwarf_filename(tcx.sess.opts.debugging_opts.split_dwarf, Some(mod_name));
|
||||||
|
let config = TargetMachineFactoryConfig { split_dwarf_file };
|
||||||
|
target_machine_factory(&tcx.sess, tcx.backend_optimization_level(LOCAL_CRATE))(config)
|
||||||
.unwrap_or_else(|err| llvm_err(tcx.sess.diagnostic(), &err).raise())
|
.unwrap_or_else(|err| llvm_err(tcx.sess.diagnostic(), &err).raise())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,7 +152,7 @@ fn to_llvm_code_model(code_model: Option<CodeModel>) -> llvm::CodeModel {
|
|||||||
pub fn target_machine_factory(
|
pub fn target_machine_factory(
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
optlvl: config::OptLevel,
|
optlvl: config::OptLevel,
|
||||||
) -> Arc<dyn Fn() -> Result<&'static mut llvm::TargetMachine, String> + Send + Sync> {
|
) -> TargetMachineFactoryFn<LlvmCodegenBackend> {
|
||||||
let reloc_model = to_llvm_relocation_model(sess.relocation_model());
|
let reloc_model = to_llvm_relocation_model(sess.relocation_model());
|
||||||
|
|
||||||
let (opt_level, _) = to_llvm_opt_settings(optlvl);
|
let (opt_level, _) = to_llvm_opt_settings(optlvl);
|
||||||
@ -152,7 +182,8 @@ pub fn target_machine_factory(
|
|||||||
let features = features.join(",");
|
let features = features.join(",");
|
||||||
let features = CString::new(features).unwrap();
|
let features = CString::new(features).unwrap();
|
||||||
let abi = SmallCStr::new(&sess.target.llvm_abiname);
|
let abi = SmallCStr::new(&sess.target.llvm_abiname);
|
||||||
let trap_unreachable = sess.target.trap_unreachable;
|
let trap_unreachable =
|
||||||
|
sess.opts.debugging_opts.trap_unreachable.unwrap_or(sess.target.trap_unreachable);
|
||||||
let emit_stack_size_section = sess.opts.debugging_opts.emit_stack_sizes;
|
let emit_stack_size_section = sess.opts.debugging_opts.emit_stack_sizes;
|
||||||
|
|
||||||
let asm_comments = sess.asm_comments();
|
let asm_comments = sess.asm_comments();
|
||||||
@ -162,7 +193,10 @@ pub fn target_machine_factory(
|
|||||||
let use_init_array =
|
let use_init_array =
|
||||||
!sess.opts.debugging_opts.use_ctors_section.unwrap_or(sess.target.use_ctors_section);
|
!sess.opts.debugging_opts.use_ctors_section.unwrap_or(sess.target.use_ctors_section);
|
||||||
|
|
||||||
Arc::new(move || {
|
Arc::new(move |config: TargetMachineFactoryConfig| {
|
||||||
|
let split_dwarf_file = config.split_dwarf_file.unwrap_or_default();
|
||||||
|
let split_dwarf_file = CString::new(split_dwarf_file.to_str().unwrap()).unwrap();
|
||||||
|
|
||||||
let tm = unsafe {
|
let tm = unsafe {
|
||||||
llvm::LLVMRustCreateTargetMachine(
|
llvm::LLVMRustCreateTargetMachine(
|
||||||
triple.as_ptr(),
|
triple.as_ptr(),
|
||||||
@ -181,6 +215,7 @@ pub fn target_machine_factory(
|
|||||||
emit_stack_size_section,
|
emit_stack_size_section,
|
||||||
relax_elf_relocations,
|
relax_elf_relocations,
|
||||||
use_init_array,
|
use_init_array,
|
||||||
|
split_dwarf_file.as_ptr(),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -377,11 +412,6 @@ fn get_pgo_use_path(config: &ModuleConfig) -> Option<CString> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn should_use_new_llvm_pass_manager(config: &ModuleConfig) -> bool {
|
pub(crate) fn should_use_new_llvm_pass_manager(config: &ModuleConfig) -> bool {
|
||||||
// We only support the new pass manager starting with LLVM 9.
|
|
||||||
if llvm_util::get_major_version() < 9 {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// The new pass manager is disabled by default.
|
// The new pass manager is disabled by default.
|
||||||
config.new_llvm_pass_manager
|
config.new_llvm_pass_manager
|
||||||
}
|
}
|
||||||
@ -789,7 +819,15 @@ pub(crate) unsafe fn codegen(
|
|||||||
llmod
|
llmod
|
||||||
};
|
};
|
||||||
with_codegen(tm, llmod, config.no_builtins, |cpm| {
|
with_codegen(tm, llmod, config.no_builtins, |cpm| {
|
||||||
write_output_file(diag_handler, tm, cpm, llmod, &path, llvm::FileType::AssemblyFile)
|
write_output_file(
|
||||||
|
diag_handler,
|
||||||
|
tm,
|
||||||
|
cpm,
|
||||||
|
llmod,
|
||||||
|
&path,
|
||||||
|
None,
|
||||||
|
llvm::FileType::AssemblyFile,
|
||||||
|
)
|
||||||
})?;
|
})?;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -798,6 +836,15 @@ pub(crate) unsafe fn codegen(
|
|||||||
let _timer = cgcx
|
let _timer = cgcx
|
||||||
.prof
|
.prof
|
||||||
.generic_activity_with_arg("LLVM_module_codegen_emit_obj", &module.name[..]);
|
.generic_activity_with_arg("LLVM_module_codegen_emit_obj", &module.name[..]);
|
||||||
|
|
||||||
|
let dwo_out = cgcx.output_filenames.temp_path_dwo(module_name);
|
||||||
|
let dwo_out = match cgcx.split_dwarf_kind {
|
||||||
|
// Don't change how DWARF is emitted in single mode (or when disabled).
|
||||||
|
SplitDwarfKind::None | SplitDwarfKind::Single => None,
|
||||||
|
// Emit (a subset of the) DWARF into a separate file in split mode.
|
||||||
|
SplitDwarfKind::Split => Some(dwo_out.as_path()),
|
||||||
|
};
|
||||||
|
|
||||||
with_codegen(tm, llmod, config.no_builtins, |cpm| {
|
with_codegen(tm, llmod, config.no_builtins, |cpm| {
|
||||||
write_output_file(
|
write_output_file(
|
||||||
diag_handler,
|
diag_handler,
|
||||||
@ -805,6 +852,7 @@ pub(crate) unsafe fn codegen(
|
|||||||
cpm,
|
cpm,
|
||||||
llmod,
|
llmod,
|
||||||
&obj_out,
|
&obj_out,
|
||||||
|
dwo_out,
|
||||||
llvm::FileType::ObjectFile,
|
llvm::FileType::ObjectFile,
|
||||||
)
|
)
|
||||||
})?;
|
})?;
|
||||||
@ -832,6 +880,7 @@ pub(crate) unsafe fn codegen(
|
|||||||
|
|
||||||
Ok(module.into_compiled_module(
|
Ok(module.into_compiled_module(
|
||||||
config.emit_obj != EmitObj::None,
|
config.emit_obj != EmitObj::None,
|
||||||
|
cgcx.split_dwarf_kind == SplitDwarfKind::Split,
|
||||||
config.emit_bc,
|
config.emit_bc,
|
||||||
&cgcx.output_filenames,
|
&cgcx.output_filenames,
|
||||||
))
|
))
|
||||||
@ -925,9 +974,7 @@ unsafe fn embed_bitcode(
|
|||||||
|| cgcx.opts.target_triple.triple().starts_with("asmjs")
|
|| cgcx.opts.target_triple.triple().starts_with("asmjs")
|
||||||
{
|
{
|
||||||
// nothing to do here
|
// nothing to do here
|
||||||
} else if cgcx.opts.target_triple.triple().contains("windows")
|
} else if cgcx.is_pe_coff {
|
||||||
|| cgcx.opts.target_triple.triple().contains("uefi")
|
|
||||||
{
|
|
||||||
let asm = "
|
let asm = "
|
||||||
.section .llvmbc,\"n\"
|
.section .llvmbc,\"n\"
|
||||||
.section .llvmcmd,\"n\"
|
.section .llvmcmd,\"n\"
|
||||||
|
@ -97,14 +97,12 @@ pub fn compile_codegen_unit(
|
|||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
cgu_name: Symbol,
|
cgu_name: Symbol,
|
||||||
) -> (ModuleCodegen<ModuleLlvm>, u64) {
|
) -> (ModuleCodegen<ModuleLlvm>, u64) {
|
||||||
let prof_timer = tcx.prof.generic_activity_with_arg("codegen_module", cgu_name.to_string());
|
|
||||||
let start_time = Instant::now();
|
let start_time = Instant::now();
|
||||||
|
|
||||||
let dep_node = tcx.codegen_unit(cgu_name).codegen_dep_node(tcx);
|
let dep_node = tcx.codegen_unit(cgu_name).codegen_dep_node(tcx);
|
||||||
let (module, _) =
|
let (module, _) =
|
||||||
tcx.dep_graph.with_task(dep_node, tcx, cgu_name, module_codegen, dep_graph::hash_result);
|
tcx.dep_graph.with_task(dep_node, tcx, cgu_name, module_codegen, dep_graph::hash_result);
|
||||||
let time_to_codegen = start_time.elapsed();
|
let time_to_codegen = start_time.elapsed();
|
||||||
drop(prof_timer);
|
|
||||||
|
|
||||||
// We assume that the cost to run LLVM on a CGU is proportional to
|
// We assume that the cost to run LLVM on a CGU is proportional to
|
||||||
// the time we needed for codegenning it.
|
// the time we needed for codegenning it.
|
||||||
@ -112,6 +110,10 @@ pub fn compile_codegen_unit(
|
|||||||
|
|
||||||
fn module_codegen(tcx: TyCtxt<'_>, cgu_name: Symbol) -> ModuleCodegen<ModuleLlvm> {
|
fn module_codegen(tcx: TyCtxt<'_>, cgu_name: Symbol) -> ModuleCodegen<ModuleLlvm> {
|
||||||
let cgu = tcx.codegen_unit(cgu_name);
|
let cgu = tcx.codegen_unit(cgu_name);
|
||||||
|
let _prof_timer = tcx.prof.generic_activity_with_args(
|
||||||
|
"codegen_module",
|
||||||
|
&[cgu_name.to_string(), cgu.size_estimate().to_string()],
|
||||||
|
);
|
||||||
// Instantiate monomorphizations without filling out definitions yet...
|
// Instantiate monomorphizations without filling out definitions yet...
|
||||||
let llvm_module = ModuleLlvm::new(tcx, &cgu_name.as_str());
|
let llvm_module = ModuleLlvm::new(tcx, &cgu_name.as_str());
|
||||||
{
|
{
|
||||||
|
@ -100,11 +100,6 @@ fn to_llvm_tls_model(tls_model: TlsModel) -> llvm::ThreadLocalMode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn strip_function_ptr_alignment(data_layout: String) -> String {
|
|
||||||
// FIXME: Make this more general.
|
|
||||||
data_layout.replace("-Fi8-", "-")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn strip_x86_address_spaces(data_layout: String) -> String {
|
fn strip_x86_address_spaces(data_layout: String) -> String {
|
||||||
data_layout.replace("-p270:32:32-p271:32:32-p272:64:64-", "-")
|
data_layout.replace("-p270:32:32-p271:32:32-p272:64:64-", "-")
|
||||||
}
|
}
|
||||||
@ -119,9 +114,6 @@ pub unsafe fn create_module(
|
|||||||
let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx);
|
let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx);
|
||||||
|
|
||||||
let mut target_data_layout = sess.target.data_layout.clone();
|
let mut target_data_layout = sess.target.data_layout.clone();
|
||||||
if llvm_util::get_major_version() < 9 {
|
|
||||||
target_data_layout = strip_function_ptr_alignment(target_data_layout);
|
|
||||||
}
|
|
||||||
if llvm_util::get_major_version() < 10
|
if llvm_util::get_major_version() < 10
|
||||||
&& (sess.target.arch == "x86" || sess.target.arch == "x86_64")
|
&& (sess.target.arch == "x86" || sess.target.arch == "x86_64")
|
||||||
{
|
{
|
||||||
|
@ -3,11 +3,14 @@ use crate::coverageinfo;
|
|||||||
use crate::llvm;
|
use crate::llvm;
|
||||||
|
|
||||||
use llvm::coverageinfo::CounterMappingRegion;
|
use llvm::coverageinfo::CounterMappingRegion;
|
||||||
use rustc_codegen_ssa::coverageinfo::map::{Counter, CounterExpression};
|
use rustc_codegen_ssa::coverageinfo::map::{Counter, CounterExpression, FunctionCoverage};
|
||||||
use rustc_codegen_ssa::traits::{BaseTypeMethods, ConstMethods};
|
use rustc_codegen_ssa::traits::ConstMethods;
|
||||||
use rustc_data_structures::fx::FxIndexSet;
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
|
||||||
|
use rustc_hir::def_id::{DefId, DefIdSet, LOCAL_CRATE};
|
||||||
use rustc_llvm::RustString;
|
use rustc_llvm::RustString;
|
||||||
use rustc_middle::mir::coverage::CodeRegion;
|
use rustc_middle::mir::coverage::CodeRegion;
|
||||||
|
use rustc_middle::ty::{Instance, TyCtxt};
|
||||||
|
use rustc_span::Symbol;
|
||||||
|
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
|
|
||||||
@ -15,9 +18,9 @@ use tracing::debug;
|
|||||||
|
|
||||||
/// Generates and exports the Coverage Map.
|
/// Generates and exports the Coverage Map.
|
||||||
///
|
///
|
||||||
/// This Coverage Map complies with Coverage Mapping Format version 3 (zero-based encoded as 2),
|
/// This Coverage Map complies with Coverage Mapping Format version 4 (zero-based encoded as 3),
|
||||||
/// as defined at [LLVM Code Coverage Mapping Format](https://github.com/rust-lang/llvm-project/blob/llvmorg-8.0.0/llvm/docs/CoverageMappingFormat.rst#llvm-code-coverage-mapping-format)
|
/// as defined at [LLVM Code Coverage Mapping Format](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/docs/CoverageMappingFormat.rst#llvm-code-coverage-mapping-format)
|
||||||
/// and published in Rust's current (July 2020) fork of LLVM. This version is supported by the
|
/// and published in Rust's current (November 2020) fork of LLVM. This version is supported by the
|
||||||
/// LLVM coverage tools (`llvm-profdata` and `llvm-cov`) bundled with Rust's fork of LLVM.
|
/// LLVM coverage tools (`llvm-profdata` and `llvm-cov`) bundled with Rust's fork of LLVM.
|
||||||
///
|
///
|
||||||
/// Consequently, Rust's bundled version of Clang also generates Coverage Maps compliant with
|
/// Consequently, Rust's bundled version of Clang also generates Coverage Maps compliant with
|
||||||
@ -26,7 +29,17 @@ use tracing::debug;
|
|||||||
/// undocumented details in Clang's implementation (that may or may not be important) were also
|
/// undocumented details in Clang's implementation (that may or may not be important) were also
|
||||||
/// replicated for Rust's Coverage Map.
|
/// replicated for Rust's Coverage Map.
|
||||||
pub fn finalize<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) {
|
pub fn finalize<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) {
|
||||||
let function_coverage_map = match cx.coverage_context() {
|
let tcx = cx.tcx;
|
||||||
|
// Ensure LLVM supports Coverage Map Version 4 (encoded as a zero-based value: 3).
|
||||||
|
// If not, the LLVM Version must be less than 11.
|
||||||
|
let version = coverageinfo::mapping_version();
|
||||||
|
if version != 3 {
|
||||||
|
tcx.sess.fatal("rustc option `-Z instrument-coverage` requires LLVM 11 or higher.");
|
||||||
|
}
|
||||||
|
|
||||||
|
debug!("Generating coverage map for CodegenUnit: `{}`", cx.codegen_unit.name());
|
||||||
|
|
||||||
|
let mut function_coverage_map = match cx.coverage_context() {
|
||||||
Some(ctx) => ctx.take_function_coverage_map(),
|
Some(ctx) => ctx.take_function_coverage_map(),
|
||||||
None => return,
|
None => return,
|
||||||
};
|
};
|
||||||
@ -35,51 +48,56 @@ pub fn finalize<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
add_unreachable_coverage(tcx, &mut function_coverage_map);
|
||||||
|
|
||||||
let mut mapgen = CoverageMapGenerator::new();
|
let mut mapgen = CoverageMapGenerator::new();
|
||||||
|
|
||||||
// Encode coverage mappings and generate function records
|
// Encode coverage mappings and generate function records
|
||||||
let mut function_records = Vec::<&'ll llvm::Value>::new();
|
let mut function_data = Vec::new();
|
||||||
let coverage_mappings_buffer = llvm::build_byte_buffer(|coverage_mappings_buffer| {
|
for (instance, function_coverage) in function_coverage_map {
|
||||||
for (instance, function_coverage) in function_coverage_map.into_iter() {
|
debug!("Generate function coverage for {}, {:?}", cx.codegen_unit.name(), instance);
|
||||||
debug!("Generate coverage map for: {:?}", instance);
|
let mangled_function_name = tcx.symbol_name(instance).to_string();
|
||||||
|
|
||||||
let mangled_function_name = cx.tcx.symbol_name(instance).to_string();
|
|
||||||
let function_source_hash = function_coverage.source_hash();
|
let function_source_hash = function_coverage.source_hash();
|
||||||
let (expressions, counter_regions) =
|
let (expressions, counter_regions) =
|
||||||
function_coverage.get_expressions_and_counter_regions();
|
function_coverage.get_expressions_and_counter_regions();
|
||||||
|
|
||||||
let old_len = coverage_mappings_buffer.len();
|
let coverage_mapping_buffer = llvm::build_byte_buffer(|coverage_mapping_buffer| {
|
||||||
mapgen.write_coverage_mappings(expressions, counter_regions, coverage_mappings_buffer);
|
mapgen.write_coverage_mapping(expressions, counter_regions, coverage_mapping_buffer);
|
||||||
let mapping_data_size = coverage_mappings_buffer.len() - old_len;
|
});
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
mapping_data_size > 0,
|
coverage_mapping_buffer.len() > 0,
|
||||||
"Every `FunctionCoverage` should have at least one counter"
|
"Every `FunctionCoverage` should have at least one counter"
|
||||||
);
|
);
|
||||||
|
|
||||||
let function_record = mapgen.make_function_record(
|
function_data.push((mangled_function_name, function_source_hash, coverage_mapping_buffer));
|
||||||
cx,
|
|
||||||
mangled_function_name,
|
|
||||||
function_source_hash,
|
|
||||||
mapping_data_size,
|
|
||||||
);
|
|
||||||
function_records.push(function_record);
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
// Encode all filenames referenced by counters/expressions in this module
|
// Encode all filenames referenced by counters/expressions in this module
|
||||||
let filenames_buffer = llvm::build_byte_buffer(|filenames_buffer| {
|
let filenames_buffer = llvm::build_byte_buffer(|filenames_buffer| {
|
||||||
coverageinfo::write_filenames_section_to_buffer(&mapgen.filenames, filenames_buffer);
|
coverageinfo::write_filenames_section_to_buffer(&mapgen.filenames, filenames_buffer);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let filenames_size = filenames_buffer.len();
|
||||||
|
let filenames_val = cx.const_bytes(&filenames_buffer[..]);
|
||||||
|
let filenames_ref = coverageinfo::hash_bytes(filenames_buffer);
|
||||||
|
|
||||||
// Generate the LLVM IR representation of the coverage map and store it in a well-known global
|
// Generate the LLVM IR representation of the coverage map and store it in a well-known global
|
||||||
mapgen.save_generated_coverage_map(
|
let cov_data_val = mapgen.generate_coverage_map(cx, version, filenames_size, filenames_val);
|
||||||
|
|
||||||
|
for (mangled_function_name, function_source_hash, coverage_mapping_buffer) in function_data {
|
||||||
|
save_function_record(
|
||||||
cx,
|
cx,
|
||||||
function_records,
|
mangled_function_name,
|
||||||
filenames_buffer,
|
function_source_hash,
|
||||||
coverage_mappings_buffer,
|
filenames_ref,
|
||||||
|
coverage_mapping_buffer,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Save the coverage data value to LLVM IR
|
||||||
|
coverageinfo::save_cov_data_to_mod(cx, cov_data_val);
|
||||||
|
}
|
||||||
|
|
||||||
struct CoverageMapGenerator {
|
struct CoverageMapGenerator {
|
||||||
filenames: FxIndexSet<CString>,
|
filenames: FxIndexSet<CString>,
|
||||||
}
|
}
|
||||||
@ -92,12 +110,12 @@ impl CoverageMapGenerator {
|
|||||||
/// Using the `expressions` and `counter_regions` collected for the current function, generate
|
/// Using the `expressions` and `counter_regions` collected for the current function, generate
|
||||||
/// the `mapping_regions` and `virtual_file_mapping`, and capture any new filenames. Then use
|
/// the `mapping_regions` and `virtual_file_mapping`, and capture any new filenames. Then use
|
||||||
/// LLVM APIs to encode the `virtual_file_mapping`, `expressions`, and `mapping_regions` into
|
/// LLVM APIs to encode the `virtual_file_mapping`, `expressions`, and `mapping_regions` into
|
||||||
/// the given `coverage_mappings` byte buffer, compliant with the LLVM Coverage Mapping format.
|
/// the given `coverage_mapping` byte buffer, compliant with the LLVM Coverage Mapping format.
|
||||||
fn write_coverage_mappings(
|
fn write_coverage_mapping(
|
||||||
&mut self,
|
&mut self,
|
||||||
expressions: Vec<CounterExpression>,
|
expressions: Vec<CounterExpression>,
|
||||||
counter_regions: impl Iterator<Item = (Counter, &'a CodeRegion)>,
|
counter_regions: impl Iterator<Item = (Counter, &'a CodeRegion)>,
|
||||||
coverage_mappings_buffer: &RustString,
|
coverage_mapping_buffer: &RustString,
|
||||||
) {
|
) {
|
||||||
let mut counter_regions = counter_regions.collect::<Vec<_>>();
|
let mut counter_regions = counter_regions.collect::<Vec<_>>();
|
||||||
if counter_regions.is_empty() {
|
if counter_regions.is_empty() {
|
||||||
@ -145,89 +163,228 @@ impl CoverageMapGenerator {
|
|||||||
virtual_file_mapping,
|
virtual_file_mapping,
|
||||||
expressions,
|
expressions,
|
||||||
mapping_regions,
|
mapping_regions,
|
||||||
coverage_mappings_buffer,
|
coverage_mapping_buffer,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generate and return the function record `Value`
|
/// Construct coverage map header and the array of function records, and combine them into the
|
||||||
fn make_function_record(
|
/// coverage map. Save the coverage map data into the LLVM IR as a static global using a
|
||||||
&mut self,
|
/// specific, well-known section and name.
|
||||||
|
fn generate_coverage_map(
|
||||||
|
self,
|
||||||
|
cx: &CodegenCx<'ll, 'tcx>,
|
||||||
|
version: u32,
|
||||||
|
filenames_size: usize,
|
||||||
|
filenames_val: &'ll llvm::Value,
|
||||||
|
) -> &'ll llvm::Value {
|
||||||
|
debug!("cov map: filenames_size = {}, 0-based version = {}", filenames_size, version);
|
||||||
|
|
||||||
|
// Create the coverage data header (Note, fields 0 and 2 are now always zero,
|
||||||
|
// as of `llvm::coverage::CovMapVersion::Version4`.)
|
||||||
|
let zero_was_n_records_val = cx.const_u32(0);
|
||||||
|
let filenames_size_val = cx.const_u32(filenames_size as u32);
|
||||||
|
let zero_was_coverage_size_val = cx.const_u32(0);
|
||||||
|
let version_val = cx.const_u32(version);
|
||||||
|
let cov_data_header_val = cx.const_struct(
|
||||||
|
&[zero_was_n_records_val, filenames_size_val, zero_was_coverage_size_val, version_val],
|
||||||
|
/*packed=*/ false,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Create the complete LLVM coverage data value to add to the LLVM IR
|
||||||
|
cx.const_struct(&[cov_data_header_val, filenames_val], /*packed=*/ false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Construct a function record and combine it with the function's coverage mapping data.
|
||||||
|
/// Save the function record into the LLVM IR as a static global using a
|
||||||
|
/// specific, well-known section and name.
|
||||||
|
fn save_function_record(
|
||||||
cx: &CodegenCx<'ll, 'tcx>,
|
cx: &CodegenCx<'ll, 'tcx>,
|
||||||
mangled_function_name: String,
|
mangled_function_name: String,
|
||||||
function_source_hash: u64,
|
function_source_hash: u64,
|
||||||
mapping_data_size: usize,
|
filenames_ref: u64,
|
||||||
) -> &'ll llvm::Value {
|
coverage_mapping_buffer: Vec<u8>,
|
||||||
let name_ref = coverageinfo::compute_hash(&mangled_function_name);
|
|
||||||
let name_ref_val = cx.const_u64(name_ref);
|
|
||||||
let mapping_data_size_val = cx.const_u32(mapping_data_size as u32);
|
|
||||||
let func_hash_val = cx.const_u64(function_source_hash);
|
|
||||||
cx.const_struct(
|
|
||||||
&[name_ref_val, mapping_data_size_val, func_hash_val],
|
|
||||||
/*packed=*/ true,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Combine the filenames and coverage mappings buffers, construct coverage map header and the
|
|
||||||
/// array of function records, and combine everything into the complete coverage map. Save the
|
|
||||||
/// coverage map data into the LLVM IR as a static global using a specific, well-known section
|
|
||||||
/// and name.
|
|
||||||
fn save_generated_coverage_map(
|
|
||||||
self,
|
|
||||||
cx: &CodegenCx<'ll, 'tcx>,
|
|
||||||
function_records: Vec<&'ll llvm::Value>,
|
|
||||||
filenames_buffer: Vec<u8>,
|
|
||||||
mut coverage_mappings_buffer: Vec<u8>,
|
|
||||||
) {
|
) {
|
||||||
// Concatenate the encoded filenames and encoded coverage mappings, and add additional zero
|
// Concatenate the encoded coverage mappings
|
||||||
// bytes as-needed to ensure 8-byte alignment.
|
let coverage_mapping_size = coverage_mapping_buffer.len();
|
||||||
let mut coverage_size = coverage_mappings_buffer.len();
|
let coverage_mapping_val = cx.const_bytes(&coverage_mapping_buffer[..]);
|
||||||
let filenames_size = filenames_buffer.len();
|
|
||||||
let remaining_bytes =
|
|
||||||
(filenames_size + coverage_size) % coverageinfo::COVMAP_VAR_ALIGN_BYTES;
|
|
||||||
if remaining_bytes > 0 {
|
|
||||||
let pad = coverageinfo::COVMAP_VAR_ALIGN_BYTES - remaining_bytes;
|
|
||||||
coverage_mappings_buffer.append(&mut [0].repeat(pad));
|
|
||||||
coverage_size += pad;
|
|
||||||
}
|
|
||||||
let filenames_and_coverage_mappings = [filenames_buffer, coverage_mappings_buffer].concat();
|
|
||||||
let filenames_and_coverage_mappings_val =
|
|
||||||
cx.const_bytes(&filenames_and_coverage_mappings[..]);
|
|
||||||
|
|
||||||
debug!(
|
let func_name_hash = coverageinfo::hash_str(&mangled_function_name);
|
||||||
"cov map: n_records = {}, filenames_size = {}, coverage_size = {}, 0-based version = {}",
|
let func_name_hash_val = cx.const_u64(func_name_hash);
|
||||||
function_records.len(),
|
let coverage_mapping_size_val = cx.const_u32(coverage_mapping_size as u32);
|
||||||
filenames_size,
|
let func_hash_val = cx.const_u64(function_source_hash);
|
||||||
coverage_size,
|
let filenames_ref_val = cx.const_u64(filenames_ref);
|
||||||
coverageinfo::mapping_version()
|
let func_record_val = cx.const_struct(
|
||||||
);
|
&[
|
||||||
|
func_name_hash_val,
|
||||||
// Create the coverage data header
|
coverage_mapping_size_val,
|
||||||
let n_records_val = cx.const_u32(function_records.len() as u32);
|
func_hash_val,
|
||||||
let filenames_size_val = cx.const_u32(filenames_size as u32);
|
filenames_ref_val,
|
||||||
let coverage_size_val = cx.const_u32(coverage_size as u32);
|
coverage_mapping_val,
|
||||||
let version_val = cx.const_u32(coverageinfo::mapping_version());
|
],
|
||||||
let cov_data_header_val = cx.const_struct(
|
|
||||||
&[n_records_val, filenames_size_val, coverage_size_val, version_val],
|
|
||||||
/*packed=*/ false,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Create the function records array
|
|
||||||
let name_ref_from_u64 = cx.type_i64();
|
|
||||||
let mapping_data_size_from_u32 = cx.type_i32();
|
|
||||||
let func_hash_from_u64 = cx.type_i64();
|
|
||||||
let function_record_ty = cx.type_struct(
|
|
||||||
&[name_ref_from_u64, mapping_data_size_from_u32, func_hash_from_u64],
|
|
||||||
/*packed=*/ true,
|
/*packed=*/ true,
|
||||||
);
|
);
|
||||||
let function_records_val = cx.const_array(function_record_ty, &function_records[..]);
|
|
||||||
|
|
||||||
// Create the complete LLVM coverage data value to add to the LLVM IR
|
// At the present time, the coverage map for Rust assumes every instrumented function `is_used`.
|
||||||
let cov_data_val = cx.const_struct(
|
// Note that Clang marks functions as "unused" in `CodeGenPGO::emitEmptyCounterMapping`. (See:
|
||||||
&[cov_data_header_val, function_records_val, filenames_and_coverage_mappings_val],
|
// https://github.com/rust-lang/llvm-project/blob/de02a75e398415bad4df27b4547c25b896c8bf3b/clang%2Flib%2FCodeGen%2FCodeGenPGO.cpp#L877-L878
|
||||||
/*packed=*/ false,
|
// for example.)
|
||||||
);
|
//
|
||||||
|
// It's not yet clear if or how this may be applied to Rust in the future, but the `is_used`
|
||||||
|
// argument is available and handled similarly.
|
||||||
|
let is_used = true;
|
||||||
|
coverageinfo::save_func_record_to_mod(cx, func_name_hash, func_record_val, is_used);
|
||||||
|
}
|
||||||
|
|
||||||
// Save the coverage data value to LLVM IR
|
/// When finalizing the coverage map, `FunctionCoverage` only has the `CodeRegion`s and counters for
|
||||||
coverageinfo::save_map_to_mod(cx, cov_data_val);
|
/// the functions that went through codegen; such as public functions and "used" functions
|
||||||
|
/// (functions referenced by other "used" or public items). Any other functions considered unused,
|
||||||
|
/// or "Unreachable" were still parsed and processed through the MIR stage.
|
||||||
|
///
|
||||||
|
/// We can find the unreachable functions by the set difference of all MIR `DefId`s (`tcx` query
|
||||||
|
/// `mir_keys`) minus the codegenned `DefId`s (`tcx` query `collect_and_partition_mono_items`).
|
||||||
|
///
|
||||||
|
/// *HOWEVER* the codegenned `DefId`s are partitioned across multiple `CodegenUnit`s (CGUs), and
|
||||||
|
/// this function is processing a `function_coverage_map` for the functions (`Instance`/`DefId`)
|
||||||
|
/// allocated to only one of those CGUs. We must NOT inject any "Unreachable" functions's
|
||||||
|
/// `CodeRegion`s more than once, so we have to pick which CGU's `function_coverage_map` to add
|
||||||
|
/// each "Unreachable" function to.
|
||||||
|
///
|
||||||
|
/// Some constraints:
|
||||||
|
///
|
||||||
|
/// 1. The file name of an "Unreachable" function must match the file name of the existing
|
||||||
|
/// codegenned (covered) function to which the unreachable code regions will be added.
|
||||||
|
/// 2. The function to which the unreachable code regions will be added must not be a genaric
|
||||||
|
/// function (must not have type parameters) because the coverage tools will get confused
|
||||||
|
/// if the codegenned function has more than one instantiation and additional `CodeRegion`s
|
||||||
|
/// attached to only one of those instantiations.
|
||||||
|
fn add_unreachable_coverage<'tcx>(
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
function_coverage_map: &mut FxHashMap<Instance<'tcx>, FunctionCoverage<'tcx>>,
|
||||||
|
) {
|
||||||
|
// FIXME(#79622): Can this solution be simplified and/or improved? Are there other sources
|
||||||
|
// of compiler state data that might help (or better sources that could be exposed, but
|
||||||
|
// aren't yet)?
|
||||||
|
|
||||||
|
// Note: If the crate *only* defines generic functions, there are no codegenerated non-generic
|
||||||
|
// functions to add any unreachable code to. In this case, the unreachable code regions will
|
||||||
|
// have no coverage, instead of having coverage with zero executions.
|
||||||
|
//
|
||||||
|
// This is probably still an improvement over Clang, which does not generate any coverage
|
||||||
|
// for uninstantiated template functions.
|
||||||
|
|
||||||
|
let has_non_generic_def_ids =
|
||||||
|
function_coverage_map.keys().any(|instance| instance.def.attrs(tcx).len() == 0);
|
||||||
|
|
||||||
|
if !has_non_generic_def_ids {
|
||||||
|
// There are no non-generic functions to add unreachable `CodeRegion`s to
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let all_def_ids: DefIdSet =
|
||||||
|
tcx.mir_keys(LOCAL_CRATE).iter().map(|local_def_id| local_def_id.to_def_id()).collect();
|
||||||
|
|
||||||
|
let (codegenned_def_ids, _) = tcx.collect_and_partition_mono_items(LOCAL_CRATE);
|
||||||
|
|
||||||
|
let mut unreachable_def_ids_by_file: FxHashMap<Symbol, Vec<DefId>> = FxHashMap::default();
|
||||||
|
for &non_codegenned_def_id in all_def_ids.difference(codegenned_def_ids) {
|
||||||
|
// Make sure the non-codegenned (unreachable) function has a file_name
|
||||||
|
if let Some(non_codegenned_file_name) = tcx.covered_file_name(non_codegenned_def_id) {
|
||||||
|
let def_ids = unreachable_def_ids_by_file
|
||||||
|
.entry(*non_codegenned_file_name)
|
||||||
|
.or_insert_with(|| Vec::new());
|
||||||
|
def_ids.push(non_codegenned_def_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if unreachable_def_ids_by_file.is_empty() {
|
||||||
|
// There are no unreachable functions with file names to add (in any CGU)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Since there may be multiple `CodegenUnit`s, some codegenned_def_ids may be codegenned in a
|
||||||
|
// different CGU, and will be added to the function_coverage_map for each CGU. Determine which
|
||||||
|
// function_coverage_map has the responsibility for publishing unreachable coverage
|
||||||
|
// based on file name:
|
||||||
|
//
|
||||||
|
// For each covered file name, sort ONLY the non-generic codegenned_def_ids, and if
|
||||||
|
// covered_def_ids.contains(the first def_id) for a given file_name, add the unreachable code
|
||||||
|
// region in this function_coverage_map. Otherwise, ignore it and assume another CGU's
|
||||||
|
// function_coverage_map will be adding it (because it will be first for one, and only one,
|
||||||
|
// of them).
|
||||||
|
let mut sorted_codegenned_def_ids: Vec<DefId> =
|
||||||
|
codegenned_def_ids.iter().map(|def_id| *def_id).collect();
|
||||||
|
sorted_codegenned_def_ids.sort_unstable();
|
||||||
|
|
||||||
|
let mut first_covered_def_id_by_file: FxHashMap<Symbol, DefId> = FxHashMap::default();
|
||||||
|
for &def_id in sorted_codegenned_def_ids.iter() {
|
||||||
|
// Only consider non-generic functions, to potentially add unreachable code regions
|
||||||
|
if tcx.generics_of(def_id).count() == 0 {
|
||||||
|
if let Some(covered_file_name) = tcx.covered_file_name(def_id) {
|
||||||
|
// Only add files known to have unreachable functions
|
||||||
|
if unreachable_def_ids_by_file.contains_key(covered_file_name) {
|
||||||
|
first_covered_def_id_by_file.entry(*covered_file_name).or_insert(def_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the set of def_ids with coverage regions, known by *this* CoverageContext.
|
||||||
|
let cgu_covered_def_ids: DefIdSet =
|
||||||
|
function_coverage_map.keys().map(|instance| instance.def.def_id()).collect();
|
||||||
|
|
||||||
|
let mut cgu_covered_files: FxHashSet<Symbol> = first_covered_def_id_by_file
|
||||||
|
.iter()
|
||||||
|
.filter_map(
|
||||||
|
|(&file_name, def_id)| {
|
||||||
|
if cgu_covered_def_ids.contains(def_id) { Some(file_name) } else { None }
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
// Find the first covered, non-generic function (instance) for each cgu_covered_file. Take the
|
||||||
|
// unreachable code regions for that file, and add them to the function.
|
||||||
|
//
|
||||||
|
// There are three `for` loops here, but (a) the lists have already been reduced to the minimum
|
||||||
|
// required values, the lists are further reduced (by `remove()` calls) when elements are no
|
||||||
|
// longer needed, and there are several opportunities to branch out of loops early.
|
||||||
|
for (instance, function_coverage) in function_coverage_map.iter_mut() {
|
||||||
|
if instance.def.attrs(tcx).len() > 0 {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// The covered function is not generic...
|
||||||
|
let covered_def_id = instance.def.def_id();
|
||||||
|
if let Some(covered_file_name) = tcx.covered_file_name(covered_def_id) {
|
||||||
|
if !cgu_covered_files.remove(&covered_file_name) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// The covered function's file is one of the files with unreachable code regions, so
|
||||||
|
// all of the unreachable code regions for this file will be added to this function.
|
||||||
|
for def_id in
|
||||||
|
unreachable_def_ids_by_file.remove(&covered_file_name).into_iter().flatten()
|
||||||
|
{
|
||||||
|
// Note, this loop adds an unreachable code regions for each MIR-derived region.
|
||||||
|
// Alternatively, we could add a single code region for the maximum span of all
|
||||||
|
// code regions here.
|
||||||
|
//
|
||||||
|
// Observed downsides of this approach are:
|
||||||
|
//
|
||||||
|
// 1. The coverage results will appear inconsistent compared with the same (or
|
||||||
|
// similar) code in a function that is reached.
|
||||||
|
// 2. If the function is unreachable from one crate but reachable when compiling
|
||||||
|
// another referencing crate (such as a cross-crate reference to a
|
||||||
|
// generic function or inlined function), actual coverage regions overlaid
|
||||||
|
// on a single larger code span of `Zero` coverage can appear confusing or
|
||||||
|
// wrong. Chaning the unreachable coverage from a `code_region` to a
|
||||||
|
// `gap_region` can help, but still can look odd with `0` line counts for
|
||||||
|
// lines between executed (> 0) lines (such as for blank lines or comments).
|
||||||
|
for ®ion in tcx.covered_code_regions(def_id) {
|
||||||
|
function_coverage.add_unreachable_region(region.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if cgu_covered_files.is_empty() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ use tracing::debug;
|
|||||||
|
|
||||||
pub mod mapgen;
|
pub mod mapgen;
|
||||||
|
|
||||||
const COVMAP_VAR_ALIGN_BYTES: usize = 8;
|
const VAR_ALIGN_BYTES: usize = 8;
|
||||||
|
|
||||||
/// A context object for maintaining all state needed by the coverageinfo module.
|
/// A context object for maintaining all state needed by the coverageinfo module.
|
||||||
pub struct CrateCoverageContext<'tcx> {
|
pub struct CrateCoverageContext<'tcx> {
|
||||||
@ -177,17 +177,20 @@ pub(crate) fn write_mapping_to_buffer(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub(crate) fn hash_str(strval: &str) -> u64 {
|
||||||
|
let strval = CString::new(strval).expect("null error converting hashable str to C string");
|
||||||
|
unsafe { llvm::LLVMRustCoverageHashCString(strval.as_ptr()) }
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn compute_hash(name: &str) -> u64 {
|
pub(crate) fn hash_bytes(bytes: Vec<u8>) -> u64 {
|
||||||
let name = CString::new(name).expect("null error converting hashable name to C string");
|
unsafe { llvm::LLVMRustCoverageHashByteArray(bytes.as_ptr().cast(), bytes.len()) }
|
||||||
unsafe { llvm::LLVMRustCoverageComputeHash(name.as_ptr()) }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn mapping_version() -> u32 {
|
pub(crate) fn mapping_version() -> u32 {
|
||||||
unsafe { llvm::LLVMRustCoverageMappingVersion() }
|
unsafe { llvm::LLVMRustCoverageMappingVersion() }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn save_map_to_mod<'ll, 'tcx>(
|
pub(crate) fn save_cov_data_to_mod<'ll, 'tcx>(
|
||||||
cx: &CodegenCx<'ll, 'tcx>,
|
cx: &CodegenCx<'ll, 'tcx>,
|
||||||
cov_data_val: &'ll llvm::Value,
|
cov_data_val: &'ll llvm::Value,
|
||||||
) {
|
) {
|
||||||
@ -198,7 +201,7 @@ pub(crate) fn save_map_to_mod<'ll, 'tcx>(
|
|||||||
debug!("covmap var name: {:?}", covmap_var_name);
|
debug!("covmap var name: {:?}", covmap_var_name);
|
||||||
|
|
||||||
let covmap_section_name = llvm::build_string(|s| unsafe {
|
let covmap_section_name = llvm::build_string(|s| unsafe {
|
||||||
llvm::LLVMRustCoverageWriteSectionNameToString(cx.llmod, s);
|
llvm::LLVMRustCoverageWriteMapSectionNameToString(cx.llmod, s);
|
||||||
})
|
})
|
||||||
.expect("Rust Coverage section name failed UTF-8 conversion");
|
.expect("Rust Coverage section name failed UTF-8 conversion");
|
||||||
debug!("covmap section name: {:?}", covmap_section_name);
|
debug!("covmap section name: {:?}", covmap_section_name);
|
||||||
@ -206,8 +209,43 @@ pub(crate) fn save_map_to_mod<'ll, 'tcx>(
|
|||||||
let llglobal = llvm::add_global(cx.llmod, cx.val_ty(cov_data_val), &covmap_var_name);
|
let llglobal = llvm::add_global(cx.llmod, cx.val_ty(cov_data_val), &covmap_var_name);
|
||||||
llvm::set_initializer(llglobal, cov_data_val);
|
llvm::set_initializer(llglobal, cov_data_val);
|
||||||
llvm::set_global_constant(llglobal, true);
|
llvm::set_global_constant(llglobal, true);
|
||||||
llvm::set_linkage(llglobal, llvm::Linkage::InternalLinkage);
|
llvm::set_linkage(llglobal, llvm::Linkage::PrivateLinkage);
|
||||||
llvm::set_section(llglobal, &covmap_section_name);
|
llvm::set_section(llglobal, &covmap_section_name);
|
||||||
llvm::set_alignment(llglobal, COVMAP_VAR_ALIGN_BYTES);
|
llvm::set_alignment(llglobal, VAR_ALIGN_BYTES);
|
||||||
|
cx.add_used_global(llglobal);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn save_func_record_to_mod<'ll, 'tcx>(
|
||||||
|
cx: &CodegenCx<'ll, 'tcx>,
|
||||||
|
func_name_hash: u64,
|
||||||
|
func_record_val: &'ll llvm::Value,
|
||||||
|
is_used: bool,
|
||||||
|
) {
|
||||||
|
// Assign a name to the function record. This is used to merge duplicates.
|
||||||
|
//
|
||||||
|
// In LLVM, a "translation unit" (effectively, a `Crate` in Rust) can describe functions that
|
||||||
|
// are included-but-not-used. If (or when) Rust generates functions that are
|
||||||
|
// included-but-not-used, note that a dummy description for a function included-but-not-used
|
||||||
|
// in a Crate can be replaced by full description provided by a different Crate. The two kinds
|
||||||
|
// of descriptions play distinct roles in LLVM IR; therefore, assign them different names (by
|
||||||
|
// appending "u" to the end of the function record var name, to prevent `linkonce_odr` merging.
|
||||||
|
let func_record_var_name =
|
||||||
|
format!("__covrec_{:X}{}", func_name_hash, if is_used { "u" } else { "" });
|
||||||
|
debug!("function record var name: {:?}", func_record_var_name);
|
||||||
|
|
||||||
|
let func_record_section_name = llvm::build_string(|s| unsafe {
|
||||||
|
llvm::LLVMRustCoverageWriteFuncSectionNameToString(cx.llmod, s);
|
||||||
|
})
|
||||||
|
.expect("Rust Coverage function record section name failed UTF-8 conversion");
|
||||||
|
debug!("function record section name: {:?}", func_record_section_name);
|
||||||
|
|
||||||
|
let llglobal = llvm::add_global(cx.llmod, cx.val_ty(func_record_val), &func_record_var_name);
|
||||||
|
llvm::set_initializer(llglobal, func_record_val);
|
||||||
|
llvm::set_global_constant(llglobal, true);
|
||||||
|
llvm::set_linkage(llglobal, llvm::Linkage::LinkOnceODRLinkage);
|
||||||
|
llvm::set_visibility(llglobal, llvm::Visibility::Hidden);
|
||||||
|
llvm::set_section(llglobal, &func_record_section_name);
|
||||||
|
llvm::set_alignment(llglobal, VAR_ALIGN_BYTES);
|
||||||
|
llvm::set_comdat(cx.llmod, llglobal, &func_record_var_name);
|
||||||
cx.add_used_global(llglobal);
|
cx.add_used_global(llglobal);
|
||||||
}
|
}
|
||||||
|
@ -92,7 +92,7 @@ fn make_mir_scope(
|
|||||||
let callee = cx.tcx.subst_and_normalize_erasing_regions(
|
let callee = cx.tcx.subst_and_normalize_erasing_regions(
|
||||||
instance.substs,
|
instance.substs,
|
||||||
ty::ParamEnv::reveal_all(),
|
ty::ParamEnv::reveal_all(),
|
||||||
&callee,
|
callee,
|
||||||
);
|
);
|
||||||
let callee_fn_abi = FnAbi::of_instance(cx, callee, &[]);
|
let callee_fn_abi = FnAbi::of_instance(cx, callee, &[]);
|
||||||
cx.dbg_scope_fn(callee, &callee_fn_abi, None)
|
cx.dbg_scope_fn(callee, &callee_fn_abi, None)
|
||||||
|
@ -189,7 +189,7 @@ impl TypeMap<'ll, 'tcx> {
|
|||||||
// something that provides more than the 64 bits of the DefaultHasher.
|
// something that provides more than the 64 bits of the DefaultHasher.
|
||||||
let mut hasher = StableHasher::new();
|
let mut hasher = StableHasher::new();
|
||||||
let mut hcx = cx.tcx.create_stable_hashing_context();
|
let mut hcx = cx.tcx.create_stable_hashing_context();
|
||||||
let type_ = cx.tcx.erase_regions(&type_);
|
let type_ = cx.tcx.erase_regions(type_);
|
||||||
hcx.while_hashing_spans(false, |hcx| {
|
hcx.while_hashing_spans(false, |hcx| {
|
||||||
hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
|
hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
|
||||||
type_.hash_stable(hcx, &mut hasher);
|
type_.hash_stable(hcx, &mut hasher);
|
||||||
@ -427,7 +427,7 @@ fn subroutine_type_metadata(
|
|||||||
span: Span,
|
span: Span,
|
||||||
) -> MetadataCreationResult<'ll> {
|
) -> MetadataCreationResult<'ll> {
|
||||||
let signature =
|
let signature =
|
||||||
cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &signature);
|
cx.tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), signature);
|
||||||
|
|
||||||
let signature_metadata: Vec<_> = iter::once(
|
let signature_metadata: Vec<_> = iter::once(
|
||||||
// return type
|
// return type
|
||||||
@ -993,9 +993,15 @@ pub fn compile_unit_metadata(
|
|||||||
let producer = format!("clang LLVM ({})", rustc_producer);
|
let producer = format!("clang LLVM ({})", rustc_producer);
|
||||||
|
|
||||||
let name_in_debuginfo = name_in_debuginfo.to_string_lossy();
|
let name_in_debuginfo = name_in_debuginfo.to_string_lossy();
|
||||||
let work_dir = tcx.sess.working_dir.0.to_string_lossy();
|
|
||||||
let flags = "\0";
|
let flags = "\0";
|
||||||
let split_name = "";
|
|
||||||
|
let out_dir = &tcx.output_filenames(LOCAL_CRATE).out_directory;
|
||||||
|
let split_name = tcx
|
||||||
|
.output_filenames(LOCAL_CRATE)
|
||||||
|
.split_dwarf_filename(tcx.sess.opts.debugging_opts.split_dwarf, Some(codegen_unit_name))
|
||||||
|
.unwrap_or_default();
|
||||||
|
let out_dir = out_dir.to_str().unwrap();
|
||||||
|
let split_name = split_name.to_str().unwrap();
|
||||||
|
|
||||||
// FIXME(#60020):
|
// FIXME(#60020):
|
||||||
//
|
//
|
||||||
@ -1020,8 +1026,8 @@ pub fn compile_unit_metadata(
|
|||||||
debug_context.builder,
|
debug_context.builder,
|
||||||
name_in_debuginfo.as_ptr().cast(),
|
name_in_debuginfo.as_ptr().cast(),
|
||||||
name_in_debuginfo.len(),
|
name_in_debuginfo.len(),
|
||||||
work_dir.as_ptr().cast(),
|
out_dir.as_ptr().cast(),
|
||||||
work_dir.len(),
|
out_dir.len(),
|
||||||
llvm::ChecksumKind::None,
|
llvm::ChecksumKind::None,
|
||||||
ptr::null(),
|
ptr::null(),
|
||||||
0,
|
0,
|
||||||
@ -1039,6 +1045,8 @@ pub fn compile_unit_metadata(
|
|||||||
split_name.as_ptr().cast(),
|
split_name.as_ptr().cast(),
|
||||||
split_name.len(),
|
split_name.len(),
|
||||||
kind,
|
kind,
|
||||||
|
0,
|
||||||
|
tcx.sess.opts.debugging_opts.split_dwarf_inlining,
|
||||||
);
|
);
|
||||||
|
|
||||||
if tcx.sess.opts.debugging_opts.profile {
|
if tcx.sess.opts.debugging_opts.profile {
|
||||||
@ -1152,10 +1160,7 @@ impl<'ll> MemberDescription<'ll> {
|
|||||||
self.size.bits(),
|
self.size.bits(),
|
||||||
self.align.bits() as u32,
|
self.align.bits() as u32,
|
||||||
self.offset.bits(),
|
self.offset.bits(),
|
||||||
match self.discriminant {
|
self.discriminant.map(|v| cx.const_u64(v)),
|
||||||
None => None,
|
|
||||||
Some(value) => Some(cx.const_u64(value)),
|
|
||||||
},
|
|
||||||
self.flags,
|
self.flags,
|
||||||
self.type_metadata,
|
self.type_metadata,
|
||||||
)
|
)
|
||||||
@ -1412,10 +1417,11 @@ fn generator_layout_and_saved_local_names(
|
|||||||
|
|
||||||
let state_arg = mir::Local::new(1);
|
let state_arg = mir::Local::new(1);
|
||||||
for var in &body.var_debug_info {
|
for var in &body.var_debug_info {
|
||||||
if var.place.local != state_arg {
|
let place = if let mir::VarDebugInfoContents::Place(p) = var.value { p } else { continue };
|
||||||
|
if place.local != state_arg {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
match var.place.projection[..] {
|
match place.projection[..] {
|
||||||
[
|
[
|
||||||
// Deref of the `Pin<&mut Self>` state argument.
|
// Deref of the `Pin<&mut Self>` state argument.
|
||||||
mir::ProjectionElem::Field(..),
|
mir::ProjectionElem::Field(..),
|
||||||
|
@ -501,7 +501,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
|||||||
let impl_self_ty = cx.tcx.subst_and_normalize_erasing_regions(
|
let impl_self_ty = cx.tcx.subst_and_normalize_erasing_regions(
|
||||||
instance.substs,
|
instance.substs,
|
||||||
ty::ParamEnv::reveal_all(),
|
ty::ParamEnv::reveal_all(),
|
||||||
&cx.tcx.type_of(impl_def_id),
|
cx.tcx.type_of(impl_def_id),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Only "class" methods are generally understood by LLVM,
|
// Only "class" methods are generally understood by LLVM,
|
||||||
|
@ -91,7 +91,7 @@ impl IntrinsicCallMethods<'tcx> for Builder<'a, 'll, 'tcx> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let sig = callee_ty.fn_sig(tcx);
|
let sig = callee_ty.fn_sig(tcx);
|
||||||
let sig = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
|
let sig = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), sig);
|
||||||
let arg_tys = sig.inputs();
|
let arg_tys = sig.inputs();
|
||||||
let ret_ty = sig.output();
|
let ret_ty = sig.output();
|
||||||
let name = tcx.item_name(def_id);
|
let name = tcx.item_name(def_id);
|
||||||
@ -777,8 +777,8 @@ fn generic_simd_intrinsic(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let tcx = bx.tcx();
|
let tcx = bx.tcx();
|
||||||
let sig = tcx
|
let sig =
|
||||||
.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &callee_ty.fn_sig(tcx));
|
tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), callee_ty.fn_sig(tcx));
|
||||||
let arg_tys = sig.inputs();
|
let arg_tys = sig.inputs();
|
||||||
let name_str = &*name.as_str();
|
let name_str = &*name.as_str();
|
||||||
|
|
||||||
@ -792,7 +792,7 @@ fn generic_simd_intrinsic(
|
|||||||
_ => return_error!("`{}` is not an integral type", in_ty),
|
_ => return_error!("`{}` is not an integral type", in_ty),
|
||||||
};
|
};
|
||||||
require_simd!(arg_tys[1], "argument");
|
require_simd!(arg_tys[1], "argument");
|
||||||
let v_len = arg_tys[1].simd_size(tcx);
|
let (v_len, _) = arg_tys[1].simd_size_and_type(bx.tcx());
|
||||||
require!(
|
require!(
|
||||||
// Allow masks for vectors with fewer than 8 elements to be
|
// Allow masks for vectors with fewer than 8 elements to be
|
||||||
// represented with a u8 or i8.
|
// represented with a u8 or i8.
|
||||||
@ -812,8 +812,6 @@ fn generic_simd_intrinsic(
|
|||||||
// every intrinsic below takes a SIMD vector as its first argument
|
// every intrinsic below takes a SIMD vector as its first argument
|
||||||
require_simd!(arg_tys[0], "input");
|
require_simd!(arg_tys[0], "input");
|
||||||
let in_ty = arg_tys[0];
|
let in_ty = arg_tys[0];
|
||||||
let in_elem = arg_tys[0].simd_type(tcx);
|
|
||||||
let in_len = arg_tys[0].simd_size(tcx);
|
|
||||||
|
|
||||||
let comparison = match name {
|
let comparison = match name {
|
||||||
sym::simd_eq => Some(hir::BinOpKind::Eq),
|
sym::simd_eq => Some(hir::BinOpKind::Eq),
|
||||||
@ -825,10 +823,11 @@ fn generic_simd_intrinsic(
|
|||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let (in_len, in_elem) = arg_tys[0].simd_size_and_type(bx.tcx());
|
||||||
if let Some(cmp_op) = comparison {
|
if let Some(cmp_op) = comparison {
|
||||||
require_simd!(ret_ty, "return");
|
require_simd!(ret_ty, "return");
|
||||||
|
|
||||||
let out_len = ret_ty.simd_size(tcx);
|
let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx());
|
||||||
require!(
|
require!(
|
||||||
in_len == out_len,
|
in_len == out_len,
|
||||||
"expected return type with length {} (same as input type `{}`), \
|
"expected return type with length {} (same as input type `{}`), \
|
||||||
@ -842,7 +841,7 @@ fn generic_simd_intrinsic(
|
|||||||
bx.type_kind(bx.element_type(llret_ty)) == TypeKind::Integer,
|
bx.type_kind(bx.element_type(llret_ty)) == TypeKind::Integer,
|
||||||
"expected return type with integer elements, found `{}` with non-integer `{}`",
|
"expected return type with integer elements, found `{}` with non-integer `{}`",
|
||||||
ret_ty,
|
ret_ty,
|
||||||
ret_ty.simd_type(tcx)
|
out_ty
|
||||||
);
|
);
|
||||||
|
|
||||||
return Ok(compare_simd_types(
|
return Ok(compare_simd_types(
|
||||||
@ -855,14 +854,14 @@ fn generic_simd_intrinsic(
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
if name_str.starts_with("simd_shuffle") {
|
if let Some(stripped) = name_str.strip_prefix("simd_shuffle") {
|
||||||
let n: u64 = name_str["simd_shuffle".len()..].parse().unwrap_or_else(|_| {
|
let n: u64 = stripped.parse().unwrap_or_else(|_| {
|
||||||
span_bug!(span, "bad `simd_shuffle` instruction only caught in codegen?")
|
span_bug!(span, "bad `simd_shuffle` instruction only caught in codegen?")
|
||||||
});
|
});
|
||||||
|
|
||||||
require_simd!(ret_ty, "return");
|
require_simd!(ret_ty, "return");
|
||||||
|
|
||||||
let out_len = ret_ty.simd_size(tcx);
|
let (out_len, out_ty) = ret_ty.simd_size_and_type(bx.tcx());
|
||||||
require!(
|
require!(
|
||||||
out_len == n,
|
out_len == n,
|
||||||
"expected return type of length {}, found `{}` with length {}",
|
"expected return type of length {}, found `{}` with length {}",
|
||||||
@ -871,13 +870,13 @@ fn generic_simd_intrinsic(
|
|||||||
out_len
|
out_len
|
||||||
);
|
);
|
||||||
require!(
|
require!(
|
||||||
in_elem == ret_ty.simd_type(tcx),
|
in_elem == out_ty,
|
||||||
"expected return element type `{}` (element of input `{}`), \
|
"expected return element type `{}` (element of input `{}`), \
|
||||||
found `{}` with element type `{}`",
|
found `{}` with element type `{}`",
|
||||||
in_elem,
|
in_elem,
|
||||||
in_ty,
|
in_ty,
|
||||||
ret_ty,
|
ret_ty,
|
||||||
ret_ty.simd_type(tcx)
|
out_ty
|
||||||
);
|
);
|
||||||
|
|
||||||
let total_len = u128::from(in_len) * 2;
|
let total_len = u128::from(in_len) * 2;
|
||||||
@ -946,7 +945,7 @@ fn generic_simd_intrinsic(
|
|||||||
let m_elem_ty = in_elem;
|
let m_elem_ty = in_elem;
|
||||||
let m_len = in_len;
|
let m_len = in_len;
|
||||||
require_simd!(arg_tys[1], "argument");
|
require_simd!(arg_tys[1], "argument");
|
||||||
let v_len = arg_tys[1].simd_size(tcx);
|
let (v_len, _) = arg_tys[1].simd_size_and_type(bx.tcx());
|
||||||
require!(
|
require!(
|
||||||
m_len == v_len,
|
m_len == v_len,
|
||||||
"mismatched lengths: mask length `{}` != other vector length `{}`",
|
"mismatched lengths: mask length `{}` != other vector length `{}`",
|
||||||
@ -1173,25 +1172,27 @@ fn generic_simd_intrinsic(
|
|||||||
require_simd!(ret_ty, "return");
|
require_simd!(ret_ty, "return");
|
||||||
|
|
||||||
// Of the same length:
|
// Of the same length:
|
||||||
|
let (out_len, _) = arg_tys[1].simd_size_and_type(bx.tcx());
|
||||||
|
let (out_len2, _) = arg_tys[2].simd_size_and_type(bx.tcx());
|
||||||
require!(
|
require!(
|
||||||
in_len == arg_tys[1].simd_size(tcx),
|
in_len == out_len,
|
||||||
"expected {} argument with length {} (same as input type `{}`), \
|
"expected {} argument with length {} (same as input type `{}`), \
|
||||||
found `{}` with length {}",
|
found `{}` with length {}",
|
||||||
"second",
|
"second",
|
||||||
in_len,
|
in_len,
|
||||||
in_ty,
|
in_ty,
|
||||||
arg_tys[1],
|
arg_tys[1],
|
||||||
arg_tys[1].simd_size(tcx)
|
out_len
|
||||||
);
|
);
|
||||||
require!(
|
require!(
|
||||||
in_len == arg_tys[2].simd_size(tcx),
|
in_len == out_len2,
|
||||||
"expected {} argument with length {} (same as input type `{}`), \
|
"expected {} argument with length {} (same as input type `{}`), \
|
||||||
found `{}` with length {}",
|
found `{}` with length {}",
|
||||||
"third",
|
"third",
|
||||||
in_len,
|
in_len,
|
||||||
in_ty,
|
in_ty,
|
||||||
arg_tys[2],
|
arg_tys[2],
|
||||||
arg_tys[2].simd_size(tcx)
|
out_len2
|
||||||
);
|
);
|
||||||
|
|
||||||
// The return type must match the first argument type
|
// The return type must match the first argument type
|
||||||
@ -1215,39 +1216,40 @@ fn generic_simd_intrinsic(
|
|||||||
|
|
||||||
// The second argument must be a simd vector with an element type that's a pointer
|
// The second argument must be a simd vector with an element type that's a pointer
|
||||||
// to the element type of the first argument
|
// to the element type of the first argument
|
||||||
let (pointer_count, underlying_ty) = match arg_tys[1].simd_type(tcx).kind() {
|
let (_, element_ty0) = arg_tys[0].simd_size_and_type(bx.tcx());
|
||||||
ty::RawPtr(p) if p.ty == in_elem => {
|
let (_, element_ty1) = arg_tys[1].simd_size_and_type(bx.tcx());
|
||||||
(ptr_count(arg_tys[1].simd_type(tcx)), non_ptr(arg_tys[1].simd_type(tcx)))
|
let (pointer_count, underlying_ty) = match element_ty1.kind() {
|
||||||
}
|
ty::RawPtr(p) if p.ty == in_elem => (ptr_count(element_ty1), non_ptr(element_ty1)),
|
||||||
_ => {
|
_ => {
|
||||||
require!(
|
require!(
|
||||||
false,
|
false,
|
||||||
"expected element type `{}` of second argument `{}` \
|
"expected element type `{}` of second argument `{}` \
|
||||||
to be a pointer to the element type `{}` of the first \
|
to be a pointer to the element type `{}` of the first \
|
||||||
argument `{}`, found `{}` != `*_ {}`",
|
argument `{}`, found `{}` != `*_ {}`",
|
||||||
arg_tys[1].simd_type(tcx),
|
element_ty1,
|
||||||
arg_tys[1],
|
arg_tys[1],
|
||||||
in_elem,
|
in_elem,
|
||||||
in_ty,
|
in_ty,
|
||||||
arg_tys[1].simd_type(tcx),
|
element_ty1,
|
||||||
in_elem
|
in_elem
|
||||||
);
|
);
|
||||||
unreachable!();
|
unreachable!();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
assert!(pointer_count > 0);
|
assert!(pointer_count > 0);
|
||||||
assert_eq!(pointer_count - 1, ptr_count(arg_tys[0].simd_type(tcx)));
|
assert_eq!(pointer_count - 1, ptr_count(element_ty0));
|
||||||
assert_eq!(underlying_ty, non_ptr(arg_tys[0].simd_type(tcx)));
|
assert_eq!(underlying_ty, non_ptr(element_ty0));
|
||||||
|
|
||||||
// The element type of the third argument must be a signed integer type of any width:
|
// The element type of the third argument must be a signed integer type of any width:
|
||||||
match arg_tys[2].simd_type(tcx).kind() {
|
let (_, element_ty2) = arg_tys[2].simd_size_and_type(bx.tcx());
|
||||||
|
match element_ty2.kind() {
|
||||||
ty::Int(_) => (),
|
ty::Int(_) => (),
|
||||||
_ => {
|
_ => {
|
||||||
require!(
|
require!(
|
||||||
false,
|
false,
|
||||||
"expected element type `{}` of third argument `{}` \
|
"expected element type `{}` of third argument `{}` \
|
||||||
to be a signed integer type",
|
to be a signed integer type",
|
||||||
arg_tys[2].simd_type(tcx),
|
element_ty2,
|
||||||
arg_tys[2]
|
arg_tys[2]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1299,25 +1301,27 @@ fn generic_simd_intrinsic(
|
|||||||
require_simd!(arg_tys[2], "third");
|
require_simd!(arg_tys[2], "third");
|
||||||
|
|
||||||
// Of the same length:
|
// Of the same length:
|
||||||
|
let (element_len1, _) = arg_tys[1].simd_size_and_type(bx.tcx());
|
||||||
|
let (element_len2, _) = arg_tys[2].simd_size_and_type(bx.tcx());
|
||||||
require!(
|
require!(
|
||||||
in_len == arg_tys[1].simd_size(tcx),
|
in_len == element_len1,
|
||||||
"expected {} argument with length {} (same as input type `{}`), \
|
"expected {} argument with length {} (same as input type `{}`), \
|
||||||
found `{}` with length {}",
|
found `{}` with length {}",
|
||||||
"second",
|
"second",
|
||||||
in_len,
|
in_len,
|
||||||
in_ty,
|
in_ty,
|
||||||
arg_tys[1],
|
arg_tys[1],
|
||||||
arg_tys[1].simd_size(tcx)
|
element_len1
|
||||||
);
|
);
|
||||||
require!(
|
require!(
|
||||||
in_len == arg_tys[2].simd_size(tcx),
|
in_len == element_len2,
|
||||||
"expected {} argument with length {} (same as input type `{}`), \
|
"expected {} argument with length {} (same as input type `{}`), \
|
||||||
found `{}` with length {}",
|
found `{}` with length {}",
|
||||||
"third",
|
"third",
|
||||||
in_len,
|
in_len,
|
||||||
in_ty,
|
in_ty,
|
||||||
arg_tys[2],
|
arg_tys[2],
|
||||||
arg_tys[2].simd_size(tcx)
|
element_len2
|
||||||
);
|
);
|
||||||
|
|
||||||
// This counts how many pointers
|
// This counts how many pointers
|
||||||
@ -1338,9 +1342,12 @@ fn generic_simd_intrinsic(
|
|||||||
|
|
||||||
// The second argument must be a simd vector with an element type that's a pointer
|
// The second argument must be a simd vector with an element type that's a pointer
|
||||||
// to the element type of the first argument
|
// to the element type of the first argument
|
||||||
let (pointer_count, underlying_ty) = match arg_tys[1].simd_type(tcx).kind() {
|
let (_, element_ty0) = arg_tys[0].simd_size_and_type(bx.tcx());
|
||||||
|
let (_, element_ty1) = arg_tys[1].simd_size_and_type(bx.tcx());
|
||||||
|
let (_, element_ty2) = arg_tys[2].simd_size_and_type(bx.tcx());
|
||||||
|
let (pointer_count, underlying_ty) = match element_ty1.kind() {
|
||||||
ty::RawPtr(p) if p.ty == in_elem && p.mutbl == hir::Mutability::Mut => {
|
ty::RawPtr(p) if p.ty == in_elem && p.mutbl == hir::Mutability::Mut => {
|
||||||
(ptr_count(arg_tys[1].simd_type(tcx)), non_ptr(arg_tys[1].simd_type(tcx)))
|
(ptr_count(element_ty1), non_ptr(element_ty1))
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
require!(
|
require!(
|
||||||
@ -1348,29 +1355,29 @@ fn generic_simd_intrinsic(
|
|||||||
"expected element type `{}` of second argument `{}` \
|
"expected element type `{}` of second argument `{}` \
|
||||||
to be a pointer to the element type `{}` of the first \
|
to be a pointer to the element type `{}` of the first \
|
||||||
argument `{}`, found `{}` != `*mut {}`",
|
argument `{}`, found `{}` != `*mut {}`",
|
||||||
arg_tys[1].simd_type(tcx),
|
element_ty1,
|
||||||
arg_tys[1],
|
arg_tys[1],
|
||||||
in_elem,
|
in_elem,
|
||||||
in_ty,
|
in_ty,
|
||||||
arg_tys[1].simd_type(tcx),
|
element_ty1,
|
||||||
in_elem
|
in_elem
|
||||||
);
|
);
|
||||||
unreachable!();
|
unreachable!();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
assert!(pointer_count > 0);
|
assert!(pointer_count > 0);
|
||||||
assert_eq!(pointer_count - 1, ptr_count(arg_tys[0].simd_type(tcx)));
|
assert_eq!(pointer_count - 1, ptr_count(element_ty0));
|
||||||
assert_eq!(underlying_ty, non_ptr(arg_tys[0].simd_type(tcx)));
|
assert_eq!(underlying_ty, non_ptr(element_ty0));
|
||||||
|
|
||||||
// The element type of the third argument must be a signed integer type of any width:
|
// The element type of the third argument must be a signed integer type of any width:
|
||||||
match arg_tys[2].simd_type(tcx).kind() {
|
match element_ty2.kind() {
|
||||||
ty::Int(_) => (),
|
ty::Int(_) => (),
|
||||||
_ => {
|
_ => {
|
||||||
require!(
|
require!(
|
||||||
false,
|
false,
|
||||||
"expected element type `{}` of third argument `{}` \
|
"expected element type `{}` of third argument `{}` \
|
||||||
to be a signed integer type",
|
be a signed integer type",
|
||||||
arg_tys[2].simd_type(tcx),
|
element_ty2,
|
||||||
arg_tys[2]
|
arg_tys[2]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1567,7 +1574,7 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
|
|||||||
|
|
||||||
if name == sym::simd_cast {
|
if name == sym::simd_cast {
|
||||||
require_simd!(ret_ty, "return");
|
require_simd!(ret_ty, "return");
|
||||||
let out_len = ret_ty.simd_size(tcx);
|
let (out_len, out_elem) = ret_ty.simd_size_and_type(bx.tcx());
|
||||||
require!(
|
require!(
|
||||||
in_len == out_len,
|
in_len == out_len,
|
||||||
"expected return type with length {} (same as input type `{}`), \
|
"expected return type with length {} (same as input type `{}`), \
|
||||||
@ -1578,8 +1585,6 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
|
|||||||
out_len
|
out_len
|
||||||
);
|
);
|
||||||
// casting cares about nominal type, not just structural type
|
// casting cares about nominal type, not just structural type
|
||||||
let out_elem = ret_ty.simd_type(tcx);
|
|
||||||
|
|
||||||
if in_elem == out_elem {
|
if in_elem == out_elem {
|
||||||
return Ok(args[0].immediate());
|
return Ok(args[0].immediate());
|
||||||
}
|
}
|
||||||
@ -1695,7 +1700,7 @@ unsupported {} from `{}` with element `{}` of size `{}` to `{}`"#,
|
|||||||
return_error!(
|
return_error!(
|
||||||
"expected element type `{}` of vector type `{}` \
|
"expected element type `{}` of vector type `{}` \
|
||||||
to be a signed or unsigned integer type",
|
to be a signed or unsigned integer type",
|
||||||
arg_tys[0].simd_type(tcx),
|
arg_tys[0].simd_size_and_type(bx.tcx()).1,
|
||||||
arg_tys[0]
|
arg_tys[0]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,9 @@ use back::write::{create_informational_target_machine, create_target_machine};
|
|||||||
pub use llvm_util::target_features;
|
pub use llvm_util::target_features;
|
||||||
use rustc_ast::expand::allocator::AllocatorKind;
|
use rustc_ast::expand::allocator::AllocatorKind;
|
||||||
use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule};
|
use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule};
|
||||||
use rustc_codegen_ssa::back::write::{CodegenContext, FatLTOInput, ModuleConfig};
|
use rustc_codegen_ssa::back::write::{
|
||||||
|
CodegenContext, FatLTOInput, ModuleConfig, TargetMachineFactoryConfig, TargetMachineFactoryFn,
|
||||||
|
};
|
||||||
use rustc_codegen_ssa::traits::*;
|
use rustc_codegen_ssa::traits::*;
|
||||||
use rustc_codegen_ssa::ModuleCodegen;
|
use rustc_codegen_ssa::ModuleCodegen;
|
||||||
use rustc_codegen_ssa::{CodegenResults, CompiledModule};
|
use rustc_codegen_ssa::{CodegenResults, CompiledModule};
|
||||||
@ -34,7 +36,6 @@ use rustc_span::symbol::Symbol;
|
|||||||
|
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
mod back {
|
mod back {
|
||||||
pub mod archive;
|
pub mod archive;
|
||||||
@ -109,7 +110,7 @@ impl ExtraBackendMethods for LlvmCodegenBackend {
|
|||||||
&self,
|
&self,
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
optlvl: OptLevel,
|
optlvl: OptLevel,
|
||||||
) -> Arc<dyn Fn() -> Result<&'static mut llvm::TargetMachine, String> + Send + Sync> {
|
) -> TargetMachineFactoryFn<Self> {
|
||||||
back::write::target_machine_factory(sess, optlvl)
|
back::write::target_machine_factory(sess, optlvl)
|
||||||
}
|
}
|
||||||
fn target_cpu<'b>(&self, sess: &'b Session) -> &'b str {
|
fn target_cpu<'b>(&self, sess: &'b Session) -> &'b str {
|
||||||
@ -331,7 +332,7 @@ impl ModuleLlvm {
|
|||||||
unsafe {
|
unsafe {
|
||||||
let llcx = llvm::LLVMRustContextCreate(tcx.sess.fewer_names());
|
let llcx = llvm::LLVMRustContextCreate(tcx.sess.fewer_names());
|
||||||
let llmod_raw = context::create_module(tcx, llcx, mod_name) as *const _;
|
let llmod_raw = context::create_module(tcx, llcx, mod_name) as *const _;
|
||||||
ModuleLlvm { llmod_raw, llcx, tm: create_target_machine(tcx) }
|
ModuleLlvm { llmod_raw, llcx, tm: create_target_machine(tcx, mod_name) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -352,7 +353,13 @@ impl ModuleLlvm {
|
|||||||
unsafe {
|
unsafe {
|
||||||
let llcx = llvm::LLVMRustContextCreate(cgcx.fewer_names);
|
let llcx = llvm::LLVMRustContextCreate(cgcx.fewer_names);
|
||||||
let llmod_raw = back::lto::parse_module(llcx, name, buffer, handler)?;
|
let llmod_raw = back::lto::parse_module(llcx, name, buffer, handler)?;
|
||||||
let tm = match (cgcx.tm_factory.0)() {
|
|
||||||
|
let split_dwarf_file = cgcx
|
||||||
|
.output_filenames
|
||||||
|
.split_dwarf_filename(cgcx.split_dwarf_kind, Some(name.to_str().unwrap()));
|
||||||
|
let tm_factory_config = TargetMachineFactoryConfig { split_dwarf_file };
|
||||||
|
|
||||||
|
let tm = match (cgcx.tm_factory)(tm_factory_config) {
|
||||||
Ok(m) => m,
|
Ok(m) => m,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
handler.struct_err(&e).emit();
|
handler.struct_err(&e).emit();
|
||||||
|
@ -642,7 +642,7 @@ pub type InlineAsmDiagHandler = unsafe extern "C" fn(&SMDiagnostic, *const c_voi
|
|||||||
pub mod coverageinfo {
|
pub mod coverageinfo {
|
||||||
use super::coverage_map;
|
use super::coverage_map;
|
||||||
|
|
||||||
/// Aligns with [llvm::coverage::CounterMappingRegion::RegionKind](https://github.com/rust-lang/llvm-project/blob/rustc/10.0-2020-05-05/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L205-L221)
|
/// Aligns with [llvm::coverage::CounterMappingRegion::RegionKind](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L206-L222)
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub enum RegionKind {
|
pub enum RegionKind {
|
||||||
@ -665,13 +665,13 @@ pub mod coverageinfo {
|
|||||||
|
|
||||||
/// This struct provides LLVM's representation of a "CoverageMappingRegion", encoded into the
|
/// This struct provides LLVM's representation of a "CoverageMappingRegion", encoded into the
|
||||||
/// coverage map, in accordance with the
|
/// coverage map, in accordance with the
|
||||||
/// [LLVM Code Coverage Mapping Format](https://github.com/rust-lang/llvm-project/blob/llvmorg-8.0.0/llvm/docs/CoverageMappingFormat.rst#llvm-code-coverage-mapping-format).
|
/// [LLVM Code Coverage Mapping Format](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/docs/CoverageMappingFormat.rst#llvm-code-coverage-mapping-format).
|
||||||
/// The struct composes fields representing the `Counter` type and value(s) (injected counter
|
/// The struct composes fields representing the `Counter` type and value(s) (injected counter
|
||||||
/// ID, or expression type and operands), the source file (an indirect index into a "filenames
|
/// ID, or expression type and operands), the source file (an indirect index into a "filenames
|
||||||
/// array", encoded separately), and source location (start and end positions of the represented
|
/// array", encoded separately), and source location (start and end positions of the represented
|
||||||
/// code region).
|
/// code region).
|
||||||
///
|
///
|
||||||
/// Aligns with [llvm::coverage::CounterMappingRegion](https://github.com/rust-lang/llvm-project/blob/rustc/10.0-2020-05-05/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L223-L226)
|
/// Aligns with [llvm::coverage::CounterMappingRegion](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L224-L227)
|
||||||
/// Important: The Rust struct layout (order and types of fields) must match its C++
|
/// Important: The Rust struct layout (order and types of fields) must match its C++
|
||||||
/// counterpart.
|
/// counterpart.
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
@ -1791,10 +1791,14 @@ extern "C" {
|
|||||||
|
|
||||||
pub fn LLVMRustCoverageCreatePGOFuncNameVar(F: &'a Value, FuncName: *const c_char)
|
pub fn LLVMRustCoverageCreatePGOFuncNameVar(F: &'a Value, FuncName: *const c_char)
|
||||||
-> &'a Value;
|
-> &'a Value;
|
||||||
pub fn LLVMRustCoverageComputeHash(Name: *const c_char) -> u64;
|
pub fn LLVMRustCoverageHashCString(StrVal: *const c_char) -> u64;
|
||||||
|
pub fn LLVMRustCoverageHashByteArray(Bytes: *const c_char, NumBytes: size_t) -> u64;
|
||||||
|
|
||||||
#[allow(improper_ctypes)]
|
#[allow(improper_ctypes)]
|
||||||
pub fn LLVMRustCoverageWriteSectionNameToString(M: &Module, Str: &RustString);
|
pub fn LLVMRustCoverageWriteMapSectionNameToString(M: &Module, Str: &RustString);
|
||||||
|
|
||||||
|
#[allow(improper_ctypes)]
|
||||||
|
pub fn LLVMRustCoverageWriteFuncSectionNameToString(M: &Module, Str: &RustString);
|
||||||
|
|
||||||
#[allow(improper_ctypes)]
|
#[allow(improper_ctypes)]
|
||||||
pub fn LLVMRustCoverageWriteMappingVarNameToString(Str: &RustString);
|
pub fn LLVMRustCoverageWriteMappingVarNameToString(Str: &RustString);
|
||||||
@ -1826,6 +1830,8 @@ extern "C" {
|
|||||||
SplitName: *const c_char,
|
SplitName: *const c_char,
|
||||||
SplitNameLen: size_t,
|
SplitNameLen: size_t,
|
||||||
kind: DebugEmissionKind,
|
kind: DebugEmissionKind,
|
||||||
|
DWOId: u64,
|
||||||
|
SplitDebugInlining: bool,
|
||||||
) -> &'a DIDescriptor;
|
) -> &'a DIDescriptor;
|
||||||
|
|
||||||
pub fn LLVMRustDIBuilderCreateFile(
|
pub fn LLVMRustDIBuilderCreateFile(
|
||||||
@ -2147,6 +2153,7 @@ extern "C" {
|
|||||||
EmitStackSizeSection: bool,
|
EmitStackSizeSection: bool,
|
||||||
RelaxELFRelocations: bool,
|
RelaxELFRelocations: bool,
|
||||||
UseInitArray: bool,
|
UseInitArray: bool,
|
||||||
|
SplitDwarfFile: *const c_char,
|
||||||
) -> Option<&'static mut TargetMachine>;
|
) -> Option<&'static mut TargetMachine>;
|
||||||
pub fn LLVMRustDisposeTargetMachine(T: &'static mut TargetMachine);
|
pub fn LLVMRustDisposeTargetMachine(T: &'static mut TargetMachine);
|
||||||
pub fn LLVMRustAddBuilderLibraryInfo(
|
pub fn LLVMRustAddBuilderLibraryInfo(
|
||||||
@ -2175,6 +2182,7 @@ extern "C" {
|
|||||||
PM: &PassManager<'a>,
|
PM: &PassManager<'a>,
|
||||||
M: &'a Module,
|
M: &'a Module,
|
||||||
Output: *const c_char,
|
Output: *const c_char,
|
||||||
|
DwoOutput: *const c_char,
|
||||||
FileType: FileType,
|
FileType: FileType,
|
||||||
) -> LLVMRustResult;
|
) -> LLVMRustResult;
|
||||||
pub fn LLVMRustOptimizeWithNewPassManager(
|
pub fn LLVMRustOptimizeWithNewPassManager(
|
||||||
|
@ -220,12 +220,24 @@ pub fn set_linkage(llglobal: &Value, linkage: Linkage) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_visibility(llglobal: &Value, visibility: Visibility) {
|
||||||
|
unsafe {
|
||||||
|
LLVMRustSetVisibility(llglobal, visibility);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_alignment(llglobal: &Value, bytes: usize) {
|
pub fn set_alignment(llglobal: &Value, bytes: usize) {
|
||||||
unsafe {
|
unsafe {
|
||||||
ffi::LLVMSetAlignment(llglobal, bytes as c_uint);
|
ffi::LLVMSetAlignment(llglobal, bytes as c_uint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_comdat(llmod: &Module, llglobal: &Value, name: &str) {
|
||||||
|
unsafe {
|
||||||
|
LLVMRustSetComdat(llmod, llglobal, name.as_ptr().cast(), name.len());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Safe wrapper around `LLVMGetParam`, because segfaults are no fun.
|
/// Safe wrapper around `LLVMGetParam`, because segfaults are no fun.
|
||||||
pub fn get_param(llfn: &Value, index: c_uint) -> &Value {
|
pub fn get_param(llfn: &Value, index: c_uint) -> &Value {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -3,7 +3,6 @@ use crate::llvm;
|
|||||||
use libc::c_int;
|
use libc::c_int;
|
||||||
use rustc_codegen_ssa::target_features::supported_target_features;
|
use rustc_codegen_ssa::target_features::supported_target_features;
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_feature::UnstableFeatures;
|
|
||||||
use rustc_middle::bug;
|
use rustc_middle::bug;
|
||||||
use rustc_session::config::PrintRequest;
|
use rustc_session::config::PrintRequest;
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
@ -104,7 +103,7 @@ unsafe fn configure_llvm(sess: &Session) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if sess.opts.debugging_opts.llvm_time_trace && get_major_version() >= 9 {
|
if sess.opts.debugging_opts.llvm_time_trace {
|
||||||
// time-trace is not thread safe and running it in parallel will cause seg faults.
|
// time-trace is not thread safe and running it in parallel will cause seg faults.
|
||||||
if !sess.opts.debugging_opts.no_parallel_llvm {
|
if !sess.opts.debugging_opts.no_parallel_llvm {
|
||||||
bug!("`-Z llvm-time-trace` requires `-Z no-parallel-llvm")
|
bug!("`-Z llvm-time-trace` requires `-Z no-parallel-llvm")
|
||||||
@ -122,16 +121,21 @@ unsafe fn configure_llvm(sess: &Session) {
|
|||||||
|
|
||||||
pub fn time_trace_profiler_finish(file_name: &str) {
|
pub fn time_trace_profiler_finish(file_name: &str) {
|
||||||
unsafe {
|
unsafe {
|
||||||
if get_major_version() >= 9 {
|
|
||||||
let file_name = CString::new(file_name).unwrap();
|
let file_name = CString::new(file_name).unwrap();
|
||||||
llvm::LLVMTimeTraceProfilerFinish(file_name.as_ptr());
|
llvm::LLVMTimeTraceProfilerFinish(file_name.as_ptr());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// WARNING: the features after applying `to_llvm_feature` must be known
|
// WARNING: the features after applying `to_llvm_feature` must be known
|
||||||
// to LLVM or the feature detection code will walk past the end of the feature
|
// to LLVM or the feature detection code will walk past the end of the feature
|
||||||
// array, leading to crashes.
|
// array, leading to crashes.
|
||||||
|
// To find a list of LLVM's names, check llvm-project/llvm/include/llvm/Support/*TargetParser.def
|
||||||
|
// where the * matches the architecture's name
|
||||||
|
// Beware to not use the llvm github project for this, but check the git submodule
|
||||||
|
// found in src/llvm-project
|
||||||
|
// Though note that Rust can also be build with an external precompiled version of LLVM
|
||||||
|
// which might lead to failures if the oldest tested / supported LLVM version
|
||||||
|
// doesn't yet support the relevant intrinsics
|
||||||
pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> &'a str {
|
pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> &'a str {
|
||||||
let arch = if sess.target.arch == "x86_64" { "x86" } else { &*sess.target.arch };
|
let arch = if sess.target.arch == "x86_64" { "x86" } else { &*sess.target.arch };
|
||||||
match (arch, s) {
|
match (arch, s) {
|
||||||
@ -139,6 +143,9 @@ pub fn to_llvm_feature<'a>(sess: &Session, s: &'a str) -> &'a str {
|
|||||||
("x86", "rdrand") => "rdrnd",
|
("x86", "rdrand") => "rdrnd",
|
||||||
("x86", "bmi1") => "bmi",
|
("x86", "bmi1") => "bmi",
|
||||||
("x86", "cmpxchg16b") => "cx16",
|
("x86", "cmpxchg16b") => "cx16",
|
||||||
|
("x86", "avx512vaes") => "vaes",
|
||||||
|
("x86", "avx512gfni") => "gfni",
|
||||||
|
("x86", "avx512vpclmulqdq") => "vpclmulqdq",
|
||||||
("aarch64", "fp") => "fp-armv8",
|
("aarch64", "fp") => "fp-armv8",
|
||||||
("aarch64", "fp16") => "fullfp16",
|
("aarch64", "fp16") => "fullfp16",
|
||||||
(_, s) => s,
|
(_, s) => s,
|
||||||
@ -149,13 +156,11 @@ pub fn target_features(sess: &Session) -> Vec<Symbol> {
|
|||||||
let target_machine = create_informational_target_machine(sess);
|
let target_machine = create_informational_target_machine(sess);
|
||||||
supported_target_features(sess)
|
supported_target_features(sess)
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|&(feature, gate)| {
|
.filter_map(
|
||||||
if UnstableFeatures::from_environment().is_nightly_build() || gate.is_none() {
|
|&(feature, gate)| {
|
||||||
Some(feature)
|
if sess.is_nightly_build() || gate.is_none() { Some(feature) } else { None }
|
||||||
} else {
|
},
|
||||||
None
|
)
|
||||||
}
|
|
||||||
})
|
|
||||||
.filter(|feature| {
|
.filter(|feature| {
|
||||||
let llvm_feature = to_llvm_feature(sess, feature);
|
let llvm_feature = to_llvm_feature(sess, feature);
|
||||||
let cstr = CString::new(llvm_feature).unwrap();
|
let cstr = CString::new(llvm_feature).unwrap();
|
||||||
|
@ -40,9 +40,7 @@ fn uncached_llvm_type<'a, 'tcx>(
|
|||||||
// FIXME(eddyb) producing readable type names for trait objects can result
|
// FIXME(eddyb) producing readable type names for trait objects can result
|
||||||
// in problematically distinct types due to HRTB and subtyping (see #47638).
|
// in problematically distinct types due to HRTB and subtyping (see #47638).
|
||||||
// ty::Dynamic(..) |
|
// ty::Dynamic(..) |
|
||||||
ty::Adt(..) | ty::Closure(..) | ty::Foreign(..) | ty::Generator(..) | ty::Str
|
ty::Adt(..) | ty::Closure(..) | ty::Foreign(..) | ty::Generator(..) | ty::Str => {
|
||||||
if !cx.sess().fewer_names() =>
|
|
||||||
{
|
|
||||||
let mut name = with_no_trimmed_paths(|| layout.ty.to_string());
|
let mut name = with_no_trimmed_paths(|| layout.ty.to_string());
|
||||||
if let (&ty::Adt(def, _), &Variants::Single { index }) =
|
if let (&ty::Adt(def, _), &Variants::Single { index }) =
|
||||||
(layout.ty.kind(), &layout.variants)
|
(layout.ty.kind(), &layout.variants)
|
||||||
@ -58,12 +56,6 @@ fn uncached_llvm_type<'a, 'tcx>(
|
|||||||
}
|
}
|
||||||
Some(name)
|
Some(name)
|
||||||
}
|
}
|
||||||
ty::Adt(..) => {
|
|
||||||
// If `Some` is returned then a named struct is created in LLVM. Name collisions are
|
|
||||||
// avoided by LLVM (with increasing suffixes). If rustc doesn't generate names then that
|
|
||||||
// can improve perf.
|
|
||||||
Some(String::new())
|
|
||||||
}
|
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -252,7 +244,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
|
|||||||
|
|
||||||
// Make sure lifetimes are erased, to avoid generating distinct LLVM
|
// Make sure lifetimes are erased, to avoid generating distinct LLVM
|
||||||
// types for Rust types that only differ in the choice of lifetimes.
|
// types for Rust types that only differ in the choice of lifetimes.
|
||||||
let normal_ty = cx.tcx.erase_regions(&self.ty);
|
let normal_ty = cx.tcx.erase_regions(self.ty);
|
||||||
|
|
||||||
let mut defer = None;
|
let mut defer = None;
|
||||||
let llty = if self.ty != normal_ty {
|
let llty = if self.ty != normal_ty {
|
||||||
|
@ -2,7 +2,7 @@ use rustc_data_structures::fx::FxHashSet;
|
|||||||
use rustc_data_structures::temp_dir::MaybeTempDir;
|
use rustc_data_structures::temp_dir::MaybeTempDir;
|
||||||
use rustc_fs_util::fix_windows_verbatim_for_gcc;
|
use rustc_fs_util::fix_windows_verbatim_for_gcc;
|
||||||
use rustc_hir::def_id::CrateNum;
|
use rustc_hir::def_id::CrateNum;
|
||||||
use rustc_middle::middle::cstore::{EncodedMetadata, LibSource, NativeLib};
|
use rustc_middle::middle::cstore::{EncodedMetadata, LibSource};
|
||||||
use rustc_middle::middle::dependency_format::Linkage;
|
use rustc_middle::middle::dependency_format::Linkage;
|
||||||
use rustc_session::config::{self, CFGuard, CrateType, DebugInfo};
|
use rustc_session::config::{self, CFGuard, CrateType, DebugInfo};
|
||||||
use rustc_session::config::{OutputFilenames, OutputType, PrintRequest, SanitizerSet};
|
use rustc_session::config::{OutputFilenames, OutputType, PrintRequest, SanitizerSet};
|
||||||
@ -21,7 +21,10 @@ use super::archive::ArchiveBuilder;
|
|||||||
use super::command::Command;
|
use super::command::Command;
|
||||||
use super::linker::{self, Linker};
|
use super::linker::{self, Linker};
|
||||||
use super::rpath::{self, RPathConfig};
|
use super::rpath::{self, RPathConfig};
|
||||||
use crate::{looks_like_rust_object_file, CodegenResults, CrateInfo, METADATA_FILENAME};
|
use crate::{
|
||||||
|
looks_like_rust_object_file, CodegenResults, CompiledModule, CrateInfo, NativeLib,
|
||||||
|
METADATA_FILENAME,
|
||||||
|
};
|
||||||
|
|
||||||
use cc::windows_registry;
|
use cc::windows_registry;
|
||||||
use tempfile::Builder as TempFileBuilder;
|
use tempfile::Builder as TempFileBuilder;
|
||||||
@ -96,6 +99,9 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(
|
|||||||
path.as_ref(),
|
path.as_ref(),
|
||||||
target_cpu,
|
target_cpu,
|
||||||
);
|
);
|
||||||
|
if sess.opts.debugging_opts.split_dwarf == config::SplitDwarfKind::Split {
|
||||||
|
link_dwarf_object(sess, &out_filename);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if sess.opts.json_artifact_notifications {
|
if sess.opts.json_artifact_notifications {
|
||||||
@ -107,22 +113,30 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(
|
|||||||
// Remove the temporary object file and metadata if we aren't saving temps
|
// Remove the temporary object file and metadata if we aren't saving temps
|
||||||
sess.time("link_binary_remove_temps", || {
|
sess.time("link_binary_remove_temps", || {
|
||||||
if !sess.opts.cg.save_temps {
|
if !sess.opts.cg.save_temps {
|
||||||
|
let remove_temps_from_module = |module: &CompiledModule| {
|
||||||
|
if let Some(ref obj) = module.object {
|
||||||
|
remove(sess, obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(ref obj) = module.dwarf_object {
|
||||||
|
remove(sess, obj);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if sess.opts.output_types.should_codegen()
|
if sess.opts.output_types.should_codegen()
|
||||||
&& !preserve_objects_for_their_debuginfo(sess)
|
&& !preserve_objects_for_their_debuginfo(sess)
|
||||||
{
|
{
|
||||||
for obj in codegen_results.modules.iter().filter_map(|m| m.object.as_ref()) {
|
for module in &codegen_results.modules {
|
||||||
remove(sess, obj);
|
remove_temps_from_module(module);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(ref metadata_module) = codegen_results.metadata_module {
|
if let Some(ref metadata_module) = codegen_results.metadata_module {
|
||||||
if let Some(ref obj) = metadata_module.object {
|
remove_temps_from_module(metadata_module);
|
||||||
remove(sess, obj);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(ref allocator_module) = codegen_results.allocator_module {
|
if let Some(ref allocator_module) = codegen_results.allocator_module {
|
||||||
if let Some(ref obj) = allocator_module.object {
|
remove_temps_from_module(allocator_module);
|
||||||
remove(sess, obj);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -279,12 +293,12 @@ pub fn emit_metadata(sess: &Session, metadata: &EncodedMetadata, tmpdir: &MaybeT
|
|||||||
out_filename
|
out_filename
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create an 'rlib'
|
/// Create an 'rlib'.
|
||||||
//
|
///
|
||||||
// An rlib in its current incarnation is essentially a renamed .a file. The
|
/// An rlib in its current incarnation is essentially a renamed .a file. The rlib primarily contains
|
||||||
// rlib primarily contains the object file of the crate, but it also contains
|
/// the object file of the crate, but it also contains all of the object files from native
|
||||||
// all of the object files from native libraries. This is done by unzipping
|
/// libraries. This is done by unzipping native libraries and inserting all of the contents into
|
||||||
// native libraries and inserting all of the contents into this archive.
|
/// this archive.
|
||||||
fn link_rlib<'a, B: ArchiveBuilder<'a>>(
|
fn link_rlib<'a, B: ArchiveBuilder<'a>>(
|
||||||
sess: &'a Session,
|
sess: &'a Session,
|
||||||
codegen_results: &CodegenResults,
|
codegen_results: &CodegenResults,
|
||||||
@ -379,18 +393,17 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
|
|||||||
ab
|
ab
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a static archive
|
/// Create a static archive.
|
||||||
//
|
///
|
||||||
// This is essentially the same thing as an rlib, but it also involves adding
|
/// This is essentially the same thing as an rlib, but it also involves adding all of the upstream
|
||||||
// all of the upstream crates' objects into the archive. This will slurp in
|
/// crates' objects into the archive. This will slurp in all of the native libraries of upstream
|
||||||
// all of the native libraries of upstream dependencies as well.
|
/// dependencies as well.
|
||||||
//
|
///
|
||||||
// Additionally, there's no way for us to link dynamic libraries, so we warn
|
/// Additionally, there's no way for us to link dynamic libraries, so we warn about all dynamic
|
||||||
// about all dynamic library dependencies that they're not linked in.
|
/// library dependencies that they're not linked in.
|
||||||
//
|
///
|
||||||
// There's no need to include metadata in a static archive, so ensure to not
|
/// There's no need to include metadata in a static archive, so ensure to not link in the metadata
|
||||||
// link in the metadata object file (and also don't prepare the archive with a
|
/// object file (and also don't prepare the archive with a metadata file).
|
||||||
// metadata file).
|
|
||||||
fn link_staticlib<'a, B: ArchiveBuilder<'a>>(
|
fn link_staticlib<'a, B: ArchiveBuilder<'a>>(
|
||||||
sess: &'a Session,
|
sess: &'a Session,
|
||||||
codegen_results: &CodegenResults,
|
codegen_results: &CodegenResults,
|
||||||
@ -447,10 +460,73 @@ fn link_staticlib<'a, B: ArchiveBuilder<'a>>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a dynamic library or executable
|
fn escape_stdout_stderr_string(s: &[u8]) -> String {
|
||||||
//
|
str::from_utf8(s).map(|s| s.to_owned()).unwrap_or_else(|_| {
|
||||||
// This will invoke the system linker/cc to create the resulting file. This
|
let mut x = "Non-UTF-8 output: ".to_string();
|
||||||
// links to all upstream files as well.
|
x.extend(s.iter().flat_map(|&b| ascii::escape_default(b)).map(char::from));
|
||||||
|
x
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const LLVM_DWP_EXECUTABLE: &'static str = "rust-llvm-dwp";
|
||||||
|
|
||||||
|
/// Invoke `llvm-dwp` (shipped alongside rustc) to link `dwo` files from Split DWARF into a `dwp`
|
||||||
|
/// file.
|
||||||
|
fn link_dwarf_object<'a>(sess: &'a Session, executable_out_filename: &Path) {
|
||||||
|
info!("preparing dwp to {}.dwp", executable_out_filename.to_str().unwrap());
|
||||||
|
|
||||||
|
let dwp_out_filename = executable_out_filename.with_extension("dwp");
|
||||||
|
let mut cmd = Command::new(LLVM_DWP_EXECUTABLE);
|
||||||
|
cmd.arg("-e");
|
||||||
|
cmd.arg(executable_out_filename);
|
||||||
|
cmd.arg("-o");
|
||||||
|
cmd.arg(&dwp_out_filename);
|
||||||
|
|
||||||
|
let mut new_path = sess.host_filesearch(PathKind::All).get_tools_search_paths(false);
|
||||||
|
if let Some(path) = env::var_os("PATH") {
|
||||||
|
new_path.extend(env::split_paths(&path));
|
||||||
|
}
|
||||||
|
let new_path = env::join_paths(new_path).unwrap();
|
||||||
|
cmd.env("PATH", new_path);
|
||||||
|
|
||||||
|
info!("{:?}", &cmd);
|
||||||
|
match sess.time("run_dwp", || cmd.output()) {
|
||||||
|
Ok(prog) if !prog.status.success() => {
|
||||||
|
sess.struct_err(&format!(
|
||||||
|
"linking dwarf objects with `{}` failed: {}",
|
||||||
|
LLVM_DWP_EXECUTABLE, prog.status
|
||||||
|
))
|
||||||
|
.note(&format!("{:?}", &cmd))
|
||||||
|
.note(&escape_stdout_stderr_string(&prog.stdout))
|
||||||
|
.note(&escape_stdout_stderr_string(&prog.stderr))
|
||||||
|
.emit();
|
||||||
|
info!("linker stderr:\n{}", escape_stdout_stderr_string(&prog.stderr));
|
||||||
|
info!("linker stdout:\n{}", escape_stdout_stderr_string(&prog.stdout));
|
||||||
|
}
|
||||||
|
Ok(_) => {}
|
||||||
|
Err(e) => {
|
||||||
|
let dwp_not_found = e.kind() == io::ErrorKind::NotFound;
|
||||||
|
let mut err = if dwp_not_found {
|
||||||
|
sess.struct_err(&format!("linker `{}` not found", LLVM_DWP_EXECUTABLE))
|
||||||
|
} else {
|
||||||
|
sess.struct_err(&format!("could not exec the linker `{}`", LLVM_DWP_EXECUTABLE))
|
||||||
|
};
|
||||||
|
|
||||||
|
err.note(&e.to_string());
|
||||||
|
|
||||||
|
if !dwp_not_found {
|
||||||
|
err.note(&format!("{:?}", &cmd));
|
||||||
|
}
|
||||||
|
|
||||||
|
err.emit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a dynamic library or executable.
|
||||||
|
///
|
||||||
|
/// This will invoke the system linker/cc to create the resulting file. This links to all upstream
|
||||||
|
/// files as well.
|
||||||
fn link_natively<'a, B: ArchiveBuilder<'a>>(
|
fn link_natively<'a, B: ArchiveBuilder<'a>>(
|
||||||
sess: &'a Session,
|
sess: &'a Session,
|
||||||
crate_type: CrateType,
|
crate_type: CrateType,
|
||||||
@ -643,8 +719,6 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match prog {
|
|
||||||
Ok(prog) => {
|
|
||||||
fn escape_string(s: &[u8]) -> String {
|
fn escape_string(s: &[u8]) -> String {
|
||||||
str::from_utf8(s).map(|s| s.to_owned()).unwrap_or_else(|_| {
|
str::from_utf8(s).map(|s| s.to_owned()).unwrap_or_else(|_| {
|
||||||
let mut x = "Non-UTF-8 output: ".to_string();
|
let mut x = "Non-UTF-8 output: ".to_string();
|
||||||
@ -652,6 +726,9 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(
|
|||||||
x
|
x
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
match prog {
|
||||||
|
Ok(prog) => {
|
||||||
if !prog.status.success() {
|
if !prog.status.success() {
|
||||||
let mut output = prog.stderr.clone();
|
let mut output = prog.stderr.clone();
|
||||||
output.extend_from_slice(&prog.stdout);
|
output.extend_from_slice(&prog.stdout);
|
||||||
@ -661,7 +738,7 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(
|
|||||||
prog.status
|
prog.status
|
||||||
))
|
))
|
||||||
.note(&format!("{:?}", &cmd))
|
.note(&format!("{:?}", &cmd))
|
||||||
.note(&escape_string(&output))
|
.note(&escape_stdout_stderr_string(&output))
|
||||||
.emit();
|
.emit();
|
||||||
|
|
||||||
// If MSVC's `link.exe` was expected but the return code
|
// If MSVC's `link.exe` was expected but the return code
|
||||||
@ -714,8 +791,8 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(
|
|||||||
|
|
||||||
sess.abort_if_errors();
|
sess.abort_if_errors();
|
||||||
}
|
}
|
||||||
info!("linker stderr:\n{}", escape_string(&prog.stderr));
|
info!("linker stderr:\n{}", escape_stdout_stderr_string(&prog.stderr));
|
||||||
info!("linker stdout:\n{}", escape_string(&prog.stdout));
|
info!("linker stdout:\n{}", escape_stdout_stderr_string(&prog.stdout));
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let linker_not_found = e.kind() == io::ErrorKind::NotFound;
|
let linker_not_found = e.kind() == io::ErrorKind::NotFound;
|
||||||
@ -760,8 +837,21 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(
|
|||||||
&& sess.opts.debuginfo != DebugInfo::None
|
&& sess.opts.debuginfo != DebugInfo::None
|
||||||
&& !preserve_objects_for_their_debuginfo(sess)
|
&& !preserve_objects_for_their_debuginfo(sess)
|
||||||
{
|
{
|
||||||
if let Err(e) = Command::new("dsymutil").arg(out_filename).output() {
|
let prog = Command::new("dsymutil").arg(out_filename).output();
|
||||||
sess.fatal(&format!("failed to run dsymutil: {}", e))
|
match prog {
|
||||||
|
Ok(prog) => {
|
||||||
|
if !prog.status.success() {
|
||||||
|
let mut output = prog.stderr.clone();
|
||||||
|
output.extend_from_slice(&prog.stdout);
|
||||||
|
sess.struct_warn(&format!(
|
||||||
|
"processing debug info with `dsymutil` failed: {}",
|
||||||
|
prog.status
|
||||||
|
))
|
||||||
|
.note(&escape_string(&output))
|
||||||
|
.emit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => sess.fatal(&format!("unable to run `dsymutil`: {}", e)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -948,6 +1038,13 @@ fn preserve_objects_for_their_debuginfo(sess: &Session) -> bool {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Single mode keeps debuginfo in the same object file, but in such a way that it it skipped
|
||||||
|
// by the linker - so it's expected that when codegen units are linked together that this
|
||||||
|
// debuginfo would be lost without keeping around the temps.
|
||||||
|
if sess.opts.debugging_opts.split_dwarf == config::SplitDwarfKind::Single {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// If we're on OSX then the equivalent of split dwarf is turned on by
|
// If we're on OSX then the equivalent of split dwarf is turned on by
|
||||||
// default. The final executable won't actually have any debug information
|
// default. The final executable won't actually have any debug information
|
||||||
// except it'll have pointers to elsewhere. Historically we've always run
|
// except it'll have pointers to elsewhere. Historically we've always run
|
||||||
@ -1663,17 +1760,15 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
|
|||||||
cmd.take_cmd()
|
cmd.take_cmd()
|
||||||
}
|
}
|
||||||
|
|
||||||
// # Native library linking
|
/// # Native library linking
|
||||||
//
|
///
|
||||||
// User-supplied library search paths (-L on the command line). These are
|
/// User-supplied library search paths (-L on the command line). These are the same paths used to
|
||||||
// the same paths used to find Rust crates, so some of them may have been
|
/// find Rust crates, so some of them may have been added already by the previous crate linking
|
||||||
// added already by the previous crate linking code. This only allows them
|
/// code. This only allows them to be found at compile time so it is still entirely up to outside
|
||||||
// to be found at compile time so it is still entirely up to outside
|
/// forces to make sure that library can be found at runtime.
|
||||||
// forces to make sure that library can be found at runtime.
|
///
|
||||||
//
|
/// Also note that the native libraries linked here are only the ones located in the current crate.
|
||||||
// Also note that the native libraries linked here are only the ones located
|
/// Upstream crates with native library dependencies may have their native library pulled in above.
|
||||||
// in the current crate. Upstream crates with native library dependencies
|
|
||||||
// may have their native library pulled in above.
|
|
||||||
fn add_local_native_libraries(
|
fn add_local_native_libraries(
|
||||||
cmd: &mut dyn Linker,
|
cmd: &mut dyn Linker,
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
@ -1713,11 +1808,10 @@ fn add_local_native_libraries(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// # Rust Crate linking
|
/// # Rust Crate linking
|
||||||
//
|
///
|
||||||
// Rust crates are not considered at all when creating an rlib output. All
|
/// Rust crates are not considered at all when creating an rlib output. All dependencies will be
|
||||||
// dependencies will be linked when producing the final output (instead of
|
/// linked when producing the final output (instead of the intermediate rlib version).
|
||||||
// the intermediate rlib version)
|
|
||||||
fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
|
fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
|
||||||
cmd: &mut dyn Linker,
|
cmd: &mut dyn Linker,
|
||||||
sess: &'a Session,
|
sess: &'a Session,
|
||||||
@ -1982,24 +2076,21 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Link in all of our upstream crates' native dependencies. Remember that
|
/// Link in all of our upstream crates' native dependencies. Remember that all of these upstream
|
||||||
// all of these upstream native dependencies are all non-static
|
/// native dependencies are all non-static dependencies. We've got two cases then:
|
||||||
// dependencies. We've got two cases then:
|
///
|
||||||
//
|
/// 1. The upstream crate is an rlib. In this case we *must* link in the native dependency because
|
||||||
// 1. The upstream crate is an rlib. In this case we *must* link in the
|
/// the rlib is just an archive.
|
||||||
// native dependency because the rlib is just an archive.
|
///
|
||||||
//
|
/// 2. The upstream crate is a dylib. In order to use the dylib, we have to have the dependency
|
||||||
// 2. The upstream crate is a dylib. In order to use the dylib, we have to
|
/// present on the system somewhere. Thus, we don't gain a whole lot from not linking in the
|
||||||
// have the dependency present on the system somewhere. Thus, we don't
|
/// dynamic dependency to this crate as well.
|
||||||
// gain a whole lot from not linking in the dynamic dependency to this
|
///
|
||||||
// crate as well.
|
/// The use case for this is a little subtle. In theory the native dependencies of a crate are
|
||||||
//
|
/// purely an implementation detail of the crate itself, but the problem arises with generic and
|
||||||
// The use case for this is a little subtle. In theory the native
|
/// inlined functions. If a generic function calls a native function, then the generic function
|
||||||
// dependencies of a crate are purely an implementation detail of the crate
|
/// must be instantiated in the target crate, meaning that the native symbol must also be resolved
|
||||||
// itself, but the problem arises with generic and inlined functions. If a
|
/// in the target crate.
|
||||||
// generic function calls a native function, then the generic function must
|
|
||||||
// be instantiated in the target crate, meaning that the native symbol must
|
|
||||||
// also be resolved in the target crate.
|
|
||||||
fn add_upstream_native_libraries(
|
fn add_upstream_native_libraries(
|
||||||
cmd: &mut dyn Linker,
|
cmd: &mut dyn Linker,
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
@ -2090,9 +2181,10 @@ fn add_apple_sdk(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
|
|||||||
("aarch64", "tvos") => "appletvos",
|
("aarch64", "tvos") => "appletvos",
|
||||||
("x86_64", "tvos") => "appletvsimulator",
|
("x86_64", "tvos") => "appletvsimulator",
|
||||||
("arm", "ios") => "iphoneos",
|
("arm", "ios") => "iphoneos",
|
||||||
|
("aarch64", "ios") if llvm_target.contains("macabi") => "macosx",
|
||||||
("aarch64", "ios") => "iphoneos",
|
("aarch64", "ios") => "iphoneos",
|
||||||
("x86", "ios") => "iphonesimulator",
|
("x86", "ios") => "iphonesimulator",
|
||||||
("x86_64", "ios") if llvm_target.contains("macabi") => "macosx10.15",
|
("x86_64", "ios") if llvm_target.contains("macabi") => "macosx",
|
||||||
("x86_64", "ios") => "iphonesimulator",
|
("x86_64", "ios") => "iphonesimulator",
|
||||||
_ => {
|
_ => {
|
||||||
sess.err(&format!("unsupported arch `{}` for os `{}`", arch, os));
|
sess.err(&format!("unsupported arch `{}` for os `{}`", arch, os));
|
||||||
|
@ -274,16 +274,19 @@ impl ModuleConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// HACK(eddyb) work around `#[derive]` producing wrong bounds for `Clone`.
|
/// Configuration passed to the function returned by the `target_machine_factory`.
|
||||||
pub struct TargetMachineFactory<B: WriteBackendMethods>(
|
pub struct TargetMachineFactoryConfig {
|
||||||
pub Arc<dyn Fn() -> Result<B::TargetMachine, String> + Send + Sync>,
|
/// Split DWARF is enabled in LLVM by checking that `TM.MCOptions.SplitDwarfFile` isn't empty,
|
||||||
);
|
/// so the path to the dwarf object has to be provided when we create the target machine.
|
||||||
|
/// This can be ignored by backends which do not need it for their Split DWARF support.
|
||||||
|
pub split_dwarf_file: Option<PathBuf>,
|
||||||
|
}
|
||||||
|
|
||||||
impl<B: WriteBackendMethods> Clone for TargetMachineFactory<B> {
|
pub type TargetMachineFactoryFn<B> = Arc<
|
||||||
fn clone(&self) -> Self {
|
dyn Fn(TargetMachineFactoryConfig) -> Result<<B as WriteBackendMethods>::TargetMachine, String>
|
||||||
TargetMachineFactory(self.0.clone())
|
+ Send
|
||||||
}
|
+ Sync,
|
||||||
}
|
>;
|
||||||
|
|
||||||
pub type ExportedSymbols = FxHashMap<CrateNum, Arc<Vec<(String, SymbolExportLevel)>>>;
|
pub type ExportedSymbols = FxHashMap<CrateNum, Arc<Vec<(String, SymbolExportLevel)>>>;
|
||||||
|
|
||||||
@ -305,11 +308,13 @@ pub struct CodegenContext<B: WriteBackendMethods> {
|
|||||||
pub regular_module_config: Arc<ModuleConfig>,
|
pub regular_module_config: Arc<ModuleConfig>,
|
||||||
pub metadata_module_config: Arc<ModuleConfig>,
|
pub metadata_module_config: Arc<ModuleConfig>,
|
||||||
pub allocator_module_config: Arc<ModuleConfig>,
|
pub allocator_module_config: Arc<ModuleConfig>,
|
||||||
pub tm_factory: TargetMachineFactory<B>,
|
pub tm_factory: TargetMachineFactoryFn<B>,
|
||||||
pub msvc_imps_needed: bool,
|
pub msvc_imps_needed: bool,
|
||||||
|
pub is_pe_coff: bool,
|
||||||
pub target_pointer_width: u32,
|
pub target_pointer_width: u32,
|
||||||
pub target_arch: String,
|
pub target_arch: String,
|
||||||
pub debuginfo: config::DebugInfo,
|
pub debuginfo: config::DebugInfo,
|
||||||
|
pub split_dwarf_kind: config::SplitDwarfKind,
|
||||||
|
|
||||||
// Number of cgus excluding the allocator/metadata modules
|
// Number of cgus excluding the allocator/metadata modules
|
||||||
pub total_cgus: usize,
|
pub total_cgus: usize,
|
||||||
@ -626,6 +631,12 @@ fn produce_final_output_artifacts(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(ref path) = module.dwarf_object {
|
||||||
|
if !keep_numbered_objects {
|
||||||
|
remove(sess, path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(ref path) = module.bytecode {
|
if let Some(ref path) = module.bytecode {
|
||||||
if !keep_numbered_bitcode {
|
if !keep_numbered_bitcode {
|
||||||
remove(sess, path);
|
remove(sess, path);
|
||||||
@ -848,6 +859,7 @@ fn execute_copy_from_cache_work_item<B: ExtraBackendMethods>(
|
|||||||
name: module.name,
|
name: module.name,
|
||||||
kind: ModuleKind::Regular,
|
kind: ModuleKind::Regular,
|
||||||
object,
|
object,
|
||||||
|
dwarf_object: None,
|
||||||
bytecode: None,
|
bytecode: None,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
@ -1019,12 +1031,14 @@ fn start_executing_work<B: ExtraBackendMethods>(
|
|||||||
regular_module_config: regular_config,
|
regular_module_config: regular_config,
|
||||||
metadata_module_config: metadata_config,
|
metadata_module_config: metadata_config,
|
||||||
allocator_module_config: allocator_config,
|
allocator_module_config: allocator_config,
|
||||||
tm_factory: TargetMachineFactory(backend.target_machine_factory(tcx.sess, ol)),
|
tm_factory: backend.target_machine_factory(tcx.sess, ol),
|
||||||
total_cgus,
|
total_cgus,
|
||||||
msvc_imps_needed: msvc_imps_needed(tcx),
|
msvc_imps_needed: msvc_imps_needed(tcx),
|
||||||
|
is_pe_coff: tcx.sess.target.is_like_windows,
|
||||||
target_pointer_width: tcx.sess.target.pointer_width,
|
target_pointer_width: tcx.sess.target.pointer_width,
|
||||||
target_arch: tcx.sess.target.arch.clone(),
|
target_arch: tcx.sess.target.arch.clone(),
|
||||||
debuginfo: tcx.sess.opts.debuginfo,
|
debuginfo: tcx.sess.opts.debuginfo,
|
||||||
|
split_dwarf_kind: tcx.sess.opts.debugging_opts.split_dwarf,
|
||||||
};
|
};
|
||||||
|
|
||||||
// This is the "main loop" of parallel work happening for parallel codegen.
|
// This is the "main loop" of parallel work happening for parallel codegen.
|
||||||
|
@ -399,7 +399,7 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||||||
// late-bound regions, since late-bound
|
// late-bound regions, since late-bound
|
||||||
// regions must appear in the argument
|
// regions must appear in the argument
|
||||||
// listing.
|
// listing.
|
||||||
let main_ret_ty = cx.tcx().erase_regions(&main_ret_ty.no_bound_vars().unwrap());
|
let main_ret_ty = cx.tcx().erase_regions(main_ret_ty.no_bound_vars().unwrap());
|
||||||
|
|
||||||
let llfn = match cx.declare_c_main(llfty) {
|
let llfn = match cx.declare_c_main(llfty) {
|
||||||
Some(llfn) => llfn,
|
Some(llfn) => llfn,
|
||||||
@ -766,7 +766,7 @@ impl CrateInfo {
|
|||||||
profiler_runtime: None,
|
profiler_runtime: None,
|
||||||
is_no_builtins: Default::default(),
|
is_no_builtins: Default::default(),
|
||||||
native_libraries: Default::default(),
|
native_libraries: Default::default(),
|
||||||
used_libraries: tcx.native_libraries(LOCAL_CRATE),
|
used_libraries: tcx.native_libraries(LOCAL_CRATE).iter().map(Into::into).collect(),
|
||||||
link_args: tcx.link_args(LOCAL_CRATE),
|
link_args: tcx.link_args(LOCAL_CRATE),
|
||||||
crate_name: Default::default(),
|
crate_name: Default::default(),
|
||||||
used_crates_dynamic: cstore::used_crates(tcx, LinkagePreference::RequireDynamic),
|
used_crates_dynamic: cstore::used_crates(tcx, LinkagePreference::RequireDynamic),
|
||||||
@ -787,7 +787,8 @@ impl CrateInfo {
|
|||||||
info.missing_lang_items.reserve(n_crates);
|
info.missing_lang_items.reserve(n_crates);
|
||||||
|
|
||||||
for &cnum in crates.iter() {
|
for &cnum in crates.iter() {
|
||||||
info.native_libraries.insert(cnum, tcx.native_libraries(cnum));
|
info.native_libraries
|
||||||
|
.insert(cnum, tcx.native_libraries(cnum).iter().map(Into::into).collect());
|
||||||
info.crate_name.insert(cnum, tcx.crate_name(cnum).to_string());
|
info.crate_name.insert(cnum, tcx.crate_name(cnum).to_string());
|
||||||
info.used_crate_source.insert(cnum, tcx.used_crate_source(cnum));
|
info.used_crate_source.insert(cnum, tcx.used_crate_source(cnum));
|
||||||
if tcx.is_panic_runtime(cnum) {
|
if tcx.is_panic_runtime(cnum) {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use rustc_middle::mir::coverage::{CounterValueReference, MappedExpressionIndex};
|
use rustc_middle::mir::coverage::{CounterValueReference, MappedExpressionIndex};
|
||||||
|
|
||||||
/// Aligns with [llvm::coverage::Counter::CounterKind](https://github.com/rust-lang/llvm-project/blob/rustc/10.0-2020-05-05/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L91)
|
/// Aligns with [llvm::coverage::Counter::CounterKind](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L206-L222)
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub enum CounterKind {
|
pub enum CounterKind {
|
||||||
@ -17,7 +17,7 @@ pub enum CounterKind {
|
|||||||
/// `instrprof.increment()`)
|
/// `instrprof.increment()`)
|
||||||
/// * For `CounterKind::Expression`, `id` is the index into the coverage map's array of
|
/// * For `CounterKind::Expression`, `id` is the index into the coverage map's array of
|
||||||
/// counter expressions.
|
/// counter expressions.
|
||||||
/// Aligns with [llvm::coverage::Counter](https://github.com/rust-lang/llvm-project/blob/rustc/10.0-2020-05-05/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L98-L99)
|
/// Aligns with [llvm::coverage::Counter](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L99-L100)
|
||||||
/// Important: The Rust struct layout (order and types of fields) must match its C++ counterpart.
|
/// Important: The Rust struct layout (order and types of fields) must match its C++ counterpart.
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
@ -41,7 +41,7 @@ impl Counter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Aligns with [llvm::coverage::CounterExpression::ExprKind](https://github.com/rust-lang/llvm-project/blob/rustc/10.0-2020-05-05/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L146)
|
/// 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)
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub enum ExprKind {
|
pub enum ExprKind {
|
||||||
@ -49,7 +49,7 @@ pub enum ExprKind {
|
|||||||
Add = 1,
|
Add = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Aligns with [llvm::coverage::CounterExpression](https://github.com/rust-lang/llvm-project/blob/rustc/10.0-2020-05-05/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L147-L148)
|
/// Aligns with [llvm::coverage::CounterExpression](https://github.com/rust-lang/llvm-project/blob/rustc/11.0-2020-10-12/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L148-L149)
|
||||||
/// Important: The Rust struct layout (order and types of fields) must match its C++
|
/// Important: The Rust struct layout (order and types of fields) must match its C++
|
||||||
/// counterpart.
|
/// counterpart.
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
@ -94,7 +94,14 @@ pub fn push_debuginfo_type_name<'tcx>(
|
|||||||
push_debuginfo_type_name(tcx, inner_type, true, output, visited);
|
push_debuginfo_type_name(tcx, inner_type, true, output, visited);
|
||||||
|
|
||||||
if cpp_like_names {
|
if cpp_like_names {
|
||||||
output.push('*');
|
// Slices and `&str` are treated like C++ pointers when computing debug
|
||||||
|
// info for MSVC debugger. However, adding '*' at the end of these types' names
|
||||||
|
// causes the .natvis engine for WinDbg to fail to display their data, so we opt these
|
||||||
|
// types out to aid debugging in MSVC.
|
||||||
|
match *inner_type.kind() {
|
||||||
|
ty::Slice(_) | ty::Str => {}
|
||||||
|
_ => output.push('*'),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ty::Array(inner_type, len) => {
|
ty::Array(inner_type, len) => {
|
||||||
@ -120,8 +127,8 @@ pub fn push_debuginfo_type_name<'tcx>(
|
|||||||
}
|
}
|
||||||
ty::Dynamic(ref trait_data, ..) => {
|
ty::Dynamic(ref trait_data, ..) => {
|
||||||
if let Some(principal) = trait_data.principal() {
|
if let Some(principal) = trait_data.principal() {
|
||||||
let principal = tcx
|
let principal =
|
||||||
.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &principal);
|
tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), principal);
|
||||||
push_item_name(tcx, principal.def_id, false, output);
|
push_item_name(tcx, principal.def_id, false, output);
|
||||||
push_type_params(tcx, principal.substs, output, visited);
|
push_type_params(tcx, principal.substs, output, visited);
|
||||||
} else {
|
} else {
|
||||||
@ -159,7 +166,7 @@ pub fn push_debuginfo_type_name<'tcx>(
|
|||||||
|
|
||||||
output.push_str("fn(");
|
output.push_str("fn(");
|
||||||
|
|
||||||
let sig = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
|
let sig = tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), sig);
|
||||||
if !sig.inputs().is_empty() {
|
if !sig.inputs().is_empty() {
|
||||||
for ¶meter_type in sig.inputs() {
|
for ¶meter_type in sig.inputs() {
|
||||||
push_debuginfo_type_name(tcx, parameter_type, true, output, visited);
|
push_debuginfo_type_name(tcx, parameter_type, true, output, visited);
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#![feature(bool_to_option)]
|
#![feature(bool_to_option)]
|
||||||
#![feature(option_expect_none)]
|
#![feature(option_expect_none)]
|
||||||
#![feature(box_patterns)]
|
#![feature(box_patterns)]
|
||||||
|
#![feature(drain_filter)]
|
||||||
#![feature(try_blocks)]
|
#![feature(try_blocks)]
|
||||||
#![feature(in_band_lifetimes)]
|
#![feature(in_band_lifetimes)]
|
||||||
#![feature(nll)]
|
#![feature(nll)]
|
||||||
@ -20,15 +21,17 @@ extern crate tracing;
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate rustc_middle;
|
extern crate rustc_middle;
|
||||||
|
|
||||||
|
use rustc_ast as ast;
|
||||||
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
||||||
use rustc_data_structures::sync::Lrc;
|
use rustc_data_structures::sync::Lrc;
|
||||||
use rustc_hir::def_id::CrateNum;
|
use rustc_hir::def_id::CrateNum;
|
||||||
use rustc_hir::LangItem;
|
use rustc_hir::LangItem;
|
||||||
use rustc_middle::dep_graph::WorkProduct;
|
use rustc_middle::dep_graph::WorkProduct;
|
||||||
use rustc_middle::middle::cstore::{CrateSource, LibSource, NativeLib};
|
use rustc_middle::middle::cstore::{self, CrateSource, LibSource};
|
||||||
use rustc_middle::middle::dependency_format::Dependencies;
|
use rustc_middle::middle::dependency_format::Dependencies;
|
||||||
use rustc_middle::ty::query::Providers;
|
use rustc_middle::ty::query::Providers;
|
||||||
use rustc_session::config::{OutputFilenames, OutputType, RUST_CGU_EXT};
|
use rustc_session::config::{OutputFilenames, OutputType, RUST_CGU_EXT};
|
||||||
|
use rustc_session::utils::NativeLibKind;
|
||||||
use rustc_span::symbol::Symbol;
|
use rustc_span::symbol::Symbol;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
@ -63,13 +66,15 @@ impl<M> ModuleCodegen<M> {
|
|||||||
pub fn into_compiled_module(
|
pub fn into_compiled_module(
|
||||||
self,
|
self,
|
||||||
emit_obj: bool,
|
emit_obj: bool,
|
||||||
|
emit_dwarf_obj: bool,
|
||||||
emit_bc: bool,
|
emit_bc: bool,
|
||||||
outputs: &OutputFilenames,
|
outputs: &OutputFilenames,
|
||||||
) -> CompiledModule {
|
) -> CompiledModule {
|
||||||
let object = emit_obj.then(|| outputs.temp_path(OutputType::Object, Some(&self.name)));
|
let object = emit_obj.then(|| outputs.temp_path(OutputType::Object, Some(&self.name)));
|
||||||
|
let dwarf_object = emit_dwarf_obj.then(|| outputs.temp_path_dwo(Some(&self.name)));
|
||||||
let bytecode = emit_bc.then(|| outputs.temp_path(OutputType::Bitcode, Some(&self.name)));
|
let bytecode = emit_bc.then(|| outputs.temp_path(OutputType::Bitcode, Some(&self.name)));
|
||||||
|
|
||||||
CompiledModule { name: self.name.clone(), kind: self.kind, object, bytecode }
|
CompiledModule { name: self.name.clone(), kind: self.kind, object, dwarf_object, bytecode }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,6 +83,7 @@ pub struct CompiledModule {
|
|||||||
pub name: String,
|
pub name: String,
|
||||||
pub kind: ModuleKind,
|
pub kind: ModuleKind,
|
||||||
pub object: Option<PathBuf>,
|
pub object: Option<PathBuf>,
|
||||||
|
pub dwarf_object: Option<PathBuf>,
|
||||||
pub bytecode: Option<PathBuf>,
|
pub bytecode: Option<PathBuf>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -101,6 +107,19 @@ bitflags::bitflags! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Encodable, Decodable, HashStable)]
|
||||||
|
pub struct NativeLib {
|
||||||
|
pub kind: NativeLibKind,
|
||||||
|
pub name: Option<Symbol>,
|
||||||
|
pub cfg: Option<ast::MetaItem>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&cstore::NativeLib> for NativeLib {
|
||||||
|
fn from(lib: &cstore::NativeLib) -> Self {
|
||||||
|
NativeLib { kind: lib.kind.clone(), name: lib.name.clone(), cfg: lib.cfg.clone() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Misc info we load from metadata to persist beyond the tcx.
|
/// Misc info we load from metadata to persist beyond the tcx.
|
||||||
///
|
///
|
||||||
/// Note: though `CrateNum` is only meaningful within the same tcx, information within `CrateInfo`
|
/// Note: though `CrateNum` is only meaningful within the same tcx, information within `CrateInfo`
|
||||||
@ -115,9 +134,9 @@ pub struct CrateInfo {
|
|||||||
pub compiler_builtins: Option<CrateNum>,
|
pub compiler_builtins: Option<CrateNum>,
|
||||||
pub profiler_runtime: Option<CrateNum>,
|
pub profiler_runtime: Option<CrateNum>,
|
||||||
pub is_no_builtins: FxHashSet<CrateNum>,
|
pub is_no_builtins: FxHashSet<CrateNum>,
|
||||||
pub native_libraries: FxHashMap<CrateNum, Lrc<Vec<NativeLib>>>,
|
pub native_libraries: FxHashMap<CrateNum, Vec<NativeLib>>,
|
||||||
pub crate_name: FxHashMap<CrateNum, String>,
|
pub crate_name: FxHashMap<CrateNum, String>,
|
||||||
pub used_libraries: Lrc<Vec<NativeLib>>,
|
pub used_libraries: Vec<NativeLib>,
|
||||||
pub link_args: Lrc<Vec<String>>,
|
pub link_args: Lrc<Vec<String>>,
|
||||||
pub used_crate_source: FxHashMap<CrateNum, Lrc<CrateSource>>,
|
pub used_crate_source: FxHashMap<CrateNum, Lrc<CrateSource>>,
|
||||||
pub used_crates_static: Vec<(CrateNum, LibSource)>,
|
pub used_crates_static: Vec<(CrateNum, LibSource)>,
|
||||||
|
@ -24,7 +24,7 @@ pub fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||||||
analyzer.visit_body(&mir);
|
analyzer.visit_body(&mir);
|
||||||
|
|
||||||
for (local, decl) in mir.local_decls.iter_enumerated() {
|
for (local, decl) in mir.local_decls.iter_enumerated() {
|
||||||
let ty = fx.monomorphize(&decl.ty);
|
let ty = fx.monomorphize(decl.ty);
|
||||||
debug!("local {:?} has type `{}`", local, ty);
|
debug!("local {:?} has type `{}`", local, ty);
|
||||||
let layout = fx.cx.spanned_layout_of(ty, decl.source_info.span);
|
let layout = fx.cx.spanned_layout_of(ty, decl.source_info.span);
|
||||||
if fx.cx.is_backend_immediate(layout) {
|
if fx.cx.is_backend_immediate(layout) {
|
||||||
@ -121,10 +121,10 @@ impl<Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx, Bx> {
|
|||||||
if is_consume {
|
if is_consume {
|
||||||
let base_ty =
|
let base_ty =
|
||||||
mir::Place::ty_from(place_ref.local, proj_base, self.fx.mir, cx.tcx());
|
mir::Place::ty_from(place_ref.local, proj_base, self.fx.mir, cx.tcx());
|
||||||
let base_ty = self.fx.monomorphize(&base_ty);
|
let base_ty = self.fx.monomorphize(base_ty);
|
||||||
|
|
||||||
// ZSTs don't require any actual memory access.
|
// ZSTs don't require any actual memory access.
|
||||||
let elem_ty = base_ty.projection_ty(cx.tcx(), self.fx.monomorphize(&elem)).ty;
|
let elem_ty = base_ty.projection_ty(cx.tcx(), self.fx.monomorphize(elem)).ty;
|
||||||
let span = self.fx.mir.local_decls[place_ref.local].source_info.span;
|
let span = self.fx.mir.local_decls[place_ref.local].source_info.span;
|
||||||
if cx.spanned_layout_of(elem_ty, span).is_zst() {
|
if cx.spanned_layout_of(elem_ty, span).is_zst() {
|
||||||
return;
|
return;
|
||||||
@ -313,7 +313,7 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> Visitor<'tcx>
|
|||||||
|
|
||||||
PlaceContext::MutatingUse(MutatingUseContext::Drop) => {
|
PlaceContext::MutatingUse(MutatingUseContext::Drop) => {
|
||||||
let ty = self.fx.mir.local_decls[local].ty;
|
let ty = self.fx.mir.local_decls[local].ty;
|
||||||
let ty = self.fx.monomorphize(&ty);
|
let ty = self.fx.monomorphize(ty);
|
||||||
|
|
||||||
// Only need the place if we're actually dropping it.
|
// Only need the place if we're actually dropping it.
|
||||||
if self.fx.cx.type_needs_drop(ty) {
|
if self.fx.cx.type_needs_drop(ty) {
|
||||||
|
@ -37,12 +37,9 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> {
|
|||||||
/// `funclet_bb` member if it is not `None`.
|
/// `funclet_bb` member if it is not `None`.
|
||||||
fn funclet<'b, Bx: BuilderMethods<'a, 'tcx>>(
|
fn funclet<'b, Bx: BuilderMethods<'a, 'tcx>>(
|
||||||
&self,
|
&self,
|
||||||
fx: &'b mut FunctionCx<'a, 'tcx, Bx>,
|
fx: &'b FunctionCx<'a, 'tcx, Bx>,
|
||||||
) -> Option<&'b Bx::Funclet> {
|
) -> Option<&'b Bx::Funclet> {
|
||||||
match self.funclet_bb {
|
self.funclet_bb.and_then(|funcl| fx.funclets[funcl].as_ref())
|
||||||
Some(funcl) => fx.funclets[funcl].as_ref(),
|
|
||||||
None => None,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lltarget<Bx: BuilderMethods<'a, 'tcx>>(
|
fn lltarget<Bx: BuilderMethods<'a, 'tcx>>(
|
||||||
@ -255,7 +252,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let llval = match self.fn_abi.ret.mode {
|
let llval = match self.fn_abi.ret.mode {
|
||||||
PassMode::Ignore | PassMode::Indirect(..) => {
|
PassMode::Ignore | PassMode::Indirect { .. } => {
|
||||||
bx.ret_void();
|
bx.ret_void();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -306,7 +303,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
unwind: Option<mir::BasicBlock>,
|
unwind: Option<mir::BasicBlock>,
|
||||||
) {
|
) {
|
||||||
let ty = location.ty(self.mir, bx.tcx()).ty;
|
let ty = location.ty(self.mir, bx.tcx()).ty;
|
||||||
let ty = self.monomorphize(&ty);
|
let ty = self.monomorphize(ty);
|
||||||
let drop_fn = Instance::resolve_drop_in_place(bx.tcx(), ty);
|
let drop_fn = Instance::resolve_drop_in_place(bx.tcx(), ty);
|
||||||
|
|
||||||
if let ty::InstanceDef::DropGlue(_, None) = drop_fn.def {
|
if let ty::InstanceDef::DropGlue(_, None) = drop_fn.def {
|
||||||
@ -454,7 +451,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
Inhabited,
|
Inhabited,
|
||||||
ZeroValid,
|
ZeroValid,
|
||||||
UninitValid,
|
UninitValid,
|
||||||
};
|
}
|
||||||
let panic_intrinsic = intrinsic.and_then(|i| match i {
|
let panic_intrinsic = intrinsic.and_then(|i| match i {
|
||||||
sym::assert_inhabited => Some(AssertIntrinsic::Inhabited),
|
sym::assert_inhabited => Some(AssertIntrinsic::Inhabited),
|
||||||
sym::assert_zero_valid => Some(AssertIntrinsic::ZeroValid),
|
sym::assert_zero_valid => Some(AssertIntrinsic::ZeroValid),
|
||||||
@ -576,7 +573,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
.iter()
|
.iter()
|
||||||
.map(|op_arg| {
|
.map(|op_arg| {
|
||||||
let op_ty = op_arg.ty(self.mir, bx.tcx());
|
let op_ty = op_arg.ty(self.mir, bx.tcx());
|
||||||
self.monomorphize(&op_ty)
|
self.monomorphize(op_ty)
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
@ -900,7 +897,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
mir::InlineAsmOperand::SymFn { ref value } => {
|
mir::InlineAsmOperand::SymFn { ref value } => {
|
||||||
let literal = self.monomorphize(&value.literal);
|
let literal = self.monomorphize(value.literal);
|
||||||
if let ty::FnDef(def_id, substs) = *literal.ty.kind() {
|
if let ty::FnDef(def_id, substs) = *literal.ty.kind() {
|
||||||
let instance = ty::Instance::resolve_for_fn_ptr(
|
let instance = ty::Instance::resolve_for_fn_ptr(
|
||||||
bx.tcx(),
|
bx.tcx(),
|
||||||
@ -1101,7 +1098,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
// Force by-ref if we have to load through a cast pointer.
|
// Force by-ref if we have to load through a cast pointer.
|
||||||
let (mut llval, align, by_ref) = match op.val {
|
let (mut llval, align, by_ref) = match op.val {
|
||||||
Immediate(_) | Pair(..) => match arg.mode {
|
Immediate(_) | Pair(..) => match arg.mode {
|
||||||
PassMode::Indirect(..) | PassMode::Cast(_) => {
|
PassMode::Indirect { .. } | PassMode::Cast(_) => {
|
||||||
let scratch = PlaceRef::alloca(bx, arg.layout);
|
let scratch = PlaceRef::alloca(bx, arg.layout);
|
||||||
op.val.store(bx, scratch);
|
op.val.store(bx, scratch);
|
||||||
(scratch.llval, scratch.align, true)
|
(scratch.llval, scratch.align, true)
|
||||||
@ -1398,6 +1395,25 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
dst: PlaceRef<'tcx, Bx::Value>,
|
dst: PlaceRef<'tcx, Bx::Value>,
|
||||||
) {
|
) {
|
||||||
let src = self.codegen_operand(bx, src);
|
let src = self.codegen_operand(bx, src);
|
||||||
|
|
||||||
|
// Special-case transmutes between scalars as simple bitcasts.
|
||||||
|
match (&src.layout.abi, &dst.layout.abi) {
|
||||||
|
(abi::Abi::Scalar(src_scalar), abi::Abi::Scalar(dst_scalar)) => {
|
||||||
|
// HACK(eddyb) LLVM doesn't like `bitcast`s between pointers and non-pointers.
|
||||||
|
if (src_scalar.value == abi::Pointer) == (dst_scalar.value == abi::Pointer) {
|
||||||
|
assert_eq!(src.layout.size, dst.layout.size);
|
||||||
|
|
||||||
|
// NOTE(eddyb) the `from_immediate` and `to_immediate_scalar`
|
||||||
|
// conversions allow handling `bool`s the same as `u8`s.
|
||||||
|
let src = bx.from_immediate(src.immediate());
|
||||||
|
let src_as_dst = bx.bitcast(src, bx.backend_type(dst.layout));
|
||||||
|
Immediate(bx.to_immediate_scalar(src_as_dst, dst_scalar)).store(bx, dst);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
let llty = bx.backend_type(src.layout);
|
let llty = bx.backend_type(src.layout);
|
||||||
let cast_ptr = bx.pointercast(dst.llval, bx.type_ptr_to(llty));
|
let cast_ptr = bx.pointercast(dst.llval, bx.type_ptr_to(llty));
|
||||||
let align = src.layout.align.abi.min(dst.align);
|
let align = src.layout.align.abi.min(dst.align);
|
||||||
|
@ -11,20 +11,20 @@ use super::FunctionCx;
|
|||||||
|
|
||||||
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
pub fn eval_mir_constant_to_operand(
|
pub fn eval_mir_constant_to_operand(
|
||||||
&mut self,
|
&self,
|
||||||
bx: &mut Bx,
|
bx: &mut Bx,
|
||||||
constant: &mir::Constant<'tcx>,
|
constant: &mir::Constant<'tcx>,
|
||||||
) -> Result<OperandRef<'tcx, Bx::Value>, ErrorHandled> {
|
) -> Result<OperandRef<'tcx, Bx::Value>, ErrorHandled> {
|
||||||
let val = self.eval_mir_constant(constant)?;
|
let val = self.eval_mir_constant(constant)?;
|
||||||
let ty = self.monomorphize(&constant.literal.ty);
|
let ty = self.monomorphize(constant.literal.ty);
|
||||||
Ok(OperandRef::from_const(bx, val, ty))
|
Ok(OperandRef::from_const(bx, val, ty))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn eval_mir_constant(
|
pub fn eval_mir_constant(
|
||||||
&mut self,
|
&self,
|
||||||
constant: &mir::Constant<'tcx>,
|
constant: &mir::Constant<'tcx>,
|
||||||
) -> Result<ConstValue<'tcx>, ErrorHandled> {
|
) -> Result<ConstValue<'tcx>, ErrorHandled> {
|
||||||
match self.monomorphize(&constant.literal).val {
|
match self.monomorphize(constant.literal).val {
|
||||||
ty::ConstKind::Unevaluated(def, substs, promoted) => self
|
ty::ConstKind::Unevaluated(def, substs, promoted) => self
|
||||||
.cx
|
.cx
|
||||||
.tcx()
|
.tcx()
|
||||||
@ -83,7 +83,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
.unwrap_or_else(|_| {
|
.unwrap_or_else(|_| {
|
||||||
bx.tcx().sess.span_err(span, "could not evaluate shuffle_indices at compile time");
|
bx.tcx().sess.span_err(span, "could not evaluate shuffle_indices at compile time");
|
||||||
// We've errored, so we don't have to produce working code.
|
// We've errored, so we don't have to produce working code.
|
||||||
let ty = self.monomorphize(&ty);
|
let ty = self.monomorphize(ty);
|
||||||
let llty = bx.backend_type(bx.layout_of(ty));
|
let llty = bx.backend_type(bx.layout_of(ty));
|
||||||
(bx.const_undef(llty), ty)
|
(bx.const_undef(llty), ty)
|
||||||
})
|
})
|
||||||
|
@ -8,7 +8,7 @@ use rustc_span::symbol::{kw, Symbol};
|
|||||||
use rustc_span::{BytePos, Span};
|
use rustc_span::{BytePos, Span};
|
||||||
use rustc_target::abi::{LayoutOf, Size};
|
use rustc_target::abi::{LayoutOf, Size};
|
||||||
|
|
||||||
use super::operand::OperandValue;
|
use super::operand::{OperandRef, OperandValue};
|
||||||
use super::place::PlaceRef;
|
use super::place::PlaceRef;
|
||||||
use super::{FunctionCx, LocalRef};
|
use super::{FunctionCx, LocalRef};
|
||||||
|
|
||||||
@ -116,6 +116,24 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
span
|
span
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn spill_operand_to_stack(
|
||||||
|
operand: &OperandRef<'tcx, Bx::Value>,
|
||||||
|
name: Option<String>,
|
||||||
|
bx: &mut Bx,
|
||||||
|
) -> PlaceRef<'tcx, Bx::Value> {
|
||||||
|
// "Spill" the value onto the stack, for debuginfo,
|
||||||
|
// without forcing non-debuginfo uses of the local
|
||||||
|
// to also load from the stack every single time.
|
||||||
|
// FIXME(#68817) use `llvm.dbg.value` instead,
|
||||||
|
// at least for the cases which LLVM handles correctly.
|
||||||
|
let spill_slot = PlaceRef::alloca(bx, operand.layout);
|
||||||
|
if let Some(name) = name {
|
||||||
|
bx.set_var_name(spill_slot.llval, &(name + ".dbg.spill"));
|
||||||
|
}
|
||||||
|
operand.val.store(bx, spill_slot);
|
||||||
|
spill_slot
|
||||||
|
}
|
||||||
|
|
||||||
/// Apply debuginfo and/or name, after creating the `alloca` for a local,
|
/// Apply debuginfo and/or name, after creating the `alloca` for a local,
|
||||||
/// or initializing the local with an operand (whichever applies).
|
/// or initializing the local with an operand (whichever applies).
|
||||||
pub fn debug_introduce_local(&self, bx: &mut Bx, local: mir::Local) {
|
pub fn debug_introduce_local(&self, bx: &mut Bx, local: mir::Local) {
|
||||||
@ -160,7 +178,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
// FIXME(eddyb) is this `+ 1` needed at all?
|
// FIXME(eddyb) is this `+ 1` needed at all?
|
||||||
let kind = VariableKind::ArgumentVariable(arg_index + 1);
|
let kind = VariableKind::ArgumentVariable(arg_index + 1);
|
||||||
|
|
||||||
let arg_ty = self.monomorphize(&decl.ty);
|
let arg_ty = self.monomorphize(decl.ty);
|
||||||
|
|
||||||
self.cx.create_dbg_var(name, arg_ty, dbg_scope, kind, span)
|
self.cx.create_dbg_var(name, arg_ty, dbg_scope, kind, span)
|
||||||
},
|
},
|
||||||
@ -226,17 +244,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// "Spill" the value onto the stack, for debuginfo,
|
Self::spill_operand_to_stack(operand, name, bx)
|
||||||
// without forcing non-debuginfo uses of the local
|
|
||||||
// to also load from the stack every single time.
|
|
||||||
// FIXME(#68817) use `llvm.dbg.value` instead,
|
|
||||||
// at least for the cases which LLVM handles correctly.
|
|
||||||
let spill_slot = PlaceRef::alloca(bx, operand.layout);
|
|
||||||
if let Some(name) = name {
|
|
||||||
bx.set_var_name(spill_slot.llval, &(name + ".dbg.spill"));
|
|
||||||
}
|
|
||||||
operand.val.store(bx, spill_slot);
|
|
||||||
spill_slot
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LocalRef::Place(place) => *place,
|
LocalRef::Place(place) => *place,
|
||||||
@ -308,6 +316,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
/// Partition all `VarDebugInfo` in `self.mir`, by their base `Local`.
|
/// Partition all `VarDebugInfo` in `self.mir`, by their base `Local`.
|
||||||
pub fn compute_per_local_var_debug_info(
|
pub fn compute_per_local_var_debug_info(
|
||||||
&self,
|
&self,
|
||||||
|
bx: &mut Bx,
|
||||||
) -> Option<IndexVec<mir::Local, Vec<PerLocalVarDebugInfo<'tcx, Bx::DIVariable>>>> {
|
) -> Option<IndexVec<mir::Local, Vec<PerLocalVarDebugInfo<'tcx, Bx::DIVariable>>>> {
|
||||||
let full_debug_info = self.cx.sess().opts.debuginfo == DebugInfo::Full;
|
let full_debug_info = self.cx.sess().opts.debuginfo == DebugInfo::Full;
|
||||||
|
|
||||||
@ -322,8 +331,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let dbg_var = dbg_scope_and_span.map(|(dbg_scope, _, span)| {
|
let dbg_var = dbg_scope_and_span.map(|(dbg_scope, _, span)| {
|
||||||
let place = var.place;
|
let (var_ty, var_kind) = match var.value {
|
||||||
|
mir::VarDebugInfoContents::Place(place) => {
|
||||||
let var_ty = self.monomorphized_place_ty(place.as_ref());
|
let var_ty = self.monomorphized_place_ty(place.as_ref());
|
||||||
let var_kind = if self.mir.local_kind(place.local) == mir::LocalKind::Arg
|
let var_kind = if self.mir.local_kind(place.local) == mir::LocalKind::Arg
|
||||||
&& place.projection.is_empty()
|
&& place.projection.is_empty()
|
||||||
@ -338,16 +349,46 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
} else {
|
} else {
|
||||||
VariableKind::LocalVariable
|
VariableKind::LocalVariable
|
||||||
};
|
};
|
||||||
|
(var_ty, var_kind)
|
||||||
|
}
|
||||||
|
mir::VarDebugInfoContents::Const(c) => {
|
||||||
|
let ty = self.monomorphize(c.literal.ty);
|
||||||
|
(ty, VariableKind::LocalVariable)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
self.cx.create_dbg_var(var.name, var_ty, dbg_scope, var_kind, span)
|
self.cx.create_dbg_var(var.name, var_ty, dbg_scope, var_kind, span)
|
||||||
});
|
});
|
||||||
|
|
||||||
per_local[var.place.local].push(PerLocalVarDebugInfo {
|
match var.value {
|
||||||
|
mir::VarDebugInfoContents::Place(place) => {
|
||||||
|
per_local[place.local].push(PerLocalVarDebugInfo {
|
||||||
name: var.name,
|
name: var.name,
|
||||||
source_info: var.source_info,
|
source_info: var.source_info,
|
||||||
dbg_var,
|
dbg_var,
|
||||||
projection: var.place.projection,
|
projection: place.projection,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
mir::VarDebugInfoContents::Const(c) => {
|
||||||
|
if let Some(dbg_var) = dbg_var {
|
||||||
|
let dbg_loc = match self.dbg_loc(var.source_info) {
|
||||||
|
Some(dbg_loc) => dbg_loc,
|
||||||
|
None => continue,
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Ok(operand) = self.eval_mir_constant_to_operand(bx, &c) {
|
||||||
|
let base = Self::spill_operand_to_stack(
|
||||||
|
&operand,
|
||||||
|
Some(var.name.to_string()),
|
||||||
|
bx,
|
||||||
|
);
|
||||||
|
|
||||||
|
bx.dbg_var_addr(dbg_var, dbg_loc, base.llval, Size::ZERO, &[]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Some(per_local)
|
Some(per_local)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let sig = callee_ty.fn_sig(bx.tcx());
|
let sig = callee_ty.fn_sig(bx.tcx());
|
||||||
let sig = bx.tcx().normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), &sig);
|
let sig = bx.tcx().normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), sig);
|
||||||
let arg_tys = sig.inputs();
|
let arg_tys = sig.inputs();
|
||||||
let ret_ty = sig.output();
|
let ret_ty = sig.output();
|
||||||
let name = bx.tcx().item_name(def_id);
|
let name = bx.tcx().item_name(def_id);
|
||||||
@ -83,9 +83,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
sym::unreachable => {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
sym::va_start => bx.va_start(args[0].immediate()),
|
sym::va_start => bx.va_start(args[0].immediate()),
|
||||||
sym::va_end => bx.va_end(args[0].immediate()),
|
sym::va_end => bx.va_end(args[0].immediate()),
|
||||||
sym::size_of_val => {
|
sym::size_of_val => {
|
||||||
@ -106,8 +103,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
bx.const_usize(bx.layout_of(tp_ty).align.abi.bytes())
|
bx.const_usize(bx.layout_of(tp_ty).align.abi.bytes())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sym::size_of
|
sym::pref_align_of
|
||||||
| sym::pref_align_of
|
|
||||||
| sym::min_align_of
|
| sym::min_align_of
|
||||||
| sym::needs_drop
|
| sym::needs_drop
|
||||||
| sym::type_id
|
| sym::type_id
|
||||||
@ -119,10 +115,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
OperandRef::from_const(bx, value, ret_ty).immediate_or_packed_pair(bx)
|
OperandRef::from_const(bx, value, ret_ty).immediate_or_packed_pair(bx)
|
||||||
}
|
}
|
||||||
// Effectively no-op
|
|
||||||
sym::forget => {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
sym::offset => {
|
sym::offset => {
|
||||||
let ptr = args[0].immediate();
|
let ptr = args[0].immediate();
|
||||||
let offset = args[1].immediate();
|
let offset = args[1].immediate();
|
||||||
@ -218,9 +210,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
sym::add_with_overflow
|
sym::add_with_overflow
|
||||||
| sym::sub_with_overflow
|
| sym::sub_with_overflow
|
||||||
| sym::mul_with_overflow
|
| sym::mul_with_overflow
|
||||||
| sym::wrapping_add
|
|
||||||
| sym::wrapping_sub
|
|
||||||
| sym::wrapping_mul
|
|
||||||
| sym::unchecked_div
|
| sym::unchecked_div
|
||||||
| sym::unchecked_rem
|
| sym::unchecked_rem
|
||||||
| sym::unchecked_shl
|
| sym::unchecked_shl
|
||||||
@ -254,9 +243,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
sym::wrapping_add => bx.add(args[0].immediate(), args[1].immediate()),
|
|
||||||
sym::wrapping_sub => bx.sub(args[0].immediate(), args[1].immediate()),
|
|
||||||
sym::wrapping_mul => bx.mul(args[0].immediate(), args[1].immediate()),
|
|
||||||
sym::exact_div => {
|
sym::exact_div => {
|
||||||
if signed {
|
if signed {
|
||||||
bx.exactsdiv(args[0].immediate(), args[1].immediate())
|
bx.exactsdiv(args[0].immediate(), args[1].immediate())
|
||||||
@ -437,16 +423,20 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
match split[1] {
|
match split[1] {
|
||||||
"cxchg" | "cxchgweak" => {
|
"cxchg" | "cxchgweak" => {
|
||||||
let ty = substs.type_at(0);
|
let ty = substs.type_at(0);
|
||||||
if int_type_width_signed(ty, bx.tcx()).is_some() {
|
if int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_unsafe_ptr() {
|
||||||
let weak = split[1] == "cxchgweak";
|
let weak = split[1] == "cxchgweak";
|
||||||
let pair = bx.atomic_cmpxchg(
|
let mut dst = args[0].immediate();
|
||||||
args[0].immediate(),
|
let mut cmp = args[1].immediate();
|
||||||
args[1].immediate(),
|
let mut src = args[2].immediate();
|
||||||
args[2].immediate(),
|
if ty.is_unsafe_ptr() {
|
||||||
order,
|
// Some platforms do not support atomic operations on pointers,
|
||||||
failorder,
|
// so we cast to integer first.
|
||||||
weak,
|
let ptr_llty = bx.type_ptr_to(bx.type_isize());
|
||||||
);
|
dst = bx.pointercast(dst, ptr_llty);
|
||||||
|
cmp = bx.ptrtoint(cmp, bx.type_isize());
|
||||||
|
src = bx.ptrtoint(src, bx.type_isize());
|
||||||
|
}
|
||||||
|
let pair = bx.atomic_cmpxchg(dst, cmp, src, order, failorder, weak);
|
||||||
let val = bx.extract_value(pair, 0);
|
let val = bx.extract_value(pair, 0);
|
||||||
let success = bx.extract_value(pair, 1);
|
let success = bx.extract_value(pair, 1);
|
||||||
let val = bx.from_immediate(val);
|
let val = bx.from_immediate(val);
|
||||||
@ -464,9 +454,23 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
|
|
||||||
"load" => {
|
"load" => {
|
||||||
let ty = substs.type_at(0);
|
let ty = substs.type_at(0);
|
||||||
if int_type_width_signed(ty, bx.tcx()).is_some() {
|
if int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_unsafe_ptr() {
|
||||||
let size = bx.layout_of(ty).size;
|
let layout = bx.layout_of(ty);
|
||||||
bx.atomic_load(args[0].immediate(), order, size)
|
let size = layout.size;
|
||||||
|
let mut source = args[0].immediate();
|
||||||
|
if ty.is_unsafe_ptr() {
|
||||||
|
// Some platforms do not support atomic operations on pointers,
|
||||||
|
// so we cast to integer first...
|
||||||
|
let ptr_llty = bx.type_ptr_to(bx.type_isize());
|
||||||
|
source = bx.pointercast(source, ptr_llty);
|
||||||
|
}
|
||||||
|
let result = bx.atomic_load(source, order, size);
|
||||||
|
if ty.is_unsafe_ptr() {
|
||||||
|
// ... and then cast the result back to a pointer
|
||||||
|
bx.inttoptr(result, bx.backend_type(layout))
|
||||||
|
} else {
|
||||||
|
result
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return invalid_monomorphization(ty);
|
return invalid_monomorphization(ty);
|
||||||
}
|
}
|
||||||
@ -474,9 +478,18 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
|
|
||||||
"store" => {
|
"store" => {
|
||||||
let ty = substs.type_at(0);
|
let ty = substs.type_at(0);
|
||||||
if int_type_width_signed(ty, bx.tcx()).is_some() {
|
if int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_unsafe_ptr() {
|
||||||
let size = bx.layout_of(ty).size;
|
let size = bx.layout_of(ty).size;
|
||||||
bx.atomic_store(args[1].immediate(), args[0].immediate(), order, size);
|
let mut val = args[1].immediate();
|
||||||
|
let mut ptr = args[0].immediate();
|
||||||
|
if ty.is_unsafe_ptr() {
|
||||||
|
// Some platforms do not support atomic operations on pointers,
|
||||||
|
// so we cast to integer first.
|
||||||
|
let ptr_llty = bx.type_ptr_to(bx.type_isize());
|
||||||
|
ptr = bx.pointercast(ptr, ptr_llty);
|
||||||
|
val = bx.ptrtoint(val, bx.type_isize());
|
||||||
|
}
|
||||||
|
bx.atomic_store(val, ptr, order, size);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
return invalid_monomorphization(ty);
|
return invalid_monomorphization(ty);
|
||||||
@ -511,8 +524,19 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let ty = substs.type_at(0);
|
let ty = substs.type_at(0);
|
||||||
if int_type_width_signed(ty, bx.tcx()).is_some() {
|
if int_type_width_signed(ty, bx.tcx()).is_some()
|
||||||
bx.atomic_rmw(atom_op, args[0].immediate(), args[1].immediate(), order)
|
|| (ty.is_unsafe_ptr() && op == "xchg")
|
||||||
|
{
|
||||||
|
let mut ptr = args[0].immediate();
|
||||||
|
let mut val = args[1].immediate();
|
||||||
|
if ty.is_unsafe_ptr() {
|
||||||
|
// Some platforms do not support atomic operations on pointers,
|
||||||
|
// so we cast to integer first.
|
||||||
|
let ptr_llty = bx.type_ptr_to(bx.type_isize());
|
||||||
|
ptr = bx.pointercast(ptr, ptr_llty);
|
||||||
|
val = bx.ptrtoint(val, bx.type_isize());
|
||||||
|
}
|
||||||
|
bx.atomic_rmw(atom_op, ptr, val, order)
|
||||||
} else {
|
} else {
|
||||||
return invalid_monomorphization(ty);
|
return invalid_monomorphization(ty);
|
||||||
}
|
}
|
||||||
|
@ -87,7 +87,7 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||||
pub fn monomorphize<T>(&self, value: &T) -> T
|
pub fn monomorphize<T>(&self, value: T) -> T
|
||||||
where
|
where
|
||||||
T: Copy + TypeFoldable<'tcx>,
|
T: Copy + TypeFoldable<'tcx>,
|
||||||
{
|
{
|
||||||
@ -186,7 +186,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||||||
caller_location: None,
|
caller_location: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
fx.per_local_var_debug_info = fx.compute_per_local_var_debug_info();
|
fx.per_local_var_debug_info = fx.compute_per_local_var_debug_info(&mut bx);
|
||||||
|
|
||||||
for const_ in &mir.required_consts {
|
for const_ in &mir.required_consts {
|
||||||
if let Err(err) = fx.eval_mir_constant(const_) {
|
if let Err(err) = fx.eval_mir_constant(const_) {
|
||||||
@ -208,7 +208,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||||||
|
|
||||||
let mut allocate_local = |local| {
|
let mut allocate_local = |local| {
|
||||||
let decl = &mir.local_decls[local];
|
let decl = &mir.local_decls[local];
|
||||||
let layout = bx.layout_of(fx.monomorphize(&decl.ty));
|
let layout = bx.layout_of(fx.monomorphize(decl.ty));
|
||||||
assert!(!layout.ty.has_erasable_regions());
|
assert!(!layout.ty.has_erasable_regions());
|
||||||
|
|
||||||
if local == mir::RETURN_PLACE && fx.fn_abi.ret.is_indirect() {
|
if local == mir::RETURN_PLACE && fx.fn_abi.ret.is_indirect() {
|
||||||
@ -364,7 +364,7 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||||||
// to reconstruct it into a tuple local variable, from multiple
|
// to reconstruct it into a tuple local variable, from multiple
|
||||||
// individual LLVM function arguments.
|
// individual LLVM function arguments.
|
||||||
|
|
||||||
let arg_ty = fx.monomorphize(&arg_decl.ty);
|
let arg_ty = fx.monomorphize(arg_decl.ty);
|
||||||
let tupled_arg_tys = match arg_ty.kind() {
|
let tupled_arg_tys = match arg_ty.kind() {
|
||||||
ty::Tuple(tys) => tys,
|
ty::Tuple(tys) => tys,
|
||||||
_ => bug!("spread argument isn't a tuple?!"),
|
_ => bug!("spread argument isn't a tuple?!"),
|
||||||
@ -385,7 +385,7 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if fx.fn_abi.c_variadic && arg_index == fx.fn_abi.args.len() {
|
if fx.fn_abi.c_variadic && arg_index == fx.fn_abi.args.len() {
|
||||||
let arg_ty = fx.monomorphize(&arg_decl.ty);
|
let arg_ty = fx.monomorphize(arg_decl.ty);
|
||||||
|
|
||||||
let va_list = PlaceRef::alloca(bx, bx.layout_of(arg_ty));
|
let va_list = PlaceRef::alloca(bx, bx.layout_of(arg_ty));
|
||||||
bx.va_start(va_list.llval);
|
bx.va_start(va_list.llval);
|
||||||
|
@ -452,7 +452,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||||||
bx.abort();
|
bx.abort();
|
||||||
// We still have to return an operand but it doesn't matter,
|
// We still have to return an operand but it doesn't matter,
|
||||||
// this code is unreachable.
|
// this code is unreachable.
|
||||||
let ty = self.monomorphize(&constant.literal.ty);
|
let ty = self.monomorphize(constant.literal.ty);
|
||||||
let layout = bx.cx().layout_of(ty);
|
let layout = bx.cx().layout_of(ty);
|
||||||
bx.load_operand(PlaceRef::new_sized(
|
bx.load_operand(PlaceRef::new_sized(
|
||||||
bx.cx().const_undef(bx.cx().type_ptr_to(bx.cx().backend_type(layout))),
|
bx.cx().const_undef(bx.cx().type_ptr_to(bx.cx().backend_type(layout))),
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user