2019-03-08 23:15:16 +00:00
|
|
|
#![cfg_attr(nightly, feature(unwind_attributes))]
|
|
|
|
|
2019-02-09 23:53:40 +00:00
|
|
|
use wasmer_runtime_core::{
|
2019-03-27 21:18:34 +00:00
|
|
|
backend::{Compiler, CompilerConfig, Token},
|
2019-02-23 01:34:55 +00:00
|
|
|
cache::{Artifact, Error as CacheError},
|
2019-02-09 23:53:40 +00:00
|
|
|
error::CompileError,
|
2019-02-12 03:34:04 +00:00
|
|
|
module::ModuleInner,
|
2019-02-09 23:53:40 +00:00
|
|
|
};
|
2019-03-01 23:48:43 +00:00
|
|
|
use wasmparser::{self, WasmDecoder};
|
2019-02-09 23:53:40 +00:00
|
|
|
|
2019-02-26 02:07:22 +00:00
|
|
|
mod backend;
|
2019-02-09 23:53:40 +00:00
|
|
|
mod code;
|
|
|
|
mod intrinsics;
|
2019-03-02 18:56:02 +00:00
|
|
|
mod platform;
|
2019-02-09 23:53:40 +00:00
|
|
|
mod read_info;
|
|
|
|
mod state;
|
2019-03-01 23:48:43 +00:00
|
|
|
mod trampolines;
|
2019-02-09 23:53:40 +00:00
|
|
|
|
|
|
|
pub struct LLVMCompiler {
|
|
|
|
_private: (),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl LLVMCompiler {
|
|
|
|
pub fn new() -> Self {
|
|
|
|
Self { _private: () }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-29 05:13:34 +00:00
|
|
|
use wasmer_runtime_core::codegen::SimpleStreamingCompilerGen;
|
|
|
|
pub type LLVMStreamingCompiler = SimpleStreamingCompilerGen<
|
|
|
|
code::LLVMModuleCodeGenerator,
|
|
|
|
code::LLVMFunctionCodeGenerator,
|
|
|
|
backend::LLVMBackend,
|
|
|
|
code::CodegenError,
|
|
|
|
>;
|
|
|
|
|
2019-02-09 23:53:40 +00:00
|
|
|
impl Compiler for LLVMCompiler {
|
2019-03-27 21:18:34 +00:00
|
|
|
fn compile(
|
|
|
|
&self,
|
|
|
|
wasm: &[u8],
|
|
|
|
compiler_config: CompilerConfig,
|
|
|
|
_: Token,
|
|
|
|
) -> Result<ModuleInner, CompileError> {
|
2019-03-01 23:48:43 +00:00
|
|
|
validate(wasm)?;
|
|
|
|
|
2019-03-27 21:25:29 +00:00
|
|
|
let (info, code_reader) = read_info::read_module(wasm, compiler_config).unwrap();
|
2019-02-26 02:07:22 +00:00
|
|
|
let (module, intrinsics) = code::parse_function_bodies(&info, code_reader).unwrap();
|
2019-02-09 23:53:40 +00:00
|
|
|
|
2019-04-19 20:54:48 +00:00
|
|
|
let (backend, cache_gen) = backend::LLVMBackend::new(module, intrinsics);
|
2019-02-26 02:07:22 +00:00
|
|
|
|
|
|
|
Ok(ModuleInner {
|
2019-04-12 17:05:50 +00:00
|
|
|
runnable_module: Box::new(backend),
|
2019-04-19 20:54:48 +00:00
|
|
|
cache_gen: Box::new(cache_gen),
|
2019-02-26 02:07:22 +00:00
|
|
|
|
|
|
|
info,
|
|
|
|
})
|
2019-02-09 23:53:40 +00:00
|
|
|
}
|
2019-02-23 01:34:55 +00:00
|
|
|
|
2019-04-19 20:54:48 +00:00
|
|
|
unsafe fn from_cache(&self, artifact: Artifact, _: Token) -> Result<ModuleInner, CacheError> {
|
|
|
|
let (info, _, memory) = artifact.consume();
|
|
|
|
let (backend, cache_gen) =
|
|
|
|
backend::LLVMBackend::from_buffer(memory).map_err(CacheError::DeserializeError)?;
|
|
|
|
|
|
|
|
Ok(ModuleInner {
|
|
|
|
runnable_module: Box::new(backend),
|
|
|
|
cache_gen: Box::new(cache_gen),
|
|
|
|
|
|
|
|
info,
|
|
|
|
})
|
2019-02-23 01:34:55 +00:00
|
|
|
}
|
2019-02-09 23:53:40 +00:00
|
|
|
}
|
|
|
|
|
2019-03-01 23:48:43 +00:00
|
|
|
fn validate(bytes: &[u8]) -> Result<(), CompileError> {
|
2019-03-04 06:47:34 +00:00
|
|
|
let mut parser = wasmparser::ValidatingParser::new(
|
|
|
|
bytes,
|
|
|
|
Some(wasmparser::ValidatingParserConfig {
|
|
|
|
operator_config: wasmparser::OperatorValidatorConfig {
|
|
|
|
enable_threads: false,
|
|
|
|
enable_reference_types: false,
|
|
|
|
enable_simd: false,
|
|
|
|
enable_bulk_memory: false,
|
|
|
|
},
|
|
|
|
mutable_global_imports: false,
|
|
|
|
}),
|
|
|
|
);
|
|
|
|
|
2019-03-01 23:48:43 +00:00
|
|
|
loop {
|
|
|
|
let state = parser.read();
|
|
|
|
match *state {
|
|
|
|
wasmparser::ParserState::EndWasm => break Ok(()),
|
|
|
|
wasmparser::ParserState::Error(err) => Err(CompileError::ValidationError {
|
|
|
|
msg: err.message.to_string(),
|
|
|
|
})?,
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-09 23:53:40 +00:00
|
|
|
#[test]
|
|
|
|
fn test_read_module() {
|
2019-02-28 20:31:39 +00:00
|
|
|
use std::mem::transmute;
|
2019-02-09 23:53:40 +00:00
|
|
|
use wabt::wat2wasm;
|
2019-04-12 17:33:30 +00:00
|
|
|
use wasmer_runtime_core::{
|
|
|
|
backend::RunnableModule, structures::TypedIndex, types::LocalFuncIndex, vm,
|
|
|
|
};
|
2019-02-15 02:08:20 +00:00
|
|
|
// let wasm = include_bytes!("../../spectests/examples/simple/simple.wasm") as &[u8];
|
2019-02-13 02:02:00 +00:00
|
|
|
let wat = r#"
|
2019-02-09 23:53:40 +00:00
|
|
|
(module
|
|
|
|
(type $t0 (func (param i32) (result i32)))
|
2019-02-13 02:02:00 +00:00
|
|
|
(type $t1 (func (result i32)))
|
2019-02-14 23:13:58 +00:00
|
|
|
(memory 1)
|
2019-02-15 02:08:20 +00:00
|
|
|
(global $g0 (mut i32) (i32.const 0))
|
2019-02-13 02:02:00 +00:00
|
|
|
(func $foo (type $t0) (param i32) (result i32)
|
|
|
|
get_local 0
|
|
|
|
))
|
2019-02-09 23:53:40 +00:00
|
|
|
"#;
|
2019-02-13 02:02:00 +00:00
|
|
|
let wasm = wat2wasm(wat).unwrap();
|
2019-02-09 23:53:40 +00:00
|
|
|
|
2019-03-28 17:08:41 +00:00
|
|
|
let (info, code_reader) = read_info::read_module(&wasm, Default::default()).unwrap();
|
2019-02-09 23:53:40 +00:00
|
|
|
|
2019-02-16 00:02:20 +00:00
|
|
|
let (module, intrinsics) = code::parse_function_bodies(&info, code_reader).unwrap();
|
|
|
|
|
2019-04-19 21:09:41 +00:00
|
|
|
let (backend, _) = backend::LLVMBackend::new(module, intrinsics);
|
2019-02-26 02:07:22 +00:00
|
|
|
|
2019-02-28 20:31:39 +00:00
|
|
|
let func_ptr = backend.get_func(&info, LocalFuncIndex::new(0)).unwrap();
|
2019-02-16 00:02:20 +00:00
|
|
|
|
2019-02-28 20:31:39 +00:00
|
|
|
println!("func_ptr: {:p}", func_ptr.as_ptr());
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
let func: unsafe extern "C" fn(*mut vm::Ctx, i32) -> i32 = transmute(func_ptr);
|
|
|
|
let result = func(0 as _, 42);
|
|
|
|
println!("result: {}", result);
|
|
|
|
}
|
2019-02-09 23:53:40 +00:00
|
|
|
}
|