Skip to content

Commit

Permalink
Add new test directive needs-target-has-atomic to support rust-lang…
Browse files Browse the repository at this point in the history
  • Loading branch information
kei519 committed Nov 28, 2024
1 parent 9b4d7c6 commit 0a0db62
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 4 deletions.
16 changes: 15 additions & 1 deletion src/tools/compiletest/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ use std::ffi::OsString;
use std::path::{Path, PathBuf};
use std::process::Command;
use std::str::FromStr;
use std::sync::OnceLock;
use std::sync::{LazyLock, OnceLock};
use std::{fmt, iter};

use build_helper::git::GitConfig;
use regex::Regex;
use semver::Version;
use serde::de::{Deserialize, Deserializer, Error as _};
use test::{ColorConfig, OutputFormat};
Expand Down Expand Up @@ -477,6 +478,19 @@ impl Config {
ASM_SUPPORTED_ARCHS.contains(&self.target_cfg().arch.as_str())
}

pub fn has_atomic(&self, size: &str) -> bool {
static TARGET_HAS_ATOMIC: LazyLock<Regex> =
LazyLock::new(|| Regex::new(r#"target_has_atomic="(?<size>[0-9a-zA-Z]+)""#).unwrap());

TARGET_HAS_ATOMIC
.captures_iter(&rustc_output(
self,
&["--print=cfg", "--target", &self.target],
Default::default(),
))
.any(|caps| &caps["size"] == size)
}

pub fn git_config(&self) -> GitConfig<'_> {
GitConfig {
git_repository: &self.git_repository,
Expand Down
1 change: 1 addition & 0 deletions src/tools/compiletest/src/directive-list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
"needs-sanitizer-thread",
"needs-std-debug-assertions",
"needs-symlink",
"needs-target-has-atomic",
"needs-threads",
"needs-unwind",
"needs-wasmtime",
Expand Down
50 changes: 47 additions & 3 deletions src/tools/compiletest/src/header/needs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,9 +171,12 @@ pub(super) fn handle_needs(
},
];

let (name, comment) = match ln.split_once([':', ' ']) {
Some((name, comment)) => (name, Some(comment)),
None => (ln, None),
// Because `needs-target-has-atomic` accepts comma separated arguments following a colon to
// specify data sizes, we check whether comment starts with colon.
let (name, comment, comment_starts_with_colon) = if let Some(index) = ln.find([':', ' ']) {
(&ln[..index], Some(&ln[index + 1..]), ln.as_bytes()[index] == b':')
} else {
(ln, None, false)
};

if !name.starts_with("needs-") {
Expand All @@ -185,6 +188,11 @@ pub(super) fn handle_needs(
return IgnoreDecision::Continue;
}

// Check here because `needs-target-has-atomic` requires parsing comments.
if name == "needs-target-has-atomic" {
return handle_needs_target_has_atomic(comment_starts_with_colon, comment, config);
}

let mut found_valid = false;
for need in needs {
if need.name == name {
Expand All @@ -210,6 +218,42 @@ pub(super) fn handle_needs(
}
}

fn handle_needs_target_has_atomic(
comment_starts_with_colon: bool,
comment: Option<&str>,
config: &Config,
) -> IgnoreDecision {
// `needs-target-has-atomic` requires comma-separated data sizes following a collon.
if !comment_starts_with_colon || comment.is_none() {
return IgnoreDecision::Error {
message: "`needs-target-has-atomic` requires data sizes for atomic operations".into(),
};
}
let comment = comment.unwrap();

// Parse the comment to specify data sizes.
for size in comment.split(',').map(|size| size.trim()) {
if !["ptr", "128", "64", "32", "16", "8"].contains(&size) {
return IgnoreDecision::Error {
message: "expected values for `needs-target-has-atomic` are: `128`, `16`, \\
`32`, `64`, `8`, and `ptr`"
.into(),
};
}
if !config.has_atomic(size) {
return IgnoreDecision::Ignore {
reason: if size == "ptr" {
"ignored on targets without ptr-size atomic operations".into()
} else {
format!("ignored on targets without {size}-bit atomic operations")
},
};
}
}

IgnoreDecision::Continue
}

struct Need {
name: &'static str,
condition: bool,
Expand Down

0 comments on commit 0a0db62

Please sign in to comment.