Skip to content

Commit a74764c

Browse files
committed
Add new test directive needs-target-has-atomic to support #87377
1 parent 48696f5 commit a74764c

File tree

3 files changed

+58
-3
lines changed

3 files changed

+58
-3
lines changed

src/tools/compiletest/src/common.rs

+18
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,24 @@ impl Config {
477477
ASM_SUPPORTED_ARCHS.contains(&self.target_cfg().arch.as_str())
478478
}
479479

480+
pub fn has_atomic(&self, size: &str) -> bool {
481+
for config in
482+
rustc_output(self, &["--print=cfg", "--target", &self.target], Default::default())
483+
.trim()
484+
.lines()
485+
{
486+
let Some((key, value)) = config.split_once("=\"").map(|(k, v)| {
487+
(k, v.strip_suffix('"').expect("key-value pair should be properly quoted"))
488+
}) else {
489+
continue;
490+
};
491+
if key == "target_has_atomic" && value == size {
492+
return true;
493+
}
494+
}
495+
false
496+
}
497+
480498
pub fn git_config(&self) -> GitConfig<'_> {
481499
GitConfig {
482500
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

+39-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 after a colon to specify
175+
// 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,39 @@ 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+
// `needs-target-has-atomic` requires comma-separated data sizes.
194+
if !comment_starts_with_colon || comment.is_none() {
195+
return IgnoreDecision::Error {
196+
message: "`needs-target-has-atomic` requires data sizes for atomic operations"
197+
.into(),
198+
};
199+
}
200+
let comment = comment.unwrap();
201+
202+
// Parse the comment to specify data sizes.
203+
for size in comment.split(',').map(|size| size.trim()) {
204+
if !["ptr", "128", "64", "32", "16", "8"].contains(&size) {
205+
return IgnoreDecision::Error {
206+
message: "expected values for `needs-target-has-atomic` are: `128`, `16`, \
207+
`32`, `64`, `8`, and `ptr`"
208+
.into(),
209+
};
210+
}
211+
if !config.has_atomic(size) {
212+
return IgnoreDecision::Ignore {
213+
reason: if size == "ptr" {
214+
"ignored on targets without ptr-size atomic operations".into()
215+
} else {
216+
format!("ignored on targets without {size}-bit atomic operations")
217+
},
218+
};
219+
}
220+
}
221+
return IgnoreDecision::Continue;
222+
}
223+
188224
let mut found_valid = false;
189225
for need in needs {
190226
if need.name == name {

0 commit comments

Comments
 (0)