Add Newarray

This commit is contained in:
Max Bernstein 2025-02-06 11:41:20 -05:00 committed by Takashi Kokubun
parent 0bb709718b
commit 21026abbd6
Notes: git 2025-04-18 13:49:49 +00:00

View File

@ -19,6 +19,8 @@ enum Insn {
Param { idx: usize }, Param { idx: usize },
StringCopy { val: Opnd }, StringCopy { val: Opnd },
StringIntern { val: Opnd }, StringIntern { val: Opnd },
AllocArray { count: usize },
ArraySet { idx: usize, val: Opnd },
// Control flow instructions // Control flow instructions
Return { val: Opnd }, Return { val: Opnd },
@ -72,6 +74,7 @@ enum RubyOpcode {
Intern, Intern,
Setlocal(usize), Setlocal(usize),
Getlocal(usize), Getlocal(usize),
Newarray(usize),
Leave, Leave,
} }
@ -129,6 +132,13 @@ fn to_ssa(opcodes: &Vec<RubyOpcode>) -> Function {
let insn_id = result.push_insn(block, Insn::StringIntern { val }); let insn_id = result.push_insn(block, Insn::StringIntern { val });
state.push(Opnd::Insn(insn_id)); state.push(Opnd::Insn(insn_id));
} }
RubyOpcode::Newarray(count) => {
let insn_id = result.push_insn(block, Insn::AllocArray { count: *count });
for idx in (0..*count).rev() {
result.push_insn(block, Insn::ArraySet { idx, val: state.pop() });
}
state.push(Opnd::Insn(insn_id));
}
RubyOpcode::Setlocal(idx) => { RubyOpcode::Setlocal(idx) => {
let val = state.pop(); let val = state.pop();
state.setlocal(*idx, val); state.setlocal(*idx, val);
@ -187,4 +197,69 @@ mod tests {
], ],
}); });
} }
#[test]
fn test_newarray0() {
let opcodes = vec![
RubyOpcode::Newarray(0),
RubyOpcode::Leave,
];
let function = to_ssa(&opcodes);
assert_eq!(function, Function {
entry_block: BlockId(0),
insns: vec![
Insn::AllocArray { count: 0 },
Insn::Return { val: Opnd::Insn(InsnId(0)) }
],
blocks: vec![
Block { params: vec![], insns: vec![InsnId(0), InsnId(1)] }
],
});
}
#[test]
fn test_newarray1() {
let opcodes = vec![
RubyOpcode::Putnil,
RubyOpcode::Newarray(1),
RubyOpcode::Leave,
];
let function = to_ssa(&opcodes);
assert_eq!(function, Function {
entry_block: BlockId(0),
insns: vec![
Insn::AllocArray { count: 1 },
Insn::ArraySet { idx: 0, val: Opnd::Const(Qnil) },
Insn::Return { val: Opnd::Insn(InsnId(0)) }
],
blocks: vec![
Block { params: vec![], insns: vec![InsnId(0), InsnId(1), InsnId(2)] }
],
});
}
#[test]
fn test_newarray2() {
let three: VALUE = VALUE::fixnum_from_usize(3);
let four: VALUE = VALUE::fixnum_from_usize(4);
let opcodes = vec![
RubyOpcode::Putobject(three),
RubyOpcode::Putobject(four),
RubyOpcode::Newarray(2),
RubyOpcode::Leave,
];
let function = to_ssa(&opcodes);
assert_eq!(function, Function {
entry_block: BlockId(0),
insns: vec![
Insn::AllocArray { count: 2 },
Insn::ArraySet { idx: 1, val: Opnd::Const(four) },
Insn::ArraySet { idx: 0, val: Opnd::Const(three) },
Insn::Return { val: Opnd::Insn(InsnId(0)) }
],
blocks: vec![
Block { params: vec![], insns: vec![InsnId(0), InsnId(1), InsnId(2), InsnId(3)] }
],
});
}
} }