From 6096bb431a2b7c024631d9cc79b0d55716d189b8 Mon Sep 17 00:00:00 2001 From: Daniel M Date: Tue, 1 Feb 2022 09:08:09 +0100 Subject: [PATCH] Playing around with non enum based bytecode --- src/bytecode.rs | 78 +++++++++++++++++++++++++++---------------------- src/vm.rs | 35 ++++++++++------------ 2 files changed, 59 insertions(+), 54 deletions(-) diff --git a/src/bytecode.rs b/src/bytecode.rs index 74e6005..7ffdf08 100644 --- a/src/bytecode.rs +++ b/src/bytecode.rs @@ -2,6 +2,8 @@ use std::collections::HashMap; use crate::ast::{Ast, Expr, Stmt, BinOpType}; +type OpcodeSize = u32; + #[repr(u32)] #[derive(Debug, Clone, Copy)] pub enum OP { @@ -35,8 +37,6 @@ pub enum OP { JumpFalse, - Value(u32), - Print, DbgPrint, @@ -44,7 +44,7 @@ pub enum OP { #[derive(Debug, Default)] pub struct Compiler { - ops: Vec, + ops: Vec, global_vars: HashMap, } @@ -58,7 +58,7 @@ impl Compiler { match stmt { Stmt::Expr(expr) => { self.compile_expr(expr); - self.ops.push(OP::Pop); + self.ops.push(OP::Pop as OpcodeSize); } Stmt::Let(name, rhs) => { let id = self.global_vars.len() as u64; @@ -71,13 +71,13 @@ impl Compiler { let idx_start = self.ops.len(); self.compile_expr(cond); - self.ops.push(OP::JumpFalse); + self.ops.push(OP::JumpFalse as OpcodeSize); let idx_jmp = self.ops.len(); self.gen_i64(0); self.compile(body); - self.ops.push(OP::Jump); + self.ops.push(OP::Jump as OpcodeSize); self.gen_i64(idx_start as i64); self.overwrite_i64(idx_jmp, self.ops.len() as i64); @@ -86,13 +86,13 @@ impl Compiler { Stmt::If(cond, if_block, else_block) => { self.compile_expr(cond); - self.ops.push(OP::JumpFalse); + self.ops.push(OP::JumpFalse as OpcodeSize); let idx_if = self.ops.len(); self.gen_i64(0); self.compile(if_block); - self.ops.push(OP::Jump); + self.ops.push(OP::Jump as OpcodeSize); let idx_else = self.ops.len(); self.gen_i64(0); @@ -105,24 +105,24 @@ impl Compiler { }, Stmt::DbgPrint(expr) => { self.compile_expr(expr); - self.ops.push(OP::DbgPrint); + self.ops.push(OP::DbgPrint as OpcodeSize); } Stmt::Print(expr) => { self.compile_expr(expr); - self.ops.push(OP::Print); + self.ops.push(OP::Print as OpcodeSize); } } } } - pub fn into_ops(self) -> Vec { + pub fn into_ops(self) -> Vec { self.ops } pub fn compile_expr(&mut self, expr: &Expr) { match expr { Expr::I64(val) => { - self.ops.push(OP::Push); + self.ops.push(OP::Push as OpcodeSize); self.gen_i64(*val) } Expr::Ident(name) => { @@ -155,48 +155,56 @@ impl Compiler { self.compile_expr(rhs); match bo { - BinOpType::Add => self.ops.push(OP::Add), - BinOpType::Sub => self.ops.push(OP::Subtract), - BinOpType::Mul => self.ops.push(OP::Multiply), - BinOpType::Div => self.ops.push(OP::Divide), - BinOpType::Mod => self.ops.push(OP::Modulo), - BinOpType::BOr => self.ops.push(OP::BOr), - BinOpType::BAnd => self.ops.push(OP::BAnd), - BinOpType::BXor => self.ops.push(OP::BXor), - BinOpType::Shl => self.ops.push(OP::Shl), - BinOpType::Shr => self.ops.push(OP::Shr), - BinOpType::Equ => self.ops.push(OP::Eq), - BinOpType::Neq => self.ops.push(OP::Neq), - BinOpType::Gt => self.ops.push(OP::Gt), - BinOpType::Ge => self.ops.push(OP::Ge), - BinOpType::Lt => self.ops.push(OP::Lt), - BinOpType::Le => self.ops.push(OP::Le), + BinOpType::Add => self.ops.push(OP::Add as OpcodeSize), + BinOpType::Sub => self.ops.push(OP::Subtract as OpcodeSize), + BinOpType::Mul => self.ops.push(OP::Multiply as OpcodeSize), + BinOpType::Div => self.ops.push(OP::Divide as OpcodeSize), + BinOpType::Mod => self.ops.push(OP::Modulo as OpcodeSize), + BinOpType::BOr => self.ops.push(OP::BOr as OpcodeSize), + BinOpType::BAnd => self.ops.push(OP::BAnd as OpcodeSize), + BinOpType::BXor => self.ops.push(OP::BXor as OpcodeSize), + BinOpType::Shl => self.ops.push(OP::Shl as OpcodeSize), + BinOpType::Shr => self.ops.push(OP::Shr as OpcodeSize), + BinOpType::Equ => self.ops.push(OP::Eq as OpcodeSize), + BinOpType::Neq => self.ops.push(OP::Neq as OpcodeSize), + BinOpType::Gt => self.ops.push(OP::Gt as OpcodeSize), + BinOpType::Ge => self.ops.push(OP::Ge as OpcodeSize), + BinOpType::Lt => self.ops.push(OP::Lt as OpcodeSize), + BinOpType::Le => self.ops.push(OP::Le as OpcodeSize), BinOpType::Assign => unreachable!(), } } fn gen_i64(&mut self, val: i64) { - self.ops.push(OP::Value((val & u32::MAX as i64) as u32)); - self.ops.push(OP::Value((val >> 32) as u32)); + // for i in 0 .. 8 { + // self.ops.push(((val >> i*8) & 0xff) as OpcodeSize); + // } + for i in 0 .. 2 { + self.ops.push(((val >> i*32) & 0xffffffff) as OpcodeSize); + } } fn overwrite_i64(&mut self, idx: usize, val: i64) { - self.ops[idx] = OP::Value((val & u32::MAX as i64) as u32); - self.ops[idx+1] = OP::Value((val >> 32) as u32); + // for i in 0 .. 8 { + // self.ops[idx+i] = ((val >> i*8) & 0xff) as OpcodeSize; + // } + for i in 0 .. 2 { + self.ops[idx+i] = ((val >> i*32) & 0xffffffff) as OpcodeSize; + } } fn gen_load(&mut self, addr: u64) { - self.ops.push(OP::Load); + self.ops.push(OP::Load as OpcodeSize); self.gen_i64(addr as i64) } fn gen_store(&mut self, addr: u64) { - self.ops.push(OP::Store); + self.ops.push(OP::Store as OpcodeSize); self.gen_i64(addr as i64) } } -pub fn compile(ast: &Ast) -> Vec { +pub fn compile(ast: &Ast) -> Vec { let mut compiler = Compiler::new(); compiler.compile(ast); compiler.into_ops() diff --git a/src/vm.rs b/src/vm.rs index 5323792..4a80477 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -2,7 +2,7 @@ use crate::{bytecode::OP, interpreter::Value}; #[derive(Debug, Default)] pub struct Vm { - prog: Vec, + prog: Vec, ip: usize, stack: Vec, @@ -11,7 +11,7 @@ pub struct Vm { } impl Vm { - pub fn new(prog: Vec) -> Self { + pub fn new(prog: Vec) -> Self { Self { prog, ..Default::default() @@ -19,7 +19,7 @@ impl Vm { } pub fn run(&mut self) { - while let Some(op) = self.prog.get(self.ip).copied() { + while let Some(op) = self.prog.get(self.ip).copied().map(|op| unsafe { std::mem::transmute::(op) }) { self.ip += 1; match op { @@ -136,9 +136,6 @@ impl Vm { let vals = self.pop2_i64(); self.stack.push(Value::I64(vals.0 >> vals.1)) } - OP::Value(_) => { - panic!("This is not an instruction, but data. This should never be evaluated") - } OP::Jump => { self.ip = self.read_i64() as usize; } @@ -168,22 +165,22 @@ impl Vm { } fn read_i64(&mut self) -> i64 { - let mut val = if let Some(OP::Value(val)) = self.prog.get(self.ip).copied() { - val - } else { - panic!("Expected Value as next OP") - } as i64; + let mut val = *self.prog.get(self.ip).unwrap() as i64; + val |= (*self.prog.get(self.ip + 1).unwrap() as i64) << 32; - self.ip += 1; + // let mut bytes = [0; 8]; + // bytes.copy_from_slice(&self.prog[self.ip..self.ip+8]); + // val = i64::from_le_bytes(bytes); - val |= (if let Some(OP::Value(val)) = self.prog.get(self.ip).copied() { - val - } else { - panic!("Expected Value as next OP") - } as i64) - << 32; + // for i in 0 .. 8 { + // if let Some(tmp) = self.prog.get(self.ip + i).copied() { + // val |= ((tmp as i64) << i*8) as i64; + // } else { + // panic!("Expected Value as next OP") + // } + // } - self.ip += 1; + self.ip += 2; val }