Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

compiletest: use target cfg instead of hard-coded tables #100260

Merged
merged 3 commits into from
Aug 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -816,6 +816,7 @@ dependencies = [
"getopts",
"glob",
"lazy_static",
"lazycell",
"libc",
"miow",
"regex",
Expand Down
1 change: 1 addition & 0 deletions src/tools/compiletest/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ rustfix = "0.6.0"
lazy_static = "1.0"
walkdir = "2"
glob = "0.3.0"
lazycell = "1.3.0"

[target.'cfg(unix)'.dependencies]
libc = "0.2"
Expand Down
129 changes: 129 additions & 0 deletions src/tools/compiletest/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -371,6 +373,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 {
Expand All @@ -380,6 +384,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)]
Expand Down
31 changes: 25 additions & 6 deletions src/tools/compiletest/src/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -661,17 +661,36 @@ impl Config {

let name = line[prefix.len() + 1..].split(&[':', ' '][..]).next().unwrap();

let matches_pointer_width = || {
name.strip_suffix("bit")
.and_then(|width| width.parse::<u32>().ok())
.map(|width| self.get_pointer_width() == width)
.unwrap_or(false)
};

// If something is ignored for emscripten, it likely also needs to be
// ignored for wasm32-unknown-unknown.
// `wasm32-bare` is an alias to refer to just wasm32-unknown-unknown
// (in contrast to `wasm32` which also matches non-bare targets like
// asmjs-unknown-emscripten).
let matches_wasm32_alias = || {
self.target == "wasm32-unknown-unknown" && matches!(name, "emscripten" | "wasm32-bare")
};

let is_match = name == "test" ||
self.target == name || // triple
util::matches_os(&self.target, name) || // target
util::matches_env(&self.target, name) || // env
self.matches_os(name) ||
self.matches_env(name) ||
self.matches_abi(name) ||
self.matches_family(name) ||
self.target.ends_with(name) || // target and env
name == util::get_arch(&self.target) || // architecture
name == util::get_pointer_width(&self.target) || // pointer width
self.matches_arch(name) ||
matches_wasm32_alias() ||
matches_pointer_width() ||
name == self.stage_id.split('-').next().unwrap() || // stage
name == self.channel || // channel
(self.target != self.host && name == "cross-compile") ||
(name == "endian-big" && util::is_big_endian(&self.target)) ||
(name == "endian-big" && self.is_big_endian()) ||
(self.remote_test_client.is_some() && name == "remote") ||
match self.compare_mode {
Some(CompareMode::Polonius) => name == "compare-mode-polonius",
Expand Down Expand Up @@ -869,7 +888,7 @@ pub fn make_test_description<R: Read>(

let rustc_has_profiler_support = env::var_os("RUSTC_PROFILER_SUPPORT").is_some();
let rustc_has_sanitizer_support = env::var_os("RUSTC_SANITIZER_SUPPORT").is_some();
let has_asm_support = util::has_asm_support(&config.target);
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_lsan = util::LSAN_SUPPORTED_TARGETS.contains(&&*config.target);
Expand Down
Loading