about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGary Guo <gary@garyguo.net>2021-11-22 02:05:56 +0000
committerGary Guo <gary@garyguo.net>2021-11-22 03:15:12 +0000
commit894468a5377b374da3cb5c143549b21dd2dd32d6 (patch)
tree79f24b50f1de1b27e834e5192378104699141850
parentf16d27aca48454fc3a05a477b20ba5264a740b14 (diff)
downloadrust-894468a5377b374da3cb5c143549b21dd2dd32d6.tar.gz
rust-894468a5377b374da3cb5c143549b21dd2dd32d6.zip
Move stack slot allocation to a new fn
-rw-r--r--src/inline_asm.rs93
1 files changed, 70 insertions, 23 deletions
diff --git a/src/inline_asm.rs b/src/inline_asm.rs
index 771f3056ec2..dde776d8e51 100644
--- a/src/inline_asm.rs
+++ b/src/inline_asm.rs
@@ -103,25 +103,10 @@ pub(crate) fn codegen_inline_asm<'tcx>(
         crate::trap::trap_unimplemented(fx, "Alloca is not supported");
     }
 
-    let mut slot_size = Size::from_bytes(0);
     let mut clobbered_regs = Vec::new();
     let mut inputs = Vec::new();
     let mut outputs = Vec::new();
 
-    let mut new_slot = |reg_class: InlineAsmRegClass| {
-        let reg_size = reg_class
-            .supported_types(InlineAsmArch::X86_64)
-            .iter()
-            .map(|(ty, _)| ty.size())
-            .max()
-            .unwrap();
-        let align = rustc_target::abi::Align::from_bytes(reg_size.bytes()).unwrap();
-        slot_size = slot_size.align_to(align);
-        let offset = slot_size;
-        slot_size += reg_size;
-        offset
-    };
-
     let mut asm_gen = InlineAssemblyGenerator {
         tcx: fx.tcx,
         arch: InlineAsmArch::X86_64,
@@ -129,44 +114,49 @@ pub(crate) fn codegen_inline_asm<'tcx>(
         operands,
         options,
         registers: Vec::new(),
+        stack_slots_clobber: Vec::new(),
+        stack_slots_input: Vec::new(),
+        stack_slots_output: Vec::new(),
+        stack_slot_size: Size::from_bytes(0),
     };
     asm_gen.allocate_registers();
+    asm_gen.allocate_stack_slots();
 
     // FIXME overlap input and output slots to save stack space
     for (i, operand) in operands.iter().enumerate() {
         match *operand {
             InlineAsmOperand::In { reg, ref value } => {
                 let reg = asm_gen.registers[i].unwrap();
-                clobbered_regs.push((reg, new_slot(reg.reg_class())));
+                clobbered_regs.push((reg, asm_gen.stack_slots_clobber[i].unwrap()));
                 inputs.push((
                     reg,
-                    new_slot(reg.reg_class()),
+                    asm_gen.stack_slots_input[i].unwrap(),
                     crate::base::codegen_operand(fx, value).load_scalar(fx),
                 ));
             }
             InlineAsmOperand::Out { reg, late: _, place } => {
                 let reg = asm_gen.registers[i].unwrap();
-                clobbered_regs.push((reg, new_slot(reg.reg_class())));
+                clobbered_regs.push((reg, asm_gen.stack_slots_clobber[i].unwrap()));
                 if let Some(place) = place {
                     outputs.push((
                         reg,
-                        new_slot(reg.reg_class()),
+                        asm_gen.stack_slots_output[i].unwrap(),
                         crate::base::codegen_place(fx, place),
                     ));
                 }
             }
             InlineAsmOperand::InOut { reg, late: _, ref in_value, out_place } => {
                 let reg = asm_gen.registers[i].unwrap();
-                clobbered_regs.push((reg, new_slot(reg.reg_class())));
+                clobbered_regs.push((reg, asm_gen.stack_slots_clobber[i].unwrap()));
                 inputs.push((
                     reg,
-                    new_slot(reg.reg_class()),
+                    asm_gen.stack_slots_input[i].unwrap(),
                     crate::base::codegen_operand(fx, in_value).load_scalar(fx),
                 ));
                 if let Some(out_place) = out_place {
                     outputs.push((
                         reg,
-                        new_slot(reg.reg_class()),
+                        asm_gen.stack_slots_output[i].unwrap(),
                         crate::base::codegen_place(fx, out_place),
                     ));
                 }
@@ -184,7 +174,7 @@ pub(crate) fn codegen_inline_asm<'tcx>(
     let generated_asm = asm_gen.generate_asm_wrapper(&asm_name, clobbered_regs, &inputs, &outputs);
     fx.cx.global_asm.push_str(&generated_asm);
 
-    call_inline_asm(fx, &asm_name, slot_size, inputs, outputs);
+    call_inline_asm(fx, &asm_name, asm_gen.stack_slot_size, inputs, outputs);
 }
 
 struct InlineAssemblyGenerator<'a, 'tcx> {
@@ -194,6 +184,10 @@ struct InlineAssemblyGenerator<'a, 'tcx> {
     operands: &'a [InlineAsmOperand<'tcx>],
     options: InlineAsmOptions,
     registers: Vec<Option<InlineAsmReg>>,
+    stack_slots_clobber: Vec<Option<Size>>,
+    stack_slots_input: Vec<Option<Size>>,
+    stack_slots_output: Vec<Option<Size>>,
+    stack_slot_size: Size,
 }
 
 impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
@@ -317,6 +311,59 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
         self.registers = regs;
     }
 
+    fn allocate_stack_slots(&mut self) {
+        let mut slot_size = Size::from_bytes(0);
+        let mut slots_clobber = vec![None; self.operands.len()];
+        let mut slots_input = vec![None; self.operands.len()];
+        let mut slots_output = vec![None; self.operands.len()];
+
+        let mut new_slot = |reg_class: InlineAsmRegClass| {
+            let reg_size = reg_class
+                .supported_types(InlineAsmArch::X86_64)
+                .iter()
+                .map(|(ty, _)| ty.size())
+                .max()
+                .unwrap();
+            let align = rustc_target::abi::Align::from_bytes(reg_size.bytes()).unwrap();
+            slot_size = slot_size.align_to(align);
+            let offset = slot_size;
+            slot_size += reg_size;
+            offset
+        };
+
+        // 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() {
+                        slots_output[i] = Some(slot);
+                    }
+                }
+                InlineAsmOperand::Const { value: _ } => (),
+                InlineAsmOperand::SymFn { value: _ } => (),
+                InlineAsmOperand::SymStatic { def_id: _ } => (),
+            }
+        }
+
+        self.stack_slots_clobber = slots_clobber;
+        self.stack_slots_input = slots_input;
+        self.stack_slots_output = slots_output;
+        self.stack_slot_size = slot_size;
+    }
+
     fn generate_asm_wrapper(
         &self,
         asm_name: &str,