summaryrefslogtreecommitdiffstats
path: root/src/tools/compiletest/src/common.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/compiletest/src/common.rs')
-rw-r--r--src/tools/compiletest/src/common.rs132
1 files changed, 132 insertions, 0 deletions
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index be81ff881..64df76e27 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -3,9 +3,11 @@ pub use self::Mode::*;
use std::ffi::OsString;
use std::fmt;
use std::path::{Path, PathBuf};
+use std::process::Command;
use std::str::FromStr;
use crate::util::PathBufExt;
+use lazycell::LazyCell;
use test::ColorConfig;
#[derive(Clone, Copy, PartialEq, Debug)]
@@ -201,6 +203,9 @@ pub struct Config {
/// The jsondocck executable.
pub jsondocck_path: Option<String>,
+ /// The jsondoclint executable.
+ pub jsondoclint_path: Option<String>,
+
/// The LLVM `FileCheck` binary path.
pub llvm_filecheck: Option<PathBuf>,
@@ -371,6 +376,8 @@ pub struct Config {
/// Whether to rerun tests even if the inputs are unchanged.
pub force_rerun: bool,
+
+ pub target_cfg: LazyCell<TargetCfg>,
}
impl Config {
@@ -380,6 +387,131 @@ impl Config {
!self.target.ends_with("-fuchsia")
})
}
+
+ fn target_cfg(&self) -> &TargetCfg {
+ self.target_cfg.borrow_with(|| TargetCfg::new(&self.rustc_path, &self.target))
+ }
+
+ pub fn matches_arch(&self, arch: &str) -> bool {
+ self.target_cfg().arch == arch ||
+ // Shorthand for convenience. The arch for
+ // asmjs-unknown-emscripten is actually wasm32.
+ (arch == "asmjs" && self.target.starts_with("asmjs")) ||
+ // Matching all the thumb variants as one can be convenient.
+ // (thumbv6m, thumbv7em, thumbv7m, etc.)
+ (arch == "thumb" && self.target.starts_with("thumb"))
+ }
+
+ pub fn matches_os(&self, os: &str) -> bool {
+ self.target_cfg().os == os
+ }
+
+ pub fn matches_env(&self, env: &str) -> bool {
+ self.target_cfg().env == env
+ }
+
+ pub fn matches_abi(&self, abi: &str) -> bool {
+ self.target_cfg().abi == abi
+ }
+
+ pub fn matches_family(&self, family: &str) -> bool {
+ self.target_cfg().families.iter().any(|f| f == family)
+ }
+
+ pub fn is_big_endian(&self) -> bool {
+ self.target_cfg().endian == Endian::Big
+ }
+
+ pub fn get_pointer_width(&self) -> u32 {
+ *&self.target_cfg().pointer_width
+ }
+
+ pub fn has_asm_support(&self) -> bool {
+ static ASM_SUPPORTED_ARCHS: &[&str] = &[
+ "x86", "x86_64", "arm", "aarch64", "riscv32",
+ "riscv64",
+ // These targets require an additional asm_experimental_arch feature.
+ // "nvptx64", "hexagon", "mips", "mips64", "spirv", "wasm32",
+ ];
+ ASM_SUPPORTED_ARCHS.contains(&self.target_cfg().arch.as_str())
+ }
+}
+
+#[derive(Clone, Debug)]
+pub struct TargetCfg {
+ arch: String,
+ os: String,
+ env: String,
+ abi: String,
+ families: Vec<String>,
+ pointer_width: u32,
+ endian: Endian,
+}
+
+#[derive(Eq, PartialEq, Clone, Debug)]
+pub enum Endian {
+ Little,
+ Big,
+}
+
+impl TargetCfg {
+ fn new(rustc_path: &Path, target: &str) -> TargetCfg {
+ let output = match Command::new(rustc_path)
+ .arg("--print=cfg")
+ .arg("--target")
+ .arg(target)
+ .output()
+ {
+ Ok(output) => output,
+ Err(e) => panic!("error: failed to get cfg info from {:?}: {e}", rustc_path),
+ };
+ if !output.status.success() {
+ panic!(
+ "error: failed to get cfg info from {:?}\n--- stdout\n{}\n--- stderr\n{}",
+ rustc_path,
+ String::from_utf8(output.stdout).unwrap(),
+ String::from_utf8(output.stderr).unwrap(),
+ );
+ }
+ let print_cfg = String::from_utf8(output.stdout).unwrap();
+ let mut arch = None;
+ let mut os = None;
+ let mut env = None;
+ let mut abi = None;
+ let mut families = Vec::new();
+ let mut pointer_width = None;
+ let mut endian = None;
+ for line in print_cfg.lines() {
+ if let Some((name, value)) = line.split_once('=') {
+ let value = value.trim_matches('"');
+ match name {
+ "target_arch" => arch = Some(value),
+ "target_os" => os = Some(value),
+ "target_env" => env = Some(value),
+ "target_abi" => abi = Some(value),
+ "target_family" => families.push(value.to_string()),
+ "target_pointer_width" => pointer_width = Some(value.parse().unwrap()),
+ "target_endian" => {
+ endian = Some(match value {
+ "little" => Endian::Little,
+ "big" => Endian::Big,
+ s => panic!("unexpected {s}"),
+ })
+ }
+ _ => {}
+ }
+ }
+ }
+ TargetCfg {
+ arch: arch.unwrap().to_string(),
+ os: os.unwrap().to_string(),
+ env: env.unwrap().to_string(),
+ abi: abi.unwrap().to_string(),
+ families,
+ pointer_width: pointer_width.unwrap(),
+ endian: endian.unwrap(),
+ }
+ }
}
#[derive(Debug, Clone)]