Skip to content

Commit 3d72793

Browse files
committed
Auto merge of rust-lang#120060 - saethlin:mir-opt-bless-targets, r=wesleywiser
Use the same mir-opt bless targets on all platforms This undoes some of the implementation in rust-lang#119035, but not the effect. Sorry for the churn, I've learned a lot about how all this works over the past few weeks. The objective here is to make `x test mir-opt --bless` use the same set of targets on all platforms. It didn't do that from the start because bootstrap assumes that a target linker is available, so the availability of cross-linkers is how we ended up with `MIR_OPT_BLESS_TARGET_MAPPING` and poor support for blessing mir-opt tests from Aarch64 MacOS. This PR corrects that. So I've adjusted the bless targets for mir-opt tests, as well as tweaked some of the logic in bootstrap about linker configuration so that we don't try to access the cache of cc/linker configuration when doing the mir-opt builds. While working on that I realized that if I swapped from the `cargo rustc -p std` strategy to `cargo check` on the sysroot, I could use the existing code for check builds to bypass some linker logic. Sweet. But just doing that doesn't work, because then mir-opt tests complain that they can't find an rlib for any of the standard library crates. That happens because nearly all the mir-opt tests are attempting to build `CrateType::Executable`. We already have all the MIR required for mir-opt tests from the rmeta files, but since rustc think we're trying to build an executable it demands we have access to all the upstream monomorphizations that only exist in rlibs, not the meta files in a MIR-only sysroot. So to fix that, I've swapped all the mir-opt tests be passed `--crate-type=rlib`. That works, but leaves us with a few broken mir-opt tests which I've blessed or fixed up; we also lose MIR for some functions so I added `-Clink-dead-code` to paper over that. The inlining changes are because changing the crate-type perturbs the hashes that are compared here to sometimes let us do inlining even in a possibly-recursive call: https://github.com/rust-lang/rust/blob/4cb17b4e78e0540e49d2da884cc621a6bf6f47fa/compiler/rustc_mir_transform/src/inline.rs#L332-L341
2 parents 586893c + 3611d5a commit 3d72793

15 files changed

+225
-268
lines changed

Diff for: src/bootstrap/src/core/build_steps/compile.rs

+24-10
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,20 @@ impl Std {
9797
is_for_mir_opt_tests: false,
9898
}
9999
}
100+
101+
fn copy_extra_objects(
102+
&self,
103+
builder: &Builder<'_>,
104+
compiler: &Compiler,
105+
target: TargetSelection,
106+
) -> Vec<(PathBuf, DependencyType)> {
107+
let mut deps = Vec::new();
108+
if !self.is_for_mir_opt_tests {
109+
deps.extend(copy_third_party_objects(builder, &compiler, target));
110+
deps.extend(copy_self_contained_objects(builder, &compiler, target));
111+
}
112+
deps
113+
}
100114
}
101115

