wasmer/lib/runtime-core/src/codegen.rs

434 lines
14 KiB
Rust
Raw Normal View History

//! The codegen module provides common functions and data structures used by multiple backends
//! during the code generation process.
2019-11-22 00:36:34 +08:00
#[cfg(unix)]
use crate::fault::FaultInfo;
2019-04-27 12:31:04 +08:00
use crate::{
backend::RunnableModule,
backend::{CacheGen, Compiler, CompilerConfig, Features, Token},
2019-04-27 12:31:04 +08:00
cache::{Artifact, Error as CacheError},
error::{CompileError, CompileResult},
module::{ModuleInfo, ModuleInner},
structures::Map,
types::{FuncIndex, FuncSig, SigIndex},
2019-04-27 12:31:04 +08:00
};
use smallvec::SmallVec;
use std::any::Any;
2019-06-27 15:49:43 +08:00
use std::collections::HashMap;
2019-05-05 13:37:36 -05:00
use std::fmt;
use std::fmt::Debug;
2019-04-27 12:31:04 +08:00
use std::marker::PhantomData;
use std::sync::{Arc, RwLock};
use wasmparser::{self, WasmDecoder};
use wasmparser::{Operator, Type as WpType};
2019-04-27 12:31:04 +08:00
/// A type that defines a function pointer, which is called when breakpoints occur.
2019-07-04 01:45:54 +08:00
pub type BreakpointHandler =
Box<dyn Fn(BreakpointInfo) -> Result<(), Box<dyn Any + Send>> + Send + Sync + 'static>;
/// Maps instruction pointers to their breakpoint handlers.
2019-07-04 01:45:06 +08:00
pub type BreakpointMap = Arc<HashMap<usize, BreakpointHandler>>;
2019-06-27 15:49:43 +08:00
/// An event generated during parsing of a wasm binary
2019-05-03 00:14:25 -05:00
#[derive(Debug)]
2019-04-27 12:31:04 +08:00
pub enum Event<'a, 'b> {
/// An internal event created by the parser used to provide hooks during code generation.
2019-04-27 12:31:04 +08:00
Internal(InternalEvent),
/// An event generated by parsing a wasm operator
2019-04-27 12:31:04 +08:00
Wasm(&'b Operator<'a>),
/// An event generated by parsing a wasm operator that contains an owned `Operator`
WasmOwned(Operator<'a>),
2019-04-27 12:31:04 +08:00
}
/// Kinds of `InternalEvent`s created during parsing.
2019-04-27 12:31:04 +08:00
pub enum InternalEvent {
/// A function parse is about to begin.
FunctionBegin(u32),
/// A function parsing has just completed.
2019-04-27 12:31:04 +08:00
FunctionEnd,
/// A breakpoint emitted during parsing.
2019-07-04 01:45:06 +08:00
Breakpoint(BreakpointHandler),
/// Indicates setting an internal field.
SetInternal(u32),
/// Indicates getting an internal field.
GetInternal(u32),
2019-04-27 12:31:04 +08:00
}
2019-05-03 00:14:25 -05: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"),
}
}
}
/// Information for a breakpoint
2019-11-22 00:51:20 +08:00
#[cfg(unix)]
2019-07-04 01:45:06 +08:00
pub struct BreakpointInfo<'a> {
/// Fault.
pub fault: Option<&'a FaultInfo>,
}
2019-11-22 00:51:20 +08:00
/// Information for a breakpoint
#[cfg(not(unix))]
2019-11-22 07:26:35 +08:00
pub struct BreakpointInfo {
/// Fault placeholder.
pub fault: Option<()>,
}
/// A trait that represents the functions needed to be implemented to generate code for a module.
2019-04-27 12:31:04 +08:00
pub trait ModuleCodeGenerator<FCG: FunctionCodeGenerator<E>, RM: RunnableModule, E: Debug> {
2019-05-14 16:13:42 +08:00
/// Creates a new module code generator.
2019-04-27 12:31:04 +08:00
fn new() -> Self;
2019-05-14 16:13:42 +08:00
/// Creates a new module code generator for specified target.
fn new_with_target(
triple: Option<String>,
cpu_name: Option<String>,
cpu_features: Option<String>,
) -> Self;
2019-05-14 16:13:42 +08:00
/// Returns the backend id associated with this MCG.
2020-01-13 15:40:09 +01:00
fn backend_id() -> &'static str;
2019-04-27 12:31:04 +08:00
/// It sets if the current compiler requires validation before compilation
2019-12-20 20:11:56 -08:00
fn requires_pre_validation() -> bool {
true
}
2019-05-14 16:13:42 +08:00
/// Feeds the compiler config.
fn feed_compiler_config(&mut self, _config: &CompilerConfig) -> Result<(), E> {
Ok(())
}
/// Adds an import function.
fn feed_import_function(&mut self) -> Result<(), E>;
/// Sets the signatures.
2019-04-27 12:31:04 +08:00
fn feed_signatures(&mut self, signatures: Map<SigIndex, FuncSig>) -> Result<(), E>;
/// Sets function signatures.
fn feed_function_signatures(&mut self, assoc: Map<FuncIndex, SigIndex>) -> Result<(), E>;
2019-05-14 16:13:42 +08:00
/// Checks the precondition for a module.
fn check_precondition(&mut self, module_info: &ModuleInfo) -> Result<(), E>;
/// Creates a new function and returns the function-scope code generator for it.
2020-02-11 09:52:21 -08:00
fn next_function(&mut self, module_info: Arc<RwLock<ModuleInfo>>, loc: (u32, u32)) -> Result<&mut FCG, E>;
2019-05-14 16:13:42 +08:00
/// Finalizes this module.
2020-02-11 09:52:21 -08:00
fn finalize(
self,
module_info: &ModuleInfo,
) -> Result<((RM, Option<DebugMetadata>), Box<dyn CacheGen>), E>;
2019-04-27 12:31:04 +08:00
2019-05-14 16:13:42 +08:00
/// Creates a module from cache.
2019-05-05 20:11:47 -05:00
unsafe fn from_cache(cache: Artifact, _: Token) -> Result<ModuleInner, CacheError>;
2019-04-27 12:31:04 +08:00
}
use cranelift_entity::PrimaryMap;
/// missing documentation!
pub struct DebugMetadata {
///f unc info
pub func_info: PrimaryMap<FuncIndex, wasm_debug::types::CompiledFunctionData>,
/// inst_info
pub inst_info: PrimaryMap<FuncIndex, wasm_debug::types::ValueLabelsRangesInner>,
2020-02-11 09:52:21 -08:00
/// stack slot offsets!
pub stack_slot_offsets: PrimaryMap<FuncIndex, Vec<Option<i32>>>,
/// function pointers and their lengths
pub pointers: Vec<(*const u8, usize)>,
}
/// A streaming compiler which is designed to generated code for a module based on a stream
/// of wasm parser events.
2019-04-27 12:31:04 +08:00
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>,
}
/// A simple generator for a `StreamingCompiler`.
2019-04-27 12:31:04 +08:00
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<
MCG: ModuleCodeGenerator<FCG, RM, E>,
FCG: FunctionCodeGenerator<E>,
RM: RunnableModule + 'static,
E: Debug,
> SimpleStreamingCompilerGen<MCG, FCG, RM, E>
{
/// Create a new `StreamingCompiler`.
2019-04-27 12:31:04 +08:00
pub fn new() -> StreamingCompiler<MCG, FCG, RM, E, impl Fn() -> MiddlewareChain> {
StreamingCompiler::new(|| MiddlewareChain::new())
}
}
impl<
MCG: ModuleCodeGenerator<FCG, RM, E>,
FCG: FunctionCodeGenerator<E>,
RM: RunnableModule + 'static,
E: Debug,
CGEN: Fn() -> MiddlewareChain,
> StreamingCompiler<MCG, FCG, RM, E, CGEN>
{
/// Create a new `StreamingCompiler` with the given `MiddlewareChain`.
2019-04-27 12:31:04 +08: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,
}
}
}
/// Create a new `ValidatingParserConfig` with the given features.
pub fn validating_parser_config(features: &Features) -> wasmparser::ValidatingParserConfig {
wasmparser::ValidatingParserConfig {
operator_config: wasmparser::OperatorValidatorConfig {
enable_threads: features.threads,
enable_reference_types: false,
enable_simd: features.simd,
enable_bulk_memory: false,
enable_multi_value: false,
#[cfg(feature = "deterministic-execution")]
deterministic_only: true,
},
}
}
fn validate_with_features(bytes: &[u8], features: &Features) -> CompileResult<()> {
let mut parser =
wasmparser::ValidatingParser::new(bytes, Some(validating_parser_config(features)));
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-04-27 12:31:04 +08:00
impl<
MCG: ModuleCodeGenerator<FCG, RM, E>,
FCG: FunctionCodeGenerator<E>,
RM: RunnableModule + 'static,
E: Debug,
CGEN: Fn() -> MiddlewareChain,
> Compiler for StreamingCompiler<MCG, FCG, RM, E, CGEN>
{
#[allow(unused_variables)]
2019-04-27 12:31:04 +08:00
fn compile(
&self,
wasm: &[u8],
compiler_config: CompilerConfig,
_: Token,
) -> CompileResult<ModuleInner> {
if MCG::requires_pre_validation() {
validate_with_features(wasm, &compiler_config.features)?;
}
2020-01-13 15:40:09 +01:00
let mut mcg = match MCG::backend_id() {
2019-12-20 20:11:56 -08:00
"llvm" => MCG::new_with_target(
compiler_config.triple.clone(),
compiler_config.cpu_name.clone(),
compiler_config.cpu_features.clone(),
),
_ => MCG::new(),
};
2019-04-27 12:31:04 +08:00
let mut chain = (self.middleware_chain_generator)();
2019-12-20 22:01:18 -08:00
let info = crate::parse::read_module(wasm, &mut mcg, &mut chain, &compiler_config)?;
2020-02-11 09:52:21 -08:00
let ((exec_context, debug_metadata), cache_gen) = mcg
.finalize(&info.read().unwrap())
.map_err(|x| CompileError::InternalError {
msg: format!("{:?}", x),
})?;
use target_lexicon::{
Architecture, BinaryFormat, Environment, OperatingSystem, Triple, Vendor,
};
const X86_64_OSX: Triple = Triple {
architecture: Architecture::X86_64,
vendor: Vendor::Apple,
operating_system: OperatingSystem::Darwin,
environment: Environment::Unknown,
binary_format: BinaryFormat::Macho,
};
2020-02-11 09:52:21 -08:00
if compiler_config.generate_debug_info {
let debug_metadata = debug_metadata.expect("debug metadata");
let debug_info = wasm_debug::read_debuginfo(wasm);
2020-02-11 09:52:21 -08:00
let extra_info = wasm_debug::types::ModuleVmctxInfo::new(14 * 8, debug_metadata.stack_slot_offsets.values());
// lazy type hack (TODO:)
2020-02-11 09:52:21 -08:00
let compiled_fn_map = wasm_debug::types::create_module_address_map(debug_metadata.func_info.values());
let range_map = wasm_debug::types::build_values_ranges(debug_metadata.inst_info.values());
let raw_func_slice = debug_metadata.pointers;
dbg!("DEBUG INFO GENERATED");
2020-02-11 09:52:21 -08:00
let debug_image = wasm_debug::emit_debugsections_image(
X86_64_OSX,
std::mem::size_of::<usize>() as u8,
&debug_info,
&extra_info,
&compiled_fn_map,
&range_map,
&raw_func_slice,
)
.expect("make debug image");
crate::jit_debug::register_new_jit_code_entry(
&debug_image,
crate::jit_debug::JITAction::JIT_REGISTER_FN,
);
}
2019-04-27 12:31:04 +08:00
Ok(ModuleInner {
2019-05-05 20:11:47 -05:00
cache_gen,
2019-12-20 20:33:50 -08:00
runnable_module: Arc::new(Box::new(exec_context)),
info: Arc::try_unwrap(info).unwrap().into_inner().unwrap(),
2019-04-27 12:31:04 +08:00
})
}
2019-05-05 20:11:47 -05:00
unsafe fn from_cache(
&self,
artifact: Artifact,
token: Token,
) -> Result<ModuleInner, CacheError> {
MCG::from_cache(artifact, token)
2019-04-27 12:31:04 +08:00
}
}
/// A sink for parse events.
2019-04-27 12:31:04 +08:00
pub struct EventSink<'a, 'b> {
buffer: SmallVec<[Event<'a, 'b>; 2]>,
2019-04-27 12:31:04 +08:00
}
impl<'a, 'b> EventSink<'a, 'b> {
/// Push a new `Event` to this sink.
2019-04-27 12:31:04 +08:00
pub fn push(&mut self, ev: Event<'a, 'b>) {
self.buffer.push(ev);
}
}
/// A container for a chain of middlewares.
2019-04-27 12:31:04 +08:00
pub struct MiddlewareChain {
2019-08-08 16:46:52 -06:00
chain: Vec<Box<dyn GenericFunctionMiddleware>>,
2019-04-27 12:31:04 +08:00
}
impl MiddlewareChain {
/// Create a new empty `MiddlewareChain`.
2019-04-27 12:31:04 +08:00
pub fn new() -> MiddlewareChain {
MiddlewareChain { chain: vec![] }
2019-04-27 12:31:04 +08:00
}
/// Push a new `FunctionMiddleware` to this `MiddlewareChain`.
2019-04-27 12:31:04 +08:00
pub fn push<M: FunctionMiddleware + 'static>(&mut self, m: M) {
self.chain.push(Box::new(m));
}
/// Run this chain with the provided function code generator, event and module info.
pub(crate) fn run<E: Debug, FCG: FunctionCodeGenerator<E>>(
&mut self,
fcg: Option<&mut FCG>,
ev: Event,
module_info: &ModuleInfo,
2020-02-11 09:52:21 -08:00
loc: u32,
) -> Result<(), String> {
2019-04-27 12:31:04 +08: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 {
2020-02-11 09:52:21 -08:00
m.feed_event(ev, module_info, &mut sink, loc)?;
2019-04-27 12:31:04 +08:00
}
}
if let Some(fcg) = fcg {
for ev in sink.buffer {
2020-02-11 09:52:21 -08:00
fcg.feed_event(ev, module_info, loc)
.map_err(|x| format!("{:?}", x))?;
2019-04-27 12:31:04 +08:00
}
}
Ok(())
}
}
/// A trait that represents the signature required to implement middleware for a function.
2019-04-27 12:31:04 +08:00
pub trait FunctionMiddleware {
/// The error type for this middleware's functions.
2019-04-27 12:31:04 +08:00
type Error: Debug;
/// Processes the given event, module info and sink.
fn feed_event<'a, 'b: 'a>(
2019-04-27 12:31:04 +08:00
&mut self,
op: Event<'a, 'b>,
2019-04-27 12:31:04 +08:00
module_info: &ModuleInfo,
sink: &mut EventSink<'a, 'b>,
2020-02-11 09:52:21 -08:00
loc: u32,
2019-04-27 12:31:04 +08:00
) -> Result<(), Self::Error>;
}
pub(crate) trait GenericFunctionMiddleware {
fn feed_event<'a, 'b: 'a>(
2019-04-27 12:31:04 +08:00
&mut self,
op: Event<'a, 'b>,
2019-04-27 12:31:04 +08:00
module_info: &ModuleInfo,
sink: &mut EventSink<'a, 'b>,
2020-02-11 09:52:21 -08:00
loc: u32,
2019-04-27 12:31:04 +08:00
) -> Result<(), String>;
}
impl<E: Debug, T: FunctionMiddleware<Error = E>> GenericFunctionMiddleware for T {
fn feed_event<'a, 'b: 'a>(
2019-04-27 12:31:04 +08:00
&mut self,
op: Event<'a, 'b>,
2019-04-27 12:31:04 +08:00
module_info: &ModuleInfo,
sink: &mut EventSink<'a, 'b>,
2020-02-11 09:52:21 -08:00
loc: u32,
2019-04-27 12:31:04 +08:00
) -> Result<(), String> {
2020-02-11 09:52:21 -08:00
<Self as FunctionMiddleware>::feed_event(self, op, module_info, sink, loc)
.map_err(|x| format!("{:?}", x))
2019-04-27 12:31:04 +08: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.
2020-02-11 09:52:21 -08:00
fn feed_local(&mut self, ty: WpType, n: usize, loc: u32) -> Result<(), E>;
2019-04-27 12:31:04 +08:00
/// Called before the first call to `feed_opcode`.
2019-05-03 00:14:25 -05:00
fn begin_body(&mut self, module_info: &ModuleInfo) -> Result<(), E>;
2019-04-27 12:31:04 +08:00
/// Called for each operator.
2020-02-11 09:52:21 -08:00
fn feed_event(&mut self, op: Event, module_info: &ModuleInfo, loc: u32) -> Result<(), E>;
2019-04-27 12:31:04 +08:00
/// Finalizes the function.
fn finalize(&mut self) -> Result<(), E>;
}