2019-04-27 04:31:04 +00:00
|
|
|
use crate::{
|
|
|
|
backend::RunnableModule,
|
|
|
|
backend::{sys::Memory, Backend, CacheGen, Compiler, CompilerConfig, Token},
|
|
|
|
cache::{Artifact, Error as CacheError},
|
|
|
|
error::{CompileError, CompileResult},
|
|
|
|
module::{ModuleInfo, ModuleInner},
|
|
|
|
parse::LoadError,
|
2019-04-27 08:31:47 +00:00
|
|
|
structures::Map,
|
|
|
|
types::{FuncIndex, FuncSig, SigIndex},
|
2019-04-27 04:31:04 +00:00
|
|
|
};
|
|
|
|
use smallvec::SmallVec;
|
2019-05-05 18:37:36 +00:00
|
|
|
use std::fmt;
|
2019-04-27 08:31:47 +00:00
|
|
|
use std::fmt::Debug;
|
2019-04-27 04:31:04 +00:00
|
|
|
use std::marker::PhantomData;
|
2019-04-27 08:31:47 +00:00
|
|
|
use wasmparser::{Operator, Type as WpType};
|
2019-04-27 04:31:04 +00:00
|
|
|
|
2019-05-03 05:14:25 +00:00
|
|
|
#[derive(Debug)]
|
2019-04-27 04:31:04 +00:00
|
|
|
pub enum Event<'a, 'b> {
|
|
|
|
Internal(InternalEvent),
|
|
|
|
Wasm(&'b Operator<'a>),
|
|
|
|
}
|
|
|
|
|
|
|
|
pub enum InternalEvent {
|
2019-04-27 08:31:47 +00:00
|
|
|
FunctionBegin(u32),
|
2019-04-27 04:31:04 +00:00
|
|
|
FunctionEnd,
|
2019-04-28 04:48:01 +00:00
|
|
|
Breakpoint(Box<Fn(BkptInfo) + Send + Sync + 'static>),
|
2019-04-27 08:31:47 +00:00
|
|
|
SetInternal(u32),
|
|
|
|
GetInternal(u32),
|
2019-04-27 04:31:04 +00:00
|
|
|
}
|
|
|
|
|
2019-05-03 05:14:25 +00:00
|
|
|
impl fmt::Debug for InternalEvent {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
match self {
|
|
|
|
InternalEvent::FunctionBegin(_) => write!(f, "FunctionBegin"),
|
|
|
|
InternalEvent::FunctionEnd => write!(f, "FunctionEnd"),
|
|
|
|
InternalEvent::Breakpoint(_) => write!(f, "Breakpoint"),
|
|
|
|
InternalEvent::SetInternal(_) => write!(f, "SetInternal"),
|
|
|
|
InternalEvent::GetInternal(_) => write!(f, "GetInternal"),
|
2019-05-05 18:37:36 +00:00
|
|
|
_ => panic!("unknown event"),
|
2019-05-03 05:14:25 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-27 08:31:47 +00:00
|
|
|
pub struct BkptInfo {}
|
|
|
|
|
2019-04-27 04:31:04 +00:00
|
|
|
pub trait ModuleCodeGenerator<FCG: FunctionCodeGenerator<E>, RM: RunnableModule, E: Debug> {
|
|
|
|
fn new() -> Self;
|
|
|
|
fn backend_id() -> Backend;
|
|
|
|
fn check_precondition(&mut self, module_info: &ModuleInfo) -> Result<(), E>;
|
|
|
|
|
|
|
|
/// Creates a new function and returns the function-scope code generator for it.
|
|
|
|
fn next_function(&mut self) -> Result<&mut FCG, E>;
|
|
|
|
fn finalize(self, module_info: &ModuleInfo) -> Result<RM, E>;
|
|
|
|
fn feed_signatures(&mut self, signatures: Map<SigIndex, FuncSig>) -> Result<(), E>;
|
|
|
|
|
|
|
|
/// Sets function signatures.
|
2019-04-27 08:31:47 +00:00
|
|
|
fn feed_function_signatures(&mut self, assoc: Map<FuncIndex, SigIndex>) -> Result<(), E>;
|
2019-04-27 04:31:04 +00:00
|
|
|
|
|
|
|
/// Adds an import function.
|
|
|
|
fn feed_import_function(&mut self) -> Result<(), E>;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct StreamingCompiler<
|
|
|
|
MCG: ModuleCodeGenerator<FCG, RM, E>,
|
|
|
|
FCG: FunctionCodeGenerator<E>,
|
|
|
|
RM: RunnableModule + 'static,
|
|
|
|
E: Debug,
|
|
|
|
CGEN: Fn() -> MiddlewareChain,
|
|
|
|
> {
|
|
|
|
middleware_chain_generator: CGEN,
|
|
|
|
_phantom_mcg: PhantomData<MCG>,
|
|
|
|
_phantom_fcg: PhantomData<FCG>,
|
|
|
|
_phantom_rm: PhantomData<RM>,
|
|
|
|
_phantom_e: PhantomData<E>,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct SimpleStreamingCompilerGen<
|
|
|
|
MCG: ModuleCodeGenerator<FCG, RM, E>,
|
|
|
|
FCG: FunctionCodeGenerator<E>,
|
|
|
|
RM: RunnableModule + 'static,
|
|
|
|
E: Debug,
|
|
|
|
> {
|
|
|
|
_phantom_mcg: PhantomData<MCG>,
|
|
|
|
_phantom_fcg: PhantomData<FCG>,
|
|
|
|
_phantom_rm: PhantomData<RM>,
|
|
|
|
_phantom_e: PhantomData<E>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<
|
2019-04-27 08:31:47 +00:00
|
|
|
MCG: ModuleCodeGenerator<FCG, RM, E>,
|
|
|
|
FCG: FunctionCodeGenerator<E>,
|
|
|
|
RM: RunnableModule + 'static,
|
|
|
|
E: Debug,
|
|
|
|
> SimpleStreamingCompilerGen<MCG, FCG, RM, E>
|
|
|
|
{
|
2019-04-27 04:31:04 +00:00
|
|
|
pub fn new() -> StreamingCompiler<MCG, FCG, RM, E, impl Fn() -> MiddlewareChain> {
|
|
|
|
StreamingCompiler::new(|| MiddlewareChain::new())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<
|
2019-04-27 08:31:47 +00:00
|
|
|
MCG: ModuleCodeGenerator<FCG, RM, E>,
|
|
|
|
FCG: FunctionCodeGenerator<E>,
|
|
|
|
RM: RunnableModule + 'static,
|
|
|
|
E: Debug,
|
|
|
|
CGEN: Fn() -> MiddlewareChain,
|
|
|
|
> StreamingCompiler<MCG, FCG, RM, E, CGEN>
|
|
|
|
{
|
2019-04-27 04:31:04 +00:00
|
|
|
pub fn new(chain_gen: CGEN) -> Self {
|
|
|
|
Self {
|
|
|
|
middleware_chain_generator: chain_gen,
|
|
|
|
_phantom_mcg: PhantomData,
|
|
|
|
_phantom_fcg: PhantomData,
|
|
|
|
_phantom_rm: PhantomData,
|
|
|
|
_phantom_e: PhantomData,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<
|
2019-04-27 08:31:47 +00:00
|
|
|
MCG: ModuleCodeGenerator<FCG, RM, E>,
|
|
|
|
FCG: FunctionCodeGenerator<E>,
|
|
|
|
RM: RunnableModule + 'static,
|
|
|
|
E: Debug,
|
|
|
|
CGEN: Fn() -> MiddlewareChain,
|
|
|
|
> Compiler for StreamingCompiler<MCG, FCG, RM, E, CGEN>
|
|
|
|
{
|
2019-04-27 04:31:04 +00:00
|
|
|
fn compile(
|
|
|
|
&self,
|
|
|
|
wasm: &[u8],
|
|
|
|
compiler_config: CompilerConfig,
|
|
|
|
_: Token,
|
|
|
|
) -> CompileResult<ModuleInner> {
|
|
|
|
struct Placeholder;
|
|
|
|
impl CacheGen for Placeholder {
|
|
|
|
fn generate_cache(&self) -> Result<(Box<[u8]>, Memory), CacheError> {
|
|
|
|
Err(CacheError::Unknown(
|
2019-04-28 04:48:01 +00:00
|
|
|
"the streaming compiler API doesn't support caching yet".to_string(),
|
2019-04-27 04:31:04 +00:00
|
|
|
))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut mcg = MCG::new();
|
|
|
|
let mut chain = (self.middleware_chain_generator)();
|
2019-04-27 08:31:47 +00:00
|
|
|
let info = crate::parse::read_module(
|
|
|
|
wasm,
|
|
|
|
MCG::backend_id(),
|
|
|
|
&mut mcg,
|
|
|
|
&mut chain,
|
|
|
|
&compiler_config,
|
|
|
|
)?;
|
|
|
|
let exec_context = mcg
|
|
|
|
.finalize(&info)
|
|
|
|
.map_err(|x| CompileError::InternalError {
|
|
|
|
msg: format!("{:?}", x),
|
|
|
|
})?;
|
2019-04-27 04:31:04 +00:00
|
|
|
Ok(ModuleInner {
|
|
|
|
cache_gen: Box::new(Placeholder),
|
|
|
|
runnable_module: Box::new(exec_context),
|
|
|
|
info: info,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
unsafe fn from_cache(&self, _artifact: Artifact, _: Token) -> Result<ModuleInner, CacheError> {
|
|
|
|
Err(CacheError::Unknown(
|
2019-04-28 04:48:01 +00:00
|
|
|
"the streaming compiler API doesn't support caching yet".to_string(),
|
2019-04-27 04:31:04 +00:00
|
|
|
))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct EventSink<'a, 'b> {
|
2019-04-27 08:31:47 +00:00
|
|
|
buffer: SmallVec<[Event<'a, 'b>; 2]>,
|
2019-04-27 04:31:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a, 'b> EventSink<'a, 'b> {
|
|
|
|
pub fn push(&mut self, ev: Event<'a, 'b>) {
|
|
|
|
self.buffer.push(ev);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct MiddlewareChain {
|
|
|
|
chain: Vec<Box<GenericFunctionMiddleware>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl MiddlewareChain {
|
|
|
|
pub fn new() -> MiddlewareChain {
|
2019-04-27 08:31:47 +00:00
|
|
|
MiddlewareChain { chain: vec![] }
|
2019-04-27 04:31:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn push<M: FunctionMiddleware + 'static>(&mut self, m: M) {
|
|
|
|
self.chain.push(Box::new(m));
|
|
|
|
}
|
|
|
|
|
2019-04-27 08:31:47 +00:00
|
|
|
pub(crate) fn run<E: Debug, FCG: FunctionCodeGenerator<E>>(
|
|
|
|
&mut self,
|
|
|
|
fcg: Option<&mut FCG>,
|
|
|
|
ev: Event,
|
|
|
|
module_info: &ModuleInfo,
|
|
|
|
) -> Result<(), String> {
|
2019-04-27 04:31:04 +00:00
|
|
|
let mut sink = EventSink {
|
|
|
|
buffer: SmallVec::new(),
|
|
|
|
};
|
|
|
|
sink.push(ev);
|
|
|
|
for m in &mut self.chain {
|
|
|
|
let prev: SmallVec<[Event; 2]> = sink.buffer.drain().collect();
|
|
|
|
for ev in prev {
|
|
|
|
m.feed_event(ev, module_info, &mut sink)?;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if let Some(fcg) = fcg {
|
|
|
|
for ev in sink.buffer {
|
2019-04-27 08:31:47 +00:00
|
|
|
fcg.feed_event(ev, module_info)
|
|
|
|
.map_err(|x| format!("{:?}", x))?;
|
2019-04-27 04:31:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub trait FunctionMiddleware {
|
|
|
|
type Error: Debug;
|
2019-04-27 08:31:47 +00:00
|
|
|
fn feed_event<'a, 'b: 'a>(
|
2019-04-27 04:31:04 +00:00
|
|
|
&mut self,
|
2019-04-27 08:31:47 +00:00
|
|
|
op: Event<'a, 'b>,
|
2019-04-27 04:31:04 +00:00
|
|
|
module_info: &ModuleInfo,
|
2019-04-27 08:31:47 +00:00
|
|
|
sink: &mut EventSink<'a, 'b>,
|
2019-04-27 04:31:04 +00:00
|
|
|
) -> Result<(), Self::Error>;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) trait GenericFunctionMiddleware {
|
2019-04-27 08:31:47 +00:00
|
|
|
fn feed_event<'a, 'b: 'a>(
|
2019-04-27 04:31:04 +00:00
|
|
|
&mut self,
|
2019-04-27 08:31:47 +00:00
|
|
|
op: Event<'a, 'b>,
|
2019-04-27 04:31:04 +00:00
|
|
|
module_info: &ModuleInfo,
|
2019-04-27 08:31:47 +00:00
|
|
|
sink: &mut EventSink<'a, 'b>,
|
2019-04-27 04:31:04 +00:00
|
|
|
) -> Result<(), String>;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<E: Debug, T: FunctionMiddleware<Error = E>> GenericFunctionMiddleware for T {
|
2019-04-27 08:31:47 +00:00
|
|
|
fn feed_event<'a, 'b: 'a>(
|
2019-04-27 04:31:04 +00:00
|
|
|
&mut self,
|
2019-04-27 08:31:47 +00:00
|
|
|
op: Event<'a, 'b>,
|
2019-04-27 04:31:04 +00:00
|
|
|
module_info: &ModuleInfo,
|
2019-04-27 08:31:47 +00:00
|
|
|
sink: &mut EventSink<'a, 'b>,
|
2019-04-27 04:31:04 +00:00
|
|
|
) -> Result<(), String> {
|
2019-04-27 08:31:47 +00:00
|
|
|
<Self as FunctionMiddleware>::feed_event(self, op, module_info, sink)
|
|
|
|
.map_err(|x| format!("{:?}", x))
|
2019-04-27 04:31:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// The function-scope code generator trait.
|
|
|
|
pub trait FunctionCodeGenerator<E: Debug> {
|
|
|
|
/// Sets the return type.
|
|
|
|
fn feed_return(&mut self, ty: WpType) -> Result<(), E>;
|
|
|
|
|
|
|
|
/// Adds a parameter to the function.
|
|
|
|
fn feed_param(&mut self, ty: WpType) -> Result<(), E>;
|
|
|
|
|
|
|
|
/// Adds `n` locals to the function.
|
|
|
|
fn feed_local(&mut self, ty: WpType, n: usize) -> Result<(), E>;
|
|
|
|
|
|
|
|
/// Called before the first call to `feed_opcode`.
|
2019-05-03 05:14:25 +00:00
|
|
|
fn begin_body(&mut self, module_info: &ModuleInfo) -> Result<(), E>;
|
2019-04-27 04:31:04 +00:00
|
|
|
|
|
|
|
/// Called for each operator.
|
|
|
|
fn feed_event(&mut self, op: Event, module_info: &ModuleInfo) -> Result<(), E>;
|
|
|
|
|
|
|
|
/// Finalizes the function.
|
|
|
|
fn finalize(&mut self) -> Result<(), E>;
|
|
|
|
}
|