From ddd5fd1e3cff5e0f1971fb8ba545804ac96652f5 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Wed, 5 Jul 2023 15:56:13 -0700 Subject: [PATCH 01/16] style-guide: Expand example of combinable expressions to include arrays Arrays are allowed as combinable expressions, but none of the examples show that. --- src/doc/style-guide/src/expressions.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/doc/style-guide/src/expressions.md b/src/doc/style-guide/src/expressions.md index f5e37b6c46f69..5b07a27c8fcab 100644 --- a/src/doc/style-guide/src/expressions.md +++ b/src/doc/style-guide/src/expressions.md @@ -801,6 +801,16 @@ foo(|param| { action(); foo(param) }) + +let x = combinable([ + an_expr, + another_expr, +]); + +let arr = [combinable( + an_expr, + another_expr, +)]; ``` Such behaviour should extend recursively, however, tools may choose to limit the From ea17415f470207e376d5f73d75bdabc7cbe45931 Mon Sep 17 00:00:00 2001 From: jyn Date: Sun, 9 Jul 2023 17:17:22 -0500 Subject: [PATCH 02/16] Add even more GHA log groups This also adds a dynamic check that we don't emit nested groups, since GHA currently doesn't support them. --- src/bootstrap/doc.rs | 9 ++++++ src/bootstrap/test.rs | 52 ++++++++++++++++++++++---------- src/ci/docker/run.sh | 4 ++- src/ci/run.sh | 8 +++-- src/tools/build_helper/src/ci.rs | 13 ++++++++ 5 files changed, 67 insertions(+), 19 deletions(-) diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 5ebfe0995a8a8..316a13dc198e0 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -1073,7 +1073,16 @@ impl Step for RustcBook { // config.toml), then this needs to explicitly update the dylib search // path. builder.add_rustc_lib_path(self.compiler, &mut cmd); + let doc_generator_guard = builder.msg( + Kind::Run, + self.compiler.stage, + "lint-docs", + self.compiler.host, + self.target, + ); builder.run(&mut cmd); + drop(doc_generator_guard); + // Run rustbook/mdbook to generate the HTML pages. builder.ensure(RustbookSrc { target: self.target, diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index eed7a584b6035..ba4d58c2f639d 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -117,12 +117,7 @@ impl Step for CrateBootstrap { SourceType::InTree, &[], ); - builder.info(&format!( - "{} {} stage0 ({})", - builder.kind.description(), - path, - bootstrap_host, - )); + let _group = builder.msg(Kind::Test, compiler.stage, path, compiler.host, bootstrap_host); let crate_name = path.rsplit_once('/').unwrap().1; run_cargo_test(cargo, &[], &[], crate_name, compiler, bootstrap_host, builder); } @@ -163,6 +158,15 @@ You can skip linkcheck with --exclude src/tools/linkchecker" // Test the linkchecker itself. let bootstrap_host = builder.config.build; let compiler = builder.compiler(0, bootstrap_host); + + let self_test_group = builder.msg( + Kind::Test, + compiler.stage, + "linkchecker self tests", + bootstrap_host, + bootstrap_host, + ); + let cargo = tool::prepare_tool_cargo( builder, compiler, @@ -174,6 +178,7 @@ You can skip linkcheck with --exclude src/tools/linkchecker" &[], ); run_cargo_test(cargo, &[], &[], "linkchecker", compiler, bootstrap_host, builder); + drop(self_test_group); if builder.doc_tests == DocTests::No { return; @@ -182,13 +187,14 @@ You can skip linkcheck with --exclude src/tools/linkchecker" // Build all the default documentation. builder.default_doc(&[]); + // Build the linkchecker before calling `msg`, since GHA doesn't support nested groups. + let mut linkchecker = builder.tool_cmd(Tool::Linkchecker); + // Run the linkchecker. + let _guard = + builder.msg(Kind::Test, compiler.stage, "Linkcheck", bootstrap_host, bootstrap_host); let _time = util::timeit(&builder); - try_run( - builder, - builder.tool_cmd(Tool::Linkchecker).arg(builder.out.join(host.triple).join("doc")), - ) - .unwrap(); + try_run(builder, linkchecker.arg(builder.out.join(host.triple).join("doc"))).unwrap(); } fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { @@ -2676,6 +2682,10 @@ impl Step for Bootstrap { /// Tests the build system itself. fn run(self, builder: &Builder<'_>) { + let host = builder.config.build; + let compiler = builder.compiler(0, host); + let _guard = builder.msg(Kind::Test, 0, "bootstrap", host, host); + let mut check_bootstrap = Command::new(&builder.python()); check_bootstrap .args(["-m", "unittest", "bootstrap_test.py"]) @@ -2686,8 +2696,6 @@ impl Step for Bootstrap { // Use `python -m unittest` manually if you want to pass arguments. try_run(builder, &mut check_bootstrap).unwrap(); - let host = builder.config.build; - let compiler = builder.compiler(0, host); let mut cmd = Command::new(&builder.initial_cargo); cmd.arg("test") .current_dir(builder.src.join("src/bootstrap")) @@ -2755,7 +2763,13 @@ impl Step for TierCheck { cargo.arg("--verbose"); } - builder.info("platform support check"); + let _guard = builder.msg( + Kind::Test, + self.compiler.stage, + "platform support check", + self.compiler.host, + self.compiler.host, + ); try_run(builder, &mut cargo.into()).unwrap(); } } @@ -2803,8 +2817,6 @@ impl Step for RustInstaller { /// Ensure the version placeholder replacement tool builds fn run(self, builder: &Builder<'_>) { - builder.info("test rust-installer"); - let bootstrap_host = builder.config.build; let compiler = builder.compiler(0, bootstrap_host); let cargo = tool::prepare_tool_cargo( @@ -2817,6 +2829,14 @@ impl Step for RustInstaller { SourceType::InTree, &[], ); + + let _guard = builder.msg( + Kind::Test, + compiler.stage, + "rust-installer", + bootstrap_host, + bootstrap_host, + ); run_cargo_test(cargo, &[], &[], "installer", compiler, bootstrap_host, builder); // We currently don't support running the test.sh script outside linux(?) environments. diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh index 4b218d5772769..da9d68672c4b7 100755 --- a/src/ci/docker/run.sh +++ b/src/ci/docker/run.sh @@ -79,7 +79,7 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then loaded_images=$(/usr/bin/timeout -k 720 600 docker load -i /tmp/rustci_docker_cache \ | sed 's/.* sha/sha/') set -e - echo "Downloaded containers:\n$loaded_images" + printf "Downloaded containers:\n$loaded_images\n" fi dockerfile="$docker_dir/$image/Dockerfile" @@ -89,12 +89,14 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then else context="$script_dir" fi + echo "::group::Building docker image for $image" retry docker \ build \ --rm \ -t rust-ci \ -f "$dockerfile" \ "$context" + echo "::endgroup::" if [ "$CI" != "" ]; then s3url="s3://$SCCACHE_BUCKET/docker/$cksum" diff --git a/src/ci/run.sh b/src/ci/run.sh index 48fb40d6a6dd8..da1960fc05712 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -154,13 +154,13 @@ fi # check for clock drifts. An HTTP URL is used instead of HTTPS since on Azure # Pipelines it happened that the certificates were marked as expired. datecheck() { - echo "== clock drift check ==" + echo "::group::Clock drift check" echo -n " local time: " date echo -n " network time: " curl -fs --head http://ci-caches.rust-lang.org | grep ^Date: \ | sed 's/Date: //g' || true - echo "== end clock drift check ==" + echo "::endgroup::" } datecheck trap datecheck EXIT @@ -177,6 +177,7 @@ retry make prepare # Display the CPU and memory information. This helps us know why the CI timing # is fluctuating. +echo "::group::Display CPU and Memory information" if isMacOS; then system_profiler SPHardwareDataType || true sysctl hw || true @@ -186,6 +187,7 @@ else cat /proc/meminfo || true ncpus=$(grep processor /proc/cpuinfo | wc -l) fi +echo "::endgroup::" if [ ! -z "$SCRIPT" ]; then echo "Executing ${SCRIPT}" @@ -218,4 +220,6 @@ if [ "$RUN_CHECK_WITH_PARALLEL_QUERIES" != "" ]; then CARGO_INCREMENTAL=0 ../x check fi +echo "::group::sccache stats" sccache --show-stats || true +echo "::endgroup::" diff --git a/src/tools/build_helper/src/ci.rs b/src/tools/build_helper/src/ci.rs index 893195b69c219..08bc861fd2195 100644 --- a/src/tools/build_helper/src/ci.rs +++ b/src/tools/build_helper/src/ci.rs @@ -36,6 +36,10 @@ impl CiEnv { } pub mod gha { + use std::sync::atomic::{AtomicBool, Ordering}; + + static GROUP_ACTIVE: AtomicBool = AtomicBool::new(false); + /// All github actions log messages from this call to the Drop of the return value /// will be grouped and hidden by default in logs. Note that nesting these does /// not really work. @@ -45,6 +49,11 @@ pub mod gha { } else { eprintln!("{name}") } + // https://github.com/actions/toolkit/issues/1001 + assert!( + !GROUP_ACTIVE.swap(true, Ordering::Relaxed), + "nested groups are not supported by GHA!" + ); Group(()) } @@ -57,6 +66,10 @@ pub mod gha { if std::env::var_os("GITHUB_ACTIONS").is_some() { eprintln!("::endgroup::"); } + assert!( + GROUP_ACTIVE.swap(false, Ordering::Relaxed), + "group dropped but no group active!" + ); } } } From 8010365ca48dbb3d1e6469b502b5e7daf736559f Mon Sep 17 00:00:00 2001 From: jyn Date: Sun, 9 Jul 2023 18:59:23 -0500 Subject: [PATCH 03/16] Don't nest GHA groups in `check::Std` --- src/bootstrap/check.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index 1a0f0047812ed..4e9f67f6873f9 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -137,6 +137,7 @@ impl Step for Std { let hostdir = builder.sysroot_libdir(compiler, compiler.host); add_to_sysroot(&builder, &libdir, &hostdir, &libstd_stamp(builder, compiler, target)); } + drop(_guard); // don't run on std twice with x.py clippy // don't check test dependencies if we haven't built libtest From 116223e8aa343ac52785a561b9bac93bfa81d71c Mon Sep 17 00:00:00 2001 From: jyn Date: Sun, 9 Jul 2023 18:59:48 -0500 Subject: [PATCH 04/16] Don't checkout the LLVM submodule in `x dist --dry-run` We don't actually need it and it's quite slow. --- src/bootstrap/dist.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 4522819f996e8..66888a07c9e10 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -897,7 +897,9 @@ impl Step for Src { /// Creates the `rust-src` installer component fn run(self, builder: &Builder<'_>) -> GeneratedTarball { - builder.update_submodule(&Path::new("src/llvm-project")); + if !builder.config.dry_run() { + builder.update_submodule(&Path::new("src/llvm-project")); + } let tarball = Tarball::new_targetless(builder, "rust-src"); From ec2d072d89ca1bd07b57eb5593d4b35f3b556de0 Mon Sep 17 00:00:00 2001 From: jyn Date: Sun, 9 Jul 2023 20:28:47 -0500 Subject: [PATCH 05/16] fix nested GHA groups (redux) --- src/bootstrap/test.rs | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index ba4d58c2f639d..d9c03a017d19b 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1899,14 +1899,6 @@ impl Step for BookTest { /// /// This uses the `rustdoc` that sits next to `compiler`. fn run(self, builder: &Builder<'_>) { - let host = self.compiler.host; - let _guard = builder.msg( - Kind::Test, - self.compiler.stage, - &format!("book {}", self.name), - host, - host, - ); // External docs are different from local because: // - Some books need pre-processing by mdbook before being tested. // - They need to save their state to toolstate. @@ -1949,7 +1941,7 @@ impl BookTest { let _guard = builder.msg( Kind::Test, compiler.stage, - format_args!("rustbook {}", self.path.display()), + format_args!("mdbook {}", self.path.display()), compiler.host, compiler.host, ); @@ -1965,8 +1957,12 @@ impl BookTest { /// This runs `rustdoc --test` on all `.md` files in the path. fn run_local_doc(self, builder: &Builder<'_>) { let compiler = self.compiler; + let host = self.compiler.host; - builder.ensure(compile::Std::new(compiler, compiler.host)); + builder.ensure(compile::Std::new(compiler, host)); + + let _guard = + builder.msg(Kind::Test, compiler.stage, &format!("book {}", self.name), host, host); // Do a breadth-first traversal of the `src/doc` directory and just run // tests for all files that end in `*.md` From d634f26ce39b55f31ae1eef2c4ddd028be9c005f Mon Sep 17 00:00:00 2001 From: jyn Date: Sun, 9 Jul 2023 21:03:01 -0500 Subject: [PATCH 06/16] Make sure toolstates.json ends in a newline This avoids the following broken logging in CI: ``` {"book":"test-pass","reference":"test-pass","rustbook":"test-fail","rust-by-example":"test-pass","nomicon":"test-pass","embedded-book":"test-pass","edition-guide":"test-pass"}::group::Building bootstrap ``` --- src/bootstrap/toolstate.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/toolstate.rs b/src/bootstrap/toolstate.rs index 9c4d0ea265ddf..1285603a63da5 100644 --- a/src/bootstrap/toolstate.rs +++ b/src/bootstrap/toolstate.rs @@ -262,6 +262,8 @@ impl Builder<'_> { /// `rust.save-toolstates` in `config.toml`. If unspecified, nothing will be /// done. The file is updated immediately after this function completes. pub fn save_toolstate(&self, tool: &str, state: ToolState) { + use std::io::Write; + // If we're in a dry run setting we don't want to save toolstates as // that means if we e.g. panic down the line it'll look like we tested // everything (but we actually haven't). @@ -286,7 +288,8 @@ impl Builder<'_> { current_toolstates.insert(tool.into(), state); t!(file.seek(SeekFrom::Start(0))); t!(file.set_len(0)); - t!(serde_json::to_writer(file, ¤t_toolstates)); + t!(serde_json::to_writer(&file, ¤t_toolstates)); + t!(writeln!(file)); // make sure this ends in a newline } } } From dd5797ae82753eb9a6f9f4cea2e0c1ea1358f25b Mon Sep 17 00:00:00 2001 From: jyn Date: Sun, 9 Jul 2023 21:26:11 -0500 Subject: [PATCH 07/16] Add GHA log groups for tool tests --- src/bootstrap/test.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index d9c03a017d19b..4813f82c7ac0f 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -415,6 +415,7 @@ impl Step for RustAnalyzer { cargo.env("SKIP_SLOW_TESTS", "1"); cargo.add_rustc_lib_path(builder, compiler); + builder.msg_sysroot_tool(Kind::Test, compiler.stage, "rust-analyzer", host, host); run_cargo_test(cargo, &[], &[], "rust-analyzer", compiler, host, builder); } } @@ -464,6 +465,7 @@ impl Step for Rustfmt { cargo.add_rustc_lib_path(builder, compiler); + builder.msg_sysroot_tool(Kind::Test, compiler.stage, "rustfmt", host, host); run_cargo_test(cargo, &[], &[], "rustfmt", compiler, host, builder); } } @@ -556,6 +558,13 @@ impl Miri { cargo.env("RUST_BACKTRACE", "1"); let mut cargo = Command::from(cargo); + let _guard = builder.msg( + Kind::Build, + compiler.stage + 1, + "miri sysroot", + compiler.host, + compiler.host, + ); builder.run(&mut cargo); // # Determine where Miri put its sysroot. @@ -633,6 +642,8 @@ impl Step for Miri { SourceType::InTree, &[], ); + let _guard = builder.msg_sysroot_tool(Kind::Test, compiler.stage, "miri", host, host); + cargo.add_rustc_lib_path(builder, compiler); // miri tests need to know about the stage sysroot @@ -801,6 +812,8 @@ impl Step for Clippy { cargo.env("BLESS", "Gesundheit"); } + builder.msg_sysroot_tool(Kind::Test, compiler.stage, "clippy", host, host); + if builder.try_run(&mut cargo).is_ok() { // The tests succeeded; nothing to do. return; @@ -1056,6 +1069,13 @@ impl Step for RustdocGUI { } let _time = util::timeit(&builder); + let _guard = builder.msg_sysroot_tool( + Kind::Test, + self.compiler.stage, + "rustdoc-gui", + self.compiler.host, + self.target, + ); crate::render_tests::try_run_tests(builder, &mut cmd, true); } } From 611b0864bbede4bdc6adde46d6b50dc376a313f9 Mon Sep 17 00:00:00 2001 From: jyn Date: Sun, 9 Jul 2023 21:59:27 -0500 Subject: [PATCH 08/16] Add must_use to `msg_` functions This caught several places which weren't waiting until the command finished to drop the Group. I also took the liberty of calling `msg_sysroot_tool` from `run_cargo_test` to reduce code duplication and make errors like this less likely in the future. --- src/bootstrap/doc.rs | 8 ++-- src/bootstrap/lib.rs | 6 +++ src/bootstrap/test.rs | 98 +++++++++++++++++++++++++------------------ 3 files changed, 67 insertions(+), 45 deletions(-) diff --git a/src/bootstrap/doc.rs b/src/bootstrap/doc.rs index 316a13dc198e0..d64f84f00e4c8 100644 --- a/src/bootstrap/doc.rs +++ b/src/bootstrap/doc.rs @@ -222,7 +222,7 @@ impl Step for TheBook { let shared_assets = builder.ensure(SharedAssets { target }); // build the redirect pages - builder.msg_doc(compiler, "book redirect pages", target); + let _guard = builder.msg_doc(compiler, "book redirect pages", target); for file in t!(fs::read_dir(builder.src.join(&relative_path).join("redirects"))) { let file = t!(file); let path = file.path(); @@ -306,7 +306,7 @@ impl Step for Standalone { fn run(self, builder: &Builder<'_>) { let target = self.target; let compiler = self.compiler; - builder.msg_doc(compiler, "standalone", target); + let _guard = builder.msg_doc(compiler, "standalone", target); let out = builder.doc_out(target); t!(fs::create_dir_all(&out)); @@ -812,8 +812,6 @@ macro_rules! tool_doc { SourceType::Submodule }; - builder.msg_doc(compiler, stringify!($tool).to_lowercase(), target); - // Symlink compiler docs to the output directory of rustdoc documentation. let out_dirs = [ builder.stage_out(compiler, Mode::ToolRustc).join(target.triple).join("doc"), @@ -852,6 +850,8 @@ macro_rules! tool_doc { cargo.rustdocflag("--show-type-layout"); cargo.rustdocflag("--generate-link-to-definition"); cargo.rustdocflag("-Zunstable-options"); + + let _guard = builder.msg_doc(compiler, stringify!($tool).to_lowercase(), target); builder.run(&mut cargo.into()); } } diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 0a7aff62257a5..31742061b4f97 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -1004,6 +1004,7 @@ impl Build { } } + #[must_use = "Groups should not be dropped until the Step finishes running"] fn msg_check( &self, what: impl Display, @@ -1012,6 +1013,7 @@ impl Build { self.msg(Kind::Check, self.config.stage, what, self.config.build, target) } + #[must_use = "Groups should not be dropped until the Step finishes running"] fn msg_doc( &self, compiler: Compiler, @@ -1021,6 +1023,7 @@ impl Build { self.msg(Kind::Doc, compiler.stage, what, compiler.host, target.into()) } + #[must_use = "Groups should not be dropped until the Step finishes running"] fn msg_build( &self, compiler: Compiler, @@ -1033,6 +1036,7 @@ impl Build { /// Return a `Group` guard for a [`Step`] that is built for each `--stage`. /// /// [`Step`]: crate::builder::Step + #[must_use = "Groups should not be dropped until the Step finishes running"] fn msg( &self, action: impl Into, @@ -1059,6 +1063,7 @@ impl Build { /// Return a `Group` guard for a [`Step`] that is only built once and isn't affected by `--stage`. /// /// [`Step`]: crate::builder::Step + #[must_use = "Groups should not be dropped until the Step finishes running"] fn msg_unstaged( &self, action: impl Into, @@ -1070,6 +1075,7 @@ impl Build { self.group(&msg) } + #[must_use = "Groups should not be dropped until the Step finishes running"] fn msg_sysroot_tool( &self, action: impl Into, diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 4813f82c7ac0f..63a0605273431 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -117,9 +117,8 @@ impl Step for CrateBootstrap { SourceType::InTree, &[], ); - let _group = builder.msg(Kind::Test, compiler.stage, path, compiler.host, bootstrap_host); let crate_name = path.rsplit_once('/').unwrap().1; - run_cargo_test(cargo, &[], &[], crate_name, compiler, bootstrap_host, builder); + run_cargo_test(cargo, &[], &[], crate_name, crate_name, compiler, bootstrap_host, builder); } } @@ -159,14 +158,6 @@ You can skip linkcheck with --exclude src/tools/linkchecker" let bootstrap_host = builder.config.build; let compiler = builder.compiler(0, bootstrap_host); - let self_test_group = builder.msg( - Kind::Test, - compiler.stage, - "linkchecker self tests", - bootstrap_host, - bootstrap_host, - ); - let cargo = tool::prepare_tool_cargo( builder, compiler, @@ -177,8 +168,16 @@ You can skip linkcheck with --exclude src/tools/linkchecker" SourceType::InTree, &[], ); - run_cargo_test(cargo, &[], &[], "linkchecker", compiler, bootstrap_host, builder); - drop(self_test_group); + run_cargo_test( + cargo, + &[], + &[], + "linkchecker", + "linkchecker self tests", + compiler, + bootstrap_host, + builder, + ); if builder.doc_tests == DocTests::No { return; @@ -415,8 +414,7 @@ impl Step for RustAnalyzer { cargo.env("SKIP_SLOW_TESTS", "1"); cargo.add_rustc_lib_path(builder, compiler); - builder.msg_sysroot_tool(Kind::Test, compiler.stage, "rust-analyzer", host, host); - run_cargo_test(cargo, &[], &[], "rust-analyzer", compiler, host, builder); + run_cargo_test(cargo, &[], &[], "rust-analyzer", "rust-analyzer", compiler, host, builder); } } @@ -465,8 +463,7 @@ impl Step for Rustfmt { cargo.add_rustc_lib_path(builder, compiler); - builder.msg_sysroot_tool(Kind::Test, compiler.stage, "rustfmt", host, host); - run_cargo_test(cargo, &[], &[], "rustfmt", compiler, host, builder); + run_cargo_test(cargo, &[], &[], "rustfmt", "rustfmt", compiler, host, builder); } } @@ -514,7 +511,16 @@ impl Step for RustDemangler { cargo.env("RUST_DEMANGLER_DRIVER_PATH", rust_demangler); cargo.add_rustc_lib_path(builder, compiler); - run_cargo_test(cargo, &[], &[], "rust-demangler", compiler, host, builder); + run_cargo_test( + cargo, + &[], + &[], + "rust-demangler", + "rust-demangler", + compiler, + host, + builder, + ); } } @@ -756,7 +762,16 @@ impl Step for CompiletestTest { &[], ); cargo.allow_features("test"); - run_cargo_test(cargo, &[], &[], "compiletest", compiler, host, builder); + run_cargo_test( + cargo, + &[], + &[], + "compiletest", + "compiletest self test", + compiler, + host, + builder, + ); } } @@ -812,7 +827,7 @@ impl Step for Clippy { cargo.env("BLESS", "Gesundheit"); } - builder.msg_sysroot_tool(Kind::Test, compiler.stage, "clippy", host, host); + let _guard = builder.msg_sysroot_tool(Kind::Test, compiler.stage, "clippy", host, host); if builder.try_run(&mut cargo).is_ok() { // The tests succeeded; nothing to do. @@ -2207,11 +2222,12 @@ impl Step for CrateLibrustc { /// Given a `cargo test` subcommand, add the appropriate flags and run it. /// /// Returns whether the test succeeded. -fn run_cargo_test( +fn run_cargo_test<'a>( cargo: impl Into, libtest_args: &[&str], crates: &[Interned], primary_crate: &str, + description: impl Into>, compiler: Compiler, target: TargetSelection, builder: &Builder<'_>, @@ -2219,6 +2235,9 @@ fn run_cargo_test( let mut cargo = prepare_cargo_test(cargo, libtest_args, crates, primary_crate, compiler, target, builder); let _time = util::timeit(&builder); + let _group = description.into().and_then(|what| { + builder.msg_sysroot_tool(Kind::Test, compiler.stage, what, compiler.host, target) + }); #[cfg(feature = "build-metrics")] builder.metrics.begin_test_suite( @@ -2384,14 +2403,16 @@ impl Step for Crate { _ => panic!("can only test libraries"), }; - let _guard = builder.msg( - builder.kind, - compiler.stage, - crate_description(&self.crates), - compiler.host, + run_cargo_test( + cargo, + &[], + &self.crates, + &self.crates[0], + &*crate_description(&self.crates), + compiler, target, + builder, ); - run_cargo_test(cargo, &[], &self.crates, &self.crates[0], compiler, target, builder); } } @@ -2484,18 +2505,12 @@ impl Step for CrateRustdoc { dylib_path.insert(0, PathBuf::from(&*libdir)); cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap()); - let _guard = builder.msg_sysroot_tool( - builder.kind, - compiler.stage, - "rustdoc", - compiler.host, - target, - ); run_cargo_test( cargo, &[], &[INTERNER.intern_str("rustdoc:0.0.0")], "rustdoc", + "rustdoc", compiler, target, builder, @@ -2551,13 +2566,12 @@ impl Step for CrateRustdocJsonTypes { &[] }; - let _guard = - builder.msg(builder.kind, compiler.stage, "rustdoc-json-types", compiler.host, target); run_cargo_test( cargo, libtest_args, &[INTERNER.intern_str("rustdoc-json-types")], "rustdoc-json-types", + "rustdoc-json-types", compiler, target, builder, @@ -2728,7 +2742,7 @@ impl Step for Bootstrap { } // rustbuild tests are racy on directory creation so just run them one at a time. // Since there's not many this shouldn't be a problem. - run_cargo_test(cmd, &["--test-threads=1"], &[], "bootstrap", compiler, host, builder); + run_cargo_test(cmd, &["--test-threads=1"], &[], "bootstrap", None, compiler, host, builder); } fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { @@ -2846,14 +2860,16 @@ impl Step for RustInstaller { &[], ); - let _guard = builder.msg( - Kind::Test, - compiler.stage, + run_cargo_test( + cargo, + &[], + &[], + "installer", "rust-installer", + compiler, bootstrap_host, - bootstrap_host, + builder, ); - run_cargo_test(cargo, &[], &[], "installer", compiler, bootstrap_host, builder); // We currently don't support running the test.sh script outside linux(?) environments. // Eventually this should likely migrate to #[test]s in rust-installer proper rather than a From 301ef437221f63ddced7ca1266ba0f3e350beb40 Mon Sep 17 00:00:00 2001 From: jyn Date: Sun, 9 Jul 2023 22:12:39 -0500 Subject: [PATCH 09/16] don't print download progress in CI --- src/bootstrap/bootstrap.py | 2 +- src/bootstrap/download.rs | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 149350e62a014..57d213c4453b7 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -97,7 +97,7 @@ def _download(path, url, probably_big, verbose, exception): print("downloading {}".format(url), file=sys.stderr) try: - if probably_big or verbose: + if (probably_big or verbose) and "GITHUB_ACTIONS" not in os.environ: option = "-#" else: option = "-s" diff --git a/src/bootstrap/download.rs b/src/bootstrap/download.rs index cb40521dda763..335f334b06c06 100644 --- a/src/bootstrap/download.rs +++ b/src/bootstrap/download.rs @@ -7,7 +7,7 @@ use std::{ process::{Command, Stdio}, }; -use build_helper::util::try_run; +use build_helper::{util::try_run, ci::CiEnv}; use once_cell::sync::OnceCell; use xz2::bufread::XzDecoder; @@ -213,7 +213,6 @@ impl Config { // Try curl. If that fails and we are on windows, fallback to PowerShell. let mut curl = Command::new("curl"); curl.args(&[ - "-#", "-y", "30", "-Y", @@ -224,6 +223,12 @@ impl Config { "3", "-SRf", ]); + // Don't print progress in CI; the \r wrapping looks bad and downloads don't take long enough for progress to be useful. + if CiEnv::is_ci() { + curl.arg("-s"); + } else { + curl.arg("--progress-bar"); + } curl.arg(url); let f = File::create(tempfile).unwrap(); curl.stdout(Stdio::from(f)); From 8153f5be7bbe68f251e209752f32033b5a09bb70 Mon Sep 17 00:00:00 2001 From: jyn Date: Sun, 9 Jul 2023 22:14:48 -0500 Subject: [PATCH 10/16] put configure behind a group --- src/bootstrap/configure.py | 4 ++++ src/bootstrap/download.rs | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index e8eebdfb5a581..a7beb2a176759 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -550,6 +550,8 @@ def quit_if_file_exists(file): # If 'config.toml' already exists, exit the script at this point quit_if_file_exists('config.toml') + if "GITHUB_ACTIONS" in os.environ: + print("::group::Configure the build") p("processing command line") # Parse all known arguments into a configuration structure that reflects the # TOML we're going to write out @@ -572,3 +574,5 @@ def quit_if_file_exists(file): p("") p("run `python {}/x.py --help`".format(rust_dir)) + if "GITHUB_ACTIONS" in os.environ: + print("::endgroup::") diff --git a/src/bootstrap/download.rs b/src/bootstrap/download.rs index 335f334b06c06..c0cefc88ecef8 100644 --- a/src/bootstrap/download.rs +++ b/src/bootstrap/download.rs @@ -7,7 +7,7 @@ use std::{ process::{Command, Stdio}, }; -use build_helper::{util::try_run, ci::CiEnv}; +use build_helper::{ci::CiEnv, util::try_run}; use once_cell::sync::OnceCell; use xz2::bufread::XzDecoder; From 7064af0af25f9d7896fc8d07f9a84276c2766a7e Mon Sep 17 00:00:00 2001 From: jyn Date: Sun, 9 Jul 2023 22:57:17 -0500 Subject: [PATCH 11/16] add a couple more groups - group rustdoc-js-std - group rust-installer/test.sh --- src/bootstrap/test.rs | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 63a0605273431..04319f4f5ae17 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -940,6 +940,13 @@ impl Step for RustdocJSStd { self.target, DocumentationFormat::HTML, )); + let _guard = builder.msg( + Kind::Test, + builder.top_stage, + "rustdoc-js-std", + builder.config.build, + self.target, + ); builder.run(&mut command); } else { builder.info("No nodejs found, skipping \"tests/rustdoc-js-std\" tests"); @@ -2860,16 +2867,14 @@ impl Step for RustInstaller { &[], ); - run_cargo_test( - cargo, - &[], - &[], - "installer", + let _guard = builder.msg( + Kind::Test, + compiler.stage, "rust-installer", - compiler, bootstrap_host, - builder, + bootstrap_host, ); + run_cargo_test(cargo, &[], &[], "installer", None, compiler, bootstrap_host, builder); // We currently don't support running the test.sh script outside linux(?) environments. // Eventually this should likely migrate to #[test]s in rust-installer proper rather than a From 0726c7826b81242d986e91535572935b9908b82f Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Mon, 10 Jul 2023 00:19:06 -0700 Subject: [PATCH 12/16] Reuse LLVMConstInBoundsGEP2 We have had LLVM 14 as our minimum for a bit now. --- compiler/rustc_codegen_llvm/src/common.rs | 4 ++-- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 2 +- compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp | 11 ----------- 3 files changed, 3 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs index a2db59bd6c47b..4d879fbdcb7a7 100644 --- a/compiler/rustc_codegen_llvm/src/common.rs +++ b/compiler/rustc_codegen_llvm/src/common.rs @@ -290,7 +290,7 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { } }; let llval = unsafe { - llvm::LLVMRustConstInBoundsGEP2( + llvm::LLVMConstInBoundsGEP2( self.type_i8(), self.const_bitcast(base_addr, self.type_i8p_ext(base_addr_space)), &self.const_usize(offset.bytes()), @@ -320,7 +320,7 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn const_ptr_byte_offset(&self, base_addr: Self::Value, offset: abi::Size) -> Self::Value { unsafe { - llvm::LLVMRustConstInBoundsGEP2( + llvm::LLVMConstInBoundsGEP2( self.type_i8(), self.const_bitcast(base_addr, self.type_i8p()), &self.const_usize(offset.bytes()), diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 3ad546b61e9b6..e1dfc1b2dd6fa 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -1155,7 +1155,7 @@ extern "C" { pub fn LLVMConstVector(ScalarConstantVals: *const &Value, Size: c_uint) -> &Value; // Constant expressions - pub fn LLVMRustConstInBoundsGEP2<'a>( + pub fn LLVMConstInBoundsGEP2<'a>( ty: &'a Type, ConstantVal: &'a Value, ConstantIndices: *const &'a Value, diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index bb7510b3a53de..ab5fa961b95a4 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -1616,17 +1616,6 @@ extern "C" void LLVMRustSetLinkage(LLVMValueRef V, LLVMSetLinkage(V, fromRust(RustLinkage)); } -// FIXME: replace with LLVMConstInBoundsGEP2 when bumped minimal version to llvm-14 -extern "C" LLVMValueRef LLVMRustConstInBoundsGEP2(LLVMTypeRef Ty, - LLVMValueRef ConstantVal, - LLVMValueRef *ConstantIndices, - unsigned NumIndices) { - ArrayRef IdxList(unwrap(ConstantIndices, NumIndices), - NumIndices); - Constant *Val = unwrap(ConstantVal); - return wrap(ConstantExpr::getInBoundsGetElementPtr(unwrap(Ty), Val, IdxList)); -} - extern "C" bool LLVMRustConstIntGetZExtValue(LLVMValueRef CV, uint64_t *value) { auto C = unwrap(CV); if (C->getBitWidth() > 64) From 44d0fce1504a570260deebdadb3b5fcf59eea940 Mon Sep 17 00:00:00 2001 From: "Celina G. Val" Date: Tue, 20 Jun 2023 10:32:12 -0700 Subject: [PATCH 13/16] Fix standalone build Add extern declarations and optional dependencies to fix build done directly via `cargo build`. --- Cargo.lock | 1 + compiler/rustc_smir/Cargo.toml | 6 +++++- compiler/rustc_smir/rust-toolchain.toml | 2 +- compiler/rustc_smir/src/lib.rs | 10 ++++++++++ 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 96eda77abb279..f880fb9bafb9b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4235,6 +4235,7 @@ dependencies = [ "rustc_middle", "rustc_span", "scoped-tls", + "rustc_target", "tracing", ] diff --git a/compiler/rustc_smir/Cargo.toml b/compiler/rustc_smir/Cargo.toml index a6e6de5f785a2..80d4e7ed02fe2 100644 --- a/compiler/rustc_smir/Cargo.toml +++ b/compiler/rustc_smir/Cargo.toml @@ -4,14 +4,18 @@ version = "0.0.0" edition = "2021" [dependencies] -rustc_hir = { path = "../rustc_hir" } +# Use optional dependencies for rustc_* in order to support building this crate separately. +rustc_hir = { path = "../rustc_hir", optional = true } rustc_middle = { path = "../rustc_middle", optional = true } rustc_span = { path = "../rustc_span", optional = true } +rustc_target = { path = "../rustc_target", optional = true } tracing = "0.1" scoped-tls = "1.0" [features] default = [ + "rustc_hir", "rustc_middle", "rustc_span", + "rustc_target", ] diff --git a/compiler/rustc_smir/rust-toolchain.toml b/compiler/rustc_smir/rust-toolchain.toml index 157dfd620ee1b..d75e8e33b1c56 100644 --- a/compiler/rustc_smir/rust-toolchain.toml +++ b/compiler/rustc_smir/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2023-02-28" +channel = "nightly-2023-06-14" components = [ "rustfmt", "rustc-dev" ] diff --git a/compiler/rustc_smir/src/lib.rs b/compiler/rustc_smir/src/lib.rs index fb03633b99b31..21c72f3aaa18a 100644 --- a/compiler/rustc_smir/src/lib.rs +++ b/compiler/rustc_smir/src/lib.rs @@ -14,6 +14,16 @@ #![feature(local_key_cell_methods)] #![feature(ptr_metadata)] +// Declare extern rustc_* crates to enable building this crate separately from the compiler. +#[cfg(not(feature = "default"))] +extern crate rustc_hir; +#[cfg(not(feature = "default"))] +extern crate rustc_middle; +#[cfg(not(feature = "default"))] +extern crate rustc_span; +#[cfg(not(feature = "default"))] +extern crate rustc_target; + pub mod rustc_internal; pub mod stable_mir; From 697563289d18ba54aa96ec9ba8f9f716d095ce46 Mon Sep 17 00:00:00 2001 From: "Celina G. Val" Date: Tue, 20 Jun 2023 10:40:23 -0700 Subject: [PATCH 14/16] Implement Stable for AssertMessage --- compiler/rustc_smir/src/rustc_smir/mod.rs | 67 +++++++++++++---------- 1 file changed, 37 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 85d5bb00c4e10..8a6153269a119 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -137,8 +137,11 @@ fn smir_crate(tcx: TyCtxt<'_>, crate_num: CrateNum) -> stable_mir::Crate { stable_mir::Crate { id: crate_num.into(), name: crate_name, is_local } } -pub trait Stable { +/// Trait used to convert between an internal MIR type to a Stable MIR type. +pub(crate) trait Stable { + /// The stable representation of the type implementing Stable. type T; + /// Converts an object to the equivalent Stable MIR representation. fn stable(&self) -> Self::T; } @@ -229,34 +232,38 @@ impl Stable for mir::UnwindAction { } } -fn rustc_assert_msg_to_msg<'tcx>( - assert_message: &rustc_middle::mir::AssertMessage<'tcx>, -) -> stable_mir::mir::AssertMessage { - use rustc_middle::mir::AssertKind; - match assert_message { - AssertKind::BoundsCheck { len, index } => { - stable_mir::mir::AssertMessage::BoundsCheck { len: len.stable(), index: index.stable() } - } - AssertKind::Overflow(bin_op, op1, op2) => { - stable_mir::mir::AssertMessage::Overflow(bin_op.stable(), op1.stable(), op2.stable()) - } - AssertKind::OverflowNeg(op) => stable_mir::mir::AssertMessage::OverflowNeg(op.stable()), - AssertKind::DivisionByZero(op) => { - stable_mir::mir::AssertMessage::DivisionByZero(op.stable()) - } - AssertKind::RemainderByZero(op) => { - stable_mir::mir::AssertMessage::RemainderByZero(op.stable()) - } - AssertKind::ResumedAfterReturn(generator) => { - stable_mir::mir::AssertMessage::ResumedAfterReturn(generator.stable()) - } - AssertKind::ResumedAfterPanic(generator) => { - stable_mir::mir::AssertMessage::ResumedAfterPanic(generator.stable()) - } - AssertKind::MisalignedPointerDereference { required, found } => { - stable_mir::mir::AssertMessage::MisalignedPointerDereference { - required: required.stable(), - found: found.stable(), +impl<'tcx> Stable for mir::AssertMessage<'tcx> { + type T = stable_mir::mir::AssertMessage; + fn stable(&self) -> Self::T { + use rustc_middle::mir::AssertKind; + match self { + AssertKind::BoundsCheck { len, index } => stable_mir::mir::AssertMessage::BoundsCheck { + len: len.stable(), + index: index.stable(), + }, + AssertKind::Overflow(bin_op, op1, op2) => stable_mir::mir::AssertMessage::Overflow( + bin_op.stable(), + op1.stable(), + op2.stable(), + ), + AssertKind::OverflowNeg(op) => stable_mir::mir::AssertMessage::OverflowNeg(op.stable()), + AssertKind::DivisionByZero(op) => { + stable_mir::mir::AssertMessage::DivisionByZero(op.stable()) + } + AssertKind::RemainderByZero(op) => { + stable_mir::mir::AssertMessage::RemainderByZero(op.stable()) + } + AssertKind::ResumedAfterReturn(generator) => { + stable_mir::mir::AssertMessage::ResumedAfterReturn(generator.stable()) + } + AssertKind::ResumedAfterPanic(generator) => { + stable_mir::mir::AssertMessage::ResumedAfterPanic(generator.stable()) + } + AssertKind::MisalignedPointerDereference { required, found } => { + stable_mir::mir::AssertMessage::MisalignedPointerDereference { + required: required.stable(), + found: found.stable(), + } } } } @@ -381,7 +388,7 @@ impl<'tcx> Stable for mir::Terminator<'tcx> { Assert { cond, expected, msg, target, unwind } => Terminator::Assert { cond: cond.stable(), expected: *expected, - msg: rustc_assert_msg_to_msg(msg), + msg: msg.stable(), target: target.as_usize(), unwind: unwind.stable(), }, From b9f378b19bd5ac234139663e9df1fe8ddca5c120 Mon Sep 17 00:00:00 2001 From: "Celina G. Val" Date: Tue, 13 Jun 2023 15:08:14 -0700 Subject: [PATCH 15/16] Implement a few more rvalue translation to smir - Introduce an Opaque type for adding information that is still internal to the compiler. --- Cargo.lock | 2 +- compiler/rustc_smir/src/lib.rs | 1 + compiler/rustc_smir/src/rustc_internal/mod.rs | 10 + compiler/rustc_smir/src/rustc_smir/mod.rs | 134 ++++++++++++- .../rustc_smir/src/stable_mir/mir/body.rs | 181 +++++++++++++++++- 5 files changed, 318 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f880fb9bafb9b..3b427d1f3f48d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4234,8 +4234,8 @@ dependencies = [ "rustc_hir", "rustc_middle", "rustc_span", - "scoped-tls", "rustc_target", + "scoped-tls", "tracing", ] diff --git a/compiler/rustc_smir/src/lib.rs b/compiler/rustc_smir/src/lib.rs index 21c72f3aaa18a..8450bb7311996 100644 --- a/compiler/rustc_smir/src/lib.rs +++ b/compiler/rustc_smir/src/lib.rs @@ -13,6 +13,7 @@ #![cfg_attr(not(feature = "default"), feature(rustc_private))] #![feature(local_key_cell_methods)] #![feature(ptr_metadata)] +#![feature(type_alias_impl_trait)] // Used to define opaque types. // Declare extern rustc_* crates to enable building this crate separately from the compiler. #[cfg(not(feature = "default"))] diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index 609a04d263c96..87e0b211556b9 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -3,6 +3,9 @@ //! For that, we define APIs that will temporarily be public to 3P that exposes rustc internal APIs //! until stable MIR is complete. +use std::fmt::Debug; +use std::string::ToString; + use crate::{ rustc_smir::Tables, stable_mir::{self, with}, @@ -49,3 +52,10 @@ pub fn crate_num(item: &stable_mir::Crate) -> CrateNum { pub fn run(tcx: TyCtxt<'_>, f: impl FnOnce()) { crate::stable_mir::run(Tables { tcx, def_ids: vec![], types: vec![] }, f); } + +/// A type that provides internal information but that can still be used for debug purpose. +pub type Opaque = impl Debug + ToString + Clone; + +pub(crate) fn opaque(value: &T) -> Opaque { + format!("{value:?}") +} diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 8a6153269a119..f22c620021eeb 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -7,11 +7,13 @@ //! //! For now, we are developing everything inside `rustc`, thus, we keep this module private. +use crate::rustc_internal::{self, opaque}; use crate::stable_mir::ty::{FloatTy, IntTy, RigidTy, TyKind, UintTy}; use crate::stable_mir::{self, Context}; use rustc_middle::mir; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE}; +use rustc_target::abi::FieldIdx; use tracing::debug; impl<'tcx> Context for Tables<'tcx> { @@ -145,6 +147,13 @@ pub(crate) trait Stable { fn stable(&self) -> Self::T; } +impl Stable for DefId { + type T = stable_mir::CrateItem; + fn stable(&self) -> Self::T { + rustc_internal::crate_item(*self) + } +} + impl<'tcx> Stable for mir::Statement<'tcx> { type T = stable_mir::mir::Statement; fn stable(&self) -> Self::T { @@ -176,12 +185,18 @@ impl<'tcx> Stable for mir::Rvalue<'tcx> { match self { Use(op) => stable_mir::mir::Rvalue::Use(op.stable()), Repeat(_, _) => todo!(), - Ref(_, _, _) => todo!(), - ThreadLocalRef(_) => todo!(), - AddressOf(_, _) => todo!(), - Len(_) => todo!(), + Ref(region, kind, place) => { + stable_mir::mir::Rvalue::Ref(opaque(region), kind.stable(), place.stable()) + } + ThreadLocalRef(def_id) => stable_mir::mir::Rvalue::ThreadLocalRef(def_id.stable()), + AddressOf(mutability, place) => { + stable_mir::mir::Rvalue::AddressOf(mutability.stable(), place.stable()) + } + Len(place) => stable_mir::mir::Rvalue::Len(place.stable()), Cast(_, _, _) => todo!(), - BinaryOp(_, _) => todo!(), + BinaryOp(bin_op, ops) => { + stable_mir::mir::Rvalue::BinaryOp(bin_op.stable(), ops.0.stable(), ops.1.stable()) + } CheckedBinaryOp(bin_op, ops) => stable_mir::mir::Rvalue::CheckedBinaryOp( bin_op.stable(), ops.0.stable(), @@ -189,14 +204,119 @@ impl<'tcx> Stable for mir::Rvalue<'tcx> { ), NullaryOp(_, _) => todo!(), UnaryOp(un_op, op) => stable_mir::mir::Rvalue::UnaryOp(un_op.stable(), op.stable()), - Discriminant(_) => todo!(), + Discriminant(place) => stable_mir::mir::Rvalue::Discriminant(place.stable()), Aggregate(_, _) => todo!(), ShallowInitBox(_, _) => todo!(), - CopyForDeref(_) => todo!(), + CopyForDeref(place) => stable_mir::mir::Rvalue::CopyForDeref(place.stable()), } } } +impl Stable for mir::Mutability { + type T = stable_mir::mir::Mutability; + fn stable(&self) -> Self::T { + use mir::Mutability::*; + match *self { + Not => stable_mir::mir::Mutability::Not, + Mut => stable_mir::mir::Mutability::Mut, + } + } +} + +impl Stable for mir::BorrowKind { + type T = stable_mir::mir::BorrowKind; + fn stable(&self) -> Self::T { + use mir::BorrowKind::*; + match *self { + Shared => stable_mir::mir::BorrowKind::Shared, + Shallow => stable_mir::mir::BorrowKind::Shallow, + Mut { kind } => stable_mir::mir::BorrowKind::Mut { kind: kind.stable() }, + } + } +} + +impl Stable for mir::MutBorrowKind { + type T = stable_mir::mir::MutBorrowKind; + fn stable(&self) -> Self::T { + use mir::MutBorrowKind::*; + match *self { + Default => stable_mir::mir::MutBorrowKind::Default, + TwoPhaseBorrow => stable_mir::mir::MutBorrowKind::TwoPhaseBorrow, + ClosureCapture => stable_mir::mir::MutBorrowKind::ClosureCapture, + } + } +} + +impl<'tcx> Stable for mir::NullOp<'tcx> { + type T = stable_mir::mir::NullOp; + fn stable(&self) -> Self::T { + use mir::NullOp::*; + match self { + SizeOf => stable_mir::mir::NullOp::SizeOf, + AlignOf => stable_mir::mir::NullOp::AlignOf, + OffsetOf(indices) => { + stable_mir::mir::NullOp::OffsetOf(indices.iter().map(|idx| idx.stable()).collect()) + } + } + } +} + +impl Stable for mir::CastKind { + type T = stable_mir::mir::CastKind; + fn stable(&self) -> Self::T { + use mir::CastKind::*; + match self { + PointerExposeAddress => stable_mir::mir::CastKind::PointerExposeAddress, + PointerFromExposedAddress => stable_mir::mir::CastKind::PointerFromExposedAddress, + PointerCoercion(c) => stable_mir::mir::CastKind::PointerCoercion(c.stable()), + DynStar => stable_mir::mir::CastKind::DynStar, + IntToInt => stable_mir::mir::CastKind::IntToInt, + FloatToInt => stable_mir::mir::CastKind::FloatToInt, + FloatToFloat => stable_mir::mir::CastKind::FloatToFloat, + IntToFloat => stable_mir::mir::CastKind::IntToFloat, + PtrToPtr => stable_mir::mir::CastKind::PtrToPtr, + FnPtrToPtr => stable_mir::mir::CastKind::FnPtrToPtr, + Transmute => stable_mir::mir::CastKind::Transmute, + } + } +} + +impl Stable for ty::adjustment::PointerCoercion { + type T = stable_mir::mir::PointerCoercion; + fn stable(&self) -> Self::T { + use ty::adjustment::PointerCoercion; + match self { + PointerCoercion::ReifyFnPointer => stable_mir::mir::PointerCoercion::ReifyFnPointer, + PointerCoercion::UnsafeFnPointer => stable_mir::mir::PointerCoercion::UnsafeFnPointer, + PointerCoercion::ClosureFnPointer(unsafety) => { + stable_mir::mir::PointerCoercion::ClosureFnPointer(unsafety.stable()) + } + PointerCoercion::MutToConstPointer => { + stable_mir::mir::PointerCoercion::MutToConstPointer + } + PointerCoercion::ArrayToPointer => stable_mir::mir::PointerCoercion::ArrayToPointer, + PointerCoercion::Unsize => stable_mir::mir::PointerCoercion::Unsize, + } + } +} + +impl Stable for rustc_hir::Unsafety { + type T = stable_mir::mir::Safety; + fn stable(&self) -> Self::T { + match self { + rustc_hir::Unsafety::Unsafe => stable_mir::mir::Safety::Unsafe, + rustc_hir::Unsafety::Normal => stable_mir::mir::Safety::Normal, + } + } +} + +impl Stable for FieldIdx { + type T = usize; + fn stable(&self) -> Self::T { + self.as_usize() + } +} + impl<'tcx> Stable for mir::Operand<'tcx> { type T = stable_mir::mir::Operand; fn stable(&self) -> Self::T { diff --git a/compiler/rustc_smir/src/stable_mir/mir/body.rs b/compiler/rustc_smir/src/stable_mir/mir/body.rs index 468e915d1a073..fa3b0d6c5596b 100644 --- a/compiler/rustc_smir/src/stable_mir/mir/body.rs +++ b/compiler/rustc_smir/src/stable_mir/mir/body.rs @@ -1,4 +1,5 @@ -use crate::stable_mir::ty::Ty; +use crate::rustc_internal::Opaque; +use crate::stable_mir::{self, ty::Ty}; #[derive(Clone, Debug)] pub struct Body { @@ -136,12 +137,98 @@ pub enum Statement { Nop, } +type Region = Opaque; + // FIXME this is incomplete #[derive(Clone, Debug)] pub enum Rvalue { - Use(Operand), + /// Creates a pointer with the indicated mutability to the place. + /// + /// This is generated by pointer casts like `&v as *const _` or raw address of expressions like + /// `&raw v` or `addr_of!(v)`. + AddressOf(Mutability, Place), + + /// * `Offset` has the same semantics as [`offset`](pointer::offset), except that the second + /// parameter may be a `usize` as well. + /// * The comparison operations accept `bool`s, `char`s, signed or unsigned integers, floats, + /// raw pointers, or function pointers and return a `bool`. The types of the operands must be + /// matching, up to the usual caveat of the lifetimes in function pointers. + /// * Left and right shift operations accept signed or unsigned integers not necessarily of the + /// same type and return a value of the same type as their LHS. Like in Rust, the RHS is + /// truncated as needed. + /// * The `Bit*` operations accept signed integers, unsigned integers, or bools with matching + /// types and return a value of that type. + /// * The remaining operations accept signed integers, unsigned integers, or floats with + /// matching types and return a value of that type. + BinaryOp(BinOp, Operand, Operand), + + /// Performs essentially all of the casts that can be performed via `as`. + /// + /// This allows for casts from/to a variety of types. + Cast(CastKind, Operand, Ty), + + /// Same as `BinaryOp`, but yields `(T, bool)` with a `bool` indicating an error condition. + /// + /// For addition, subtraction, and multiplication on integers the error condition is set when + /// the infinite precision result would not be equal to the actual result. CheckedBinaryOp(BinOp, Operand, Operand), + + /// A CopyForDeref is equivalent to a read from a place. + /// When such a read happens, it is guaranteed that the only use of the returned value is a + /// deref operation, immediately followed by one or more projections. + CopyForDeref(Place), + + /// Computes the discriminant of the place, returning it as an integer of type + /// [`discriminant_ty`]. Returns zero for types without discriminant. + /// + /// The validity requirements for the underlying value are undecided for this rvalue, see + /// [#91095]. Note too that the value of the discriminant is not the same thing as the + /// variant index; use [`discriminant_for_variant`] to convert. + /// + /// [`discriminant_ty`]: crate::ty::Ty::discriminant_ty + /// [#91095]: https://github.com/rust-lang/rust/issues/91095 + /// [`discriminant_for_variant`]: crate::ty::Ty::discriminant_for_variant + Discriminant(Place), + + /// Yields the length of the place, as a `usize`. + /// + /// If the type of the place is an array, this is the array length. For slices (`[T]`, not + /// `&[T]`) this accesses the place's metadata to determine the length. This rvalue is + /// ill-formed for places of other types. + Len(Place), + + /// Creates a reference to the place. + Ref(Region, BorrowKind, Place), + + /// Transmutes a `*mut u8` into shallow-initialized `Box`. + /// + /// This is different from a normal transmute because dataflow analysis will treat the box as + /// initialized but its content as uninitialized. Like other pointer casts, this in general + /// affects alias analysis. + ShallowInitBox(Operand, Ty), + + /// Creates a pointer/reference to the given thread local. + /// + /// The yielded type is a `*mut T` if the static is mutable, otherwise if the static is extern a + /// `*const T`, and if neither of those apply a `&T`. + /// + /// **Note:** This is a runtime operation that actually executes code and is in this sense more + /// like a function call. Also, eliminating dead stores of this rvalue causes `fn main() {}` to + /// SIGILL for some reason that I (JakobDegen) never got a chance to look into. + /// + /// **Needs clarification**: Are there weird additional semantics here related to the runtime + /// nature of this operation? + ThreadLocalRef(stable_mir::CrateItem), + + /// Exactly like `BinaryOp`, but less operands. + /// + /// Also does two's-complement arithmetic. Negation requires a signed integer or a float; + /// bitwise not requires a signed integer, unsigned integer, or bool. Both operation kinds + /// return a value with the same type as their operand. UnaryOp(UnOp, Operand), + + /// Yields the operand unchanged + Use(Operand), } #[derive(Clone, Debug)] @@ -157,8 +244,98 @@ pub struct Place { pub projection: String, } +type FieldIdx = usize; + #[derive(Clone, Debug)] pub struct SwitchTarget { pub value: u128, pub target: usize, } + +#[derive(Clone, Debug)] +pub enum BorrowKind { + /// Data must be immutable and is aliasable. + Shared, + + /// The immediately borrowed place must be immutable, but projections from + /// it don't need to be. For example, a shallow borrow of `a.b` doesn't + /// conflict with a mutable borrow of `a.b.c`. + Shallow, + + /// Data is mutable and not aliasable. + Mut { + /// `true` if this borrow arose from method-call auto-ref + kind: MutBorrowKind, + }, +} + +#[derive(Clone, Debug)] +pub enum MutBorrowKind { + Default, + TwoPhaseBorrow, + ClosureCapture, +} + +#[derive(Clone, Debug)] +pub enum Mutability { + Not, + Mut, +} + +#[derive(Clone, Debug)] +pub enum Safety { + Unsafe, + Normal, +} + +#[derive(Clone, Debug)] +pub enum PointerCoercion { + /// Go from a fn-item type to a fn-pointer type. + ReifyFnPointer, + + /// Go from a safe fn pointer to an unsafe fn pointer. + UnsafeFnPointer, + + /// Go from a non-capturing closure to an fn pointer or an unsafe fn pointer. + /// It cannot convert a closure that requires unsafe. + ClosureFnPointer(Safety), + + /// Go from a mut raw pointer to a const raw pointer. + MutToConstPointer, + + /// Go from `*const [T; N]` to `*const T` + ArrayToPointer, + + /// Unsize a pointer/reference value, e.g., `&[T; n]` to + /// `&[T]`. Note that the source could be a thin or fat pointer. + /// This will do things like convert thin pointers to fat + /// pointers, or convert structs containing thin pointers to + /// structs containing fat pointers, or convert between fat + /// pointers. + Unsize, +} + +#[derive(Clone, Debug)] +pub enum CastKind { + PointerExposeAddress, + PointerFromExposedAddress, + PointerCoercion(PointerCoercion), + DynStar, + IntToInt, + FloatToInt, + FloatToFloat, + IntToFloat, + PtrToPtr, + FnPtrToPtr, + Transmute, +} + +#[derive(Clone, Debug)] +pub enum NullOp { + /// Returns the size of a value of that type. + SizeOf, + /// Returns the minimum alignment of a type. + AlignOf, + /// Returns the offset of a field. + OffsetOf(Vec), +} From 094cb1a9fbb6b2c9b6094cd6424139f70f8912cc Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Mon, 10 Jul 2023 01:45:31 -0700 Subject: [PATCH 16/16] Dynamically size sigaltstk in rustc rustc installs a signal stack that assumes that MINSIGSTKSZ is a constant, unchanging value. Newer hardware undermines that assumption greatly, with register files larger than MINSIGSTKZ. Properly handle this so that it is correct on all supported Linux versions with all CPUs. --- compiler/rustc_driver_impl/src/lib.rs | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 9352fe3147e59..2e26ce111f01d 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -1453,13 +1453,13 @@ mod signal_handler { /// When an error signal (such as SIGABRT or SIGSEGV) is delivered to the /// process, print a stack trace and then exit. pub(super) fn install() { + use std::alloc::{alloc, Layout}; + unsafe { - const ALT_STACK_SIZE: usize = libc::MINSIGSTKSZ + 64 * 1024; + let alt_stack_size: usize = min_sigstack_size() + 64 * 1024; let mut alt_stack: libc::stack_t = std::mem::zeroed(); - alt_stack.ss_sp = - std::alloc::alloc(std::alloc::Layout::from_size_align(ALT_STACK_SIZE, 1).unwrap()) - as *mut libc::c_void; - alt_stack.ss_size = ALT_STACK_SIZE; + alt_stack.ss_sp = alloc(Layout::from_size_align(alt_stack_size, 1).unwrap()).cast(); + alt_stack.ss_size = alt_stack_size; libc::sigaltstack(&alt_stack, std::ptr::null_mut()); let mut sa: libc::sigaction = std::mem::zeroed(); @@ -1469,6 +1469,23 @@ mod signal_handler { libc::sigaction(libc::SIGSEGV, &sa, std::ptr::null_mut()); } } + + /// Modern kernels on modern hardware can have dynamic signal stack sizes. + #[cfg(any(target_os = "linux", target_os = "android"))] + fn min_sigstack_size() -> usize { + const AT_MINSIGSTKSZ: core::ffi::c_ulong = 51; + let dynamic_sigstksz = unsafe { libc::getauxval(AT_MINSIGSTKSZ) }; + // If getauxval couldn't find the entry, it returns 0, + // so take the higher of the "constant" and auxval. + // This transparently supports older kernels which don't provide AT_MINSIGSTKSZ + libc::MINSIGSTKSZ.max(dynamic_sigstksz as _) + } + + /// Not all OS support hardware where this is needed. + #[cfg(not(any(target_os = "linux", target_os = "android")))] + fn min_sigstack_size() -> usize { + libc::MINSIGSTKSZ + } } #[cfg(not(all(unix, any(target_env = "gnu", target_os = "macos"))))]