Skip to content
Merged
Changes from 1 commit
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
fad76c6
save
ShaharNaveh Jan 11, 2026
af70361
Merge remote-tracking branch 'upstream/main' into bytecode-pseudo-opc…
ShaharNaveh Jan 11, 2026
ea53cec
save
ShaharNaveh Jan 11, 2026
1ca20a9
Merge remote-tracking branch 'upstream/main' into bytecode-pseudo-opc…
ShaharNaveh Jan 12, 2026
6f09ebe
Base compiler-core
ShaharNaveh Jan 12, 2026
6805175
save
ShaharNaveh Jan 12, 2026
046e17a
Codegen compile
ShaharNaveh Jan 12, 2026
d627623
Move LoadCloure back to RealInstruction
ShaharNaveh Jan 12, 2026
697fe41
Fix opcode.rs
ShaharNaveh Jan 12, 2026
11fc63f
Merge remote-tracking branch 'upstream/main' into bytecode-pseudo-opc…
ShaharNaveh Jan 13, 2026
33b4554
Fix `TryFrom<u8>` for RealInstruction
ShaharNaveh Jan 13, 2026
6140186
Fix script
ShaharNaveh Jan 13, 2026
7acdc1a
Fix jit
ShaharNaveh Jan 13, 2026
0fad43f
Fix typo
ShaharNaveh Jan 13, 2026
24f5161
Fix typo
ShaharNaveh Jan 13, 2026
6e91410
Remove popblock
ShaharNaveh Jan 13, 2026
8751953
Fix docs
ShaharNaveh Jan 13, 2026
8b73441
Fix more docs
ShaharNaveh Jan 13, 2026
d6e46f8
ok word `argty`
ShaharNaveh Jan 13, 2026
0872cb6
Revert "ok word `argty`"
ShaharNaveh Jan 13, 2026
0c7880d
Rename argty -> arg_ty
ShaharNaveh Jan 13, 2026
1a5c72b
Merge remote-tracking branch 'upstream/main' into bytecode-pseudo-opc…
ShaharNaveh Jan 13, 2026
761fa4a
Simplify `emit` macro
ShaharNaveh Jan 13, 2026
4eed137
Trigger CI
ShaharNaveh Jan 13, 2026
8f777d2
Trigger CI
ShaharNaveh Jan 13, 2026
bff25eb
Trigger CI
ShaharNaveh Jan 13, 2026
91c01e6
Merge remote-tracking branch 'upstream/main' into bytecode-pseudo-opc…
ShaharNaveh Jan 14, 2026
f6a0b26
Merge remote-tracking branch 'upstream/main' into bytecode-pseudo-opc…
ShaharNaveh Jan 14, 2026
118ecf3
Move docs
ShaharNaveh Jan 14, 2026
c517585
Fix oparg docs
ShaharNaveh Jan 14, 2026
78958aa
Revert "Move docs"
ShaharNaveh Jan 14, 2026
a405cca
Merge remote-tracking branch 'upstream/main' into bytecode-pseudo-opc…
ShaharNaveh Jan 14, 2026
8ae98b2
Remove `Eq` & `ParitalEq` for RealInstruction
ShaharNaveh Jan 14, 2026
1453726
Simplify `match` arms
ShaharNaveh Jan 14, 2026
f207284
Trigger CI
ShaharNaveh Jan 14, 2026
a1555dc
Trigger CI
ShaharNaveh Jan 14, 2026
c443f8e
Remove `repr(u16)` for `Instruction`
ShaharNaveh Jan 14, 2026
453212e
Fix doc
ShaharNaveh Jan 14, 2026
1f8722a
Rename the enums
ShaharNaveh Jan 14, 2026
0096a65
Restore fmt_dis for LoadClousure
ShaharNaveh Jan 14, 2026
045d576
Fix script
ShaharNaveh Jan 14, 2026
b00f81f
Fix commet
ShaharNaveh Jan 14, 2026
4823d17
Merge remote-tracking branch 'upstream/main' into bytecode-pseudo-opc…
ShaharNaveh Jan 14, 2026
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
Fix typo
  • Loading branch information
ShaharNaveh committed Jan 13, 2026
commit 0fad43f9109051a6d1df4f57a25c3bc528163ceb
68 changes: 34 additions & 34 deletions crates/jit/src/instructions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use cranelift::prelude::*;
use num_traits::cast::ToPrimitive;
use rustpython_compiler_core::bytecode::{
self, BinaryOperator, BorrowedConstant, CodeObject, ComparisonOperator, IntrinsicFunction1,
Label, OpArg, OpArgState, ReallInstruction,
Label, OpArg, OpArgState, RealInstruction,
};
use std::collections::HashMap;

