summaryrefslogtreecommitdiffstats
path: root/src/tools/compiletest
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-07 05:48:48 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-07 05:48:48 +0000
commitef24de24a82fe681581cc130f342363c47c0969a (patch)
tree0d494f7e1a38b95c92426f58fe6eaa877303a86c /src/tools/compiletest
parentReleasing progress-linux version 1.74.1+dfsg1-1~progress7.99u1. (diff)
downloadrustc-ef24de24a82fe681581cc130f342363c47c0969a.tar.xz
rustc-ef24de24a82fe681581cc130f342363c47c0969a.zip
Merging upstream version 1.75.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/tools/compiletest')
-rw-r--r--src/tools/compiletest/Cargo.toml1
-rw-r--r--src/tools/compiletest/src/common.rs23
-rw-r--r--src/tools/compiletest/src/header.rs14
-rw-r--r--src/tools/compiletest/src/header/needs.rs4
-rw-r--r--src/tools/compiletest/src/header/tests.rs2
-rw-r--r--src/tools/compiletest/src/lib.rs12
-rw-r--r--src/tools/compiletest/src/runtest.rs145
7 files changed, 125 insertions, 76 deletions
diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml
index bb1fa6e92..31c6353e6 100644
--- a/src/tools/compiletest/Cargo.toml
+++ b/src/tools/compiletest/Cargo.toml
@@ -11,6 +11,7 @@ colored = "2"
diff = "0.1.10"
unified-diff = "0.2.1"
getopts = "0.2"
+indexmap = "2.0.0"
miropt-test-tools = { path = "../miropt-test-tools" }
build_helper = { path = "../build_helper" }
tracing = "0.1"
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index 0e1bf0c6c..1e9684555 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -8,6 +8,7 @@ use std::process::Command;
use std::str::FromStr;
use crate::util::{add_dylib_path, PathBufExt};
+use build_helper::git::GitConfig;
use lazycell::AtomicLazyCell;
use serde::de::{Deserialize, Deserializer, Error as _};
use std::collections::{HashMap, HashSet};
@@ -67,7 +68,7 @@ string_enum! {
MirOpt => "mir-opt",
Assembly => "assembly",
CoverageMap => "coverage-map",
- RunCoverage => "run-coverage",
+ CoverageRun => "coverage-run",
}
}
@@ -78,7 +79,7 @@ impl Default for Mode {
}
impl Mode {
- pub fn disambiguator(self) -> &'static str {
+ pub fn aux_dir_disambiguator(self) -> &'static str {
// Pretty-printing tests could run concurrently, and if they do,
// they need to keep their output segregated.
match self {
@@ -86,6 +87,15 @@ impl Mode {
_ => "",
}
}
+
+ pub fn output_dir_disambiguator(self) -> &'static str {
+ // Coverage tests use the same test files for multiple test modes,
+ // so each mode should have a separate output directory.
+ match self {
+ CoverageMap | CoverageRun => self.to_str(),
+ _ => "",
+ }
+ }
}
string_enum! {
@@ -370,6 +380,10 @@ pub struct Config {
pub target_cfgs: AtomicLazyCell<TargetCfgs>,
pub nocapture: bool,
+
+ // Needed both to construct build_helper::git::GitConfig
+ pub git_repository: String,
+ pub nightly_branch: String,
}
impl Config {
@@ -441,6 +455,10 @@ impl Config {
];
ASM_SUPPORTED_ARCHS.contains(&self.target_cfg().arch.as_str())
}
+
+ pub fn git_config(&self) -> GitConfig<'_> {
+ GitConfig { git_repository: &self.git_repository, nightly_branch: &self.nightly_branch }
+ }
}
#[derive(Debug, Clone)]
@@ -699,6 +717,7 @@ pub fn output_testname_unique(
let mode = config.compare_mode.as_ref().map_or("", |m| m.to_str());
let debugger = config.debugger.as_ref().map_or("", |m| m.to_str());
PathBuf::from(&testpaths.file.file_stem().unwrap())
+ .with_extra_extension(config.mode.output_dir_disambiguator())
.with_extra_extension(revision.unwrap_or(""))
.with_extra_extension(mode)
.with_extra_extension(debugger)
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 269d93843..d6516cff6 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -322,7 +322,15 @@ impl TestProps {
);
if let Some(flags) = config.parse_name_value_directive(ln, COMPILE_FLAGS) {
- self.compile_flags.extend(flags.split_whitespace().map(|s| s.to_owned()));
+ self.compile_flags.extend(
+ flags
+ .split("'")
+ .enumerate()
+ .flat_map(|(i, f)| {
+ if i % 2 == 1 { vec![f] } else { f.split_whitespace().collect() }
+ })
+ .map(|s| s.to_owned()),
+ );
}
if config.parse_name_value_directive(ln, INCORRECT_COMPILER_FLAGS).is_some() {
panic!("`compiler-flags` directive should be spelled `compile-flags`");
@@ -903,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/header/needs.rs b/src/tools/compiletest/src/header/needs.rs
index 2b7a4387c..4a40fb55f 100644
--- a/src/tools/compiletest/src/header/needs.rs
+++ b/src/tools/compiletest/src/header/needs.rs
@@ -241,8 +241,8 @@ impl CachedNeedsConditions {
profiler_support: std::env::var_os("RUSTC_PROFILER_SUPPORT").is_some(),
xray: config.target_cfg().xray,
- // For tests using the `needs-rust-lld` directive (e.g. for `-Zgcc-ld=lld`), we need to find
- // whether `rust-lld` is present in the compiler under test.
+ // For tests using the `needs-rust-lld` directive (e.g. for `-Clink-self-contained=+linker`),
+ // we need to find whether `rust-lld` is present in the compiler under test.
//
// The --compile-lib-path is the path to host shared libraries, but depends on the OS. For
// example:
diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs
index 2fd80b52c..85e745bed 100644
--- a/src/tools/compiletest/src/header/tests.rs
+++ b/src/tools/compiletest/src/header/tests.rs
@@ -126,6 +126,8 @@ impl ConfigBuilder {
self.host.as_deref().unwrap_or("x86_64-unknown-linux-gnu"),
"--target",
self.target.as_deref().unwrap_or("x86_64-unknown-linux-gnu"),
+ "--git-repository=",
+ "--nightly-branch=",
];
let mut args: Vec<String> = args.iter().map(ToString::to_string).collect();
diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs
index 619ff9b32..bb09c03ef 100644
--- a/src/tools/compiletest/src/lib.rs
+++ b/src/tools/compiletest/src/lib.rs
@@ -144,7 +144,9 @@ pub fn parse_config(args: Vec<String>) -> Config {
.optflag("h", "help", "show this message")
.reqopt("", "channel", "current Rust channel", "CHANNEL")
.optflag("", "git-hash", "run tests which rely on commit version being compiled into the binaries")
- .optopt("", "edition", "default Rust edition", "EDITION");
+ .optopt("", "edition", "default Rust edition", "EDITION")
+ .reqopt("", "git-repository", "name of the git repository", "ORG/REPO")
+ .reqopt("", "nightly-branch", "name of the git branch for nightly", "BRANCH");
let (argv0, args_) = args.split_first().unwrap();
if args.len() == 1 || args[1] == "-h" || args[1] == "--help" {
@@ -307,6 +309,9 @@ pub fn parse_config(args: Vec<String>) -> Config {
target_cfgs: AtomicLazyCell::new(),
nocapture: matches.opt_present("nocapture"),
+
+ git_repository: matches.opt_str("git-repository").unwrap(),
+ nightly_branch: matches.opt_str("nightly-branch").unwrap(),
}
}
@@ -609,9 +614,10 @@ fn modified_tests(config: &Config, dir: &Path) -> Result<Vec<PathBuf>, String> {
return Ok(vec![]);
}
let files =
- get_git_modified_files(Some(dir), &vec!["rs", "stderr", "fixed"])?.unwrap_or(vec![]);
+ get_git_modified_files(&config.git_config(), Some(dir), &vec!["rs", "stderr", "fixed"])?
+ .unwrap_or(vec![]);
// Add new test cases to the list, it will be convenient in daily development.
- let untracked_files = get_git_untracked_files(None)?.unwrap_or(vec![]);
+ let untracked_files = get_git_untracked_files(&config.git_config(), None)?.unwrap_or(vec![]);
let all_paths = [&files[..], &untracked_files[..]].concat();
let full_paths = {
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 657d074b3..63e8ba7c7 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};
@@ -15,6 +15,7 @@ use crate::json;
use crate::read2::{read2_abbreviated, Truncated};
use crate::util::{add_dylib_path, dylib_env_var, logv, PathBufExt};
use crate::ColorConfig;
+use miropt_test_tools::{files_for_miropt_test, MiroptTest, MiroptTestFile};
use regex::{Captures, Regex};
use rustfix::{apply_suggestions, get_suggestions_from_json, Filter};
@@ -229,6 +230,7 @@ enum Emit {
None,
Metadata,
LlvmIr,
+ Mir,
Asm,
LinkArgsAsm,
}
@@ -255,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(),
}
}
@@ -508,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);
@@ -547,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);
}
@@ -2191,7 +2193,7 @@ impl<'test> TestCx<'test> {
|| self.is_vxworks_pure_static()
|| self.config.target.contains("bpf")
|| !self.config.target_cfg().dynamic_linking
- || self.config.mode == 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
@@ -2335,17 +2337,14 @@ impl<'test> TestCx<'test> {
rustc.arg("-Zsimulate-remapped-rust-src-base=/rustc/FAKE_PREFIX");
rustc.arg("-Ztranslate-remapped-path-to-local-path=no");
- // #[cfg(not(bootstrap))]: After beta bump, this should **always** run.
- if !(self.config.stage_id.starts_with("stage1-") && self.config.suite == "ui-fulldeps") {
- // Hide Cargo dependency sources from ui tests to make sure the error message doesn't
- // change depending on whether $CARGO_HOME is remapped or not. If this is not present,
- // when $CARGO_HOME is remapped the source won't be shown, and when it's not remapped the
- // source will be shown, causing a blessing hell.
- rustc.arg("-Z").arg(format!(
- "ignore-directory-in-diagnostics-source-blocks={}",
- home::cargo_home().expect("failed to find cargo home").to_str().unwrap()
- ));
- }
+ // Hide Cargo dependency sources from ui tests to make sure the error message doesn't
+ // change depending on whether $CARGO_HOME is remapped or not. If this is not present,
+ // when $CARGO_HOME is remapped the source won't be shown, and when it's not remapped the
+ // source will be shown, causing a blessing hell.
+ rustc.arg("-Z").arg(format!(
+ "ignore-directory-in-diagnostics-source-blocks={}",
+ home::cargo_home().expect("failed to find cargo home").to_str().unwrap()
+ ));
// Optionally prevent default --sysroot if specified in test compile-flags.
if !self.props.compile_flags.iter().any(|flag| flag.starts_with("--sysroot"))
@@ -2396,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
@@ -2471,7 +2470,7 @@ impl<'test> TestCx<'test> {
}
CoverageMap => {
rustc.arg("-Cinstrument-coverage");
- // These tests only compile to MIR, so they don't need the
+ // These tests only compile to LLVM IR, so they don't need the
// profiler runtime to be present.
rustc.arg("-Zno-profiler-runtime");
// Coverage mappings are sensitive to MIR optimizations, and
@@ -2479,12 +2478,12 @@ 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 no optimization unless
+ // and the current snapshots assume `opt-level=2` unless
// overridden by `compile-flags`.
- rustc.arg("-Copt-level=0");
+ rustc.arg("-Copt-level=2");
}
RunPassValgrind | Pretty | DebugInfo | Codegen | Rustdoc | RustdocJson | RunMake
| CodegenUnits | JsDocTest | Assembly => {
@@ -2509,6 +2508,9 @@ impl<'test> TestCx<'test> {
Emit::LlvmIr => {
rustc.args(&["--emit", "llvm-ir"]);
}
+ Emit::Mir => {
+ rustc.args(&["--emit", "mir"]);
+ }
Emit::Asm => {
rustc.args(&["--emit", "asm"]);
}
@@ -2718,7 +2720,7 @@ impl<'test> TestCx<'test> {
fn aux_output_dir_name(&self) -> PathBuf {
self.output_base_dir()
.join("auxiliary")
- .with_extra_extension(self.config.mode.disambiguator())
+ .with_extra_extension(self.config.mode.aux_dir_disambiguator())
}
/// Generates a unique name for the test, such as `testname.revision.mode`.
@@ -3544,10 +3546,6 @@ impl<'test> TestCx<'test> {
cmd.env("RUSTDOC", cwd.join(rustdoc));
}
- if let Some(ref rust_demangler) = self.config.rust_demangler_path {
- cmd.env("RUST_DEMANGLER", cwd.join(rust_demangler));
- }
-
if let Some(ref node) = self.config.nodejs {
cmd.env("NODE", node);
}
@@ -3964,7 +3962,7 @@ impl<'test> TestCx<'test> {
// And finally, compile the fixed code and make sure it both
// succeeds and has no diagnostics.
let rustc = self.make_compile_args(
- &self.testpaths.file.with_extension(UI_FIXED),
+ &self.expected_output_path(UI_FIXED),
TargetLocation::ThisFile(self.make_exe_name()),
emit_metadata,
AllowUnused::No,
@@ -3987,14 +3985,20 @@ impl<'test> TestCx<'test> {
fn run_mir_opt_test(&self) {
let pm = self.pass_mode();
let should_run = self.should_run(pm);
- let emit_metadata = self.should_emit_metadata(pm);
- let passes = self.get_passes();
- let proc_res = self.compile_test_with_passes(should_run, emit_metadata, passes);
- self.check_mir_dump();
+ let mut test_info = files_for_miropt_test(
+ &self.testpaths.file,
+ self.config.get_pointer_width(),
+ self.config.target_cfg().panic.for_miropt_test_tools(),
+ );
+
+ let passes = std::mem::take(&mut test_info.passes);
+
+ let proc_res = self.compile_test_with_passes(should_run, Emit::Mir, passes);
if !proc_res.status.success() {
self.fatal_proc_rec("compilation failed!", &proc_res);
}
+ self.check_mir_dump(test_info);
if let WillExecute::Yes = should_run {
let proc_res = self.exec_compiled_test();
@@ -4005,37 +4009,12 @@ impl<'test> TestCx<'test> {
}
}
- fn get_passes(&self) -> Vec<String> {
- let files = miropt_test_tools::files_for_miropt_test(
- &self.testpaths.file,
- self.config.get_pointer_width(),
- self.config.target_cfg().panic.for_miropt_test_tools(),
- );
-
- let mut out = Vec::new();
-
- for miropt_test_tools::MiroptTestFiles {
- from_file: _,
- to_file: _,
- expected_file: _,
- passes,
- } in files
- {
- out.extend(passes);
- }
- out
- }
-
- fn check_mir_dump(&self) {
+ fn check_mir_dump(&self, test_info: MiroptTest) {
let test_dir = self.testpaths.file.parent().unwrap();
let test_crate =
self.testpaths.file.file_stem().unwrap().to_str().unwrap().replace("-", "_");
- let suffix = miropt_test_tools::output_file_suffix(
- &self.testpaths.file,
- self.config.get_pointer_width(),
- self.config.target_cfg().panic.for_miropt_test_tools(),
- );
+ let MiroptTest { run_filecheck, suffix, files, passes: _ } = test_info;
if self.config.bless {
for e in
@@ -4050,14 +4029,7 @@ impl<'test> TestCx<'test> {
}
}
- let files = miropt_test_tools::files_for_miropt_test(
- &self.testpaths.file,
- self.config.get_pointer_width(),
- self.config.target_cfg().panic.for_miropt_test_tools(),
- );
- for miropt_test_tools::MiroptTestFiles { from_file, to_file, expected_file, passes: _ } in
- files
- {
+ for MiroptTestFile { from_file, to_file, expected_file } in files {
let dumped_string = if let Some(after) = to_file {
self.diff_mir_files(from_file.into(), after.into())
} else {
@@ -4098,6 +4070,14 @@ impl<'test> TestCx<'test> {
}
}
}
+
+ if run_filecheck {
+ let output_path = self.output_base_name().with_extension("mir");
+ let proc_res = self.verify_with_filecheck(&output_path);
+ if !proc_res.status.success() {
+ self.fatal_proc_rec("verification with 'FileCheck' failed", &proc_res);
+ }
+ }
}
fn diff_mir_files(&self, before: PathBuf, after: PathBuf) -> String {
@@ -4261,6 +4241,39 @@ impl<'test> TestCx<'test> {
V0_BACK_REF_RE.replace_all(&normalized, V0_BACK_REF_PLACEHOLDER).into_owned();
}
+ // AllocId are numbered globally in a compilation session. This can lead to changes
+ // depending on the exact compilation flags and host architecture. Meanwhile, we want
+ // to keep them numbered, to see if the same id appears multiple times.
+ // So we remap to deterministic numbers that only depend on the subset of allocations
+ // that actually appear in the output.
+ // We use uppercase ALLOC to distinguish from the non-normalized version.
+ {
+ let mut seen_allocs = indexmap::IndexSet::new();
+
+ // The alloc-id appears in pretty-printed allocations.
+ let re = Regex::new(r"╾─*a(lloc)?([0-9]+)(\+0x[0-9]+)?─*╼").unwrap();
+ normalized = re
+ .replace_all(&normalized, |caps: &Captures<'_>| {
+ // Renumber the captured index.
+ let index = caps.get(2).unwrap().as_str().to_string();
+ let (index, _) = seen_allocs.insert_full(index);
+ let offset = caps.get(3).map_or("", |c| c.as_str());
+ // Do not bother keeping it pretty, just make it deterministic.
+ format!("╾ALLOC{index}{offset}╼")
+ })
+ .into_owned();
+
+ // The alloc-id appears in a sentence.
+ let re = Regex::new(r"\balloc([0-9]+)\b").unwrap();
+ normalized = re
+ .replace_all(&normalized, |caps: &Captures<'_>| {
+ let index = caps.get(1).unwrap().as_str().to_string();
+ let (index, _) = seen_allocs.insert_full(index);
+ format!("ALLOC{index}")
+ })
+ .into_owned();
+ }
+
// Custom normalization rules
for rule in custom_rules {
let re = Regex::new(&rule.0).expect("bad regex in custom normalization rule");