Make FuncEnvironment independent from ModuleEnvironment (formerly WasmRuntime).

This renames WasmRuntime to ModuleEnvironment, and makes several changes
to allow for more flexible compilation.

ModuleEnvironment no longer derives from FuncEnvironment, and no longer
has the `begin_translation` and `next_translation` functions, so that
independent `FuncEnvironment` instances can operate within the same
module.

Also, this obviates the rest of TranslationResult, as it moves processing
of function bodies into the environment. The DummyEnvironment implementation
gives an example of decoding the function bodies as they are parsed, however
other implementation strategies are now possible.
This commit is contained in:
Dan Gohman
2017-10-10 15:21:29 -07:00
parent d4c0c5babc
commit 733870aee4
9 changed files with 245 additions and 187 deletions

View File

@@ -4,7 +4,7 @@
//! IL. Can also executes the `start` function of the module by laying out the memories, globals //! IL. Can also executes the `start` function of the module by laying out the memories, globals
//! and tables, then emitting the translated code with hardcoded addresses to memory. //! and tables, then emitting the translated code with hardcoded addresses to memory.
use cton_wasm::{translate_module, DummyRuntime, WasmRuntime}; use cton_wasm::{translate_module, DummyEnvironment, ModuleEnvironment};
use std::path::PathBuf; use std::path::PathBuf;
use cretonne::Context; use cretonne::Context;
use cretonne::settings::FlagsOrIsa; use cretonne::settings::FlagsOrIsa;
@@ -98,8 +98,8 @@ fn handle_module(
|err| String::from(err.description()), |err| String::from(err.description()),
)?; )?;
} }
let mut dummy_runtime = DummyRuntime::with_flags(fisa.flags.clone()); let mut dummy_environ = DummyEnvironment::with_flags(fisa.flags.clone());
let translation = translate_module(&data, &mut dummy_runtime)?; translate_module(&data, &mut dummy_environ)?;
terminal.fg(term::color::GREEN).unwrap(); terminal.fg(term::color::GREEN).unwrap();
vprintln!(flag_verbose, "ok"); vprintln!(flag_verbose, "ok");
terminal.reset().unwrap(); terminal.reset().unwrap();
@@ -113,8 +113,8 @@ fn handle_module(
vprint!(flag_verbose, "Compiling... "); vprint!(flag_verbose, "Compiling... ");
} }
terminal.reset().unwrap(); terminal.reset().unwrap();
let num_func_imports = dummy_runtime.get_num_func_imports(); let num_func_imports = dummy_environ.get_num_func_imports();
for (def_index, func) in translation.functions.iter().enumerate() { for (def_index, func) in dummy_environ.info.function_bodies.iter().enumerate() {
let func_index = num_func_imports + def_index; let func_index = num_func_imports + def_index;
let mut context = Context::new(); let mut context = Context::new();
context.func = func.clone(); context.func = func.clone();
@@ -133,12 +133,12 @@ fn handle_module(
} }
if flag_print { if flag_print {
vprintln!(flag_verbose, ""); vprintln!(flag_verbose, "");
if let Some(start_func) = dummy_runtime.start_func { if let Some(start_func) = dummy_environ.info.start_func {
if func_index == start_func { if func_index == start_func {
println!("; Selected as wasm start function"); println!("; Selected as wasm start function");
} }
} }
for export_name in &dummy_runtime.functions[func_index].export_names { for export_name in &dummy_environ.info.functions[func_index].export_names {
println!("; Exported as \"{}\"", export_name); println!("; Exported as \"{}\"", export_name);
} }
println!("{}", context.func.display(fisa.isa)); println!("{}", context.func.display(fisa.isa));

View File

@@ -233,7 +233,7 @@ fn cur_srcloc(reader: &BinaryReader) -> ir::SourceLoc {
mod tests { mod tests {
use cretonne::{ir, Context}; use cretonne::{ir, Context};
use cretonne::ir::types::I32; use cretonne::ir::types::I32;
use runtime::{DummyRuntime, FuncEnvironment}; use runtime::{DummyEnvironment, FuncEnvironment};
use super::FuncTranslator; use super::FuncTranslator;
#[test] #[test]
@@ -252,7 +252,7 @@ mod tests {
]; ];
let mut trans = FuncTranslator::new(); let mut trans = FuncTranslator::new();
let mut runtime = DummyRuntime::default(); let runtime = DummyEnvironment::default();
let mut ctx = Context::new(); let mut ctx = Context::new();
ctx.func.name = ir::FunctionName::new("small1"); ctx.func.name = ir::FunctionName::new("small1");
@@ -263,9 +263,11 @@ mod tests {
ir::ArgumentType::new(I32), ir::ArgumentType::new(I32),
); );
trans.translate(&BODY, &mut ctx.func, &mut runtime).unwrap(); trans
.translate(&BODY, &mut ctx.func, &mut runtime.func_env())
.unwrap();
dbg!("{}", ctx.func.display(None)); dbg!("{}", ctx.func.display(None));
ctx.verify(runtime.flags()).unwrap(); ctx.verify(runtime.func_env().flags()).unwrap();
} }
#[test] #[test]
@@ -285,7 +287,7 @@ mod tests {
]; ];
let mut trans = FuncTranslator::new(); let mut trans = FuncTranslator::new();
let mut runtime = DummyRuntime::default(); let runtime = DummyEnvironment::default();
let mut ctx = Context::new(); let mut ctx = Context::new();
ctx.func.name = ir::FunctionName::new("small2"); ctx.func.name = ir::FunctionName::new("small2");
@@ -296,9 +298,11 @@ mod tests {
ir::ArgumentType::new(I32), ir::ArgumentType::new(I32),
); );
trans.translate(&BODY, &mut ctx.func, &mut runtime).unwrap(); trans
.translate(&BODY, &mut ctx.func, &mut runtime.func_env())
.unwrap();
dbg!("{}", ctx.func.display(None)); dbg!("{}", ctx.func.display(None));
ctx.verify(runtime.flags()).unwrap(); ctx.verify(runtime.func_env().flags()).unwrap();
} }
#[test] #[test]
@@ -327,7 +331,7 @@ mod tests {
]; ];
let mut trans = FuncTranslator::new(); let mut trans = FuncTranslator::new();
let mut runtime = DummyRuntime::default(); let runtime = DummyEnvironment::default();
let mut ctx = Context::new(); let mut ctx = Context::new();
ctx.func.name = ir::FunctionName::new("infloop"); ctx.func.name = ir::FunctionName::new("infloop");
@@ -335,8 +339,10 @@ mod tests {
ir::ArgumentType::new(I32), ir::ArgumentType::new(I32),
); );
trans.translate(&BODY, &mut ctx.func, &mut runtime).unwrap(); trans
.translate(&BODY, &mut ctx.func, &mut runtime.func_env())
.unwrap();
dbg!("{}", ctx.func.display(None)); dbg!("{}", ctx.func.display(None));
ctx.verify(runtime.flags()).unwrap(); ctx.verify(runtime.func_env().flags()).unwrap();
} }
} }