Expand Down Expand Up @@ -210,11 +210,11 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {

// If that was an unconditional branch or return, mark future instructions unreachable
match instruction {
ReallInstruction::ReturnValue
| ReallInstruction::ReturnConst { .. }
| ReallInstruction::JumpBackward { .. }
| ReallInstruction::JumpBackwardNoInterrupt { .. }
| ReallInstruction::JumpForward { .. } => {
RealInstruction::ReturnValue
| RealInstruction::ReturnConst { .. }
| RealInstruction::JumpBackward { .. }
| RealInstruction::JumpBackwardNoInterrupt { .. }
| RealInstruction::JumpForward { .. } => {
in_unreachable_code = true;
}
_ => {}
Expand Down Expand Up @@ -289,11 +289,11 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
&mut self,
func_ref: FuncRef,
bytecode: &CodeObject<C>,
instruction: ReallInstruction,
instruction: RealInstruction,
arg: OpArg,
) -> Result<(), JitCompileError> {
match instruction {
ReallInstruction::BinaryOp { op } => {
RealInstruction::BinaryOp { op } => {
let op = op.get(arg);
// the rhs is popped off first
let b = self.stack.pop().ok_or(JitCompileError::BadBytecode)?;
Expand Down Expand Up @@ -454,12 +454,12 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {

Ok(())
}
ReallInstruction::BuildTuple { size } => {
RealInstruction::BuildTuple { size } => {
let elements = self.pop_multiple(size.get(arg) as usize);
self.stack.push(JitValue::Tuple(elements));
Ok(())
}
ReallInstruction::Call { nargs } => {
RealInstruction::Call { nargs } => {
let nargs = nargs.get(arg);

let mut args = Vec::new();
Expand All @@ -485,11 +485,11 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
_ => Err(JitCompileError::BadBytecode),
}
}
ReallInstruction::PushNull => {
RealInstruction::PushNull => {
self.stack.push(JitValue::Null);
Ok(())
}
ReallInstruction::CallIntrinsic1 { func } => {
RealInstruction::CallIntrinsic1 { func } => {
match func.get(arg) {
IntrinsicFunction1::UnaryPositive => {
match self.stack.pop().ok_or(JitCompileError::BadBytecode)? {
Expand All @@ -504,7 +504,7 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
_ => Err(JitCompileError::NotSupported),
}
}
ReallInstruction::CompareOp { op, .. } => {
RealInstruction::CompareOp { op, .. } => {
let op = op.get(arg);
// the rhs is popped off first
let b = self.stack.pop().ok_or(JitCompileError::BadBytecode)?;
Expand Down Expand Up @@ -558,22 +558,22 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
_ => Err(JitCompileError::NotSupported),
}
}
ReallInstruction::ExtendedArg => Ok(()),
RealInstruction::ExtendedArg => Ok(()),

ReallInstruction::JumpBackward { target }
| ReallInstruction::JumpBackwardNoInterrupt { target }
| ReallInstruction::JumpForward { target } => {
RealInstruction::JumpBackward { target }
| RealInstruction::JumpBackwardNoInterrupt { target }
| RealInstruction::JumpForward { target } => {
let target_block = self.get_or_create_block(target.get(arg));
self.builder.ins().jump(target_block, &[]);
Ok(())
}
ReallInstruction::LoadConst { idx } => {
RealInstruction::LoadConst { idx } => {
let val = self
.prepare_const(bytecode.constants[idx.get(arg) as usize].borrow_constant())?;
self.stack.push(val);
Ok(())
}
ReallInstruction::LoadFast(idx) => {
RealInstruction::LoadFast(idx) => {
let local = self.variables[idx.get(arg) as usize]
.as_ref()
.ok_or(JitCompileError::BadBytecode)?;
Expand All @@ -583,7 +583,7 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
));
Ok(())
}
ReallInstruction::LoadGlobal(idx) => {
RealInstruction::LoadGlobal(idx) => {
let name = &bytecode.names[idx.get(arg) as usize];

if name.as_ref() != bytecode.obj_name.as_ref() {
Expand All @@ -593,12 +593,12 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
Ok(())
}
}
ReallInstruction::Nop => Ok(()),
ReallInstruction::PopBlock => {
RealInstruction::Nop => Ok(()),
RealInstruction::PopBlock => {
// TODO: block support
Ok(())
}
ReallInstruction::PopJumpIfFalse { target } => {
RealInstruction::PopJumpIfFalse { target } => {
let cond = self.stack.pop().ok_or(JitCompileError::BadBytecode)?;
let val = self.boolean_val(cond)?;
let then_block = self.get_or_create_block(target.get(arg));
Expand All @@ -611,7 +611,7 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {

Ok(())
}
ReallInstruction::PopJumpIfTrue { target } => {
RealInstruction::PopJumpIfTrue { target } => {
let cond = self.stack.pop().ok_or(JitCompileError::BadBytecode)?;
let val = self.boolean_val(cond)?;
let then_block = self.get_or_create_block(target.get(arg));
Expand All @@ -624,41 +624,41 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {

Ok(())
}
ReallInstruction::PopTop => {
RealInstruction::PopTop => {
self.stack.pop();
Ok(())
}
ReallInstruction::Resume { arg: _resume_arg } => {
RealInstruction::Resume { arg: _resume_arg } => {
// TODO: Implement the resume instruction
Ok(())
}
ReallInstruction::ReturnConst { idx } => {
RealInstruction::ReturnConst { idx } => {
let val = self
.prepare_const(bytecode.constants[idx.get(arg) as usize].borrow_constant())?;
self.return_value(val)
}
ReallInstruction::ReturnValue => {
RealInstruction::ReturnValue => {
let val = self.stack.pop().ok_or(JitCompileError::BadBytecode)?;
self.return_value(val)
}
ReallInstruction::StoreFast(idx) => {
RealInstruction::StoreFast(idx) => {
let val = self.stack.pop().ok_or(JitCompileError::BadBytecode)?;
self.store_variable(idx.get(arg), val)
}
ReallInstruction::Swap { index } => {
RealInstruction::Swap { index } => {
let len = self.stack.len();
let i = len - 1;
let j = len - 1 - index.get(arg) as usize;
self.stack.swap(i, j);
Ok(())
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Fix SWAP semantics: index math is off by one vs CPython/RustPython stack convention.

On Line 647, j = len - 1 - index makes SWAP 1 swap TOS with the second-from-top, but SWAP(1) should swap TOS with itself (no-op). This can miscompile valid code.

Proposed fix (treat SWAP index as 1-based)
             RealInstruction::Swap { index } => {
                 let len = self.stack.len();
-                let i = len - 1;
-                let j = len - 1 - index.get(arg) as usize;
+                let i = len - 1;
+                let n = index.get(arg) as usize; // 1-based
+                if n == 0 || n > len {
+                    return Err(JitCompileError::BadBytecode);
+                }
+                let j = len - n;
                 self.stack.swap(i, j);
                 Ok(())
             }
🤖 Prompt for AI Agents
In @crates/jit/src/instructions.rs around lines 644 - 650, The SWAP
implementation in RealInstruction::Swap uses zero-based math so `SWAP 1`
incorrectly swaps TOS with second-from-top; treat the operand as 1-based by
changing the index arithmetic: compute j so that SWAP(1) yields j == i (no-op),
e.g. use j = len - index.get(arg) as usize instead of len - 1 - index.get(arg)
as usize, and keep i = len - 1; ensure you reference RealInstruction::Swap and
the index.get(arg) call when updating the code.

ReallInstruction::ToBool => {
RealInstruction::ToBool => {
let a = self.stack.pop().ok_or(JitCompileError::BadBytecode)?;
let value = self.boolean_val(a)?;
self.stack.push(JitValue::Bool(value));
Ok(())
}
ReallInstruction::UnaryNot => {
RealInstruction::UnaryNot => {
let boolean = match self.stack.pop().ok_or(JitCompileError::BadBytecode)? {
JitValue::Bool(val) => val,
_ => return Err(JitCompileError::BadBytecode),
Expand All @@ -667,7 +667,7 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
self.stack.push(JitValue::Bool(not_boolean));
Ok(())
}
ReallInstruction::UnaryNegative => {
RealInstruction::UnaryNegative => {
match self.stack.pop().ok_or(JitCompileError::BadBytecode)? {
JitValue::Int(val) => {
// Compile minus as 0 - val.
Expand All @@ -679,7 +679,7 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
_ => Err(JitCompileError::NotSupported),
}
}
ReallInstruction::UnpackSequence { size } => {
RealInstruction::UnpackSequence { size } => {
let val = self.stack.pop().ok_or(JitCompileError::BadBytecode)?;

let elements = match val {
Expand Down