forked from wasmerio/wasmer
-
Notifications
You must be signed in to change notification settings - Fork 0
/
lib.rs
131 lines (109 loc) · 3.44 KB
/
lib.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#[cfg(feature = "cache")]
mod cache;
mod call;
mod func_env;
mod libcalls;
mod module;
mod module_env;
mod relocation;
mod resolver;
mod trampoline;
use cranelift_codegen::{
isa,
settings::{self, Configurable},
};
use target_lexicon::Triple;
#[cfg(feature = "cache")]
use wasmer_runtime_core::{
backend::sys::Memory,
cache::{Cache, Error as CacheError},
module::ModuleInfo,
};
use wasmer_runtime_core::{
backend::{Compiler, Token},
error::{CompileError, CompileResult},
module::ModuleInner,
};
#[cfg(feature = "cache")]
#[macro_use]
extern crate serde_derive;
#[cfg(feature = "cache")]
extern crate serde;
use wasmparser::{self, WasmDecoder};
/// An empty struct to implement logic needed for Cranelift internals.
///
/// See the design (#SPC-arch.clif_compiler) for more information.
pub struct CraneliftCompiler {}
impl CraneliftCompiler {
pub fn new() -> Self {
Self {}
}
}
impl Compiler for CraneliftCompiler {
/// Compiles wasm binary to a wasmer module.
fn compile(&self, wasm: &[u8], _: Token) -> CompileResult<ModuleInner> {
validate(wasm)?;
let isa = get_isa();
let mut module = module::Module::empty();
let module_env = module_env::ModuleEnv::new(&mut module, &*isa);
let func_bodies = module_env.translate(wasm)?;
module.compile(&*isa, func_bodies)
}
/// Create a wasmer Module from an already-compiled cache.
#[cfg(feature = "cache")]
unsafe fn from_cache(&self, cache: Cache, _: Token) -> Result<ModuleInner, CacheError> {
module::Module::from_cache(cache)
}
#[cfg(feature = "cache")]
fn compile_to_backend_cache_data(
&self,
wasm: &[u8],
_: Token,
) -> CompileResult<(Box<ModuleInfo>, Vec<u8>, Memory)> {
validate(wasm)?;
let isa = get_isa();
let mut module = module::Module::empty();
let module_env = module_env::ModuleEnv::new(&mut module, &*isa);
let func_bodies = module_env.translate(wasm)?;
let (info, backend_cache, compiled_code) = module
.compile_to_backend_cache(&*isa, func_bodies)
.map_err(|e| CompileError::InternalError {
msg: format!("{:?}", e),
})?;
let buffer =
backend_cache
.into_backend_data()
.map_err(|e| CompileError::InternalError {
msg: format!("{:?}", e),
})?;
Ok((Box::new(info), buffer, compiled_code))
}
}
fn get_isa() -> Box<isa::TargetIsa> {
let flags = {
let mut builder = settings::builder();
builder.set("opt_level", "best").unwrap();
if cfg!(not(test)) {
builder.set("enable_verifier", "false").unwrap();
}
let flags = settings::Flags::new(builder);
debug_assert_eq!(flags.opt_level(), settings::OptLevel::Best);
flags
};
isa::lookup(Triple::host()).unwrap().finish(flags)
}
fn validate(bytes: &[u8]) -> CompileResult<()> {
let mut parser = wasmparser::ValidatingParser::new(bytes, None);
loop {
let state = parser.read();
match *state {
wasmparser::ParserState::EndWasm => break Ok(()),
wasmparser::ParserState::Error(err) => Err(CompileError::ValidationError {
msg: err.message.to_string(),
})?,
_ => {}
}
}
}
/// The current version of this crate
pub const VERSION: &str = env!("CARGO_PKG_VERSION");