Make iseq_to_ssa return Function object
This commit is contained in:
parent
5208720746
commit
c5e17f50b7
Notes:
git
2025-04-18 13:49:31 +00:00
@ -24,7 +24,7 @@ impl std::fmt::Display for BlockId {
|
|||||||
|
|
||||||
/// Instruction operand
|
/// Instruction operand
|
||||||
#[derive(Debug, PartialEq, Clone, Copy)]
|
#[derive(Debug, PartialEq, Clone, Copy)]
|
||||||
enum Opnd {
|
pub enum Opnd {
|
||||||
Const(VALUE),
|
Const(VALUE),
|
||||||
Insn(InsnId),
|
Insn(InsnId),
|
||||||
}
|
}
|
||||||
@ -40,13 +40,13 @@ impl std::fmt::Display for Opnd {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
struct BranchEdge {
|
pub struct BranchEdge {
|
||||||
target: BlockId,
|
target: BlockId,
|
||||||
args: Vec<Opnd>,
|
args: Vec<Opnd>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
enum Insn {
|
pub enum Insn {
|
||||||
// SSA block parameter. Also used for function parameters in the function's entry block.
|
// SSA block parameter. Also used for function parameters in the function's entry block.
|
||||||
Param { idx: usize },
|
Param { idx: usize },
|
||||||
|
|
||||||
@ -89,7 +89,7 @@ enum Insn {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Debug, PartialEq)]
|
#[derive(Default, Debug, PartialEq)]
|
||||||
struct Block {
|
pub struct Block {
|
||||||
params: Vec<InsnId>,
|
params: Vec<InsnId>,
|
||||||
insns: Vec<InsnId>,
|
insns: Vec<InsnId>,
|
||||||
}
|
}
|
||||||
@ -98,7 +98,7 @@ impl Block {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
struct Function {
|
pub struct Function {
|
||||||
// TODO:
|
// TODO:
|
||||||
// ISEQ this function refers to
|
// ISEQ this function refers to
|
||||||
//iseq: *const iseqptr_t,
|
//iseq: *const iseqptr_t,
|
||||||
@ -240,6 +240,7 @@ fn to_ssa(opcodes: &Vec<RubyOpcode>) -> Function {
|
|||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get instruction argument
|
||||||
fn get_arg(pc: *const VALUE, arg_idx: isize) -> VALUE {
|
fn get_arg(pc: *const VALUE, arg_idx: isize) -> VALUE {
|
||||||
unsafe { *(pc.offset(arg_idx + 1)) }
|
unsafe { *(pc.offset(arg_idx + 1)) }
|
||||||
}
|
}
|
||||||
@ -272,10 +273,10 @@ fn compute_jump_targets(iseq: *const rb_iseq_t) -> Vec<u32> {
|
|||||||
jump_targets
|
jump_targets
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn iseq_to_ssa(iseq: *const rb_iseq_t) {
|
pub fn iseq_to_ssa(iseq: *const rb_iseq_t) -> Function {
|
||||||
let mut result = Function::new();
|
let mut fun = Function::new();
|
||||||
let mut state = FrameState::new();
|
let mut state = FrameState::new();
|
||||||
let mut block = result.entry_block;
|
let mut block = fun.entry_block;
|
||||||
|
|
||||||
let iseq_size = unsafe { get_iseq_encoded_size(iseq) };
|
let iseq_size = unsafe { get_iseq_encoded_size(iseq) };
|
||||||
let mut insn_idx = 0;
|
let mut insn_idx = 0;
|
||||||
@ -287,7 +288,7 @@ pub fn iseq_to_ssa(iseq: *const rb_iseq_t) {
|
|||||||
if insn_idx == 0 {
|
if insn_idx == 0 {
|
||||||
todo!("Separate entry block for param/self/...");
|
todo!("Separate entry block for param/self/...");
|
||||||
}
|
}
|
||||||
insn_idx_to_block.insert(insn_idx, result.new_block());
|
insn_idx_to_block.insert(insn_idx, fun.new_block());
|
||||||
}
|
}
|
||||||
|
|
||||||
while insn_idx < iseq_size {
|
while insn_idx < iseq_size {
|
||||||
@ -310,19 +311,19 @@ pub fn iseq_to_ssa(iseq: *const rb_iseq_t) {
|
|||||||
YARVINSN_putobject => { state.push(Opnd::Const(get_arg(pc, 0))); },
|
YARVINSN_putobject => { state.push(Opnd::Const(get_arg(pc, 0))); },
|
||||||
YARVINSN_putstring => {
|
YARVINSN_putstring => {
|
||||||
let val = Opnd::Const(get_arg(pc, 0));
|
let val = Opnd::Const(get_arg(pc, 0));
|
||||||
let insn_id = result.push_insn(block, Insn::StringCopy { val });
|
let insn_id = fun.push_insn(block, Insn::StringCopy { val });
|
||||||
state.push(Opnd::Insn(insn_id));
|
state.push(Opnd::Insn(insn_id));
|
||||||
}
|
}
|
||||||
YARVINSN_intern => {
|
YARVINSN_intern => {
|
||||||
let val = state.pop();
|
let val = state.pop();
|
||||||
let insn_id = result.push_insn(block, Insn::StringIntern { val });
|
let insn_id = fun.push_insn(block, Insn::StringIntern { val });
|
||||||
state.push(Opnd::Insn(insn_id));
|
state.push(Opnd::Insn(insn_id));
|
||||||
}
|
}
|
||||||
YARVINSN_newarray => {
|
YARVINSN_newarray => {
|
||||||
let count = get_arg(pc, 0).as_usize();
|
let count = get_arg(pc, 0).as_usize();
|
||||||
let insn_id = result.push_insn(block, Insn::NewArray { count });
|
let insn_id = fun.push_insn(block, Insn::NewArray { count });
|
||||||
for idx in (0..count).rev() {
|
for idx in (0..count).rev() {
|
||||||
result.push_insn(block, Insn::ArraySet { idx, val: state.pop() });
|
fun.push_insn(block, Insn::ArraySet { idx, val: state.pop() });
|
||||||
}
|
}
|
||||||
state.push(Opnd::Insn(insn_id));
|
state.push(Opnd::Insn(insn_id));
|
||||||
}
|
}
|
||||||
@ -341,18 +342,18 @@ pub fn iseq_to_ssa(iseq: *const rb_iseq_t) {
|
|||||||
let obj = get_arg(pc, 0);
|
let obj = get_arg(pc, 0);
|
||||||
let pushval = get_arg(pc, 0);
|
let pushval = get_arg(pc, 0);
|
||||||
let v = state.pop();
|
let v = state.pop();
|
||||||
state.push(Opnd::Insn(result.push_insn(block, Insn::Defined { op_type, obj, pushval, v })));
|
state.push(Opnd::Insn(fun.push_insn(block, Insn::Defined { op_type, obj, pushval, v })));
|
||||||
}
|
}
|
||||||
YARVINSN_opt_getconstant_path => {
|
YARVINSN_opt_getconstant_path => {
|
||||||
let ic = get_arg(pc, 0).as_ptr::<u8>();
|
let ic = get_arg(pc, 0).as_ptr::<u8>();
|
||||||
state.push(Opnd::Insn(result.push_insn(block, Insn::GetConstantPath { ic })));
|
state.push(Opnd::Insn(fun.push_insn(block, Insn::GetConstantPath { ic })));
|
||||||
}
|
}
|
||||||
YARVINSN_branchunless => {
|
YARVINSN_branchunless => {
|
||||||
let offset = get_arg(pc, 0).as_i64();
|
let offset = get_arg(pc, 0).as_i64();
|
||||||
let val = state.pop();
|
let val = state.pop();
|
||||||
let test_id = result.push_insn(block, Insn::Test { val });
|
let test_id = fun.push_insn(block, Insn::Test { val });
|
||||||
// TODO(max): Check interrupts
|
// TODO(max): Check interrupts
|
||||||
let branch_id = result.push_insn(block,
|
let branch_id = fun.push_insn(block,
|
||||||
Insn::IfFalse {
|
Insn::IfFalse {
|
||||||
val: Opnd::Insn(test_id),
|
val: Opnd::Insn(test_id),
|
||||||
target: BranchEdge {
|
target: BranchEdge {
|
||||||
@ -378,7 +379,7 @@ pub fn iseq_to_ssa(iseq: *const rb_iseq_t) {
|
|||||||
// TODO: we need to add a BOP not redefined check here
|
// TODO: we need to add a BOP not redefined check here
|
||||||
let v0 = state.pop();
|
let v0 = state.pop();
|
||||||
let v1 = state.pop();
|
let v1 = state.pop();
|
||||||
let add_id = result.push_insn(block, Insn::Add { v0, v1 });
|
let add_id = fun.push_insn(block, Insn::Add { v0, v1 });
|
||||||
state.push(Opnd::Insn(add_id));
|
state.push(Opnd::Insn(add_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -386,18 +387,19 @@ pub fn iseq_to_ssa(iseq: *const rb_iseq_t) {
|
|||||||
// TODO: we need to add a BOP not redefined check here
|
// TODO: we need to add a BOP not redefined check here
|
||||||
let v0 = state.pop();
|
let v0 = state.pop();
|
||||||
let v1 = state.pop();
|
let v1 = state.pop();
|
||||||
let lt_id = result.push_insn(block, Insn::Lt { v0, v1 });
|
let lt_id = fun.push_insn(block, Insn::Lt { v0, v1 });
|
||||||
state.push(Opnd::Insn(lt_id));
|
state.push(Opnd::Insn(lt_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
YARVINSN_leave => {
|
YARVINSN_leave => {
|
||||||
result.push_insn(block, Insn::Return { val: state.pop() });
|
fun.push_insn(block, Insn::Return { val: state.pop() });
|
||||||
}
|
}
|
||||||
_ => eprintln!("zjit: to_ssa: unknown opcode `{}'", insn_name(opcode as usize)),
|
_ => eprintln!("zjit: to_ssa: unknown opcode `{}'", insn_name(opcode as usize)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
print!("SSA:\n{result}");
|
|
||||||
return;
|
print!("SSA:\n{fun}");
|
||||||
|
return fun;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user