about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorGary Guo <gary@garyguo.net>2021-11-22 02:38:50 +0000
committerGary Guo <gary@garyguo.net>2021-11-22 13:45:17 +0000
commit14aa039d3087b76152018e3ca8c5df34fe1540b3 (patch)
treee6b8f3cceef12d382c5acdd2e21dfa9b7a0c609a /src
parent703027f0fc5dbd47d1655f1af013e67ae7d5f974 (diff)
downloadrust-14aa039d3087b76152018e3ca8c5df34fe1540b3.tar.gz
rust-14aa039d3087b76152018e3ca8c5df34fe1540b3.zip
Skip registers saved by calling convention
Diffstat (limited to 'src')
-rw-r--r--src/inline_asm.rs30
1 files changed, 26 insertions, 4 deletions
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 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
             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 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
 
         // Save clobbered registers
         if !self.options.contains(InlineAsmOptions::NORETURN) {
-            // FIXME skip registers saved by the calling convention
             for (reg, slot) in self
                 .registers
                 .iter()