Skip to content

Commit c0aecdc

Browse files
committed
Add new test directive needs-atomic to support #87377
1 parent f2a3542 commit c0aecdc

File tree

3 files changed

+98
-3
lines changed

3 files changed

+98
-3
lines changed

src/tools/compiletest/src/common.rs

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

480+
pub fn has_atomic(&self, size: Option<u64>) -> bool {
481+
if let Some(size) = size {
482+
(self.target_cfg().min_atomic_width()..=self.target_cfg().max_atomic_width())
483+
.contains(&size)
484+
&& self.target_cfg().atomic_cas
485+
} else {
486+
self.target_cfg().atomic_cas
487+
}
488+
}
489+
480490
pub fn git_config(&self) -> GitConfig<'_> {
481491
GitConfig {
482492
git_repository: &self.git_repository,
@@ -645,12 +655,26 @@ pub struct TargetCfg {
645655
pub(crate) xray: bool,
646656
#[serde(default = "default_reloc_model")]
647657
pub(crate) relocation_model: String,
658+
#[serde(default)]
659+
max_atomic_width: Option<u64>,
660+
#[serde(default)]
661+
min_atomic_width: Option<u64>,
662+
#[serde(default = "default_atomic_cas")]
663+
atomic_cas: bool,
648664
}
649665

650666
impl TargetCfg {
651667
pub(crate) fn os_and_env(&self) -> String {
652668
format!("{}-{}", self.os, self.env)
653669
}
670+
671+
fn max_atomic_width(&self) -> u64 {
672+
self.max_atomic_width.unwrap_or(self.pointer_width as _)
673+
}
674+
675+
fn min_atomic_width(&self) -> u64 {
676+
self.min_atomic_width.unwrap_or(8)
677+
}
654678
}
655679

656680
fn default_os() -> String {
@@ -661,6 +685,10 @@ fn default_reloc_model() -> String {
661685
"pic".into()
662686
}
663687

688+
fn default_atomic_cas() -> bool {
689+
true
690+
}
691+
664692
#[derive(Eq, PartialEq, Clone, Debug, Default, serde::Deserialize)]
665693
#[serde(rename_all = "kebab-case")]
666694
pub enum Endian {

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

+1
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
127127
"min-llvm-version",
128128
"min-system-llvm-version",
129129
"needs-asm-support",
130+
"needs-atomic",
130131
"needs-deterministic-layouts",
131132
"needs-dlltool",
132133
"needs-dynamic-linking",

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

+69-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-atomic` accepts one argument after colon to specify data size, we check whther
175+
// 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,69 @@ pub(super) fn handle_needs(
185188
return IgnoreDecision::Continue;
186189
}
187190

191+
// Check here because `needs-atomic` requires parsing comments.
192+
if name == "needs-atomic" {
193+
let mut comment = comment;
194+
195+
// Parse the comment to specify data size.
196+
// Just comments not arguments are also accepted.
197+
// No arguments are handled as (none).
198+
let size = if !comment_starts_with_colon {
199+
// Comments starting with spaces are not arguments.
200+
None
201+
} else {
202+
if let Some(comment_content) = comment {
203+
if comment_content.trim().is_empty() {
204+
None
205+
} else {
206+
let (size, rest) = match comment_content.trim_start().split_once([':', ' ']) {
207+
Some((size, rest)) => (size, Some(rest)),
208+
None => (comment_content.trim(), None),
209+
};
210+
211+
if size == "ptr" {
212+
comment = rest;
213+
Some(config.target_cfg().pointer_width as _)
214+
} else if let Ok(size) = size.parse() {
215+
if ![128, 64, 32, 16, 8].contains(&size) {
216+
// Numeric literals but non data size are disallowed.
217+
return IgnoreDecision::Error {
218+
message: "expected values for `needs-atomic` are: (none), `128`,\
219+
`16`, `32`, `64`, `8`, and `ptr"
220+
.into(),
221+
};
222+
} else {
223+
comment = rest;
224+
Some(size)
225+
}
226+
} else {
227+
// Comments starting with non-numeric literals are not arguments.
228+
None
229+
}
230+
}
231+
} else {
232+
None
233+
}
234+
};
235+
236+
return if config.has_atomic(size) {
237+
IgnoreDecision::Continue
238+
} else {
239+
let base = if let Some(size) = size {
240+
format!("ignored on targets without {size}-bit atomic operations")
241+
} else {
242+
format!("ignored on targets without atomic operations")
243+
};
244+
IgnoreDecision::Ignore {
245+
reason: if let Some(comment) = comment {
246+
format!("{base}: ({})", comment.trim())
247+
} else {
248+
base
249+
},
250+
}
251+
};
252+
}
253+
188254
let mut found_valid = false;
189255
for need in needs {
190256
if need.name == name {

0 commit comments

Comments
 (0)