Skip to content
Open
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
documentation
  • Loading branch information
LuigiTheJokesterAlvarez committed Jun 29, 2026
commit f32149d880c2c9b02d5fcd65dbff20924c77b5ea
70 changes: 42 additions & 28 deletions crates/jit/src/instructions.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// instructions.rs
// spell-checker: disable
use super::{JitCompileError, JitSig, JitType};
use alloc::collections::BTreeSet;
Expand Down Expand Up @@ -31,14 +30,8 @@ enum ElementShape {
struct TupleShape(Vec<ElementShape>);
#[derive(Clone)]
enum Local {
Scalar {
var: Variable,
ty: JitType,
},
Object {
var: Variable,
kind: Rc<ObjectKind>,
}
Scalar { var: Variable, ty: JitType },
Object { var: Variable, kind: Rc<ObjectKind> },
}
#[derive(Debug)]
enum JitValue {
Expand Down Expand Up @@ -126,11 +119,13 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
compiler
}

/// Pops Multiple Values off the Stack, returning a Vector
fn pop_multiple(&mut self, count: usize) -> Vec<JitValue> {
let stack_len = self.stack.len();
self.stack.drain(stack_len - count..).collect()
}

/// Generates a local out of a jitvalue
fn local_from_value(
builder: &mut FunctionBuilder<'_>,
value: JitValue,
Expand All @@ -152,22 +147,30 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
}
}

fn local_to_value(builder: &mut FunctionBuilder<'_>, local: &Local) -> Result<JitValue, JitCompileError> {
/// Generates a JitValue out of a Local
fn local_to_value(
builder: &mut FunctionBuilder<'_>,
local: &Local,
) -> Result<JitValue, JitCompileError> {
match local {
Local::Scalar { var, ty } => Ok(JitValue::from_type_and_value(
ty.clone(),
builder.use_var(*var),
)),
Local::Object { var, kind } => Ok(JitValue::Object(builder.use_var(*var), kind.clone())),
Local::Object { var, kind } => {
Ok(JitValue::Object(builder.use_var(*var), kind.clone()))
}
}
}
/// Stores a Local into the variables array
fn store_variable(&mut self, idx: oparg::VarNum, val: JitValue) -> Result<(), JitCompileError> {
#[expect(clippy::mut_mut, reason = "This seems like a false positive")]
let builder = &mut self.builder;
let local = Self::local_from_value(builder, val)?;
self.variables[idx] = Some(local);
Ok(())
}
/// Generates a boolean value out of a JitValue, Nulls FuncRefs and Objects aren't supported
fn boolean_val(&mut self, val: JitValue) -> Result<Value, JitCompileError> {
match val {
JitValue::Float(val) => {
Expand All @@ -183,7 +186,7 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
JitValue::Bool(val) => Ok(val),
JitValue::None => Ok(self.builder.ins().iconst(types::I8, 0)),
JitValue::Null | JitValue::FuncRef(_) | JitValue::Object(_, _) => {
Err(JitCompileError::NotSupported)
Err(JitCompileError::NotSupported)
}
}
}
Expand Down Expand Up @@ -376,7 +379,10 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
};
Ok(value)
}
fn build_heap_tuple(&mut self, elements: Vec<JitValue>) -> Result<(Value, Rc<TupleShape>), JitCompileError> {
fn build_heap_tuple(
&mut self,
elements: Vec<JitValue>,
) -> Result<(Value, Rc<TupleShape>), JitCompileError> {
let len_val = self.builder.ins().iconst(types::I64, elements.len() as i64);
let call = self.builder.ins().call(self.alloc_func, &[len_val]);
let ptr = self.builder.inst_results(call)[0];
Expand Down Expand Up @@ -404,11 +410,17 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
let offset = 8 + 8 * i as i32;
let value = match element_shape {
ElementShape::Scalar(ty) => {
let val = self.builder.ins().load(ty.to_cranelift(), MemFlags::new(), ptr, offset);
let val =
self.builder
.ins()
.load(ty.to_cranelift(), MemFlags::new(), ptr, offset);
JitValue::from_type_and_value(ty.clone(), val)
}
ElementShape::Object(kind) => {
let val = self.builder.ins().load(types::I64, MemFlags::new(), ptr, offset);
let val = self
.builder
.ins()
.load(types::I64, MemFlags::new(), ptr, offset);
JitValue::Object(val, kind.clone())
}
};
Expand All @@ -418,9 +430,9 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
}
fn return_value(&mut self, val: JitValue) -> Result<(), JitCompileError> {
let (cr_val, ret_ty) = match val {
JitValue::Int(v) => (v, JitType::Int),
JitValue::Float(v) => (v, JitType::Float),
JitValue::Bool(v) => (v, JitType::Bool),
JitValue::Int(v) => (v, JitType::Int),
JitValue::Float(v) => (v, JitType::Float),
JitValue::Bool(v) => (v, JitType::Bool),
JitValue::Object(p, _) => (p, JitType::Object),
//JitValue::None => (self.none_ptr(), JitType::Object),
_ => return Err(JitCompileError::NotSupported),
Expand All @@ -429,7 +441,9 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
// single abi type
if self.sig.ret.is_none() {
self.sig.ret = Some(ret_ty.clone());
self.builder.func.signature
self.builder
.func
.signature
.returns
.push(AbiParam::new(ret_ty.to_cranelift()));
}
Expand Down Expand Up @@ -611,7 +625,8 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
Instruction::BuildTuple { count } => {
let elements = self.pop_multiple(count.get(arg) as usize);
let (ptr, shape) = self.build_heap_tuple(elements)?;
self.stack.push(JitValue::Object(ptr, Rc::new(ObjectKind::Tuple(shape))));
self.stack
.push(JitValue::Object(ptr, Rc::new(ObjectKind::Tuple(shape))));
Ok(())
}
Instruction::Call { argc } => {
Expand All @@ -622,7 +637,7 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
let arg = self.stack.pop().ok_or(JitCompileError::BadBytecode)?;
args.push(arg.into_value().unwrap());
}

// Pop self_or_null (should be Null for JIT-compiled recursive calls)
let self_or_null = self.stack.pop().ok_or(JitCompileError::BadBytecode)?;
if !matches!(self_or_null, JitValue::Null) {
Expand Down Expand Up @@ -1369,7 +1384,7 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
even_block,
&[inf_f.into()],
);

self.builder.switch_to_block(odd_block);
let phi_neg_inf = self.builder.block_params(odd_block)[0];
self.builder.ins().jump(merge_block, &[phi_neg_inf.into()]);
Expand All @@ -1388,7 +1403,7 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
self.builder
.ins()
.brif(cmp_lt, a_neg_block, &[], a_pos_block, &[]);

// ----- Case: a > 0: Compute a^b = exp(b * ln(a)) using double–double arithmetic.
self.builder.switch_to_block(a_pos_block);
let ln_a_dd = self.dd_ln(a);
Expand Down Expand Up @@ -1426,7 +1441,7 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
let remainder = self.builder.ins().band(b_i64, one_i);
let zero_i = self.builder.ins().iconst(i64_ty, 0);
let is_odd = self.builder.ins().icmp(IntCC::NotEqual, remainder, zero_i);

let odd_block = self.builder.create_block();
let even_block = self.builder.create_block();
// Append block parameters for both branches:
Expand Down Expand Up @@ -1542,7 +1557,7 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
let is_odd = self.builder.ins().icmp_imm(IntCC::Equal, is_odd, 1);
let mul_result = self.builder.ins().imul(result_phi, base_phi);
let new_result = self.builder.ins().select(is_odd, mul_result, result_phi);

// Square the base and divide exponent by 2
let squared_base = self.builder.ins().imul(base_phi, base_phi);
let new_exp = self.builder.ins().sshr_imm(exp_phi, 1);
Expand All @@ -1561,8 +1576,7 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
self.builder.seal_block(loop_block);
self.builder.seal_block(continue_block);
self.builder.seal_block(exit_block);

res
}

}
}
48 changes: 41 additions & 7 deletions crates/jit/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
// lib.rs
mod instructions;

