Add setlocal and getlocal
This commit is contained in:
parent
8ad08f1126
commit
bb9b45a8dd
Notes:
git
2025-04-18 13:49:52 +00:00
@ -7,7 +7,7 @@ pub struct InsnId(usize);
|
|||||||
pub struct BlockId(usize);
|
pub struct BlockId(usize);
|
||||||
|
|
||||||
/// Instruction operand
|
/// Instruction operand
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq, Clone, Copy)]
|
||||||
enum Opnd {
|
enum Opnd {
|
||||||
Const(VALUE),
|
Const(VALUE),
|
||||||
Insn(InsnId),
|
Insn(InsnId),
|
||||||
@ -15,7 +15,7 @@ enum Opnd {
|
|||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
enum Insn {
|
enum Insn {
|
||||||
// SSA block parameter
|
// SSA block parameter. Also used for function parameters in the function's entry block.
|
||||||
Param { idx: usize },
|
Param { idx: usize },
|
||||||
Return { val: Opnd },
|
Return { val: Opnd },
|
||||||
}
|
}
|
||||||
@ -53,6 +53,8 @@ impl Function {
|
|||||||
enum RubyOpcode {
|
enum RubyOpcode {
|
||||||
Putnil,
|
Putnil,
|
||||||
Putobject(VALUE),
|
Putobject(VALUE),
|
||||||
|
Setlocal(usize),
|
||||||
|
Getlocal(usize),
|
||||||
Leave,
|
Leave,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -62,11 +64,12 @@ struct FrameState {
|
|||||||
// pc:
|
// pc:
|
||||||
|
|
||||||
stack: Vec<Opnd>,
|
stack: Vec<Opnd>,
|
||||||
|
locals: Vec<Opnd>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FrameState {
|
impl FrameState {
|
||||||
fn new() -> FrameState {
|
fn new() -> FrameState {
|
||||||
FrameState { stack: vec![] }
|
FrameState { stack: vec![], locals: vec![] }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn push(&mut self, opnd: Opnd) {
|
fn push(&mut self, opnd: Opnd) {
|
||||||
@ -76,6 +79,20 @@ impl FrameState {
|
|||||||
fn pop(&mut self) -> Opnd {
|
fn pop(&mut self) -> Opnd {
|
||||||
self.stack.pop().expect("Bytecode stack mismatch")
|
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 {
|
fn to_ssa(opcodes: &Vec<RubyOpcode>) -> Function {
|
||||||
@ -86,6 +103,14 @@ fn to_ssa(opcodes: &Vec<RubyOpcode>) -> Function {
|
|||||||
match opcode {
|
match opcode {
|
||||||
RubyOpcode::Putnil => { state.push(Opnd::Const(Qnil)); },
|
RubyOpcode::Putnil => { state.push(Opnd::Const(Qnil)); },
|
||||||
RubyOpcode::Putobject(val) => { state.push(Opnd::Const(*val)); },
|
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 => {
|
RubyOpcode::Leave => {
|
||||||
result.push_insn(block, Insn::Return { val: state.pop() });
|
result.push_insn(block, Insn::Return { val: state.pop() });
|
||||||
},
|
},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user