Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/bootstrap/src/core/build_steps/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,8 +218,10 @@ impl CommandLineStep for Std {

if Self::should_be_uplifted_from_stage_1(builder, build_compiler.stage) {
let build_compiler_for_std_to_uplift = builder.compiler(1, builder.host_target);
let stage_1_stamp = builder.std(build_compiler_for_std_to_uplift, target);

let stage_1_stamp = builder.ensure(
Std::new(build_compiler_for_std_to_uplift, target)
.is_for_mir_opt_tests(self.is_for_mir_opt_tests),
);
let msg = if build_compiler_for_std_to_uplift.host == target {
format!(
"Uplifting library (stage{} -> stage{stage})",
Expand Down
59 changes: 46 additions & 13 deletions src/bootstrap/src/core/build_steps/synthetic_targets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,40 @@ use crate::core::builder::{Builder, Step};
use crate::core::compiler::Compiler;
use crate::core::config::TargetSelection;

/// Note that this currently only contains panic strategies that we somehow use in bootstrap, not
/// all possible strategires supported by rustc.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub(crate) enum PanicStrategy {
Unwind,
Abort,
}
Comment thread
Kobzol marked this conversation as resolved.

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub(crate) struct MirOptPanicAbortSyntheticTarget {
pub(crate) struct SyntheticTargetWithPanicStrategy {
pub(crate) compiler: Compiler,
pub(crate) base: TargetSelection,
pub(crate) strategy: PanicStrategy,
}

impl SyntheticTargetWithPanicStrategy {
pub(crate) fn panic_abort(compiler: Compiler, base: TargetSelection) -> Self {
Self { compiler, base, strategy: PanicStrategy::Abort }
}
pub(crate) fn panic_unwind(compiler: Compiler, base: TargetSelection) -> Self {
Self { compiler, base, strategy: PanicStrategy::Unwind }
}
}

impl Step for MirOptPanicAbortSyntheticTarget {
impl Step for SyntheticTargetWithPanicStrategy {
type Output = TargetSelection;

fn run(self, builder: &Builder<'_>) -> Self::Output {
let strategy = match self.strategy {
PanicStrategy::Unwind => "unwind",
PanicStrategy::Abort => "abort",
};
Comment thread
jieyouxu marked this conversation as resolved.
create_synthetic_target(builder, self.compiler, "miropt-abort", self.base, |spec| {
spec.insert("panic-strategy".into(), "abort".into());
spec.insert("panic-strategy".into(), strategy.into());
})
}
}
Expand All @@ -49,16 +71,7 @@ fn create_synthetic_target(
return TargetSelection::create_synthetic(&name, path.to_str().unwrap());
}

let mut cmd = builder.rustc_cmd(compiler);
cmd.arg("--target").arg(base.rustc_target_arg());
cmd.args(["-Zunstable-options", "--print", "target-spec-json"]);

// If `rust.channel` is set to either beta or stable, rustc will complain that
// we cannot use nightly features. So `RUSTC_BOOTSTRAP` is needed here.
cmd.env("RUSTC_BOOTSTRAP", "1");

let output = cmd.run_capture(builder).stdout();
let mut spec: serde_json::Value = serde_json::from_slice(output.as_bytes()).unwrap();
let mut spec = get_target_specs(builder, compiler, base);
let spec_map = spec.as_object_mut().unwrap();

// The `is-builtin` attribute of a spec needs to be removed, otherwise rustc will complain.
Expand All @@ -69,3 +82,23 @@ fn create_synthetic_target(
std::fs::write(&path, serde_json::to_vec_pretty(&spec).unwrap()).unwrap();
TargetSelection::create_synthetic(&name, path.to_str().unwrap())
}

/// Get the JSON target specs from the given compiler.
Comment thread
jieyouxu marked this conversation as resolved.
/// Note that the set of targets will differ between the stage0 and stage1+ (in-tree) compiler!
pub fn get_target_specs(
builder: &Builder<'_>,
compiler: Compiler,
target: TargetSelection,
) -> serde_json::Value {
let mut cmd = builder.rustc_cmd(compiler);
cmd.arg("--target").arg(target.rustc_target_arg());
cmd.args(["-Zunstable-options", "--print", "target-spec-json"]);

// If `rust.channel` is set to either beta or stable, rustc will complain that
// we cannot use nightly features. So `RUSTC_BOOTSTRAP` is needed here.
cmd.env("RUSTC_BOOTSTRAP", "1");

let output = cmd.cached().run_capture(builder).stdout();
let spec: serde_json::Value = serde_json::from_slice(output.as_bytes()).unwrap();
spec
}
129 changes: 98 additions & 31 deletions src/bootstrap/src/core/build_steps/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ use crate::core::build_steps::format::InternalRustfmt;
use crate::core::build_steps::gcc::{Gcc, GccTargetPair, add_cg_gcc_cargo_flags};
use crate::core::build_steps::llvm::get_llvm_version;
use crate::core::build_steps::run::{get_completion_paths, get_help_path};
use crate::core::build_steps::synthetic_targets::MirOptPanicAbortSyntheticTarget;
use crate::core::build_steps::synthetic_targets::{
PanicStrategy, SyntheticTargetWithPanicStrategy, get_target_specs,
};
use crate::core::build_steps::test::compiletest::CompiletestMode;
use crate::core::build_steps::test::failed_tests::{RecordFailedTests, SetupFailedTestsFile};
use crate::core::build_steps::tool::{
Expand Down Expand Up @@ -2168,8 +2170,8 @@ test!(CoverageRunRustdoc {
// For the mir-opt suite we do not use macros, as we need custom behavior when blessing.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct MirOpt {
pub compiler: Compiler,
pub target: TargetSelection,
compiler: Compiler,
target: TargetSelection,
}

impl CommandLineStep for MirOpt {
Expand All @@ -2185,45 +2187,110 @@ impl CommandLineStep for MirOpt {

fn make_run(run: RunConfig<'_>) {
let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
run.builder.ensure(MirOpt { compiler, target: run.target });
}

fn run(self, builder: &Builder<'_>) {
let run = |target| {
builder.ensure(Compiletest {
test_compiler: self.compiler,
target,
mode: CompiletestMode::MirOpt,
suite: "mir-opt",
path: "tests/mir-opt",
compare_mode: None,
})
// The mir-opt tests check four distinct configurations, the cross-product of the
// following two axes:
// - Bit-width: 32-bit and 64-bit
// - Panic strategy: unwind and abort

// Return the bitwidth and panic strategy of the default (usually host) target
let get_bitwidth_and_panic_strategy = || -> (u64, PanicStrategy) {
if run.builder.config.dry_run() {
return (64, PanicStrategy::Unwind);
}

let specs = get_target_specs(run.builder, compiler, run.target);
let specs = specs.as_object();
let bitwidth = specs
.and_then(|obj| obj.get("target-pointer-width"))
.and_then(|v| v.as_i64())
.map(|v| v as u64)
.unwrap_or(64);
let panic_strategy = specs
.and_then(|obj| obj.get("panic-strategy"))
.and_then(|v| v.as_str())
.map(|v| match v {
"unwind" => PanicStrategy::Unwind,
_ => PanicStrategy::Abort,
})
Comment thread
jieyouxu marked this conversation as resolved.
// The default panic strategy is unwind
.unwrap_or(PanicStrategy::Unwind);
(bitwidth, panic_strategy)
};

run(self.target);
// Here we generate several configurations of this step to evaluate multiple targets.
let targets = if run.builder.config.cmd.bless() {
// When blessing, we generate a fixed set of 4 targets that cover all the
// possible combinations. This selection covers all our tier 1 operating systems and
// architectures using only tier 1 targets.

// Run more targets with `--bless`. But we always run the host target first, since some
// tests use very specific `only` clauses that are not covered by the target set below.
if builder.config.cmd.bless() {
// All that we really need to do is cover all combinations of 32/64-bit and unwind/abort,
// but while we're at it we might as well flex our cross-compilation support. This
// selection covers all our tier 1 operating systems and architectures using only tier
// 1 targets.
// We also include the host target, since some tests use very specific `only` clauses
// that are not covered by the target set below.
Comment thread
Kobzol marked this conversation as resolved.

let (bitwidth, strategy) = get_bitwidth_and_panic_strategy();
let mut targets = vec![(bitwidth, strategy, run.target)];

for target in ["aarch64-unknown-linux-gnu", "i686-pc-windows-msvc"] {
run(TargetSelection::from_user(target));
// 64-bit and 32-bit panic=unwind
for (bitwidth, target) in
[(64, "aarch64-unknown-linux-gnu"), (32, "i686-pc-windows-msvc")]
{
targets.push((bitwidth, PanicStrategy::Unwind, TargetSelection::from_user(target)));
}

for target in ["x86_64-apple-darwin", "i686-unknown-linux-musl"] {
// 64-bit and 32-bit panic=abort
for (bitwidth, target) in [(64, "x86_64-apple-darwin"), (32, "i686-unknown-linux-musl")]
{
let target = TargetSelection::from_user(target);
let panic_abort_target = builder.ensure(MirOptPanicAbortSyntheticTarget {
compiler: self.compiler,
base: target,
});
run(panic_abort_target);
let panic_abort_target = run
.builder
.ensure(SyntheticTargetWithPanicStrategy::panic_abort(compiler, target));
targets.push((bitwidth, PanicStrategy::Abort, panic_abort_target));
}
// This is a small optimization for local blessing.
// If we figure out that the host target already has a given bitwidth/panic strategy
// combination, we do not add the fixed targets to the list.
let mut unique = HashSet::new();
targets.retain(|(bitwidth, strategy, _)| unique.insert((*bitwidth, *strategy)));

targets.into_iter().map(|(_, _, target)| target).collect()
} else {
// When not blessing, we could also test all four configurations. But that would make
// local tests quite slow. So instead, we check the current target, and then the
// current target with switched panic strategy.
// On CI, we should be running this test for both 32-bit and 64-bit targets, so together
// this should check all possible configurations on CI.

// The complicated thing here is how to figure out the panic strategy of the current
// target. In theory, we could just assume that in most situations, the target is
// panic=unwind, and force generation of panic=abort. But to ensure that we do this
// properly, we actually query the compiler to figure out the panic strategy, and then
// generate a synthetic target with the opposite strategy.
Comment thread
Kobzol marked this conversation as resolved.
let panic_strategy = get_bitwidth_and_panic_strategy().1;
let synthetic_target = if panic_strategy == PanicStrategy::Unwind {
run.builder
.ensure(SyntheticTargetWithPanicStrategy::panic_abort(compiler, run.target))
} else {
run.builder
.ensure(SyntheticTargetWithPanicStrategy::panic_unwind(compiler, run.target))
};
vec![run.target, synthetic_target]
};

for target in targets {
run.builder.ensure(MirOpt { compiler, target });
}
}

fn run(self, builder: &Builder<'_>) {
builder.ensure(Compiletest {
test_compiler: self.compiler,
target: self.target,
mode: CompiletestMode::MirOpt,
suite: "mir-opt",
path: "tests/mir-opt",
compare_mode: None,
});
}
}

/// Executes the `compiletest` tool to run a suite of tests.
Expand Down
6 changes: 5 additions & 1 deletion src/bootstrap/src/core/builder/cargo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,11 @@ impl Cargo {
// No need to configure the target linker for these command types.
Kind::Clean | Kind::Check | Kind::Format | Kind::Setup => {}
_ => {
cargo.configure_linker(builder);
// Do not configure the linker for synthetic targets, as we won't have cc set up
// for them.
if !target.is_synthetic() {
cargo.configure_linker(builder);
}
}
}

Expand Down
54 changes: 53 additions & 1 deletion src/bootstrap/src/core/builder/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1941,6 +1941,8 @@ mod snapshot {
[test] compiletest-coverage 1 <host>
[build] rustc 1 <host> -> std 1 <host>
[test] compiletest-mir-opt 1 <host>
[build] rustc 1 <host> -> std 1 <host-synthetic-miropt-abort>
[test] compiletest-mir-opt 1 <host-synthetic-miropt-abort>
[test] compiletest-codegen-llvm 1 <host>
[test] compiletest-codegen-units 1 <host>
[test] compiletest-assembly-llvm 1 <host>
Expand Down Expand Up @@ -2120,8 +2122,12 @@ mod snapshot {
[build] rustc 0 <host> -> CoverageDump 1 <host>
[test] compiletest-coverage 2 <host>
[test] compiletest-coverage 2 <host>
[build] rustc 1 <host> -> std 1 <host>
[build] rustc 2 <host> -> std 2 <host>
[test] compiletest-mir-opt 2 <host>
[build] rustc 1 <host> -> std 1 <host-synthetic-miropt-abort>
[build] rustc 2 <host> -> std 2 <host-synthetic-miropt-abort>
[test] compiletest-mir-opt 2 <host-synthetic-miropt-abort>
[test] compiletest-codegen-llvm 2 <host>
[test] compiletest-codegen-units 2 <host>
[test] compiletest-assembly-llvm 2 <host>
Expand Down Expand Up @@ -2389,6 +2395,52 @@ mod snapshot {
");
}

#[test]
fn test_mir_opt() {
let ctx = TestCtx::new();
insta::assert_snapshot!(
prepare_test_config(&ctx)
.path("tests/mir-opt")
.render_steps(), @"
[build] llvm <host>
[build] rustc 0 <host> -> rustc 1 <host>
[build] rustc 1 <host> -> std 1 <host>
[build] rustc 0 <host> -> Compiletest 1 <host>
[test] compiletest-mir-opt 1 <host>
[build] rustc 1 <host> -> std 1 <host-synthetic-miropt-abort>
[test] compiletest-mir-opt 1 <host-synthetic-miropt-abort>
");
}

#[test]
fn test_mir_opt_bless() {
let ctx = TestCtx::new();
insta::assert_snapshot!(
prepare_test_config(&ctx)
.arg("--bless")
.hosts(&[TEST_TRIPLE_1])
.arg("--build")
.arg(TEST_TRIPLE_1)
.targets(&[TEST_TRIPLE_1])
.path("tests/mir-opt")
.get_steps()
.render_with(RenderConfig {
normalize_host: false
}), @"
[build] llvm <target1>
[build] rustc 0 <target1> -> rustc 1 <target1>
[build] rustc 1 <target1> -> std 1 <target1>
[build] rustc 0 <target1> -> Compiletest 1 <target1>
[test] compiletest-mir-opt 1 <target1>
[build] rustc 1 <target1> -> std 1 <i686-pc-windows-msvc>
[test] compiletest-mir-opt 1 <i686-pc-windows-msvc>
[build] rustc 1 <target1> -> std 1 <x86_64-apple-darwin-synthetic-miropt-abort>
[test] compiletest-mir-opt 1 <x86_64-apple-darwin-synthetic-miropt-abort>
[build] rustc 1 <target1> -> std 1 <i686-unknown-linux-musl-synthetic-miropt-abort>
[test] compiletest-mir-opt 1 <i686-unknown-linux-musl-synthetic-miropt-abort>
");
}

#[test]
fn doc_all() {
let ctx = TestCtx::new();
Expand Down Expand Up @@ -3184,7 +3236,7 @@ fn render_metadata(metadata: &StepMetadata, config: &RenderConfig) -> String {
}

fn normalize_target(target: TargetSelection, config: &RenderConfig) -> String {
let mut target = target.to_string();
let mut target = target.triple.to_string();
if config.normalize_host {
target = target.replace(&host_target(), "host");
}
Expand Down
4 changes: 2 additions & 2 deletions src/ci/docker/host-x86_64/test-various/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,11 @@ ENV WASM_WASIP_SCRIPT="python3 /checkout/x.py --stage 2 test --host= --target $W
tests/run-make \
tests/run-make-cargo \
tests/ui \
tests/mir-opt \
tests/codegen-units \
tests/codegen-llvm \
tests/assembly-llvm \
library/core"
library/core \
tests/mir-opt"

ENV NVPTX_TARGETS=nvptx64-nvidia-cuda
ENV NVPTX_SCRIPT="python3 /checkout/x.py --stage 2 test --host= --target $NVPTX_TARGETS \
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
//@ test-mir-pass: GVN
// layout randomization affects the alloc output
//@ needs-deterministic-layouts
//@ compile-flags: -Zinline-mir --crate-type lib
// EMIT_MIR_FOR_EACH_BIT_WIDTH
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
debug x => _34;
}
scope 18 (inlined <Enumerate<std::slice::Iter<'_, T>> as Iterator>::next) {
let mut _22: std::option::Option<std::convert::Infallible>;
let mut _22: std::option::Option<!>;
let mut _27: std::option::Option<&T>;
let mut _30: (usize, bool);
let mut _31: (usize, &T);
Expand All @@ -32,7 +32,7 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
}
scope 20 {
scope 21 {
scope 27 (inlined <Option<(usize, &T)> as FromResidual<Option<Infallible>>>::from_residual) {
scope 27 (inlined <Option<(usize, &T)> as FromResidual<Option<!>>>::from_residual) {
let mut _21: isize;
let mut _23: bool;
}
Expand Down
Loading