diff options
Diffstat (limited to 'yjit/src/backend/ir.rs')
-rw-r--r-- | yjit/src/backend/ir.rs | 26 |
1 files changed, 25 insertions, 1 deletions
diff --git a/yjit/src/backend/ir.rs b/yjit/src/backend/ir.rs index 1dea189f24..dd0390f39c 100644 --- a/yjit/src/backend/ir.rs +++ b/yjit/src/backend/ir.rs @@ -7,7 +7,7 @@ use std::fmt; use std::convert::From; use std::io::Write; use std::mem::take; -use crate::cruby::{VALUE}; +use crate::cruby::{VALUE, SIZEOF_VALUE_I32}; use crate::virtualmem::{CodePtr}; use crate::asm::{CodeBlock, uimm_num_bits, imm_num_bits}; use crate::core::{Context, Type, TempMapping}; @@ -72,6 +72,9 @@ pub enum Opnd // Output of a preceding instruction in this block InsnOut{ idx: usize, num_bits: u8 }, + // Pointer to a slot on the VM stack + Stack { idx: i32, sp_offset: i16, num_bits: u8 }, + // Low-level operands, for lowering Imm(i64), // Raw signed immediate UImm(u64), // Raw unsigned immediate @@ -85,6 +88,7 @@ impl fmt::Debug for Opnd { match self { Self::None => write!(fmt, "None"), Value(val) => write!(fmt, "Value({val:?})"), + Stack { idx, sp_offset, .. } => write!(fmt, "SP[{}]", *sp_offset as i32 - idx - 1), InsnOut { idx, num_bits } => write!(fmt, "Out{num_bits}({idx})"), Imm(signed) => write!(fmt, "{signed:x}_i64"), UImm(unsigned) => write!(fmt, "{unsigned:x}_u64"), @@ -158,6 +162,7 @@ impl Opnd Opnd::Reg(reg) => Some(Opnd::Reg(reg.with_num_bits(num_bits))), Opnd::Mem(Mem { base, disp, .. }) => Some(Opnd::Mem(Mem { base, disp, num_bits })), Opnd::InsnOut { idx, .. } => Some(Opnd::InsnOut { idx, num_bits }), + Opnd::Stack { idx, sp_offset, .. } => Some(Opnd::Stack { idx, sp_offset, num_bits }), _ => None, } } @@ -914,6 +919,25 @@ impl Assembler Target::Label(label_idx) } + /// Convert Stack operands to memory operands + pub fn lower_stack(mut self) -> Assembler + { + let mut asm = Assembler::new_with_label_names(take(&mut self.label_names)); + let mut iterator = self.into_draining_iter(); + + while let Some((index, mut insn)) = iterator.next_unmapped() { + let mut opnd_iter = insn.opnd_iter_mut(); + while let Some(opnd) = opnd_iter.next() { + if let Opnd::Stack { idx, sp_offset, num_bits } = *opnd { + *opnd = Opnd::mem(num_bits, SP, (sp_offset as i32 - idx - 1) * SIZEOF_VALUE_I32); + } + } + asm.push_insn(insn); + } + + asm + } + /// Sets the out field on the various instructions that require allocated /// registers because their output is used as the operand on a subsequent /// instruction. This is our implementation of the linear scan algorithm. |