Traverse bytecode using block queue
This commit is contained in:
parent
3b97bcea13
commit
948560ac5a
Notes:
git
2025-04-18 13:49:14 +00:00
@ -313,14 +313,6 @@ pub enum ParseError {
|
|||||||
|
|
||||||
pub fn iseq_to_ssa(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
|
pub fn iseq_to_ssa(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
|
||||||
let mut fun = Function::new(iseq);
|
let mut fun = Function::new(iseq);
|
||||||
// TODO(max): Queue TranslationContexts so that we can assign states to basic blocks instead of
|
|
||||||
// flowing one state through the linear iseq
|
|
||||||
let mut state = FrameState::new();
|
|
||||||
let mut block = fun.entry_block;
|
|
||||||
|
|
||||||
let iseq_size = unsafe { get_iseq_encoded_size(iseq) };
|
|
||||||
let mut insn_idx = 0;
|
|
||||||
|
|
||||||
// Compute a map of PC->Block by finding jump targets
|
// Compute a map of PC->Block by finding jump targets
|
||||||
let jump_targets = compute_jump_targets(iseq);
|
let jump_targets = compute_jump_targets(iseq);
|
||||||
let mut insn_idx_to_block = HashMap::new();
|
let mut insn_idx_to_block = HashMap::new();
|
||||||
@ -331,23 +323,23 @@ pub fn iseq_to_ssa(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
|
|||||||
insn_idx_to_block.insert(insn_idx, fun.new_block());
|
insn_idx_to_block.insert(insn_idx, fun.new_block());
|
||||||
}
|
}
|
||||||
|
|
||||||
while insn_idx < iseq_size {
|
// Iteratively fill out basic blocks using a queue
|
||||||
// Get the block id for this instruction
|
// TODO(max): Basic block arguments at edges
|
||||||
if let Some(block_id) = insn_idx_to_block.get(&insn_idx) {
|
let mut queue = std::collections::VecDeque::new();
|
||||||
block = *block_id;
|
queue.push_back((FrameState::new(), fun.entry_block, /*insn_idx=*/0 as u32));
|
||||||
}
|
|
||||||
|
|
||||||
|
let iseq_size = unsafe { get_iseq_encoded_size(iseq) };
|
||||||
|
while let Some((mut state, block, mut insn_idx)) = queue.pop_front() {
|
||||||
|
while insn_idx < iseq_size {
|
||||||
// Get the current pc and opcode
|
// Get the current pc and opcode
|
||||||
let pc = unsafe { rb_iseq_pc_at_idx(iseq, insn_idx.into()) };
|
let pc = unsafe { rb_iseq_pc_at_idx(iseq, insn_idx.into()) };
|
||||||
state.pc = unsafe { *pc };
|
state.pc = unsafe { *pc };
|
||||||
|
|
||||||
fun.push_insn(block, Insn::Snapshot { state: state.clone() });
|
fun.push_insn(block, Insn::Snapshot { state: state.clone() });
|
||||||
|
|
||||||
// try_into() call below is unfortunate. Maybe pick i32 instead of usize for opcodes.
|
// try_into() call below is unfortunate. Maybe pick i32 instead of usize for opcodes.
|
||||||
let opcode: u32 = unsafe { rb_iseq_opcode_at_pc(iseq, pc) }
|
let opcode: u32 = unsafe { rb_iseq_opcode_at_pc(iseq, pc) }
|
||||||
.try_into()
|
.try_into()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// Move to the next instruction to compile
|
// Move to the next instruction to compile
|
||||||
insn_idx += insn_len(opcode as usize);
|
insn_idx += insn_len(opcode as usize);
|
||||||
|
|
||||||
@ -488,6 +480,12 @@ pub fn iseq_to_ssa(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
|
|||||||
}
|
}
|
||||||
_ => eprintln!("zjit: to_ssa: unknown opcode `{}'", insn_name(opcode as usize)),
|
_ => eprintln!("zjit: to_ssa: unknown opcode `{}'", insn_name(opcode as usize)),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if insn_idx_to_block.contains_key(&insn_idx) {
|
||||||
|
queue.push_back((state, insn_idx_to_block[&insn_idx], insn_idx));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let formatter = FunctionPrinter::from(&fun);
|
let formatter = FunctionPrinter::from(&fun);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user