From bb52a4e6ebd703d50038e8b85d84010280574ec6 Mon Sep 17 00:00:00 2001 From: losfair Date: Fri, 15 Feb 2019 02:21:52 +0800 Subject: [PATCH] Now we can run `add`! --- lib/dynasm-backend/src/codegen.rs | 5 +- lib/dynasm-backend/src/codegen_x64.rs | 91 +++++++++++++++++++++++++-- lib/dynasm-backend/src/lib.rs | 57 +++++++---------- 3 files changed, 111 insertions(+), 42 deletions(-) diff --git a/lib/dynasm-backend/src/codegen.rs b/lib/dynasm-backend/src/codegen.rs index 2695d2435..18e67f5e1 100644 --- a/lib/dynasm-backend/src/codegen.rs +++ b/lib/dynasm-backend/src/codegen.rs @@ -1,8 +1,9 @@ +use wasmer_runtime_core::backend::ProtectedCaller; use wasmparser::{Operator, Type as WpType}; -pub trait ModuleCodeGenerator { +pub trait ModuleCodeGenerator { fn next_function(&mut self) -> Result<&mut FCG, CodegenError>; - fn finalize(&mut self) -> Result<(), CodegenError>; + fn finalize(self) -> Result; } pub trait FunctionCodeGenerator { diff --git a/lib/dynasm-backend/src/codegen_x64.rs b/lib/dynasm-backend/src/codegen_x64.rs index c6f3dc495..3d0582530 100644 --- a/lib/dynasm-backend/src/codegen_x64.rs +++ b/lib/dynasm-backend/src/codegen_x64.rs @@ -1,6 +1,19 @@ use super::codegen::*; use super::stack::{ValueInfo, ValueLocation, ValueStack}; -use dynasmrt::{x64::Assembler, DynamicLabel, DynasmApi, DynasmLabelApi}; +use dynasmrt::{ + x64::Assembler, AssemblyOffset, DynamicLabel, DynasmApi, DynasmLabelApi, ExecutableBuffer, +}; +use wasmer_runtime_core::{ + backend::{Backend, Compiler, FuncResolver, ProtectedCaller, Token, UserTrapper}, + error::{CompileError, CompileResult, RuntimeError, RuntimeResult}, + module::{ModuleInfo, ModuleInner, StringTable}, + structures::{Map, TypedIndex}, + types::{ + FuncIndex, FuncSig, GlobalIndex, LocalFuncIndex, MemoryIndex, SigIndex, TableIndex, Type, + Value, + }, + vm::{self, ImportBacking}, +}; use wasmparser::{Operator, Type as WpType}; #[repr(u8)] @@ -49,6 +62,7 @@ pub struct X64ModuleCodeGenerator { pub struct X64FunctionCode { id: usize, begin_label: DynamicLabel, + begin_offset: AssemblyOffset, cleanup_label: DynamicLabel, assembler: Option, returns: Vec, @@ -58,6 +72,55 @@ pub struct X64FunctionCode { value_stack: ValueStack, } +pub struct X64ExecutionContext { + code: ExecutableBuffer, + functions: Vec, +} + +impl ProtectedCaller for X64ExecutionContext { + fn call( + &self, + _module: &ModuleInner, + _func_index: FuncIndex, + _params: &[Value], + _import_backing: &ImportBacking, + _vmctx: *mut vm::Ctx, + _: Token, + ) -> RuntimeResult> { + let index = _func_index.index(); + let ptr = self.code.ptr(self.functions[index].begin_offset); + let return_ty = self.functions[index].returns.last().cloned(); + + if self.functions[index].num_params != _params.len() { + return Err(RuntimeError::User { + msg: "param count mismatch".into(), + }); + } + + match self.functions[index].num_params { + 2 => unsafe { + let ptr: extern "C" fn(i64, i64) -> i64 = ::std::mem::transmute(ptr); + Ok(vec![Value::I32( + ptr(value_to_i64(&_params[0]), value_to_i64(&_params[1])) as i32, + )]) + }, + _ => unimplemented!(), + } + } + + fn get_early_trapper(&self) -> Box { + pub struct Trapper; + + impl UserTrapper for Trapper { + unsafe fn do_early_trap(&self, msg: String) -> ! { + panic!("{}", msg); + } + } + + Box::new(Trapper) + } +} + #[derive(Copy, Clone, Debug)] struct Local { ty: WpType, @@ -70,7 +133,7 @@ impl X64ModuleCodeGenerator { } } -impl ModuleCodeGenerator for X64ModuleCodeGenerator { +impl ModuleCodeGenerator for X64ModuleCodeGenerator { fn next_function(&mut self) -> Result<&mut X64FunctionCode, CodegenError> { let mut assembler = match self.functions.last_mut() { Some(x) => x.assembler.take().unwrap(), @@ -84,6 +147,7 @@ impl ModuleCodeGenerator for X64ModuleCodeGenerator { }, }; let begin_label = assembler.new_dynamic_label(); + let begin_offset = assembler.offset(); dynasm!( assembler ; => begin_label @@ -93,6 +157,7 @@ impl ModuleCodeGenerator for X64ModuleCodeGenerator { let code = X64FunctionCode { id: self.functions.len(), begin_label: begin_label, + begin_offset: begin_offset, cleanup_label: assembler.new_dynamic_label(), assembler: Some(assembler), returns: vec![], @@ -105,13 +170,20 @@ impl ModuleCodeGenerator for X64ModuleCodeGenerator { Ok(self.functions.last_mut().unwrap()) } - fn finalize(&mut self) -> Result<(), CodegenError> { + fn finalize(mut self) -> Result { let mut assembler = match self.functions.last_mut() { Some(x) => x.assembler.take().unwrap(), - None => return Ok(()), + None => { + return Err(CodegenError { + message: "no function", + }) + } }; let output = assembler.finalize().unwrap(); - Ok(()) + Ok(X64ExecutionContext { + code: output, + functions: self.functions, + }) } } @@ -345,3 +417,12 @@ fn get_size_of_type(ty: &WpType) -> Result { fn is_dword(n: usize) -> bool { n == 4 } + +fn value_to_i64(v: &Value) -> i64 { + match *v { + Value::F32(x) => x.to_bits() as u64 as i64, + Value::F64(x) => x.to_bits() as u64 as i64, + Value::I32(x) => x as u64 as i64, + Value::I64(x) => x as u64 as i64, + } +} diff --git a/lib/dynasm-backend/src/lib.rs b/lib/dynasm-backend/src/lib.rs index 3b4ffdbe2..f7f751c37 100644 --- a/lib/dynasm-backend/src/lib.rs +++ b/lib/dynasm-backend/src/lib.rs @@ -11,6 +11,8 @@ mod codegen_x64; mod parse; mod stack; +use crate::codegen::{CodegenError, ModuleCodeGenerator}; +use crate::parse::LoadError; use std::ptr::NonNull; use wasmer_runtime_core::{ backend::{Backend, Compiler, FuncResolver, ProtectedCaller, Token, UserTrapper}, @@ -32,53 +34,38 @@ impl FuncResolver for Placeholder { _module: &ModuleInner, _local_func_index: LocalFuncIndex, ) -> Option> { + panic!(); None } } -impl ProtectedCaller for Placeholder { - fn call( - &self, - _module: &ModuleInner, - _func_index: FuncIndex, - _params: &[Value], - _import_backing: &ImportBacking, - _vmctx: *mut vm::Ctx, - _: Token, - ) -> RuntimeResult> { - Ok(vec![]) - } - - fn get_early_trapper(&self) -> Box { - pub struct Trapper; - - impl UserTrapper for Trapper { - unsafe fn do_early_trap(&self, msg: String) -> ! { - panic!("{}", msg); - } - } - - Box::new(Trapper) - } -} - pub struct SinglePassCompiler {} impl Compiler for SinglePassCompiler { fn compile(&self, wasm: &[u8], _: Token) -> CompileResult { let mut mcg = codegen_x64::X64ModuleCodeGenerator::new(); - let info = match parse::read_module(wasm, Backend::Dynasm, &mut mcg) { - Ok(x) => x, - Err(e) => { - return Err(CompileError::InternalError { - msg: format!("{:?}", e), - }) - } - }; + let info = parse::read_module(wasm, Backend::Dynasm, &mut mcg)?; + let ec = mcg.finalize()?; Ok(ModuleInner { func_resolver: Box::new(Placeholder), - protected_caller: Box::new(Placeholder), + protected_caller: Box::new(ec), info: info, }) } } + +impl From for CompileError { + fn from(other: CodegenError) -> CompileError { + CompileError::InternalError { + msg: other.message.into(), + } + } +} + +impl From for CompileError { + fn from(other: LoadError) -> CompileError { + CompileError::InternalError { + msg: format!("{:?}", other), + } + } +}