diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000..6cf32c0b85 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "wasmparser.rs"] + path = wasmparser.rs + url = git@github.com:yurydelendik/wasmparser.rs diff --git a/Cargo.toml b/Cargo.toml index 61149c7b7f..e7035d8738 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,7 @@ itertools = "0.8" capstone = "0.5.0" failure = "0.1.3" failure_derive = "0.1.3" +cranelift-codegen = "0.28" wabt = "0.7" lazy_static = "1.2" quickcheck = "0.7" diff --git a/src/backend.rs b/src/backend.rs index 37c86d97b3..18cf1f1468 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -4,12 +4,13 @@ // small maximum size and so we can consider iterating over them to be essentially constant-time. use arrayvec::ArrayVec; +use self::registers::*; use dynasmrt::x64::Assembler; use dynasmrt::{AssemblyOffset, DynamicLabel, DynasmApi, DynasmLabelApi, ExecutableBuffer}; use error::Error; use std::{iter, mem}; -use module::{RuntimeFunc, VmCtx}; +use module::{ModuleContext, RuntimeFunc}; /// Size of a pointer on the target in bytes. const WORD_SIZE: u32 = 8; @@ -27,23 +28,25 @@ impl GPRs { } } -const RAX: u8 = 0; -const RCX: u8 = 1; -const RDX: u8 = 2; -const RBX: u8 = 3; -const RSP: u8 = 4; -const RBP: u8 = 5; -const RSI: u8 = 6; -const RDI: u8 = 7; -const R8: u8 = 8; -const R9: u8 = 9; -const R10: u8 = 10; -const R11: u8 = 11; -const R12: u8 = 12; -const R13: u8 = 13; -const R14: u8 = 14; -const R15: u8 = 15; -const NUM_GPRS: u8 = 16; +pub mod registers { + pub const RAX: u8 = 0; + pub const RCX: u8 = 1; + pub const RDX: u8 = 2; + pub const RBX: u8 = 3; + pub const RSP: u8 = 4; + pub const RBP: u8 = 5; + pub const RSI: u8 = 6; + pub const RDI: u8 = 7; + pub const R8: u8 = 8; + pub const R9: u8 = 9; + pub const R10: u8 = 10; + pub const R11: u8 = 11; + pub const R12: u8 = 12; + pub const R13: u8 = 13; + pub const R14: u8 = 14; + pub const R15: u8 = 15; + pub const NUM_GPRS: u8 = 16; +} extern "sysv64" fn println(len: u64, args: *const u8) { println!("{}", unsafe { @@ -205,14 +208,14 @@ pub struct FunctionEnd { should_generate_epilogue: bool, } -pub struct CodeGenSession { +pub struct CodeGenSession<'a, M> { assembler: Assembler, + pub module_context: &'a M, func_starts: Vec<(Option, DynamicLabel)>, - has_memory: bool, } -impl CodeGenSession { - pub fn new(func_count: u32, has_memory: bool) -> Self { +impl<'a, M> CodeGenSession<'a, M> { + pub fn new(func_count: u32, module_context: &'a M) -> Self { let mut assembler = Assembler::new().unwrap(); let func_starts = iter::repeat_with(|| (None, assembler.new_dynamic_label())) .take(func_count as usize) @@ -221,11 +224,11 @@ impl CodeGenSession { CodeGenSession { assembler, func_starts, - has_memory, + module_context, } } - pub fn new_context(&mut self, func_idx: u32) -> Context { + pub fn new_context(&mut self, func_idx: u32) -> Context<'_, M> { { let func_start = &mut self.func_starts[func_idx as usize]; @@ -238,9 +241,9 @@ impl CodeGenSession { Context { asm: &mut self.assembler, func_starts: &self.func_starts, - has_memory: self.has_memory, trap_label: None, block_state: Default::default(), + module_context: self.module_context, } } @@ -292,6 +295,24 @@ impl TranslatedCodeSection { self.exec_buf.ptr(offset) } + pub fn func_range(&self, idx: usize) -> std::ops::Range { + let end = self + .func_starts + .get(idx + 1) + .map(|i| i.0) + .unwrap_or(self.exec_buf.len()); + + self.func_starts[idx].0..end + } + + pub fn funcs<'a>(&'a self) -> impl Iterator> + 'a { + (0..self.func_starts.len()).map(move |i| self.func_range(i)) + } + + pub fn buffer(&self) -> &[u8] { + &*self.exec_buf + } + pub fn disassemble(&self) { ::disassemble::disassemble(&*self.exec_buf).unwrap(); } @@ -494,10 +515,10 @@ impl Locals { pub struct BlockState { stack: Stack, // TODO: `BitVec` - stack_map: Vec, - depth: StackDepth, - return_register: Option, - regs: Registers, + pub stack_map: Vec, + pub depth: StackDepth, + pub return_register: Option, + pub regs: Registers, /// This is the _current_ locals, since we can shuffle them about during function calls. pub locals: Locals, /// In non-linear control flow (ifs and loops) we have to set the locals to the state that @@ -521,13 +542,13 @@ pub enum MemoryAccessMode { Unchecked, } -pub struct Context<'a> { +pub struct Context<'a, M> { asm: &'a mut Assembler, + module_context: &'a M, func_starts: &'a Vec<(Option, DynamicLabel)>, /// Each push and pop on the value stack increments or decrements this value by 1 respectively. pub block_state: BlockState, trap_label: Option