From bb9b45a8ddb66001a75ff5aa46729f4f8d5e3f97 Mon Sep 17 00:00:00 2001 From: Max Bernstein Date: Thu, 6 Feb 2025 11:13:17 -0500 Subject: [PATCH] Add setlocal and getlocal --- zjit/src/ir.rs | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/zjit/src/ir.rs b/zjit/src/ir.rs index 2bc93b4c3a..3411f5bcb6 100644 --- a/zjit/src/ir.rs +++ b/zjit/src/ir.rs @@ -7,7 +7,7 @@ pub struct InsnId(usize); pub struct BlockId(usize); /// Instruction operand -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Clone, Copy)] enum Opnd { Const(VALUE), Insn(InsnId), @@ -15,7 +15,7 @@ enum Opnd { #[derive(Debug, PartialEq)] enum Insn { - // SSA block parameter + // SSA block parameter. Also used for function parameters in the function's entry block. Param { idx: usize }, Return { val: Opnd }, } @@ -53,6 +53,8 @@ impl Function { enum RubyOpcode { Putnil, Putobject(VALUE), + Setlocal(usize), + Getlocal(usize), Leave, } @@ -62,11 +64,12 @@ struct FrameState { // pc: stack: Vec, + locals: Vec, } impl FrameState { fn new() -> FrameState { - FrameState { stack: vec![] } + FrameState { stack: vec![], locals: vec![] } } fn push(&mut self, opnd: Opnd) { @@ -76,6 +79,20 @@ impl FrameState { fn pop(&mut self) -> Opnd { self.stack.pop().expect("Bytecode stack mismatch") } + + fn setlocal(&mut self, idx: usize, opnd: Opnd) { + if idx >= self.locals.len() { + self.locals.resize(idx+1, Opnd::Const(Qnil)); + } + self.locals[idx] = opnd; + } + + fn getlocal(&mut self, idx: usize) -> Opnd { + if idx >= self.locals.len() { + self.locals.resize(idx+1, Opnd::Const(Qnil)); + } + self.locals[idx] + } } fn to_ssa(opcodes: &Vec) -> Function { @@ -86,6 +103,14 @@ fn to_ssa(opcodes: &Vec) -> Function { match opcode { RubyOpcode::Putnil => { state.push(Opnd::Const(Qnil)); }, RubyOpcode::Putobject(val) => { state.push(Opnd::Const(*val)); }, + RubyOpcode::Setlocal(idx) => { + let val = state.pop(); + state.setlocal(*idx, val); + } + RubyOpcode::Getlocal(idx) => { + let val = state.getlocal(*idx); + state.push(val); + } RubyOpcode::Leave => { result.push_insn(block, Insn::Return { val: state.pop() }); },