summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--zjit/src/ir.rs31
1 files 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<Opnd>,
+ locals: Vec<Opnd>,
}
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<RubyOpcode>) -> Function {
@@ -86,6 +103,14 @@ fn to_ssa(opcodes: &Vec<RubyOpcode>) -> 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() });
},