View File

@@ -1,12 +1,10 @@
//! Performs the translation from a wasm module in binary format to the in-memory representation //! Performs the translation from a wasm module in binary format to the in-memory representation
//! of the Cretonne IL. More particularly, it translates the code of all the functions bodies and //! of the Cretonne IL. More particularly, it translates the code of all the functions bodies and
//! interacts with a runtime implementing the [`WasmRuntime`](trait.WasmRuntime.html) trait to //! interacts with a runtime implementing the [`ModuleEnvironment`](trait.ModuleEnvironment.html)
//! deal with tables, globals and linear memory. //! trait to deal with tables, globals and linear memory.
//! //!
//! The crate provides a `DummyRuntime` trait that will allow to translate the code of the //! The crate provides a `DummyEnvironment` struct that will allow to translate the code of the
//! functions but will fail at execution. You should use //! functions but will fail at execution.
//! [`wasmstandalone::StandaloneRuntime`](../wasmstandalone/struct.StandaloneRuntime.html) to be
//! able to execute the translated code.
//! //!
//! The main function of this module is [`translate_module`](fn.translate_module.html). //! The main function of this module is [`translate_module`](fn.translate_module.html).
@@ -26,7 +24,7 @@ mod state;
mod translation_utils; mod translation_utils;
pub use func_translator::FuncTranslator; pub use func_translator::FuncTranslator;
pub use module_translator::{translate_module, TranslationResult}; pub use module_translator::translate_module;
pub use runtime::{FuncEnvironment, WasmRuntime, DummyRuntime, GlobalValue}; pub use runtime::{FuncEnvironment, ModuleEnvironment, DummyEnvironment, GlobalValue};
pub use translation_utils::{FunctionIndex, GlobalIndex, TableIndex, MemoryIndex, SignatureIndex, pub use translation_utils::{FunctionIndex, GlobalIndex, TableIndex, MemoryIndex, SignatureIndex,
Global, GlobalInit, Table, Memory}; Global, GlobalInit, Table, Memory};

View File

