Add setlocal and getlocal

This commit is contained in:
Max Bernstein 2025-02-06 11:13:17 -05:00 committed by Takashi Kokubun
parent 8ad08f1126
commit bb9b45a8dd
Notes: git 2025-04-18 13:49:52 +00:00

View File

@ -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() });
},