Skip to content

Commit

Permalink
Add new test directive needs-atomic to support rust-lang#87377
Browse files Browse the repository at this point in the history
  • Loading branch information
kei519 committed Nov 17, 2024
1 parent f2a3542 commit c0aecdc
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 3 deletions.
28 changes: 28 additions & 0 deletions src/tools/compiletest/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,16 @@ impl Config {
ASM_SUPPORTED_ARCHS.contains(&self.target_cfg().arch.as_str())
}

pub fn has_atomic(&self, size: Option<u64>) -> bool {
if let Some(size) = size {
(self.target_cfg().min_atomic_width()..=self.target_cfg().max_atomic_width())
.contains(&size)
&& self.target_cfg().atomic_cas
} else {
self.target_cfg().atomic_cas
}
}

pub fn git_config(&self) -> GitConfig<'_> {
GitConfig {
git_repository: &self.git_repository,
Expand Down Expand Up @@ -645,12 +655,26 @@ pub struct TargetCfg {
pub(crate) xray: bool,
#[serde(default = "default_reloc_model")]
pub(crate) relocation_model: String,
#[serde(default)]
max_atomic_width: Option<u64>,
#[serde(default)]
min_atomic_width: Option<u64>,
#[serde(default = "default_atomic_cas")]
atomic_cas: bool,
}

impl TargetCfg {
pub(crate) fn os_and_env(&self) -> String {
format!("{}-{}", self.os, self.env)
}

fn max_atomic_width(&self) -> u64 {
self.max_atomic_width.unwrap_or(self.pointer_width as _)
}

fn min_atomic_width(&self) -> u64 {
self.min_atomic_width.unwrap_or(8)
}
}

fn default_os() -> String {
Expand All @@ -661,6 +685,10 @@ fn default_reloc_model() -> String {
"pic".into()
}

fn default_atomic_cas() -> bool {
true
}

#[derive(Eq, PartialEq, Clone, Debug, Default, serde::Deserialize)]
#[serde(rename_all = "kebab-case")]
pub enum Endian {
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 @@ -127,6 +127,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
"min-llvm-version",
"min-system-llvm-version",
"needs-asm-support",
"needs-atomic",
"needs-deterministic-layouts",
"needs-dlltool",
"needs-dynamic-linking",
Expand Down
72 changes: 69 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-atomic` accepts one argument after colon to specify data size, we check whther
// 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,69 @@ pub(super) fn handle_needs(
return IgnoreDecision::Continue;
}

// Check here because `needs-atomic` requires parsing comments.
if name == "needs-atomic" {
let mut comment = comment;

// Parse the comment to specify data size.
// Just comments not arguments are also accepted.
// No arguments are handled as (none).
let size = if !comment_starts_with_colon {
// Comments starting with spaces are not arguments.
None
} else {
if let Some(comment_content) = comment {
if comment_content.trim().is_empty() {
None
} else {
let (size, rest) = match comment_content.trim_start().split_once([':', ' ']) {
Some((size, rest)) => (size, Some(rest)),
None => (comment_content.trim(), None),
};

if size == "ptr" {
comment = rest;
Some(config.target_cfg().pointer_width as _)
} else if let Ok(size) = size.parse() {
if ![128, 64, 32, 16, 8].contains(&size) {
// Numeric literals but non data size are disallowed.
return IgnoreDecision::Error {
message: "expected values for `needs-atomic` are: (none), `128`,\
`16`, `32`, `64`, `8`, and `ptr"
.into(),
};
} else {
comment = rest;
Some(size)
}
} else {
// Comments starting with non-numeric literals are not arguments.
None
}
}
} else {
None
}
};

return if config.has_atomic(size) {
IgnoreDecision::Continue
} else {
let base = if let Some(size) = size {
format!("ignored on targets without {size}-bit atomic operations")
} else {
format!("ignored on targets without atomic operations")
};
IgnoreDecision::Ignore {
reason: if let Some(comment) = comment {
format!("{base}: ({})", comment.trim())
} else {
base
},
}
};
}

let mut found_valid = false;
for need in needs {
if need.name == name {
Expand Down

0 comments on commit c0aecdc

Please sign in to comment.