@@ -5,25 +5,16 @@ use sections_translator::{SectionParsingError, parse_function_signatures, parse_
parse_function_section, parse_export_section, parse_start_section, parse_function_section, parse_export_section, parse_start_section,
parse_memory_section, parse_global_section, parse_table_section, parse_memory_section, parse_global_section, parse_table_section,
parse_elements_section, parse_data_section}; parse_elements_section, parse_data_section};
use cretonne::ir::Function; use runtime::ModuleEnvironment;
use func_translator::FuncTranslator;
use std::error::Error;
use runtime::WasmRuntime;
/// Output of the [`translate_module`](fn.translate_module.html) function.
pub struct TranslationResult {
/// The translated functions.
pub functions: Vec<Function>,
}
/// Translate a sequence of bytes forming a valid Wasm binary into a list of valid Cretonne IL /// Translate a sequence of bytes forming a valid Wasm binary into a list of valid Cretonne IL
/// [`Function`](../cretonne/ir/function/struct.Function.html). /// [`Function`](../cretonne/ir/function/struct.Function.html).
/// Returns the functions and also the mappings for imported functions and signature between the /// Returns the functions and also the mappings for imported functions and signature between the
/// indexes in the wasm module and the indexes inside each functions. /// indexes in the wasm module and the indexes inside each functions.
pub fn translate_module( pub fn translate_module<'data>(
data: &[u8], data: &'data [u8],
runtime: &mut WasmRuntime, environ: &mut ModuleEnvironment,
) -> Result<TranslationResult, String> { ) -> Result<(), String> {
let mut parser = Parser::new(data); let mut parser = Parser::new(data);
match *parser.read() { match *parser.read() {
ParserState::BeginWasm { .. } => {} ParserState::BeginWasm { .. } => {}
@@ -36,7 +27,7 @@ pub fn translate_module(
loop { loop {
match *parser.read_with_input(next_input) { match *parser.read_with_input(next_input) {
ParserState::BeginSection { code: SectionCode::Type, .. } => { ParserState::BeginSection { code: SectionCode::Type, .. } => {
match parse_function_signatures(&mut parser, runtime) { match parse_function_signatures(&mut parser, environ) {
Ok(()) => (), Ok(()) => (),
Err(SectionParsingError::WrongSectionContent(s)) => { Err(SectionParsingError::WrongSectionContent(s)) => {
return Err(format!("wrong content in the type section: {}", s)) return Err(format!("wrong content in the type section: {}", s))
@@ -45,7 +36,7 @@ pub fn translate_module(
next_input = ParserInput::Default; next_input = ParserInput::Default;
} }
ParserState::BeginSection { code: SectionCode::Import, .. } => { ParserState::BeginSection { code: SectionCode::Import, .. } => {
match parse_import_section(&mut parser, runtime) { match parse_import_section(&mut parser, environ) {
Ok(()) => {} Ok(()) => {}
Err(SectionParsingError::WrongSectionContent(s)) => { Err(SectionParsingError::WrongSectionContent(s)) => {
return Err(format!("wrong content in the import section: {}", s)) return Err(format!("wrong content in the import section: {}", s))
@@ -54,7 +45,7 @@ pub fn translate_module(
next_input = ParserInput::Default; next_input = ParserInput::Default;
} }
ParserState::BeginSection { code: SectionCode::Function, .. } => { ParserState::BeginSection { code: SectionCode::Function, .. } => {
match parse_function_section(&mut parser, runtime) { match parse_function_section(&mut parser, environ) {
Ok(()) => {} Ok(()) => {}
Err(SectionParsingError::WrongSectionContent(s)) => { Err(SectionParsingError::WrongSectionContent(s)) => {
return Err(format!("wrong content in the function section: {}", s)) return Err(format!("wrong content in the function section: {}", s))
@@ -63,7 +54,7 @@ pub fn translate_module(
next_input = ParserInput::Default; next_input = ParserInput::Default;
} }
ParserState::BeginSection { code: SectionCode::Table, .. } => { ParserState::BeginSection { code: SectionCode::Table, .. } => {
match parse_table_section(&mut parser, runtime) { match parse_table_section(&mut parser, environ) {
Ok(()) => (), Ok(()) => (),
Err(SectionParsingError::WrongSectionContent(s)) => { Err(SectionParsingError::WrongSectionContent(s)) => {
return Err(format!("wrong content in the table section: {}", s)) return Err(format!("wrong content in the table section: {}", s))
@@ -71,7 +62,7 @@ pub fn translate_module(
} }
} }
ParserState::BeginSection { code: SectionCode::Memory, .. } => { ParserState::BeginSection { code: SectionCode::Memory, .. } => {
match parse_memory_section(&mut parser, runtime) { match parse_memory_section(&mut parser, environ) {
Ok(()) => {} Ok(()) => {}
Err(SectionParsingError::WrongSectionContent(s)) => { Err(SectionParsingError::WrongSectionContent(s)) => {
return Err(format!("wrong content in the memory section: {}", s)) return Err(format!("wrong content in the memory section: {}", s))
@@ -80,7 +71,7 @@ pub fn translate_module(
next_input = ParserInput::Default; next_input = ParserInput::Default;
} }
ParserState::BeginSection { code: SectionCode::Global, .. } => { ParserState::BeginSection { code: SectionCode::Global, .. } => {
match parse_global_section(&mut parser, runtime) { match parse_global_section(&mut parser, environ) {
Ok(()) => {} Ok(()) => {}
Err(SectionParsingError::WrongSectionContent(s)) => { Err(SectionParsingError::WrongSectionContent(s)) => {
return Err(format!("wrong content in the global section: {}", s)) return Err(format!("wrong content in the global section: {}", s))
@@ -89,7 +80,7 @@ pub fn translate_module(
next_input = ParserInput::Default; next_input = ParserInput::Default;
} }
ParserState::BeginSection { code: SectionCode::Export, .. } => { ParserState::BeginSection { code: SectionCode::Export, .. } => {
match parse_export_section(&mut parser, runtime) { match parse_export_section(&mut parser, environ) {
Ok(()) => {} Ok(()) => {}
Err(SectionParsingError::WrongSectionContent(s)) => { Err(SectionParsingError::WrongSectionContent(s)) => {
return Err(format!("wrong content in the export section: {}", s)) return Err(format!("wrong content in the export section: {}", s))
@@ -98,7 +89,7 @@ pub fn translate_module(
next_input = ParserInput::Default; next_input = ParserInput::Default;
} }
ParserState::BeginSection { code: SectionCode::Start, .. } => { ParserState::BeginSection { code: SectionCode::Start, .. } => {
match parse_start_section(&mut parser, runtime) { match parse_start_section(&mut parser, environ) {
Ok(()) => (), Ok(()) => (),
Err(SectionParsingError::WrongSectionContent(s)) => { Err(SectionParsingError::WrongSectionContent(s)) => {
return Err(format!("wrong content in the start section: {}", s)) return Err(format!("wrong content in the start section: {}", s))
@@ -107,7 +98,7 @@ pub fn translate_module(
next_input = ParserInput::Default; next_input = ParserInput::Default;
} }
ParserState::BeginSection { code: SectionCode::Element, .. } => { ParserState::BeginSection { code: SectionCode::Element, .. } => {
match parse_elements_section(&mut parser, runtime) { match parse_elements_section(&mut parser, environ) {
Ok(()) => (), Ok(()) => (),
Err(SectionParsingError::WrongSectionContent(s)) => { Err(SectionParsingError::WrongSectionContent(s)) => {
return Err(format!("wrong content in the element section: {}", s)) return Err(format!("wrong content in the element section: {}", s))
@@ -122,9 +113,9 @@ pub fn translate_module(
ParserState::EndSection => { ParserState::EndSection => {
next_input = ParserInput::Default; next_input = ParserInput::Default;
} }
ParserState::EndWasm => return Ok(TranslationResult { functions: Vec::new() }), ParserState::EndWasm => return Ok(()),
ParserState::BeginSection { code: SectionCode::Data, .. } => { ParserState::BeginSection { code: SectionCode::Data, .. } => {
match parse_data_section(&mut parser, runtime) { match parse_data_section(&mut parser, environ) {
Ok(()) => (), Ok(()) => (),
Err(SectionParsingError::WrongSectionContent(s)) => { Err(SectionParsingError::WrongSectionContent(s)) => {
return Err(format!("wrong content in the data section: {}", s)) return Err(format!("wrong content in the data section: {}", s))
@@ -135,41 +126,33 @@ pub fn translate_module(
}; };
} }
// At this point we've entered the code section // At this point we've entered the code section
let num_func_imports = runtime.get_num_func_imports();
let mut il_functions: Vec<Function> = Vec::new();
let mut trans = FuncTranslator::new();
runtime.begin_translation();
loop { loop {
match *parser.read() { match *parser.read() {
ParserState::BeginFunctionBody { .. } => {} ParserState::BeginFunctionBody { .. } => {}
ParserState::EndSection => break, ParserState::EndSection => break,
_ => return Err(String::from("wrong content in code section")), _ => return Err(String::from("wrong content in code section")),
} }
runtime.next_function(); let mut reader = parser.create_binary_reader();
// First we build the Function object with its name and signature let size = reader.bytes_remaining();
let mut func = Function::new(); environ.define_function_body(
let function_index = num_func_imports + il_functions.len(); reader.read_bytes(size).map_err(|e| {
func.signature = runtime format!("at offset {}: {}", e.offset, e.message)
.get_signature(runtime.get_func_type(function_index)) })?,
.clone(); )?;
func.name = runtime.get_func_name(function_index);
trans
.translate_from_reader(parser.create_binary_reader(), &mut func, runtime)
.map_err(|e| String::from(e.description()))?;
il_functions.push(func);
} }
loop { loop {
match *parser.read() { match *parser.read() {
ParserState::BeginSection { code: SectionCode::Data, .. } => { ParserState::BeginSection { code: SectionCode::Data, .. } => {
match parse_data_section(&mut parser, runtime) { match parse_data_section(&mut parser, environ) {
Ok(()) => (), Ok(()) => (),
Err(SectionParsingError::WrongSectionContent(s)) => { Err(SectionParsingError::WrongSectionContent(s)) => {
return Err(format!("wrong content in the data section: {}", s)) return Err(format!("wrong content in the data section: {}", s))
} }
} }
} }
ParserState::EndWasm => return Ok(TranslationResult { functions: il_functions }), ParserState::EndWasm => break,
_ => (), _ => (),
} }
} }
Ok(())
} }

View File

@@ -1,10 +1,18 @@
use runtime::{FuncEnvironment, GlobalValue, WasmRuntime}; use runtime::{FuncEnvironment, GlobalValue, ModuleEnvironment};
use translation_utils::{Global, Memory, Table, GlobalIndex, TableIndex, SignatureIndex, use translation_utils::{Global, Memory, Table, GlobalIndex, TableIndex, SignatureIndex,
FunctionIndex, MemoryIndex}; FunctionIndex, MemoryIndex};
use func_translator::FuncTranslator;
use cretonne::ir::{self, InstBuilder}; use cretonne::ir::{self, InstBuilder};
use cretonne::ir::types::*; use cretonne::ir::types::*;
use cretonne::cursor::FuncCursor; use cretonne::cursor::FuncCursor;
use cretonne::settings; use cretonne::settings;
use wasmparser;
use std::error::Error;
/// Compute a `ir::FunctionName` for a given wasm function index.
fn get_func_name(func_index: FunctionIndex) -> ir::FunctionName {
ir::FunctionName::new(format!("wasm_0x{:x}", func_index))
}
/// A collection of names under which a given entity is exported. /// A collection of names under which a given entity is exported.
pub struct Exportable<T> { pub struct Exportable<T> {
@@ -24,10 +32,10 @@ impl<T> Exportable<T> {
} }
} }
/// This runtime implementation is a "naïve" one, doing essentially nothing and emitting /// The main state belonging to a `DummyEnvironment`. This is split out from
/// placeholders when forced to. Don't try to execute code translated with this runtime, it is /// `DummyEnvironment` to allow it to be borrowed separately from the
/// essentially here for translation debug purposes. /// `FuncTranslator` field.
pub struct DummyRuntime { pub struct DummyModuleInfo {
/// Compilation setting flags. /// Compilation setting flags.
pub flags: settings::Flags, pub flags: settings::Flags,
@@ -40,6 +48,9 @@ pub struct DummyRuntime {
/// Functions, imported and local. /// Functions, imported and local.
pub functions: Vec<Exportable<SignatureIndex>>, pub functions: Vec<Exportable<SignatureIndex>>,
/// Function bodies.
pub function_bodies: Vec<ir::Function>,
/// Tables as provided by `declare_table`. /// Tables as provided by `declare_table`.
pub tables: Vec<Exportable<Table>>, pub tables: Vec<Exportable<Table>>,
@@ -53,12 +64,7 @@ pub struct DummyRuntime {
pub start_func: Option<FunctionIndex>, pub start_func: Option<FunctionIndex>,
} }
impl DummyRuntime { impl DummyModuleInfo {
/// Allocates the runtime data structures with default flags.
pub fn default() -> Self {
Self::with_flags(settings::Flags::new(&settings::builder()))
}
/// Allocates the runtime data structures with the given flags. /// Allocates the runtime data structures with the given flags.
pub fn with_flags(flags: settings::Flags) -> Self { pub fn with_flags(flags: settings::Flags) -> Self {
Self { Self {
@@ -66,6 +72,7 @@ impl DummyRuntime {
signatures: Vec::new(), signatures: Vec::new(),
imported_funcs: Vec::new(), imported_funcs: Vec::new(),
functions: Vec::new(), functions: Vec::new(),
function_bodies: Vec::new(),
tables: Vec::new(), tables: Vec::new(),
memories: Vec::new(), memories: Vec::new(),
globals: Vec::new(), globals: Vec::new(),
@@ -74,9 +81,52 @@ impl DummyRuntime {
} }
} }
impl FuncEnvironment for DummyRuntime { /// This runtime implementation is a "naïve" one, doing essentially nothing and emitting
/// placeholders when forced to. Don't try to execute code translated with this runtime, it is
/// essentially here for translation debug purposes.
pub struct DummyEnvironment {
/// Module information.
pub info: DummyModuleInfo,
/// Function translation.
trans: FuncTranslator,
}
impl DummyEnvironment {
/// Allocates the runtime data structures with default flags.
pub fn default() -> Self {
Self::with_flags(settings::Flags::new(&settings::builder()))
}
/// Allocates the runtime data structures with the given flags.
pub fn with_flags(flags: settings::Flags) -> Self {
Self {
info: DummyModuleInfo::with_flags(flags),
trans: FuncTranslator::new(),
}
}
/// Return a `DummyFuncEnvironment` for translating functions within this
/// `DummyEnvironment`.
pub fn func_env(&self) -> DummyFuncEnvironment {
DummyFuncEnvironment::new(&self.info)
}
}
/// The FuncEnvironment implementation for use by the DummyEnvironment.
pub struct DummyFuncEnvironment<'dummy_environment> {
pub mod_info: &'dummy_environment DummyModuleInfo,
}
impl<'dummy_environment> DummyFuncEnvironment<'dummy_environment> {
pub fn new(mod_info: &'dummy_environment DummyModuleInfo) -> Self {
Self { mod_info }
}
}
impl<'dummy_environment> FuncEnvironment for DummyFuncEnvironment<'dummy_environment> {
fn flags(&self) -> &settings::Flags { fn flags(&self) -> &settings::Flags {
&self.flags &self.mod_info.flags
} }
fn make_global(&mut self, func: &mut ir::Function, index: GlobalIndex) -> GlobalValue { fn make_global(&mut self, func: &mut ir::Function, index: GlobalIndex) -> GlobalValue {
@@ -85,7 +135,7 @@ impl FuncEnvironment for DummyRuntime {
let gv = func.create_global_var(ir::GlobalVarData::VmCtx { offset }); let gv = func.create_global_var(ir::GlobalVarData::VmCtx { offset });
GlobalValue::Memory { GlobalValue::Memory {
gv, gv,
ty: self.globals[index].entity.ty, ty: self.mod_info.globals[index].entity.ty,
} }
} }
@@ -101,15 +151,15 @@ impl FuncEnvironment for DummyRuntime {
fn make_indirect_sig(&mut self, func: &mut ir::Function, index: SignatureIndex) -> ir::SigRef { fn make_indirect_sig(&mut self, func: &mut ir::Function, index: SignatureIndex) -> ir::SigRef {
// A real implementation would probably change the calling convention and add `vmctx` and // A real implementation would probably change the calling convention and add `vmctx` and
// signature index arguments. // signature index arguments.
func.import_signature(self.signatures[index].clone()) func.import_signature(self.mod_info.signatures[index].clone())
} }
fn make_direct_func(&mut self, func: &mut ir::Function, index: FunctionIndex) -> ir::FuncRef { fn make_direct_func(&mut self, func: &mut ir::Function, index: FunctionIndex) -> ir::FuncRef {
let sigidx = self.functions[index].entity; let sigidx = self.mod_info.functions[index].entity;
// A real implementation would probably add a `vmctx` argument. // A real implementation would probably add a `vmctx` argument.
// And maybe attempt some signature de-duplication. // And maybe attempt some signature de-duplication.
let signature = func.import_signature(self.signatures[sigidx].clone()); let signature = func.import_signature(self.mod_info.signatures[sigidx].clone());
let name = self.get_func_name(index); let name = get_func_name(index);
func.import_function(ir::ExtFuncData { name, signature }) func.import_function(ir::ExtFuncData { name, signature })
} }
@@ -145,54 +195,59 @@ impl FuncEnvironment for DummyRuntime {
} }
} }
impl WasmRuntime for DummyRuntime { impl ModuleEnvironment for DummyEnvironment {
fn get_func_name(&self, func_index: FunctionIndex) -> ir::FunctionName { fn get_func_name(&self, func_index: FunctionIndex) -> ir::FunctionName {
ir::FunctionName::new(format!("wasm_0x{:x}", func_index)) get_func_name(func_index)
} }
fn declare_signature(&mut self, sig: &ir::Signature) { fn declare_signature(&mut self, sig: &ir::Signature) {
self.signatures.push(sig.clone()); self.info.signatures.push(sig.clone());
} }
fn get_signature(&self, sig_index: SignatureIndex) -> &ir::Signature { fn get_signature(&self, sig_index: SignatureIndex) -> &ir::Signature {
&self.signatures[sig_index] &self.info.signatures[sig_index]
} }
fn declare_func_import(&mut self, sig_index: SignatureIndex, module: &str, field: &str) { fn declare_func_import<'data>(
&mut self,
sig_index: SignatureIndex,
module: &'data str,
field: &'data str,
) {
assert_eq!( assert_eq!(
self.functions.len(), self.info.functions.len(),
self.imported_funcs.len(), self.info.imported_funcs.len(),
"Imported functions must be declared first" "Imported functions must be declared first"
); );
self.functions.push(Exportable::new(sig_index)); self.info.functions.push(Exportable::new(sig_index));
self.imported_funcs.push(( self.info.imported_funcs.push((
String::from(module), String::from(module),
String::from(field), String::from(field),
)); ));
} }
fn get_num_func_imports(&self) -> usize { fn get_num_func_imports(&self) -> usize {
self.imported_funcs.len() self.info.imported_funcs.len()
} }
fn declare_func_type(&mut self, sig_index: SignatureIndex) { fn declare_func_type(&mut self, sig_index: SignatureIndex) {
self.functions.push(Exportable::new(sig_index)); self.info.functions.push(Exportable::new(sig_index));
} }
fn get_func_type(&self, func_index: FunctionIndex) -> SignatureIndex { fn get_func_type(&self, func_index: FunctionIndex) -> SignatureIndex {
self.functions[func_index].entity self.info.functions[func_index].entity
} }
fn declare_global(&mut self, global: Global) { fn declare_global(&mut self, global: Global) {
self.globals.push(Exportable::new(global)); self.info.globals.push(Exportable::new(global));
} }
fn get_global(&self, global_index: GlobalIndex) -> &Global { fn get_global(&self, global_index: GlobalIndex) -> &Global {
&self.globals[global_index].entity &self.info.globals[global_index].entity
} }
fn declare_table(&mut self, table: Table) { fn declare_table(&mut self, table: Table) {
self.tables.push(Exportable::new(table)); self.info.tables.push(Exportable::new(table));
} }
fn declare_table_elements( fn declare_table_elements(
&mut self, &mut self,
@@ -204,51 +259,68 @@ impl WasmRuntime for DummyRuntime {
// We do nothing // We do nothing
} }
fn declare_memory(&mut self, memory: Memory) { fn declare_memory(&mut self, memory: Memory) {
self.memories.push(Exportable::new(memory)); self.info.memories.push(Exportable::new(memory));
} }
fn declare_data_initialization( fn declare_data_initialization<'data>(
&mut self, &mut self,
_memory_index: MemoryIndex, _memory_index: MemoryIndex,
_base: Option<GlobalIndex>, _base: Option<GlobalIndex>,
_offset: usize, _offset: usize,
_data: &[u8], _data: &'data [u8],
) { ) {
// We do nothing // We do nothing
} }
fn declare_func_export(&mut self, func_index: FunctionIndex, name: &str) { fn declare_func_export<'data>(&mut self, func_index: FunctionIndex, name: &'data str) {
self.functions[func_index].export_names.push( self.info.functions[func_index].export_names.push(
String::from(
name,
),
);
}
fn declare_table_export<'data>(&mut self, table_index: TableIndex, name: &'data str) {
self.info.tables[table_index].export_names.push(
String::from(name), String::from(name),
); );
} }
fn declare_table_export(&mut self, table_index: TableIndex, name: &str) { fn declare_memory_export<'data>(&mut self, memory_index: MemoryIndex, name: &'data str) {
self.tables[table_index].export_names.push( self.info.memories[memory_index].export_names.push(
String::from(name), String::from(
name,
),
); );
} }
fn declare_memory_export(&mut self, memory_index: MemoryIndex, name: &str) { fn declare_global_export<'data>(&mut self, global_index: GlobalIndex, name: &'data str) {
self.memories[memory_index].export_names.push( self.info.globals[global_index].export_names.push(
String::from(name), String::from(
); name,
} ),
fn declare_global_export(&mut self, global_index: GlobalIndex, name: &str) {
self.globals[global_index].export_names.push(
String::from(name),
); );
} }
fn declare_start_func(&mut self, func_index: FunctionIndex) { fn declare_start_func(&mut self, func_index: FunctionIndex) {
debug_assert!(self.start_func.is_none()); debug_assert!(self.info.start_func.is_none());
self.start_func = Some(func_index); self.info.start_func = Some(func_index);
} }
fn begin_translation(&mut self) { /// Provides the contents of a function body.
// We do nothing fn define_function_body<'data>(&mut self, body_bytes: &'data [u8]) -> Result<(), String> {
let function_index = self.get_num_func_imports() + self.info.function_bodies.len();
let name = get_func_name(function_index);
let sig = self.get_signature(self.get_func_type(function_index))
.clone();
let mut func = ir::Function::with_name_signature(name, sig);
{
let mut func_environ = DummyFuncEnvironment::new(&self.info);
let reader = wasmparser::BinaryReader::new(body_bytes);
self.trans
.translate_from_reader(reader, &mut func, &mut func_environ)
.map_err(|e| String::from(e.description()))?;
} }
fn next_function(&mut self) { self.info.function_bodies.push(func);
// We do nothing Ok(())
} }
} }

View File

@@ -1,5 +1,5 @@
mod spec; mod spec;
mod dummy; mod dummy;
pub use runtime::spec::{WasmRuntime, FuncEnvironment, GlobalValue}; pub use runtime::spec::{ModuleEnvironment, FuncEnvironment, GlobalValue};
pub use runtime::dummy::DummyRuntime; pub use runtime::dummy::DummyEnvironment;

View File

@@ -1,5 +1,5 @@
//! All the runtime support necessary for the wasm to cretonne translation is formalized by the //! All the runtime support necessary for the wasm to cretonne translation is formalized by the
//! trait `WasmRuntime`. //! traits `FunctionEnvironment` and `ModuleEnvironment`.
use cretonne::ir::{self, InstBuilder}; use cretonne::ir::{self, InstBuilder};
use cretonne::cursor::FuncCursor; use cretonne::cursor::FuncCursor;
use cretonne::settings::Flags; use cretonne::settings::Flags;
@@ -146,21 +146,26 @@ pub trait FuncEnvironment {
) -> ir::Value; ) -> ir::Value;
} }
/// An object satisfyng the `WasmRuntime` trait can be passed as argument to the /// An object satisfyng the `ModuleEnvironment` trait can be passed as argument to the
/// [`translate_module`](fn.translate_module.html) function. These methods should not be called /// [`translate_module`](fn.translate_module.html) function. These methods should not be called
/// by the user, they are only for `cretonne-wasm` internal use. /// by the user, they are only for `cretonne-wasm` internal use.
pub trait WasmRuntime: FuncEnvironment { pub trait ModuleEnvironment {
/// Return the name for the given function index. /// Return the name for the given function index.
fn get_func_name(&self, func_index: FunctionIndex) -> ir::FunctionName; fn get_func_name(&self, func_index: FunctionIndex) -> ir::FunctionName;
/// Declares a function signature to the runtime. /// Declares a function signature to the environment.
fn declare_signature(&mut self, sig: &ir::Signature); fn declare_signature(&mut self, sig: &ir::Signature);
/// Return the signature with the given index. /// Return the signature with the given index.
fn get_signature(&self, sig_index: SignatureIndex) -> &ir::Signature; fn get_signature(&self, sig_index: SignatureIndex) -> &ir::Signature;
/// Declares a function import to the runtime. /// Declares a function import to the environment.
fn declare_func_import(&mut self, sig_index: SignatureIndex, module: &str, field: &str); fn declare_func_import<'data>(
&mut self,
sig_index: SignatureIndex,
module: &'data str,
field: &'data str,
);
/// Return the number of imported funcs. /// Return the number of imported funcs.
fn get_num_func_imports(&self) -> usize; fn get_num_func_imports(&self) -> usize;
@@ -171,13 +176,13 @@ pub trait WasmRuntime: FuncEnvironment {
/// Return the signature index for the given function index. /// Return the signature index for the given function index.
fn get_func_type(&self, func_index: FunctionIndex) -> SignatureIndex; fn get_func_type(&self, func_index: FunctionIndex) -> SignatureIndex;
/// Declares a global to the runtime. /// Declares a global to the environment.
fn declare_global(&mut self, global: Global); fn declare_global(&mut self, global: Global);
/// Return the global for the given global index. /// Return the global for the given global index.
fn get_global(&self, global_index: GlobalIndex) -> &Global; fn get_global(&self, global_index: GlobalIndex) -> &Global;
/// Declares a table to the runtime. /// Declares a table to the environment.
fn declare_table(&mut self, table: Table); fn declare_table(&mut self, table: Table);
/// Fills a declared table with references to functions in the module. /// Fills a declared table with references to functions in the module.
fn declare_table_elements( fn declare_table_elements(
@@ -187,32 +192,29 @@ pub trait WasmRuntime: FuncEnvironment {
offset: usize, offset: usize,
elements: &[FunctionIndex], elements: &[FunctionIndex],
); );
/// Declares a memory to the runtime /// Declares a memory to the environment
fn declare_memory(&mut self, memory: Memory); fn declare_memory(&mut self, memory: Memory);
/// Fills a declared memory with bytes at module instantiation. /// Fills a declared memory with bytes at module instantiation.
fn declare_data_initialization( fn declare_data_initialization<'data>(
&mut self, &mut self,
memory_index: MemoryIndex, memory_index: MemoryIndex,
base: Option<GlobalIndex>, base: Option<GlobalIndex>,
offset: usize, offset: usize,
data: &[u8], data: &'data [u8],
); );
/// Declares a function export to the runtime. /// Declares a function export to the environment.
fn declare_func_export(&mut self, func_index: FunctionIndex, name: &str); fn declare_func_export<'data>(&mut self, func_index: FunctionIndex, name: &'data str);
/// Declares a table export to the runtime. /// Declares a table export to the environment.
fn declare_table_export(&mut self, table_index: TableIndex, name: &str); fn declare_table_export<'data>(&mut self, table_index: TableIndex, name: &'data str);
/// Declares a memory export to the runtime. /// Declares a memory export to the environment.
fn declare_memory_export(&mut self, memory_index: MemoryIndex, name: &str); fn declare_memory_export<'data>(&mut self, memory_index: MemoryIndex, name: &'data str);
/// Declares a global export to the runtime. /// Declares a global export to the environment.
fn declare_global_export(&mut self, global_index: GlobalIndex, name: &str); fn declare_global_export<'data>(&mut self, global_index: GlobalIndex, name: &'data str);
/// Declares a start function. /// Declares a start function.
fn declare_start_func(&mut self, index: FunctionIndex); fn declare_start_func(&mut self, index: FunctionIndex);
/// Call this function after having declared all the runtime elements but prior to the /// Provides the contents of a function body.
/// function body translation. fn define_function_body<'data>(&mut self, body_bytes: &'data [u8]) -> Result<(), String>;
fn begin_translation(&mut self);
/// Call this function between each function body translation.
fn next_function(&mut self);
} }

View File

@@ -15,7 +15,7 @@ use wasmparser::{Parser, ParserState, FuncType, ImportSectionEntryType, External
MemoryType, Operator}; MemoryType, Operator};
use wasmparser; use wasmparser;
use std::str::from_utf8; use std::str::from_utf8;
use runtime::WasmRuntime; use runtime::ModuleEnvironment;
pub enum SectionParsingError { pub enum SectionParsingError {
WrongSectionContent(String), WrongSectionContent(String),
@@ -24,7 +24,7 @@ pub enum SectionParsingError {
/// Reads the Type Section of the wasm module and returns the corresponding function signatures. /// Reads the Type Section of the wasm module and returns the corresponding function signatures.
pub fn parse_function_signatures( pub fn parse_function_signatures(
parser: &mut Parser, parser: &mut Parser,
runtime: &mut WasmRuntime, environ: &mut ModuleEnvironment,
) -> Result<(), SectionParsingError> { ) -> Result<(), SectionParsingError> {
loop { loop {
match *parser.read() { match *parser.read() {
@@ -47,7 +47,7 @@ pub fn parse_function_signatures(
); );
ArgumentType::new(cret_arg) ArgumentType::new(cret_arg)
})); }));
runtime.declare_signature(&sig); environ.declare_signature(&sig);
} }
ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))), ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))),
} }
@@ -58,7 +58,7 @@ pub fn parse_function_signatures(
/// Retrieves the imports from the imports section of the binary. /// Retrieves the imports from the imports section of the binary.
pub fn parse_import_section( pub fn parse_import_section(
parser: &mut Parser, parser: &mut Parser,
runtime: &mut WasmRuntime, environ: &mut ModuleEnvironment,
) -> Result<(), SectionParsingError> { ) -> Result<(), SectionParsingError> {
loop { loop {
match *parser.read() { match *parser.read() {
@@ -72,12 +72,12 @@ pub fn parse_import_section(
// becomes a concern here. // becomes a concern here.
let module_name = from_utf8(module).unwrap(); let module_name = from_utf8(module).unwrap();
let field_name = from_utf8(field).unwrap(); let field_name = from_utf8(field).unwrap();
runtime.declare_func_import(sig as SignatureIndex, module_name, field_name); environ.declare_func_import(sig as SignatureIndex, module_name, field_name);
} }
ParserState::ImportSectionEntry { ParserState::ImportSectionEntry {
ty: ImportSectionEntryType::Memory(MemoryType { limits: ref memlimits }), .. ty: ImportSectionEntryType::Memory(MemoryType { limits: ref memlimits }), ..
} => { } => {
runtime.declare_memory(Memory { environ.declare_memory(Memory {
pages_count: memlimits.initial as usize, pages_count: memlimits.initial as usize,
maximum: memlimits.maximum.map(|x| x as usize), maximum: memlimits.maximum.map(|x| x as usize),
}); });
@@ -85,7 +85,7 @@ pub fn parse_import_section(
ParserState::ImportSectionEntry { ParserState::ImportSectionEntry {
ty: ImportSectionEntryType::Global(ref ty), .. ty: ImportSectionEntryType::Global(ref ty), ..
} => { } => {
runtime.declare_global(Global { environ.declare_global(Global {
ty: type_to_type(&ty.content_type).unwrap(), ty: type_to_type(&ty.content_type).unwrap(),
mutability: ty.mutable, mutability: ty.mutable,
initializer: GlobalInit::Import(), initializer: GlobalInit::Import(),
@@ -94,7 +94,7 @@ pub fn parse_import_section(
ParserState::ImportSectionEntry { ParserState::ImportSectionEntry {
ty: ImportSectionEntryType::Table(ref tab), .. ty: ImportSectionEntryType::Table(ref tab), ..
} => { } => {
runtime.declare_table(Table { environ.declare_table(Table {
ty: match type_to_type(&tab.element_type) { ty: match type_to_type(&tab.element_type) {
Ok(t) => TableElementType::Val(t), Ok(t) => TableElementType::Val(t),
Err(()) => TableElementType::Func(), Err(()) => TableElementType::Func(),
@@ -113,12 +113,12 @@ pub fn parse_import_section(
/// Retrieves the correspondances between functions and signatures from the function section /// Retrieves the correspondances between functions and signatures from the function section
pub fn parse_function_section( pub fn parse_function_section(
parser: &mut Parser, parser: &mut Parser,
runtime: &mut WasmRuntime, environ: &mut ModuleEnvironment,
) -> Result<(), SectionParsingError> { ) -> Result<(), SectionParsingError> {
loop { loop {
match *parser.read() { match *parser.read() {
ParserState::FunctionSectionEntry(sigindex) => { ParserState::FunctionSectionEntry(sigindex) => {
runtime.declare_func_type(sigindex as SignatureIndex); environ.declare_func_type(sigindex as SignatureIndex);
} }
ParserState::EndSection => break, ParserState::EndSection => break,
ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))), ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))),
@@ -130,7 +130,7 @@ pub fn parse_function_section(
/// Retrieves the names of the functions from the export section /// Retrieves the names of the functions from the export section
pub fn parse_export_section( pub fn parse_export_section(
parser: &mut Parser, parser: &mut Parser,
runtime: &mut WasmRuntime, environ: &mut ModuleEnvironment,
) -> Result<(), SectionParsingError> { ) -> Result<(), SectionParsingError> {
loop { loop {
match *parser.read() { match *parser.read() {
@@ -145,10 +145,10 @@ pub fn parse_export_section(
let name = from_utf8(field).unwrap(); let name = from_utf8(field).unwrap();
let func_index = index as FunctionIndex; let func_index = index as FunctionIndex;
match *kind { match *kind {
ExternalKind::Function => runtime.declare_func_export(func_index, name), ExternalKind::Function => environ.declare_func_export(func_index, name),
ExternalKind::Table => runtime.declare_table_export(func_index, name), ExternalKind::Table => environ.declare_table_export(func_index, name),
ExternalKind::Memory => runtime.declare_memory_export(func_index, name), ExternalKind::Memory => environ.declare_memory_export(func_index, name),
ExternalKind::Global => runtime.declare_global_export(func_index, name), ExternalKind::Global => environ.declare_global_export(func_index, name),
} }
} }
ParserState::EndSection => break, ParserState::EndSection => break,
@@ -161,12 +161,12 @@ pub fn parse_export_section(
/// Retrieves the start function index from the start section /// Retrieves the start function index from the start section
pub fn parse_start_section( pub fn parse_start_section(
parser: &mut Parser, parser: &mut Parser,
runtime: &mut WasmRuntime, environ: &mut ModuleEnvironment,
) -> Result<(), SectionParsingError> { ) -> Result<(), SectionParsingError> {
loop { loop {
match *parser.read() { match *parser.read() {
ParserState::StartSectionEntry(index) => { ParserState::StartSectionEntry(index) => {
runtime.declare_start_func(index as FunctionIndex); environ.declare_start_func(index as FunctionIndex);
} }
ParserState::EndSection => break, ParserState::EndSection => break,
ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))), ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))),
@@ -178,12 +178,12 @@ pub fn parse_start_section(
/// Retrieves the size and maximum fields of memories from the memory section /// Retrieves the size and maximum fields of memories from the memory section
pub fn parse_memory_section( pub fn parse_memory_section(
parser: &mut Parser, parser: &mut Parser,
runtime: &mut WasmRuntime, environ: &mut ModuleEnvironment,
) -> Result<(), SectionParsingError> { ) -> Result<(), SectionParsingError> {
loop { loop {
match *parser.read() { match *parser.read() {
ParserState::MemorySectionEntry(ref ty) => { ParserState::MemorySectionEntry(ref ty) => {
runtime.declare_memory(Memory { environ.declare_memory(Memory {
pages_count: ty.limits.initial as usize, pages_count: ty.limits.initial as usize,
maximum: ty.limits.maximum.map(|x| x as usize), maximum: ty.limits.maximum.map(|x| x as usize),
}); });
@@ -198,7 +198,7 @@ pub fn parse_memory_section(
/// Retrieves the size and maximum fields of memories from the memory section /// Retrieves the size and maximum fields of memories from the memory section
pub fn parse_global_section( pub fn parse_global_section(
parser: &mut Parser, parser: &mut Parser,
runtime: &mut WasmRuntime, environ: &mut ModuleEnvironment,
) -> Result<(), SectionParsingError> { ) -> Result<(), SectionParsingError> {
loop { loop {
let (content_type, mutability) = match *parser.read() { let (content_type, mutability) = match *parser.read() {
@@ -237,7 +237,7 @@ pub fn parse_global_section(
mutability: mutability, mutability: mutability,
initializer: initializer, initializer: initializer,
}; };
runtime.declare_global(global); environ.declare_global(global);
match *parser.read() { match *parser.read() {
ParserState::EndGlobalSectionEntry => (), ParserState::EndGlobalSectionEntry => (),
ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))), ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))),
@@ -248,7 +248,7 @@ pub fn parse_global_section(
pub fn parse_data_section( pub fn parse_data_section(
parser: &mut Parser, parser: &mut Parser,
runtime: &mut WasmRuntime, environ: &mut ModuleEnvironment,
) -> Result<(), SectionParsingError> { ) -> Result<(), SectionParsingError> {
loop { loop {
let memory_index = match *parser.read() { let memory_index = match *parser.read() {
@@ -265,7 +265,7 @@ pub fn parse_data_section(
(None, value as u32 as usize) (None, value as u32 as usize)
} }
ParserState::InitExpressionOperator(Operator::GetGlobal { global_index }) => { ParserState::InitExpressionOperator(Operator::GetGlobal { global_index }) => {
match runtime.get_global(global_index as GlobalIndex).initializer { match environ.get_global(global_index as GlobalIndex).initializer {
GlobalInit::I32Const(value) => (None, value as u32 as usize), GlobalInit::I32Const(value) => (None, value as u32 as usize),
GlobalInit::Import() => (Some(global_index as GlobalIndex), 0), GlobalInit::Import() => (Some(global_index as GlobalIndex), 0),
_ => panic!("should not happen"), _ => panic!("should not happen"),
@@ -288,7 +288,7 @@ pub fn parse_data_section(
ParserState::EndDataSectionEntryBody => break, ParserState::EndDataSectionEntryBody => break,
ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))), ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))),
}; };
runtime.declare_data_initialization( environ.declare_data_initialization(
memory_index as MemoryIndex, memory_index as MemoryIndex,
base, base,
running_offset, running_offset,
@@ -307,12 +307,12 @@ pub fn parse_data_section(
/// Retrieves the tables from the table section /// Retrieves the tables from the table section
pub fn parse_table_section( pub fn parse_table_section(
parser: &mut Parser, parser: &mut Parser,
runtime: &mut WasmRuntime, environ: &mut ModuleEnvironment,
) -> Result<(), SectionParsingError> { ) -> Result<(), SectionParsingError> {
loop { loop {
match *parser.read() { match *parser.read() {
ParserState::TableSectionEntry(ref table) => { ParserState::TableSectionEntry(ref table) => {
runtime.declare_table(Table { environ.declare_table(Table {
ty: match type_to_type(&table.element_type) { ty: match type_to_type(&table.element_type) {
Ok(t) => TableElementType::Val(t), Ok(t) => TableElementType::Val(t),
Err(()) => TableElementType::Func(), Err(()) => TableElementType::Func(),
@@ -331,7 +331,7 @@ pub fn parse_table_section(
/// Retrieves the tables from the table section /// Retrieves the tables from the table section
pub fn parse_elements_section( pub fn parse_elements_section(
parser: &mut Parser, parser: &mut Parser,
runtime: &mut WasmRuntime, environ: &mut ModuleEnvironment,
) -> Result<(), SectionParsingError> { ) -> Result<(), SectionParsingError> {
loop { loop {
let table_index = match *parser.read() { let table_index = match *parser.read() {
@@ -348,7 +348,7 @@ pub fn parse_elements_section(
(None, value as u32 as usize) (None, value as u32 as usize)
} }
ParserState::InitExpressionOperator(Operator::GetGlobal { global_index }) => { ParserState::InitExpressionOperator(Operator::GetGlobal { global_index }) => {
match runtime.get_global(global_index as GlobalIndex).initializer { match environ.get_global(global_index as GlobalIndex).initializer {
GlobalInit::I32Const(value) => (None, value as u32 as usize), GlobalInit::I32Const(value) => (None, value as u32 as usize),
GlobalInit::Import() => (Some(global_index as GlobalIndex), 0), GlobalInit::Import() => (Some(global_index as GlobalIndex), 0),
_ => panic!("should not happen"), _ => panic!("should not happen"),
@@ -364,7 +364,7 @@ pub fn parse_elements_section(
ParserState::ElementSectionEntryBody(ref elements) => { ParserState::ElementSectionEntryBody(ref elements) => {
let elems: Vec<FunctionIndex> = let elems: Vec<FunctionIndex> =
elements.iter().map(|&x| x as FunctionIndex).collect(); elements.iter().map(|&x| x as FunctionIndex).collect();
runtime.declare_table_elements(table_index, base, offset, &elems) environ.declare_table_elements(table_index, base, offset, &elems)
} }
ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))), ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))),
}; };

View File

@@ -2,7 +2,7 @@ extern crate cton_wasm;
extern crate cretonne; extern crate cretonne;
extern crate tempdir; extern crate tempdir;
use cton_wasm::{translate_module, DummyRuntime, WasmRuntime}; use cton_wasm::{translate_module, DummyEnvironment};
use std::path::PathBuf; use std::path::PathBuf;
use std::fs::File; use std::fs::File;
use std::error::Error; use std::error::Error;
@@ -92,12 +92,9 @@ fn handle_module(path: PathBuf, flags: &Flags) {
} }
} }
}; };
let mut dummy_runtime = DummyRuntime::with_flags(flags.clone()); let mut dummy_environ = DummyEnvironment::with_flags(flags.clone());
let translation = { translate_module(&data, &mut dummy_environ).unwrap();
let runtime: &mut WasmRuntime = &mut dummy_runtime; for func in &dummy_environ.info.function_bodies {
translate_module(&data, runtime).unwrap()
};
for func in &translation.functions {
verifier::verify_function(func, flags) verifier::verify_function(func, flags)
.map_err(|err| panic!(pretty_verifier_error(func, None, err))) .map_err(|err| panic!(pretty_verifier_error(func, None, err)))
.unwrap(); .unwrap();