explicitly model that certain ABIs require/forbid certain target features

This commit is contained in:
Ralf Jung
2024-12-26 18:32:22 +01:00
parent 41b579660c
commit 2bf27e09be
18 changed files with 304 additions and 273 deletions

View File

@@ -2651,10 +2651,6 @@ impl TargetOptions {
pub(crate) fn has_feature(&self, search_feature: &str) -> bool {
self.features.split(',').any(|f| f.strip_prefix('+').is_some_and(|f| f == search_feature))
}
pub(crate) fn has_neg_feature(&self, search_feature: &str) -> bool {
self.features.split(',').any(|f| f.strip_prefix('-').is_some_and(|f| f == search_feature))
}
}
impl Default for TargetOptions {
@@ -3201,7 +3197,8 @@ impl Target {
check_matches!(
&*self.llvm_abiname,
"ilp32" | "ilp32f" | "ilp32d" | "ilp32e",
"invalid RISC-V ABI name"
"invalid RISC-V ABI name: {}",
self.llvm_abiname,
);
}
"riscv64" => {
@@ -3209,7 +3206,8 @@ impl Target {
check_matches!(
&*self.llvm_abiname,
"lp64" | "lp64f" | "lp64d" | "lp64e",
"invalid RISC-V ABI name"
"invalid RISC-V ABI name: {}",
self.llvm_abiname,
);
}
"arm" => {
@@ -3243,6 +3241,26 @@ impl Target {
));
}
}
// Check that we don't mis-set any of the ABI-relevant features.
let (abi_enable, abi_disable) = self.abi_required_features();
for feat in abi_enable {
// The feature might be enabled by default so we can't *require* it to show up.
// But it must not be *disabled*.
if features_disabled.contains(feat) {
return Err(format!(
"target feature `{feat}` is required by the ABI but gets disabled in target spec"
));
}
}
for feat in abi_disable {
// The feature might be disable by default so we can't *require* it to show up.
// But it must not be *enabled*.
if features_enabled.contains(feat) {
return Err(format!(
"target feature `{feat}` is incompatible with the ABI but gets enabled in target spec"
));
}
}
}
Ok(())