diff --git a/src/inline_asm.rs b/src/inline_asm.rs index 8b999f3c55a..8f9deeec718 100644 --- a/src/inline_asm.rs +++ b/src/inline_asm.rs @@ -320,21 +320,44 @@ fn allocate_stack_slots(&mut self) { offset }; + // Allocate stack slots for saving clobbered registers + let abi_clobber = + InlineAsmClobberAbi::parse(self.arch, &self.tcx.sess.target, Symbol::intern("C")) + .unwrap() + .clobbered_regs(); + for (i, reg) in self.registers.iter().enumerate().filter_map(|(i, r)| r.map(|r| (i, r))) { + let mut need_save = true; + // If the register overlaps with a register clobbered by function call, then + // we don't need to save it. + for r in abi_clobber { + r.overlapping_regs(|r| { + if r == reg { + need_save = false; + } + }); + + if !need_save { + break; + } + } + + if need_save { + slots_clobber[i] = Some(new_slot(reg.reg_class())); + } + } + // FIXME overlap input and output slots to save stack space for (i, operand) in self.operands.iter().enumerate() { match *operand { InlineAsmOperand::In { reg, .. } => { - slots_clobber[i] = Some(new_slot(reg.reg_class())); slots_input[i] = Some(new_slot(reg.reg_class())); } InlineAsmOperand::Out { reg, place, .. } => { - slots_clobber[i] = Some(new_slot(reg.reg_class())); if place.is_some() { slots_output[i] = Some(new_slot(reg.reg_class())); } } InlineAsmOperand::InOut { reg, out_place, .. } => { - slots_clobber[i] = Some(new_slot(reg.reg_class())); let slot = new_slot(reg.reg_class()); slots_input[i] = Some(slot); if out_place.is_some() { @@ -366,7 +389,6 @@ fn generate_asm_wrapper(&self, asm_name: &str) -> String { // Save clobbered registers if !self.options.contains(InlineAsmOptions::NORETURN) { - // FIXME skip registers saved by the calling convention for (reg, slot) in self .registers .iter()