make #[target_feature] work with asm
register classes
This commit is contained in:
parent
d7539a6af0
commit
271da7d8bc
7 changed files with 213 additions and 112 deletions
|
@ -202,39 +202,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
|
||||
let mut used_input_regs = FxHashMap::default();
|
||||
let mut used_output_regs = FxHashMap::default();
|
||||
let mut required_features: Vec<&str> = vec![];
|
||||
|
||||
for (idx, &(ref op, op_sp)) in operands.iter().enumerate() {
|
||||
if let Some(reg) = op.reg() {
|
||||
// Make sure we don't accidentally carry features from the
|
||||
// previous iteration.
|
||||
required_features.clear();
|
||||
|
||||
let reg_class = reg.reg_class();
|
||||
if reg_class == asm::InlineAsmRegClass::Err {
|
||||
continue;
|
||||
}
|
||||
|
||||
// We ignore target feature requirements for clobbers: if the
|
||||
// feature is disabled then the compiler doesn't care what we
|
||||
// do with the registers.
|
||||
//
|
||||
// Note that this is only possible for explicit register
|
||||
// operands, which cannot be used in the asm string.
|
||||
let is_clobber = matches!(
|
||||
op,
|
||||
hir::InlineAsmOperand::Out {
|
||||
reg: asm::InlineAsmRegOrRegClass::Reg(_),
|
||||
late: _,
|
||||
expr: None
|
||||
}
|
||||
);
|
||||
|
||||
// Some register classes can only be used as clobbers. This
|
||||
// means that we disallow passing a value in/out of the asm and
|
||||
// require that the operand name an explicit register, not a
|
||||
// register class.
|
||||
if reg_class.is_clobber_only(asm_arch.unwrap())
|
||||
&& !(is_clobber && matches!(reg, asm::InlineAsmRegOrRegClass::Reg(_)))
|
||||
&& !(op.is_clobber() && matches!(reg, asm::InlineAsmRegOrRegClass::Reg(_)))
|
||||
{
|
||||
let msg = format!(
|
||||
"register class `{}` can only be used as a clobber, \
|
||||
|
@ -245,47 +226,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
continue;
|
||||
}
|
||||
|
||||
if !is_clobber {
|
||||
// Validate register classes against currently enabled target
|
||||
// features. We check that at least one type is available for
|
||||
// the current target.
|
||||
for &(_, feature) in reg_class.supported_types(asm_arch.unwrap()) {
|
||||
if let Some(feature) = feature {
|
||||
if self.sess.target_features.contains(&Symbol::intern(feature)) {
|
||||
required_features.clear();
|
||||
break;
|
||||
} else {
|
||||
required_features.push(feature);
|
||||
}
|
||||
} else {
|
||||
required_features.clear();
|
||||
break;
|
||||
}
|
||||
}
|
||||
// We are sorting primitive strs here and can use unstable sort here
|
||||
required_features.sort_unstable();
|
||||
required_features.dedup();
|
||||
match &required_features[..] {
|
||||
[] => {}
|
||||
[feature] => {
|
||||
let msg = format!(
|
||||
"register class `{}` requires the `{}` target feature",
|
||||
reg_class.name(),
|
||||
feature
|
||||
);
|
||||
sess.struct_span_err(op_sp, &msg).emit();
|
||||
}
|
||||
features => {
|
||||
let msg = format!(
|
||||
"register class `{}` requires at least one target feature: {}",
|
||||
reg_class.name(),
|
||||
features.join(", ")
|
||||
);
|
||||
sess.struct_span_err(op_sp, &msg).emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check for conflicts between explicit register operands.
|
||||
if let asm::InlineAsmRegOrRegClass::Reg(reg) = reg {
|
||||
let (input, output) = match op {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue