Skip to content

Commit 969771e

Browse files
committed
Add new opcodes: ADD_INT, SUB_INT, MUL_INT (etc...)
Add unsafe as_int_unchecked for fast integer extraction Add compiler type tracking (StaticType enum) For loop-optimized functions, assume numeric params are integers
1 parent 5017c5e commit 969771e

File tree

4 files changed

+437
-11
lines changed

4 files changed

+437
-11
lines changed

src/bytecode.rs

Lines changed: 102 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,17 @@ impl std::fmt::Debug for Op {
7575
Self::CAR_LAST => write!(f, "CarLast({}, {})", self.a(), self.b()),
7676
Self::CDR_LAST => write!(f, "CdrLast({}, {})", self.a(), self.b()),
7777
Self::CONS_MOVE => write!(f, "ConsMove({}, {}, {})", self.a(), self.b(), self.c()),
78+
Self::ADD_INT => write!(f, "AddInt({}, {}, {})", self.a(), self.b(), self.c()),
79+
Self::SUB_INT => write!(f, "SubInt({}, {}, {})", self.a(), self.b(), self.c()),
80+
Self::MUL_INT => write!(f, "MulInt({}, {}, {})", self.a(), self.b(), self.c()),
81+
Self::ADD_INT_IMM => write!(f, "AddIntImm({}, {}, {})", self.a(), self.b(), self.c() as i8),
82+
Self::SUB_INT_IMM => write!(f, "SubIntImm({}, {}, {})", self.a(), self.b(), self.c() as i8),
83+
Self::LT_INT => write!(f, "LtInt({}, {}, {})", self.a(), self.b(), self.c()),
84+
Self::LE_INT => write!(f, "LeInt({}, {}, {})", self.a(), self.b(), self.c()),
85+
Self::GT_INT => write!(f, "GtInt({}, {}, {})", self.a(), self.b(), self.c()),
86+
Self::GE_INT => write!(f, "GeInt({}, {}, {})", self.a(), self.b(), self.c()),
87+
Self::JUMP_IF_LE_INT_IMM => write!(f, "JumpIfLeIntImm({}, {}, {})", self.a(), self.b() as i8, self.c() as i8),
88+
Self::JUMP_IF_GT_INT_IMM => write!(f, "JumpIfGtIntImm({}, {}, {})", self.a(), self.b() as i8, self.c() as i8),
7889
_ => write!(f, "Unknown(0x{:08x})", self.0),
7990
}
8091
}
@@ -146,6 +157,21 @@ impl Op {
146157
// If B & 0x80, move from car register (B & 0x7F); if C & 0x80, move from cdr register (C & 0x7F)
147158
pub const CONS_MOVE: u8 = 54; // ABC: dest, car|0x80?, cdr|0x80? - cons with optional moves
148159

160+
// Unboxed integer opcodes - skip type checking for known integer operands
161+
// These are emitted when the compiler can prove both operands are integers
162+
pub const ADD_INT: u8 = 55; // ABC: dest, left, right - integer add (no type check)
163+
pub const SUB_INT: u8 = 56; // ABC: dest, left, right - integer sub (no type check)
164+
pub const MUL_INT: u8 = 57; // ABC: dest, left, right - integer mul (no type check)
165+
pub const ADD_INT_IMM: u8 = 58; // ABC: dest, src, imm (C is i8) - integer add immediate
166+
pub const SUB_INT_IMM: u8 = 59; // ABC: dest, src, imm (C is i8) - integer sub immediate
167+
pub const LT_INT: u8 = 60; // ABC: dest, left, right - integer less than
168+
pub const LE_INT: u8 = 61; // ABC: dest, left, right - integer less or equal
169+
pub const GT_INT: u8 = 62; // ABC: dest, left, right - integer greater than
170+
pub const GE_INT: u8 = 63; // ABC: dest, left, right - integer greater or equal
171+
// Combined compare-and-jump for integers (most common loop pattern)
172+
pub const JUMP_IF_LE_INT_IMM: u8 = 64; // ABC: src, imm (i8), offset (i8) - jump if src <= imm
173+
pub const JUMP_IF_GT_INT_IMM: u8 = 65; // ABC: src, imm (i8), offset (i8) - jump if src > imm (for opposite)
174+
149175
// ========== Constructors ==========
150176

151177
/// Create ABC format instruction: [opcode:8][A:8][B:8][C:8]
@@ -497,6 +523,63 @@ impl Op {
497523
Self::abc(Self::CONS_MOVE, dest, car_with_flag, cdr_with_flag)
498524
}
499525

526+
// ========== Unboxed integer opcodes ==========
527+
528+
#[inline(always)]
529+
pub const fn add_int(dest: Reg, left: Reg, right: Reg) -> Self {
530+
Self::abc(Self::ADD_INT, dest, left, right)
531+
}
532+
533+
#[inline(always)]
534+
pub const fn sub_int(dest: Reg, left: Reg, right: Reg) -> Self {
535+
Self::abc(Self::SUB_INT, dest, left, right)
536+
}
537+
538+
#[inline(always)]
539+
pub const fn mul_int(dest: Reg, left: Reg, right: Reg) -> Self {
540+
Self::abc(Self::MUL_INT, dest, left, right)
541+
}
542+
543+
#[inline(always)]
544+
pub const fn add_int_imm(dest: Reg, src: Reg, imm: i8) -> Self {
545+
Self::abc(Self::ADD_INT_IMM, dest, src, imm as u8)
546+
}
547+
548+
#[inline(always)]
549+
pub const fn sub_int_imm(dest: Reg, src: Reg, imm: i8) -> Self {
550+
Self::abc(Self::SUB_INT_IMM, dest, src, imm as u8)
551+
}
552+
553+
#[inline(always)]
554+
pub const fn lt_int(dest: Reg, left: Reg, right: Reg) -> Self {
555+
Self::abc(Self::LT_INT, dest, left, right)
556+
}
557+
558+
#[inline(always)]
559+
pub const fn le_int(dest: Reg, left: Reg, right: Reg) -> Self {
560+
Self::abc(Self::LE_INT, dest, left, right)
561+
}
562+
563+
#[inline(always)]
564+
pub const fn gt_int(dest: Reg, left: Reg, right: Reg) -> Self {
565+
Self::abc(Self::GT_INT, dest, left, right)
566+
}
567+
568+
#[inline(always)]
569+
pub const fn ge_int(dest: Reg, left: Reg, right: Reg) -> Self {
570+
Self::abc(Self::GE_INT, dest, left, right)
571+
}
572+
573+
#[inline(always)]
574+
pub const fn jump_if_le_int_imm(src: Reg, imm: i8, offset: i8) -> Self {
575+
Self::abc(Self::JUMP_IF_LE_INT_IMM, src, imm as u8, offset as u8)
576+
}
577+
578+
#[inline(always)]
579+
pub const fn jump_if_gt_int_imm(src: Reg, imm: i8, offset: i8) -> Self {
580+
Self::abc(Self::JUMP_IF_GT_INT_IMM, src, imm as u8, offset as u8)
581+
}
582+
500583
// ========== Jump patching helpers ==========
501584

502585
/// Check if this is a jump instruction (for patching)
@@ -509,6 +592,7 @@ impl Op {
509592
|| op == Self::JUMP_IF_LT_IMM || op == Self::JUMP_IF_LE_IMM
510593
|| op == Self::JUMP_IF_GT_IMM || op == Self::JUMP_IF_GE_IMM
511594
|| op == Self::JUMP_IF_NIL || op == Self::JUMP_IF_NOT_NIL
595+
|| op == Self::JUMP_IF_LE_INT_IMM || op == Self::JUMP_IF_GT_INT_IMM
512596
}
513597

514598
/// Patch the offset of a jump instruction
@@ -586,7 +670,8 @@ impl Chunk {
586670
if target < self.code.len() {
587671
jump_targets[target] = true;
588672
}
589-
} else if opcode >= Op::JUMP_IF_LT && opcode <= Op::JUMP_IF_GE_IMM {
673+
} else if (opcode >= Op::JUMP_IF_LT && opcode <= Op::JUMP_IF_GE_IMM)
674+
|| opcode == Op::JUMP_IF_LE_INT_IMM || opcode == Op::JUMP_IF_GT_INT_IMM {
590675
// These use i8 offset in C byte
591676
let offset = op.c() as i8 as isize;
592677
let target = (i as isize + 1 + offset) as usize;
@@ -613,9 +698,15 @@ impl Chunk {
613698
ever_live |= 1u128 << op.c();
614699
}
615700
Op::ADD_IMM | Op::SUB_IMM |
616-
Op::LT_IMM | Op::LE_IMM | Op::GT_IMM | Op::GE_IMM => {
701+
Op::LT_IMM | Op::LE_IMM | Op::GT_IMM | Op::GE_IMM |
702+
Op::ADD_INT_IMM | Op::SUB_INT_IMM => {
617703
ever_live |= 1u128 << op.b();
618704
}
705+
Op::ADD_INT | Op::SUB_INT | Op::MUL_INT |
706+
Op::LT_INT | Op::LE_INT | Op::GT_INT | Op::GE_INT => {
707+
ever_live |= 1u128 << op.b();
708+
ever_live |= 1u128 << op.c();
709+
}
619710
Op::SET_GLOBAL | Op::RETURN => {
620711
ever_live |= 1u128 << op.a();
621712
}
@@ -628,7 +719,8 @@ impl Chunk {
628719
ever_live |= 1u128 << op.b();
629720
}
630721
Op::JUMP_IF_LT_IMM | Op::JUMP_IF_LE_IMM |
631-
Op::JUMP_IF_GT_IMM | Op::JUMP_IF_GE_IMM => {
722+
Op::JUMP_IF_GT_IMM | Op::JUMP_IF_GE_IMM |
723+
Op::JUMP_IF_LE_INT_IMM | Op::JUMP_IF_GT_INT_IMM => {
632724
ever_live |= 1u128 << op.a();
633725
}
634726
_ => {}
@@ -717,7 +809,9 @@ impl Chunk {
717809
// ===== ABC-format arithmetic/comparison (read B, C; write A) =====
718810

719811
Op::ADD | Op::SUB | Op::MUL | Op::DIV | Op::MOD |
720-
Op::LT | Op::LE | Op::GT | Op::GE | Op::EQ | Op::NE => {
812+
Op::LT | Op::LE | Op::GT | Op::GE | Op::EQ | Op::NE |
813+
Op::ADD_INT | Op::SUB_INT | Op::MUL_INT |
814+
Op::LT_INT | Op::LE_INT | Op::GT_INT | Op::GE_INT => {
721815
let dest = op.a();
722816
let b = op.b();
723817
let c = op.c();
@@ -729,7 +823,8 @@ impl Chunk {
729823
// ===== Immediate variants (read B only) =====
730824

731825
Op::ADD_IMM | Op::SUB_IMM |
732-
Op::LT_IMM | Op::LE_IMM | Op::GT_IMM | Op::GE_IMM => {
826+
Op::LT_IMM | Op::LE_IMM | Op::GT_IMM | Op::GE_IMM |
827+
Op::ADD_INT_IMM | Op::SUB_INT_IMM => {
733828
let dest = op.a();
734829
let src = op.b();
735830
live &= !(1u128 << dest);
@@ -773,7 +868,8 @@ impl Chunk {
773868
}
774869

775870
Op::JUMP_IF_LT_IMM | Op::JUMP_IF_LE_IMM |
776-
Op::JUMP_IF_GT_IMM | Op::JUMP_IF_GE_IMM => {
871+
Op::JUMP_IF_GT_IMM | Op::JUMP_IF_GE_IMM |
872+
Op::JUMP_IF_LE_INT_IMM | Op::JUMP_IF_GT_INT_IMM => {
777873
let src = op.a();
778874
live |= 1u128 << src;
779875
}

0 commit comments

Comments
 (0)