fix(bytecode): get rid of redundant 'jump' instruction

This commit is contained in:
Alain Zscheile 2022-09-25 17:08:23 +02:00
parent 7388571a33
commit 0aa63e6c85
3 changed files with 11 additions and 28 deletions

View file

@ -13,11 +13,11 @@ pub enum ValueType {
#[repr(u8)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, IntEnum)]
pub enum OpType {
// control flow
Label = 0x4c, /* L */
CallRemote = 0x43, /* C */
CallLocal = 0x49, /* I */
CallLDefer = 0x64, /* d */
Jump = 0x4a, /* J */
JumpCond = 0x6a, /* j */
Return = 0x52, /* R */
// stack operations

View file

@ -17,14 +17,12 @@ pub enum Instr<'a> {
/// calls the destination $0 inside of the current module
CallLocal(u64),
/// calls the destination $0 after the next `Return`,
/// by inserting the call into the call stack,
/// calls the destination $0 inside of the current module after the
/// next `Return`, by inserting the call into the call stack,
/// but continuing execution normally.
/// A classic `Jump(i)` is then just `[CallLDefer(i), Return]`.
CallLDefer(u64),
/// jumps to the destination $0 inside of the current module
Jump(u64),
/// pops the top stack value and if it is non-zero,
/// jumps to the specified destination inside of the current module
JumpCond(u64),
@ -62,7 +60,6 @@ impl Instr<'_> {
Instr::CallRemote(_, _) => OpType::CallRemote,
Instr::CallLocal(_) => OpType::CallLocal,
Instr::CallLDefer(_) => OpType::CallLDefer,
Instr::Jump(_) => OpType::Jump,
Instr::JumpCond(_) => OpType::JumpCond,
Instr::Return => OpType::Return,
Instr::Push(_) => OpType::Push,
@ -116,7 +113,6 @@ impl<'a> crate::Parse<'a> for Instr<'a> {
}
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::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::Pop => u16::parse(inp).map(|(inp, val)| (inp, Instr::Pop(val))),
@ -144,7 +140,6 @@ impl Instr<'_> {
}
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::JumpCond(val) => writer.write_all(&val.to_be_bytes())?,
Instr::Push(val) => val.write_to(writer)?,
Instr::Pop(val) => writer.write_all(&val.to_be_bytes())?,

View file

@ -55,11 +55,11 @@ pub enum StackEntValue {
struct Process {
stack: Vec<StackEntValue>,
callstack: Vec<InstrPtr>,
instrp: (Arc<Module>, usize),
instrp: InstrPtr,
}
impl Process {
fn is_call2jump(instrp: &(Arc<Module>, usize)) -> bool {
fn is_call2jump(instrp: &InstrPtr) -> bool {
let mut call2jump = false;
if let Some(n2xti_arr) = instrp.0.h.get(instrp.1..) {
if let Ok((_, Instr::Return)) = Instr::parse(n2xti_arr) {
@ -173,29 +173,17 @@ impl Process {
if !Self::verify_jumptarget_explicit(previptr, "call-l-defer", &jtip) {
break;
}
self.callstack.push(jtip);
if Self::is_call2jump(&self.instrp) {
self.instrp = jtip;
} else {
self.callstack.push(jtip);
}
}
Err(_) => {
tracing::error!("jump to out-of-bounds address @ {} -> {}", previptr, x);
break;
}
},
Instr::Jump(x) => {
self.instrp.1 = match x.try_into() {
Ok(y) => y,
Err(_) => {
tracing::error!(
"jump to out-of-bounds address @ {} -> {}",
previptr,
x
);
break;
}
};
if !self.verify_jumptarget(previptr, "jump") {
break;
}
}
Instr::JumpCond(x) => {
let x: usize = match x.try_into() {
Ok(y) => y,