.emit();
}
+ let mut clobber_abi = None;
+ 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)),
+ Err(&[]) => {
+ self.sess
+ .struct_span_err(
+ 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`");
+ let mut abis = format!("`{}`", supported_abis[0]);
+ for m in &supported_abis[1..] {
+ let _ = write!(abis, ", `{}`", m);
+ }
+ err.note(&format!(
+ "the following ABIs are supported on this target: {}",
+ abis
+ ));
+ err.emit();
+ }
+ }
+ }
+ }
+
// Lower operands to HIR. We use dummy register classes if an error
// occurs during lowering because we still need to be able to produce a
// valid HIR.
let sess = self.sess;
- let operands: Vec<_> = asm
+ let mut operands: Vec<_> = asm
.operands
.iter()
.map(|(op, op_sp)| {
hir::InlineAsmOperand::Sym { expr: self.lower_expr_mut(expr) }
}
};
- (op, *op_sp)
+ (op, self.lower_span(*op_sp))
})
.collect();
}
}
+ // If a clobber_abi is specified, add the necessary clobbers to the
+ // operands list.
+ if let Some((abi, abi_span)) = clobber_abi {
+ for &clobber in abi.clobbered_regs() {
+ let mut output_used = false;
+ clobber.overlapping_regs(|reg| {
+ if used_output_regs.contains_key(®) {
+ output_used = true;
+ }
+ });
+
+ if !output_used {
+ operands.push((
+ hir::InlineAsmOperand::Out {
+ reg: asm::InlineAsmRegOrRegClass::Reg(clobber),
+ late: true,
+ expr: None,
+ },
+ self.lower_span(abi_span),
+ ));
+ }
+ }
+ }
+
let operands = self.arena.alloc_from_iter(operands);
let template = self.arena.alloc_from_iter(asm.template.iter().cloned());
- let line_spans = self.arena.alloc_slice(&asm.line_spans[..]);
- let hir_asm = hir::InlineAsm { template, operands, options: asm.options, line_spans };
+ let template_strs = self.arena.alloc_from_iter(
+ asm.template_strs
+ .iter()
+ .map(|(sym, snippet, span)| (*sym, *snippet, self.lower_span(*span))),
+ );
+ let line_spans =
+ self.arena.alloc_from_iter(asm.line_spans.iter().map(|span| self.lower_span(*span)));
+ let hir_asm =
+ hir::InlineAsm { template, template_strs, operands, options: asm.options, line_spans };
self.arena.alloc(hir_asm)
}
}