feat(bytecode): add ability to insert a deferred local call
This commit is contained in:
parent
7ce7753bae
commit
7388571a33
|
@ -16,6 +16,7 @@ pub enum OpType {
|
||||||
Label = 0x4c, /* L */
|
Label = 0x4c, /* L */
|
||||||
CallRemote = 0x43, /* C */
|
CallRemote = 0x43, /* C */
|
||||||
CallLocal = 0x49, /* I */
|
CallLocal = 0x49, /* I */
|
||||||
|
CallLDefer = 0x64, /* d */
|
||||||
Jump = 0x4a, /* J */
|
Jump = 0x4a, /* J */
|
||||||
JumpCond = 0x6a, /* j */
|
JumpCond = 0x6a, /* j */
|
||||||
Return = 0x52, /* R */
|
Return = 0x52, /* R */
|
||||||
|
|
|
@ -10,17 +10,23 @@ pub enum Instr<'a> {
|
||||||
|
|
||||||
/// pops the descriptor table pointer from the stack,
|
/// pops the descriptor table pointer from the stack,
|
||||||
/// then tries to call the $0 on it.
|
/// then tries to call the $0 on it.
|
||||||
/// $1 is the amount of arguments (arity) extracted from the stack after the pointer
|
/// $1 is the amount of arguments (arity) extracted
|
||||||
|
/// from the stack after the pointer
|
||||||
CallRemote(Atom, u8),
|
CallRemote(Atom, u8),
|
||||||
|
|
||||||
/// calls the destination $0 inside of the current module
|
/// calls the destination $0 inside of the current module
|
||||||
CallLocal(u64),
|
CallLocal(u64),
|
||||||
|
|
||||||
|
/// calls the destination $0 after the next `Return`,
|
||||||
|
/// by inserting the call into the call stack,
|
||||||
|
/// but continuing execution normally.
|
||||||
|
CallLDefer(u64),
|
||||||
|
|
||||||
/// jumps to the destination $0 inside of the current module
|
/// jumps to the destination $0 inside of the current module
|
||||||
Jump(u64),
|
Jump(u64),
|
||||||
|
|
||||||
/// pops the top stack value and if it is non-zero, jumps to the specified destination
|
/// pops the top stack value and if it is non-zero,
|
||||||
/// inside of the current module
|
/// jumps to the specified destination inside of the current module
|
||||||
JumpCond(u64),
|
JumpCond(u64),
|
||||||
|
|
||||||
/// pops the current call frame
|
/// pops the current call frame
|
||||||
|
@ -55,6 +61,7 @@ impl Instr<'_> {
|
||||||
Instr::Label => OpType::Label,
|
Instr::Label => OpType::Label,
|
||||||
Instr::CallRemote(_, _) => OpType::CallRemote,
|
Instr::CallRemote(_, _) => OpType::CallRemote,
|
||||||
Instr::CallLocal(_) => OpType::CallLocal,
|
Instr::CallLocal(_) => OpType::CallLocal,
|
||||||
|
Instr::CallLDefer(_) => OpType::CallLDefer,
|
||||||
Instr::Jump(_) => OpType::Jump,
|
Instr::Jump(_) => OpType::Jump,
|
||||||
Instr::JumpCond(_) => OpType::JumpCond,
|
Instr::JumpCond(_) => OpType::JumpCond,
|
||||||
Instr::Return => OpType::Return,
|
Instr::Return => OpType::Return,
|
||||||
|
@ -108,6 +115,7 @@ impl<'a> crate::Parse<'a> for Instr<'a> {
|
||||||
Ok((inp, Instr::CallRemote(val, arity)))
|
Ok((inp, Instr::CallRemote(val, arity)))
|
||||||
}
|
}
|
||||||
OpType::CallLocal => u64::parse(inp).map(|(inp, val)| (inp, Instr::CallLocal(val))),
|
OpType::CallLocal => u64::parse(inp).map(|(inp, val)| (inp, Instr::CallLocal(val))),
|
||||||
|
OpType::CallLDefer => u64::parse(inp).map(|(inp, val)| (inp, Instr::CallLDefer(val))),
|
||||||
OpType::Jump => u64::parse(inp).map(|(inp, val)| (inp, Instr::Jump(val))),
|
OpType::Jump => u64::parse(inp).map(|(inp, val)| (inp, Instr::Jump(val))),
|
||||||
OpType::JumpCond => u64::parse(inp).map(|(inp, val)| (inp, Instr::JumpCond(val))),
|
OpType::JumpCond => u64::parse(inp).map(|(inp, val)| (inp, Instr::JumpCond(val))),
|
||||||
OpType::Push => Ok(Value::parse(inp).map(|(inp, val)| (inp, Instr::Push(val)))?),
|
OpType::Push => Ok(Value::parse(inp).map(|(inp, val)| (inp, Instr::Push(val)))?),
|
||||||
|
@ -135,6 +143,7 @@ impl Instr<'_> {
|
||||||
writer.write_all(&[*arity])?;
|
writer.write_all(&[*arity])?;
|
||||||
}
|
}
|
||||||
Instr::CallLocal(val) => writer.write_all(&val.to_be_bytes())?,
|
Instr::CallLocal(val) => writer.write_all(&val.to_be_bytes())?,
|
||||||
|
Instr::CallLDefer(val) => writer.write_all(&val.to_be_bytes())?,
|
||||||
Instr::Jump(val) => writer.write_all(&val.to_be_bytes())?,
|
Instr::Jump(val) => writer.write_all(&val.to_be_bytes())?,
|
||||||
Instr::JumpCond(val) => writer.write_all(&val.to_be_bytes())?,
|
Instr::JumpCond(val) => writer.write_all(&val.to_be_bytes())?,
|
||||||
Instr::Push(val) => val.write_to(writer)?,
|
Instr::Push(val) => val.write_to(writer)?,
|
||||||
|
|
|
@ -70,8 +70,8 @@ impl Process {
|
||||||
call2jump
|
call2jump
|
||||||
}
|
}
|
||||||
|
|
||||||
fn verify_jumptarget(&self, previptr: usize, jinstr: &str) -> bool {
|
fn verify_jumptarget_explicit(previptr: usize, jinstr: &str, jtip: &InstrPtr) -> bool {
|
||||||
if let Some(n2xti_arr) = self.instrp.0.h.get(self.instrp.1..) {
|
if let Some(n2xti_arr) = jtip.0.h.get(jtip.1..) {
|
||||||
if let Ok((_, trgi)) = Instr::parse(n2xti_arr) {
|
if let Ok((_, trgi)) = Instr::parse(n2xti_arr) {
|
||||||
if trgi != Instr::Label {
|
if trgi != Instr::Label {
|
||||||
tracing::error!(
|
tracing::error!(
|
||||||
|
@ -87,6 +87,10 @@ impl Process {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn verify_jumptarget(&self, previptr: usize, jinstr: &str) -> bool {
|
||||||
|
Self::verify_jumptarget_explicit(previptr, jinstr, &self.instrp)
|
||||||
|
}
|
||||||
|
|
||||||
fn run(&mut self) {
|
fn run(&mut self) {
|
||||||
loop {
|
loop {
|
||||||
use fogtix_bytecode::consts::MathBinOp;
|
use fogtix_bytecode::consts::MathBinOp;
|
||||||
|
@ -163,6 +167,19 @@ impl Process {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Instr::CallLDefer(x) => match x.try_into() {
|
||||||
|
Ok(dfi) => {
|
||||||
|
let jtip = (self.instrp.0.clone(), dfi);
|
||||||
|
if !Self::verify_jumptarget_explicit(previptr, "call-l-defer", &jtip) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
self.callstack.push(jtip);
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
tracing::error!("jump to out-of-bounds address @ {} -> {}", previptr, x);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
Instr::Jump(x) => {
|
Instr::Jump(x) => {
|
||||||
self.instrp.1 = match x.try_into() {
|
self.instrp.1 = match x.try_into() {
|
||||||
Ok(y) => y,
|
Ok(y) => y,
|
||||||
|
|
Loading…
Reference in a new issue