102116
impl Step for Std {
@@ -159,8 +173,7 @@ impl Step for Std {
159173
{
160174
builder.info("WARNING: Using a potentially old libstd. This may not behave well.");
161175

162-
copy_third_party_objects(builder, &compiler, target);
163-
copy_self_contained_objects(builder, &compiler, target);
176+
self.copy_extra_objects(builder, &compiler, target);
164177

165178
builder.ensure(StdLink::from_std(self, compiler));
166179
return;
@@ -193,15 +206,13 @@ impl Step for Std {
193206

194207
// Even if we're not building std this stage, the new sysroot must
195208
// still contain the third party objects needed by various targets.
196-
copy_third_party_objects(builder, &compiler, target);
197-
copy_self_contained_objects(builder, &compiler, target);
209+
self.copy_extra_objects(builder, &compiler, target);
198210

199211
builder.ensure(StdLink::from_std(self, compiler_to_use));
200212
return;
201213
}
202214

203-
target_deps.extend(copy_third_party_objects(builder, &compiler, target));
204-
target_deps.extend(copy_self_contained_objects(builder, &compiler, target));
215+
target_deps.extend(self.copy_extra_objects(builder, &compiler, target));
205216

206217
// The LLD wrappers and `rust-lld` are self-contained linking components that can be
207218
// necessary to link the stdlib on some targets. We'll also need to copy these binaries to
@@ -222,10 +233,13 @@ impl Step for Std {
222233
}
223234
}
224235

236+
// We build a sysroot for mir-opt tests using the same trick that Miri does: A check build
237+
// with -Zalways-encode-mir. This frees us from the need to have a target linker, and the
238+
// fact that this is a check build integrates nicely with run_cargo.
225239
let mut cargo = if self.is_for_mir_opt_tests {
226-
let mut cargo = builder.cargo(compiler, Mode::Std, SourceType::InTree, target, "rustc");
227-
cargo.arg("-p").arg("std").arg("--crate-type=lib");
228-
std_cargo(builder, target, compiler.stage, &mut cargo);
240+
let mut cargo = builder.cargo(compiler, Mode::Std, SourceType::InTree, target, "check");
241+
cargo.rustflag("-Zalways-encode-mir");
242+
cargo.arg("--manifest-path").arg(builder.src.join("library/sysroot/Cargo.toml"));
229243
cargo
230244
} else {
231245
let mut cargo = builder.cargo(compiler, Mode::Std, SourceType::InTree, target, "build");
@@ -257,7 +271,7 @@ impl Step for Std {
257271
vec![],
258272
&libstd_stamp(builder, compiler, target),
259273
target_deps,
260-
false,
274+
self.is_for_mir_opt_tests, // is_check
261275
false,
262276
);
263277

Diff for: src/bootstrap/src/core/build_steps/test.rs

+37-79
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ use crate::core::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step};
2525
use crate::core::config::flags::get_completion;
2626
use crate::core::config::flags::Subcommand;
2727
use crate::core::config::TargetSelection;
28-
use crate::utils;
2928
use crate::utils::cache::{Interned, INTERNER};
3029
use crate::utils::exec::BootstrapCommand;
3130
use crate::utils::helpers::{
@@ -38,23 +37,6 @@ use crate::{envify, CLang, DocTests, GitRepo, Mode};
3837

3938
const ADB_TEST_DIR: &str = "/data/local/tmp/work";
4039

41-
// mir-opt tests have different variants depending on whether a target is 32bit or 64bit, and
42-
// blessing them requires blessing with each target. To aid developers, when blessing the mir-opt
43-
// test suite the corresponding target of the opposite pointer size is also blessed.
44-
//
45-
// This array serves as the known mappings between 32bit and 64bit targets. If you're developing on
46-
// a target where a target with the opposite pointer size exists, feel free to add it here.
47-
const MIR_OPT_BLESS_TARGET_MAPPING: &[(&str, &str)] = &[
48-
// (32bit, 64bit)
49-
("i686-unknown-linux-gnu", "x86_64-unknown-linux-gnu"),
50-
("i686-unknown-linux-musl", "x86_64-unknown-linux-musl"),
51-
("i686-pc-windows-msvc", "x86_64-pc-windows-msvc"),
52-
("i686-pc-windows-gnu", "x86_64-pc-windows-gnu"),
53-
// ARM Macs don't have a corresponding 32-bit target that they can (easily)
54-
// build for, so there is no entry for "aarch64-apple-darwin" here.
55-
// Likewise, i686 for macOS is no longer possible to build.
56-
];
57-
5840
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
5941
pub struct CrateBootstrap {
6042
path: Interned<PathBuf>,
@@ -1487,46 +1469,18 @@ impl Step for MirOpt {
14871469
})
14881470
};
14891471

1490-
// We use custom logic to bless the mir-opt suite: mir-opt tests have multiple variants
1491-
// (32bit vs 64bit, and panic=abort vs panic=unwind), and all of them needs to be blessed.
1492-
// When blessing, we try best-effort to also bless the other variants, to aid developers.
14931472
if builder.config.cmd.bless() {
1494-
let targets = MIR_OPT_BLESS_TARGET_MAPPING
1495-
.iter()
1496-
.filter(|(target_32bit, target_64bit)| {
1497-
*target_32bit == &*self.target.triple || *target_64bit == &*self.target.triple
1498-
})
1499-
.next()
1500-
.map(|(target_32bit, target_64bit)| {
1501-
let target_32bit = TargetSelection::from_user(target_32bit);
1502-
let target_64bit = TargetSelection::from_user(target_64bit);
1503-
1504-
// Running compiletest requires a C compiler to be available, but it might not
1505-
// have been detected by bootstrap if the target we're testing wasn't in the
1506-
// --target flags.
1507-
if !builder.cc.borrow().contains_key(&target_32bit) {
1508-
utils::cc_detect::find_target(builder, target_32bit);
1509-
}
1510-
if !builder.cc.borrow().contains_key(&target_64bit) {
1511-
utils::cc_detect::find_target(builder, target_64bit);
1512-
}
1473+
// All that we really need to do is cover all combinations of 32/64-bit and unwind/abort,
1474+
// but while we're at it we might as well flex our cross-compilation support. This
1475+
// selection covers all our tier 1 operating systems and architectures using only tier
1476+
// 1 targets.
15131477

1514-
vec![target_32bit, target_64bit]
1515-
})
1516-
.unwrap_or_else(|| {
1517-
eprintln!(
1518-
"\
1519-
Note that not all variants of mir-opt tests are going to be blessed, as no mapping between
1520-
a 32bit and a 64bit target was found for {target}.
1521-
You can add that mapping by changing MIR_OPT_BLESS_TARGET_MAPPING in src/bootstrap/test.rs",
1522-
target = self.target,
1523-
);
1524-
vec![self.target]
1525-
});
1526-
1527-
for target in targets {
1528-
run(target);
1478+
for target in ["aarch64-unknown-linux-gnu", "i686-pc-windows-msvc"] {
1479+
run(TargetSelection::from_user(target));
1480+
}
15291481

1482+
for target in ["x86_64-apple-darwin", "i686-unknown-linux-musl"] {
1483+
let target = TargetSelection::from_user(target);
15301484
let panic_abort_target = builder.ensure(MirOptPanicAbortSyntheticTarget {
15311485
compiler: self.compiler,
15321486
base: target,
@@ -1616,27 +1570,27 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
16161570
.ensure(dist::DebuggerScripts { sysroot: builder.sysroot(compiler), host: target });
16171571
}
16181572

1619-
if suite == "mir-opt" {
1620-
builder.ensure(compile::Std::new_for_mir_opt_tests(compiler, target));
1621-
} else {
1622-
builder.ensure(compile::Std::new(compiler, target));
1623-
}
1573+
// Also provide `rust_test_helpers` for the host.
1574+
builder.ensure(TestHelpers { target: compiler.host });
16241575

16251576
// ensure that `libproc_macro` is available on the host.
16261577
builder.ensure(compile::Std::new(compiler, compiler.host));
16271578

1628-
// Also provide `rust_test_helpers` for the host.
1629-
builder.ensure(TestHelpers { target: compiler.host });
1630-
16311579
// As well as the target, except for plain wasm32, which can't build it
16321580
if suite != "mir-opt" && !target.contains("wasm") && !target.contains("emscripten") {
16331581
builder.ensure(TestHelpers { target });
16341582
}
16351583

1636-
builder.ensure(RemoteCopyLibs { compiler, target });
1637-
16381584
let mut cmd = builder.tool_cmd(Tool::Compiletest);
16391585

1586+
if suite == "mir-opt" {
1587+
builder.ensure(compile::Std::new_for_mir_opt_tests(compiler, target));
1588+
} else {
1589+
builder.ensure(compile::Std::new(compiler, target));
1590+
}
1591+
1592+
builder.ensure(RemoteCopyLibs { compiler, target });
1593+
16401594
// compiletest currently has... a lot of arguments, so let's just pass all
16411595
// of them!
16421596

@@ -1745,11 +1699,13 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
17451699
flags.push(format!("-Cdebuginfo={}", builder.config.rust_debuginfo_level_tests));
17461700
flags.extend(builder.config.cmd.rustc_args().iter().map(|s| s.to_string()));
17471701

1748-
if let Some(linker) = builder.linker(target) {
1749-
cmd.arg("--target-linker").arg(linker);
1750-
}
1751-
if let Some(linker) = builder.linker(compiler.host) {
1752-
cmd.arg("--host-linker").arg(linker);
1702+
if suite != "mir-opt" {
1703+
if let Some(linker) = builder.linker(target) {
1704+
cmd.arg("--target-linker").arg(linker);
1705+
}
1706+
if let Some(linker) = builder.linker(compiler.host) {
1707+
cmd.arg("--host-linker").arg(linker);
1708+
}
17531709
}
17541710

17551711
let mut hostflags = flags.clone();
@@ -1936,15 +1892,17 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
19361892
cmd.arg("--remote-test-client").arg(builder.tool_exe(Tool::RemoteTestClient));
19371893
}
19381894

1939-
// Running a C compiler on MSVC requires a few env vars to be set, to be
1940-
// sure to set them here.
1941-
//
1942-
// Note that if we encounter `PATH` we make sure to append to our own `PATH`
1943-
// rather than stomp over it.
1944-
if !builder.config.dry_run() && target.is_msvc() {
1945-
for &(ref k, ref v) in builder.cc.borrow()[&target].env() {
1946-
if k != "PATH" {
1947-
cmd.env(k, v);
1895+
if suite != "mir-opt" {
1896+
// Running a C compiler on MSVC requires a few env vars to be set, to be
1897+
// sure to set them here.
1898+
//
1899+
// Note that if we encounter `PATH` we make sure to append to our own `PATH`
1900+
// rather than stomp over it.
1901+
if !builder.config.dry_run() && target.is_msvc() {
1902+
for &(ref k, ref v) in builder.cc.borrow()[&target].env() {
1903+
if k != "PATH" {
1904+
cmd.env(k, v);
1905+
}
19481906
}
19491907
}
19501908
}

0 commit comments

Comments
 (0)