extern crate alloc;

use alloc::alloc::{alloc, handle_alloc_error, Layout};
extern crate alloc
use alloc::alloc::{Layout, alloc, handle_alloc_error};
use alloc::fmt;
use core::mem::ManuallyDrop;
use cranelift::prelude::*;
Expand Down Expand Up @@ -38,6 +36,7 @@ pub enum JitArgumentError {
WrongNumberOfArguments,
}

/// Allocates a tuple in the heap and returns it's pointer, Unsafe function
extern "C" fn jit_alloc_tuple(len: i64) -> i64 {
let layout = Layout::array::<i64>(len as usize + 1).unwrap();
let ptr = unsafe { alloc(layout) };
Expand Down Expand Up @@ -249,7 +248,7 @@ pub enum AbiValue {
Float(f64),
Int(i64),
Bool(bool),
Object(usize)
Object(usize),
}

impl AbiValue {
Expand All @@ -258,7 +257,7 @@ impl AbiValue {
Self::Int(i) => libffi::middle::Arg::new(i),
Self::Float(f) => libffi::middle::Arg::new(f),
Self::Bool(b) => libffi::middle::Arg::new(b),
Self::Object(p) => libffi::middle::Arg::new(p)
Self::Object(p) => libffi::middle::Arg::new(p),
}
}
}
Expand Down Expand Up @@ -357,7 +356,7 @@ impl UnTypedAbiValue {
JitType::Int => AbiValue::Int(self.int),
JitType::Float => AbiValue::Float(self.float),
JitType::Bool => AbiValue::Bool(self.boolean != 0),
JitType::Object => AbiValue::Object(self.object)
JitType::Object => AbiValue::Object(self.object),
}
}
}
Expand Down Expand Up @@ -424,6 +423,41 @@ pub struct Args<'a> {
code: &'a CompiledCode,
}

impl Args<'_> {
#[must_use]
pub fn invoke(&self) -> Option<AbiValue> {
let cif_args: Vec<_> = self.values.iter().map(AbiValue::to_libffi_arg).collect();
unsafe { self.code.invoke_raw(&cif_args) }
}
}
es: self.values.into_iter().map(|v| v.unwrap()).collect(),
code: self.code,
})
}
}

pub struct Args<'a> {
values: Vec<AbiValue>,
code: &'a CompiledCode,
}

impl Args<'_> {
#[must_use]
pub fn invoke(&self) -> Option<AbiValue> {
let cif_args: Vec<_> = self.values.iter().map(AbiValue::to_libffi_arg).collect();
unsafe { self.code.invoke_raw(&cif_args) }
}
}: self.values.into_iter().map(|v| v.unwrap()).collect(),
code: self.code,
})
}
}

pub struct Args<'a> {
values: Vec<AbiValue>,
code: &'a CompiledCode,
}

impl Args<'_> {
#[must_use]
pub fn invoke(&self) -> Option<AbiValue> {
Expand Down
Loading