1
Fork 0

Add support for specifying multiple clobber_abi in asm!

Allow multiple clobber_abi in asm

Update docs
Fix aarch64 test
Combine abis
Emit duplicate ABI error, empty ABI list error
multiple clobber_abi
This commit is contained in:
asquared31415 2021-10-14 03:23:09 -04:00
parent 214cd1f228
commit b233d3b5da
14 changed files with 370 additions and 147 deletions

View file

@ -2,6 +2,7 @@ use super::LoweringContext;
use rustc_ast::*;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stable_set::FxHashSet;
use rustc_errors::struct_span_err;
use rustc_hir as hir;
use rustc_session::parse::feature_err;
@ -49,22 +50,47 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
.emit();
}
let mut clobber_abi = None;
let mut clobber_abis = FxHashMap::default();
if let Some(asm_arch) = asm_arch {
if let Some((abi_name, abi_span)) = asm.clobber_abi {
match asm::InlineAsmClobberAbi::parse(asm_arch, &self.sess.target, abi_name) {
Ok(abi) => clobber_abi = Some((abi, abi_span)),
for (abi_name, abi_span) in &asm.clobber_abis {
match asm::InlineAsmClobberAbi::parse(asm_arch, &self.sess.target, *abi_name) {
Ok(abi) => {
// If the abi was already in the list, emit an error
match clobber_abis.get(&abi) {
Some((prev_name, prev_sp)) => {
let mut err = self.sess.struct_span_err(
*abi_span,
&format!("`{}` ABI specified multiple times", prev_name),
);
err.span_label(*prev_sp, "previously specified here");
// Multiple different abi names may actually be the same ABI
// If the specified ABIs are not the same name, alert the user that they resolve to the same ABI
let source_map = self.sess.source_map();
if source_map.span_to_snippet(*prev_sp)
!= source_map.span_to_snippet(*abi_span)
{
err.note("these ABIs are equivalent on the current target");
}
err.emit();
}
None => {
clobber_abis.insert(abi, (abi_name, *abi_span));
}
}
}
Err(&[]) => {
self.sess
.struct_span_err(
abi_span,
*abi_span,
"`clobber_abi` is not supported on this target",
)
.emit();
}
Err(supported_abis) => {
let mut err =
self.sess.struct_span_err(abi_span, "invalid ABI for `clobber_abi`");
self.sess.struct_span_err(*abi_span, "invalid ABI for `clobber_abi`");
let mut abis = format!("`{}`", supported_abis[0]);
for m in &supported_abis[1..] {
let _ = write!(abis, ", `{}`", m);
@ -348,8 +374,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
// If a clobber_abi is specified, add the necessary clobbers to the
// operands list.
if let Some((abi, abi_span)) = clobber_abi {
let mut clobbered = FxHashSet::default();
for (abi, (_, abi_span)) in clobber_abis {
for &clobber in abi.clobbered_regs() {
// Don't emit a clobber for a register already clobbered
if clobbered.contains(&clobber) {
continue;
}
let mut output_used = false;
clobber.overlapping_regs(|reg| {
if used_output_regs.contains_key(&reg) {
@ -366,6 +398,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
},
self.lower_span(abi_span),
));
clobbered.insert(clobber);
}
}
}