Skip to content

Commit 0a0db62

Browse files
committed
Add new test directive needs-target-has-atomic to support #87377
1 parent 9b4d7c6 commit 0a0db62

File tree

3 files changed

+63
-4
lines changed

3 files changed

+63
-4
lines changed

src/tools/compiletest/src/common.rs

+15-1
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@ use std::ffi::OsString;
33
use std::path::{Path, PathBuf};
44
use std::process::Command;
55
use std::str::FromStr;
6-
use std::sync::OnceLock;
6+
use std::sync::{LazyLock, OnceLock};
77
use std::{fmt, iter};
88

99
use build_helper::git::GitConfig;
10+
use regex::Regex;
1011
use semver::Version;
1112
use serde::de::{Deserialize, Deserializer, Error as _};
1213
use test::{ColorConfig, OutputFormat};
@@ -477,6 +478,19 @@ impl Config {
477478
ASM_SUPPORTED_ARCHS.contains(&self.target_cfg().arch.as_str())
478479
}
479480

481+
pub fn has_atomic(&self, size: &str) -> bool {
482+
static TARGET_HAS_ATOMIC: LazyLock<Regex> =
483+
LazyLock::new(|| Regex::new(r#"target_has_atomic="(?<size>[0-9a-zA-Z]+)""#).unwrap());
484+
485+
TARGET_HAS_ATOMIC
486+
.captures_iter(&rustc_output(
487+
self,
488+
&["--print=cfg", "--target", &self.target],
489+
Default::default(),
490+
))
491+
.any(|caps| &caps["size"] == size)
492+
}
493+
480494
pub fn git_config(&self) -> GitConfig<'_> {
481495
GitConfig {
482496
git_repository: &self.git_repository,

src/tools/compiletest/src/directive-list.rs

+1
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
154154
"needs-sanitizer-thread",
155155
"needs-std-debug-assertions",
156156
"needs-symlink",
157+
"needs-target-has-atomic",
157158
"needs-threads",
158159
"needs-unwind",
159160
"needs-wasmtime",

src/tools/compiletest/src/header/needs.rs

+47-3
Original file line numberDiff line numberDiff line change
@@ -171,9 +171,12 @@ pub(super) fn handle_needs(
171171
},
172172
];
173173

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

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

191+
// Check here because `needs-target-has-atomic` requires parsing comments.
192+
if name == "needs-target-has-atomic" {
193+
return handle_needs_target_has_atomic(comment_starts_with_colon, comment, config);
194+
}
195+
188196
let mut found_valid = false;
189197
for need in needs {
190198
if need.name == name {
@@ -210,6 +218,42 @@ pub(super) fn handle_needs(
210218
}
211219
}
212220

221+
fn handle_needs_target_has_atomic(
222+
comment_starts_with_colon: bool,
223+
comment: Option<&str>,
224+
config: &Config,
225+
) -> IgnoreDecision {
226+
// `needs-target-has-atomic` requires comma-separated data sizes following a collon.
227+
if !comment_starts_with_colon || comment.is_none() {
228+
return IgnoreDecision::Error {
229+
message: "`needs-target-has-atomic` requires data sizes for atomic operations".into(),
230+
};
231+
}
232+
let comment = comment.unwrap();
233+
234+
// Parse the comment to specify data sizes.
235+
for size in comment.split(',').map(|size| size.trim()) {
236+
if !["ptr", "128", "64", "32", "16", "8"].contains(&size) {
237+
return IgnoreDecision::Error {
238+
message: "expected values for `needs-target-has-atomic` are: `128`, `16`, \\
239+
`32`, `64`, `8`, and `ptr`"
240+
.into(),
241+
};
242+
}
243+
if !config.has_atomic(size) {
244+
return IgnoreDecision::Ignore {
245+
reason: if size == "ptr" {
246+
"ignored on targets without ptr-size atomic operations".into()
247+
} else {
248+
format!("ignored on targets without {size}-bit atomic operations")
249+
},
250+
};
251+
}
252+
}
253+
254+
IgnoreDecision::Continue
255+
}
256+
213257
struct Need {
214258
name: &'static str,
215259
condition: bool,

0 commit comments

Comments
 (0)