refactor needs, validate them, and add ignore reasons
This commit is contained in:
parent
89281b3aa4
commit
aea43673f2
@ -11,10 +11,10 @@
|
|||||||
use crate::common::{Config, Debugger, FailMode, Mode, PassMode};
|
use crate::common::{Config, Debugger, FailMode, Mode, PassMode};
|
||||||
use crate::header::cfg::parse_cfg_name_directive;
|
use crate::header::cfg::parse_cfg_name_directive;
|
||||||
use crate::header::cfg::MatchOutcome;
|
use crate::header::cfg::MatchOutcome;
|
||||||
use crate::util;
|
|
||||||
use crate::{extract_cdb_version, extract_gdb_version};
|
use crate::{extract_cdb_version, extract_gdb_version};
|
||||||
|
|
||||||
mod cfg;
|
mod cfg;
|
||||||
|
mod needs;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
@ -660,14 +660,6 @@ fn parse_custom_normalization(&self, mut line: &str, prefix: &str) -> Option<(St
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_needs_matching_clang(&self, line: &str) -> bool {
|
|
||||||
self.parse_name_directive(line, "needs-matching-clang")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_needs_profiler_support(&self, line: &str) -> bool {
|
|
||||||
self.parse_name_directive(line, "needs-profiler-support")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn has_cfg_prefix(&self, line: &str, prefix: &str) -> bool {
|
fn has_cfg_prefix(&self, line: &str, prefix: &str) -> bool {
|
||||||
// returns whether this line contains this prefix or not. For prefix
|
// returns whether this line contains this prefix or not. For prefix
|
||||||
// "ignore", returns true if line says "ignore-x86_64", "ignore-arch",
|
// "ignore", returns true if line says "ignore-x86_64", "ignore-arch",
|
||||||
@ -871,69 +863,13 @@ pub fn make_test_description<R: Read>(
|
|||||||
let mut ignore_message = None;
|
let mut ignore_message = None;
|
||||||
let mut should_fail = false;
|
let mut should_fail = false;
|
||||||
|
|
||||||
let rustc_has_profiler_support = env::var_os("RUSTC_PROFILER_SUPPORT").is_some();
|
let needs_cache = needs::CachedNeedsConditions::load(config);
|
||||||
let rustc_has_sanitizer_support = env::var_os("RUSTC_SANITIZER_SUPPORT").is_some();
|
|
||||||
let has_asm_support = config.has_asm_support();
|
|
||||||
let has_asan = util::ASAN_SUPPORTED_TARGETS.contains(&&*config.target);
|
|
||||||
let has_cfi = util::CFI_SUPPORTED_TARGETS.contains(&&*config.target);
|
|
||||||
let has_kcfi = util::KCFI_SUPPORTED_TARGETS.contains(&&*config.target);
|
|
||||||
let has_kasan = util::KASAN_SUPPORTED_TARGETS.contains(&&*config.target);
|
|
||||||
let has_lsan = util::LSAN_SUPPORTED_TARGETS.contains(&&*config.target);
|
|
||||||
let has_msan = util::MSAN_SUPPORTED_TARGETS.contains(&&*config.target);
|
|
||||||
let has_tsan = util::TSAN_SUPPORTED_TARGETS.contains(&&*config.target);
|
|
||||||
let has_hwasan = util::HWASAN_SUPPORTED_TARGETS.contains(&&*config.target);
|
|
||||||
let has_memtag = util::MEMTAG_SUPPORTED_TARGETS.contains(&&*config.target);
|
|
||||||
let has_shadow_call_stack = util::SHADOWCALLSTACK_SUPPORTED_TARGETS.contains(&&*config.target);
|
|
||||||
let has_xray = util::XRAY_SUPPORTED_TARGETS.contains(&&*config.target);
|
|
||||||
|
|
||||||
// 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.
|
|
||||||
//
|
|
||||||
// The --compile-lib-path is the path to host shared libraries, but depends on the OS. For
|
|
||||||
// example:
|
|
||||||
// - on linux, it can be <sysroot>/lib
|
|
||||||
// - on windows, it can be <sysroot>/bin
|
|
||||||
//
|
|
||||||
// However, `rust-lld` is only located under the lib path, so we look for it there.
|
|
||||||
let has_rust_lld = config
|
|
||||||
.compile_lib_path
|
|
||||||
.parent()
|
|
||||||
.expect("couldn't traverse to the parent of the specified --compile-lib-path")
|
|
||||||
.join("lib")
|
|
||||||
.join("rustlib")
|
|
||||||
.join(&config.target)
|
|
||||||
.join("bin")
|
|
||||||
.join(if config.host.contains("windows") { "rust-lld.exe" } else { "rust-lld" })
|
|
||||||
.exists();
|
|
||||||
|
|
||||||
fn is_on_path(file: &'static str) -> impl Fn() -> bool {
|
|
||||||
move || env::split_paths(&env::var_os("PATH").unwrap()).any(|dir| dir.join(file).is_file())
|
|
||||||
}
|
|
||||||
|
|
||||||
// On Windows, dlltool.exe is used for all architectures.
|
|
||||||
#[cfg(windows)]
|
|
||||||
let (has_i686_dlltool, has_x86_64_dlltool) =
|
|
||||||
(is_on_path("dlltool.exe"), is_on_path("dlltool.exe"));
|
|
||||||
// For non-Windows, there are architecture specific dlltool binaries.
|
|
||||||
#[cfg(not(windows))]
|
|
||||||
let (has_i686_dlltool, has_x86_64_dlltool) =
|
|
||||||
(is_on_path("i686-w64-mingw32-dlltool"), is_on_path("x86_64-w64-mingw32-dlltool"));
|
|
||||||
|
|
||||||
iter_header(path, src, &mut |revision, ln| {
|
iter_header(path, src, &mut |revision, ln| {
|
||||||
if revision.is_some() && revision != cfg {
|
if revision.is_some() && revision != cfg {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
macro_rules! reason {
|
|
||||||
($e:expr) => {
|
|
||||||
ignore |= match $e {
|
|
||||||
true => {
|
|
||||||
ignore_message = Some(stringify!($e));
|
|
||||||
true
|
|
||||||
}
|
|
||||||
false => ignore,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
macro_rules! decision {
|
macro_rules! decision {
|
||||||
($e:expr) => {
|
($e:expr) => {
|
||||||
match $e {
|
match $e {
|
||||||
@ -944,6 +880,10 @@ macro_rules! decision {
|
|||||||
// compiletest so it won't grow indefinitely.
|
// compiletest so it won't grow indefinitely.
|
||||||
ignore_message = Some(Box::leak(Box::<str>::from(reason)));
|
ignore_message = Some(Box::leak(Box::<str>::from(reason)));
|
||||||
}
|
}
|
||||||
|
IgnoreDecision::Error { message } => {
|
||||||
|
eprintln!("error: {}: {message}", path.display());
|
||||||
|
panic!();
|
||||||
|
}
|
||||||
IgnoreDecision::Continue => {}
|
IgnoreDecision::Continue => {}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -989,48 +929,27 @@ macro_rules! decision {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
decision!(needs::handle_needs(&needs_cache, config, ln));
|
||||||
decision!(ignore_llvm(config, ln));
|
decision!(ignore_llvm(config, ln));
|
||||||
decision!(ignore_cdb(config, ln));
|
decision!(ignore_cdb(config, ln));
|
||||||
decision!(ignore_gdb(config, ln));
|
decision!(ignore_gdb(config, ln));
|
||||||
decision!(ignore_lldb(config, ln));
|
decision!(ignore_lldb(config, ln));
|
||||||
|
|
||||||
reason!(
|
if config.target == "wasm32-unknown-unknown" {
|
||||||
config.run_clang_based_tests_with.is_none() && config.parse_needs_matching_clang(ln)
|
if config.parse_name_directive(ln, directives::CHECK_RUN_RESULTS) {
|
||||||
);
|
decision!(IgnoreDecision::Ignore {
|
||||||
reason!(!has_asm_support && config.parse_name_directive(ln, "needs-asm-support"));
|
reason: "ignored when checking the run results on WASM".into(),
|
||||||
reason!(!rustc_has_profiler_support && config.parse_needs_profiler_support(ln));
|
});
|
||||||
reason!(!config.run_enabled() && config.parse_name_directive(ln, "needs-run-enabled"));
|
}
|
||||||
reason!(
|
}
|
||||||
!rustc_has_sanitizer_support
|
|
||||||
&& config.parse_name_directive(ln, "needs-sanitizer-support")
|
if config.debugger == Some(Debugger::Lldb) && !config.lldb_native_rust {
|
||||||
);
|
if config.parse_name_directive(ln, "rust-lldb") {
|
||||||
reason!(!has_asan && config.parse_name_directive(ln, "needs-sanitizer-address"));
|
decision!(IgnoreDecision::Ignore {
|
||||||
reason!(!has_cfi && config.parse_name_directive(ln, "needs-sanitizer-cfi"));
|
reason: "ignored on targets wihtout Rust's LLDB".into()
|
||||||
reason!(!has_kcfi && config.parse_name_directive(ln, "needs-sanitizer-kcfi"));
|
});
|
||||||
reason!(!has_kasan && config.parse_name_directive(ln, "needs-sanitizer-kasan"));
|
}
|
||||||
reason!(!has_lsan && config.parse_name_directive(ln, "needs-sanitizer-leak"));
|
}
|
||||||
reason!(!has_msan && config.parse_name_directive(ln, "needs-sanitizer-memory"));
|
|
||||||
reason!(!has_tsan && config.parse_name_directive(ln, "needs-sanitizer-thread"));
|
|
||||||
reason!(!has_hwasan && config.parse_name_directive(ln, "needs-sanitizer-hwaddress"));
|
|
||||||
reason!(!has_memtag && config.parse_name_directive(ln, "needs-sanitizer-memtag"));
|
|
||||||
reason!(
|
|
||||||
!has_shadow_call_stack
|
|
||||||
&& config.parse_name_directive(ln, "needs-sanitizer-shadow-call-stack")
|
|
||||||
);
|
|
||||||
reason!(!config.can_unwind() && config.parse_name_directive(ln, "needs-unwind"));
|
|
||||||
reason!(!has_xray && config.parse_name_directive(ln, "needs-xray"));
|
|
||||||
reason!(
|
|
||||||
config.target == "wasm32-unknown-unknown"
|
|
||||||
&& config.parse_name_directive(ln, directives::CHECK_RUN_RESULTS)
|
|
||||||
);
|
|
||||||
reason!(!has_rust_lld && config.parse_name_directive(ln, "needs-rust-lld"));
|
|
||||||
reason!(config.parse_name_directive(ln, "needs-i686-dlltool") && !has_i686_dlltool());
|
|
||||||
reason!(config.parse_name_directive(ln, "needs-x86_64-dlltool") && !has_x86_64_dlltool());
|
|
||||||
reason!(
|
|
||||||
config.parse_name_directive(ln, "rust-lldb")
|
|
||||||
&& config.debugger == Some(Debugger::Lldb)
|
|
||||||
&& !config.lldb_native_rust
|
|
||||||
);
|
|
||||||
|
|
||||||
should_fail |= config.parse_name_directive(ln, "should-fail");
|
should_fail |= config.parse_name_directive(ln, "should-fail");
|
||||||
});
|
});
|
||||||
@ -1226,4 +1145,5 @@ fn ignore_llvm(config: &Config, line: &str) -> IgnoreDecision {
|
|||||||
enum IgnoreDecision {
|
enum IgnoreDecision {
|
||||||
Ignore { reason: String },
|
Ignore { reason: String },
|
||||||
Continue,
|
Continue,
|
||||||
|
Error { message: String },
|
||||||
}
|
}
|
||||||
|
226
src/tools/compiletest/src/header/needs.rs
Normal file
226
src/tools/compiletest/src/header/needs.rs
Normal file
@ -0,0 +1,226 @@
|
|||||||
|
use crate::common::Config;
|
||||||
|
use crate::header::IgnoreDecision;
|
||||||
|
use crate::util;
|
||||||
|
|
||||||
|
pub(super) fn handle_needs(
|
||||||
|
cache: &CachedNeedsConditions,
|
||||||
|
config: &Config,
|
||||||
|
ln: &str,
|
||||||
|
) -> IgnoreDecision {
|
||||||
|
// Note thet we intentionally still put the needs- prefix here to make the file show up when
|
||||||
|
// grepping for a directive name, even though we could technically strip that.
|
||||||
|
let needs = &[
|
||||||
|
Need {
|
||||||
|
name: "needs-asm-support",
|
||||||
|
condition: config.has_asm_support(),
|
||||||
|
ignore_reason: "ignored on targets without inline assembly support",
|
||||||
|
},
|
||||||
|
Need {
|
||||||
|
name: "needs-sanitizer-support",
|
||||||
|
condition: cache.sanitizer_support,
|
||||||
|
ignore_reason: "ignored on targets without sanitizers support",
|
||||||
|
},
|
||||||
|
Need {
|
||||||
|
name: "needs-sanitizer-address",
|
||||||
|
condition: cache.sanitizer_address,
|
||||||
|
ignore_reason: "ignored on targets without address sanitizer",
|
||||||
|
},
|
||||||
|
Need {
|
||||||
|
name: "needs-sanitizer-cfi",
|
||||||
|
condition: cache.sanitizer_cfi,
|
||||||
|
ignore_reason: "ignored on targets without CFI sanitizer",
|
||||||
|
},
|
||||||
|
Need {
|
||||||
|
name: "needs-sanitizer-kcfi",
|
||||||
|
condition: cache.sanitizer_kcfi,
|
||||||
|
ignore_reason: "ignored on targets without kernel CFI sanitizer",
|
||||||
|
},
|
||||||
|
Need {
|
||||||
|
name: "needs-sanitizer-kasan",
|
||||||
|
condition: cache.sanitizer_kasan,
|
||||||
|
ignore_reason: "ignored on targets without kernel address sanitizer",
|
||||||
|
},
|
||||||
|
Need {
|
||||||
|
name: "needs-sanitizer-leak",
|
||||||
|
condition: cache.sanitizer_leak,
|
||||||
|
ignore_reason: "ignored on targets without leak sanitizer",
|
||||||
|
},
|
||||||
|
Need {
|
||||||
|
name: "needs-sanitizer-memory",
|
||||||
|
condition: cache.sanitizer_memory,
|
||||||
|
ignore_reason: "ignored on targets without memory sanitizer",
|
||||||
|
},
|
||||||
|
Need {
|
||||||
|
name: "needs-sanitizer-thread",
|
||||||
|
condition: cache.sanitizer_thread,
|
||||||
|
ignore_reason: "ignored on targets without thread sanitizer",
|
||||||
|
},
|
||||||
|
Need {
|
||||||
|
name: "needs-sanitizer-hwaddress",
|
||||||
|
condition: cache.sanitizer_hwaddress,
|
||||||
|
ignore_reason: "ignored on targets without hardware-assisted address sanitizer",
|
||||||
|
},
|
||||||
|
Need {
|
||||||
|
name: "needs-sanitizer-memtag",
|
||||||
|
condition: cache.sanitizer_memtag,
|
||||||
|
ignore_reason: "ignored on targets without memory tagging sanitizer",
|
||||||
|
},
|
||||||
|
Need {
|
||||||
|
name: "needs-sanitizer-shadow-call-stack",
|
||||||
|
condition: cache.sanitizer_shadow_call_stack,
|
||||||
|
ignore_reason: "ignored on targets without shadow call stacks",
|
||||||
|
},
|
||||||
|
Need {
|
||||||
|
name: "needs-run-enabled",
|
||||||
|
condition: config.run_enabled(),
|
||||||
|
ignore_reason: "ignored when running the resulting test binaries is disabled",
|
||||||
|
},
|
||||||
|
Need {
|
||||||
|
name: "needs-unwind",
|
||||||
|
condition: config.can_unwind(),
|
||||||
|
ignore_reason: "ignored on targets without unwinding support",
|
||||||
|
},
|
||||||
|
Need {
|
||||||
|
name: "needs-profiler-support",
|
||||||
|
condition: std::env::var_os("RUSTC_PROFILER_SUPPORT").is_some(),
|
||||||
|
ignore_reason: "ignored when profiler support is disabled",
|
||||||
|
},
|
||||||
|
Need {
|
||||||
|
name: "needs-matching-clang",
|
||||||
|
condition: config.run_clang_based_tests_with.is_some(),
|
||||||
|
ignore_reason: "ignored when the used clang does not match the built LLVM",
|
||||||
|
},
|
||||||
|
Need {
|
||||||
|
name: "needs-xray",
|
||||||
|
condition: cache.xray,
|
||||||
|
ignore_reason: "ignored on targets without xray tracing",
|
||||||
|
},
|
||||||
|
Need {
|
||||||
|
name: "needs-rust-lld",
|
||||||
|
condition: cache.rust_lld,
|
||||||
|
ignore_reason: "ignored on targets without Rust's LLD",
|
||||||
|
},
|
||||||
|
Need {
|
||||||
|
name: "needs-i686-dlltool",
|
||||||
|
condition: cache.i686_dlltool,
|
||||||
|
ignore_reason: "ignored when dlltool for i686 is not present",
|
||||||
|
},
|
||||||
|
Need {
|
||||||
|
name: "needs-x86_64-dlltool",
|
||||||
|
condition: cache.x86_64_dlltool,
|
||||||
|
ignore_reason: "ignored when dlltool for x86_64 is not present",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
let (name, comment) = match ln.split_once([':', ' ']) {
|
||||||
|
Some((name, comment)) => (name, Some(comment)),
|
||||||
|
None => (ln, None),
|
||||||
|
};
|
||||||
|
|
||||||
|
if !name.starts_with("needs-") {
|
||||||
|
return IgnoreDecision::Continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut found_valid = false;
|
||||||
|
for need in needs {
|
||||||
|
if need.name == name {
|
||||||
|
if need.condition {
|
||||||
|
found_valid = true;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
return IgnoreDecision::Ignore {
|
||||||
|
reason: if let Some(comment) = comment {
|
||||||
|
format!("{} ({comment})", need.ignore_reason)
|
||||||
|
} else {
|
||||||
|
need.ignore_reason.into()
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if found_valid {
|
||||||
|
IgnoreDecision::Continue
|
||||||
|
} else {
|
||||||
|
IgnoreDecision::Error { message: format!("invalid needs directive: {name}") }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Need {
|
||||||
|
name: &'static str,
|
||||||
|
condition: bool,
|
||||||
|
ignore_reason: &'static str,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) struct CachedNeedsConditions {
|
||||||
|
sanitizer_support: bool,
|
||||||
|
sanitizer_address: bool,
|
||||||
|
sanitizer_cfi: bool,
|
||||||
|
sanitizer_kcfi: bool,
|
||||||
|
sanitizer_kasan: bool,
|
||||||
|
sanitizer_leak: bool,
|
||||||
|
sanitizer_memory: bool,
|
||||||
|
sanitizer_thread: bool,
|
||||||
|
sanitizer_hwaddress: bool,
|
||||||
|
sanitizer_memtag: bool,
|
||||||
|
sanitizer_shadow_call_stack: bool,
|
||||||
|
xray: bool,
|
||||||
|
rust_lld: bool,
|
||||||
|
i686_dlltool: bool,
|
||||||
|
x86_64_dlltool: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CachedNeedsConditions {
|
||||||
|
pub(super) fn load(config: &Config) -> Self {
|
||||||
|
let path = std::env::var_os("PATH").expect("missing PATH environment variable");
|
||||||
|
let path = std::env::split_paths(&path).collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let target = &&*config.target;
|
||||||
|
Self {
|
||||||
|
sanitizer_support: std::env::var_os("RUSTC_SANITIZER_SUPPORT").is_some(),
|
||||||
|
sanitizer_address: util::ASAN_SUPPORTED_TARGETS.contains(target),
|
||||||
|
sanitizer_cfi: util::CFI_SUPPORTED_TARGETS.contains(target),
|
||||||
|
sanitizer_kcfi: util::KCFI_SUPPORTED_TARGETS.contains(target),
|
||||||
|
sanitizer_kasan: util::KASAN_SUPPORTED_TARGETS.contains(target),
|
||||||
|
sanitizer_leak: util::LSAN_SUPPORTED_TARGETS.contains(target),
|
||||||
|
sanitizer_memory: util::MSAN_SUPPORTED_TARGETS.contains(target),
|
||||||
|
sanitizer_thread: util::TSAN_SUPPORTED_TARGETS.contains(target),
|
||||||
|
sanitizer_hwaddress: util::HWASAN_SUPPORTED_TARGETS.contains(target),
|
||||||
|
sanitizer_memtag: util::MEMTAG_SUPPORTED_TARGETS.contains(target),
|
||||||
|
sanitizer_shadow_call_stack: util::SHADOWCALLSTACK_SUPPORTED_TARGETS.contains(target),
|
||||||
|
xray: util::XRAY_SUPPORTED_TARGETS.contains(target),
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
// The --compile-lib-path is the path to host shared libraries, but depends on the OS. For
|
||||||
|
// example:
|
||||||
|
// - on linux, it can be <sysroot>/lib
|
||||||
|
// - on windows, it can be <sysroot>/bin
|
||||||
|
//
|
||||||
|
// However, `rust-lld` is only located under the lib path, so we look for it there.
|
||||||
|
rust_lld: config
|
||||||
|
.compile_lib_path
|
||||||
|
.parent()
|
||||||
|
.expect("couldn't traverse to the parent of the specified --compile-lib-path")
|
||||||
|
.join("lib")
|
||||||
|
.join("rustlib")
|
||||||
|
.join(target)
|
||||||
|
.join("bin")
|
||||||
|
.join(if config.host.contains("windows") { "rust-lld.exe" } else { "rust-lld" })
|
||||||
|
.exists(),
|
||||||
|
|
||||||
|
// On Windows, dlltool.exe is used for all architectures.
|
||||||
|
#[cfg(windows)]
|
||||||
|
i686_dlltool: path.iter().any(|dir| dir.join("dlltool.exe").is_file()),
|
||||||
|
#[cfg(windows)]
|
||||||
|
x86_64_dlltool: path.iter().any(|dir| dir.join("dlltool.exe").is_file()),
|
||||||
|
|
||||||
|
// For non-Windows, there are architecture specific dlltool binaries.
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
i686_dlltool: path.iter().any(|dir| dir.join("i686-w64-mingw32-dlltool").is_file()),
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
x86_64_dlltool: path.iter().any(|dir| dir.join("x86_64-w64-mingw32-dlltool").is_file()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user