diff --git a/.gitignore b/.gitignore
index e5ca3e503130..ce797a7a8371 100644
--- a/.gitignore
+++ b/.gitignore
@@ -41,7 +41,7 @@ no_llvm_build
/inst/
/llvm/
/mingw-build/
-/build/
+build/
/build-rust-analyzer/
/dist/
/unicode-downloads
diff --git a/.gitmodules b/.gitmodules
index 4011a6fa6b95..e79f2f089c1e 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,6 +1,3 @@
-[submodule "src/rust-installer"]
- path = src/tools/rust-installer
- url = https://github.com/rust-lang/rust-installer.git
[submodule "src/doc/nomicon"]
path = src/doc/nomicon
url = https://github.com/rust-lang/nomicon.git
diff --git a/Cargo.lock b/Cargo.lock
index 5530541cdd0f..7776964adf9f 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -42,6 +42,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf6ccdb167abbf410dcb915cabd428929d7f6a04980b54a11f26a39f1c7f7107"
dependencies = [
"cfg-if",
+ "getrandom",
"once_cell",
"version_check",
]
@@ -112,6 +113,12 @@ dependencies = [
"object 0.29.0",
]
+[[package]]
+name = "arc-swap"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6"
+
[[package]]
name = "array_tool"
version = "1.0.3"
@@ -132,47 +139,36 @@ checksum = "5a2f58b0bb10c380af2b26e57212856b8c9a59e0925b4c20f4a174a49734eaf7"
[[package]]
name = "askama"
-version = "0.11.0"
+version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4d8f355701c672c2ba3d718acbd213f740beea577cc4eae66accdffe15be1882"
+checksum = "47cbc3cf73fa8d9833727bbee4835ba5c421a0d65b72daf9a7b5d0e0f9cfb57e"
dependencies = [
"askama_derive",
"askama_escape",
- "askama_shared",
]
[[package]]
name = "askama_derive"
-version = "0.11.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "84704cab5b7ae0fd3a9f78ee5eb7b27f3749df445f04623db6633459ae283267"
-dependencies = [
- "askama_shared",
- "proc-macro2",
- "syn",
-]
-
-[[package]]
-name = "askama_escape"
-version = "0.10.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a1bb320f97e6edf9f756bf015900038e43c7700e059688e5724a928c8f3b8d5"
-
-[[package]]
-name = "askama_shared"
version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dae03eebba55a2697a376e58b573a29fe36893157173ac8df312ad85f3c0e012"
+checksum = "e80b5ad1afe82872b7aa3e9de9b206ecb85584aa324f0f60fa4c903ce935936b"
dependencies = [
- "askama_escape",
+ "basic-toml",
+ "mime",
+ "mime_guess",
"nom",
"proc-macro2",
"quote",
"serde",
"syn",
- "toml 0.5.7",
]
+[[package]]
+name = "askama_escape"
+version = "0.10.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "619743e34b5ba4e9703bba34deac3427c72507c7159f5fd030aea8cac0cfe341"
+
[[package]]
name = "atty"
version = "0.2.14"
@@ -213,9 +209,9 @@ checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce"
[[package]]
name = "base64"
-version = "0.13.1"
+version = "0.21.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
+checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a"
[[package]]
name = "base64ct"
@@ -223,6 +219,15 @@ version = "1.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b645a089122eccb6111b4f81cbc1a49f5900ac4666bb93ac027feaecf15607bf"
+[[package]]
+name = "basic-toml"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c0de75129aa8d0cceaf750b89013f0e08804d6ec61416da787b35ad0d7cddf1"
+dependencies = [
+ "serde",
+]
+
[[package]]
name = "bitflags"
version = "1.3.2"
@@ -260,9 +265,9 @@ dependencies = [
[[package]]
name = "bstr"
-version = "1.0.1"
+version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fca0852af221f458706eb0725c03e4ed6c46af9ac98e6a689d5e634215d594dd"
+checksum = "5ffdb39cb703212f3c11973452c2861b972f757b021158f3516ba10f2fa8b2c1"
dependencies = [
"memchr",
"once_cell",
@@ -270,13 +275,22 @@ dependencies = [
"serde",
]
+[[package]]
+name = "btoi"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9dd6407f73a9b8b6162d8a2ef999fe6afd7cc15902ebf42c5cd296addf17e0ad"
+dependencies = [
+ "num-traits",
+]
+
[[package]]
name = "build-manifest"
version = "0.1.0"
dependencies = [
"anyhow",
"flate2",
- "hex 0.4.2",
+ "hex",
"rayon",
"serde",
"serde_json",
@@ -358,8 +372,10 @@ dependencies = [
"fwdansi",
"git2",
"git2-curl",
+ "gix",
+ "gix-features",
"glob",
- "hex 0.4.2",
+ "hex",
"hmac",
"home",
"http-auth",
@@ -498,18 +514,18 @@ dependencies = [
[[package]]
name = "cargo-util"
-version = "0.2.3"
+version = "0.2.4"
dependencies = [
"anyhow",
"core-foundation",
- "crypto-hash",
"filetime",
- "hex 0.4.2",
+ "hex",
"jobserver",
"libc",
"log",
"miow 0.5.0",
"same-file",
+ "sha2",
"shell-escape",
"tempfile",
"walkdir",
@@ -796,6 +812,12 @@ dependencies = [
"rustc-semver",
]
+[[package]]
+name = "clru"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8191fa7302e03607ff0e237d4246cc043ff5b3cb9409d995172ba3bea16b807"
+
[[package]]
name = "collect-license-metadata"
version = "0.1.0"
@@ -844,24 +866,6 @@ dependencies = [
"winapi",
]
-[[package]]
-name = "commoncrypto"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d056a8586ba25a1e4d61cb090900e495952c7886786fc55f909ab2f819b69007"
-dependencies = [
- "commoncrypto-sys",
-]
-
-[[package]]
-name = "commoncrypto-sys"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1fed34f46747aa73dfaa578069fd8279d2818ade2b55f38f22a9401c7f4083e2"
-dependencies = [
- "libc",
-]
-
[[package]]
name = "compiler_builtins"
version = "0.1.87"
@@ -1081,18 +1085,6 @@ dependencies = [
"typenum",
]
-[[package]]
-name = "crypto-hash"
-version = "0.3.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a77162240fd97248d19a564a565eb563a3f592b386e4136fb300909e67dddca"
-dependencies = [
- "commoncrypto",
- "hex 0.3.2",
- "openssl",
- "winapi",
-]
-
[[package]]
name = "cstr"
version = "0.2.8"
@@ -1297,9 +1289,9 @@ dependencies = [
[[package]]
name = "dunce"
-version = "1.0.2"
+version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "453440c271cf5577fd2a40e4942540cb7d0d2f85e27c8d07dd0023c925a67541"
+checksum = "0bd4b30a6560bbd9b4620f4de34c3f14f60848e58a9b7216801afcb4c7b31c3c"
[[package]]
name = "ecdsa"
@@ -1509,14 +1501,14 @@ checksum = "a214f5bb88731d436478f3ae1f8a277b62124089ba9fb67f4f93fb100ef73c90"
[[package]]
name = "filetime"
-version = "0.2.14"
+version = "0.2.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d34cfa13a63ae058bfa601fe9e313bbdb3746427c1459185464ce0fcf62e1e8"
+checksum = "8a3de6e8d11b22ff9edc6d916f890800597d60f8b2da1caf2955c274638d6412"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
- "winapi",
+ "windows-sys 0.45.0",
]
[[package]]
@@ -1818,6 +1810,559 @@ dependencies = [
"url",
]
+[[package]]
+name = "gix"
+version = "0.39.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dabfac58aecb4a38cdd2568de66eb1f0d968fd6726f5a80cb8bea7944ef10cc0"
+dependencies = [
+ "gix-actor",
+ "gix-attributes",
+ "gix-config",
+ "gix-credentials",
+ "gix-date",
+ "gix-diff",
+ "gix-discover",
+ "gix-features",
+ "gix-glob",
+ "gix-hash",
+ "gix-hashtable",
+ "gix-index",
+ "gix-lock",
+ "gix-mailmap",
+ "gix-object",
+ "gix-odb",
+ "gix-pack",
+ "gix-path",
+ "gix-prompt",
+ "gix-protocol",
+ "gix-ref",
+ "gix-refspec",
+ "gix-revision",
+ "gix-sec",
+ "gix-tempfile",
+ "gix-transport",
+ "gix-traverse",
+ "gix-url",
+ "gix-validate",
+ "gix-worktree",
+ "log",
+ "once_cell",
+ "prodash",
+ "signal-hook",
+ "smallvec",
+ "thiserror",
+ "unicode-normalization",
+]
+
+[[package]]
+name = "gix-actor"
+version = "0.19.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dc22b0cdc52237667c301dd7cdc6ead8f8f73c9f824e9942c8ebd6b764f6c0bf"
+dependencies = [
+ "bstr 1.3.0",
+ "btoi",
+ "gix-date",
+ "itoa",
+ "nom",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-attributes"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2231a25934a240d0a4b6f4478401c73ee81d8be52de0293eedbc172334abf3e1"
+dependencies = [
+ "bstr 1.3.0",
+ "gix-features",
+ "gix-glob",
+ "gix-path",
+ "gix-quote",
+ "thiserror",
+ "unicode-bom",
+]
+
+[[package]]
+name = "gix-bitmap"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "024bca0c7187517bda5ea24ab148c9ca8208dd0c3e2bea88cdb2008f91791a6d"
+dependencies = [
+ "thiserror",
+]
+
+[[package]]
+name = "gix-chunk"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b0d39583cab06464b8bf73b3f1707458270f0e7383cb24c3c9c1a16e6f792978"
+dependencies = [
+ "thiserror",
+]
+
+[[package]]
+name = "gix-command"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2c6f75c1e0f924de39e750880a6e21307194bb1ab773efe3c7d2d787277f8ab"
+dependencies = [
+ "bstr 1.3.0",
+]
+
+[[package]]
+name = "gix-config"
+version = "0.18.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "52c62e26ce11f607712e4f49a0a192ed87675d30187fd61be070abbd607d12f1"
+dependencies = [
+ "bstr 1.3.0",
+ "gix-config-value",
+ "gix-features",
+ "gix-glob",
+ "gix-path",
+ "gix-ref",
+ "gix-sec",
+ "memchr",
+ "nom",
+ "once_cell",
+ "smallvec",
+ "thiserror",
+ "unicode-bom",
+]
+
+[[package]]
+name = "gix-config-value"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "693d4a4ba0531e46fe558459557a5b29fb86c3e4b2666c1c0861d93c7c678331"
+dependencies = [
+ "bitflags",
+ "bstr 1.3.0",
+ "gix-path",
+ "libc",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-credentials"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5be32b5fe339a31b8e53fa854081dc914c45020dcb64637f3c21baf69c96fc1b"
+dependencies = [
+ "bstr 1.3.0",
+ "gix-command",
+ "gix-config-value",
+ "gix-path",
+ "gix-prompt",
+ "gix-sec",
+ "gix-url",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-date"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b96271912ce39822501616f177dea7218784e6c63be90d5f36322ff3a722aae2"
+dependencies = [
+ "bstr 1.3.0",
+ "itoa",
+ "thiserror",
+ "time 0.3.17",
+]
+
+[[package]]
+name = "gix-diff"
+version = "0.28.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "585b0834d4b6791a848637c4e109545fda9b0f29b591ba55edb33ceda6e7856b"
+dependencies = [
+ "gix-hash",
+ "gix-object",
+ "imara-diff",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-discover"
+version = "0.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "91c204adba5ebd211c74735cbb65817d277e154486bac0dffa3701f163b80350"
+dependencies = [
+ "bstr 1.3.0",
+ "dunce",
+ "gix-hash",
+ "gix-path",
+ "gix-ref",
+ "gix-sec",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-features"
+version = "0.28.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5e6a9dfa7b3c1a99315203e8b97f8f99f3bd95731590607abeaa5ca31bc41fe3"
+dependencies = [
+ "bytes",
+ "crc32fast",
+ "crossbeam-channel",
+ "flate2",
+ "gix-hash",
+ "libc",
+ "once_cell",
+ "parking_lot 0.12.1",
+ "prodash",
+ "sha1_smol",
+ "thiserror",
+ "walkdir",
+]
+
+[[package]]
+name = "gix-glob"
+version = "0.5.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93e43efd776bc543f46f0fd0ca3d920c37af71a764a16f2aebd89765e9ff2993"
+dependencies = [
+ "bitflags",
+ "bstr 1.3.0",
+]
+
+[[package]]
+name = "gix-hash"
+version = "0.10.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0c0c5a9f4d621d4f4ea046bb331df5c746ca735b8cae5b234cc2be70ee4dbef0"
+dependencies = [
+ "hex",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-hashtable"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9609c1b8f36f12968e6a6098f7cdb52004f7d42d570f47a2d6d7c16612f19acb"
+dependencies = [
+ "gix-hash",
+ "hashbrown 0.13.1",
+ "parking_lot 0.12.1",
+]
+
+[[package]]
+name = "gix-index"
+version = "0.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c12caf7886c7ba06f2b28835cdc2be1dca86bd047d00299d2d49e707ce1c2616"
+dependencies = [
+ "bitflags",
+ "bstr 1.3.0",
+ "btoi",
+ "filetime",
+ "gix-bitmap",
+ "gix-features",
+ "gix-hash",
+ "gix-lock",
+ "gix-object",
+ "gix-traverse",
+ "itoa",
+ "memmap2 0.5.10",
+ "smallvec",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-lock"
+version = "4.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "66119ff8a4a395d0ea033fef718bc85f8b4f0855874f4ce1e005fc16cfe1f66e"
+dependencies = [
+ "fastrand",
+ "gix-tempfile",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-mailmap"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b66aea5e52875cd4915f4957a6f4b75831a36981e2ec3f5fad9e370e444fe1a"
+dependencies = [
+ "bstr 1.3.0",
+ "gix-actor",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-object"
+version = "0.28.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8df068db9180ee935fbb70504848369e270bdcb576b05c0faa8b9fd3b86fc017"
+dependencies = [
+ "bstr 1.3.0",
+ "btoi",
+ "gix-actor",
+ "gix-features",
+ "gix-hash",
+ "gix-validate",
+ "hex",
+ "itoa",
+ "nom",
+ "smallvec",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-odb"
+version = "0.42.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e9a5f9e1afbd509761977a2ea02869cedaaba500b4e783deb2e4de5179a55a80"
+dependencies = [
+ "arc-swap",
+ "gix-features",
+ "gix-hash",
+ "gix-object",
+ "gix-pack",
+ "gix-path",
+ "gix-quote",
+ "parking_lot 0.12.1",
+ "tempfile",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-pack"
+version = "0.32.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e51db84e1459a8022e518d40a8778028d793dbb28e4d35c9a5eaf92658fb0775"
+dependencies = [
+ "clru",
+ "gix-chunk",
+ "gix-diff",
+ "gix-features",
+ "gix-hash",
+ "gix-hashtable",
+ "gix-object",
+ "gix-path",
+ "gix-tempfile",
+ "gix-traverse",
+ "memmap2 0.5.10",
+ "parking_lot 0.12.1",
+ "smallvec",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-packetline"
+version = "0.14.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d63e5e5a9a92d4fc6b63ff9d94954d25c779ce25c98d5bbe2e4399aa42f7073c"
+dependencies = [
+ "bstr 1.3.0",
+ "hex",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-path"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f6c104a66dec149cb8f7aaafc6ab797654cf82d67f050fd0cb7e7294e328354b"
+dependencies = [
+ "bstr 1.3.0",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-prompt"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a20cebf73229debaa82574c4fd20dcaf00fa8d4bfce823a862c4e990d7a0b5b4"
+dependencies = [
+ "gix-command",
+ "gix-config-value",
+ "nix",
+ "parking_lot 0.12.1",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-protocol"
+version = "0.28.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d372ab11d5d28ac21800e3f1a6603a67c1ead57f6f5fab07e1e73e960f331c1"
+dependencies = [
+ "bstr 1.3.0",
+ "btoi",
+ "gix-credentials",
+ "gix-features",
+ "gix-hash",
+ "gix-transport",
+ "maybe-async",
+ "nom",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-quote"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a282f5a8d9ee0b09ec47390ac727350c48f2f5c76d803cd8da6b3e7ad56e0bcb"
+dependencies = [
+ "bstr 1.3.0",
+ "btoi",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-ref"
+version = "0.26.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90a0ed29e581f04b904ecd0c32b11f33b8209b5a0af9c43f415249a4f2fba632"
+dependencies = [
+ "gix-actor",
+ "gix-features",
+ "gix-hash",
+ "gix-lock",
+ "gix-object",
+ "gix-path",
+ "gix-tempfile",
+ "gix-validate",
+ "memmap2 0.5.10",
+ "nom",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-refspec"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aba332462bda2e8efeae4302b39a6ed01ad56ef772fd5b7ef197cf2798294d65"
+dependencies = [
+ "bstr 1.3.0",
+ "gix-hash",
+ "gix-revision",
+ "gix-validate",
+ "smallvec",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-revision"
+version = "0.12.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed98e4a0254953c64bc913bd23146a1de662067d5cf974cbdde396958b39e5b0"
+dependencies = [
+ "bstr 1.3.0",
+ "gix-date",
+ "gix-hash",
+ "gix-hashtable",
+ "gix-object",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-sec"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e8ffa5bf0772f9b01de501c035b6b084cf9b8bb07dec41e3afc6a17336a65f47"
+dependencies = [
+ "bitflags",
+ "dirs",
+ "gix-path",
+ "libc",
+ "windows",
+]
+
+[[package]]
+name = "gix-tempfile"
+version = "4.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "88751f247234b1f73c8e8056fd835a0999b04e596e052302cb71186005dc4b27"
+dependencies = [
+ "libc",
+ "once_cell",
+ "parking_lot 0.12.1",
+ "signal-hook",
+ "signal-hook-registry",
+ "tempfile",
+]
+
+[[package]]
+name = "gix-transport"
+version = "0.27.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d633947b36a2fbbc089195bdc71621158f1660c2ff2a6b12b0279c16e2f764bc"
+dependencies = [
+ "base64",
+ "bstr 1.3.0",
+ "curl",
+ "gix-command",
+ "gix-credentials",
+ "gix-features",
+ "gix-packetline",
+ "gix-quote",
+ "gix-sec",
+ "gix-url",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-traverse"
+version = "0.24.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dd9a4a07bb22168dc79c60e1a6a41919d198187ca83d8a5940ad8d7122a45df3"
+dependencies = [
+ "gix-hash",
+ "gix-hashtable",
+ "gix-object",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-url"
+version = "0.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "044072b7ce8601b62dcec841b92129f5cc677072823324121b395d766ac5f528"
+dependencies = [
+ "bstr 1.3.0",
+ "gix-features",
+ "gix-path",
+ "home",
+ "thiserror",
+ "url",
+]
+
+[[package]]
+name = "gix-validate"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b69ddb780ea1465255e66818d75b7098371c58dbc9560da4488a44b9f5c7e443"
+dependencies = [
+ "bstr 1.3.0",
+ "thiserror",
+]
+
+[[package]]
+name = "gix-worktree"
+version = "0.14.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b7cb9af6e56152953d8fe113c4f9d7cf60cf7a982362711e9200a255579b49cb"
+dependencies = [
+ "bstr 1.3.0",
+ "gix-attributes",
+ "gix-features",
+ "gix-glob",
+ "gix-hash",
+ "gix-index",
+ "gix-object",
+ "gix-path",
+ "io-close",
+ "thiserror",
+]
+
[[package]]
name = "glob"
version = "0.3.0"
@@ -1933,12 +2478,6 @@ dependencies = [
"rustc-std-workspace-core",
]
-[[package]]
-name = "hex"
-version = "0.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77"
-
[[package]]
name = "hex"
version = "0.4.2"
@@ -2132,6 +2671,16 @@ dependencies = [
"version_check",
]
+[[package]]
+name = "imara-diff"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e98c1d0ad70fc91b8b9654b1f33db55e59579d3b3de2bffdced0fdb810570cb8"
+dependencies = [
+ "ahash 0.8.2",
+ "hashbrown 0.12.3",
+]
+
[[package]]
name = "indenter"
version = "0.3.3"
@@ -2201,6 +2750,16 @@ dependencies = [
"unic-langid",
]
+[[package]]
+name = "io-close"
+version = "0.3.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9cadcf447f06744f8ce713d2d6239bb5bde2c357a452397a9ed90c625da390bc"
+dependencies = [
+ "libc",
+ "winapi",
+]
+
[[package]]
name = "io-lifetimes"
version = "1.0.3"
@@ -2234,9 +2793,9 @@ dependencies = [
[[package]]
name = "itoa"
-version = "1.0.2"
+version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d"
+checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
[[package]]
name = "jemalloc-sys"
@@ -2287,6 +2846,7 @@ dependencies = [
"anyhow",
"clap 4.1.4",
"fs-err",
+ "rustc-hash",
"rustdoc-json-types",
"serde",
"serde_json",
@@ -2521,6 +3081,17 @@ version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
+[[package]]
+name = "maybe-async"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0f1b8c13cb1f814b634a96b2c725449fe7ed464a7b8781de8688be5ffbd3f305"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
[[package]]
name = "md-5"
version = "0.10.0"
@@ -2578,7 +3149,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cbdc226fa10994e8f66a4d2f6f000148bc563a1c671b6dcd2135737018033d8a"
dependencies = [
"log",
- "memmap2",
+ "memmap2 0.2.1",
"parking_lot 0.11.2",
"perf-event-open-sys",
"rustc-hash",
@@ -2604,6 +3175,15 @@ dependencies = [
"libc",
]
+[[package]]
+name = "memmap2"
+version = "0.5.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327"
+dependencies = [
+ "libc",
+]
+
[[package]]
name = "memoffset"
version = "0.7.1"
@@ -2613,6 +3193,22 @@ dependencies = [
"autocfg",
]
+[[package]]
+name = "mime"
+version = "0.3.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
+
+[[package]]
+name = "mime_guess"
+version = "2.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef"
+dependencies = [
+ "mime",
+ "unicase",
+]
+
[[package]]
name = "minifier"
version = "0.2.2"
@@ -2689,6 +3285,18 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54"
+[[package]]
+name = "nix"
+version = "0.26.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a"
+dependencies = [
+ "bitflags",
+ "cfg-if",
+ "libc",
+ "static_assertions",
+]
+
[[package]]
name = "nom"
version = "7.1.0"
@@ -2744,6 +3352,15 @@ dependencies = [
"libc",
]
+[[package]]
+name = "num_threads"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44"
+dependencies = [
+ "libc",
+]
+
[[package]]
name = "object"
version = "0.29.0"
@@ -3244,6 +3861,15 @@ dependencies = [
"std",
]
+[[package]]
+name = "prodash"
+version = "23.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d73c6b64cb5b99eb63ca97d378685712617ec0172ff5c04cd47a489d3e2c51f8"
+dependencies = [
+ "parking_lot 0.12.1",
+]
+
[[package]]
name = "profiler_builtins"
version = "0.0.0"
@@ -3590,11 +4216,14 @@ dependencies = [
"bstr 0.2.17",
"clap 3.2.20",
"getrandom",
+ "hashbrown 0.12.3",
"libc",
"libz-sys",
+ "once_cell",
"rand",
"regex",
"serde_json",
+ "smallvec",
"syn",
"url",
"winapi",
@@ -3885,7 +4514,7 @@ dependencies = [
"jobserver",
"libc",
"measureme",
- "memmap2",
+ "memmap2 0.2.1",
"parking_lot 0.11.2",
"rustc-hash",
"rustc-rayon",
@@ -4654,15 +5283,9 @@ dependencies = [
name = "rustc_smir"
version = "0.0.0"
dependencies = [
- "rustc_borrowck",
- "rustc_driver",
- "rustc_hir",
- "rustc_interface",
"rustc_middle",
- "rustc_mir_dataflow",
- "rustc_mir_transform",
- "rustc_serialize",
- "rustc_trait_selection",
+ "rustc_span",
+ "tracing",
]
[[package]]
@@ -4850,6 +5473,7 @@ dependencies = [
name = "rustdoc-json-types"
version = "0.1.0"
dependencies = [
+ "rustc-hash",
"serde",
"serde_json",
]
@@ -5098,6 +5722,12 @@ dependencies = [
"digest",
]
+[[package]]
+name = "sha1_smol"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012"
+
[[package]]
name = "sha2"
version = "0.10.6"
@@ -5130,6 +5760,25 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42a568c8f2cd051a4d283bd6eb0343ac214c1b0f1ac19f93e1175b2dee38c73d"
+[[package]]
+name = "signal-hook"
+version = "0.3.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "732768f1176d21d09e076c23a93123d40bba92d50c4058da34d45c8de8e682b9"
+dependencies = [
+ "libc",
+ "signal-hook-registry",
+]
+
+[[package]]
+name = "signal-hook-registry"
+version = "1.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1"
+dependencies = [
+ "libc",
+]
+
[[package]]
name = "signature"
version = "1.6.4"
@@ -5170,9 +5819,9 @@ checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
[[package]]
name = "smallvec"
-version = "1.8.1"
+version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc88c725d61fc6c3132893370cac4a0200e3fedf5da8331c570664b1987f5ca2"
+checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
[[package]]
name = "snap"
@@ -5595,6 +6244,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376"
dependencies = [
"itoa",
+ "libc",
+ "num_threads",
"serde",
"time-core",
"time-macros",
@@ -5835,7 +6486,7 @@ version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54ddb6f31025943e2f9d59237f433711c461a43d9415974c3eb3a4902edc1c1f"
dependencies = [
- "bstr 1.0.1",
+ "bstr 1.3.0",
"cargo_metadata 0.15.3",
"color-eyre",
"colored",
@@ -5958,6 +6609,12 @@ dependencies = [
"matches",
]
+[[package]]
+name = "unicode-bom"
+version = "1.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "63ec69f541d875b783ca40184d655f2927c95f0bffd486faa83cd3ac3529ec32"
+
[[package]]
name = "unicode-ident"
version = "1.0.5"
@@ -6226,6 +6883,21 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+[[package]]
+name = "windows"
+version = "0.43.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "04662ed0e3e5630dfa9b26e4cb823b817f1a9addda855d973a9458c236556244"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
[[package]]
name = "windows-sys"
version = "0.42.0"
diff --git a/RELEASES.md b/RELEASES.md
index 00d0171de6df..4e974bbe9747 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1,3 +1,99 @@
+Version 1.68.0 (2023-03-09)
+==========================
+
+
+
+Language
+--------
+
+- [Stabilize default_alloc_error_handler](https://github.com/rust-lang/rust/pull/102318/)
+ This allows usage of `alloc` on stable without requiring the
+ definition of a handler for allocation failure. Defining custom handlers is still unstable.
+- [Stabilize `efiapi` calling convention.](https://github.com/rust-lang/rust/pull/105795/)
+- [Remove implicit promotion for types with drop glue](https://github.com/rust-lang/rust/pull/105085/)
+
+
+
+Compiler
+--------
+
+- [Change `bindings_with_variant_name` to deny-by-default](https://github.com/rust-lang/rust/pull/104154/)
+- [Allow .. to be parsed as let initializer](https://github.com/rust-lang/rust/pull/105701/)
+- [Add `armv7-sony-vita-newlibeabihf` as a tier 3 target](https://github.com/rust-lang/rust/pull/105712/)
+- [Always check alignment during compile-time const evaluation](https://github.com/rust-lang/rust/pull/104616/)
+- [Disable "split dwarf inlining" by default.](https://github.com/rust-lang/rust/pull/106709/)
+- [Add vendor to Fuchsia's target triple](https://github.com/rust-lang/rust/pull/106429/)
+- [Enable sanitizers for s390x-linux](https://github.com/rust-lang/rust/pull/107127/)
+
+
+
+Libraries
+---------
+
+- [Loosen the bound on the Debug implementation of Weak.](https://github.com/rust-lang/rust/pull/90291/)
+- [Make `std::task::Context` !Send and !Sync](https://github.com/rust-lang/rust/pull/95985/)
+- [PhantomData layout guarantees](https://github.com/rust-lang/rust/pull/104081/)
+- [Don't derive Debug for `OnceWith` & `RepeatWith`](https://github.com/rust-lang/rust/pull/104163/)
+- [Implement DerefMut for PathBuf](https://github.com/rust-lang/rust/pull/105018/)
+- [Add O(1) `Vec -> VecDeque` conversion guarantee](https://github.com/rust-lang/rust/pull/105128/)
+- [Leak amplification for peek_mut() to ensure BinaryHeap's invariant is always met](https://github.com/rust-lang/rust/pull/105851/)
+
+
+
+Stabilized APIs
+---------------
+
+- [`{core,std}::pin::pin!`](https://doc.rust-lang.org/stable/std/pin/macro.pin.html)
+- [`impl From for {f32,f64}`](https://doc.rust-lang.org/stable/std/primitive.f32.html#impl-From%3Cbool%3E-for-f32)
+- [`std::path::MAIN_SEPARATOR_STR`](https://doc.rust-lang.org/stable/std/path/constant.MAIN_SEPARATOR_STR.html)
+- [`impl DerefMut for PathBuf`](https://doc.rust-lang.org/stable/std/path/struct.PathBuf.html#impl-DerefMut-for-PathBuf)
+
+These APIs are now stable in const contexts:
+
+- [`VecDeque::new`](https://doc.rust-lang.org/stable/std/collections/struct.VecDeque.html#method.new)
+
+
+
+Cargo
+-----
+
+- [Stabilize sparse registry support for crates.io](https://github.com/rust-lang/cargo/pull/11224/)
+- [`cargo build --verbose` tells you more about why it recompiles.](https://github.com/rust-lang/cargo/pull/11407/)
+- [Show progress of crates.io index update even `net.git-fetch-with-cli` option enabled](https://github.com/rust-lang/cargo/pull/11579/)
+
+
+
+Misc
+----
+
+
+
+Compatibility Notes
+-------------------
+
+- [Add `SEMICOLON_IN_EXPRESSIONS_FROM_MACROS` to future-incompat report](https://github.com/rust-lang/rust/pull/103418/)
+- [Only specify `--target` by default for `-Zgcc-ld=lld` on wasm](https://github.com/rust-lang/rust/pull/101792/)
+- [Bump `IMPLIED_BOUNDS_ENTAILMENT` to Deny + ReportNow](https://github.com/rust-lang/rust/pull/106465/)
+- [`std::task::Context` no longer implements Send and Sync](https://github.com/rust-lang/rust/pull/95985)
+
+
+
+Internal Changes
+----------------
+
+These changes do not affect any public interfaces of Rust, but they represent
+significant improvements to the performance or internals of rustc and related
+tools.
+
+- [Encode spans relative to the enclosing item](https://github.com/rust-lang/rust/pull/84762/)
+- [Don't normalize in AstConv](https://github.com/rust-lang/rust/pull/101947/)
+- [Find the right lower bound region in the scenario of partial order relations](https://github.com/rust-lang/rust/pull/104765/)
+- [Fix impl block in const expr](https://github.com/rust-lang/rust/pull/104889/)
+- [Check ADT fields for copy implementations considering regions](https://github.com/rust-lang/rust/pull/105102/)
+- [rustdoc: simplify JS search routine by not messing with lev distance](https://github.com/rust-lang/rust/pull/105796/)
+- [Enable ThinLTO for rustc on `x86_64-pc-windows-msvc`](https://github.com/rust-lang/rust/pull/103591/)
+- [Enable ThinLTO for rustc on `x86_64-apple-darwin`](https://github.com/rust-lang/rust/pull/103647/)
+
Version 1.67.1 (2023-02-09)
===========================
@@ -3765,6 +3861,8 @@ Version 1.41.1 (2020-02-27)
* [Always check types of static items][69145]
* [Always check lifetime bounds of `Copy` impls][69145]
* [Fix miscompilation in callers of `Layout::repeat`][69225]
+* [Rust 1.41.0 was announced as the last Rust release with tier 1 or tier 2 support for 32-bit Apple targets][apple-32bit-drop].
+ That announcement did not expect a patch release. 1.41.1 also includes release binaries for these targets.
[69225]: https://github.com/rust-lang/rust/issues/69225
[69145]: https://github.com/rust-lang/rust/pull/69145
@@ -3857,7 +3955,7 @@ Misc
Compatibility Notes
-------------------
-- [As previously announced 1.41.0 will be the last tier 1 release for 32-bit
+- [As previously announced 1.41 will be the last tier 1 release for 32-bit
Apple targets.][apple-32bit-drop] This means that the source code is still
available to build, but the targets are no longer being tested and release
binaries for those platforms will no longer be distributed by the Rust project.
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 7dcb03b4c786..6fed0b660e86 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -12,7 +12,7 @@ use crate::ptr::P;
use crate::token::{self, Token};
use crate::tokenstream::*;
-use rustc_data_structures::map_in_place::MapInPlace;
+use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
use rustc_data_structures::sync::Lrc;
use rustc_span::source_map::Spanned;
use rustc_span::symbol::Ident;
diff --git a/compiler/rustc_borrowck/src/borrow_set.rs b/compiler/rustc_borrowck/src/borrow_set.rs
index 5bb92a358261..fa0552e012de 100644
--- a/compiler/rustc_borrowck/src/borrow_set.rs
+++ b/compiler/rustc_borrowck/src/borrow_set.rs
@@ -4,7 +4,7 @@ use crate::nll::ToRegionVid;
use crate::path_utils::allow_two_phase_borrow;
use crate::place_ext::PlaceExt;
use crate::BorrowIndex;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
+use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_index::bit_set::BitSet;
use rustc_middle::mir::traversal;
use rustc_middle::mir::visit::{MutatingUseContext, NonUseContext, PlaceContext, Visitor};
@@ -26,10 +26,10 @@ pub struct BorrowSet<'tcx> {
/// NOTE: a given location may activate more than one borrow in the future
/// when more general two-phase borrow support is introduced, but for now we
/// only need to store one borrow index.
- pub activation_map: FxHashMap>,
+ pub activation_map: FxIndexMap>,
/// Map from local to all the borrows on that local.
- pub local_map: FxHashMap>,
+ pub local_map: FxIndexMap>,
pub(crate) locals_state_at_exit: LocalsStateAtExit,
}
@@ -175,8 +175,8 @@ struct GatherBorrows<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
body: &'a Body<'tcx>,
location_map: FxIndexMap>,
- activation_map: FxHashMap>,
- local_map: FxHashMap>,
+ activation_map: FxIndexMap>,
+ local_map: FxIndexMap>,
/// When we encounter a 2-phase borrow statement, it will always
/// be assigning into a temporary TEMP:
@@ -186,7 +186,7 @@ struct GatherBorrows<'a, 'tcx> {
/// We add TEMP into this map with `b`, where `b` is the index of
/// the borrow. When we find a later use of this activation, we
/// remove from the map (and add to the "tombstone" set below).
- pending_activations: FxHashMap,
+ pending_activations: FxIndexMap,
locals_state_at_exit: LocalsStateAtExit,
}
diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs
index 2821677c5371..0762987e2296 100644
--- a/compiler/rustc_borrowck/src/dataflow.rs
+++ b/compiler/rustc_borrowck/src/dataflow.rs
@@ -1,6 +1,6 @@
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
-use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::fx::FxIndexMap;
use rustc_index::bit_set::BitSet;
use rustc_middle::mir::{self, BasicBlock, Body, Location, Place};
use rustc_middle::ty::RegionVid;
@@ -124,7 +124,7 @@ pub struct Borrows<'a, 'tcx> {
body: &'a Body<'tcx>,
borrow_set: &'a BorrowSet<'tcx>,
- borrows_out_of_scope_at_location: FxHashMap>,
+ borrows_out_of_scope_at_location: FxIndexMap>,
}
struct StackEntry {
@@ -138,7 +138,7 @@ struct OutOfScopePrecomputer<'a, 'tcx> {
visit_stack: Vec,
body: &'a Body<'tcx>,
regioncx: &'a RegionInferenceContext<'tcx>,
- borrows_out_of_scope_at_location: FxHashMap>,
+ borrows_out_of_scope_at_location: FxIndexMap>,
}
impl<'a, 'tcx> OutOfScopePrecomputer<'a, 'tcx> {
@@ -148,7 +148,7 @@ impl<'a, 'tcx> OutOfScopePrecomputer<'a, 'tcx> {
visit_stack: vec![],
body,
regioncx,
- borrows_out_of_scope_at_location: FxHashMap::default(),
+ borrows_out_of_scope_at_location: FxIndexMap::default(),
}
}
}
@@ -390,6 +390,7 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> {
| mir::StatementKind::Deinit(..)
| mir::StatementKind::StorageLive(..)
| mir::StatementKind::Retag { .. }
+ | mir::StatementKind::PlaceMention(..)
| mir::StatementKind::AscribeUserType(..)
| mir::StatementKind::Coverage(..)
| mir::StatementKind::Intrinsic(..)
diff --git a/compiler/rustc_borrowck/src/def_use.rs b/compiler/rustc_borrowck/src/def_use.rs
index 8e62a0198be4..9e9f0b4b4ad0 100644
--- a/compiler/rustc_borrowck/src/def_use.rs
+++ b/compiler/rustc_borrowck/src/def_use.rs
@@ -72,6 +72,8 @@ pub fn categorize(context: PlaceContext) -> Option {
PlaceContext::MutatingUse(MutatingUseContext::Drop) =>
Some(DefUse::Drop),
+ // This statement exists to help unsafeck. It does not require the place to be live.
+ PlaceContext::NonUse(NonUseContext::PlaceMention) => None,
// Debug info is neither def nor use.
PlaceContext::NonUse(NonUseContext::VarDebugInfo) => None,
diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index a622a215a2e8..f43b611f54ed 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -1,7 +1,7 @@
use either::Either;
use rustc_const_eval::util::CallKind;
use rustc_data_structures::captures::Captures;
-use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::fx::FxIndexSet;
use rustc_errors::{
struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan,
};
@@ -173,7 +173,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let mut is_loop_move = false;
let mut in_pattern = false;
- let mut seen_spans = FxHashSet::default();
+ let mut seen_spans = FxIndexSet::default();
for move_site in &move_site_vec {
let move_out = self.move_data.moves[(*move_site).moi];
@@ -2223,8 +2223,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
}
- let mut visited = FxHashSet::default();
- let mut move_locations = FxHashSet::default();
+ let mut visited = FxIndexSet::default();
+ let mut move_locations = FxIndexSet::default();
let mut reinits = vec![];
let mut result = vec![];
@@ -2351,7 +2351,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let reinits_reachable = reinits
.into_iter()
.filter(|reinit| {
- let mut visited = FxHashSet::default();
+ let mut visited = FxIndexSet::default();
let mut stack = vec![*reinit];
while let Some(location) = stack.pop() {
if !visited.insert(location) {
diff --git a/compiler/rustc_borrowck/src/diagnostics/find_use.rs b/compiler/rustc_borrowck/src/diagnostics/find_use.rs
index 15f42e26cbf4..fd1fda2ee4bd 100644
--- a/compiler/rustc_borrowck/src/diagnostics/find_use.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/find_use.rs
@@ -9,7 +9,7 @@ use crate::{
nll::ToRegionVid,
region_infer::{Cause, RegionInferenceContext},
};
-use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::fx::FxIndexSet;
use rustc_middle::mir::visit::{MirVisitable, PlaceContext, Visitor};
use rustc_middle::mir::{Body, Local, Location};
use rustc_middle::ty::{RegionVid, TyCtxt};
@@ -37,7 +37,7 @@ struct UseFinder<'cx, 'tcx> {
impl<'cx, 'tcx> UseFinder<'cx, 'tcx> {
fn find(&mut self) -> Option {
let mut queue = VecDeque::new();
- let mut visited = FxHashSet::default();
+ let mut visited = FxIndexSet::default();
queue.push_back(self.start_point);
while let Some(p) = queue.pop_front() {
diff --git a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs
index 1eaf0a2f15ce..d5ece57437e0 100644
--- a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs
@@ -1,7 +1,7 @@
//! Contains utilities for generating suggestions for borrowck errors related to unsatisfied
//! outlives constraints.
-use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::fx::FxIndexSet;
use rustc_errors::Diagnostic;
use rustc_middle::ty::RegionVid;
use smallvec::SmallVec;
@@ -87,7 +87,7 @@ impl OutlivesSuggestionBuilder {
// Keep track of variables that we have already suggested unifying so that we don't print
// out silly duplicate messages.
- let mut unified_already = FxHashSet::default();
+ let mut unified_already = FxIndexSet::default();
for (fr, outlived) in &self.constraints_to_add {
let Some(fr_name) = self.region_vid_to_name(mbcx, *fr) else {
diff --git a/compiler/rustc_borrowck/src/invalidation.rs b/compiler/rustc_borrowck/src/invalidation.rs
index 6217676d5c15..a71c41632861 100644
--- a/compiler/rustc_borrowck/src/invalidation.rs
+++ b/compiler/rustc_borrowck/src/invalidation.rs
@@ -79,6 +79,8 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
}
// Only relevant for mir typeck
StatementKind::AscribeUserType(..)
+ // Only relevant for unsafeck
+ | StatementKind::PlaceMention(..)
// Doesn't have any language semantics
| StatementKind::Coverage(..)
// Does not actually affect borrowck
@@ -118,15 +120,6 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
LocalMutationIsAllowed::Yes,
);
}
- TerminatorKind::DropAndReplace {
- place: drop_place,
- value: new_value,
- target: _,
- unwind: _,
- } => {
- self.mutate_place(location, *drop_place, Deep);
- self.consume_operand(location, new_value);
- }
TerminatorKind::Call {
func,
args,
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 115e512a9742..f84a4691d32a 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -1,6 +1,5 @@
//! This query borrow-checks the MIR to (further) ensure it is not broken.
-#![allow(rustc::potential_query_instability)]
#![feature(associated_type_bounds)]
#![feature(box_patterns)]
#![feature(let_chains)]
@@ -18,7 +17,7 @@ extern crate rustc_middle;
#[macro_use]
extern crate tracing;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_data_structures::graph::dominators::Dominators;
use rustc_data_structures::vec_map::VecMap;
use rustc_errors::{Diagnostic, DiagnosticBuilder, DiagnosticMessage, SubdiagnosticMessage};
@@ -404,7 +403,7 @@ fn do_mir_borrowck<'tcx>(
// Note that this set is expected to be small - only upvars from closures
// would have a chance of erroneously adding non-user-defined mutable vars
// to the set.
- let temporary_used_locals: FxHashSet = mbcx
+ let temporary_used_locals: FxIndexSet = mbcx
.used_mut
.iter()
.filter(|&local| !mbcx.body.local_decls[*local].is_user_variable())
@@ -491,7 +490,7 @@ pub struct BodyWithBorrowckFacts<'tcx> {
pub struct BorrowckInferCtxt<'cx, 'tcx> {
pub(crate) infcx: &'cx InferCtxt<'tcx>,
- pub(crate) reg_var_to_origin: RefCell>,
+ pub(crate) reg_var_to_origin: RefCell>,
}
impl<'cx, 'tcx> BorrowckInferCtxt<'cx, 'tcx> {
@@ -588,7 +587,7 @@ struct MirBorrowckCtxt<'cx, 'tcx> {
/// borrow errors that is handled by the `reservation_error_reported` field as the inclusion
/// of the `Span` type (while required to mute some errors) stops the muting of the reservation
/// errors.
- access_place_error_reported: FxHashSet<(Place<'tcx>, Span)>,
+ access_place_error_reported: FxIndexSet<(Place<'tcx>, Span)>,
/// This field keeps track of when borrow conflict errors are reported
/// for reservations, so that we don't report seemingly duplicate
/// errors for corresponding activations.
@@ -596,17 +595,17 @@ struct MirBorrowckCtxt<'cx, 'tcx> {
// FIXME: ideally this would be a set of `BorrowIndex`, not `Place`s,
// but it is currently inconvenient to track down the `BorrowIndex`
// at the time we detect and report a reservation error.
- reservation_error_reported: FxHashSet>,
+ reservation_error_reported: FxIndexSet>,
/// This fields keeps track of the `Span`s that we have
/// used to report extra information for `FnSelfUse`, to avoid
/// unnecessarily verbose errors.
- fn_self_span_reported: FxHashSet,
+ fn_self_span_reported: FxIndexSet,
/// This field keeps track of errors reported in the checking of uninitialized variables,
/// so that we don't report seemingly duplicate errors.
- uninitialized_error_reported: FxHashSet>,
+ uninitialized_error_reported: FxIndexSet>,
/// This field keeps track of all the local variables that are declared mut and are mutated.
/// Used for the warning issued by an unused mutable local variable.
- used_mut: FxHashSet,
+ used_mut: FxIndexSet,
/// If the function we're checking is a closure, then we'll need to report back the list of
/// mutable upvars that have been used. This field keeps track of them.
used_mut_upvars: SmallVec<[Field; 8]>,
@@ -628,7 +627,7 @@ struct MirBorrowckCtxt<'cx, 'tcx> {
/// Record the region names generated for each region in the given
/// MIR def so that we can reuse them later in help/error messages.
- region_names: RefCell>,
+ region_names: RefCell>,
/// The counter for generating new region names.
next_region_name: RefCell,
@@ -691,6 +690,8 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
}
// Only relevant for mir typeck
StatementKind::AscribeUserType(..)
+ // Only relevant for unsafeck
+ | StatementKind::PlaceMention(..)
// Doesn't have any language semantics
| StatementKind::Coverage(..)
// These do not actually affect borrowck
@@ -744,15 +745,6 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
flow_state,
);
}
- TerminatorKind::DropAndReplace {
- place: drop_place,
- value: new_value,
- target: _,
- unwind: _,
- } => {
- self.mutate_place(loc, (*drop_place, span), Deep, flow_state);
- self.consume_operand(loc, (new_value, span), flow_state);
- }
TerminatorKind::Call {
func,
args,
@@ -867,7 +859,6 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx
| TerminatorKind::Assert { .. }
| TerminatorKind::Call { .. }
| TerminatorKind::Drop { .. }
- | TerminatorKind::DropAndReplace { .. }
| TerminatorKind::FalseEdge { real_target: _, imaginary_target: _ }
| TerminatorKind::FalseUnwind { real_target: _, unwind: _ }
| TerminatorKind::Goto { .. }
@@ -2329,7 +2320,7 @@ mod error {
/// same primary span come out in a consistent order.
buffered_move_errors:
BTreeMap, (PlaceRef<'tcx>, DiagnosticBuilder<'tcx, ErrorGuaranteed>)>,
- buffered_mut_errors: FxHashMap, usize)>,
+ buffered_mut_errors: FxIndexMap, usize)>,
/// Diagnostics to be reported buffer.
buffered: Vec,
/// Set to Some if we emit an error during borrowck
diff --git a/compiler/rustc_borrowck/src/member_constraints.rs b/compiler/rustc_borrowck/src/member_constraints.rs
index 4af324f740ae..b6c5d4245d7b 100644
--- a/compiler/rustc_borrowck/src/member_constraints.rs
+++ b/compiler/rustc_borrowck/src/member_constraints.rs
@@ -1,7 +1,7 @@
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
use rustc_data_structures::captures::Captures;
-use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::fx::FxIndexMap;
use rustc_index::vec::IndexVec;
use rustc_middle::infer::MemberConstraint;
use rustc_middle::ty::{self, Ty};
@@ -18,7 +18,7 @@ where
{
/// Stores the first "member" constraint for a given `R0`. This is an
/// index into the `constraints` vector below.
- first_constraints: FxHashMap,
+ first_constraints: FxIndexMap,
/// Stores the data about each `R0 member of [R1..Rn]` constraint.
/// These are organized into a linked list, so each constraint
@@ -132,7 +132,7 @@ where
let MemberConstraintSet { first_constraints, mut constraints, choice_regions } = self;
- let mut first_constraints2 = FxHashMap::default();
+ let mut first_constraints2 = FxIndexMap::default();
first_constraints2.reserve(first_constraints.len());
for (r1, start1) in first_constraints {
diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs
index e5dbb83dd072..96228338a4c2 100644
--- a/compiler/rustc_borrowck/src/nll.rs
+++ b/compiler/rustc_borrowck/src/nll.rs
@@ -10,10 +10,9 @@ use rustc_middle::mir::{
BasicBlock, Body, ClosureOutlivesSubject, ClosureRegionRequirements, LocalKind, Location,
Promoted,
};
-use rustc_middle::ty::{self, OpaqueHiddenType, Region, RegionVid};
+use rustc_middle::ty::{self, OpaqueHiddenType, Region, RegionVid, TyCtxt};
use rustc_span::symbol::sym;
use std::env;
-use std::fmt::Debug;
use std::io;
use std::path::PathBuf;
use std::rc::Rc;
@@ -325,7 +324,7 @@ pub(super) fn dump_mir_results<'tcx>(
infcx: &BorrowckInferCtxt<'_, 'tcx>,
body: &Body<'tcx>,
regioncx: &RegionInferenceContext<'tcx>,
- closure_region_requirements: &Option>,
+ closure_region_requirements: &Option>,
) {
if !dump_enabled(infcx.tcx, "nll", body.source.def_id()) {
return;
@@ -340,9 +339,11 @@ pub(super) fn dump_mir_results<'tcx>(
if let Some(closure_region_requirements) = closure_region_requirements {
writeln!(out, "| Free Region Constraints")?;
- for_each_region_constraint(closure_region_requirements, &mut |msg| {
- writeln!(out, "| {}", msg)
- })?;
+ for_each_region_constraint(
+ infcx.tcx,
+ closure_region_requirements,
+ &mut |msg| writeln!(out, "| {}", msg),
+ )?;
writeln!(out, "|")?;
}
}
@@ -375,7 +376,7 @@ pub(super) fn dump_annotation<'tcx>(
infcx: &BorrowckInferCtxt<'_, 'tcx>,
body: &Body<'tcx>,
regioncx: &RegionInferenceContext<'tcx>,
- closure_region_requirements: &Option>,
+ closure_region_requirements: &Option>,
opaque_type_values: &VecMap>,
errors: &mut crate::error::BorrowckErrors<'tcx>,
) {
@@ -405,7 +406,7 @@ pub(super) fn dump_annotation<'tcx>(
// Dump the region constraints we are imposing *between* those
// newly created variables.
- for_each_region_constraint(closure_region_requirements, &mut |msg| {
+ for_each_region_constraint(tcx, closure_region_requirements, &mut |msg| {
err.note(msg);
Ok(())
})
@@ -426,16 +427,19 @@ pub(super) fn dump_annotation<'tcx>(
errors.buffer_non_error_diag(err);
}
-fn for_each_region_constraint(
- closure_region_requirements: &ClosureRegionRequirements<'_>,
+fn for_each_region_constraint<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ closure_region_requirements: &ClosureRegionRequirements<'tcx>,
with_msg: &mut dyn FnMut(&str) -> io::Result<()>,
) -> io::Result<()> {
for req in &closure_region_requirements.outlives_requirements {
- let subject: &dyn Debug = match &req.subject {
- ClosureOutlivesSubject::Region(subject) => subject,
- ClosureOutlivesSubject::Ty(ty) => ty,
+ let subject = match req.subject {
+ ClosureOutlivesSubject::Region(subject) => format!("{:?}", subject),
+ ClosureOutlivesSubject::Ty(ty) => {
+ format!("{:?}", ty.instantiate(tcx, |vid| tcx.mk_re_var(vid)))
+ }
};
- with_msg(&format!("where {:?}: {:?}", subject, req.outlived_free_region,))?;
+ with_msg(&format!("where {}: {:?}", subject, req.outlived_free_region,))?;
}
Ok(())
}
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index 21b5bd7cb94d..905d8c42b28b 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -3,7 +3,7 @@ use std::rc::Rc;
use rustc_data_structures::binary_search_util;
use rustc_data_structures::frozen::Frozen;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_data_structures::graph::scc::Sccs;
use rustc_errors::Diagnostic;
use rustc_hir::def_id::CRATE_DEF_ID;
@@ -12,8 +12,9 @@ use rustc_infer::infer::outlives::test_type_match;
use rustc_infer::infer::region_constraints::{GenericKind, VarInfos, VerifyBound, VerifyIfEq};
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin};
use rustc_middle::mir::{
- Body, ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureRegionRequirements,
- ConstraintCategory, Local, Location, ReturnConstraint, TerminatorKind,
+ Body, ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureOutlivesSubjectTy,
+ ClosureRegionRequirements, ConstraintCategory, Local, Location, ReturnConstraint,
+ TerminatorKind,
};
use rustc_middle::traits::ObligationCause;
use rustc_middle::traits::ObligationCauseCode;
@@ -87,7 +88,7 @@ pub struct RegionInferenceContext<'tcx> {
member_constraints_applied: Vec,
/// Map universe indexes to information on why we created it.
- universe_causes: FxHashMap>,
+ universe_causes: FxIndexMap>,
/// Contains the minimum universe of any variable within the same
/// SCC. We will ensure that no SCC contains values that are not
@@ -262,7 +263,7 @@ fn sccs_info<'cx, 'tcx>(
debug!(debug_str);
let num_components = sccs.scc_data().ranges().len();
- let mut components = vec![FxHashSet::default(); num_components];
+ let mut components = vec![FxIndexSet::default(); num_components];
for (reg_var_idx, scc_idx) in sccs.scc_indices().iter().enumerate() {
let reg_var = ty::RegionVid::from_usize(reg_var_idx);
@@ -294,9 +295,9 @@ fn sccs_info<'cx, 'tcx>(
(ConstraintSccIndex::from_usize(scc_idx), repr)
})
- .collect::>();
+ .collect::>();
- let mut scc_node_to_edges = FxHashMap::default();
+ let mut scc_node_to_edges = FxIndexMap::default();
for (scc_idx, repr) in components_representatives.iter() {
let edges_range = sccs.scc_data().ranges()[*scc_idx].clone();
let edges = &sccs.scc_data().all_successors()[edges_range];
@@ -324,7 +325,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
universal_region_relations: Frozen>,
outlives_constraints: OutlivesConstraintSet<'tcx>,
member_constraints_in: MemberConstraintSet<'tcx, RegionVid>,
- universe_causes: FxHashMap>,
+ universe_causes: FxIndexMap>,
type_tests: Vec>,
liveness_constraints: LivenessValues,
elements: &Rc,
@@ -521,6 +522,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
/// outlives `'a` and hence contains R0 and R1.
fn init_free_and_bound_regions(&mut self) {
// Update the names (if any)
+ // This iterator has unstable order but we collect it all into an IndexVec
for (external_name, variable) in self.universal_regions.named_universal_regions() {
debug!(
"init_universal_regions: region {:?} has external name {:?}",
@@ -917,7 +919,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
// Sometimes we register equivalent type-tests that would
// result in basically the exact same error being reported to
// the user. Avoid that.
- let mut deduplicate_errors = FxHashSet::default();
+ let mut deduplicate_errors = FxIndexSet::default();
for type_test in &self.type_tests {
debug!("check_type_test: {:?}", type_test);
@@ -1084,18 +1086,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
true
}
- /// When we promote a type test `T: 'r`, we have to convert the
- /// type `T` into something we can store in a query result (so
- /// something allocated for `'tcx`). This is problematic if `ty`
- /// contains regions. During the course of NLL region checking, we
- /// will have replaced all of those regions with fresh inference
- /// variables. To create a test subject, we want to replace those
- /// inference variables with some region from the closure
- /// signature -- this is not always possible, so this is a
- /// fallible process. Presuming we do find a suitable region, we
- /// will use it's *external name*, which will be a `RegionKind`
- /// variant that can be used in query responses such as
- /// `ReEarlyBound`.
+ /// When we promote a type test `T: 'r`, we have to replace all region
+ /// variables in the type `T` with an equal universal region from the
+ /// closure signature.
+ /// This is not always possible, so this is a fallible process.
#[instrument(level = "debug", skip(self, infcx))]
fn try_promote_type_test_subject(
&self,
@@ -1104,91 +1098,63 @@ impl<'tcx> RegionInferenceContext<'tcx> {
) -> Option> {
let tcx = infcx.tcx;
+ // Opaque types' substs may include useless lifetimes.
+ // We will replace them with ReStatic.
+ struct OpaqueFolder<'tcx> {
+ tcx: TyCtxt<'tcx>,
+ }
+ impl<'tcx> ty::TypeFolder> for OpaqueFolder<'tcx> {
+ fn interner(&self) -> TyCtxt<'tcx> {
+ self.tcx
+ }
+ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
+ use ty::TypeSuperFoldable as _;
+ let tcx = self.tcx;
+ let &ty::Alias(ty::Opaque, ty::AliasTy { substs, def_id, .. }) = t.kind() else {
+ return t.super_fold_with(self);
+ };
+ let substs =
+ std::iter::zip(substs, tcx.variances_of(def_id)).map(|(arg, v)| {
+ match (arg.unpack(), v) {
+ (ty::GenericArgKind::Lifetime(_), ty::Bivariant) => {
+ tcx.lifetimes.re_static.into()
+ }
+ _ => arg.fold_with(self),
+ }
+ });
+ tcx.mk_opaque(def_id, tcx.mk_substs_from_iter(substs))
+ }
+ }
+
+ let ty = ty.fold_with(&mut OpaqueFolder { tcx });
+
let ty = tcx.fold_regions(ty, |r, _depth| {
- let region_vid = self.to_region_vid(r);
+ let r_vid = self.to_region_vid(r);
+ let r_scc = self.constraint_sccs.scc(r_vid);
// The challenge if this. We have some region variable `r`
// whose value is a set of CFG points and universal
// regions. We want to find if that set is *equivalent* to
// any of the named regions found in the closure.
- //
- // To do so, we compute the
- // `non_local_universal_upper_bound`. This will be a
- // non-local, universal region that is greater than `r`.
- // However, it might not be *contained* within `r`, so
- // then we further check whether this bound is contained
- // in `r`. If so, we can say that `r` is equivalent to the
- // bound.
- //
- // Let's work through a few examples. For these, imagine
- // that we have 3 non-local regions (I'll denote them as
- // `'static`, `'a`, and `'b`, though of course in the code
- // they would be represented with indices) where:
- //
- // - `'static: 'a`
- // - `'static: 'b`
- //
- // First, let's assume that `r` is some existential
- // variable with an inferred value `{'a, 'static}` (plus
- // some CFG nodes). In this case, the non-local upper
- // bound is `'static`, since that outlives `'a`. `'static`
- // is also a member of `r` and hence we consider `r`
- // equivalent to `'static` (and replace it with
- // `'static`).
- //
- // Now let's consider the inferred value `{'a, 'b}`. This
- // means `r` is effectively `'a | 'b`. I'm not sure if
- // this can come about, actually, but assuming it did, we
- // would get a non-local upper bound of `'static`. Since
- // `'static` is not contained in `r`, we would fail to
- // find an equivalent.
- let upper_bound = self.non_local_universal_upper_bound(region_vid);
- if self.region_contains(region_vid, upper_bound) {
- self.definitions[upper_bound].external_name.unwrap_or(r)
- } else {
- // In the case of a failure, use a `ReVar` result. This will
- // cause the `needs_infer` later on to return `None`.
- r
- }
+ // To do so, we simply check every candidate `u_r` for equality.
+ self.scc_values
+ .universal_regions_outlived_by(r_scc)
+ .filter(|&u_r| !self.universal_regions.is_local_free_region(u_r))
+ .find(|&u_r| self.eval_equal(u_r, r_vid))
+ .map(|u_r| tcx.mk_re_var(u_r))
+ // In the case of a failure, use `ReErased`. We will eventually
+ // return `None` in this case.
+ .unwrap_or(tcx.lifetimes.re_erased)
});
debug!("try_promote_type_test_subject: folded ty = {:?}", ty);
- // `needs_infer` will only be true if we failed to promote some region.
- if ty.needs_infer() {
+ // This will be true if we failed to promote some region.
+ if ty.has_erased_regions() {
return None;
}
- Some(ClosureOutlivesSubject::Ty(ty))
- }
-
- /// Given some universal or existential region `r`, finds a
- /// non-local, universal region `r+` that outlives `r` at entry to (and
- /// exit from) the closure. In the worst case, this will be
- /// `'static`.
- ///
- /// This is used for two purposes. First, if we are propagated
- /// some requirement `T: r`, we can use this method to enlarge `r`
- /// to something we can encode for our creator (which only knows
- /// about non-local, universal regions). It is also used when
- /// encoding `T` as part of `try_promote_type_test_subject` (see
- /// that fn for details).
- ///
- /// This is based on the result `'y` of `universal_upper_bound`,
- /// except that it converts further takes the non-local upper
- /// bound of `'y`, so that the final result is non-local.
- fn non_local_universal_upper_bound(&self, r: RegionVid) -> RegionVid {
- debug!("non_local_universal_upper_bound(r={:?}={})", r, self.region_value_str(r));
-
- let lub = self.universal_upper_bound(r);
-
- // Grow further to get smallest universal region known to
- // creator.
- let non_local_lub = self.universal_region_relations.non_local_upper_bound(lub);
-
- debug!("non_local_universal_upper_bound: non_local_lub={:?}", non_local_lub);
-
- non_local_lub
+ Some(ClosureOutlivesSubject::Ty(ClosureOutlivesSubjectTy::bind(tcx, ty)))
}
/// Returns a universally quantified region that outlives the
@@ -1539,6 +1505,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
// the outlives suggestions or the debug output from `#[rustc_regions]` would be
// duplicated. The polonius subset errors are deduplicated here, while keeping the
// CFG-location ordering.
+ // We can iterate the HashMap here because the result is sorted afterwards.
+ #[allow(rustc::potential_query_instability)]
let mut subset_errors: Vec<_> = polonius_output
.subset_errors
.iter()
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index c550e37c63ee..ec4b2e9d3e44 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -1,4 +1,4 @@
-use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
+use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_data_structures::vec_map::VecMap;
use rustc_errors::ErrorGuaranteed;
use rustc_hir::def_id::LocalDefId;
@@ -65,7 +65,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
) -> VecMap> {
let mut result: VecMap> = VecMap::new();
- let member_constraints: FxHashMap<_, _> = self
+ let member_constraints: FxIndexMap<_, _> = self
.member_constraints
.all_indices()
.map(|ci| (self.member_constraints[ci].key, ci))
@@ -364,7 +364,7 @@ fn check_opaque_type_parameter_valid(
OpaqueTyOrigin::TyAlias => {}
}
let opaque_generics = tcx.generics_of(opaque_type_key.def_id);
- let mut seen_params: FxHashMap<_, Vec<_>> = FxHashMap::default();
+ let mut seen_params: FxIndexMap<_, Vec<_>> = FxIndexMap::default();
for (i, arg) in opaque_type_key.substs.iter().enumerate() {
let arg_is_param = match arg.unpack() {
GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)),
diff --git a/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs b/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs
index 167f66460969..23a59c12865b 100644
--- a/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs
+++ b/compiler/rustc_borrowck/src/region_infer/reverse_sccs.rs
@@ -3,7 +3,7 @@
use crate::constraints::ConstraintSccIndex;
use crate::RegionInferenceContext;
use itertools::Itertools;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_data_structures::graph::vec_graph::VecGraph;
use rustc_data_structures::graph::WithSuccessors;
use rustc_middle::ty::RegionVid;
@@ -14,7 +14,7 @@ pub(crate) struct ReverseSccGraph {
graph: VecGraph,
/// For each SCC, the range of `universal_regions` that use that SCC as
/// their value.
- scc_regions: FxHashMap>,
+ scc_regions: FxIndexMap>,
/// All of the universal regions, in grouped so that `scc_regions` can
/// index into here.
universal_regions: Vec,
@@ -26,7 +26,7 @@ impl ReverseSccGraph {
&'a self,
scc0: ConstraintSccIndex,
) -> impl Iterator- + 'a {
- let mut duplicates = FxHashSet::default();
+ let mut duplicates = FxIndexSet::default();
self.graph
.depth_first_search(scc0)
.flat_map(move |scc1| {
@@ -55,7 +55,7 @@ impl RegionInferenceContext<'_> {
paired_scc_regions.sort();
let universal_regions = paired_scc_regions.iter().map(|&(_, region)| region).collect();
- let mut scc_regions = FxHashMap::default();
+ let mut scc_regions = FxIndexMap::default();
let mut start = 0;
for (scc, group) in &paired_scc_regions.into_iter().group_by(|(scc, _)| *scc) {
let group_size = group.count();
diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
index 504633c6a5c3..a93561350062 100644
--- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
+++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
@@ -116,7 +116,9 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
let outlived_region = closure_mapping[outlives_requirement.outlived_free_region];
let subject = match outlives_requirement.subject {
ClosureOutlivesSubject::Region(re) => closure_mapping[re].into(),
- ClosureOutlivesSubject::Ty(ty) => ty.into(),
+ ClosureOutlivesSubject::Ty(subject_ty) => {
+ subject_ty.instantiate(self.tcx, |vid| closure_mapping[vid]).into()
+ }
};
self.category = outlives_requirement.category;
diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
index e2f897a89e82..4004966c40a7 100644
--- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
+++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
@@ -93,31 +93,6 @@ impl UniversalRegionRelations<'_> {
res
}
- /// Returns the "postdominating" bound of the set of
- /// `non_local_upper_bounds` for the given region.
- pub(crate) fn non_local_upper_bound(&self, fr: RegionVid) -> RegionVid {
- let upper_bounds = self.non_local_upper_bounds(fr);
-
- // In case we find more than one, reduce to one for
- // convenience. This is to prevent us from generating more
- // complex constraints, but it will cause spurious errors.
- let post_dom = self.inverse_outlives.mutual_immediate_postdominator(upper_bounds);
-
- debug!("non_local_bound: post_dom={:?}", post_dom);
-
- post_dom
- .and_then(|post_dom| {
- // If the mutual immediate postdom is not local, then
- // there is no non-local result we can return.
- if !self.universal_regions.is_local_free_region(post_dom) {
- Some(post_dom)
- } else {
- None
- }
- })
- .unwrap_or(self.universal_regions.fr_static)
- }
-
/// Finds a "lower bound" for `fr` that is not local. In other
/// words, returns the largest (*) known region `fr1` that (a) is
/// outlived by `fr` and (b) is not local.
diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs
index 717020ea5b89..17e702eb8c52 100644
--- a/compiler/rustc_borrowck/src/type_check/input_output.rs
+++ b/compiler/rustc_borrowck/src/type_check/input_output.rs
@@ -19,7 +19,7 @@ use super::{Locations, TypeChecker};
impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
/// Check explicit closure signature annotation,
- /// e.g., `|x: FxHashMap<_, &'static u32>| ...`.
+ /// e.g., `|x: FxIndexMap<_, &'static u32>| ...`.
#[instrument(skip(self, body), level = "debug")]
pub(super) fn check_signature_annotation(&mut self, body: &Body<'tcx>) {
let mir_def_id = body.source.def_id().expect_local();
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
index 473c05963007..9731b10aa99d 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
@@ -1,4 +1,4 @@
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_index::bit_set::HybridBitSet;
use rustc_index::interval::IntervalSet;
use rustc_infer::infer::canonical::QueryRegionConstraints;
@@ -56,7 +56,7 @@ pub(super) fn trace<'mir, 'tcx>(
elements,
local_use_map,
move_data,
- drop_data: FxHashMap::default(),
+ drop_data: FxIndexMap::default(),
};
let mut results = LivenessResults::new(cx);
@@ -85,7 +85,7 @@ struct LivenessContext<'me, 'typeck, 'flow, 'tcx> {
move_data: &'me MoveData<'tcx>,
/// Cache for the results of `dropck_outlives` query.
- drop_data: FxHashMap, DropData<'tcx>>,
+ drop_data: FxIndexMap, DropData<'tcx>>,
/// Results of dataflow tracking which variables (and paths) have been
/// initialized.
@@ -185,7 +185,7 @@ impl<'me, 'typeck, 'flow, 'tcx> LivenessResults<'me, 'typeck, 'flow, 'tcx> {
fn add_extra_drop_facts(
&mut self,
drop_used: Vec<(Local, Location)>,
- relevant_live_locals: FxHashSet,
+ relevant_live_locals: FxIndexSet,
) {
let locations = IntervalSet::new(self.cx.elements.num_points());
@@ -435,8 +435,7 @@ impl<'me, 'typeck, 'flow, 'tcx> LivenessResults<'me, 'typeck, 'flow, 'tcx> {
//
// What we *actually* generate is a store to a temporary
// for the call (`TMP = call()...`) and then a
- // `DropAndReplace` to swap that with `X`
- // (`DropAndReplace` has very particular semantics).
+ // `Drop(X)` followed by `X = TMP` to swap that with `X`.
}
}
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index a49da3da6c01..3919c4793a06 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -9,7 +9,7 @@ use either::Either;
use hir::OpaqueTyOrigin;
use rustc_data_structures::frozen::Frozen;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
use rustc_data_structures::vec_map::VecMap;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
@@ -145,7 +145,7 @@ pub(crate) fn type_check<'mir, 'tcx>(
outlives_constraints: OutlivesConstraintSet::default(),
member_constraints: MemberConstraintSet::default(),
type_tests: Vec::default(),
- universe_causes: FxHashMap::default(),
+ universe_causes: FxIndexMap::default(),
};
let CreateResult {
@@ -772,7 +772,9 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
match context {
PlaceContext::MutatingUse(_) => ty::Invariant,
- PlaceContext::NonUse(StorageDead | StorageLive | VarDebugInfo) => ty::Invariant,
+ PlaceContext::NonUse(StorageDead | StorageLive | PlaceMention | VarDebugInfo) => {
+ ty::Invariant
+ }
PlaceContext::NonMutatingUse(
Inspect | Copy | Move | SharedBorrow | ShallowBorrow | UniqueBorrow | AddressOf
| Projection,
@@ -875,7 +877,7 @@ struct TypeChecker<'a, 'tcx> {
user_type_annotations: &'a CanonicalUserTypeAnnotations<'tcx>,
region_bound_pairs: &'a RegionBoundPairs<'tcx>,
implicit_region_bound: ty::Region<'tcx>,
- reported_errors: FxHashSet<(Ty<'tcx>, Span)>,
+ reported_errors: FxIndexSet<(Ty<'tcx>, Span)>,
borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>,
}
@@ -925,7 +927,7 @@ pub(crate) struct MirTypeckRegionConstraints<'tcx> {
pub(crate) member_constraints: MemberConstraintSet<'tcx, RegionVid>,
- pub(crate) universe_causes: FxHashMap>,
+ pub(crate) universe_causes: FxIndexMap>,
pub(crate) type_tests: Vec>,
}
@@ -1282,6 +1284,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
| StatementKind::Retag { .. }
| StatementKind::Coverage(..)
| StatementKind::ConstEvalCounter
+ | StatementKind::PlaceMention(..)
| StatementKind::Nop => {}
StatementKind::Deinit(..) | StatementKind::SetDiscriminant { .. } => {
bug!("Statement not allowed in this MIR phase")
@@ -1312,24 +1315,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
// no checks needed for these
}
- TerminatorKind::DropAndReplace { place, value, target: _, unwind: _ } => {
- let place_ty = place.ty(body, tcx).ty;
- let rv_ty = value.ty(body, tcx);
-
- let locations = term_location.to_locations();
- if let Err(terr) =
- self.sub_types(rv_ty, place_ty, locations, ConstraintCategory::Assignment)
- {
- span_mirbug!(
- self,
- term,
- "bad DropAndReplace ({:?} = {:?}): {:?}",
- place_ty,
- rv_ty,
- terr
- );
- }
- }
TerminatorKind::SwitchInt { discr, .. } => {
self.check_operand(discr, term_location);
@@ -1629,7 +1614,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
}
TerminatorKind::Unreachable => {}
TerminatorKind::Drop { target, unwind, .. }
- | TerminatorKind::DropAndReplace { target, unwind, .. }
| TerminatorKind::Assert { target, cleanup: unwind, .. } => {
self.assert_iscleanup(body, block_data, target, is_cleanup);
if let Some(unwind) = unwind {
diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs
index 76d0b8754248..68c86051364e 100644
--- a/compiler/rustc_borrowck/src/universal_regions.rs
+++ b/compiler/rustc_borrowck/src/universal_regions.rs
@@ -312,6 +312,9 @@ impl<'tcx> UniversalRegions<'tcx> {
}
/// Gets an iterator over all the early-bound regions that have names.
+ /// Iteration order may be unstable, so this should only be used when
+ /// iteration order doesn't affect anything
+ #[allow(rustc::potential_query_instability)]
pub fn named_universal_regions<'s>(
&'s self,
) -> impl Iterator
- , ty::RegionVid)> + 's {
diff --git a/compiler/rustc_borrowck/src/used_muts.rs b/compiler/rustc_borrowck/src/used_muts.rs
index e297b1230ea0..c5991e0bc254 100644
--- a/compiler/rustc_borrowck/src/used_muts.rs
+++ b/compiler/rustc_borrowck/src/used_muts.rs
@@ -1,6 +1,6 @@
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
-use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::fx::FxIndexSet;
use rustc_middle::mir::visit::{PlaceContext, Visitor};
use rustc_middle::mir::{
Local, Location, Place, Statement, StatementKind, Terminator, TerminatorKind,
@@ -26,8 +26,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
/// See #55344 for context.
pub(crate) fn gather_used_muts(
&mut self,
- temporary_used_locals: FxHashSet,
- mut never_initialized_mut_locals: FxHashSet,
+ temporary_used_locals: FxIndexSet,
+ mut never_initialized_mut_locals: FxIndexSet,
) {
{
let mut visitor = GatherUsedMutsVisitor {
@@ -48,8 +48,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
/// MIR visitor for collecting used mutable variables.
/// The 'visit lifetime represents the duration of the MIR walk.
struct GatherUsedMutsVisitor<'visit, 'cx, 'tcx> {
- temporary_used_locals: FxHashSet,
- never_initialized_mut_locals: &'visit mut FxHashSet,
+ temporary_used_locals: FxIndexSet,
+ never_initialized_mut_locals: &'visit mut FxIndexSet,
mbcx: &'visit mut MirBorrowckCtxt<'cx, 'tcx>,
}
@@ -71,9 +71,6 @@ impl<'visit, 'cx, 'tcx> Visitor<'tcx> for GatherUsedMutsVisitor<'visit, 'cx, 'tc
TerminatorKind::Call { destination, .. } => {
self.remove_never_initialized_mut_locals(*destination);
}
- TerminatorKind::DropAndReplace { place, .. } => {
- self.remove_never_initialized_mut_locals(*place);
- }
_ => {}
}
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index 7f857528c7c5..230256ba5aa8 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -499,7 +499,6 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
TerminatorKind::Yield { .. }
| TerminatorKind::FalseEdge { .. }
| TerminatorKind::FalseUnwind { .. }
- | TerminatorKind::DropAndReplace { .. }
| TerminatorKind::GeneratorDrop => {
bug!("shouldn't exist at codegen {:?}", bb_data.terminator());
}
@@ -820,6 +819,7 @@ fn codegen_stmt<'tcx>(
| StatementKind::Nop
| StatementKind::FakeRead(..)
| StatementKind::Retag { .. }
+ | StatementKind::PlaceMention(..)
| StatementKind::AscribeUserType(..) => {}
StatementKind::Coverage { .. } => fx.tcx.sess.fatal("-Zcoverage is unimplemented"),
diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs
index 49c4f1aaaefc..efdf9f6d5bc0 100644
--- a/compiler/rustc_codegen_cranelift/src/constant.rs
+++ b/compiler/rustc_codegen_cranelift/src/constant.rs
@@ -529,6 +529,7 @@ pub(crate) fn mir_operand_get_const_val<'tcx>(
| StatementKind::StorageDead(_)
| StatementKind::Retag(_, _)
| StatementKind::AscribeUserType(_, _)
+ | StatementKind::PlaceMention(..)
| StatementKind::Coverage(_)
| StatementKind::ConstEvalCounter
| StatementKind::Nop => {}
@@ -543,8 +544,7 @@ pub(crate) fn mir_operand_get_const_val<'tcx>(
| TerminatorKind::Unreachable
| TerminatorKind::Drop { .. }
| TerminatorKind::Assert { .. } => {}
- TerminatorKind::DropAndReplace { .. }
- | TerminatorKind::Yield { .. }
+ TerminatorKind::Yield { .. }
| TerminatorKind::GeneratorDrop
| TerminatorKind::FalseEdge { .. }
| TerminatorKind::FalseUnwind { .. } => unreachable!(),
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
index e74aabf2fcb0..24f8d5e464e4 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
@@ -281,8 +281,12 @@ fn codegen_float_intrinsic_call<'tcx>(
sym::ceilf64 => ("ceil", 1, fx.tcx.types.f64),
sym::truncf32 => ("truncf", 1, fx.tcx.types.f32),
sym::truncf64 => ("trunc", 1, fx.tcx.types.f64),
+ sym::rintf32 => ("rintf", 1, fx.tcx.types.f32),
+ sym::rintf64 => ("rint", 1, fx.tcx.types.f64),
sym::roundf32 => ("roundf", 1, fx.tcx.types.f32),
sym::roundf64 => ("round", 1, fx.tcx.types.f64),
+ sym::roundevenf32 => ("roundevenf", 1, fx.tcx.types.f32),
+ sym::roundevenf64 => ("roundeven", 1, fx.tcx.types.f64),
sym::sinf32 => ("sinf", 1, fx.tcx.types.f32),
sym::sinf64 => ("sin", 1, fx.tcx.types.f64),
sym::cosf32 => ("cosf", 1, fx.tcx.types.f32),
diff --git a/compiler/rustc_codegen_gcc/.github/workflows/ci.yml b/compiler/rustc_codegen_gcc/.github/workflows/ci.yml
index 8ebdabe82610..d2b7724a2215 100644
--- a/compiler/rustc_codegen_gcc/.github/workflows/ci.yml
+++ b/compiler/rustc_codegen_gcc/.github/workflows/ci.yml
@@ -4,36 +4,72 @@ on:
- push
- pull_request
+permissions:
+ contents: read
+
+env:
+ # Enable backtraces for easier debugging
+ RUST_BACKTRACE: 1
+
jobs:
build:
- runs-on: ubuntu-latest
+ runs-on: ubuntu-22.04
strategy:
fail-fast: false
matrix:
- libgccjit_version: ["libgccjit.so", "libgccjit_without_int128.so", "libgccjit12.so"]
+ libgccjit_version:
+ - { gcc: "libgccjit.so", extra: "", env_extra: "", artifacts_branch: "master" }
+ - { gcc: "libgccjit_without_int128.so", extra: "", env_extra: "", artifacts_branch: "master-without-128bit-integers" }
+ - { gcc: "libgccjit12.so", extra: "--no-default-features", env_extra: "TEST_FLAGS='-Cpanic=abort -Zpanic-abort-tests'", artifacts_branch: "gcc12" }
+ commands: [
+ "--mini-tests",
+ "--std-tests",
+ # FIXME: re-enable asm tests when GCC can emit in the right syntax.
+ # "--asm-tests",
+ "--test-libcore",
+ "--extended-rand-tests",
+ "--extended-regex-example-tests",
+ "--extended-regex-tests",
+ "--test-successful-rustc --nb-parts 2 --current-part 0",
+ "--test-successful-rustc --nb-parts 2 --current-part 1",
+ "--test-failing-rustc",
+ ]
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v3
with:
repository: llvm/llvm-project
path: llvm
- name: Install packages
- run: sudo apt-get install ninja-build ripgrep
+ # `llvm-14-tools` is needed to install the `FileCheck` binary which is used for asm tests.
+ run: sudo apt-get install ninja-build ripgrep llvm-14-tools
+
+ - name: Install libgccjit12
+ if: matrix.libgccjit_version.gcc == 'libgccjit12.so'
+ run: sudo apt-get install libgccjit-12-dev
- name: Download artifact
+ if: matrix.libgccjit_version.gcc != 'libgccjit12.so'
uses: dawidd6/action-download-artifact@v2
with:
workflow: main.yml
- name: ${{ matrix.libgccjit_version }}
+ name: ${{ matrix.libgccjit_version.gcc }}
path: gcc-build
repo: antoyo/gcc
+ branch: ${{ matrix.libgccjit_version.artifacts_branch }}
+ event: push
search_artifacts: true # Because, instead, the action only check the last job ran and that won't work since we want multiple artifacts.
- name: Setup path to libgccjit
+ if: matrix.libgccjit_version.gcc == 'libgccjit12.so'
+ run: echo /usr/lib/gcc/x86_64-linux-gnu/12 > gcc_path
+
+ - name: Setup path to libgccjit
+ if: matrix.libgccjit_version.gcc != 'libgccjit12.so'
run: |
echo $(readlink -f gcc-build) > gcc_path
# NOTE: the filename is still libgccjit.so even when the artifact name is different.
@@ -48,49 +84,44 @@ jobs:
- name: Set RUST_COMPILER_RT_ROOT
run: echo "RUST_COMPILER_RT_ROOT="${{ env.workspace }}/llvm/compiler-rt >> $GITHUB_ENV
- # https://github.com/actions/cache/issues/133
- - name: Fixup owner of ~/.cargo/
- # Don't remove the trailing /. It is necessary to follow the symlink.
- run: sudo chown -R $(whoami):$(id -ng) ~/.cargo/
-
- name: Cache cargo installed crates
- uses: actions/cache@v1.1.2
+ uses: actions/cache@v3
with:
path: ~/.cargo/bin
key: cargo-installed-crates2-ubuntu-latest
- name: Cache cargo registry
- uses: actions/cache@v1
+ uses: actions/cache@v3
with:
path: ~/.cargo/registry
key: ${{ runner.os }}-cargo-registry2-${{ hashFiles('**/Cargo.lock') }}
- name: Cache cargo index
- uses: actions/cache@v1
+ uses: actions/cache@v3
with:
path: ~/.cargo/git
key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }}
- name: Cache cargo target dir
- uses: actions/cache@v1.1.2
+ uses: actions/cache@v3
with:
path: target
key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain') }}
- - name: Build
- if: matrix.libgccjit_version != 'libgccjit12.so'
- run: |
- ./prepare_build.sh
- ./build.sh
- cargo test
- ./clean_all.sh
+ #- name: Cache rust repository
+ ## We only clone the rust repository for rustc tests
+ #if: ${{ contains(matrix.commands, 'rustc') }}
+ #uses: actions/cache@v3
+ #id: cache-rust-repository
+ #with:
+ #path: rust
+ #key: ${{ runner.os }}-packages-${{ hashFiles('rust/.git/HEAD') }}
- name: Build
- if: matrix.libgccjit_version == 'libgccjit12.so'
run: |
./prepare_build.sh
- ./build.sh --no-default-features
- cargo test --no-default-features
+ ${{ matrix.libgccjit_version.env_extra }} ./build.sh ${{ matrix.libgccjit_version.extra }}
+ ${{ matrix.libgccjit_version.env_extra }} cargo test ${{ matrix.libgccjit_version.extra }}
./clean_all.sh
- name: Prepare dependencies
@@ -106,26 +137,16 @@ jobs:
command: build
args: --release
- - name: Test
- if: matrix.libgccjit_version != 'libgccjit12.so'
+ - name: Add more failing tests for GCC 12
+ if: ${{ matrix.libgccjit_version.gcc == 'libgccjit12.so' }}
+ run: cat failing-ui-tests12.txt >> failing-ui-tests.txt
+
+ - name: Run tests
run: |
- # Enable backtraces for easier debugging
- export RUST_BACKTRACE=1
+ ${{ matrix.libgccjit_version.env_extra }} ./test.sh --release --clean --build-sysroot ${{ matrix.commands }} ${{ matrix.libgccjit_version.extra }}
- # Reduce amount of benchmark runs as they are slow
- export COMPILE_RUNS=2
- export RUN_RUNS=2
-
- ./test.sh --release
-
- - name: Test
- if: matrix.libgccjit_version == 'libgccjit12.so'
- run: |
- # Enable backtraces for easier debugging
- export RUST_BACKTRACE=1
-
- # Reduce amount of benchmark runs as they are slow
- export COMPILE_RUNS=2
- export RUN_RUNS=2
-
- ./test.sh --release --no-default-features
+ duplicates:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3
+ - run: python tools/check_intrinsics_duplicates.py
diff --git a/compiler/rustc_codegen_gcc/.github/workflows/release.yml b/compiler/rustc_codegen_gcc/.github/workflows/release.yml
new file mode 100644
index 000000000000..c4e99469bc20
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/.github/workflows/release.yml
@@ -0,0 +1,111 @@
+name: CI with sysroot compiled in release mode
+
+on:
+ - push
+ - pull_request
+
+permissions:
+ contents: read
+
+env:
+ # Enable backtraces for easier debugging
+ RUST_BACKTRACE: 1
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+
+ strategy:
+ fail-fast: false
+ matrix:
+ libgccjit_version:
+ - { gcc: "libgccjit.so", artifacts_branch: "master" }
+ commands: [
+ "--test-successful-rustc --nb-parts 2 --current-part 0",
+ "--test-successful-rustc --nb-parts 2 --current-part 1",
+ ]
+
+ steps:
+ - uses: actions/checkout@v3
+
+ - uses: actions/checkout@v3
+ with:
+ repository: llvm/llvm-project
+ path: llvm
+
+ - name: Install packages
+ run: sudo apt-get install ninja-build ripgrep
+
+ - name: Download artifact
+ uses: dawidd6/action-download-artifact@v2
+ with:
+ workflow: main.yml
+ name: ${{ matrix.libgccjit_version.gcc }}
+ path: gcc-build
+ repo: antoyo/gcc
+ branch: ${{ matrix.libgccjit_version.artifacts_branch }}
+ event: push
+ search_artifacts: true # Because, instead, the action only check the last job ran and that won't work since we want multiple artifacts.
+
+ - name: Setup path to libgccjit
+ run: |
+ echo $(readlink -f gcc-build) > gcc_path
+ # NOTE: the filename is still libgccjit.so even when the artifact name is different.
+ ln gcc-build/libgccjit.so gcc-build/libgccjit.so.0
+
+ - name: Set env
+ run: |
+ echo "LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV
+ echo "LD_LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV
+ echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV
+
+ - name: Set RUST_COMPILER_RT_ROOT
+ run: echo "RUST_COMPILER_RT_ROOT="${{ env.workspace }}/llvm/compiler-rt >> $GITHUB_ENV
+
+ - name: Cache cargo installed crates
+ uses: actions/cache@v3
+ with:
+ path: ~/.cargo/bin
+ key: cargo-installed-crates2-ubuntu-latest
+
+ - name: Cache cargo registry
+ uses: actions/cache@v3
+ with:
+ path: ~/.cargo/registry
+ key: ${{ runner.os }}-cargo-registry2-${{ hashFiles('**/Cargo.lock') }}
+
+ - name: Cache cargo index
+ uses: actions/cache@v3
+ with:
+ path: ~/.cargo/git
+ key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }}
+
+ - name: Cache cargo target dir
+ uses: actions/cache@v3
+ with:
+ path: target
+ key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain') }}
+
+ - name: Build
+ run: |
+ ./prepare_build.sh
+ ./build.sh --release --release-sysroot
+ cargo test
+ ./clean_all.sh
+
+ - name: Prepare dependencies
+ run: |
+ git config --global user.email "user@example.com"
+ git config --global user.name "User"
+ ./prepare.sh
+
+ # Compile is a separate step, as the actions-rs/cargo action supports error annotations
+ - name: Compile
+ uses: actions-rs/cargo@v1.0.3
+ with:
+ command: build
+ args: --release
+
+ - name: Run tests
+ run: |
+ ./test.sh --release --clean --release-sysroot --build-sysroot ${{ matrix.commands }}
diff --git a/compiler/rustc_codegen_gcc/.github/workflows/stdarch.yml b/compiler/rustc_codegen_gcc/.github/workflows/stdarch.yml
new file mode 100644
index 000000000000..42fb35e738ff
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/.github/workflows/stdarch.yml
@@ -0,0 +1,116 @@
+name: stdarch tests with sysroot compiled in release mode
+
+on:
+ - push
+ - pull_request
+
+permissions:
+ contents: read
+
+env:
+ # Enable backtraces for easier debugging
+ RUST_BACKTRACE: 1
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+
+ strategy:
+ fail-fast: false
+ matrix:
+ libgccjit_version:
+ - { gcc: "libgccjit.so", artifacts_branch: "master" }
+ commands: [
+ "--test-successful-rustc --nb-parts 2 --current-part 0",
+ "--test-successful-rustc --nb-parts 2 --current-part 1",
+ ]
+
+ steps:
+ - uses: actions/checkout@v3
+
+ - uses: actions/checkout@v3
+ with:
+ repository: llvm/llvm-project
+ path: llvm
+
+ - name: Install packages
+ run: sudo apt-get install ninja-build ripgrep
+
+ - name: Download artifact
+ uses: dawidd6/action-download-artifact@v2
+ with:
+ workflow: main.yml
+ name: ${{ matrix.libgccjit_version.gcc }}
+ path: gcc-build
+ repo: antoyo/gcc
+ branch: ${{ matrix.libgccjit_version.artifacts_branch }}
+ event: push
+ search_artifacts: true # Because, instead, the action only check the last job ran and that won't work since we want multiple artifacts.
+
+ - name: Setup path to libgccjit
+ run: |
+ echo $(readlink -f gcc-build) > gcc_path
+ # NOTE: the filename is still libgccjit.so even when the artifact name is different.
+ ln gcc-build/libgccjit.so gcc-build/libgccjit.so.0
+
+ - name: Set env
+ run: |
+ echo "LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV
+ echo "LD_LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV
+ echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV
+
+ - name: Set RUST_COMPILER_RT_ROOT
+ run: echo "RUST_COMPILER_RT_ROOT="${{ env.workspace }}/llvm/compiler-rt >> $GITHUB_ENV
+
+ - name: Cache cargo installed crates
+ uses: actions/cache@v3
+ with:
+ path: ~/.cargo/bin
+ key: cargo-installed-crates2-ubuntu-latest
+
+ - name: Cache cargo registry
+ uses: actions/cache@v3
+ with:
+ path: ~/.cargo/registry
+ key: ${{ runner.os }}-cargo-registry2-${{ hashFiles('**/Cargo.lock') }}
+
+ - name: Cache cargo index
+ uses: actions/cache@v3
+ with:
+ path: ~/.cargo/git
+ key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }}
+
+ - name: Cache cargo target dir
+ uses: actions/cache@v3
+ with:
+ path: target
+ key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain') }}
+
+ - name: Build
+ run: |
+ ./prepare_build.sh
+ ./build.sh --release --release-sysroot
+ cargo test
+ ./clean_all.sh
+
+ - name: Prepare dependencies
+ run: |
+ git config --global user.email "user@example.com"
+ git config --global user.name "User"
+ ./prepare.sh
+
+ # Compile is a separate step, as the actions-rs/cargo action supports error annotations
+ - name: Compile
+ uses: actions-rs/cargo@v1.0.3
+ with:
+ command: build
+ args: --release
+
+ - name: Run tests
+ run: |
+ ./test.sh --release --clean --release-sysroot --build-sysroot --mini-tests --std-tests --test-libcore
+
+ - name: Run stdarch tests
+ run: |
+ cd build_sysroot/sysroot_src/library/stdarch/
+ CHANNEL=release TARGET=x86_64-unknown-linux-gnu ../../../../cargo.sh test
diff --git a/compiler/rustc_codegen_gcc/Cargo.lock b/compiler/rustc_codegen_gcc/Cargo.lock
index 1cb219e12e04..80e574189408 100644
--- a/compiler/rustc_codegen_gcc/Cargo.lock
+++ b/compiler/rustc_codegen_gcc/Cargo.lock
@@ -35,7 +35,7 @@ dependencies = [
[[package]]
name = "gccjit"
version = "1.0.0"
-source = "git+https://github.com/antoyo/gccjit.rs#bdb86fb5092895ff5589726b33250010c64d93f6"
+source = "git+https://github.com/antoyo/gccjit.rs#eefb8c662d61477f34b7c32d26bcda5f1ef08432"
dependencies = [
"gccjit_sys",
]
@@ -43,7 +43,7 @@ dependencies = [
[[package]]
name = "gccjit_sys"
version = "0.0.1"
-source = "git+https://github.com/antoyo/gccjit.rs#bdb86fb5092895ff5589726b33250010c64d93f6"
+source = "git+https://github.com/antoyo/gccjit.rs#eefb8c662d61477f34b7c32d26bcda5f1ef08432"
dependencies = [
"libc 0.1.12",
]
@@ -208,6 +208,7 @@ version = "0.1.0"
dependencies = [
"gccjit",
"lang_tester",
+ "smallvec",
"tempfile",
]
@@ -220,6 +221,12 @@ dependencies = [
"winapi-util",
]
+[[package]]
+name = "smallvec"
+version = "1.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
+
[[package]]
name = "tempfile"
version = "3.2.0"
diff --git a/compiler/rustc_codegen_gcc/Cargo.toml b/compiler/rustc_codegen_gcc/Cargo.toml
index 1f3da2f799b7..81066d9ce1f0 100644
--- a/compiler/rustc_codegen_gcc/Cargo.toml
+++ b/compiler/rustc_codegen_gcc/Cargo.toml
@@ -27,6 +27,8 @@ gccjit = { git = "https://github.com/antoyo/gccjit.rs" }
# Local copy.
#gccjit = { path = "../gccjit.rs" }
+smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
+
[dev-dependencies]
lang_tester = "0.3.9"
tempfile = "3.1.0"
diff --git a/compiler/rustc_codegen_gcc/Readme.md b/compiler/rustc_codegen_gcc/Readme.md
index fe23a2676966..bb7419438925 100644
--- a/compiler/rustc_codegen_gcc/Readme.md
+++ b/compiler/rustc_codegen_gcc/Readme.md
@@ -1,5 +1,7 @@
# WIP libgccjit codegen backend for rust
+[](https://web.libera.chat/#rustc_codegen_gcc)
+
This is a GCC codegen for rustc, which means it can be loaded by the existing rustc frontend, but benefits from GCC: more architectures are supported and GCC's optimizations are used.
**Despite its name, libgccjit can be used for ahead-of-time compilation, as is used here.**
@@ -16,21 +18,61 @@ The patches in [this repository](https://github.com/antoyo/libgccjit-patches) ne
(Those patches should work when applied on master, but in case it doesn't work, they are known to work when applied on 079c23cfe079f203d5df83fea8e92a60c7d7e878.)
You can also use my [fork of gcc](https://github.com/antoyo/gcc) which already includes these patches.**
+To build it (most of these instructions come from [here](https://gcc.gnu.org/onlinedocs/jit/internals/index.html), so don't hesitate to take a look there if you encounter an issue):
+
+```bash
+$ git clone https://github.com/antoyo/gcc
+$ sudo apt install flex libmpfr-dev libgmp-dev libmpc3 libmpc-dev
+$ mkdir gcc-build gcc-install
+$ cd gcc-build
+$ ../gcc/configure \
+ --enable-host-shared \
+ --enable-languages=jit \
+ --enable-checking=release \ # it enables extra checks which allow to find bugs
+ --disable-bootstrap \
+ --disable-multilib \
+ --prefix=$(pwd)/../gcc-install
+$ make -j4 # You can replace `4` with another number depending on how many cores you have.
+```
+
+If you want to run libgccjit tests, you will need to also enable the C++ language in the `configure`:
+
+```bash
+--enable-languages=jit,c++
+```
+
+Then to run libgccjit tests:
+
+```bash
+$ cd gcc # from the `gcc-build` folder
+$ make check-jit
+# To run one specific test:
+$ make check-jit RUNTESTFLAGS="-v -v -v jit.exp=jit.dg/test-asm.cc"
+```
+
**Put the path to your custom build of libgccjit in the file `gcc_path`.**
```bash
-$ git clone https://github.com/rust-lang/rustc_codegen_gcc.git
-$ cd rustc_codegen_gcc
+$ dirname $(readlink -f `find . -name libgccjit.so`) > gcc_path
+```
+
+You also need to set RUST_COMPILER_RT_ROOT:
+
+```bash
$ git clone https://github.com/llvm/llvm-project llvm --depth 1 --single-branch
$ export RUST_COMPILER_RT_ROOT="$PWD/llvm/compiler-rt"
-$ ./prepare_build.sh # download and patch sysroot src
-$ ./build.sh --release
+```
+
+Then you can run commands like this:
+
+```bash
+$ ./prepare.sh # download and patch sysroot src and install hyperfine for benchmarking
+$ LIBRARY_PATH=$(cat gcc_path) LD_LIBRARY_PATH=$(cat gcc_path) ./build.sh --release
```
To run the tests:
```bash
-$ ./prepare.sh # download and patch sysroot src and install hyperfine for benchmarking
$ ./test.sh --release
```
@@ -120,13 +162,52 @@ To print a debug representation of a tree:
debug_tree(expr);
```
+(defined in print-tree.h)
+
+To print a debug reprensentation of a gimple struct:
+
+```c
+debug_gimple_stmt(gimple_struct)
+```
+
To get the `rustc` command to run in `gdb`, add the `--verbose` flag to `cargo build`.
+To have the correct file paths in `gdb` instead of `/usr/src/debug/gcc/libstdc++-v3/libsupc++/eh_personality.cc`:
+
+Maybe by calling the following at the beginning of gdb:
+
+```
+set substitute-path /usr/src/debug/gcc /path/to/gcc-repo/gcc
+```
+
+TODO(antoyo): but that's not what I remember I was doing.
+
### How to use a custom-build rustc
* Build the stage2 compiler (`rustup toolchain link debug-current build/x86_64-unknown-linux-gnu/stage2`).
* Clean and rebuild the codegen with `debug-current` in the file `rust-toolchain`.
+### How to install a forked git-subtree
+
+Using git-subtree with `rustc` requires a patched git to make it work.
+The PR that is needed is [here](https://github.com/gitgitgadget/git/pull/493).
+Use the following instructions to install it:
+
+```
+git clone git@github.com:tqc/git.git
+cd git
+git checkout tqc/subtree
+make
+make install
+cd contrib/subtree
+make
+cp git-subtree ~/bin
+```
+
+### How to use [mem-trace](https://github.com/antoyo/mem-trace)
+
+`rustc` needs to be built without `jemalloc` so that `mem-trace` can overload `malloc` since `jemalloc` is linked statically, so a `LD_PRELOAD`-ed library won't a chance to intercept the calls to `malloc`.
+
### How to build a cross-compiling libgccjit
#### Building libgccjit
@@ -142,6 +223,5 @@ To get the `rustc` command to run in `gdb`, add the `--verbose` flag to `cargo b
* Since rustc doesn't support this architecture yet, set it back to `TARGET_TRIPLE="mips-unknown-linux-gnu"` (or another target having the same attributes). Alternatively, create a [target specification file](https://book.avr-rust.com/005.1-the-target-specification-json-file.html) (note that the `arch` specified in this file must be supported by the rust compiler).
* Set `linker='-Clinker=m68k-linux-gcc'`.
* Set the path to the cross-compiling libgccjit in `gcc_path`.
- * Disable the 128-bit integer types if the target doesn't support them by using `let i128_type = context.new_type::();` in `context.rs` (same for u128_type).
* Comment the line: `context.add_command_line_option("-masm=intel");` in src/base.rs.
* (might not be necessary) Disable the compilation of libstd.so (and possibly libcore.so?).
diff --git a/compiler/rustc_codegen_gcc/build_sysroot/build_sysroot.sh b/compiler/rustc_codegen_gcc/build_sysroot/build_sysroot.sh
index f293192a099d..9d692d599f6b 100755
--- a/compiler/rustc_codegen_gcc/build_sysroot/build_sysroot.sh
+++ b/compiler/rustc_codegen_gcc/build_sysroot/build_sysroot.sh
@@ -16,7 +16,7 @@ rm Cargo.lock test_target/Cargo.lock 2>/dev/null || true
rm -r sysroot/ 2>/dev/null || true
# Build libs
-export RUSTFLAGS="$RUSTFLAGS -Z force-unstable-if-unmarked -Cpanic=abort"
+export RUSTFLAGS="$RUSTFLAGS -Z force-unstable-if-unmarked"
if [[ "$1" == "--release" ]]; then
sysroot_channel='release'
RUSTFLAGS="$RUSTFLAGS -Zmir-opt-level=3" cargo build --target $TARGET_TRIPLE --release
diff --git a/compiler/rustc_codegen_gcc/config.sh b/compiler/rustc_codegen_gcc/config.sh
index b25e215fb9ee..166e83901c4f 100644
--- a/compiler/rustc_codegen_gcc/config.sh
+++ b/compiler/rustc_codegen_gcc/config.sh
@@ -38,7 +38,7 @@ if [[ "$HOST_TRIPLE" != "$TARGET_TRIPLE" ]]; then
fi
fi
-export RUSTFLAGS="$CG_RUSTFLAGS $linker -Cpanic=abort -Csymbol-mangling-version=v0 -Cdebuginfo=2 -Clto=off -Zpanic-abort-tests -Zcodegen-backend=$(pwd)/target/${CHANNEL:-debug}/librustc_codegen_gcc.$dylib_ext --sysroot $(pwd)/build_sysroot/sysroot"
+export RUSTFLAGS="$CG_RUSTFLAGS $linker -Csymbol-mangling-version=v0 -Cdebuginfo=2 -Clto=off -Zcodegen-backend=$(pwd)/target/${CHANNEL:-debug}/librustc_codegen_gcc.$dylib_ext --sysroot $(pwd)/build_sysroot/sysroot $TEST_FLAGS"
# FIXME(antoyo): remove once the atomic shim is gone
if [[ `uname` == 'Darwin' ]]; then
diff --git a/compiler/rustc_codegen_gcc/example/alloc_example.rs b/compiler/rustc_codegen_gcc/example/alloc_example.rs
index 74ea7ec4ede6..c80348ca5497 100644
--- a/compiler/rustc_codegen_gcc/example/alloc_example.rs
+++ b/compiler/rustc_codegen_gcc/example/alloc_example.rs
@@ -1,4 +1,4 @@
-#![feature(start, box_syntax, core_intrinsics, alloc_error_handler)]
+#![feature(start, box_syntax, core_intrinsics, alloc_error_handler, lang_items)]
#![no_std]
extern crate alloc;
@@ -18,16 +18,22 @@ extern "C" {
#[panic_handler]
fn panic_handler(_: &core::panic::PanicInfo) -> ! {
- unsafe {
- core::intrinsics::abort();
- }
+ core::intrinsics::abort();
}
#[alloc_error_handler]
fn alloc_error_handler(_: alloc::alloc::Layout) -> ! {
- unsafe {
- core::intrinsics::abort();
- }
+ core::intrinsics::abort();
+}
+
+#[lang = "eh_personality"]
+fn eh_personality() -> ! {
+ loop {}
+}
+
+#[no_mangle]
+unsafe extern "C" fn _Unwind_Resume() {
+ core::intrinsics::unreachable();
}
#[start]
diff --git a/compiler/rustc_codegen_gcc/example/mini_core.rs b/compiler/rustc_codegen_gcc/example/mini_core.rs
index ddcbb0d9fc7e..637b8dc53fef 100644
--- a/compiler/rustc_codegen_gcc/example/mini_core.rs
+++ b/compiler/rustc_codegen_gcc/example/mini_core.rs
@@ -1,6 +1,6 @@
#![feature(
no_core, lang_items, intrinsics, unboxed_closures, type_ascription, extern_types,
- untagged_unions, decl_macro, rustc_attrs, transparent_unions, auto_traits,
+ decl_macro, rustc_attrs, transparent_unions, auto_traits,
thread_local
)]
#![no_core]
@@ -17,6 +17,9 @@ pub trait Sized {}
#[lang = "destruct"]
pub trait Destruct {}
+#[lang = "tuple_trait"]
+pub trait Tuple {}
+
#[lang = "unsize"]
pub trait Unsize {}
@@ -39,14 +42,14 @@ impl<'a, T: ?Sized+Unsize, U: ?Sized> DispatchFromDyn<&'a mut U> for &'a mut
impl, U: ?Sized> DispatchFromDyn<*const U> for *const T {}
// *mut T -> *mut U
impl, U: ?Sized> DispatchFromDyn<*mut U> for *mut T {}
-impl, U: ?Sized> DispatchFromDyn> for Box {}
+impl, U: ?Sized> DispatchFromDyn> for Box {}
#[lang = "receiver"]
pub trait Receiver {}
impl Receiver for &T {}
impl Receiver for &mut T {}
-impl Receiver for Box {}
+impl Receiver for Box {}
#[lang = "copy"]
pub unsafe trait Copy {}
@@ -396,7 +399,7 @@ pub struct PhantomData;
#[lang = "fn_once"]
#[rustc_paren_sugar]
-pub trait FnOnce {
+pub trait FnOnce {
#[lang = "fn_once_output"]
type Output;
@@ -405,13 +408,21 @@ pub trait FnOnce {
#[lang = "fn_mut"]
#[rustc_paren_sugar]
-pub trait FnMut: FnOnce {
+pub trait FnMut: FnOnce {
extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
}
#[lang = "panic"]
#[track_caller]
-pub fn panic(_msg: &str) -> ! {
+pub fn panic(_msg: &'static str) -> ! {
+ unsafe {
+ libc::puts("Panicking\n\0" as *const str as *const u8);
+ intrinsics::abort();
+ }
+}
+
+#[lang = "panic_cannot_unwind"]
+fn panic_cannot_unwind() -> ! {
unsafe {
libc::puts("Panicking\n\0" as *const str as *const u8);
intrinsics::abort();
@@ -450,17 +461,32 @@ pub trait Deref {
pub trait Allocator {
}
+impl Allocator for () {}
+
pub struct Global;
impl Allocator for Global {}
-#[lang = "owned_box"]
-pub struct Box<
- T: ?Sized,
- A: Allocator = Global,
->(*mut T, A);
+#[repr(transparent)]
+#[rustc_layout_scalar_valid_range_start(1)]
+#[rustc_nonnull_optimization_guaranteed]
+pub struct NonNull(pub *const T);
-impl, U: ?Sized> CoerceUnsized> for Box {}
+impl CoerceUnsized> for NonNull where T: Unsize {}
+impl DispatchFromDyn> for NonNull where T: Unsize {}
+
+pub struct Unique {
+ pub pointer: NonNull,
+ pub _marker: PhantomData,
+}
+
+impl CoerceUnsized> for Unique where T: Unsize {}
+impl DispatchFromDyn> for Unique where T: Unsize {}
+
+#[lang = "owned_box"]
+pub struct Box(Unique, A);
+
+impl, U: ?Sized, A: Allocator> CoerceUnsized> for Box {}
impl Drop for Box {
fn drop(&mut self) {
@@ -468,7 +494,7 @@ impl Drop for Box {
}
}
-impl Deref for Box {
+impl Deref for Box {
type Target = T;
fn deref(&self) -> &Self::Target {
@@ -482,8 +508,8 @@ unsafe fn allocate(size: usize, _align: usize) -> *mut u8 {
}
#[lang = "box_free"]
-unsafe fn box_free(ptr: *mut T, alloc: A) {
- libc::free(ptr as *mut u8);
+unsafe fn box_free(ptr: Unique, _alloc: ()) {
+ libc::free(ptr.pointer.0 as *mut u8);
}
#[lang = "drop"]
@@ -505,17 +531,25 @@ pub union MaybeUninit {
}
pub mod intrinsics {
+ use crate::Sized;
+
extern "rust-intrinsic" {
+ #[rustc_safe_intrinsic]
pub fn abort() -> !;
+ #[rustc_safe_intrinsic]
pub fn size_of() -> usize;
- pub fn size_of_val(val: *const T) -> usize;
+ pub fn size_of_val(val: *const T) -> usize;
+ #[rustc_safe_intrinsic]
pub fn min_align_of() -> usize;
- pub fn min_align_of_val(val: *const T) -> usize;
+ pub fn min_align_of_val(val: *const T) -> usize;
pub fn copy(src: *const T, dst: *mut T, count: usize);
pub fn transmute(e: T) -> U;
pub fn ctlz_nonzero(x: T) -> T;
- pub fn needs_drop() -> bool;
+ #[rustc_safe_intrinsic]
+ pub fn needs_drop() -> bool;
+ #[rustc_safe_intrinsic]
pub fn bitreverse(x: T) -> T;
+ #[rustc_safe_intrinsic]
pub fn bswap(x: T) -> T;
pub fn write_bytes(dst: *mut T, val: u8, count: usize);
pub fn unreachable() -> !;
diff --git a/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs b/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs
index 14fd9eeffa6a..993a31e68eab 100644
--- a/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs
+++ b/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs
@@ -85,6 +85,7 @@ fn start(
main: fn() -> T,
argc: isize,
argv: *const *const u8,
+ _sigpipe: u8,
) -> isize {
if argc == 3 {
unsafe { puts(*argv); }
@@ -228,6 +229,7 @@ fn main() {
} as Box;
const FUNC_REF: Option = Some(main);
+ #[allow(unreachable_code)]
match FUNC_REF {
Some(_) => {},
None => assert!(false),
diff --git a/compiler/rustc_codegen_gcc/example/mod_bench.rs b/compiler/rustc_codegen_gcc/example/mod_bench.rs
index 2e2b0052dee8..95bcad2cd173 100644
--- a/compiler/rustc_codegen_gcc/example/mod_bench.rs
+++ b/compiler/rustc_codegen_gcc/example/mod_bench.rs
@@ -6,9 +6,7 @@ extern {}
#[panic_handler]
fn panic_handler(_: &core::panic::PanicInfo) -> ! {
- unsafe {
- core::intrinsics::abort();
- }
+ core::intrinsics::abort();
}
#[lang="eh_personality"]
@@ -32,6 +30,6 @@ fn main(_argc: isize, _argv: *const *const u8) -> isize {
#[inline(never)]
fn black_box(i: u32) {
if i != 1 {
- unsafe { core::intrinsics::abort(); }
+ core::intrinsics::abort();
}
}
diff --git a/compiler/rustc_codegen_gcc/example/std_example.rs b/compiler/rustc_codegen_gcc/example/std_example.rs
index 31069058aea3..5c171c49fd19 100644
--- a/compiler/rustc_codegen_gcc/example/std_example.rs
+++ b/compiler/rustc_codegen_gcc/example/std_example.rs
@@ -1,5 +1,6 @@
#![feature(core_intrinsics, generators, generator_trait, is_sorted)]
+#[cfg(feature="master")]
use std::arch::x86_64::*;
use std::io::Write;
use std::ops::Generator;
diff --git a/compiler/rustc_codegen_gcc/failing-ui-tests.txt b/compiler/rustc_codegen_gcc/failing-ui-tests.txt
new file mode 100644
index 000000000000..8539e27ea6a5
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/failing-ui-tests.txt
@@ -0,0 +1,68 @@
+tests/ui/allocator/custom-in-block.rs
+tests/ui/allocator/custom-in-submodule.rs
+tests/ui/allocator/custom.rs
+tests/ui/allocator/hygiene.rs
+tests/ui/allocator/no_std-alloc-error-handler-custom.rs
+tests/ui/allocator/no_std-alloc-error-handler-default.rs
+tests/ui/allocator/xcrate-use.rs
+tests/ui/allocator/xcrate-use2.rs
+tests/ui/asm/may_unwind.rs
+tests/ui/asm/x86_64/multiple-clobber-abi.rs
+tests/ui/debuginfo/debuginfo-emit-llvm-ir-and-split-debuginfo.rs
+tests/ui/functions-closures/parallel-codegen-closures.rs
+tests/ui/linkage-attr/linkage1.rs
+tests/ui/lto/dylib-works.rs
+tests/ui/numbers-arithmetic/saturating-float-casts.rs
+tests/ui/polymorphization/promoted-function.rs
+tests/ui/process/nofile-limit.rs
+tests/ui/sepcomp/sepcomp-cci.rs
+tests/ui/sepcomp/sepcomp-extern.rs
+tests/ui/sepcomp/sepcomp-fns-backwards.rs
+tests/ui/sepcomp/sepcomp-fns.rs
+tests/ui/sepcomp/sepcomp-statics.rs
+tests/ui/simd/intrinsic/generic-arithmetic-pass.rs
+tests/ui/sse2.rs
+tests/ui/target-feature/missing-plusminus.rs
+tests/ui/asm/x86_64/may_unwind.rs
+tests/ui/backtrace.rs
+tests/ui/catch-unwind-bang.rs
+tests/ui/cfg/cfg-panic-abort.rs
+tests/ui/drop/dynamic-drop-async.rs
+tests/ui/drop/repeat-drop.rs
+tests/ui/fmt/format-args-capture.rs
+tests/ui/generator/panic-drops-resume.rs
+tests/ui/generator/panic-drops.rs
+tests/ui/intrinsics/panic-uninitialized-zeroed.rs
+tests/ui/iterators/iter-sum-overflow-debug.rs
+tests/ui/iterators/iter-sum-overflow-overflow-checks.rs
+tests/ui/mir/mir_calls_to_shims.rs
+tests/ui/mir/mir_drop_order.rs
+tests/ui/mir/mir_let_chains_drop_order.rs
+tests/ui/oom_unwind.rs
+tests/ui/panic-runtime/abort-link-to-unwinding-crates.rs
+tests/ui/panic-runtime/abort.rs
+tests/ui/panic-runtime/link-to-abort.rs
+tests/ui/unwind-no-uwtable.rs
+tests/ui/parser/unclosed-delimiter-in-dep.rs
+tests/ui/runtime/rt-explody-panic-payloads.rs
+tests/ui/simd/intrinsic/ptr-cast.rs
+tests/ui/binding/fn-arg-incomplete-pattern-drop-order.rs
+tests/ui/consts/missing_span_in_backtrace.rs
+tests/ui/drop/dynamic-drop.rs
+tests/ui/dyn-star/box.rs
+tests/ui/issues/issue-40883.rs
+tests/ui/issues/issue-43853.rs
+tests/ui/issues/issue-47364.rs
+tests/ui/macros/rfc-2011-nicer-assert-messages/assert-without-captures-does-not-create-unnecessary-code.rs
+tests/ui/rfc-2091-track-caller/std-panic-locations.rs
+tests/ui/rfcs/rfc1857-drop-order.rs
+tests/ui/simd/issue-17170.rs
+tests/ui/simd/issue-39720.rs
+tests/ui/simd/issue-89193.rs
+tests/ui/statics/issue-91050-1.rs
+tests/ui/statics/issue-91050-2.rs
+tests/ui/alloc-error/default-alloc-error-hook.rs
+tests/ui/generator/panic-safe.rs
+tests/ui/issues/issue-14875.rs
+tests/ui/issues/issue-29948.rs
+tests/ui/panic-while-printing.rs
diff --git a/compiler/rustc_codegen_gcc/failing-ui-tests12.txt b/compiler/rustc_codegen_gcc/failing-ui-tests12.txt
new file mode 100644
index 000000000000..8c27bd8b8ca8
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/failing-ui-tests12.txt
@@ -0,0 +1,39 @@
+tests/ui/asm/x86_64/issue-96797.rs
+tests/ui/intrinsics/const-eval-select-x86_64.rs
+tests/ui/packed/packed-struct-drop-aligned.rs
+tests/ui/packed/packed-struct-generic-layout.rs
+tests/ui/packed/packed-struct-layout.rs
+tests/ui/packed/packed-struct-optimized-enum.rs
+tests/ui/packed/packed-struct-size.rs
+tests/ui/packed/packed-struct-vec.rs
+tests/ui/packed/packed-tuple-struct-layout.rs
+tests/ui/simd/array-type.rs
+tests/ui/simd/intrinsic/float-minmax-pass.rs
+tests/ui/simd/intrinsic/generic-arithmetic-saturating-pass.rs
+tests/ui/simd/intrinsic/generic-as.rs
+tests/ui/simd/intrinsic/generic-cast-pass.rs
+tests/ui/simd/intrinsic/generic-cast-pointer-width.rs
+tests/ui/simd/intrinsic/generic-comparison-pass.rs
+tests/ui/simd/intrinsic/generic-elements-pass.rs
+tests/ui/simd/intrinsic/generic-reduction-pass.rs
+tests/ui/simd/intrinsic/generic-select-pass.rs
+tests/ui/simd/intrinsic/inlining-issue67557-ice.rs
+tests/ui/simd/intrinsic/inlining-issue67557.rs
+tests/ui/simd/monomorphize-shuffle-index.rs
+tests/ui/simd/shuffle.rs
+tests/ui/simd/simd-bitmask.rs
+tests/ui/generator/resume-after-return.rs
+tests/ui/iterators/iter-step-overflow-debug.rs
+tests/ui/macros/rfc-2011-nicer-assert-messages/all-expr-kinds.rs
+tests/ui/numbers-arithmetic/next-power-of-two-overflow-debug.rs
+tests/ui/privacy/reachable-unnameable-items.rs
+tests/ui/rfc-1937-termination-trait/termination-trait-in-test.rs
+tests/ui/async-await/async-fn-size-moved-locals.rs
+tests/ui/async-await/async-fn-size-uninit-locals.rs
+tests/ui/cfg/cfg-panic.rs
+tests/ui/generator/size-moved-locals.rs
+tests/ui/macros/rfc-2011-nicer-assert-messages/all-not-available-cases.rs
+tests/ui/simd/intrinsic/generic-gather-pass.rs
+tests/ui/simd/issue-85915-simd-ptrs.rs
+tests/ui/issues/issue-68010-large-zst-consts.rs
+tests/ui/rust-2018/proc-macro-crate-in-paths.rs
diff --git a/compiler/rustc_codegen_gcc/locales/en-US.ftl b/compiler/rustc_codegen_gcc/locales/en-US.ftl
index 6101b28ab0cd..0a94a08f8dca 100644
--- a/compiler/rustc_codegen_gcc/locales/en-US.ftl
+++ b/compiler/rustc_codegen_gcc/locales/en-US.ftl
@@ -60,3 +60,9 @@ codegen_gcc_invalid_monomorphization_unsupported_cast =
codegen_gcc_invalid_monomorphization_unsupported_operation =
invalid monomorphization of `{$name}` intrinsic: unsupported operation on `{$in_ty}` with element `{$in_elem}`
+
+codegen_gcc_invalid_minimum_alignment =
+ invalid minimum global alignment: {$err}
+
+codegen_gcc_tied_target_features = the target features {$features} must all be either enabled or disabled together
+ .help = add the missing features in a `target_feature` attribute
diff --git a/compiler/rustc_codegen_gcc/patches/0001-Add-stdarch-Cargo.toml-for-testing.patch b/compiler/rustc_codegen_gcc/patches/0001-Add-stdarch-Cargo.toml-for-testing.patch
new file mode 100644
index 000000000000..93c63b5dcacf
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/patches/0001-Add-stdarch-Cargo.toml-for-testing.patch
@@ -0,0 +1,39 @@
+From c3821e02fbd6cb5ad6e06d759fccdc9073712375 Mon Sep 17 00:00:00 2001
+From: Antoni Boucher
+Date: Tue, 7 Jun 2022 21:40:13 -0400
+Subject: [PATCH] Add stdarch Cargo.toml for testing
+
+---
+ library/stdarch/Cargo.toml | 20 ++++++++++++++++++++
+ 1 file changed, 20 insertions(+)
+ create mode 100644 library/stdarch/Cargo.toml
+
+diff --git a/library/stdarch/Cargo.toml b/library/stdarch/Cargo.toml
+new file mode 100644
+index 0000000..fbe0a95
+--- /dev/null
++++ b/library/stdarch/Cargo.toml
+@@ -0,0 +1,20 @@
++[workspace]
++members = [
++ "crates/core_arch",
++ "crates/std_detect",
++ "crates/stdarch-gen",
++ "examples/"
++]
++exclude = [
++ "crates/wasm-assert-instr-tests"
++]
++
++[profile.release]
++debug = true
++opt-level = 3
++incremental = true
++
++[profile.bench]
++debug = 1
++opt-level = 3
++incremental = true
+--
+2.26.2.7.g19db9cfb68.dirty
+
diff --git a/compiler/rustc_codegen_gcc/patches/0001-Disable-examples.patch b/compiler/rustc_codegen_gcc/patches/0001-Disable-examples.patch
new file mode 100644
index 000000000000..1b71df1ca8df
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/patches/0001-Disable-examples.patch
@@ -0,0 +1,25 @@
+From a2d53a324a02c04b76c0e9d39dc15cd443a3b8b2 Mon Sep 17 00:00:00 2001
+From: Antoni Boucher
+Date: Fri, 25 Nov 2022 11:18:11 -0500
+Subject: [PATCH] Disable examples
+
+---
+ library/stdarch/Cargo.toml | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/library/stdarch/Cargo.toml b/library/stdarch/Cargo.toml
+index fbe0a95..748d72d 100644
+--- a/library/stdarch/Cargo.toml
++++ b/library/stdarch/Cargo.toml
+@@ -3,7 +3,7 @@ members = [
+ "crates/core_arch",
+ "crates/std_detect",
+ "crates/stdarch-gen",
+- "examples/"
++ #"examples/"
+ ]
+ exclude = [
+ "crates/wasm-assert-instr-tests"
+--
+2.26.2.7.g19db9cfb68.dirty
+
diff --git a/compiler/rustc_codegen_gcc/patches/0022-core-Disable-not-compiling-tests.patch b/compiler/rustc_codegen_gcc/patches/0022-core-Disable-not-compiling-tests.patch
index 301b3f9bde4d..4db56fa3bd2c 100644
--- a/compiler/rustc_codegen_gcc/patches/0022-core-Disable-not-compiling-tests.patch
+++ b/compiler/rustc_codegen_gcc/patches/0022-core-Disable-not-compiling-tests.patch
@@ -18,7 +18,7 @@ new file mode 100644
index 0000000..46fd999
--- /dev/null
+++ b/library/core/tests/Cargo.toml
-@@ -0,0 +1,8 @@
+@@ -0,0 +1,12 @@
+[package]
+name = "core"
+version = "0.0.0"
@@ -27,37 +27,18 @@ index 0000000..46fd999
+[lib]
+name = "coretests"
+path = "lib.rs"
-diff --git a/library/core/tests/num/flt2dec/mod.rs b/library/core/tests/num/flt2dec/mod.rs
-index a35897e..f0bf645 100644
---- a/library/core/tests/num/flt2dec/mod.rs
-+++ b/library/core/tests/num/flt2dec/mod.rs
-@@ -13,7 +13,6 @@ mod strategy {
- mod dragon;
- mod grisu;
- }
--mod random;
-
- pub fn decode_finite(v: T) -> Decoded {
- match decode(v).1 {
-diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs
-index 6609bc3..241b497 100644
---- a/library/core/tests/slice.rs
-+++ b/library/core/tests/slice.rs
-@@ -1209,6 +1209,7 @@ fn brute_force_rotate_test_1() {
- }
- }
-
-+/*
- #[test]
- #[cfg(not(target_arch = "wasm32"))]
- fn sort_unstable() {
-@@ -1394,6 +1395,7 @@ fn partition_at_index() {
- v.select_nth_unstable(0);
- assert!(v == [0xDEADBEEF]);
- }
-+*/
-
- #[test]
- #[should_panic(expected = "index 0 greater than length of slice")]
++
++[dependencies]
++rand = { version = "0.8.5", default-features = false }
++rand_xorshift = { version = "0.3.0", default-features = false }
+diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
+index 42a26ae..5ac1042 100644
+--- a/library/core/tests/lib.rs
++++ b/library/core/tests/lib.rs
+@@ -1,3 +1,4 @@
++#![cfg(test)]
+ #![feature(alloc_layout_extra)]
+ #![feature(array_chunks)]
+ #![feature(array_methods)]
--
2.21.0 (Apple Git-122)
diff --git a/compiler/rustc_codegen_gcc/patches/0024-core-Disable-portable-simd-test.patch b/compiler/rustc_codegen_gcc/patches/0024-core-Disable-portable-simd-test.patch
deleted file mode 100644
index c59a40df0398..000000000000
--- a/compiler/rustc_codegen_gcc/patches/0024-core-Disable-portable-simd-test.patch
+++ /dev/null
@@ -1,28 +0,0 @@
-From b1ae000f6da1abd3b8e9b80c40bc11c89b8ae93c Mon Sep 17 00:00:00 2001
-From: bjorn3
-Date: Thu, 30 Dec 2021 16:54:40 +0100
-Subject: [PATCH] [core] Disable portable-simd test
-
----
- library/core/tests/lib.rs | 1 -
- 1 file changed, 1 deletion(-)
-
-diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
-index 06c7be0..359e2e7 100644
---- a/library/core/tests/lib.rs
-+++ b/library/core/tests/lib.rs
-@@ -75,7 +75,6 @@
- #![feature(never_type)]
- #![feature(unwrap_infallible)]
--#![feature(portable_simd)]
- #![feature(ptr_metadata)]
- #![feature(once_cell)]
- #![feature(option_result_contains)]
-@@ -127,7 +126,6 @@ mod pin;
- mod pin_macro;
- mod ptr;
- mod result;
--mod simd;
- mod slice;
- mod str;
- mod str_lossy;
diff --git a/compiler/rustc_codegen_gcc/rust-toolchain b/compiler/rustc_codegen_gcc/rust-toolchain
index b20aeb979ad7..933ecd45baad 100644
--- a/compiler/rustc_codegen_gcc/rust-toolchain
+++ b/compiler/rustc_codegen_gcc/rust-toolchain
@@ -1,3 +1,3 @@
[toolchain]
-channel = "nightly-2022-06-06"
+channel = "nightly-2023-03-02"
components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
diff --git a/compiler/rustc_codegen_gcc/rustc_patches/compile_test.patch b/compiler/rustc_codegen_gcc/rustc_patches/compile_test.patch
deleted file mode 100644
index 59143eac37b3..000000000000
--- a/compiler/rustc_codegen_gcc/rustc_patches/compile_test.patch
+++ /dev/null
@@ -1,14 +0,0 @@
-diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
-index 887d27fd6dca4..2c2239f2b83d1 100644
---- a/src/tools/compiletest/src/header.rs
-+++ b/src/tools/compiletest/src/header.rs
-@@ -806,8 +806,8 @@ pub fn make_test_description(
- cfg: Option<&str>,
- ) -> test::TestDesc {
- let mut ignore = false;
- #[cfg(not(bootstrap))]
-- let ignore_message: Option = None;
-+ let ignore_message: Option<&str> = None;
- let mut should_fail = false;
-
- let rustc_has_profiler_support = env::var_os("RUSTC_PROFILER_SUPPORT").is_some();
diff --git a/compiler/rustc_codegen_gcc/src/allocator.rs b/compiler/rustc_codegen_gcc/src/allocator.rs
index e2c9ffe9c1c3..4bad33ee879e 100644
--- a/compiler/rustc_codegen_gcc/src/allocator.rs
+++ b/compiler/rustc_codegen_gcc/src/allocator.rs
@@ -1,3 +1,5 @@
+#[cfg(feature="master")]
+use gccjit::FnAttribute;
use gccjit::{FunctionType, GlobalKind, ToRValue};
use rustc_ast::expand::allocator::{AllocatorKind, AllocatorTy, ALLOCATOR_METHODS};
use rustc_middle::bug;
@@ -50,7 +52,8 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut GccContext, _module_nam
let func = context.new_function(None, FunctionType::Exported, output.unwrap_or(void), &args, name, false);
if tcx.sess.target.options.default_hidden_visibility {
- // TODO(antoyo): set visibility.
+ #[cfg(feature="master")]
+ func.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden));
}
if tcx.sess.must_emit_unwind_tables() {
// TODO(antoyo): emit unwind tables.
@@ -61,7 +64,8 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut GccContext, _module_nam
.map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index)))
.collect();
let callee = context.new_function(None, FunctionType::Extern, output.unwrap_or(void), &args, callee, false);
- // TODO(antoyo): set visibility.
+ #[cfg(feature="master")]
+ callee.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden));
let block = func.new_block("entry");
@@ -90,12 +94,18 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut GccContext, _module_nam
.collect();
let func = context.new_function(None, FunctionType::Exported, void, &args, name, false);
+ if tcx.sess.target.default_hidden_visibility {
+ #[cfg(feature="master")]
+ func.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden));
+ }
+
let callee = alloc_error_handler_kind.fn_name(sym::oom);
let args: Vec<_> = types.iter().enumerate()
.map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index)))
.collect();
let callee = context.new_function(None, FunctionType::Extern, void, &args, callee, false);
- //llvm::LLVMRustSetVisibility(callee, llvm::Visibility::Hidden);
+ #[cfg(feature="master")]
+ callee.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden));
let block = func.new_block("entry");
diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs
index c346dbd63cca..41e9d61a10e5 100644
--- a/compiler/rustc_codegen_gcc/src/asm.rs
+++ b/compiler/rustc_codegen_gcc/src/asm.rs
@@ -157,7 +157,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
use ConstraintOrRegister::*;
let (constraint, ty) = match (reg_to_gcc(reg), place) {
- (Constraint(constraint), Some(place)) => (constraint, place.layout.gcc_type(self.cx, false)),
+ (Constraint(constraint), Some(place)) => (constraint, place.layout.gcc_type(self.cx)),
// When `reg` is a class and not an explicit register but the out place is not specified,
// we need to create an unused output variable to assign the output to. This var
// needs to be of a type that's "compatible" with the register class, but specific type
@@ -226,7 +226,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
// This decision is also backed by the fact that LLVM needs in and out
// values to be of *exactly the same type*, not just "compatible".
// I'm not sure if GCC is so picky too, but better safe than sorry.
- let ty = in_value.layout.gcc_type(self.cx, false);
+ let ty = in_value.layout.gcc_type(self.cx);
let tmp_var = self.current_func().new_local(None, ty, "output_register");
// If the out_place is None (i.e `inout(reg) _` syntax was used), we translate
@@ -286,7 +286,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
continue
};
- let ty = out_place.layout.gcc_type(self.cx, false);
+ let ty = out_place.layout.gcc_type(self.cx);
let tmp_var = self.current_func().new_local(None, ty, "output_register");
tmp_var.set_register_name(reg_name);
@@ -306,7 +306,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
// `in("explicit register") var`
InlineAsmOperandRef::In { reg, value } => {
if let ConstraintOrRegister::Register(reg_name) = reg_to_gcc(reg) {
- let ty = value.layout.gcc_type(self.cx, false);
+ let ty = value.layout.gcc_type(self.cx);
let reg_var = self.current_func().new_local(None, ty, "input_register");
reg_var.set_register_name(reg_name);
self.llbb().add_assignment(None, reg_var, value.immediate());
@@ -325,7 +325,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
InlineAsmOperandRef::InOut { reg, late, in_value, out_place } => {
if let ConstraintOrRegister::Register(reg_name) = reg_to_gcc(reg) {
// See explanation in the first pass.
- let ty = in_value.layout.gcc_type(self.cx, false);
+ let ty = in_value.layout.gcc_type(self.cx);
let tmp_var = self.current_func().new_local(None, ty, "output_register");
tmp_var.set_register_name(reg_name);
@@ -353,8 +353,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
inputs.push(AsmInOperand {
constraint: "X".into(),
rust_idx,
- val: self.cx.rvalue_as_function(get_fn(self.cx, instance))
- .get_address(None),
+ val: get_fn(self.cx, instance).get_address(None),
});
}
@@ -382,15 +381,19 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
for piece in template {
match *piece {
InlineAsmTemplatePiece::String(ref string) => {
- // TODO(@Commeownist): switch to `Iterator::intersperse` once it's stable
- let mut iter = string.split('%');
- if let Some(s) = iter.next() {
- template_str.push_str(s);
- }
-
- for s in iter {
- template_str.push_str("%%");
- template_str.push_str(s);
+ for char in string.chars() {
+ // TODO(antoyo): might also need to escape | if rustc doesn't do it.
+ let escaped_char =
+ match char {
+ '%' => "%%",
+ '{' => "%{",
+ '}' => "%}",
+ _ => {
+ template_str.push(char);
+ continue;
+ },
+ };
+ template_str.push_str(escaped_char);
}
}
InlineAsmTemplatePiece::Placeholder { operand_idx, modifier, span: _ } => {
@@ -565,39 +568,52 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister {
_ => unimplemented!(),
}
},
+ // They can be retrieved from https://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html
InlineAsmRegOrRegClass::RegClass(reg) => match reg {
- InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => unimplemented!(),
- InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::reg) => unimplemented!(),
- InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg) => unimplemented!(),
- InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => unimplemented!(),
- InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => unimplemented!(),
+ InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::reg) => "r",
+ InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg) => "w",
+ InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => "x",
+ InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => {
+ unreachable!("clobber-only")
+ }
+ InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => "r",
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg)
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low16)
- | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low8) => unimplemented!(),
- InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg_low16)
+ | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low8)
+ | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg_low16)
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low8)
- | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low4) => unimplemented!(),
- InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg)
- | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg) => unimplemented!(),
- InlineAsmRegClass::Avr(_) => unimplemented!(),
- InlineAsmRegClass::Bpf(_) => unimplemented!(),
- InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => unimplemented!(),
- InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => unimplemented!(),
- InlineAsmRegClass::Mips(MipsInlineAsmRegClass::freg) => unimplemented!(),
- InlineAsmRegClass::Msp430(_) => unimplemented!(),
- InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg16) => unimplemented!(),
- InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg32) => unimplemented!(),
- InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg64) => unimplemented!(),
- InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg) => unimplemented!(),
- InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => unimplemented!(),
- InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => unimplemented!(),
+ | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low4)
+ | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg)
+ | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg) => "t",
+ InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg) => "r",
+ InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_upper) => "d",
+ InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_pair) => "r",
+ InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_iw) => "w",
+ InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_ptr) => "e",
+ InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => "r",
+ InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => "w",
+ InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => "r",
+ InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => "d", // more specific than "r"
+ InlineAsmRegClass::Mips(MipsInlineAsmRegClass::freg) => "f",
+ InlineAsmRegClass::Msp430(Msp430InlineAsmRegClass::reg) => "r",
+ // https://github.com/gcc-mirror/gcc/blob/master/gcc/config/nvptx/nvptx.md -> look for
+ // "define_constraint".
+ InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg16) => "h",
+ InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg32) => "r",
+ InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg64) => "l",
+
+ InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg) => "r",
+ InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => "b",
+ InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => "f",
InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::cr)
| InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) => {
unreachable!("clobber-only")
},
- InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => unimplemented!(),
- InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => unimplemented!(),
- InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => unimplemented!(),
+ InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => "r",
+ InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => "f",
+ InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => {
+ unreachable!("clobber-only")
+ }
InlineAsmRegClass::X86(X86InlineAsmRegClass::reg) => "r",
InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd) => "Q",
InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_byte) => "q",
@@ -605,16 +621,18 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister {
| InlineAsmRegClass::X86(X86InlineAsmRegClass::ymm_reg) => "x",
InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => "v",
InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => "Yk",
- InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg0) => unimplemented!(),
- InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => unimplemented!(),
InlineAsmRegClass::X86(
- X86InlineAsmRegClass::x87_reg | X86InlineAsmRegClass::mmx_reg | X86InlineAsmRegClass::tmm_reg,
+ X86InlineAsmRegClass::kreg0
+ | X86InlineAsmRegClass::x87_reg
+ | X86InlineAsmRegClass::mmx_reg
+ | X86InlineAsmRegClass::tmm_reg,
) => unreachable!("clobber-only"),
InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
bug!("GCC backend does not support SPIR-V")
}
- InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg) => unimplemented!(),
- InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => unimplemented!(),
+ InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => "r",
+ InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg) => "r",
+ InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => "f",
InlineAsmRegClass::Err => unreachable!(),
}
};
@@ -692,21 +710,23 @@ impl<'gcc, 'tcx> AsmMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
&& options.contains(InlineAsmOptions::ATT_SYNTAX);
// Build the template string
- let mut template_str = String::new();
+ let mut template_str = ".pushsection .text\n".to_owned();
+ if att_dialect {
+ template_str.push_str(".att_syntax\n");
+ }
for piece in template {
match *piece {
InlineAsmTemplatePiece::String(ref string) => {
- for line in string.lines() {
+ let mut index = 0;
+ while index < string.len() {
// NOTE: gcc does not allow inline comment, so remove them.
- let line =
- if let Some(index) = line.rfind("//") {
- &line[..index]
- }
- else {
- line
- };
- template_str.push_str(line);
- template_str.push('\n');
+ let comment_index = string[index..].find("//")
+ .map(|comment_index| comment_index + index)
+ .unwrap_or(string.len());
+ template_str.push_str(&string[index..comment_index]);
+ index = string[comment_index..].find('\n')
+ .map(|index| index + comment_index)
+ .unwrap_or(string.len());
}
},
InlineAsmTemplatePiece::Placeholder { operand_idx, modifier: _, span: _ } => {
@@ -719,6 +739,8 @@ impl<'gcc, 'tcx> AsmMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
}
GlobalAsmOperandRef::SymFn { instance } => {
+ let function = get_fn(self, instance);
+ self.add_used_function(function);
// TODO(@Amanieu): Additional mangling is needed on
// some targets to add a leading underscore (Mach-O)
// or byte count suffixes (x86 Windows).
@@ -727,6 +749,7 @@ impl<'gcc, 'tcx> AsmMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
}
GlobalAsmOperandRef::SymStatic { def_id } => {
+ // TODO(antoyo): set the global variable as used.
// TODO(@Amanieu): Additional mangling is needed on
// some targets to add a leading underscore (Mach-O).
let instance = Instance::mono(self.tcx, def_id);
@@ -738,48 +761,51 @@ impl<'gcc, 'tcx> AsmMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
}
}
- let template_str =
- if att_dialect {
- format!(".att_syntax\n\t{}\n\t.intel_syntax noprefix", template_str)
- }
- else {
- template_str
- };
+ if att_dialect {
+ template_str.push_str("\n\t.intel_syntax noprefix");
+ }
// NOTE: seems like gcc will put the asm in the wrong section, so set it to .text manually.
- let template_str = format!(".pushsection .text\n{}\n.popsection", template_str);
+ template_str.push_str("\n.popsection");
self.context.add_top_level_asm(None, &template_str);
}
}
fn modifier_to_gcc(arch: InlineAsmArch, reg: InlineAsmRegClass, modifier: Option) -> Option {
+ // The modifiers can be retrieved from
+ // https://gcc.gnu.org/onlinedocs/gcc/Modifiers.html#Modifiers
match reg {
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::reg) => modifier,
- InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => modifier,
InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg)
| InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => {
- unimplemented!()
+ if modifier == Some('v') { None } else { modifier }
}
- InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => unimplemented!(),
+ InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => {
+ unreachable!("clobber-only")
+ }
+ InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => None,
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg)
- | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg_low16) => unimplemented!(),
+ | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg_low16) => None,
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg)
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low16)
- | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low8) => unimplemented!(),
+ | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low8) => Some('P'),
InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg)
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low8)
| InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low4) => {
- unimplemented!()
+ if modifier.is_none() {
+ Some('q')
+ } else {
+ modifier
+ }
}
- InlineAsmRegClass::Avr(_) => unimplemented!(),
- InlineAsmRegClass::Bpf(_) => unimplemented!(),
- InlineAsmRegClass::Hexagon(_) => unimplemented!(),
- InlineAsmRegClass::Mips(_) => unimplemented!(),
- InlineAsmRegClass::Msp430(_) => unimplemented!(),
- InlineAsmRegClass::Nvptx(_) => unimplemented!(),
- InlineAsmRegClass::PowerPC(_) => unimplemented!(),
+ InlineAsmRegClass::Hexagon(_) => None,
+ InlineAsmRegClass::Mips(_) => None,
+ InlineAsmRegClass::Nvptx(_) => None,
+ InlineAsmRegClass::PowerPC(_) => None,
InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg)
- | InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => unimplemented!(),
- InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => unimplemented!(),
+ | InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => None,
+ InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => {
+ unreachable!("clobber-only")
+ }
InlineAsmRegClass::X86(X86InlineAsmRegClass::reg)
| InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd) => match modifier {
None => if arch == InlineAsmArch::X86_64 { Some('q') } else { Some('k') },
@@ -803,16 +829,29 @@ fn modifier_to_gcc(arch: InlineAsmArch, reg: InlineAsmRegClass, modifier: Option
_ => unreachable!(),
},
InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => None,
- InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg0) => None,
- InlineAsmRegClass::X86(X86InlineAsmRegClass::x87_reg | X86InlineAsmRegClass::mmx_reg | X86InlineAsmRegClass::tmm_reg) => {
+ InlineAsmRegClass::X86(
+ X86InlineAsmRegClass::x87_reg
+ | X86InlineAsmRegClass::mmx_reg
+ | X86InlineAsmRegClass::kreg0
+ | X86InlineAsmRegClass::tmm_reg,
+ ) => {
unreachable!("clobber-only")
}
- InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => unimplemented!(),
+ InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => None,
+ InlineAsmRegClass::Bpf(_) => None,
+ InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_pair)
+ | InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_iw)
+ | InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_ptr) => match modifier {
+ Some('h') => Some('B'),
+ Some('l') => Some('A'),
+ _ => None,
+ },
+ InlineAsmRegClass::Avr(_) => None,
+ InlineAsmRegClass::S390x(_) => None,
+ InlineAsmRegClass::Msp430(_) => None,
InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
bug!("LLVM backend does not support SPIR-V")
- },
- InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg) => unimplemented!(),
- InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => unimplemented!(),
+ }
InlineAsmRegClass::Err => unreachable!(),
}
}
diff --git a/compiler/rustc_codegen_gcc/src/attributes.rs b/compiler/rustc_codegen_gcc/src/attributes.rs
new file mode 100644
index 000000000000..db841b1b5240
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/src/attributes.rs
@@ -0,0 +1,113 @@
+#[cfg(feature="master")]
+use gccjit::FnAttribute;
+use gccjit::Function;
+use rustc_attr::InstructionSetAttr;
+use rustc_codegen_ssa::target_features::tied_target_features;
+use rustc_data_structures::fx::FxHashMap;
+use rustc_middle::ty;
+use rustc_session::Session;
+use rustc_span::symbol::sym;
+use smallvec::{smallvec, SmallVec};
+
+use crate::{context::CodegenCx, errors::TiedTargetFeatures};
+
+// Given a map from target_features to whether they are enabled or disabled,
+// ensure only valid combinations are allowed.
+pub fn check_tied_features(sess: &Session, features: &FxHashMap<&str, bool>) -> Option<&'static [&'static str]> {
+ for tied in tied_target_features(sess) {
+ // Tied features must be set to the same value, or not set at all
+ let mut tied_iter = tied.iter();
+ let enabled = features.get(tied_iter.next().unwrap());
+ if tied_iter.any(|feature| enabled != features.get(feature)) {
+ return Some(tied);
+ }
+ }
+ None
+}
+
+// TODO(antoyo): maybe move to a new module gcc_util.
+// To find a list of GCC's names, check https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
+fn to_gcc_features<'a>(sess: &Session, s: &'a str) -> SmallVec<[&'a str; 2]> {
+ let arch = if sess.target.arch == "x86_64" { "x86" } else { &*sess.target.arch };
+ match (arch, s) {
+ ("x86", "sse4.2") => smallvec!["sse4.2", "crc32"],
+ ("x86", "pclmulqdq") => smallvec!["pclmul"],
+ ("x86", "rdrand") => smallvec!["rdrnd"],
+ ("x86", "bmi1") => smallvec!["bmi"],
+ ("x86", "cmpxchg16b") => smallvec!["cx16"],
+ ("x86", "avx512vaes") => smallvec!["vaes"],
+ ("x86", "avx512gfni") => smallvec!["gfni"],
+ ("x86", "avx512vpclmulqdq") => smallvec!["vpclmulqdq"],
+ // NOTE: seems like GCC requires 'avx512bw' for 'avx512vbmi2'.
+ ("x86", "avx512vbmi2") => smallvec!["avx512vbmi2", "avx512bw"],
+ // NOTE: seems like GCC requires 'avx512bw' for 'avx512bitalg'.
+ ("x86", "avx512bitalg") => smallvec!["avx512bitalg", "avx512bw"],
+ ("aarch64", "rcpc2") => smallvec!["rcpc-immo"],
+ ("aarch64", "dpb") => smallvec!["ccpp"],
+ ("aarch64", "dpb2") => smallvec!["ccdp"],
+ ("aarch64", "frintts") => smallvec!["fptoint"],
+ ("aarch64", "fcma") => smallvec!["complxnum"],
+ ("aarch64", "pmuv3") => smallvec!["perfmon"],
+ ("aarch64", "paca") => smallvec!["pauth"],
+ ("aarch64", "pacg") => smallvec!["pauth"],
+ // Rust ties fp and neon together. In LLVM neon implicitly enables fp,
+ // but we manually enable neon when a feature only implicitly enables fp
+ ("aarch64", "f32mm") => smallvec!["f32mm", "neon"],
+ ("aarch64", "f64mm") => smallvec!["f64mm", "neon"],
+ ("aarch64", "fhm") => smallvec!["fp16fml", "neon"],
+ ("aarch64", "fp16") => smallvec!["fullfp16", "neon"],
+ ("aarch64", "jsconv") => smallvec!["jsconv", "neon"],
+ ("aarch64", "sve") => smallvec!["sve", "neon"],
+ ("aarch64", "sve2") => smallvec!["sve2", "neon"],
+ ("aarch64", "sve2-aes") => smallvec!["sve2-aes", "neon"],
+ ("aarch64", "sve2-sm4") => smallvec!["sve2-sm4", "neon"],
+ ("aarch64", "sve2-sha3") => smallvec!["sve2-sha3", "neon"],
+ ("aarch64", "sve2-bitperm") => smallvec!["sve2-bitperm", "neon"],
+ (_, s) => smallvec![s],
+ }
+}
+
+/// Composite function which sets GCC attributes for function depending on its AST (`#[attribute]`)
+/// attributes.
+pub fn from_fn_attrs<'gcc, 'tcx>(
+ cx: &CodegenCx<'gcc, 'tcx>,
+ #[cfg_attr(not(feature="master"), allow(unused_variables))]
+ func: Function<'gcc>,
+ instance: ty::Instance<'tcx>,
+) {
+ let codegen_fn_attrs = cx.tcx.codegen_fn_attrs(instance.def_id());
+
+ let function_features =
+ codegen_fn_attrs.target_features.iter().map(|features| features.as_str()).collect::>();
+
+ if let Some(features) = check_tied_features(cx.tcx.sess, &function_features.iter().map(|features| (*features, true)).collect()) {
+ let span = cx.tcx
+ .get_attr(instance.def_id(), sym::target_feature)
+ .map_or_else(|| cx.tcx.def_span(instance.def_id()), |a| a.span);
+ cx.tcx.sess.create_err(TiedTargetFeatures {
+ features: features.join(", "),
+ span,
+ })
+ .emit();
+ return;
+ }
+
+ let mut function_features = function_features
+ .iter()
+ .flat_map(|feat| to_gcc_features(cx.tcx.sess, feat).into_iter())
+ .chain(codegen_fn_attrs.instruction_set.iter().map(|x| match x {
+ InstructionSetAttr::ArmA32 => "-thumb-mode", // TODO(antoyo): support removing feature.
+ InstructionSetAttr::ArmT32 => "thumb-mode",
+ }))
+ .collect::>();
+
+ // TODO(antoyo): check if we really need global backend features. (Maybe they could be applied
+ // globally?)
+ let mut global_features = cx.tcx.global_backend_features(()).iter().map(|s| s.as_str());
+ function_features.extend(&mut global_features);
+ let target_features = function_features.join(",");
+ if !target_features.is_empty() {
+ #[cfg(feature="master")]
+ func.add_attribute(FnAttribute::Target(&target_features));
+ }
+}
diff --git a/compiler/rustc_codegen_gcc/src/back/write.rs b/compiler/rustc_codegen_gcc/src/back/write.rs
index efcf18d31eb0..5f54ac4ebc69 100644
--- a/compiler/rustc_codegen_gcc/src/back/write.rs
+++ b/compiler/rustc_codegen_gcc/src/back/write.rs
@@ -57,6 +57,7 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext, _diag_han
if env::var("CG_GCCJIT_DUMP_TO_FILE").as_deref() == Ok("1") {
let _ = fs::create_dir("/tmp/gccjit_dumps");
let path = &format!("/tmp/gccjit_dumps/{}.c", module.name);
+ context.set_debug_info(true);
context.dump_to_file(path, true);
}
context.compile_to_file(OutputKind::ObjectFile, obj_out.to_str().expect("path to str"));
diff --git a/compiler/rustc_codegen_gcc/src/base.rs b/compiler/rustc_codegen_gcc/src/base.rs
index d464bd3d12a0..dcd560b3dcd9 100644
--- a/compiler/rustc_codegen_gcc/src/base.rs
+++ b/compiler/rustc_codegen_gcc/src/base.rs
@@ -8,6 +8,8 @@ use gccjit::{
};
use rustc_middle::dep_graph;
use rustc_middle::ty::TyCtxt;
+#[cfg(feature="master")]
+use rustc_middle::mir::mono::Visibility;
use rustc_middle::mir::mono::Linkage;
use rustc_codegen_ssa::{ModuleCodegen, ModuleKind};
use rustc_codegen_ssa::base::maybe_create_entry_wrapper;
@@ -20,6 +22,15 @@ use crate::GccContext;
use crate::builder::Builder;
use crate::context::CodegenCx;
+#[cfg(feature="master")]
+pub fn visibility_to_gcc(linkage: Visibility) -> gccjit::Visibility {
+ match linkage {
+ Visibility::Default => gccjit::Visibility::Default,
+ Visibility::Hidden => gccjit::Visibility::Hidden,
+ Visibility::Protected => gccjit::Visibility::Protected,
+ }
+}
+
pub fn global_linkage_to_gcc(linkage: Linkage) -> GlobalKind {
match linkage {
Linkage::External => GlobalKind::Imported,
@@ -76,16 +87,34 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, supports_128bit_i
// Instantiate monomorphizations without filling out definitions yet...
//let llvm_module = ModuleLlvm::new(tcx, &cgu_name.as_str());
let context = Context::default();
+
+ context.add_command_line_option("-fexceptions");
+ context.add_driver_option("-fexceptions");
+
// TODO(antoyo): only set on x86 platforms.
context.add_command_line_option("-masm=intel");
// TODO(antoyo): only add the following cli argument if the feature is supported.
context.add_command_line_option("-msse2");
context.add_command_line_option("-mavx2");
- context.add_command_line_option("-msha");
- context.add_command_line_option("-mpclmul");
// FIXME(antoyo): the following causes an illegal instruction on vmovdqu64 in std_example on my CPU.
// Only add if the CPU supports it.
- //context.add_command_line_option("-mavx512f");
+ context.add_command_line_option("-msha");
+ context.add_command_line_option("-mpclmul");
+ context.add_command_line_option("-mfma");
+ context.add_command_line_option("-mfma4");
+ context.add_command_line_option("-m64");
+ context.add_command_line_option("-mbmi");
+ context.add_command_line_option("-mgfni");
+ //context.add_command_line_option("-mavxvnni"); // The CI doesn't support this option.
+ context.add_command_line_option("-mf16c");
+ context.add_command_line_option("-maes");
+ context.add_command_line_option("-mxsavec");
+ context.add_command_line_option("-mbmi2");
+ context.add_command_line_option("-mrtm");
+ context.add_command_line_option("-mvaes");
+ context.add_command_line_option("-mvpclmulqdq");
+ context.add_command_line_option("-mavx");
+
for arg in &tcx.sess.opts.cg.llvm_args {
context.add_command_line_option(arg);
}
@@ -95,12 +124,20 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, supports_128bit_i
context.add_command_line_option("-fno-semantic-interposition");
// NOTE: Rust relies on LLVM not doing TBAA (https://github.com/rust-lang/unsafe-code-guidelines/issues/292).
context.add_command_line_option("-fno-strict-aliasing");
+ // NOTE: Rust relies on LLVM doing wrapping on overflow.
+ context.add_command_line_option("-fwrapv");
if tcx.sess.opts.unstable_opts.function_sections.unwrap_or(tcx.sess.target.function_sections) {
context.add_command_line_option("-ffunction-sections");
context.add_command_line_option("-fdata-sections");
}
+ if env::var("CG_GCCJIT_DUMP_RTL").as_deref() == Ok("1") {
+ context.add_command_line_option("-fdump-rtl-vregs");
+ }
+ if env::var("CG_GCCJIT_DUMP_TREE_ALL").as_deref() == Ok("1") {
+ context.add_command_line_option("-fdump-tree-all");
+ }
if env::var("CG_GCCJIT_DUMP_CODE").as_deref() == Ok("1") {
context.set_dump_code_on_compile(true);
}
@@ -115,7 +152,7 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, supports_128bit_i
context.set_keep_intermediates(true);
}
- // TODO(bjorn3): Remove once unwinding is properly implemented
+ // NOTE: The codegen generates unrechable blocks.
context.set_allow_unreachable_blocks(true);
{
diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs
index e88c12716ecd..a3c8142bea2d 100644
--- a/compiler/rustc_codegen_gcc/src/builder.rs
+++ b/compiler/rustc_codegen_gcc/src/builder.rs
@@ -217,7 +217,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
let actual_ty = actual_val.get_type();
if expected_ty != actual_ty {
- if !actual_ty.is_vector() && !expected_ty.is_vector() && actual_ty.is_integral() && expected_ty.is_integral() && actual_ty.get_size() != expected_ty.get_size() {
+ if !actual_ty.is_vector() && !expected_ty.is_vector() && (actual_ty.is_integral() && expected_ty.is_integral()) || (actual_ty.get_pointee().is_some() && expected_ty.get_pointee().is_some()) {
self.context.new_cast(None, actual_val, expected_ty)
}
else if on_stack_param_indices.contains(&index) {
@@ -226,6 +226,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
else {
assert!(!((actual_ty.is_vector() && !expected_ty.is_vector()) || (!actual_ty.is_vector() && expected_ty.is_vector())), "{:?} ({}) -> {:?} ({}), index: {:?}[{}]", actual_ty, actual_ty.is_vector(), expected_ty, expected_ty.is_vector(), func_ptr, index);
// TODO(antoyo): perhaps use __builtin_convertvector for vector casting.
+ // TODO: remove bitcast now that vector types can be compared?
self.bitcast(actual_val, expected_ty)
}
}
@@ -279,21 +280,30 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
}
fn function_ptr_call(&mut self, func_ptr: RValue<'gcc>, args: &[RValue<'gcc>], _funclet: Option<&Funclet>) -> RValue<'gcc> {
- let args = self.check_ptr_call("call", func_ptr, args);
+ let gcc_func = func_ptr.get_type().dyncast_function_ptr_type().expect("function ptr");
+ let func_name = format!("{:?}", func_ptr);
+ let previous_arg_count = args.len();
+ let orig_args = args;
+ let args = {
+ let function_address_names = self.function_address_names.borrow();
+ let original_function_name = function_address_names.get(&func_ptr);
+ llvm::adjust_intrinsic_arguments(&self, gcc_func, args.into(), &func_name, original_function_name)
+ };
+ let args_adjusted = args.len() != previous_arg_count;
+ let args = self.check_ptr_call("call", func_ptr, &*args);
// gccjit requires to use the result of functions, even when it's not used.
// That's why we assign the result to a local or call add_eval().
- let gcc_func = func_ptr.get_type().dyncast_function_ptr_type().expect("function ptr");
let return_type = gcc_func.get_return_type();
let void_type = self.context.new_type::<()>();
let current_func = self.block.get_function();
if return_type != void_type {
unsafe { RETURN_VALUE_COUNT += 1 };
- let result = current_func.new_local(None, return_type, &format!("ptrReturnValue{}", unsafe { RETURN_VALUE_COUNT }));
- let func_name = format!("{:?}", func_ptr);
- let args = llvm::adjust_intrinsic_arguments(&self, gcc_func, args, &func_name);
- self.block.add_assignment(None, result, self.cx.context.new_call_through_ptr(None, func_ptr, &args));
+ let return_value = self.cx.context.new_call_through_ptr(None, func_ptr, &args);
+ let return_value = llvm::adjust_intrinsic_return_value(&self, return_value, &func_name, &args, args_adjusted, orig_args);
+ let result = current_func.new_local(None, return_value.get_type(), &format!("ptrReturnValue{}", unsafe { RETURN_VALUE_COUNT }));
+ self.block.add_assignment(None, result, return_value);
result.to_rvalue()
}
else {
@@ -366,10 +376,10 @@ impl<'tcx> FnAbiOfHelpers<'tcx> for Builder<'_, '_, 'tcx> {
}
}
-impl<'gcc, 'tcx> Deref for Builder<'_, 'gcc, 'tcx> {
+impl<'a, 'gcc, 'tcx> Deref for Builder<'a, 'gcc, 'tcx> {
type Target = CodegenCx<'gcc, 'tcx>;
- fn deref(&self) -> &Self::Target {
+ fn deref<'b>(&'b self) -> &'a Self::Target {
self.cx
}
}
@@ -387,7 +397,7 @@ impl<'gcc, 'tcx> BackendTypes for Builder<'_, 'gcc, 'tcx> {
}
impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
- fn build(cx: &'a CodegenCx<'gcc, 'tcx>, block: Block<'gcc>) -> Self {
+ fn build(cx: &'a CodegenCx<'gcc, 'tcx>, block: Block<'gcc>) -> Builder<'a, 'gcc, 'tcx> {
Builder::with_cx(cx, block)
}
@@ -444,17 +454,36 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
self.block.end_with_switch(None, value, default_block, &gcc_cases);
}
- fn invoke(
- &mut self,
- typ: Type<'gcc>,
- fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>,
- func: RValue<'gcc>,
- args: &[RValue<'gcc>],
- then: Block<'gcc>,
- catch: Block<'gcc>,
- _funclet: Option<&Funclet>,
- ) -> RValue<'gcc> {
- // TODO(bjorn3): Properly implement unwinding.
+ #[cfg(feature="master")]
+ fn invoke(&mut self, typ: Type<'gcc>, _fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, func: RValue<'gcc>, args: &[RValue<'gcc>], then: Block<'gcc>, catch: Block<'gcc>, _funclet: Option<&Funclet>) -> RValue<'gcc> {
+ let try_block = self.current_func().new_block("try");
+
+ let current_block = self.block.clone();
+ self.block = try_block;
+ let call = self.call(typ, None, func, args, None); // TODO(antoyo): use funclet here?
+ self.block = current_block;
+
+ let return_value = self.current_func()
+ .new_local(None, call.get_type(), "invokeResult");
+
+ try_block.add_assignment(None, return_value, call);
+
+ try_block.end_with_jump(None, then);
+
+ if self.cleanup_blocks.borrow().contains(&catch) {
+ self.block.add_try_finally(None, try_block, catch);
+ }
+ else {
+ self.block.add_try_catch(None, try_block, catch);
+ }
+
+ self.block.end_with_jump(None, then);
+
+ return_value.to_rvalue()
+ }
+
+ #[cfg(not(feature="master"))]
+ fn invoke(&mut self, typ: Type<'gcc>, fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, func: RValue<'gcc>, args: &[RValue<'gcc>], then: Block<'gcc>, catch: Block<'gcc>, _funclet: Option<&Funclet>) -> RValue<'gcc> {
let call_site = self.call(typ, None, func, args, None);
let condition = self.context.new_rvalue_from_int(self.bool_type, 1);
self.llbb().end_with_conditional(None, condition, then, catch);
@@ -542,6 +571,31 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
}
fn frem(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
+ // TODO(antoyo): add check in libgccjit since using the binary operator % causes the following error:
+ // during RTL pass: expand
+ // libgccjit.so: error: in expmed_mode_index, at expmed.h:240
+ // 0x7f0101d58dc6 expmed_mode_index
+ // ../../../gcc/gcc/expmed.h:240
+ // 0x7f0101d58e35 expmed_op_cost_ptr
+ // ../../../gcc/gcc/expmed.h:262
+ // 0x7f0101d594a1 sdiv_cost_ptr
+ // ../../../gcc/gcc/expmed.h:531
+ // 0x7f0101d594f3 sdiv_cost
+ // ../../../gcc/gcc/expmed.h:549
+ // 0x7f0101d6af7e expand_divmod(int, tree_code, machine_mode, rtx_def*, rtx_def*, rtx_def*, int, optab_methods)
+ // ../../../gcc/gcc/expmed.cc:4356
+ // 0x7f0101d94f9e expand_expr_divmod
+ // ../../../gcc/gcc/expr.cc:8929
+ // 0x7f0101d97a26 expand_expr_real_2(separate_ops*, rtx_def*, machine_mode, expand_modifier)
+ // ../../../gcc/gcc/expr.cc:9566
+ // 0x7f0101bef6ef expand_gimple_stmt_1
+ // ../../../gcc/gcc/cfgexpand.cc:3967
+ // 0x7f0101bef910 expand_gimple_stmt
+ // ../../../gcc/gcc/cfgexpand.cc:4028
+ // 0x7f0101bf6ee7 expand_gimple_basic_block
+ // ../../../gcc/gcc/cfgexpand.cc:6069
+ // 0x7f0101bf9194 execute
+ // ../../../gcc/gcc/cfgexpand.cc:6795
if a.get_type().is_compatible_with(self.cx.float_type) {
let fmodf = self.context.get_builtin_function("fmodf");
// FIXME(antoyo): this seems to produce the wrong result.
@@ -616,24 +670,29 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
a * b
}
- fn fadd_fast(&mut self, _lhs: RValue<'gcc>, _rhs: RValue<'gcc>) -> RValue<'gcc> {
- unimplemented!();
+ fn fadd_fast(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
+ // NOTE: it seems like we cannot enable fast-mode for a single operation in GCC.
+ lhs + rhs
}
- fn fsub_fast(&mut self, _lhs: RValue<'gcc>, _rhs: RValue<'gcc>) -> RValue<'gcc> {
- unimplemented!();
+ fn fsub_fast(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
+ // NOTE: it seems like we cannot enable fast-mode for a single operation in GCC.
+ lhs - rhs
}
- fn fmul_fast(&mut self, _lhs: RValue<'gcc>, _rhs: RValue<'gcc>) -> RValue<'gcc> {
- unimplemented!();
+ fn fmul_fast(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
+ // NOTE: it seems like we cannot enable fast-mode for a single operation in GCC.
+ lhs * rhs
}
- fn fdiv_fast(&mut self, _lhs: RValue<'gcc>, _rhs: RValue<'gcc>) -> RValue<'gcc> {
- unimplemented!();
+ fn fdiv_fast(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
+ // NOTE: it seems like we cannot enable fast-mode for a single operation in GCC.
+ lhs / rhs
}
- fn frem_fast(&mut self, _lhs: RValue<'gcc>, _rhs: RValue<'gcc>) -> RValue<'gcc> {
- unimplemented!();
+ fn frem_fast(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
+ // NOTE: it seems like we cannot enable fast-mode for a single operation in GCC.
+ self.frem(lhs, rhs)
}
fn checked_binop(&mut self, oop: OverflowOp, typ: Ty<'_>, lhs: Self::Value, rhs: Self::Value) -> (Self::Value, Self::Value) {
@@ -722,7 +781,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
}
else if place.layout.is_gcc_immediate() {
let load = self.load(
- place.layout.gcc_type(self, false),
+ place.layout.gcc_type(self),
place.llval,
place.align,
);
@@ -733,7 +792,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
}
else if let abi::Abi::ScalarPair(ref a, ref b) = place.layout.abi {
let b_offset = a.size(self).align_to(b.align(self).abi);
- let pair_type = place.layout.gcc_type(self, false);
+ let pair_type = place.layout.gcc_type(self);
let mut load = |i, scalar: &abi::Scalar, align| {
let llptr = self.struct_gep(pair_type, place.llval, i as u64);
@@ -833,26 +892,31 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
}
fn gep(&mut self, _typ: Type<'gcc>, ptr: RValue<'gcc>, indices: &[RValue<'gcc>]) -> RValue<'gcc> {
- let mut result = ptr;
+ let ptr_type = ptr.get_type();
+ let mut pointee_type = ptr.get_type();
+ // NOTE: we cannot use array indexing here like in inbounds_gep because array indexing is
+ // always considered in bounds in GCC (TODO(antoyo): to be verified).
+ // So, we have to cast to a number.
+ let mut result = self.context.new_bitcast(None, ptr, self.sizet_type);
+ // FIXME(antoyo): if there were more than 1 index, this code is probably wrong and would
+ // require dereferencing the pointer.
for index in indices {
- result = self.context.new_array_access(None, result, *index).get_address(None).to_rvalue();
+ pointee_type = pointee_type.get_pointee().expect("pointee type");
+ let pointee_size = self.context.new_rvalue_from_int(index.get_type(), pointee_type.get_size() as i32);
+ result = result + self.gcc_int_cast(*index * pointee_size, self.sizet_type);
}
- result
+ self.context.new_bitcast(None, result, ptr_type)
}
fn inbounds_gep(&mut self, _typ: Type<'gcc>, ptr: RValue<'gcc>, indices: &[RValue<'gcc>]) -> RValue<'gcc> {
- // FIXME(antoyo): would be safer if doing the same thing (loop) as gep.
- // TODO(antoyo): specify inbounds somehow.
- match indices.len() {
- 1 => {
- self.context.new_array_access(None, ptr, indices[0]).get_address(None)
- },
- 2 => {
- let array = ptr.dereference(None); // TODO(antoyo): assert that first index is 0?
- self.context.new_array_access(None, array, indices[1]).get_address(None)
- },
- _ => unimplemented!(),
+ // NOTE: array indexing is always considered in bounds in GCC (TODO(antoyo): to be verified).
+ let mut indices = indices.into_iter();
+ let index = indices.next().expect("first index in inbounds_gep");
+ let mut result = self.context.new_array_access(None, ptr, *index);
+ for index in indices {
+ result = self.context.new_array_access(None, result, *index);
}
+ result.get_address(None)
}
fn struct_gep(&mut self, value_type: Type<'gcc>, ptr: RValue<'gcc>, idx: u64) -> RValue<'gcc> {
@@ -1034,8 +1098,19 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
unimplemented!();
}
- fn extract_element(&mut self, _vec: RValue<'gcc>, _idx: RValue<'gcc>) -> RValue<'gcc> {
- unimplemented!();
+ #[cfg(feature="master")]
+ fn extract_element(&mut self, vec: RValue<'gcc>, idx: RValue<'gcc>) -> RValue<'gcc> {
+ self.context.new_vector_access(None, vec, idx).to_rvalue()
+ }
+
+ #[cfg(not(feature="master"))]
+ fn extract_element(&mut self, vec: RValue<'gcc>, idx: RValue<'gcc>) -> RValue<'gcc> {
+ let vector_type = vec.get_type().unqualified().dyncast_vector().expect("Called extract_element on a non-vector type");
+ let element_type = vector_type.get_element_type();
+ let vec_num_units = vector_type.get_num_units();
+ let array_type = self.context.new_array_type(None, element_type, vec_num_units as u64);
+ let array = self.context.new_bitcast(None, vec, array_type).to_rvalue();
+ self.context.new_array_access(None, array, idx).to_rvalue()
}
fn vector_splat(&mut self, _num_elts: usize, _elt: RValue<'gcc>) -> RValue<'gcc> {
@@ -1116,22 +1191,52 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
}
fn set_personality_fn(&mut self, _personality: RValue<'gcc>) {
- // TODO(antoyo)
+ #[cfg(feature="master")]
+ {
+ let personality = self.rvalue_as_function(_personality);
+ self.current_func().set_personality_function(personality);
+ }
}
+ #[cfg(feature="master")]
+ fn cleanup_landing_pad(&mut self, pers_fn: RValue<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) {
+ self.set_personality_fn(pers_fn);
+
+ // NOTE: insert the current block in a variable so that a later call to invoke knows to
+ // generate a try/finally instead of a try/catch for this block.
+ self.cleanup_blocks.borrow_mut().insert(self.block);
+
+ let eh_pointer_builtin = self.cx.context.get_target_builtin_function("__builtin_eh_pointer");
+ let zero = self.cx.context.new_rvalue_zero(self.int_type);
+ let ptr = self.cx.context.new_call(None, eh_pointer_builtin, &[zero]);
+
+ let value1_type = self.u8_type.make_pointer();
+ let ptr = self.cx.context.new_cast(None, ptr, value1_type);
+ let value1 = ptr;
+ let value2 = zero; // TODO(antoyo): set the proper value here (the type of exception?).
+
+ (value1, value2)
+ }
+
+ #[cfg(not(feature="master"))]
fn cleanup_landing_pad(&mut self, _pers_fn: RValue<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) {
- (
- self.current_func().new_local(None, self.u8_type.make_pointer(), "landing_pad0")
- .to_rvalue(),
- self.current_func().new_local(None, self.i32_type, "landing_pad1").to_rvalue(),
- )
- // TODO(antoyo): Properly implement unwinding.
- // the above is just to make the compilation work as it seems
- // rustc_codegen_ssa now calls the unwinding builder methods even on panic=abort.
+ let value1 = self.current_func().new_local(None, self.u8_type.make_pointer(), "landing_pad0")
+ .to_rvalue();
+ let value2 = self.current_func().new_local(None, self.i32_type, "landing_pad1").to_rvalue();
+ (value1, value2)
}
+ #[cfg(feature="master")]
+ fn resume(&mut self, exn0: RValue<'gcc>, _exn1: RValue<'gcc>) {
+ let exn_type = exn0.get_type();
+ let exn = self.context.new_cast(None, exn0, exn_type);
+ let unwind_resume = self.context.get_target_builtin_function("__builtin_unwind_resume");
+ self.llbb().add_eval(None, self.context.new_call(None, unwind_resume, &[exn]));
+ self.unreachable();
+ }
+
+ #[cfg(not(feature="master"))]
fn resume(&mut self, _exn0: RValue<'gcc>, _exn1: RValue<'gcc>) {
- // TODO(bjorn3): Properly implement unwinding.
self.unreachable();
}
@@ -1160,6 +1265,15 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
fn atomic_cmpxchg(&mut self, dst: RValue<'gcc>, cmp: RValue<'gcc>, src: RValue<'gcc>, order: AtomicOrdering, failure_order: AtomicOrdering, weak: bool) -> RValue<'gcc> {
let expected = self.current_func().new_local(None, cmp.get_type(), "expected");
self.llbb().add_assignment(None, expected, cmp);
+ // NOTE: gcc doesn't support a failure memory model that is stronger than the success
+ // memory model.
+ let order =
+ if failure_order as i32 > order as i32 {
+ failure_order
+ }
+ else {
+ order
+ };
let success = self.compare_exchange(dst, expected, src, order, failure_order, weak);
let pair_type = self.cx.type_struct(&[src.get_type(), self.bool_type], false);
@@ -1469,7 +1583,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
#[cfg(feature="master")]
pub fn shuffle_vector(&mut self, v1: RValue<'gcc>, v2: RValue<'gcc>, mask: RValue<'gcc>) -> RValue<'gcc> {
- let struct_type = mask.get_type().is_struct().expect("mask of struct type");
+ let struct_type = mask.get_type().is_struct().expect("mask should be of struct type");
// TODO(antoyo): use a recursive unqualified() here.
let vector_type = v1.get_type().unqualified().dyncast_vector().expect("vector type");
@@ -1501,22 +1615,17 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
vector_elements.push(self.context.new_rvalue_zero(mask_element_type));
}
- let array_type = self.context.new_array_type(None, element_type, vec_num_units as i32);
let result_type = self.context.new_vector_type(element_type, mask_num_units as u64);
let (v1, v2) =
if vec_num_units < mask_num_units {
// NOTE: the mask needs to be the same length as the input vectors, so join the 2
// vectors and create a dummy second vector.
- // TODO(antoyo): switch to using new_vector_access.
- let array = self.context.new_bitcast(None, v1, array_type);
let mut elements = vec![];
for i in 0..vec_num_units {
- elements.push(self.context.new_array_access(None, array, self.context.new_rvalue_from_int(self.int_type, i as i32)).to_rvalue());
+ elements.push(self.context.new_vector_access(None, v1, self.context.new_rvalue_from_int(self.int_type, i as i32)).to_rvalue());
}
- // TODO(antoyo): switch to using new_vector_access.
- let array = self.context.new_bitcast(None, v2, array_type);
for i in 0..(mask_num_units - vec_num_units) {
- elements.push(self.context.new_array_access(None, array, self.context.new_rvalue_from_int(self.int_type, i as i32)).to_rvalue());
+ elements.push(self.context.new_vector_access(None, v2, self.context.new_rvalue_from_int(self.int_type, i as i32)).to_rvalue());
}
let v1 = self.context.new_rvalue_from_vector(None, result_type, &elements);
let zero = self.context.new_rvalue_zero(element_type);
@@ -1536,10 +1645,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
// NOTE: if padding was added, only select the number of elements of the masks to
// remove that padding in the result.
let mut elements = vec![];
- // TODO(antoyo): switch to using new_vector_access.
- let array = self.context.new_bitcast(None, result, array_type);
for i in 0..mask_num_units {
- elements.push(self.context.new_array_access(None, array, self.context.new_rvalue_from_int(self.int_type, i as i32)).to_rvalue());
+ elements.push(self.context.new_vector_access(None, result, self.context.new_rvalue_from_int(self.int_type, i as i32)).to_rvalue());
}
self.context.new_rvalue_from_vector(None, result_type, &elements)
}
@@ -1558,18 +1665,20 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
where F: Fn(RValue<'gcc>, RValue<'gcc>, &'gcc Context<'gcc>) -> RValue<'gcc>
{
let vector_type = src.get_type().unqualified().dyncast_vector().expect("vector type");
+ let element_type = vector_type.get_element_type();
+ let mask_element_type = self.type_ix(element_type.get_size() as u64 * 8);
let element_count = vector_type.get_num_units();
let mut vector_elements = vec![];
for i in 0..element_count {
vector_elements.push(i);
}
- let mask_type = self.context.new_vector_type(self.int_type, element_count as u64);
+ let mask_type = self.context.new_vector_type(mask_element_type, element_count as u64);
let mut shift = 1;
let mut res = src;
while shift < element_count {
let vector_elements: Vec<_> =
vector_elements.iter()
- .map(|i| self.context.new_rvalue_from_int(self.int_type, ((i + shift) % element_count) as i32))
+ .map(|i| self.context.new_rvalue_from_int(mask_element_type, ((i + shift) % element_count) as i32))
.collect();
let mask = self.context.new_rvalue_from_vector(None, mask_type, &vector_elements);
let shifted = self.context.new_rvalue_vector_perm(None, res, res, mask);
@@ -1581,7 +1690,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
}
#[cfg(not(feature="master"))]
- pub fn vector_reduce(&mut self, src: RValue<'gcc>, op: F) -> RValue<'gcc>
+ pub fn vector_reduce(&mut self, _src: RValue<'gcc>, _op: F) -> RValue<'gcc>
where F: Fn(RValue<'gcc>, RValue<'gcc>, &'gcc Context<'gcc>) -> RValue<'gcc>
{
unimplemented!();
@@ -1595,15 +1704,47 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
unimplemented!();
}
+ #[cfg(feature="master")]
+ pub fn vector_reduce_fadd(&mut self, acc: RValue<'gcc>, src: RValue<'gcc>) -> RValue<'gcc> {
+ let vector_type = src.get_type().unqualified().dyncast_vector().expect("vector type");
+ let element_count = vector_type.get_num_units();
+ (0..element_count).into_iter()
+ .map(|i| self.context
+ .new_vector_access(None, src, self.context.new_rvalue_from_int(self.int_type, i as _))
+ .to_rvalue())
+ .fold(acc, |x, i| x + i)
+ }
+
+ #[cfg(not(feature="master"))]
+ pub fn vector_reduce_fadd(&mut self, _acc: RValue<'gcc>, _src: RValue<'gcc>) -> RValue<'gcc> {
+ unimplemented!();
+ }
+
pub fn vector_reduce_fmul_fast(&mut self, _acc: RValue<'gcc>, _src: RValue<'gcc>) -> RValue<'gcc> {
unimplemented!();
}
+ #[cfg(feature="master")]
+ pub fn vector_reduce_fmul(&mut self, acc: RValue<'gcc>, src: RValue<'gcc>) -> RValue<'gcc> {
+ let vector_type = src.get_type().unqualified().dyncast_vector().expect("vector type");
+ let element_count = vector_type.get_num_units();
+ (0..element_count).into_iter()
+ .map(|i| self.context
+ .new_vector_access(None, src, self.context.new_rvalue_from_int(self.int_type, i as _))
+ .to_rvalue())
+ .fold(acc, |x, i| x * i)
+ }
+
+ #[cfg(not(feature="master"))]
+ pub fn vector_reduce_fmul(&mut self, _acc: RValue<'gcc>, _src: RValue<'gcc>) -> RValue<'gcc> {
+ unimplemented!()
+ }
+
// Inspired by Hacker's Delight min implementation.
pub fn vector_reduce_min(&mut self, src: RValue<'gcc>) -> RValue<'gcc> {
self.vector_reduce(src, |a, b, context| {
let differences_or_zeros = difference_or_zero(a, b, context);
- context.new_binary_op(None, BinaryOp::Minus, a.get_type(), a, differences_or_zeros)
+ context.new_binary_op(None, BinaryOp::Plus, b.get_type(), b, differences_or_zeros)
})
}
@@ -1611,38 +1752,148 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
pub fn vector_reduce_max(&mut self, src: RValue<'gcc>) -> RValue<'gcc> {
self.vector_reduce(src, |a, b, context| {
let differences_or_zeros = difference_or_zero(a, b, context);
- context.new_binary_op(None, BinaryOp::Plus, b.get_type(), b, differences_or_zeros)
+ context.new_binary_op(None, BinaryOp::Minus, a.get_type(), a, differences_or_zeros)
})
}
+ fn vector_extremum(&mut self, a: RValue<'gcc>, b: RValue<'gcc>, direction: ExtremumOperation) -> RValue<'gcc> {
+ let vector_type = a.get_type();
+
+ // mask out the NaNs in b and replace them with the corresponding lane in a, so when a and
+ // b get compared & spliced together, we get the numeric values instead of NaNs.
+ let b_nan_mask = self.context.new_comparison(None, ComparisonOp::NotEquals, b, b);
+ let mask_type = b_nan_mask.get_type();
+ let b_nan_mask_inverted = self.context.new_unary_op(None, UnaryOp::BitwiseNegate, mask_type, b_nan_mask);
+ let a_cast = self.context.new_bitcast(None, a, mask_type);
+ let b_cast = self.context.new_bitcast(None, b, mask_type);
+ let res = (b_nan_mask & a_cast) | (b_nan_mask_inverted & b_cast);
+ let b = self.context.new_bitcast(None, res, vector_type);
+
+ // now do the actual comparison
+ let comparison_op = match direction {
+ ExtremumOperation::Min => ComparisonOp::LessThan,
+ ExtremumOperation::Max => ComparisonOp::GreaterThan,
+ };
+ let cmp = self.context.new_comparison(None, comparison_op, a, b);
+ let cmp_inverted = self.context.new_unary_op(None, UnaryOp::BitwiseNegate, cmp.get_type(), cmp);
+ let res = (cmp & a_cast) | (cmp_inverted & res);
+ self.context.new_bitcast(None, res, vector_type)
+ }
+
+ pub fn vector_fmin(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
+ self.vector_extremum(a, b, ExtremumOperation::Min)
+ }
+
+ #[cfg(feature="master")]
+ pub fn vector_reduce_fmin(&mut self, src: RValue<'gcc>) -> RValue<'gcc> {
+ let vector_type = src.get_type().unqualified().dyncast_vector().expect("vector type");
+ let element_count = vector_type.get_num_units();
+ let mut acc = self.context.new_vector_access(None, src, self.context.new_rvalue_zero(self.int_type)).to_rvalue();
+ for i in 1..element_count {
+ let elem = self.context
+ .new_vector_access(None, src, self.context.new_rvalue_from_int(self.int_type, i as _))
+ .to_rvalue();
+ let cmp = self.context.new_comparison(None, ComparisonOp::LessThan, acc, elem);
+ acc = self.select(cmp, acc, elem);
+ }
+ acc
+ }
+
+ #[cfg(not(feature="master"))]
+ pub fn vector_reduce_fmin(&mut self, _src: RValue<'gcc>) -> RValue<'gcc> {
+ unimplemented!();
+ }
+
+ pub fn vector_fmax(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
+ self.vector_extremum(a, b, ExtremumOperation::Max)
+ }
+
+ #[cfg(feature="master")]
+ pub fn vector_reduce_fmax(&mut self, src: RValue<'gcc>) -> RValue<'gcc> {
+ let vector_type = src.get_type().unqualified().dyncast_vector().expect("vector type");
+ let element_count = vector_type.get_num_units();
+ let mut acc = self.context.new_vector_access(None, src, self.context.new_rvalue_zero(self.int_type)).to_rvalue();
+ for i in 1..element_count {
+ let elem = self.context
+ .new_vector_access(None, src, self.context.new_rvalue_from_int(self.int_type, i as _))
+ .to_rvalue();
+ let cmp = self.context.new_comparison(None, ComparisonOp::GreaterThan, acc, elem);
+ acc = self.select(cmp, acc, elem);
+ }
+ acc
+ }
+
+ #[cfg(not(feature="master"))]
+ pub fn vector_reduce_fmax(&mut self, _src: RValue<'gcc>) -> RValue<'gcc> {
+ unimplemented!();
+ }
+
pub fn vector_select(&mut self, cond: RValue<'gcc>, then_val: RValue<'gcc>, else_val: RValue<'gcc>) -> RValue<'gcc> {
// cond is a vector of integers, not of bools.
- let cond_type = cond.get_type();
- let vector_type = cond_type.unqualified().dyncast_vector().expect("vector type");
+ let vector_type = cond.get_type().unqualified().dyncast_vector().expect("vector type");
let num_units = vector_type.get_num_units();
let element_type = vector_type.get_element_type();
+
+ #[cfg(feature="master")]
+ let (cond, element_type) = {
+ let then_val_vector_type = then_val.get_type().dyncast_vector().expect("vector type");
+ let then_val_element_type = then_val_vector_type.get_element_type();
+ let then_val_element_size = then_val_element_type.get_size();
+
+ // NOTE: the mask needs to be of the same size as the other arguments in order for the &
+ // operation to work.
+ if then_val_element_size != element_type.get_size() {
+ let new_element_type = self.type_ix(then_val_element_size as u64 * 8);
+ let new_vector_type = self.context.new_vector_type(new_element_type, num_units as u64);
+ let cond = self.context.convert_vector(None, cond, new_vector_type);
+ (cond, new_element_type)
+ }
+ else {
+ (cond, element_type)
+ }
+ };
+
+ let cond_type = cond.get_type();
+
let zeros = vec![self.context.new_rvalue_zero(element_type); num_units];
let zeros = self.context.new_rvalue_from_vector(None, cond_type, &zeros);
+ let result_type = then_val.get_type();
+
let masks = self.context.new_comparison(None, ComparisonOp::NotEquals, cond, zeros);
+ // NOTE: masks is a vector of integers, but the values can be vectors of floats, so use bitcast to make
+ // the & operation work.
+ let then_val = self.bitcast_if_needed(then_val, masks.get_type());
let then_vals = masks & then_val;
- let ones = vec![self.context.new_rvalue_one(element_type); num_units];
- let ones = self.context.new_rvalue_from_vector(None, cond_type, &ones);
- let inverted_masks = masks + ones;
+ let minus_ones = vec![self.context.new_rvalue_from_int(element_type, -1); num_units];
+ let minus_ones = self.context.new_rvalue_from_vector(None, cond_type, &minus_ones);
+ let inverted_masks = masks ^ minus_ones;
// NOTE: sometimes, the type of else_val can be different than the type of then_val in
// libgccjit (vector of int vs vector of int32_t), but they should be the same for the AND
// operation to work.
+ // TODO: remove bitcast now that vector types can be compared?
let else_val = self.context.new_bitcast(None, else_val, then_val.get_type());
let else_vals = inverted_masks & else_val;
- then_vals | else_vals
+ let res = then_vals | else_vals;
+ self.bitcast_if_needed(res, result_type)
}
}
fn difference_or_zero<'gcc>(a: RValue<'gcc>, b: RValue<'gcc>, context: &'gcc Context<'gcc>) -> RValue<'gcc> {
let difference = a - b;
let masks = context.new_comparison(None, ComparisonOp::GreaterThanEquals, b, a);
+ // NOTE: masks is a vector of integers, but the values can be vectors of floats, so use bitcast to make
+ // the & operation work.
+ let a_type = a.get_type();
+ let masks =
+ if masks.get_type() != a_type {
+ context.new_bitcast(None, masks, a_type)
+ }
+ else {
+ masks
+ };
difference & masks
}
diff --git a/compiler/rustc_codegen_gcc/src/callee.rs b/compiler/rustc_codegen_gcc/src/callee.rs
index 9e3a22ee05d7..ba1e86562089 100644
--- a/compiler/rustc_codegen_gcc/src/callee.rs
+++ b/compiler/rustc_codegen_gcc/src/callee.rs
@@ -1,9 +1,10 @@
-use gccjit::{FunctionType, RValue};
-use rustc_codegen_ssa::traits::BaseTypeMethods;
+#[cfg(feature="master")]
+use gccjit::{FnAttribute, Visibility};
+use gccjit::{FunctionType, Function};
use rustc_middle::ty::{self, Instance, TypeVisitableExt};
use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt};
-use crate::abi::FnAbiGccExt;
+use crate::attributes;
use crate::context::CodegenCx;
/// Codegens a reference to a fn/method item, monomorphizing and
@@ -13,22 +14,26 @@ use crate::context::CodegenCx;
///
/// - `cx`: the crate context
/// - `instance`: the instance to be instantiated
-pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>) -> RValue<'gcc> {
+pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>) -> Function<'gcc> {
let tcx = cx.tcx();
assert!(!instance.substs.needs_infer());
assert!(!instance.substs.has_escaping_bound_vars());
+ let sym = tcx.symbol_name(instance).name;
+
if let Some(&func) = cx.function_instances.borrow().get(&instance) {
return func;
}
- let sym = tcx.symbol_name(instance).name;
-
let fn_abi = cx.fn_abi_of_instance(instance, ty::List::empty());
let func =
- if let Some(func) = cx.get_declared_value(&sym) {
+ if let Some(_func) = cx.get_declared_value(&sym) {
+ // FIXME(antoyo): we never reach this because get_declared_value only returns global variables
+ // and here we try to get a function.
+ unreachable!();
+ /*
// Create a fn pointer with the new signature.
let ptrty = fn_abi.ptr_to_gcc_type(cx);
@@ -61,13 +66,105 @@ pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>)
}
else {
func
- }
+ }*/
}
else {
cx.linkage.set(FunctionType::Extern);
let func = cx.declare_fn(&sym, &fn_abi);
+ attributes::from_fn_attrs(cx, func, instance);
+
+ let instance_def_id = instance.def_id();
+
// TODO(antoyo): set linkage and attributes.
+
+ // Apply an appropriate linkage/visibility value to our item that we
+ // just declared.
+ //
+ // This is sort of subtle. Inside our codegen unit we started off
+ // compilation by predefining all our own `MonoItem` instances. That
+ // is, everything we're codegenning ourselves is already defined. That
+ // means that anything we're actually codegenning in this codegen unit
+ // will have hit the above branch in `get_declared_value`. As a result,
+ // we're guaranteed here that we're declaring a symbol that won't get
+ // defined, or in other words we're referencing a value from another
+ // codegen unit or even another crate.
+ //
+ // So because this is a foreign value we blanket apply an external
+ // linkage directive because it's coming from a different object file.
+ // The visibility here is where it gets tricky. This symbol could be
+ // referencing some foreign crate or foreign library (an `extern`
+ // block) in which case we want to leave the default visibility. We may
+ // also, though, have multiple codegen units. It could be a
+ // monomorphization, in which case its expected visibility depends on
+ // whether we are sharing generics or not. The important thing here is
+ // that the visibility we apply to the declaration is the same one that
+ // has been applied to the definition (wherever that definition may be).
+ let is_generic = instance.substs.non_erasable_generics().next().is_some();
+
+ if is_generic {
+ // This is a monomorphization. Its expected visibility depends
+ // on whether we are in share-generics mode.
+
+ if cx.tcx.sess.opts.share_generics() {
+ // We are in share_generics mode.
+
+ if let Some(instance_def_id) = instance_def_id.as_local() {
+ // This is a definition from the current crate. If the
+ // definition is unreachable for downstream crates or
+ // the current crate does not re-export generics, the
+ // definition of the instance will have been declared
+ // as `hidden`.
+ if cx.tcx.is_unreachable_local_definition(instance_def_id)
+ || !cx.tcx.local_crate_exports_generics()
+ {
+ #[cfg(feature="master")]
+ func.add_attribute(FnAttribute::Visibility(Visibility::Hidden));
+ }
+ } else {
+ // This is a monomorphization of a generic function
+ // defined in an upstream crate.
+ if instance.upstream_monomorphization(tcx).is_some() {
+ // This is instantiated in another crate. It cannot
+ // be `hidden`.
+ } else {
+ // This is a local instantiation of an upstream definition.
+ // If the current crate does not re-export it
+ // (because it is a C library or an executable), it
+ // will have been declared `hidden`.
+ if !cx.tcx.local_crate_exports_generics() {
+ #[cfg(feature="master")]
+ func.add_attribute(FnAttribute::Visibility(Visibility::Hidden));
+ }
+ }
+ }
+ } else {
+ // When not sharing generics, all instances are in the same
+ // crate and have hidden visibility
+ #[cfg(feature="master")]
+ func.add_attribute(FnAttribute::Visibility(Visibility::Hidden));
+ }
+ } else {
+ // This is a non-generic function
+ if cx.tcx.is_codegened_item(instance_def_id) {
+ // This is a function that is instantiated in the local crate
+
+ if instance_def_id.is_local() {
+ // This is function that is defined in the local crate.
+ // If it is not reachable, it is hidden.
+ if !cx.tcx.is_reachable_non_generic(instance_def_id) {
+ #[cfg(feature="master")]
+ func.add_attribute(FnAttribute::Visibility(Visibility::Hidden));
+ }
+ } else {
+ // This is a function from an upstream crate that has
+ // been instantiated here. These are always hidden.
+ #[cfg(feature="master")]
+ func.add_attribute(FnAttribute::Visibility(Visibility::Hidden));
+ }
+ }
+ }
+
func
};
diff --git a/compiler/rustc_codegen_gcc/src/common.rs b/compiler/rustc_codegen_gcc/src/common.rs
index c939da9cec3c..76fc7bd222e1 100644
--- a/compiler/rustc_codegen_gcc/src/common.rs
+++ b/compiler/rustc_codegen_gcc/src/common.rs
@@ -36,7 +36,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
pub fn bytes_in_context<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, bytes: &[u8]) -> RValue<'gcc> {
let context = &cx.context;
let byte_type = context.new_type::();
- let typ = context.new_array_type(None, byte_type, bytes.len() as i32);
+ let typ = context.new_array_type(None, byte_type, bytes.len() as u64);
let elements: Vec<_> =
bytes.iter()
.map(|&byte| context.new_rvalue_from_int(byte_type, byte as i32))
@@ -115,8 +115,8 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
self.const_uint(self.usize_type, i)
}
- fn const_u8(&self, _i: u8) -> RValue<'gcc> {
- unimplemented!();
+ fn const_u8(&self, i: u8) -> RValue<'gcc> {
+ self.const_uint(self.type_u8(), i as u64)
}
fn const_real(&self, typ: Type<'gcc>, val: f64) -> RValue<'gcc> {
@@ -133,7 +133,7 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
.1;
let len = s.len();
let cs = self.const_ptrcast(str_global.get_address(None),
- self.type_ptr_to(self.layout_of(self.tcx.types.str_).gcc_type(self, true)),
+ self.type_ptr_to(self.layout_of(self.tcx.types.str_).gcc_type(self)),
);
(cs, self.const_usize(len as u64))
}
@@ -174,8 +174,18 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
}
let value = self.const_uint_big(self.type_ix(bitsize), data);
- // TODO(bjorn3): assert size is correct
- self.const_bitcast(value, ty)
+ let bytesize = layout.size(self).bytes();
+ if bitsize > 1 && ty.is_integral() && bytesize as u32 == ty.get_size() {
+ // NOTE: since the intrinsic _xabort is called with a bitcast, which
+ // is non-const, but expects a constant, do a normal cast instead of a bitcast.
+ // FIXME(antoyo): fix bitcast to work in constant contexts.
+ // TODO(antoyo): perhaps only use bitcast for pointers?
+ self.context.new_cast(None, value, ty)
+ }
+ else {
+ // TODO(bjorn3): assert size is correct
+ self.const_bitcast(value, ty)
+ }
}
Scalar::Ptr(ptr, _size) => {
let (alloc_id, offset) = ptr.into_parts();
@@ -227,11 +237,11 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
fn from_const_alloc(&self, layout: TyAndLayout<'tcx>, alloc: ConstAllocation<'tcx>, offset: Size) -> PlaceRef<'tcx, RValue<'gcc>> {
assert_eq!(alloc.inner().align, layout.align.abi);
- let ty = self.type_ptr_to(layout.gcc_type(self, true));
+ let ty = self.type_ptr_to(layout.gcc_type(self));
let value =
if layout.size == Size::ZERO {
let value = self.const_usize(alloc.inner().align.bytes());
- self.context.new_cast(None, value, ty)
+ self.const_bitcast(value, ty)
}
else {
let init = const_alloc_to_gcc(self, alloc);
diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs
index dc41cb761b59..792ab8f890d8 100644
--- a/compiler/rustc_codegen_gcc/src/consts.rs
+++ b/compiler/rustc_codegen_gcc/src/consts.rs
@@ -1,8 +1,8 @@
-use gccjit::{GlobalKind, LValue, RValue, ToRValue, Type};
+#[cfg(feature = "master")]
+use gccjit::FnAttribute;
+use gccjit::{Function, GlobalKind, LValue, RValue, ToRValue, Type};
use rustc_codegen_ssa::traits::{BaseTypeMethods, ConstMethods, DerivedTypeMethods, StaticMethods};
-use rustc_hir as hir;
-use rustc_hir::Node;
-use rustc_middle::{bug, span_bug};
+use rustc_middle::span_bug;
use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
use rustc_middle::mir::mono::MonoItem;
use rustc_middle::ty::{self, Instance, Ty};
@@ -13,6 +13,7 @@ use rustc_target::abi::{self, Align, HasDataLayout, Primitive, Size, WrappingRan
use crate::base;
use crate::context::CodegenCx;
+use crate::errors::InvalidMinimumAlignment;
use crate::type_of::LayoutGccExt;
impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
@@ -30,6 +31,21 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
}
}
+fn set_global_alignment<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, gv: LValue<'gcc>, mut align: Align) {
+ // The target may require greater alignment for globals than the type does.
+ // Note: GCC and Clang also allow `__attribute__((aligned))` on variables,
+ // which can force it to be smaller. Rust doesn't support this yet.
+ if let Some(min) = cx.sess().target.min_global_align {
+ match Align::from_bits(min) {
+ Ok(min) => align = align.max(min),
+ Err(err) => {
+ cx.sess().emit_err(InvalidMinimumAlignment { err });
+ }
+ }
+ }
+ gv.set_alignment(align.bytes() as i32);
+}
+
impl<'gcc, 'tcx> StaticMethods for CodegenCx<'gcc, 'tcx> {
fn static_addr_of(&self, cv: RValue<'gcc>, align: Align, kind: Option<&str>) -> RValue<'gcc> {
// TODO(antoyo): implement a proper rvalue comparison in libgccjit instead of doing the
@@ -79,9 +95,9 @@ impl<'gcc, 'tcx> StaticMethods for CodegenCx<'gcc, 'tcx> {
let instance = Instance::mono(self.tcx, def_id);
let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all());
- let gcc_type = self.layout_of(ty).gcc_type(self, true);
+ let gcc_type = self.layout_of(ty).gcc_type(self);
- // TODO(antoyo): set alignment.
+ set_global_alignment(self, global, self.align_of(ty));
let value = self.bitcast_if_needed(value, gcc_type);
global.global_set_initializer_rvalue(value);
@@ -158,12 +174,19 @@ impl<'gcc, 'tcx> StaticMethods for CodegenCx<'gcc, 'tcx> {
// TODO(antoyo)
}
- fn add_compiler_used_global(&self, _global: RValue<'gcc>) {
- // TODO(antoyo)
+ fn add_compiler_used_global(&self, global: RValue<'gcc>) {
+ // NOTE: seems like GCC does not make the distinction between compiler.used and used.
+ self.add_used_global(global);
}
}
impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
+ #[cfg_attr(not(feature="master"), allow(unused_variables))]
+ pub fn add_used_function(&self, function: Function<'gcc>) {
+ #[cfg(feature = "master")]
+ function.add_attribute(FnAttribute::Used);
+ }
+
pub fn static_addr_of_mut(&self, cv: RValue<'gcc>, align: Align, kind: Option<&str>) -> RValue<'gcc> {
let global =
match kind {
@@ -208,82 +231,59 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
let sym = self.tcx.symbol_name(instance).name;
let global =
- if let Some(def_id) = def_id.as_local() {
- let id = self.tcx.hir().local_def_id_to_hir_id(def_id);
- let llty = self.layout_of(ty).gcc_type(self, true);
- // FIXME: refactor this to work without accessing the HIR
- let global = match self.tcx.hir().get(id) {
- Node::Item(&hir::Item { span, kind: hir::ItemKind::Static(..), .. }) => {
- if let Some(global) = self.get_declared_value(&sym) {
- if self.val_ty(global) != self.type_ptr_to(llty) {
- span_bug!(span, "Conflicting types for static");
- }
- }
-
- let is_tls = fn_attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL);
- let global = self.declare_global(
- &sym,
- llty,
- GlobalKind::Exported,
- is_tls,
- fn_attrs.link_section,
- );
-
- if !self.tcx.is_reachable_non_generic(def_id) {
- // TODO(antoyo): set visibility.
- }
-
- global
- }
-
- Node::ForeignItem(&hir::ForeignItem {
- span: _,
- kind: hir::ForeignItemKind::Static(..),
- ..
- }) => {
- let fn_attrs = self.tcx.codegen_fn_attrs(def_id);
- check_and_apply_linkage(&self, &fn_attrs, ty, sym)
- }
-
- item => bug!("get_static: expected static, found {:?}", item),
- };
-
- global
- }
- else {
- // FIXME(nagisa): perhaps the map of externs could be offloaded to llvm somehow?
- //debug!("get_static: sym={} item_attr={:?}", sym, self.tcx.item_attrs(def_id));
-
- let attrs = self.tcx.codegen_fn_attrs(def_id);
- let global = check_and_apply_linkage(&self, &attrs, ty, sym);
-
- let needs_dll_storage_attr = false; // TODO(antoyo)
-
- // If this assertion triggers, there's something wrong with commandline
- // argument validation.
- debug_assert!(
- !(self.tcx.sess.opts.cg.linker_plugin_lto.enabled()
- && self.tcx.sess.target.options.is_like_msvc
- && self.tcx.sess.opts.cg.prefer_dynamic)
- );
-
- if needs_dll_storage_attr {
- // This item is external but not foreign, i.e., it originates from an external Rust
- // crate. Since we don't know whether this crate will be linked dynamically or
- // statically in the final application, we always mark such symbols as 'dllimport'.
- // If final linkage happens to be static, we rely on compiler-emitted __imp_ stubs
- // to make things work.
- //
- // However, in some scenarios we defer emission of statics to downstream
- // crates, so there are cases where a static with an upstream DefId
- // is actually present in the current crate. We can find out via the
- // is_codegened_item query.
- if !self.tcx.is_codegened_item(def_id) {
- unimplemented!();
- }
+ if def_id.is_local() && !self.tcx.is_foreign_item(def_id) {
+ let llty = self.layout_of(ty).gcc_type(self);
+ if let Some(global) = self.get_declared_value(sym) {
+ if self.val_ty(global) != self.type_ptr_to(llty) {
+ span_bug!(self.tcx.def_span(def_id), "Conflicting types for static");
}
- global
- };
+ }
+
+ let is_tls = fn_attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL);
+ let global = self.declare_global(
+ &sym,
+ llty,
+ GlobalKind::Exported,
+ is_tls,
+ fn_attrs.link_section,
+ );
+
+ if !self.tcx.is_reachable_non_generic(def_id) {
+ // TODO(antoyo): set visibility.
+ }
+
+ global
+ } else {
+ check_and_apply_linkage(&self, &fn_attrs, ty, sym)
+ };
+
+ if !def_id.is_local() {
+ let needs_dll_storage_attr = false; // TODO(antoyo)
+
+ // If this assertion triggers, there's something wrong with commandline
+ // argument validation.
+ debug_assert!(
+ !(self.tcx.sess.opts.cg.linker_plugin_lto.enabled()
+ && self.tcx.sess.target.options.is_like_msvc
+ && self.tcx.sess.opts.cg.prefer_dynamic)
+ );
+
+ if needs_dll_storage_attr {
+ // This item is external but not foreign, i.e., it originates from an external Rust
+ // crate. Since we don't know whether this crate will be linked dynamically or
+ // statically in the final application, we always mark such symbols as 'dllimport'.
+ // If final linkage happens to be static, we rely on compiler-emitted __imp_ stubs
+ // to make things work.
+ //
+ // However, in some scenarios we defer emission of statics to downstream
+ // crates, so there are cases where a static with an upstream DefId
+ // is actually present in the current crate. We can find out via the
+ // is_codegened_item query.
+ if !self.tcx.is_codegened_item(def_id) {
+ unimplemented!();
+ }
+ }
+ }
// TODO(antoyo): set dll storage class.
@@ -357,7 +357,7 @@ pub fn codegen_static_initializer<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, def_id
fn check_and_apply_linkage<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, attrs: &CodegenFnAttrs, ty: Ty<'tcx>, sym: &str) -> LValue<'gcc> {
let is_tls = attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL);
- let llty = cx.layout_of(ty).gcc_type(cx, true);
+ let gcc_type = cx.layout_of(ty).gcc_type(cx);
if let Some(linkage) = attrs.import_linkage {
// Declare a symbol `foo` with the desired linkage.
let global1 = cx.declare_global_with_linkage(&sym, cx.type_i8(), base::global_linkage_to_gcc(linkage));
@@ -370,9 +370,10 @@ fn check_and_apply_linkage<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, attrs: &Codeg
// zero.
let mut real_name = "_rust_extern_with_linkage_".to_string();
real_name.push_str(&sym);
- let global2 = cx.define_global(&real_name, llty, is_tls, attrs.link_section);
+ let global2 = cx.define_global(&real_name, gcc_type, is_tls, attrs.link_section);
// TODO(antoyo): set linkage.
- global2.global_set_initializer_rvalue(global1.get_address(None));
+ let value = cx.const_ptrcast(global1.get_address(None), gcc_type);
+ global2.global_set_initializer_rvalue(value);
// TODO(antoyo): use global_set_initializer() when it will work.
global2
}
@@ -386,6 +387,6 @@ fn check_and_apply_linkage<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, attrs: &Codeg
// don't do this then linker errors can be generated where the linker
// complains that one object files has a thread local version of the
// symbol and another one doesn't.
- cx.declare_global(&sym, llty, GlobalKind::Imported, is_tls, attrs.link_section)
+ cx.declare_global(&sym, gcc_type, GlobalKind::Imported, is_tls, attrs.link_section)
}
}
diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs
index 457006319afb..661681bdb50f 100644
--- a/compiler/rustc_codegen_gcc/src/context.rs
+++ b/compiler/rustc_codegen_gcc/src/context.rs
@@ -1,9 +1,10 @@
use std::cell::{Cell, RefCell};
-use gccjit::{Block, CType, Context, Function, FunctionPtrType, FunctionType, LValue, RValue, Struct, Type};
+use gccjit::{Block, CType, Context, Function, FunctionPtrType, FunctionType, LValue, RValue, Type};
use rustc_codegen_ssa::base::wants_msvc_seh;
use rustc_codegen_ssa::traits::{
BackendTypes,
+ BaseTypeMethods,
MiscMethods,
};
use rustc_data_structures::base_n;
@@ -11,7 +12,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_middle::span_bug;
use rustc_middle::mir::mono::CodegenUnit;
use rustc_middle::ty::{self, Instance, ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt};
-use rustc_middle::ty::layout::{FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, HasTyCtxt, LayoutError, TyAndLayout, LayoutOfHelpers};
+use rustc_middle::ty::layout::{FnAbiError, FnAbiOf, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, HasTyCtxt, LayoutError, TyAndLayout, LayoutOfHelpers};
use rustc_session::Session;
use rustc_span::{Span, source_map::respan};
use rustc_target::abi::{call::FnAbi, HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx};
@@ -33,6 +34,7 @@ pub struct CodegenCx<'gcc, 'tcx> {
// TODO(bjorn3): Can this field be removed?
pub current_func: RefCell