8000 ZJIT: Add newrange support by st0012 · Pull Request #13505 · ruby/ruby · GitHub
[go: up one dir, main page]

Skip to content

ZJIT: Add newrange support #13505

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 5, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Add RangeType enum for Range insn's flag
  • Loading branch information
st0012 committed Jun 4, 2025
commit 78b2ba9d0fba27f0ca3f5f18ee8eb21e8f24ece0
4 changes: 2 additions & 2 deletions zjit/src/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::state::ZJITState;
use crate::{asm::CodeBlock, cruby::*, options::debug, virtualmem::CodePtr};
use crate::invariants::{iseq_escapes_ep, track_no_ep_escape_assumption};
use crate::backend::lir::{self, asm_comment, Assembler, Opnd, Target, CFP, C_ARG_OPNDS, C_RET_OPND, EC, SP};
use crate::hir::{iseq_to_hir, Block, BlockId, BranchEdge, CallInfo};
use crate::hir::{iseq_to_hir, Block, BlockId, BranchEdge, CallInfo, RangeType};
use crate::hir::{Const, FrameState, Function, Insn, InsnId};
use crate::hir_type::{types::Fixnum, Type};
use crate::options::get_option;
Expand Down Expand Up @@ -558,7 +558,7 @@ fn gen_new_range(
asm: &mut Assembler,
low: lir::Opnd,
high: lir::Opnd,
flag: u32,
flag: RangeType,
state: &FrameState,
) -> lir::Opnd {
asm_comment!(asm, "call rb_range_new");
Expand Down
71 changes: 55 additions & 16 deletions zjit/src/hir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,50 @@ impl Const {
}
}

pub enum RangeType {
Inclusive = 0, // include the end value
Exclusive = 1, // exclude the end value
}

impl std::fmt::Display for RangeType {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", match self {
RangeType::Inclusive => "NewRangeInclusive",
RangeType::Exclusive => "NewRangeExclusive",
})
}
}

impl std::fmt::Debug for RangeType {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", self.to_string())
}
}

impl Clone for RangeType {
fn clone(&self) -> Self {
*self
}
}

impl Copy for RangeType {}

impl From<u32> for RangeType {
fn from(flag: u32) -> Self {
match flag {
0 => RangeType::Inclusive,
1 => RangeType::Exclusive,
_ => panic!("Invalid range flag: {}", flag),
}
}
}

impl From<RangeType> for u32 {
fn from(range_type: RangeType) -> Self {
range_type as u32
}
}

/// Print adaptor for [`Const`]. See [`PtrPrintMap`].
struct ConstPrinter<'a> {
inner: &'a Const,
Expand Down Expand Up @@ -330,7 +374,7 @@ pub enum Insn {
NewArray { elements: Vec<InsnId>, state: InsnId },
/// NewHash contains a vec of (key, value) pairs
NewHash { elements: Vec<(InsnId,InsnId)>, state: InsnId },
NewRange { low: InsnId, high: InsnId, flag: u32, state: InsnId },
NewRange { low: InsnId, high: InsnId, flag: RangeType, state: InsnId },
ArraySet { array: InsnId, idx: usize, val: InsnId },
ArrayDup { val: InsnId, state: InsnId },
ArrayMax { elements: Vec<InsnId>, state: InsnId },
Expand Down Expand Up @@ -493,12 +537,7 @@ impl<'a> std::fmt::Display for InsnPrinter<'a> {
Ok(())
}
Insn::NewRange { low, high, flag, .. } => {
let flag_str = match *flag {
0 => "..",
1 => "...",
_ => &format!("flag({})", flag),
};
write!(f, "NewRange {low} {flag_str} {high}")
write!(f, "NewRange {low} {flag} {high}")
}
Insn::ArrayMax { elements, .. } => {
write!(f, "ArrayMax")?;
Expand Down Expand Up @@ -2360,7 +2399,7 @@ pub fn iseq_to_hir(iseq: *const rb_iseq_t) -> Result<Function, ParseError> {
fun.push_insn(block, Insn::SetIvar { self_val, id, val, state: exit_id });
}
YARVINSN_newrange => {
let flag = get_arg(pc, 0).as_u32();
let flag = RangeType::from(get_arg(pc, 0).as_u32());
let high = state.stack_pop()?;
let low = state.stack_pop()?;
let exit_id = fun.push_insn(block, Insn::Snapshot { state: exit_state });
Expand Down Expand Up @@ -2761,47 +2800,47 @@ mod tests {
}

#[test]
fn test_new_range_with_one_element() {
fn test_new_range_inclusive_with_one_element() {
eval("def test(a) = (a..10)");
assert_method_hir_with_opcode("test", YARVINSN_newrange, expect![[r#"
fn test:
bb0(v0:BasicObject):
v2:Fixnum[10] = Const Value(10)
v4:RangeExact = NewRange v0 .. v2
v4:RangeExact = NewRange v0 NewRangeInclusive v2
Return v4
"#]]);
}

#[test]
fn test_new_range_with_two_elements() {
fn test_new_range_inclusive_with_two_elements() {
eval("def test(a, b) = (a..b)");
assert_method_hir_with_opcode("test", YARVINSN_newrange, expect![[r#"
fn test:
bb0(v0:BasicObject, v1:BasicObject):
v4:RangeExact = NewRange v0 .. v1
v4:RangeExact = NewRange v0 NewRangeInclusive v1
Return v4
"#]]);
}

#[test]
fn test_new_range_exclude_with_one_element() {
fn test_new_range_exclusive_with_one_element() {
eval("def test(a) = (a...10)");
assert_method_hir_with_opcode("test", YARVINSN_newrange, expect![[r#"
fn test:
bb0(v0:BasicObject):
v2:Fixnum[10] = Const Value(10)
v4:RangeExact = NewRange v0 ... v2
v4:RangeExact = NewRange v0 NewRangeExclusive v2
Return v4
"#]]);
}

#[test]
fn test_new_range_exclude_with_two_elements() {
fn test_new_range_exclusive_with_two_elements() {
eval("def test(a, b) = (a...b)");
assert_method_hir_with_opcode("test", YARVINSN_newrange, expect![[r#"
fn test:
bb0(v0:BasicObject, v1:BasicObject):
v4:RangeExact = NewRange v0 ... v1
v4:RangeExact = NewRange v0 NewRangeExclusive v1
Return v4
"#]]);
}
Expand Down
0