Working basic guard that falls back to interp on fail

This commit is contained in:
2024-02-07 23:21:29 -05:00
parent ff95c5d9e7
commit c3315f04e5
2 changed files with 71 additions and 21 deletions

View File

@@ -29,7 +29,7 @@ extern "C" fn rust_cons(car: Form, cdr: Form) -> Form {
Form::new_pair(car, cdr)
}
extern "C" fn rust_eq(a: Form, b: Form) -> Form {
Form::new_bool(a == b)
Form::new_bool(ManuallyDrop::new(a) == ManuallyDrop::new(b))
}
extern "C" fn rust_cvec_form_grow(ptr: &mut Cvec<Form>) {
ptr.grow()
@@ -139,23 +139,24 @@ impl JIT {
let ok = bcx.ins().icmp_imm(IntCC::Equal, t, tag as i64);
bcx.ins().trapz(ok, TrapCode::User(0));
}
fn stack_pop(bcx: &mut FunctionBuilder, int: Type, tmp_stack_ptr: Value, local_print_func: FuncRef) -> Value {
fn stack_pop(bcx: &mut FunctionBuilder, int: Type, tmp_stack_ptr: Value, local_print_func: FuncRef, peek_only: bool) -> Value {
let len = bcx.ins().load(int, MemFlags::trusted(), tmp_stack_ptr, CVEC_LEN_OFFSET as i32);
let new_len = bcx.ins().iadd_imm(len, -1);
bcx.ins().store(MemFlags::trusted(), new_len, tmp_stack_ptr, CVEC_LEN_OFFSET as i32);
if !peek_only {
bcx.ins().store(MemFlags::trusted(), new_len, tmp_stack_ptr, CVEC_LEN_OFFSET as i32);
}
let ptr = bcx.ins().load(int, MemFlags::trusted(), tmp_stack_ptr, CVEC_PTR_OFFSET as i32);
let offset = bcx.ins().ishl_imm(new_len, 3);
let item_ptr = bcx.ins().iadd(ptr, offset);
let r = bcx.ins().load(int, MemFlags::trusted(), item_ptr, 0);
r
}
fn stack_pop_prim(bcx: &mut FunctionBuilder, int: Type, tmp_stack_ptr: Value, local_print_func: FuncRef) -> Value {
let loaded = stack_pop(bcx, int, tmp_stack_ptr, local_print_func);
let loaded = stack_pop(bcx, int, tmp_stack_ptr, local_print_func, false);
type_assert(bcx, loaded, TAG_PRIM, local_print_func, int);
loaded
}
fn gen_stack_push(bcx: &mut FunctionBuilder, int: Type, tmp_stack_ptr: Value, x: Value, local_cvec_form_grow_func: FuncRef, local_print_func: FuncRef) {
fn stack_push(bcx: &mut FunctionBuilder, int: Type, tmp_stack_ptr: Value, x: Value, local_cvec_form_grow_func: FuncRef, local_print_func: FuncRef) {
let len = bcx.ins().load(int, MemFlags::trusted(), tmp_stack_ptr, CVEC_LEN_OFFSET as i32);
let new_len = bcx.ins().iadd_imm(len, 1);
let cap = bcx.ins().load(int, MemFlags::trusted(), tmp_stack_ptr, CVEC_CAP_OFFSET as i32);
@@ -170,9 +171,9 @@ impl JIT {
bcx.ins().call(local_cvec_form_grow_func, &[tmp_stack_ptr]);
bcx.ins().jump(merge_block, &[]);
bcx.switch_to_block(merge_block);
gen_stack_push_nocap(bcx, int, tmp_stack_ptr, x, local_print_func);
stack_push_nocap(bcx, int, tmp_stack_ptr, x, local_print_func);
}
fn gen_stack_push_nocap(bcx: &mut FunctionBuilder, int: Type, tmp_stack_ptr: Value, x: Value, local_print_func: FuncRef) {
fn stack_push_nocap(bcx: &mut FunctionBuilder, int: Type, tmp_stack_ptr: Value, x: Value, local_print_func: FuncRef) {
let len = bcx.ins().load(int, MemFlags::trusted(), tmp_stack_ptr, CVEC_LEN_OFFSET as i32);
let new_len = bcx.ins().iadd_imm(len, 1);
bcx.ins().store(MemFlags::trusted(), new_len, tmp_stack_ptr, CVEC_LEN_OFFSET as i32);
@@ -182,6 +183,7 @@ impl JIT {
bcx.ins().store(MemFlags::trusted(), x, item_ptr, 0);
}
// DOESN'T RC
fn gen_eq(bcx: &mut FunctionBuilder, int: Type, a: Value, b: Value, local_eq_func: FuncRef, local_print_func: FuncRef) -> Value {
let at = bcx.ins().band_imm(a, TAG_RC as i64);
let bt = bcx.ins().band_imm(b, TAG_RC as i64);
@@ -402,10 +404,6 @@ impl JIT {
self.try_resume_trace(resume_data);
return Ok(Some((tmp_stack.pop().unwrap(), e, (*nc).clone())));
}
Op::Lookup { sym } => {
println!("Lookup(op) {sym}");
tmp_stack.push(e.lookup(sym)?.clone());
}
*/
Op::InlinePrim(p) => {
/*
@@ -416,8 +414,8 @@ impl JIT {
let cst = bcx.ins().iconst(self.int, 1337 << 3);
let _ = bcx.ins().call(local_print_func, &[cst]);
*/
let b = stack_pop(&mut bcx, self.int, tmp_stack_ptr, local_print_func);
let a = if p.two_params() { Some(stack_pop(&mut bcx, self.int, tmp_stack_ptr, local_print_func)) } else { None };
let b = stack_pop(&mut bcx, self.int, tmp_stack_ptr, local_print_func, false);
let a = if p.two_params() { Some(stack_pop(&mut bcx, self.int, tmp_stack_ptr, local_print_func, false)) } else { None };
let result = match p {
Prim::Car => { gen_cr(&mut bcx, self.int, b, false, local_drop_rc_form_func, local_print_func) },
Prim::Cdr => { gen_cr(&mut bcx, self.int, b, true, local_drop_rc_form_func, local_print_func) },
@@ -434,16 +432,23 @@ impl JIT {
_ => unreachable!(),
}
},
Prim::Eq => { gen_eq(&mut bcx, self.int, a.unwrap(), b, local_eq_func, local_print_func) },
Prim::Eq => {
// eq doesn't RC
let a = a.unwrap();
let r = gen_eq(&mut bcx, self.int, a, b, local_eq_func, local_print_func);
decrement(&mut bcx, self.int, a, local_drop_rc_form_func, local_print_func);
decrement(&mut bcx, self.int, b, local_drop_rc_form_func, local_print_func);
r
},
Prim::Cons => { let call = bcx.ins().call(local_cons_func, &[a.unwrap(), b]); bcx.inst_results(call)[0].clone() },
};
let _ = stack_pop_prim(&mut bcx, self.int, tmp_stack_ptr, local_print_func);
gen_stack_push_nocap(&mut bcx, self.int, tmp_stack_ptr, result, local_print_func); // we just popped, so cap is fine
stack_push_nocap(&mut bcx, self.int, tmp_stack_ptr, result, local_print_func); // we just popped, so cap is fine
offset += 1;
}
Op::Define { sym } => {
let s = bcx.ins().iconst(self.int, unsafe { *((&mut Form::new_symbol(sym)) as *mut Form as *mut usize) } as i64);
let v = stack_pop(&mut bcx, self.int, tmp_stack_ptr, local_print_func);
let v = stack_pop(&mut bcx, self.int, tmp_stack_ptr, local_print_func, false);
let e = bcx.ins().load(self.int, MemFlags::trusted(), e_ptr, 0);
let kv = {
@@ -465,7 +470,7 @@ impl JIT {
//e = e.define(sym, v);
}
Op::Drop => {
let v = stack_pop(&mut bcx, self.int, tmp_stack_ptr, local_print_func);
let v = stack_pop(&mut bcx, self.int, tmp_stack_ptr, local_print_func, false);
decrement(&mut bcx, self.int, v, local_drop_rc_form_func, local_print_func);
offset += 1;
//println!("Drop(op) {}", tmp_stack.last().unwrap());
@@ -480,7 +485,7 @@ impl JIT {
if con_rc {
increment_unchecked(&mut bcx, self.int, con, local_print_func);
}
gen_stack_push(&mut bcx, self.int, tmp_stack_ptr, con, local_cvec_form_grow_func, local_print_func);
stack_push(&mut bcx, self.int, tmp_stack_ptr, con, local_cvec_form_grow_func, local_print_func);
offset += 1;
/*
println!("Const(op) {con}");
@@ -524,9 +529,54 @@ impl JIT {
let kv = bcx.block_params(return_block)[0].clone();
let v = gen_cr_unchecked_norc(&mut bcx, self.int, kv, true);
increment(&mut bcx, self.int, v, local_print_func);
gen_stack_push(&mut bcx, self.int, tmp_stack_ptr, v, local_cvec_form_grow_func, local_print_func);
stack_push(&mut bcx, self.int, tmp_stack_ptr, v, local_cvec_form_grow_func, local_print_func);
offset += 1;
}
Op::Guard { const_value, side_val, side_cont, side_id, tbk } => {
let pass_block = bcx.create_block();
let fail_block = bcx.create_block();
const_value.increment();
let const_value = bcx.ins().iconst(self.int, unsafe { *(const_value as *const Form as *const usize) } as i64);
// NOTE THIS IS A PEEK NOT A POP
let v = stack_pop(&mut bcx, self.int, tmp_stack_ptr, local_print_func, true);
let eq_val = gen_eq(&mut bcx, self.int, v, const_value, local_eq_func, local_print_func); // doesn't RC
let eq = bcx.ins().icmp_imm(IntCC::Equal, eq_val, TAG_BOOL_TRUE as i64);
bcx.ins().brif(eq, pass_block, &[], fail_block, &[]);
bcx.switch_to_block(fail_block);
// for now, failed guards drop back to interpreter
let cst = bcx.ins().iconst(self.int, (id.id.get() << TRACE_ID_OFFSET) | offset as i64);
bcx.ins().return_(&[cst]);
bcx.switch_to_block(pass_block);
offset += 1;
/*
println!("Guard(op) {const_value}");
if const_value != tmp_stack.last().unwrap() {
if self.traces.contains_key(side_id) {
if side_val.is_some() {
tmp_stack.pop().unwrap();
}
println!("\tchaining trace to side trace");
id = *side_id;
offset = 0;
break; // break out of this trace and let infinate loop spin
} else {
println!("\tending playback b/c failed guard");
assert!(self.tracing.is_none());
let mut ntrace = Trace::follow_on(*side_id,tbk.clone());
if let Some(side_val) = side_val {
*tmp_stack.last_mut().unwrap() = side_val.clone();
*ntrace.tbk.stack_const.last_mut().unwrap() = false; // this might be able to be
// more precise, actually
}
self.tracing = Some(ntrace);
return Ok(Some((tmp_stack.pop().unwrap(), e, (**side_cont).clone())));
}
}
*/
}
_ => {
// quit out of trace!
println!("compiling back to interp because we can't compile {op:?}");

View File

@@ -110,7 +110,7 @@ fn main() -> Result<()> {
(debug 'gonna_faft_it)
(debug faft)
(debug (faft 6))
(debug (faft 8))
(debug 'gonna_faft_it2)
(debug (faft 10))
;(debug (faft 400))