From 11a64a18342865b166d2da703a06deb447f834c1 Mon Sep 17 00:00:00 2001
From: Zachary S <zasample18+github@gmail.com>
Date: Fri, 1 Sep 2023 20:20:29 -0500
Subject: [PATCH 01/11] don't panic in BorrowedCursor::write

---
 library/std/src/io/readbuf.rs | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/library/std/src/io/readbuf.rs b/library/std/src/io/readbuf.rs
index 034ddd8df9aed..95044de2a09e1 100644
--- a/library/std/src/io/readbuf.rs
+++ b/library/std/src/io/readbuf.rs
@@ -306,8 +306,9 @@ impl<'a> BorrowedCursor<'a> {
 
 impl<'a> Write for BorrowedCursor<'a> {
     fn write(&mut self, buf: &[u8]) -> Result<usize> {
-        self.append(buf);
-        Ok(buf.len())
+        let amt = cmp::min(buf.len(), self.capacity());
+        self.append(&buf[..amt]);
+        Ok(amt)
     }
 
     #[inline]

From eed89185bb88c75a4fd6d013b7368939bb03682e Mon Sep 17 00:00:00 2001
From: klensy <klensy@users.noreply.github.com>
Date: Tue, 7 Nov 2023 15:19:33 +0300
Subject: [PATCH 02/11] bump some deps

drop num_cpus from rust-installer as not used
update rayon, rayon-core, which drops it's deps on num_cpus and crossbeam-channel (for bootstrap too) (https://github.com/rayon-rs/rayon/blob/v1.8.0/RELEASES.md)
update erro, which drops errno-dragonfly (https://github.com/lambda-fairy/rust-errno/blob/5341791935df601306ffc57a665763c4ecd72755/CHANGELOG.md)
---
 Cargo.lock                          | 26 +++++--------------
 src/bootstrap/Cargo.lock            | 40 +++--------------------------
 src/tools/rust-installer/Cargo.toml |  1 -
 src/tools/tidy/src/deps.rs          |  1 -
 4 files changed, 10 insertions(+), 58 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index e6c5de3ca6c4f..55ed17ac256af 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1281,25 +1281,14 @@ checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1"
 
 [[package]]
 name = "errno"
-version = "0.3.1"
+version = "0.3.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
+checksum = "ac3e13f66a2f95e32a39eaa81f6b95d42878ca0e1db0c7543723dfe12557e860"
 dependencies = [
- "errno-dragonfly",
  "libc",
  "windows-sys 0.48.0",
 ]
 
-[[package]]
-name = "errno-dragonfly"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
-dependencies = [
- "cc",
- "libc",
-]
-
 [[package]]
 name = "error_index_generator"
 version = "0.0.0"
@@ -2055,7 +2044,6 @@ dependencies = [
  "anyhow",
  "clap",
  "flate2",
- "num_cpus",
  "rayon",
  "tar",
  "walkdir",
@@ -3181,9 +3169,9 @@ dependencies = [
 
 [[package]]
 name = "rayon"
-version = "1.7.0"
+version = "1.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b"
+checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1"
 dependencies = [
  "either",
  "rayon-core",
@@ -3191,14 +3179,12 @@ dependencies = [
 
 [[package]]
 name = "rayon-core"
-version = "1.11.0"
+version = "1.12.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d"
+checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed"
 dependencies = [
- "crossbeam-channel",
  "crossbeam-deque",
  "crossbeam-utils",
- "num_cpus",
 ]
 
 [[package]]
diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock
index 346bfb30fecf9..57113b0ec62c6 100644
--- a/src/bootstrap/Cargo.lock
+++ b/src/bootstrap/Cargo.lock
@@ -180,16 +180,6 @@ dependencies = [
  "libc",
 ]
 
-[[package]]
-name = "crossbeam-channel"
-version = "0.5.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521"
-dependencies = [
- "cfg-if",
- "crossbeam-utils",
-]
-
 [[package]]
 name = "crossbeam-deque"
 version = "0.8.2"
@@ -323,15 +313,6 @@ version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
 
-[[package]]
-name = "hermit-abi"
-version = "0.1.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
-dependencies = [
- "libc",
-]
-
 [[package]]
 name = "hex"
 version = "0.4.3"
@@ -443,16 +424,6 @@ dependencies = [
  "winapi",
 ]
 
-[[package]]
-name = "num_cpus"
-version = "1.13.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
-dependencies = [
- "hermit-abi",
- "libc",
-]
-
 [[package]]
 name = "object"
 version = "0.32.0"
@@ -514,25 +485,22 @@ dependencies = [
 
 [[package]]
 name = "rayon"
-version = "1.6.0"
+version = "1.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e060280438193c554f654141c9ea9417886713b7acd75974c85b18a69a88e0b"
+checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1"
 dependencies = [
- "crossbeam-deque",
  "either",
  "rayon-core",
 ]
 
 [[package]]
 name = "rayon-core"
-version = "1.10.1"
+version = "1.12.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cac410af5d00ab6884528b4ab69d1e8e146e8d471201800fa1b4524126de6ad3"
+checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed"
 dependencies = [
- "crossbeam-channel",
  "crossbeam-deque",
  "crossbeam-utils",
- "num_cpus",
 ]
 
 [[package]]
diff --git a/src/tools/rust-installer/Cargo.toml b/src/tools/rust-installer/Cargo.toml
index 471f2b5ac73ed..cdd867c5f1577 100644
--- a/src/tools/rust-installer/Cargo.toml
+++ b/src/tools/rust-installer/Cargo.toml
@@ -16,7 +16,6 @@ rayon = "1.0"
 tar = "0.4.38"
 walkdir = "2"
 xz2 = "0.1.4"
-num_cpus = "1"
 
 [dependencies.clap]
 features = ["derive"]
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index b10cccc79f6bf..7ad75f089f309 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -228,7 +228,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "ena",
     "equivalent",
     "errno",
-    "errno-dragonfly",
     "expect-test",
     "fallible-iterator", // dependency of `thorin`
     "fastrand",

From f2fd8ad788a8e90282e6aa0de44d037806b018ff Mon Sep 17 00:00:00 2001
From: Alex Macleod <alex@macleod.io>
Date: Tue, 7 Nov 2023 13:21:04 +0000
Subject: [PATCH 03/11] Document clippy_config in nightly-rustc docs

---
 src/bootstrap/src/core/build_steps/doc.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs
index f2a185f70fe0c..e3fd942fc3802 100644
--- a/src/bootstrap/src/core/build_steps/doc.rs
+++ b/src/bootstrap/src/core/build_steps/doc.rs
@@ -887,7 +887,7 @@ tool_doc!(
     "src/tools/rustfmt",
     crates = ["rustfmt-nightly", "rustfmt-config_proc_macro"]
 );
-tool_doc!(Clippy, "clippy", "src/tools/clippy", crates = ["clippy_utils"]);
+tool_doc!(Clippy, "clippy", "src/tools/clippy", crates = ["clippy_config", "clippy_utils"]);
 tool_doc!(Miri, "miri", "src/tools/miri", crates = ["miri"]);
 tool_doc!(
     Cargo,

From fcdd99edcad6e77ecc11fb5066cec3db10ee6054 Mon Sep 17 00:00:00 2001
From: Ben Kimock <kimockb@gmail.com>
Date: Mon, 6 Nov 2023 19:55:05 -0500
Subject: [PATCH 04/11] Add -Zcross-crate-inline-threshold=yes

---
 compiler/rustc_interface/src/tests.rs         | 12 +++++-----
 .../src/cross_crate_inline.rs                 | 10 ++++++--
 compiler/rustc_session/src/config.rs          | 22 +++++++++++++----
 compiler/rustc_session/src/options.rs         | 24 ++++++++++++++++++-
 .../cross-crate-inlining/always-inline.rs     | 13 ++++++++++
 .../cross-crate-inlining/auxiliary/always.rs  | 20 ++++++++++++++++
 .../cross-crate-inlining/auxiliary/leaf.rs    | 20 ++++++++++++++++
 .../cross-crate-inlining/auxiliary/never.rs   | 20 ++++++++++++++++
 .../cross-crate-inlining/leaf-inlining.rs     | 20 ++++++++++++++++
 .../cross-crate-inlining/never-inline.rs      | 13 ++++++++++
 10 files changed, 161 insertions(+), 13 deletions(-)
 create mode 100644 tests/codegen/cross-crate-inlining/always-inline.rs
 create mode 100644 tests/codegen/cross-crate-inlining/auxiliary/always.rs
 create mode 100644 tests/codegen/cross-crate-inlining/auxiliary/leaf.rs
 create mode 100644 tests/codegen/cross-crate-inlining/auxiliary/never.rs
 create mode 100644 tests/codegen/cross-crate-inlining/leaf-inlining.rs
 create mode 100644 tests/codegen/cross-crate-inlining/never-inline.rs

diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 8e66083a390fc..d308169552317 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -4,11 +4,11 @@ use rustc_data_structures::profiling::TimePassesFormat;
 use rustc_errors::{emitter::HumanReadableErrorType, registry, ColorConfig};
 use rustc_session::config::{
     build_configuration, build_session_options, rustc_optgroups, BranchProtection, CFGuard, Cfg,
-    DebugInfo, DumpMonoStatsFormat, ErrorOutputType, ExternEntry, ExternLocation, Externs, Input,
-    InstrumentCoverage, InstrumentXRay, LinkSelfContained, LinkerPluginLto, LocationDetail, LtoCli,
-    MirSpanview, OomStrategy, Options, OutFileName, OutputType, OutputTypes, PAuthKey, PacRet,
-    Passes, Polonius, ProcMacroExecutionStrategy, Strip, SwitchWithOptPath, SymbolManglingVersion,
-    TraitSolver, WasiExecModel,
+    DebugInfo, DumpMonoStatsFormat, ErrorOutputType, ExternEntry, ExternLocation, Externs,
+    InliningThreshold, Input, InstrumentCoverage, InstrumentXRay, LinkSelfContained,
+    LinkerPluginLto, LocationDetail, LtoCli, MirSpanview, OomStrategy, Options, OutFileName,
+    OutputType, OutputTypes, PAuthKey, PacRet, Passes, Polonius, ProcMacroExecutionStrategy, Strip,
+    SwitchWithOptPath, SymbolManglingVersion, TraitSolver, WasiExecModel,
 };
 use rustc_session::lint::Level;
 use rustc_session::search_paths::SearchPath;
@@ -748,7 +748,7 @@ fn test_unstable_options_tracking_hash() {
     );
     tracked!(codegen_backend, Some("abc".to_string()));
     tracked!(crate_attr, vec!["abc".to_string()]);
-    tracked!(cross_crate_inline_threshold, Some(200));
+    tracked!(cross_crate_inline_threshold, InliningThreshold::Always);
     tracked!(debug_info_for_profiling, true);
     tracked!(debug_macros, true);
     tracked!(dep_info_omit_d_target, true);
diff --git a/compiler/rustc_mir_transform/src/cross_crate_inline.rs b/compiler/rustc_mir_transform/src/cross_crate_inline.rs
index 4d0e261ed1fd7..261d9dd448d47 100644
--- a/compiler/rustc_mir_transform/src/cross_crate_inline.rs
+++ b/compiler/rustc_mir_transform/src/cross_crate_inline.rs
@@ -7,6 +7,7 @@ use rustc_middle::mir::visit::Visitor;
 use rustc_middle::mir::*;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::TyCtxt;
+use rustc_session::config::InliningThreshold;
 use rustc_session::config::OptLevel;
 
 pub fn provide(providers: &mut Providers) {
@@ -54,6 +55,12 @@ fn cross_crate_inlinable(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
         return false;
     }
 
+    let threshold = match tcx.sess.opts.unstable_opts.cross_crate_inline_threshold {
+        InliningThreshold::Always => return true,
+        InliningThreshold::Sometimes(threshold) => threshold,
+        InliningThreshold::Never => return false,
+    };
+
     let mir = tcx.optimized_mir(def_id);
     let mut checker =
         CostChecker { tcx, callee_body: mir, calls: 0, statements: 0, landing_pads: 0, resumes: 0 };
@@ -61,8 +68,7 @@ fn cross_crate_inlinable(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
     checker.calls == 0
         && checker.resumes == 0
         && checker.landing_pads == 0
-        && checker.statements
-            <= tcx.sess.opts.unstable_opts.cross_crate_inline_threshold.unwrap_or(100)
+        && checker.statements <= threshold
 }
 
 struct CostChecker<'b, 'tcx> {
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index c94e0d0ed3942..3cb8ec3a930f1 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -3161,10 +3161,10 @@ impl PpMode {
 pub(crate) mod dep_tracking {
     use super::{
         BranchProtection, CFGuard, CFProtection, CrateType, DebugInfo, DebugInfoCompression,
-        ErrorOutputType, InstrumentCoverage, InstrumentXRay, LinkerPluginLto, LocationDetail,
-        LtoCli, OomStrategy, OptLevel, OutFileName, OutputType, OutputTypes, Polonius,
-        RemapPathScopeComponents, ResolveDocLinks, SourceFileHashAlgorithm, SplitDwarfKind,
-        SwitchWithOptPath, SymbolManglingVersion, TraitSolver, TrimmedDefPaths,
+        ErrorOutputType, InliningThreshold, InstrumentCoverage, InstrumentXRay, LinkerPluginLto,
+        LocationDetail, LtoCli, OomStrategy, OptLevel, OutFileName, OutputType, OutputTypes,
+        Polonius, RemapPathScopeComponents, ResolveDocLinks, SourceFileHashAlgorithm,
+        SplitDwarfKind, SwitchWithOptPath, SymbolManglingVersion, TraitSolver, TrimmedDefPaths,
     };
     use crate::lint;
     use crate::options::WasiExecModel;
@@ -3270,6 +3270,7 @@ pub(crate) mod dep_tracking {
         LanguageIdentifier,
         TraitSolver,
         Polonius,
+        InliningThreshold,
     );
 
     impl<T1, T2> DepTrackingHash for (T1, T2)
@@ -3435,3 +3436,16 @@ impl Polonius {
         matches!(self, Polonius::Next)
     }
 }
+
+#[derive(Clone, Copy, PartialEq, Hash, Debug)]
+pub enum InliningThreshold {
+    Always,
+    Sometimes(usize),
+    Never,
+}
+
+impl Default for InliningThreshold {
+    fn default() -> Self {
+        Self::Sometimes(100)
+    }
+}
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 7510a41485af6..964a26e94fed9 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -428,6 +428,8 @@ mod desc {
         "one of supported execution strategies (`same-thread`, or `cross-thread`)";
     pub const parse_dump_solver_proof_tree: &str = "one of: `always`, `on-request`, `on-error`";
     pub const parse_remap_path_scope: &str = "comma separated list of scopes: `macro`, `diagnostics`, `unsplit-debuginfo`, `split-debuginfo`, `split-debuginfo-path`, `object`, `all`";
+    pub const parse_inlining_threshold: &str =
+        "either a boolean (`yes`, `no`, `on`, `off`, etc), or a non-negative number";
 }
 
 mod parse {
@@ -1310,6 +1312,26 @@ mod parse {
         };
         true
     }
+
+    pub(crate) fn parse_inlining_threshold(slot: &mut InliningThreshold, v: Option<&str>) -> bool {
+        match v {
+            Some("always" | "yes") => {
+                *slot = InliningThreshold::Always;
+            }
+            Some("never") => {
+                *slot = InliningThreshold::Never;
+            }
+            Some(v) => {
+                if let Ok(threshold) = v.parse() {
+                    *slot = InliningThreshold::Sometimes(threshold);
+                } else {
+                    return false;
+                }
+            }
+            None => return false,
+        }
+        true
+    }
 }
 
 options! {
@@ -1479,7 +1501,7 @@ options! {
         "combine CGUs into a single one"),
     crate_attr: Vec<String> = (Vec::new(), parse_string_push, [TRACKED],
         "inject the given attribute in the crate"),
-    cross_crate_inline_threshold: Option<usize> = (None, parse_opt_number, [TRACKED],
+    cross_crate_inline_threshold: InliningThreshold = (InliningThreshold::Sometimes(100), parse_inlining_threshold, [TRACKED],
         "threshold to allow cross crate inlining of functions"),
     debug_info_for_profiling: bool = (false, parse_bool, [TRACKED],
         "emit discriminators and other data necessary for AutoFDO"),
diff --git a/tests/codegen/cross-crate-inlining/always-inline.rs b/tests/codegen/cross-crate-inlining/always-inline.rs
new file mode 100644
index 0000000000000..f3f08bf116aee
--- /dev/null
+++ b/tests/codegen/cross-crate-inlining/always-inline.rs
@@ -0,0 +1,13 @@
+// compile-flags: -O
+// aux-build:always.rs
+
+#![crate_type = "lib"]
+
+extern crate always;
+
+// Check that we inline a cross-crate call, even though it isn't a leaf
+#[no_mangle]
+pub fn outer() -> String {
+    // CHECK-NOT: call {{.*}}stem_fn
+    always::stem_fn()
+}
diff --git a/tests/codegen/cross-crate-inlining/auxiliary/always.rs b/tests/codegen/cross-crate-inlining/auxiliary/always.rs
new file mode 100644
index 0000000000000..3670307ec8134
--- /dev/null
+++ b/tests/codegen/cross-crate-inlining/auxiliary/always.rs
@@ -0,0 +1,20 @@
+// compile-flags: -O -Zcross-crate-inline-threshold=always
+
+#![crate_type = "lib"]
+
+// This function *looks* like it contains a call, but that call will be optimized out by MIR
+// optimizations.
+pub fn leaf_fn() -> String {
+    String::new()
+}
+
+// This function contains a call, even after MIR optimizations. It is only eligible for
+// cross-crate-inlining with "always".
+pub fn stem_fn() -> String {
+    inner()
+}
+
+#[inline(never)]
+fn inner() -> String {
+    String::from("test")
+}
diff --git a/tests/codegen/cross-crate-inlining/auxiliary/leaf.rs b/tests/codegen/cross-crate-inlining/auxiliary/leaf.rs
new file mode 100644
index 0000000000000..963f087f22d4d
--- /dev/null
+++ b/tests/codegen/cross-crate-inlining/auxiliary/leaf.rs
@@ -0,0 +1,20 @@
+// compile-flags: -O
+
+#![crate_type = "lib"]
+
+// This function *looks* like it contains a call, but that call will be optimized out by MIR
+// optimizations.
+pub fn leaf_fn() -> String {
+    String::new()
+}
+
+// This function contains a call, even after MIR optimizations. It is only eligible for
+// cross-crate-inlining with "always".
+pub fn stem_fn() -> String {
+    inner()
+}
+
+#[inline(never)]
+fn inner() -> String {
+    String::from("test")
+}
diff --git a/tests/codegen/cross-crate-inlining/auxiliary/never.rs b/tests/codegen/cross-crate-inlining/auxiliary/never.rs
new file mode 100644
index 0000000000000..e222a6dea3871
--- /dev/null
+++ b/tests/codegen/cross-crate-inlining/auxiliary/never.rs
@@ -0,0 +1,20 @@
+// compile-flags: -O -Zcross-crate-inline-threshold=never
+
+#![crate_type = "lib"]
+
+// This function *looks* like it contains a call, but that call will be optimized out by MIR
+// optimizations.
+pub fn leaf_fn() -> String {
+    String::new()
+}
+
+// This function contains a call, even after MIR optimizations. It is only eligible for
+// cross-crate-inlining with "always".
+pub fn stem_fn() -> String {
+    inner()
+}
+
+#[inline(never)]
+fn inner() -> String {
+    String::from("test")
+}
diff --git a/tests/codegen/cross-crate-inlining/leaf-inlining.rs b/tests/codegen/cross-crate-inlining/leaf-inlining.rs
new file mode 100644
index 0000000000000..73b1a520b06cf
--- /dev/null
+++ b/tests/codegen/cross-crate-inlining/leaf-inlining.rs
@@ -0,0 +1,20 @@
+// compile-flags: -O -Zcross-crate-inline-threshold=yes
+// aux-build:leaf.rs
+
+#![crate_type = "lib"]
+
+extern crate leaf;
+
+// Check that we inline a leaf cross-crate call
+#[no_mangle]
+pub fn leaf_outer() -> String {
+    // CHECK-NOT: call {{.*}}leaf_fn
+    leaf::leaf_fn()
+}
+
+// Check that we do not inline a non-leaf cross-crate call
+#[no_mangle]
+pub fn stem_outer() -> String {
+    // CHECK: call {{.*}}stem_fn
+    leaf::stem_fn()
+}
diff --git a/tests/codegen/cross-crate-inlining/never-inline.rs b/tests/codegen/cross-crate-inlining/never-inline.rs
new file mode 100644
index 0000000000000..4e7bc3e5154cb
--- /dev/null
+++ b/tests/codegen/cross-crate-inlining/never-inline.rs
@@ -0,0 +1,13 @@
+// compile-flags: -O
+// aux-build:never.rs
+
+#![crate_type = "lib"]
+
+extern crate never;
+
+// Check that we do not inline a cross-crate call, even though it is a leaf
+#[no_mangle]
+pub fn outer() -> String {
+    // CHECK: call {{.*}}leaf_fn
+    never::leaf_fn()
+}

From 783d4b8b2629c31ff8359ce744060afdcb0a5bea Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote <n.nethercote@gmail.com>
Date: Tue, 31 Oct 2023 11:25:13 +1100
Subject: [PATCH 05/11] Clarify `space_between`.

To avoid `!matches!(...)`, which is hard to think about. Instead every
case now uses direct pattern matching and returns true or false.

Also add a couple of cases to the `stringify.rs` test that currently
print badly.
---
 compiler/rustc_ast_pretty/src/pprust/state.rs | 72 +++++++++++--------
 tests/ui/macros/stringify.rs                  |  2 +
 2 files changed, 44 insertions(+), 30 deletions(-)

diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index e71f421659e2e..48421ff71409c 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -146,37 +146,49 @@ pub fn print_crate<'a>(
     s.s.eof()
 }
 
-/// This makes printed token streams look slightly nicer,
-/// and also addresses some specific regressions described in #63896 and #73345.
-fn space_between(prev: &TokenTree, curr: &TokenTree) -> bool {
-    if let TokenTree::Token(token, _) = prev {
-        // No space after these tokens, e.g. `x.y`, `$e`
-        // (The carets point to `prev`.)       ^     ^
-        if matches!(token.kind, token::Dot | token::Dollar) {
-            return false;
-        }
-        if let token::DocComment(comment_kind, ..) = token.kind {
-            return comment_kind != CommentKind::Line;
-        }
-    }
-    match curr {
-        // No space before these tokens, e.g. `foo,`, `println!`, `x.y`
-        // (The carets point to `curr`.)          ^           ^     ^
+/// Should two consecutive tokens be printed with a space between them?
+///
+/// Note: some old proc macros parse pretty-printed output, so changes here can
+/// break old code. For example:
+/// - #63896: `#[allow(unused,` must be printed rather than `#[allow(unused ,`
+/// - #73345: `#[allow(unused)] must be printed rather than `# [allow(unused)]
+///
+fn space_between(tt1: &TokenTree, tt2: &TokenTree) -> bool {
+    use token::*;
+    use Delimiter::*;
+    use TokenTree::Delimited as Del;
+    use TokenTree::Token as Tok;
+
+    // Each match arm has one or more examples in comments. The default is to
+    // insert space between adjacent tokens, except for the cases listed in
+    // this match.
+    match (tt1, tt2) {
+        // No space after line doc comments.
+        (Tok(Token { kind: DocComment(CommentKind::Line, ..), .. }, _), _) => false,
+
+        // `.` + ANYTHING: `x.y`, `tup.0`
+        // `$` + ANYTHING: `$e`
+        (Tok(Token { kind: Dot | Dollar, .. }, _), _) => false,
+
+        // ANYTHING + `,`: `foo,`
+        // ANYTHING + `.`: `x.y`, `tup.0`
+        // ANYTHING + `!`: `foo! { ... }`
         //
-        // FIXME: having `Not` here works well for macro invocations like
-        // `println!()`, but is bad when `!` means "logical not" or "the never
-        // type", where the lack of space causes ugliness like this:
-        // `Fn() ->!`, `x =! y`, `if! x { f(); }`.
-        TokenTree::Token(token, _) => !matches!(token.kind, token::Comma | token::Not | token::Dot),
-        // No space before parentheses if preceded by these tokens, e.g. `foo(...)`
-        TokenTree::Delimited(_, Delimiter::Parenthesis, _) => {
-            !matches!(prev, TokenTree::Token(Token { kind: token::Ident(..), .. }, _))
-        }
-        // No space before brackets if preceded by these tokens, e.g. `#[...]`
-        TokenTree::Delimited(_, Delimiter::Bracket, _) => {
-            !matches!(prev, TokenTree::Token(Token { kind: token::Pound, .. }, _))
-        }
-        TokenTree::Delimited(..) => true,
+        // FIXME: Incorrect cases:
+        // - Logical not: `x =! y`, `if! x { f(); }`
+        // - Never type: `Fn() ->!`
+        (_, Tok(Token { kind: Comma | Dot | Not, .. }, _)) => false,
+
+        // IDENT + `(`: `f(3)`
+        //
+        // FIXME: Incorrect cases:
+        // - Let: `let(a, b) = (1, 2)`
+        (Tok(Token { kind: Ident(..), .. }, _), Del(_, Parenthesis, _)) => false,
+
+        // `#` + `[`: `#[attr]`
+        (Tok(Token { kind: Pound, .. }, _), Del(_, Bracket, _)) => false,
+
+        _ => true,
     }
 }
 
diff --git a/tests/ui/macros/stringify.rs b/tests/ui/macros/stringify.rs
index f1bbd4a621095..31e0d30c78b8f 100644
--- a/tests/ui/macros/stringify.rs
+++ b/tests/ui/macros/stringify.rs
@@ -115,6 +115,7 @@ fn test_expr() {
         "a + b * c - d + -1 * -2 - -3",
         "a + b * c - d + - 1 * - 2 - - 3"
     );
+    c2!(expr, [ x = !y ], "x = !y", "x =! y"); // FIXME
 
     // ExprKind::Unary
     c2!(expr, [ *expr ], "*expr", "* expr");
@@ -137,6 +138,7 @@ fn test_expr() {
 
     // ExprKind::If
     c1!(expr, [ if true {} ], "if true {}");
+    c2!(expr, [ if !true {} ], "if !true {}", "if! true {}"); // FIXME
     c2!(expr,
         [ if ::std::blah() { } else { } ],
         "if ::std::blah() {} else {}",

From 438b9a6e82cd74102bd41636dc48b6b846101a59 Mon Sep 17 00:00:00 2001
From: Nicholas Nethercote <n.nethercote@gmail.com>
Date: Wed, 1 Nov 2023 08:35:13 +1100
Subject: [PATCH 06/11] More tests for token stream pretty-printing with
 adjacent punctuation.

We currently do the wrong thing on a lot of these. The next commit will
fix things.
---
 tests/ui/macros/stringify.rs | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/tests/ui/macros/stringify.rs b/tests/ui/macros/stringify.rs
index 31e0d30c78b8f..70ca00285c49d 100644
--- a/tests/ui/macros/stringify.rs
+++ b/tests/ui/macros/stringify.rs
@@ -801,3 +801,32 @@ fn test_vis() {
     assert_eq!(inherited_vis!(struct), "");
     assert_eq!(stringify!(), "");
 }
+
+macro_rules! p {
+    ([$($tt:tt)*], $s:literal) => {
+        assert_eq!(stringify!($($tt)*), $s);
+    };
+}
+
+#[test]
+fn test_punct() {
+    // For all these cases, we must preserve spaces between the tokens.
+    // Otherwise, any old proc macro that parses pretty-printed code might glue
+    // together tokens that shouldn't be glued.
+    p!([ = = < < <= <= == == != != >= >= > > ], "= = < < <= <= == == != != >= >= > >");
+    p!([ && && & & || || | | ! ! ], "&& && & & || || | |!!"); // FIXME
+    p!([ ~ ~ @ @ # # ], "~ ~ @ @ # #");
+    p!([ . . .. .. ... ... ..= ..=], ".... .. ... ... ..= ..="); // FIXME
+    p!([ , , ; ; : : :: :: ], ",, ; ; : : :: ::"); // FIXME
+    p!([ -> -> <- <- => =>], "-> -> <- <- => =>");
+    p!([ $ $ ? ? ' ' ], "$$? ? ' '"); // FIXME
+    p!([ + + += += - - -= -= * * *= *= / / /= /= ], "+ + += += - - -= -= * * *= *= / / /= /=");
+    p!([ % % %= %= ^ ^ ^= ^= << << <<= <<= >> >> >>= >>= ],
+        "% % %= %= ^ ^ ^= ^= << << <<= <<= >> >> >>= >>=");
+
+    // For these one we must insert spaces between adjacent tokens, again due
+    // to proc macros.
+    p!([ +! ?= |> >>@ --> <-- $$ =====> ], "+! ? = | > >> @ - -> <- - $$== == =>"); // FIXME
+    p!([ ,; ;, ** @@ $+$ >< <> ?? +== ], ", ; ;, * * @ @ $+ $> < < > ? ? += ="); // FIXME
+    p!([ :#!@|$=&*,+;*~? ], ": #! @ | $= & *, + ; * ~ ?"); // FIXME
+}

From a5738803735db820f0c4e1d45edf706526308cf6 Mon Sep 17 00:00:00 2001
From: Zalathar <Zalathar@users.noreply.github.com>
Date: Thu, 2 Nov 2023 14:27:22 +1100
Subject: [PATCH 07/11] coverage: Rename the `run-coverage` test mode to
 `coverage-run`

This makes it more consistent with the `coverage-map` mode and the shared
`tests/coverage` test directory.
---
 src/bootstrap/src/core/build_steps/test.rs    | 22 +++++++++----------
 src/bootstrap/src/core/builder.rs             |  4 ++--
 src/tools/compiletest/src/common.rs           |  4 ++--
 src/tools/compiletest/src/header.rs           |  4 ++--
 src/tools/compiletest/src/runtest.rs          | 14 ++++++------
 .../auxiliary/doctest_crate.rs                |  0
 .../doctest.coverage                          |  0
 .../doctest.rs                                |  0
 tests/coverage/README.md                      |  6 ++---
 9 files changed, 27 insertions(+), 27 deletions(-)
 rename tests/{run-coverage-rustdoc => coverage-run-rustdoc}/auxiliary/doctest_crate.rs (100%)
 rename tests/{run-coverage-rustdoc => coverage-run-rustdoc}/doctest.coverage (100%)
 rename tests/{run-coverage-rustdoc => coverage-run-rustdoc}/doctest.rs (100%)

diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index 39667d16b7b6d..c034e5c9d69e6 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -1434,7 +1434,7 @@ impl Step for Coverage {
 
     fn run(self, builder: &Builder<'_>) {
         self.run_unified_suite(builder, CoverageMap::MODE);
-        self.run_unified_suite(builder, RunCoverage::MODE);
+        self.run_unified_suite(builder, CoverageRun::MODE);
     }
 }
 
@@ -1444,16 +1444,16 @@ coverage_test_alias!(CoverageMap {
     default: true,
     only_hosts: false,
 });
-coverage_test_alias!(RunCoverage {
-    alias_and_mode: "run-coverage",
+coverage_test_alias!(CoverageRun {
+    alias_and_mode: "coverage-run",
     default: true,
     only_hosts: true,
 });
 
-host_test!(RunCoverageRustdoc {
-    path: "tests/run-coverage-rustdoc",
-    mode: "run-coverage",
-    suite: "run-coverage-rustdoc"
+host_test!(CoverageRunRustdoc {
+    path: "tests/coverage-run-rustdoc",
+    mode: "coverage-run",
+    suite: "coverage-run-rustdoc"
 });
 
 // For the mir-opt suite we do not use macros, as we need custom behavior when blessing.
@@ -1640,7 +1640,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the
             || (mode == "ui" && is_rustdoc)
             || mode == "js-doc-test"
             || mode == "rustdoc-json"
-            || suite == "run-coverage-rustdoc"
+            || suite == "coverage-run-rustdoc"
         {
             cmd.arg("--rustdoc-path").arg(builder.rustdoc(compiler));
         }
@@ -1662,7 +1662,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the
             cmd.arg("--coverage-dump-path").arg(coverage_dump);
         }
 
-        if mode == "run-coverage" {
+        if mode == "coverage-run" {
             // The demangler doesn't need the current compiler, so we can avoid
             // unnecessary rebuilds by using the bootstrap compiler instead.
             let rust_demangler = builder
@@ -1854,11 +1854,11 @@ note: if you're sure you want to do this, please open an issue as to why. In the
             }
 
             if !builder.config.dry_run()
-                && (matches!(suite, "run-make" | "run-make-fulldeps") || mode == "run-coverage")
+                && (matches!(suite, "run-make" | "run-make-fulldeps") || mode == "coverage-run")
             {
                 // The llvm/bin directory contains many useful cross-platform
                 // tools. Pass the path to run-make tests so they can use them.
-                // (The run-coverage tests also need these tools to process
+                // (The coverage-run tests also need these tools to process
                 // coverage reports.)
                 let llvm_bin_path = llvm_config
                     .parent()
diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs
index 38eb46332738a..1b6ba89aadd2b 100644
--- a/src/bootstrap/src/core/builder.rs
+++ b/src/bootstrap/src/core/builder.rs
@@ -729,7 +729,7 @@ impl<'a> Builder<'a> {
                 test::RunPassValgrind,
                 test::Coverage,
                 test::CoverageMap,
-                test::RunCoverage,
+                test::CoverageRun,
                 test::MirOpt,
                 test::Codegen,
                 test::CodegenUnits,
@@ -740,7 +740,7 @@ impl<'a> Builder<'a> {
                 test::CodegenCranelift,
                 test::CodegenGCC,
                 test::Rustdoc,
-                test::RunCoverageRustdoc,
+                test::CoverageRunRustdoc,
                 test::Pretty,
                 test::Crate,
                 test::CrateLibrustc,
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index a908218fff14e..bdf8c35e73b58 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -67,7 +67,7 @@ string_enum! {
         MirOpt => "mir-opt",
         Assembly => "assembly",
         CoverageMap => "coverage-map",
-        RunCoverage => "run-coverage",
+        CoverageRun => "coverage-run",
     }
 }
 
@@ -91,7 +91,7 @@ impl Mode {
         // Coverage tests use the same test files for multiple test modes,
         // so each mode should have a separate output directory.
         match self {
-            CoverageMap | RunCoverage => self.to_str(),
+            CoverageMap | CoverageRun => self.to_str(),
             _ => "",
         }
     }
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 948439d6e79d2..d6516cff63fb4 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -911,11 +911,11 @@ pub fn make_test_description<R: Read>(
     let mut should_fail = false;
 
     let extra_directives: &[&str] = match config.mode {
-        // The run-coverage tests are treated as having these extra directives,
+        // The coverage-run tests are treated as having these extra directives,
         // without needing to specify them manually in every test file.
         // (Some of the comments below have been copied over from
         // `tests/run-make/coverage-reports/Makefile`, which no longer exists.)
-        Mode::RunCoverage => {
+        Mode::CoverageRun => {
             &[
                 "needs-profiler-support",
                 // FIXME(mati865): MinGW GCC miscompiles compiler-rt profiling library but with Clang it works
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index cbcd3dc2fdede..63e8ba7c79f9f 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -6,7 +6,7 @@ use crate::common::{Assembly, Incremental, JsDocTest, MirOpt, RunMake, RustdocJs
 use crate::common::{Codegen, CodegenUnits, DebugInfo, Debugger, Rustdoc};
 use crate::common::{CompareMode, FailMode, PassMode};
 use crate::common::{Config, TestPaths};
-use crate::common::{CoverageMap, Pretty, RunCoverage, RunPassValgrind};
+use crate::common::{CoverageMap, CoverageRun, Pretty, RunPassValgrind};
 use crate::common::{UI_COVERAGE, UI_COVERAGE_MAP, UI_RUN_STDERR, UI_RUN_STDOUT};
 use crate::compute_diff::{write_diff, write_filtered_diff};
 use crate::errors::{self, Error, ErrorKind};
@@ -257,7 +257,7 @@ impl<'test> TestCx<'test> {
             Assembly => self.run_assembly_test(),
             JsDocTest => self.run_js_doc_test(),
             CoverageMap => self.run_coverage_map_test(),
-            RunCoverage => self.run_coverage_test(),
+            CoverageRun => self.run_coverage_run_test(),
         }
     }
 
@@ -510,7 +510,7 @@ impl<'test> TestCx<'test> {
         }
     }
 
-    fn run_coverage_test(&self) {
+    fn run_coverage_run_test(&self) {
         let should_run = self.run_if_enabled();
         let proc_res = self.compile_test(should_run, Emit::None);
 
@@ -549,7 +549,7 @@ impl<'test> TestCx<'test> {
         let mut profraw_paths = vec![profraw_path];
         let mut bin_paths = vec![self.make_exe_name()];
 
-        if self.config.suite == "run-coverage-rustdoc" {
+        if self.config.suite == "coverage-run-rustdoc" {
             self.run_doctests_for_coverage(&mut profraw_paths, &mut bin_paths);
         }
 
@@ -2193,7 +2193,7 @@ impl<'test> TestCx<'test> {
             || self.is_vxworks_pure_static()
             || self.config.target.contains("bpf")
             || !self.config.target_cfg().dynamic_linking
-            || matches!(self.config.mode, CoverageMap | RunCoverage)
+            || matches!(self.config.mode, CoverageMap | CoverageRun)
         {
             // We primarily compile all auxiliary libraries as dynamic libraries
             // to avoid code size bloat and large binaries as much as possible
@@ -2395,7 +2395,7 @@ impl<'test> TestCx<'test> {
                     }
                 }
                 DebugInfo => { /* debuginfo tests must be unoptimized */ }
-                CoverageMap | RunCoverage => {
+                CoverageMap | CoverageRun => {
                     // Coverage mappings and coverage reports are affected by
                     // optimization level, so they ignore the optimize-tests
                     // setting and set an optimization level in their mode's
@@ -2478,7 +2478,7 @@ impl<'test> TestCx<'test> {
                 // by `compile-flags`.
                 rustc.arg("-Copt-level=2");
             }
-            RunCoverage => {
+            CoverageRun => {
                 rustc.arg("-Cinstrument-coverage");
                 // Coverage reports are sometimes sensitive to optimizations,
                 // and the current snapshots assume `opt-level=2` unless
diff --git a/tests/run-coverage-rustdoc/auxiliary/doctest_crate.rs b/tests/coverage-run-rustdoc/auxiliary/doctest_crate.rs
similarity index 100%
rename from tests/run-coverage-rustdoc/auxiliary/doctest_crate.rs
rename to tests/coverage-run-rustdoc/auxiliary/doctest_crate.rs
diff --git a/tests/run-coverage-rustdoc/doctest.coverage b/tests/coverage-run-rustdoc/doctest.coverage
similarity index 100%
rename from tests/run-coverage-rustdoc/doctest.coverage
rename to tests/coverage-run-rustdoc/doctest.coverage
diff --git a/tests/run-coverage-rustdoc/doctest.rs b/tests/coverage-run-rustdoc/doctest.rs
similarity index 100%
rename from tests/run-coverage-rustdoc/doctest.rs
rename to tests/coverage-run-rustdoc/doctest.rs
diff --git a/tests/coverage/README.md b/tests/coverage/README.md
index f1e403c65e35e..c72aa69c0ce07 100644
--- a/tests/coverage/README.md
+++ b/tests/coverage/README.md
@@ -2,8 +2,8 @@ The tests in this directory are shared by two different test modes, and can be
 run in multiple different ways:
 
 - `./x.py test coverage-map` (compiles to LLVM IR and checks coverage mappings)
-- `./x.py test run-coverage` (runs a test binary and checks its coverage report)
-- `./x.py test coverage` (runs both `coverage-map` and `run-coverage`)
+- `./x.py test coverage-run` (runs a test binary and checks its coverage report)
+- `./x.py test coverage` (runs both `coverage-map` and `coverage-run`)
 
 ## Maintenance note
 
@@ -11,6 +11,6 @@ These tests can be sensitive to small changes in MIR spans or MIR control flow,
 especially in HIR-to-MIR lowering or MIR optimizations.
 
 If you haven't touched the coverage code directly, and the tests still pass in
-`run-coverage` mode, then it should usually be OK to just re-bless the mappings
+`coverage-run` mode, then it should usually be OK to just re-bless the mappings
 as necessary with `./x.py test coverage-map --bless`, without worrying too much
 about the exact changes.

From b9b7982f720c5ce828a74395864357edf76243f8 Mon Sep 17 00:00:00 2001
From: Qiu Chaofan <qcf@ecnelises.com>
Date: Tue, 1 Aug 2023 11:37:23 +0800
Subject: [PATCH 08/11] Add AIX platform-support doc

---
 src/doc/rustc/src/SUMMARY.md              |  1 +
 src/doc/rustc/src/platform-support.md     |  2 +-
 src/doc/rustc/src/platform-support/aix.md | 26 +++++++++++++++++++++++
 3 files changed, 28 insertions(+), 1 deletion(-)
 create mode 100644 src/doc/rustc/src/platform-support/aix.md

diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md
index 8b4d673d831ce..1b27b77b3e6b2 100644
--- a/src/doc/rustc/src/SUMMARY.md
+++ b/src/doc/rustc/src/SUMMARY.md
@@ -41,6 +41,7 @@
     - [mipsel-sony-psx](platform-support/mipsel-sony-psx.md)
     - [mipsisa\*r6\*-unknown-linux-gnu\*](platform-support/mips-release-6.md)
     - [nvptx64-nvidia-cuda](platform-support/nvptx64-nvidia-cuda.md)
+    - [powerpc64-ibm-aix](platform-support/aix.md)
     - [riscv32imac-unknown-xous-elf](platform-support/riscv32imac-unknown-xous-elf.md)
     - [sparc-unknown-none-elf](./platform-support/sparc-unknown-none-elf.md)
     - [*-pc-windows-gnullvm](platform-support/pc-windows-gnullvm.md)
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index 6a979869a59a6..907e9c59f316c 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -310,7 +310,7 @@ target | std | host | notes
 `powerpc64-wrs-vxworks` | ? |  |
 `powerpc64le-unknown-linux-musl` | ? |  |
 [`powerpc64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/powerpc64
-`powerpc64-ibm-aix` | ? |  | 64-bit AIX (7.2 and newer)
+[`powerpc64-ibm-aix`](platform-support/aix.md) | ? |  | 64-bit AIX (7.2 and newer)
 `riscv32gc-unknown-linux-gnu` |   |   | RISC-V Linux (kernel 5.4, glibc 2.33)
 `riscv32gc-unknown-linux-musl` |   |   | RISC-V Linux (kernel 5.4, musl + RISCV32 support patches)
 `riscv32im-unknown-none-elf` | * |  | Bare RISC-V (RV32IM ISA)
diff --git a/src/doc/rustc/src/platform-support/aix.md b/src/doc/rustc/src/platform-support/aix.md
new file mode 100644
index 0000000000000..c3ce71a183568
--- /dev/null
+++ b/src/doc/rustc/src/platform-support/aix.md
@@ -0,0 +1,26 @@
+# `powerpc64-ibm-aix`
+
+**Tier: 3**
+
+Rust for AIX operating system, currently only 64-bit PowerPC is supported.
+
+## Target maintainers
+
+- QIU Chaofan `qiucofan@cn.ibm.com`, https://github.com/ecnelises
+- Kai LUO, `lkail@cn.ibm.com`, https://github.com/bzEq
+
+## Requirements
+
+This target supports host tools, std and alloc. This target cannot be cross-compiled as for now, mainly because of the unavailability of system linker on other platforms.
+
+Binary built for this target is expected to run on Power7 or newer CPU, and AIX 7.2 or newer version.
+
+Binary format of this platform is [XCOFF](https://www.ibm.com/docs/en/aix/7.2?topic=formats-xcoff-object-file-format). Archive file format is ['AIX big format'](https://www.ibm.com/docs/en/aix/7.2?topic=formats-ar-file-format-big).
+
+## Testing
+
+This target supports running test suites natively, but it's not available to cross-compile and execute in emulator.
+
+## Interoperability with C code
+
+This target supports C code. C code compiled by XL, Open XL and Clang are compatible with Rust. Typical triple of AIX on 64-bit PowerPC of these compilers are also `powerpc64-ibm-aix`.

From 93b1c1f329a07296c920bf41a105850c9f442a3b Mon Sep 17 00:00:00 2001
From: onur-ozkan <work@onurozkan.dev>
Date: Fri, 27 Oct 2023 06:51:12 +0300
Subject: [PATCH 09/11] handle the case when the change-id isn't found

When we switch back and forth between the old and recent branches,
if there was a breaking change in the bootstrap configuration in
between, we have to update the change-id in the build configuration
with each checkout, which can be exhausting. This change fixes that.

Signed-off-by: onur-ozkan <work@onurozkan.dev>
---
 src/bootstrap/src/bin/main.rs | 20 ++++++++++++--------
 src/bootstrap/src/lib.rs      | 17 +++++++++++++----
 2 files changed, 25 insertions(+), 12 deletions(-)

diff --git a/src/bootstrap/src/bin/main.rs b/src/bootstrap/src/bin/main.rs
index d87fb6a9cef0c..e0caecca5c076 100644
--- a/src/bootstrap/src/bin/main.rs
+++ b/src/bootstrap/src/bin/main.rs
@@ -109,31 +109,35 @@ fn check_version(config: &Config) -> Option<String> {
     }
 
     let latest_config_id = CONFIG_CHANGE_HISTORY.last().unwrap();
-    let suggestion = if let Some(id) = config.change_id {
+    if let Some(id) = config.change_id {
         if &id != latest_config_id {
-            msg.push_str("WARNING: there have been changes to x.py since you last updated.\n");
             let change_links: Vec<String> = find_recent_config_change_ids(id)
                 .iter()
                 .map(|id| format!("https://github.com/rust-lang/rust/pull/{id}"))
                 .collect();
             if !change_links.is_empty() {
+                msg.push_str("WARNING: there have been changes to x.py since you last updated.\n");
                 msg.push_str("To see more detail about these changes, visit the following PRs:\n");
+
                 for link in change_links {
                     msg.push_str(&format!("  - {link}\n"));
                 }
+
+                msg.push_str("WARNING: there have been changes to x.py since you last updated.\n");
+
+                msg.push_str("note: to silence this warning, ");
+                msg.push_str(&format!(
+                    "update `config.toml` to use `change-id = {latest_config_id}` instead"
+                ));
             }
-            msg.push_str("WARNING: there have been changes to x.py since you last updated.\n");
-            format!("update `config.toml` to use `change-id = {latest_config_id}` instead")
         } else {
             return None;
         }
     } else {
         msg.push_str("WARNING: The `change-id` is missing in the `config.toml`. This means that you will not be able to track the major changes made to the bootstrap configurations.\n");
-        format!("add `change-id = {latest_config_id}` at the top of `config.toml`")
+        msg.push_str("note: to silence this warning, ");
+        msg.push_str(&format!("add `change-id = {latest_config_id}` at the top of `config.toml`"));
     };
 
-    msg.push_str("note: to silence this warning, ");
-    msg.push_str(&suggestion);
-
     Some(msg)
 }
diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs
index 27922c9fbbe77..0734c127677aa 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -1849,10 +1849,19 @@ fn envify(s: &str) -> String {
 }
 
 pub fn find_recent_config_change_ids(current_id: usize) -> Vec<usize> {
-    let index = CONFIG_CHANGE_HISTORY
-        .iter()
-        .position(|&id| id == current_id)
-        .expect(&format!("Value `{}` was not found in `CONFIG_CHANGE_HISTORY`.", current_id));
+    if !CONFIG_CHANGE_HISTORY.contains(&current_id) {
+        // If the current change-id is greater than the most recent one,
+        // return an empty list; otherwise, return the full list.
+        if let Some(max_id) = CONFIG_CHANGE_HISTORY.iter().max() {
+            if &current_id > max_id {
+                return Vec::new();
+            }
+        }
+
+        return CONFIG_CHANGE_HISTORY.to_vec();
+    }
+
+    let index = CONFIG_CHANGE_HISTORY.iter().position(|&id| id == current_id).unwrap();
 
     CONFIG_CHANGE_HISTORY
         .iter()

From 820e8334a8bd01800703cb84dbe65e809787490b Mon Sep 17 00:00:00 2001
From: onur-ozkan <work@onurozkan.dev>
Date: Fri, 27 Oct 2023 07:03:48 +0300
Subject: [PATCH 10/11] bootstrap: improve `fn check_version`

Signed-off-by: onur-ozkan <work@onurozkan.dev>
---
 src/bootstrap/src/bin/main.rs | 42 +++++++++++++++++------------------
 1 file changed, 21 insertions(+), 21 deletions(-)

diff --git a/src/bootstrap/src/bin/main.rs b/src/bootstrap/src/bin/main.rs
index e0caecca5c076..6c0d8c8c55011 100644
--- a/src/bootstrap/src/bin/main.rs
+++ b/src/bootstrap/src/bin/main.rs
@@ -110,29 +110,29 @@ fn check_version(config: &Config) -> Option<String> {
 
     let latest_config_id = CONFIG_CHANGE_HISTORY.last().unwrap();
     if let Some(id) = config.change_id {
-        if &id != latest_config_id {
-            let change_links: Vec<String> = find_recent_config_change_ids(id)
-                .iter()
-                .map(|id| format!("https://github.com/rust-lang/rust/pull/{id}"))
-                .collect();
-            if !change_links.is_empty() {
-                msg.push_str("WARNING: there have been changes to x.py since you last updated.\n");
-                msg.push_str("To see more detail about these changes, visit the following PRs:\n");
-
-                for link in change_links {
-                    msg.push_str(&format!("  - {link}\n"));
-                }
-
-                msg.push_str("WARNING: there have been changes to x.py since you last updated.\n");
-
-                msg.push_str("note: to silence this warning, ");
-                msg.push_str(&format!(
-                    "update `config.toml` to use `change-id = {latest_config_id}` instead"
-                ));
-            }
-        } else {
+        if &id == latest_config_id {
             return None;
         }
+
+        let change_links: Vec<String> = find_recent_config_change_ids(id)
+            .iter()
+            .map(|id| format!("https://github.com/rust-lang/rust/pull/{id}"))
+            .collect();
+        if !change_links.is_empty() {
+            msg.push_str("WARNING: there have been changes to x.py since you last updated.\n");
+            msg.push_str("To see more detail about these changes, visit the following PRs:\n");
+
+            for link in change_links {
+                msg.push_str(&format!("  - {link}\n"));
+            }
+
+            msg.push_str("WARNING: there have been changes to x.py since you last updated.\n");
+
+            msg.push_str("note: to silence this warning, ");
+            msg.push_str(&format!(
+                "update `config.toml` to use `change-id = {latest_config_id}` instead"
+            ));
+        }
     } else {
         msg.push_str("WARNING: The `change-id` is missing in the `config.toml`. This means that you will not be able to track the major changes made to the bootstrap configurations.\n");
         msg.push_str("note: to silence this warning, ");

From 966c1028d340e164f3849cda1d2e55c12bc1b800 Mon Sep 17 00:00:00 2001
From: onur-ozkan <work@onurozkan.dev>
Date: Tue, 7 Nov 2023 09:29:19 +0300
Subject: [PATCH 11/11] bootstrap: add more detail on change-id comments

Signed-off-by: onur-ozkan <work@onurozkan.dev>
---
 src/bootstrap/src/lib.rs | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs
index 0734c127677aa..fe0f1bc822392 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -75,8 +75,9 @@ const LLD_FILE_NAMES: &[&str] = &["ld.lld", "ld64.lld", "lld-link", "wasm-ld"];
 /// You can visit `https://github.com/rust-lang/rust/pull/{any-id-from-the-list}` to
 /// check for more details regarding each change.
 ///
-/// If you make any major changes (such as adding new values or changing default values), please
-/// ensure that the associated PR ID is added to the end of this list.
+/// If you make any major changes (such as adding new values or changing default values),
+/// please ensure that the associated PR ID is added to the end of this list.
+/// This is necessary because the list must be sorted by the merge date.
 pub const CONFIG_CHANGE_HISTORY: &[usize] = &[115898, 116998, 117435];
 
 /// Extra --check-cfg to add when building
@@ -1850,8 +1851,10 @@ fn envify(s: &str) -> String {
 
 pub fn find_recent_config_change_ids(current_id: usize) -> Vec<usize> {
     if !CONFIG_CHANGE_HISTORY.contains(&current_id) {
-        // If the current change-id is greater than the most recent one,
-        // return an empty list; otherwise, return the full list.
+        // If the current change-id is greater than the most recent one, return
+        // an empty list (it may be due to switching from a recent branch to an
+        // older one); otherwise, return the full list (assuming the user provided
+        // the incorrect change-id by accident).
         if let Some(max_id) = CONFIG_CHANGE_HISTORY.iter().max() {
             if &current_id > max_id {
                 return Vec::new();