feat: stack var (WIP)
This commit is contained in:
@@ -19,22 +19,22 @@ pub trait JITCompile<Ctx: JITContext> {
|
||||
///
|
||||
/// # Arguments
|
||||
/// * `ctx` - The compilation context
|
||||
/// * `engine` - The evaluation context value
|
||||
/// * `rt_ctx` - The evaluation context value
|
||||
/// * `env` - The environment value
|
||||
///
|
||||
/// # Returns
|
||||
/// A stack slot containing the compiled result
|
||||
fn compile(&self, ctx: &mut Context<Ctx>, engine: ir::Value, env: ir::Value) -> StackSlot;
|
||||
fn compile(&self, ctx: &mut Context<Ctx>, rt_ctx: ir::Value) -> StackSlot;
|
||||
}
|
||||
|
||||
impl<Ctx: JITContext> JITCompile<Ctx> for ExprId {
|
||||
fn compile(&self, ctx: &mut Context<Ctx>, engine: ir::Value, env: ir::Value) -> StackSlot {
|
||||
fn compile(&self, ctx: &mut Context<Ctx>, rt_ctx: ir::Value) -> StackSlot {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Ctx: JITContext> JITCompile<Ctx> for Lir {
|
||||
fn compile(&self, ctx: &mut Context<Ctx>, engine: ir::Value, env: ir::Value) -> StackSlot {
|
||||
fn compile(&self, ctx: &mut Context<Ctx>, rt_ctx: ir::Value) -> StackSlot {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
@@ -43,10 +43,10 @@ impl<Ctx: JITContext> JITCompile<Ctx> for AttrSet {
|
||||
/// Compiles an attribute set to Cranelift IR.
|
||||
///
|
||||
/// This creates a new attribute set and compiles all static attributes into it.
|
||||
fn compile(&self, ctx: &mut Context<Ctx>, engine: ir::Value, env: ir::Value) -> StackSlot {
|
||||
fn compile(&self, ctx: &mut Context<Ctx>, rt_ctx: ir::Value) -> StackSlot {
|
||||
let attrs = ctx.create_attrs();
|
||||
for (k, v) in self.stcs.iter() {
|
||||
let v = v.compile(ctx, engine, env);
|
||||
let v = v.compile(ctx, rt_ctx);
|
||||
ctx.push_attr(attrs, k, v);
|
||||
}
|
||||
ctx.finalize_attrs(attrs)
|
||||
@@ -57,10 +57,10 @@ impl<Ctx: JITContext> JITCompile<Ctx> for List {
|
||||
/// Compiles a list to Cranelift IR.
|
||||
///
|
||||
/// This creates a new list by compiling all items and storing them in an array.
|
||||
fn compile(&self, ctx: &mut Context<Ctx>, engine: ir::Value, env: ir::Value) -> StackSlot {
|
||||
fn compile(&self, ctx: &mut Context<Ctx>, rt_ctx: ir::Value) -> StackSlot {
|
||||
let array = ctx.alloc_array(self.items.len());
|
||||
for (i, item) in self.items.iter().enumerate() {
|
||||
let item = item.compile(ctx, engine, env);
|
||||
let item = item.compile(ctx, rt_ctx);
|
||||
let tag = ctx.builder.ins().stack_load(types::I64, item, 0);
|
||||
let val0 = ctx.builder.ins().stack_load(types::I64, item, 8);
|
||||
let val1 = ctx.builder.ins().stack_load(types::I64, item, 16);
|
||||
@@ -83,7 +83,7 @@ impl<Ctx: JITContext> JITCompile<Ctx> for List {
|
||||
}
|
||||
|
||||
impl<Ctx: JITContext> JITCompile<Ctx> for HasAttr {
|
||||
fn compile(&self, ctx: &mut Context<Ctx>, engine: ir::Value, env: ir::Value) -> StackSlot {
|
||||
fn compile(&self, ctx: &mut Context<Ctx>, rt_ctx: ir::Value) -> StackSlot {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
@@ -94,10 +94,10 @@ impl<Ctx: JITContext> JITCompile<Ctx> for BinOp {
|
||||
/// This implementation handles various binary operations like addition, subtraction,
|
||||
/// division, logical AND/OR, and equality checks. It generates code that checks
|
||||
/// the types of operands and performs the appropriate operation.
|
||||
fn compile(&self, ctx: &mut Context<Ctx>, engine: ir::Value, env: ir::Value) -> StackSlot {
|
||||
fn compile(&self, ctx: &mut Context<Ctx>, rt_ctx: ir::Value) -> StackSlot {
|
||||
use BinOpKind::*;
|
||||
let lhs = self.lhs.compile(ctx, engine, env);
|
||||
let rhs = self.rhs.compile(ctx, engine, env);
|
||||
let lhs = self.lhs.compile(ctx, rt_ctx);
|
||||
let rhs = self.rhs.compile(ctx, rt_ctx);
|
||||
let lhs_tag = ctx.get_tag(lhs);
|
||||
let rhs_tag = ctx.get_tag(rhs);
|
||||
let eq = ctx.builder.ins().icmp(IntCC::Equal, lhs_tag, rhs_tag);
|
||||
@@ -349,7 +349,7 @@ impl<Ctx: JITContext> JITCompile<Ctx> for BinOp {
|
||||
}
|
||||
|
||||
impl<Ctx: JITContext> JITCompile<Ctx> for UnOp {
|
||||
fn compile(&self, ctx: &mut Context<Ctx>, engine: ir::Value, env: ir::Value) -> StackSlot {
|
||||
fn compile(&self, ctx: &mut Context<Ctx>, rt_ctx: ir::Value) -> StackSlot {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
@@ -358,11 +358,11 @@ impl<Ctx: JITContext> JITCompile<Ctx> for Attr {
|
||||
/// Compiles an attribute key to Cranelift IR.
|
||||
///
|
||||
/// An attribute can be either a static string or a dynamic expression.
|
||||
fn compile(&self, ctx: &mut Context<Ctx>, engine: ir::Value, env: ir::Value) -> StackSlot {
|
||||
fn compile(&self, ctx: &mut Context<Ctx>, rt_ctx: ir::Value) -> StackSlot {
|
||||
use Attr::*;
|
||||
match self {
|
||||
Str(string) => ctx.create_string(string),
|
||||
Dynamic(ir) => ir.compile(ctx, engine, env),
|
||||
Dynamic(ir) => ir.compile(ctx, rt_ctx),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -372,11 +372,11 @@ impl<Ctx: JITContext> JITCompile<Ctx> for Select {
|
||||
///
|
||||
/// This compiles the expression to select from, builds the attribute path,
|
||||
/// and calls the select helper function.
|
||||
fn compile(&self, ctx: &mut Context<Ctx>, engine: ir::Value, env: ir::Value) -> StackSlot {
|
||||
let val = self.expr.compile(ctx, engine, env);
|
||||
fn compile(&self, ctx: &mut Context<Ctx>, rt_ctx: ir::Value) -> StackSlot {
|
||||
let val = self.expr.compile(ctx, rt_ctx);
|
||||
let attrpath = ctx.alloc_array(self.attrpath.len());
|
||||
for (i, attr) in self.attrpath.iter().enumerate() {
|
||||
let arg = attr.compile(ctx, engine, env);
|
||||
let arg = attr.compile(ctx, rt_ctx);
|
||||
let tag = ctx.builder.ins().stack_load(types::I64, arg, 0);
|
||||
let val0 = ctx.builder.ins().stack_load(types::I64, arg, 8);
|
||||
let val1 = ctx.builder.ins().stack_load(types::I64, arg, 16);
|
||||
@@ -394,7 +394,7 @@ impl<Ctx: JITContext> JITCompile<Ctx> for Select {
|
||||
.ins()
|
||||
.store(MemFlags::new(), val2, attrpath, i as i32 * 32 + 24);
|
||||
}
|
||||
ctx.select(val, attrpath, self.attrpath.len(), engine, env);
|
||||
ctx.select(val, attrpath, self.attrpath.len(), rt_ctx);
|
||||
val
|
||||
}
|
||||
}
|
||||
@@ -404,8 +404,8 @@ impl<Ctx: JITContext> JITCompile<Ctx> for If {
|
||||
///
|
||||
/// This generates code that evaluates the condition, checks that it's a boolean,
|
||||
/// and then jumps to the appropriate branch (true or false).
|
||||
fn compile(&self, ctx: &mut Context<Ctx>, engine: ir::Value, env: ir::Value) -> StackSlot {
|
||||
let cond = self.cond.compile(ctx, engine, env);
|
||||
fn compile(&self, ctx: &mut Context<Ctx>, rt_ctx: ir::Value) -> StackSlot {
|
||||
let cond = self.cond.compile(ctx, rt_ctx);
|
||||
let cond_type = ctx.builder.ins().stack_load(types::I64, cond, 0);
|
||||
let cond_value = ctx.builder.ins().stack_load(types::I64, cond, 8);
|
||||
|
||||
@@ -430,7 +430,7 @@ impl<Ctx: JITContext> JITCompile<Ctx> for If {
|
||||
.brif(cond_value, true_block, [], false_block, []);
|
||||
|
||||
ctx.builder.switch_to_block(true_block);
|
||||
let ret = self.consq.compile(ctx, engine, env);
|
||||
let ret = self.consq.compile(ctx, rt_ctx);
|
||||
let tag = ctx.builder.ins().stack_load(types::I64, ret, 0);
|
||||
let val0 = ctx.builder.ins().stack_load(types::I64, ret, 8);
|
||||
let val1 = ctx.builder.ins().stack_load(types::I64, ret, 16);
|
||||
@@ -442,7 +442,7 @@ impl<Ctx: JITContext> JITCompile<Ctx> for If {
|
||||
ctx.builder.ins().jump(exit_block, []);
|
||||
|
||||
ctx.builder.switch_to_block(false_block);
|
||||
let ret = self.alter.compile(ctx, engine, env);
|
||||
let ret = self.alter.compile(ctx, rt_ctx);
|
||||
let tag = ctx.builder.ins().stack_load(types::I64, ret, 0);
|
||||
let val0 = ctx.builder.ins().stack_load(types::I64, ret, 8);
|
||||
let val1 = ctx.builder.ins().stack_load(types::I64, ret, 16);
|
||||
@@ -463,32 +463,10 @@ impl<Ctx: JITContext> JITCompile<Ctx> for If {
|
||||
|
||||
impl<Ctx: JITContext> JITCompile<Ctx> for Call {
|
||||
/// Compiles a function call to Cranelift IR.
|
||||
///
|
||||
/// This compiles the function expression and all arguments, builds an argument array,
|
||||
/// and calls the call helper function.
|
||||
fn compile(&self, ctx: &mut Context<Ctx>, engine: ir::Value, env: ir::Value) -> StackSlot {
|
||||
let func = self.func.compile(ctx, engine, env);
|
||||
let args = ctx.alloc_array(self.args.len());
|
||||
for (i, arg) in self.args.iter().enumerate() {
|
||||
let arg = arg.compile(ctx, engine, env);
|
||||
let tag = ctx.builder.ins().stack_load(types::I64, arg, 0);
|
||||
let val0 = ctx.builder.ins().stack_load(types::I64, arg, 8);
|
||||
let val1 = ctx.builder.ins().stack_load(types::I64, arg, 16);
|
||||
let val2 = ctx.builder.ins().stack_load(types::I64, arg, 24);
|
||||
ctx.builder
|
||||
.ins()
|
||||
.store(MemFlags::new(), tag, args, i as i32 * 32);
|
||||
ctx.builder
|
||||
.ins()
|
||||
.store(MemFlags::new(), val0, args, i as i32 * 32 + 8);
|
||||
ctx.builder
|
||||
.ins()
|
||||
.store(MemFlags::new(), val1, args, i as i32 * 32 + 16);
|
||||
ctx.builder
|
||||
.ins()
|
||||
.store(MemFlags::new(), val2, args, i as i32 * 32 + 24);
|
||||
}
|
||||
ctx.call(func, args, self.args.len(), engine, env);
|
||||
fn compile(&self, ctx: &mut Context<Ctx>, rt_ctx: ir::Value) -> StackSlot {
|
||||
let func = self.func.compile(ctx, rt_ctx);
|
||||
let arg = self.arg.compile(ctx, rt_ctx);
|
||||
ctx.call(func, arg, rt_ctx);
|
||||
func
|
||||
}
|
||||
}
|
||||
@@ -498,24 +476,24 @@ impl<Ctx: JITContext> JITCompile<Ctx> for With {
|
||||
///
|
||||
/// This enters a new `with` scope with the compiled namespace, compiles the body expression,
|
||||
/// and then exits the `with` scope.
|
||||
fn compile(&self, ctx: &mut Context<Ctx>, engine: ir::Value, env: ir::Value) -> StackSlot {
|
||||
let namespace = self.namespace.compile(ctx, engine, env);
|
||||
ctx.enter_with(env, namespace);
|
||||
let ret = self.expr.compile(ctx, engine, env);
|
||||
ctx.exit_with(env);
|
||||
fn compile(&self, ctx: &mut Context<Ctx>, rt_ctx: ir::Value) -> StackSlot {
|
||||
let namespace = self.namespace.compile(ctx, rt_ctx);
|
||||
ctx.enter_with(rt_ctx, namespace);
|
||||
let ret = self.expr.compile(ctx, rt_ctx);
|
||||
ctx.exit_with(rt_ctx);
|
||||
ctx.free_slot(namespace);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
impl<Ctx: JITContext> JITCompile<Ctx> for Assert {
|
||||
fn compile(&self, ctx: &mut Context<Ctx>, engine: ir::Value, env: ir::Value) -> StackSlot {
|
||||
fn compile(&self, ctx: &mut Context<Ctx>, rt_ctx: ir::Value) -> StackSlot {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
impl<Ctx: JITContext> JITCompile<Ctx> for ConcatStrings {
|
||||
fn compile(&self, ctx: &mut Context<Ctx>, engine: ir::Value, env: ir::Value) -> StackSlot {
|
||||
fn compile(&self, ctx: &mut Context<Ctx>, rt_ctx: ir::Value) -> StackSlot {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
@@ -525,7 +503,7 @@ impl<Ctx: JITContext> JITCompile<Ctx> for Const {
|
||||
///
|
||||
/// This handles boolean, integer, float, and null constants by storing
|
||||
/// their values and type tags in a stack slot.
|
||||
fn compile(&self, ctx: &mut Context<Ctx>, engine: ir::Value, env: ir::Value) -> StackSlot {
|
||||
fn compile(&self, ctx: &mut Context<Ctx>, rt_ctx: ir::Value) -> StackSlot {
|
||||
use nixjit_value::Const::*;
|
||||
let slot = ctx.alloca();
|
||||
match self.val {
|
||||
@@ -560,7 +538,7 @@ impl<Ctx: JITContext> JITCompile<Ctx> for Str {
|
||||
/// Compiles a string literal to Cranelift IR.
|
||||
///
|
||||
/// This creates a string value from the string literal.
|
||||
fn compile(&self, ctx: &mut Context<Ctx>, engine: ir::Value, env: ir::Value) -> StackSlot {
|
||||
fn compile(&self, ctx: &mut Context<Ctx>, rt_ctx: ir::Value) -> StackSlot {
|
||||
ctx.create_string(&self.val)
|
||||
}
|
||||
}
|
||||
@@ -569,13 +547,13 @@ impl<Ctx: JITContext> JITCompile<Ctx> for Var {
|
||||
/// Compiles a variable lookup to Cranelift IR.
|
||||
///
|
||||
/// This looks up a variable by its symbol in the current environment.
|
||||
fn compile(&self, ctx: &mut Context<Ctx>, engine: ir::Value, env: ir::Value) -> StackSlot {
|
||||
ctx.lookup(env, &self.sym)
|
||||
fn compile(&self, ctx: &mut Context<Ctx>, rt_ctx: ir::Value) -> StackSlot {
|
||||
ctx.lookup(rt_ctx, &self.sym)
|
||||
}
|
||||
}
|
||||
|
||||
impl<Ctx: JITContext> JITCompile<Ctx> for Path {
|
||||
fn compile(&self, ctx: &mut Context<Ctx>, engine: ir::Value, env: ir::Value) -> StackSlot {
|
||||
fn compile(&self, ctx: &mut Context<Ctx>, rt_ctx: ir::Value) -> StackSlot {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,24 +12,18 @@ use std::ptr::NonNull;
|
||||
use hashbrown::HashMap;
|
||||
|
||||
use nixjit_eval::{AttrSet, EvalContext, List, Value};
|
||||
use nixjit_ir::ArgIdx;
|
||||
use nixjit_ir::ExprId;
|
||||
use nixjit_ir::StackIdx;
|
||||
|
||||
use super::JITContext;
|
||||
|
||||
/// Helper function to call a function with arguments.
|
||||
///
|
||||
/// This function is called from JIT-compiled code to perform function calls.
|
||||
/// It takes a function value and an array of arguments, and executes the call.
|
||||
pub extern "C" fn helper_call<Ctx: JITContext>(
|
||||
func: &mut Value,
|
||||
args_ptr: *mut Value,
|
||||
args_len: usize,
|
||||
arg: NonNull<Value>,
|
||||
ctx: &mut Ctx,
|
||||
) {
|
||||
// TODO: Error Handling
|
||||
let args = core::ptr::slice_from_raw_parts_mut(args_ptr, args_len);
|
||||
let args = unsafe { Box::from_raw(args) };
|
||||
func.call(args.into_iter().map(Ok), ctx).unwrap();
|
||||
func.call(unsafe { arg.read() }, ctx).unwrap();
|
||||
}
|
||||
|
||||
/// Helper function to look up a value in the evaluation stack.
|
||||
@@ -37,21 +31,18 @@ pub extern "C" fn helper_call<Ctx: JITContext>(
|
||||
/// This function is called from JIT-compiled code to access values in the evaluation stack.
|
||||
pub extern "C" fn helper_lookup_stack<Ctx: JITContext + EvalContext>(
|
||||
ctx: &Ctx,
|
||||
offset: usize,
|
||||
idx: StackIdx,
|
||||
ret: &mut MaybeUninit<Value>,
|
||||
) {
|
||||
ret.write(ctx.lookup_stack(offset).clone());
|
||||
ret.write(ctx.lookup_stack(idx).clone());
|
||||
}
|
||||
|
||||
/// Helper function to look up a function argument.
|
||||
///
|
||||
/// This function is called from JIT-compiled code to access function arguments.
|
||||
pub extern "C" fn helper_lookup_arg<Ctx: EvalContext>(
|
||||
ctx: &Ctx,
|
||||
idx: ArgIdx,
|
||||
ret: &mut MaybeUninit<Value>,
|
||||
) {
|
||||
ret.write(ctx.lookup_arg(idx).clone());
|
||||
pub extern "C" fn helper_lookup_arg<Ctx: EvalContext>(ctx: &mut Ctx, ret: &mut MaybeUninit<Value>) {
|
||||
todo!()
|
||||
// ret.write(ctx.lookup_arg().unwrap().clone());
|
||||
}
|
||||
|
||||
/// Helper function to look up a variable by name.
|
||||
@@ -84,14 +75,14 @@ pub extern "C" fn helper_select<Ctx: JITContext>(
|
||||
val: &mut Value,
|
||||
path_ptr: *mut Value,
|
||||
path_len: usize,
|
||||
ctx: &mut Ctx,
|
||||
) {
|
||||
let path = core::ptr::slice_from_raw_parts_mut(path_ptr, path_len);
|
||||
let path = unsafe { Box::from_raw(path) };
|
||||
val.select(path.into_iter().map(|mut val| {
|
||||
val.coerce_to_string().unwrap();
|
||||
Ok(val.unwrap_string())
|
||||
}))
|
||||
.unwrap();
|
||||
for attr in path {
|
||||
val.select(&attr.force_string_no_ctx().unwrap(), ctx)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper function to perform attribute selection with a default value.
|
||||
@@ -102,25 +93,22 @@ pub extern "C" fn helper_select_with_default<Ctx: JITContext>(
|
||||
val: &mut Value,
|
||||
path_ptr: *mut Value,
|
||||
path_len: usize,
|
||||
default: NonNull<Value>,
|
||||
default: ExprId,
|
||||
ctx: &mut Ctx,
|
||||
) {
|
||||
let path = core::ptr::slice_from_raw_parts_mut(path_ptr, path_len);
|
||||
let path = unsafe { Box::from_raw(path) };
|
||||
val.select_with_default(
|
||||
path.into_iter().map(|mut val| {
|
||||
val.coerce_to_string().unwrap();
|
||||
Ok(val.unwrap_string())
|
||||
}),
|
||||
unsafe { default.read() },
|
||||
)
|
||||
.unwrap();
|
||||
for attr in path {
|
||||
val.select_or(&attr.force_string_no_ctx().unwrap(), default, ctx)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
/// Helper function to check equality between two values.
|
||||
///
|
||||
/// This function is called from JIT-compiled code to perform equality comparisons.
|
||||
pub extern "C" fn helper_eq<Ctx: JITContext>(lhs: &mut Value, rhs: &Value) {
|
||||
lhs.eq(unsafe { core::ptr::read(rhs) });
|
||||
pub extern "C" fn helper_eq<Ctx: JITContext>(lhs: &mut Value, rhs: NonNull<Value>) {
|
||||
lhs.eq(unsafe { rhs.read() });
|
||||
}
|
||||
|
||||
/// Helper function to create a string value.
|
||||
|
||||
@@ -51,6 +51,7 @@ type F<Ctx> = unsafe extern "C" fn(*const Ctx, *mut Value);
|
||||
/// This struct holds a function pointer to the compiled code and
|
||||
/// a set of strings that were used during compilation, which need
|
||||
/// to be kept alive for the function to work correctly.
|
||||
#[derive(Debug)]
|
||||
pub struct JITFunc<Ctx: JITContext> {
|
||||
func: F<Ctx>,
|
||||
strings: HashSet<String>,
|
||||
@@ -209,7 +210,7 @@ impl<'comp, 'ctx, Ctx: JITContext> Context<'comp, 'ctx, Ctx> {
|
||||
slot
|
||||
}
|
||||
|
||||
fn enter_with(&mut self, env: ir::Value, namespace: StackSlot) {
|
||||
fn enter_with(&mut self, rt_ctx: ir::Value, namespace: StackSlot) {
|
||||
let ptr = self
|
||||
.builder
|
||||
.ins()
|
||||
@@ -218,15 +219,15 @@ impl<'comp, 'ctx, Ctx: JITContext> Context<'comp, 'ctx, Ctx> {
|
||||
.compiler
|
||||
.module
|
||||
.declare_func_in_func(self.compiler.enter_with, self.builder.func);
|
||||
self.builder.ins().call(enter_with, &[env, ptr]);
|
||||
self.builder.ins().call(enter_with, &[rt_ctx, ptr]);
|
||||
}
|
||||
|
||||
fn exit_with(&mut self, env: ir::Value) {
|
||||
fn exit_with(&mut self, rt_ctx: ir::Value) {
|
||||
let exit_with = self
|
||||
.compiler
|
||||
.module
|
||||
.declare_func_in_func(self.compiler.exit_with, self.builder.func);
|
||||
self.builder.ins().call(exit_with, &[env]);
|
||||
self.builder.ins().call(exit_with, &[rt_ctx]);
|
||||
}
|
||||
|
||||
fn dbg(&mut self, slot: StackSlot) {
|
||||
@@ -241,18 +242,7 @@ impl<'comp, 'ctx, Ctx: JITContext> Context<'comp, 'ctx, Ctx> {
|
||||
self.builder.ins().call(dbg, &[ptr]);
|
||||
}
|
||||
|
||||
fn call(
|
||||
&mut self,
|
||||
func: StackSlot,
|
||||
args_ptr: ir::Value,
|
||||
args_len: usize,
|
||||
engine: ir::Value,
|
||||
env: ir::Value,
|
||||
) {
|
||||
let args_len = self
|
||||
.builder
|
||||
.ins()
|
||||
.iconst(self.compiler.ptr_type, args_len as i64);
|
||||
fn call(&mut self, func: StackSlot, arg: StackSlot, call_ctx: ir::Value) {
|
||||
let call = self
|
||||
.compiler
|
||||
.module
|
||||
@@ -261,12 +251,14 @@ impl<'comp, 'ctx, Ctx: JITContext> Context<'comp, 'ctx, Ctx> {
|
||||
.builder
|
||||
.ins()
|
||||
.stack_addr(self.compiler.ptr_type, func, 0);
|
||||
self.builder
|
||||
let arg = self
|
||||
.builder
|
||||
.ins()
|
||||
.call(call, &[func, args_ptr, args_len, engine, env]);
|
||||
.stack_addr(self.compiler.ptr_type, arg, 0);
|
||||
self.builder.ins().call(call, &[func, arg, call_ctx]);
|
||||
}
|
||||
|
||||
fn lookup(&mut self, env: ir::Value, sym: &str) -> StackSlot {
|
||||
fn lookup(&mut self, rt_ctx: ir::Value, sym: &str) -> StackSlot {
|
||||
let sym = self.strings.get_or_insert_with(sym, |_| sym.to_owned());
|
||||
let ptr = self
|
||||
.builder
|
||||
@@ -285,11 +277,11 @@ impl<'comp, 'ctx, Ctx: JITContext> Context<'comp, 'ctx, Ctx> {
|
||||
.builder
|
||||
.ins()
|
||||
.stack_addr(self.compiler.ptr_type, slot, 0);
|
||||
self.builder.ins().call(lookup, &[env, ptr, len, ret]);
|
||||
self.builder.ins().call(lookup, &[rt_ctx, ptr, len, ret]);
|
||||
slot
|
||||
}
|
||||
|
||||
fn lookup_stack(&mut self, env: ir::Value, idx: usize) -> StackSlot {
|
||||
fn lookup_stack(&mut self, ctx: ir::Value, idx: usize) -> StackSlot {
|
||||
let slot = self.alloca();
|
||||
let lookup_stack = self
|
||||
.compiler
|
||||
@@ -303,11 +295,11 @@ impl<'comp, 'ctx, Ctx: JITContext> Context<'comp, 'ctx, Ctx> {
|
||||
.builder
|
||||
.ins()
|
||||
.stack_addr(self.compiler.ptr_type, slot, 0);
|
||||
self.builder.ins().call(lookup_stack, &[env, idx, ptr]);
|
||||
self.builder.ins().call(lookup_stack, &[ctx, idx, ptr]);
|
||||
slot
|
||||
}
|
||||
|
||||
fn lookup_arg(&mut self, env: ir::Value, idx: usize) -> StackSlot {
|
||||
fn lookup_arg(&mut self, ctx: ir::Value, idx: usize) -> StackSlot {
|
||||
let slot = self.alloca();
|
||||
let lookup_arg = self
|
||||
.compiler
|
||||
@@ -321,18 +313,11 @@ impl<'comp, 'ctx, Ctx: JITContext> Context<'comp, 'ctx, Ctx> {
|
||||
.builder
|
||||
.ins()
|
||||
.stack_addr(self.compiler.ptr_type, slot, 0);
|
||||
self.builder.ins().call(lookup_arg, &[env, idx, ptr]);
|
||||
self.builder.ins().call(lookup_arg, &[ctx, idx, ptr]);
|
||||
slot
|
||||
}
|
||||
|
||||
fn select(
|
||||
&mut self,
|
||||
slot: StackSlot,
|
||||
path_ptr: ir::Value,
|
||||
path_len: usize,
|
||||
engine: ir::Value,
|
||||
env: ir::Value,
|
||||
) {
|
||||
fn select(&mut self, slot: StackSlot, path_ptr: ir::Value, path_len: usize, ctx: ir::Value) {
|
||||
let select = self
|
||||
.compiler
|
||||
.module
|
||||
@@ -347,7 +332,7 @@ impl<'comp, 'ctx, Ctx: JITContext> Context<'comp, 'ctx, Ctx> {
|
||||
.stack_addr(self.compiler.ptr_type, slot, 0);
|
||||
self.builder
|
||||
.ins()
|
||||
.call(select, &[ptr, path_ptr, path_len, engine, env]);
|
||||
.call(select, &[ptr, path_ptr, path_len, ctx]);
|
||||
}
|
||||
|
||||
fn select_with_default(
|
||||
@@ -357,7 +342,7 @@ impl<'comp, 'ctx, Ctx: JITContext> Context<'comp, 'ctx, Ctx> {
|
||||
path_len: usize,
|
||||
default: StackSlot,
|
||||
engine: ir::Value,
|
||||
env: ir::Value,
|
||||
rt_ctx: ir::Value,
|
||||
) {
|
||||
let select_with_default = self
|
||||
.compiler
|
||||
@@ -377,7 +362,7 @@ impl<'comp, 'ctx, Ctx: JITContext> Context<'comp, 'ctx, Ctx> {
|
||||
.stack_addr(self.compiler.ptr_type, default, 0);
|
||||
self.builder.ins().call(
|
||||
select_with_default,
|
||||
&[ptr, path_ptr, path_len, default_ptr, engine, env],
|
||||
&[ptr, path_ptr, path_len, default_ptr, engine, rt_ctx],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -489,25 +474,22 @@ impl<Ctx: JITContext> JITCompiler<Ctx> {
|
||||
let ptr_type = module.target_config().pointer_type();
|
||||
let value_type = types::I128;
|
||||
|
||||
// fn(*const Context, *const Env, *mut Value)
|
||||
let mut func_sig = module.make_signature();
|
||||
func_sig.params.extend(
|
||||
[AbiParam {
|
||||
value_type: ptr_type,
|
||||
purpose: ArgumentPurpose::Normal,
|
||||
extension: ArgumentExtension::None,
|
||||
}; 3],
|
||||
}; 2],
|
||||
);
|
||||
|
||||
// fn(func: &mut Value, args_ptr: *mut Value, args_len: usize, engine: &mut Context, env:
|
||||
// &mut Env)
|
||||
let mut call_sig = module.make_signature();
|
||||
call_sig.params.extend(
|
||||
[AbiParam {
|
||||
value_type: ptr_type,
|
||||
purpose: ArgumentPurpose::Normal,
|
||||
extension: ArgumentExtension::None,
|
||||
}; 5],
|
||||
}; 3],
|
||||
);
|
||||
let call = module
|
||||
.declare_function("helper_call", Linkage::Import, &call_sig)
|
||||
@@ -525,7 +507,6 @@ impl<Ctx: JITContext> JITCompiler<Ctx> {
|
||||
.declare_function("helper_lookup_stack", Linkage::Import, &lookup_stack_sig)
|
||||
.unwrap();
|
||||
|
||||
// fn(env: &Env, level: usize, ret: &mut MaybeUninit<Value>)
|
||||
let mut lookup_arg_sig = module.make_signature();
|
||||
lookup_arg_sig.params.extend(
|
||||
[AbiParam {
|
||||
@@ -538,7 +519,6 @@ impl<Ctx: JITContext> JITCompiler<Ctx> {
|
||||
.declare_function("helper_lookup_arg", Linkage::Import, &lookup_arg_sig)
|
||||
.unwrap();
|
||||
|
||||
// fn(env: &Env, sym_ptr: *const u8, sym_len: usize, ret: &mut MaybeUninit<Value>)
|
||||
let mut lookup_sig = module.make_signature();
|
||||
lookup_sig.params.extend(
|
||||
[AbiParam {
|
||||
@@ -551,20 +531,18 @@ impl<Ctx: JITContext> JITCompiler<Ctx> {
|
||||
.declare_function("helper_lookup", Linkage::Import, &lookup_sig)
|
||||
.unwrap();
|
||||
|
||||
// fn(val: &mut Value, path_ptr: *mut Value, path_len: usize, engine: &mut Context, env: &mut Env)
|
||||
let mut select_sig = module.make_signature();
|
||||
select_sig.params.extend(
|
||||
[AbiParam {
|
||||
value_type: ptr_type,
|
||||
purpose: ArgumentPurpose::Normal,
|
||||
extension: ArgumentExtension::None,
|
||||
}; 5],
|
||||
}; 4],
|
||||
);
|
||||
let select = module
|
||||
.declare_function("helper_select", Linkage::Import, &select_sig)
|
||||
.unwrap();
|
||||
|
||||
// fn(val: &mut Value, path_ptr: *mut Value, path_len: usize, default: NonNull<Value>, engine: &mut Context, env: &mut Env)
|
||||
let mut select_with_default_sig = module.make_signature();
|
||||
select_with_default_sig.params.extend(
|
||||
[AbiParam {
|
||||
@@ -755,10 +733,9 @@ impl<Ctx: JITContext> JITCompiler<Ctx> {
|
||||
ctx.builder.switch_to_block(entry);
|
||||
|
||||
let params = ctx.builder.block_params(entry);
|
||||
let engine = params[0];
|
||||
let env = params[1];
|
||||
let ret = params[2];
|
||||
let res = ir.compile(&mut ctx, engine, env);
|
||||
let rt_ctx = params[0];
|
||||
let ret = params[1];
|
||||
let res = ir.compile(&mut ctx, rt_ctx);
|
||||
|
||||
let tag = ctx.builder.ins().stack_load(types::I64, res, 0);
|
||||
let val0 = ctx.builder.ins().stack_load(types::I64, res, 8);
|
||||
|
||||
Reference in New Issue
Block a user