diff options
| author | Max Bernstein <max.bernstein@shopify.com> | 2025-02-11 11:13:47 -0500 |
|---|---|---|
| committer | Takashi Kokubun <takashikkbn@gmail.com> | 2025-04-18 21:52:57 +0900 |
| commit | 3372c137a73208a45ce99f805f4bf64551a89ddb (patch) | |
| tree | 1eb81d8d076e1ccac2b09ec012b6ec832b0e3ba2 | |
| parent | d96cb4fe6f0f364a4ba2163e56a1bd4f8c776924 (diff) | |
Create FrameStates with block params
Notes
Notes:
Merged: https://github.com/ruby/ruby/pull/13131
| -rw-r--r-- | zjit/src/ir.rs | 23 |
1 files changed, 21 insertions, 2 deletions
diff --git a/zjit/src/ir.rs b/zjit/src/ir.rs index 7062d65b02..2fccf785be 100644 --- a/zjit/src/ir.rs +++ b/zjit/src/ir.rs @@ -75,8 +75,8 @@ pub struct CallInfo { #[derive(Debug)] pub enum Insn { - // SSA block parameter. Also used for function parameters in the function's entry block. PutSelf, + // SSA block parameter. Also used for function parameters in the function's entry block. Param { idx: usize }, StringCopy { val: Opnd }, @@ -311,6 +311,11 @@ pub enum ParseError { StackUnderflow(FrameState), } +/// Return the number of locals in the given ISEQ +fn num_locals(iseq: *const rb_iseq_t) -> u32 { + unsafe { get_iseq_body_local_table_size(iseq) } +} + pub fn iseq_to_ssa(iseq: *const rb_iseq_t) -> Result<Function, ParseError> { let mut fun = Function::new(iseq); // Compute a map of PC->Block by finding jump targets @@ -329,7 +334,20 @@ pub fn iseq_to_ssa(iseq: *const rb_iseq_t) -> Result<Function, ParseError> { 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 let Some((incoming_state, block, mut insn_idx)) = queue.pop_front() { + let mut state = { + let mut result = FrameState::new(); + let mut idx = 0; + for _ in 0..num_locals(iseq) { + result.locals.push(Opnd::Insn(fun.push_insn(block, Insn::Param { idx }))); + idx += 1; + } + for _ in incoming_state.stack { + result.stack.push(Opnd::Insn(fun.push_insn(block, Insn::Param { idx }))); + idx += 1; + } + result + }; while insn_idx < iseq_size { // Get the current pc and opcode let pc = unsafe { rb_iseq_pc_at_idx(iseq, insn_idx.into()) }; @@ -466,6 +484,7 @@ pub fn iseq_to_ssa(iseq: *const rb_iseq_t) -> Result<Function, ParseError> { YARVINSN_leave => { fun.push_insn(block, Insn::Return { val: state.pop()? }); + break; // Don't add an edge to the queue } YARVINSN_opt_send_without_block => { |
