Declare exports via the WasmRuntime.
Also, redo how functions are named in the DummyRuntime. Use the FunctionName field to just encode the wasm function index rather than trying to shoehorn a printable name into it. And to make up for that, teach the wasm printer to print export names as comments next to the function definitions. This also makes the fields of DummyRuntime public, in preparation for the DummyRuntime to have a more general-purpose debugging role, as well as possibly to allow it to serve as a base for other implementations.
This commit is contained in:
@@ -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};
|
use cton_wasm::{translate_module, DummyRuntime, WasmRuntime};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use cretonne::Context;
|
use cretonne::Context;
|
||||||
use cretonne::settings::FlagsOrIsa;
|
use cretonne::settings::FlagsOrIsa;
|
||||||
@@ -113,7 +113,9 @@ fn handle_module(
|
|||||||
vprint!(flag_verbose, "Compiling... ");
|
vprint!(flag_verbose, "Compiling... ");
|
||||||
}
|
}
|
||||||
terminal.reset().unwrap();
|
terminal.reset().unwrap();
|
||||||
for func in &translation.functions {
|
let num_func_imports = dummy_runtime.get_num_func_imports();
|
||||||
|
for (def_index, func) in translation.functions.iter().enumerate() {
|
||||||
|
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();
|
||||||
if flag_check_translation {
|
if flag_check_translation {
|
||||||
@@ -131,6 +133,14 @@ 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 func_index == start_func {
|
||||||
|
println!("; Selected as wasm start function");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for export_name in &dummy_runtime.functions[func_index].export_names {
|
||||||
|
println!("; Exported as \"{}\"", export_name);
|
||||||
|
}
|
||||||
println!("{}", context.func.display(fisa.isa));
|
println!("{}", context.func.display(fisa.isa));
|
||||||
vprintln!(flag_verbose, "");
|
vprintln!(flag_verbose, "");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,10 +5,8 @@ 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 translation_utils::FunctionIndex;
|
use cretonne::ir::Function;
|
||||||
use cretonne::ir::{Function, FunctionName};
|
|
||||||
use func_translator::FuncTranslator;
|
use func_translator::FuncTranslator;
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use runtime::WasmRuntime;
|
use runtime::WasmRuntime;
|
||||||
|
|
||||||
@@ -34,7 +32,6 @@ pub fn translate_module(
|
|||||||
}
|
}
|
||||||
ref s => panic!("modules should begin properly: {:?}", s),
|
ref s => panic!("modules should begin properly: {:?}", s),
|
||||||
}
|
}
|
||||||
let mut exports: HashMap<FunctionIndex, String> = HashMap::new();
|
|
||||||
let mut next_input = ParserInput::Default;
|
let mut next_input = ParserInput::Default;
|
||||||
loop {
|
loop {
|
||||||
match *parser.read_with_input(next_input) {
|
match *parser.read_with_input(next_input) {
|
||||||
@@ -92,8 +89,8 @@ 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) {
|
match parse_export_section(&mut parser, runtime) {
|
||||||
Ok(exps) => exports = exps,
|
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))
|
||||||
}
|
}
|
||||||
@@ -155,9 +152,7 @@ pub fn translate_module(
|
|||||||
func.signature = runtime
|
func.signature = runtime
|
||||||
.get_signature(runtime.get_func_type(function_index))
|
.get_signature(runtime.get_func_type(function_index))
|
||||||
.clone();
|
.clone();
|
||||||
if let Some(name) = exports.get(&function_index) {
|
func.name = runtime.get_name(function_index);
|
||||||
func.name = FunctionName::new(name.clone());
|
|
||||||
}
|
|
||||||
trans
|
trans
|
||||||
.translate_from_reader(parser.create_binary_reader(), &mut func, runtime)
|
.translate_from_reader(parser.create_binary_reader(), &mut func, runtime)
|
||||||
.map_err(|e| String::from(e.description()))?;
|
.map_err(|e| String::from(e.description()))?;
|
||||||
|
|||||||
@@ -6,25 +6,51 @@ use cretonne::ir::types::*;
|
|||||||
use cretonne::cursor::FuncCursor;
|
use cretonne::cursor::FuncCursor;
|
||||||
use cretonne::settings;
|
use cretonne::settings;
|
||||||
|
|
||||||
|
/// A collection of names under which a given entity is exported.
|
||||||
|
pub struct Exportable<T> {
|
||||||
|
/// A wasm entity.
|
||||||
|
pub entity: T,
|
||||||
|
|
||||||
|
/// Names under which the entity is exported.
|
||||||
|
pub export_names: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Exportable<T> {
|
||||||
|
pub fn new(entity: T) -> Self {
|
||||||
|
Self {
|
||||||
|
entity,
|
||||||
|
export_names: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// This runtime implementation is a "naïve" one, doing essentially nothing and emitting
|
/// 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
|
/// placeholders when forced to. Don't try to execute code translated with this runtime, it is
|
||||||
/// essentially here for translation debug purposes.
|
/// essentially here for translation debug purposes.
|
||||||
pub struct DummyRuntime {
|
pub struct DummyRuntime {
|
||||||
// Unprocessed signatures exactly as provided by `declare_signature()`.
|
/// Compilation setting flags.
|
||||||
signatures: Vec<ir::Signature>,
|
pub flags: settings::Flags,
|
||||||
globals: Vec<Global>,
|
|
||||||
|
|
||||||
// Types of functions, imported and local.
|
/// Signatures as provided by `declare_signature`.
|
||||||
func_types: Vec<SignatureIndex>,
|
pub signatures: Vec<ir::Signature>,
|
||||||
|
|
||||||
// Names of imported functions.
|
/// Module and field names of imported functions as provided by `declare_func_import`.
|
||||||
imported_funcs: Vec<ir::FunctionName>,
|
pub imported_funcs: Vec<(String, String)>,
|
||||||
|
|
||||||
// Compilation setting flags.
|
/// Functions, imported and local.
|
||||||
flags: settings::Flags,
|
pub functions: Vec<Exportable<SignatureIndex>>,
|
||||||
|
|
||||||
// The start function.
|
/// Tables as provided by `declare_table`.
|
||||||
start_func: Option<FunctionIndex>,
|
pub tables: Vec<Exportable<Table>>,
|
||||||
|
|
||||||
|
/// Memories as provided by `declare_memory`.
|
||||||
|
pub memories: Vec<Exportable<Memory>>,
|
||||||
|
|
||||||
|
/// Globals as provided by `declare_global`.
|
||||||
|
pub globals: Vec<Exportable<Global>>,
|
||||||
|
|
||||||
|
/// The start function.
|
||||||
|
pub start_func: Option<FunctionIndex>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DummyRuntime {
|
impl DummyRuntime {
|
||||||
@@ -36,11 +62,13 @@ impl DummyRuntime {
|
|||||||
/// 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 {
|
||||||
signatures: Vec::new(),
|
|
||||||
globals: Vec::new(),
|
|
||||||
func_types: Vec::new(),
|
|
||||||
imported_funcs: Vec::new(),
|
|
||||||
flags,
|
flags,
|
||||||
|
signatures: Vec::new(),
|
||||||
|
imported_funcs: Vec::new(),
|
||||||
|
functions: Vec::new(),
|
||||||
|
tables: Vec::new(),
|
||||||
|
memories: Vec::new(),
|
||||||
|
globals: Vec::new(),
|
||||||
start_func: None,
|
start_func: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -57,7 +85,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].ty,
|
ty: self.globals[index].entity.ty,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,16 +105,11 @@ impl FuncEnvironment for DummyRuntime {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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.func_types[index];
|
let sigidx = self.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.signatures[sigidx].clone());
|
||||||
|
let name = self.get_name(index);
|
||||||
let name = match self.imported_funcs.get(index) {
|
|
||||||
Some(name) => name.clone(),
|
|
||||||
None => ir::FunctionName::new(format!("localfunc{}", index)),
|
|
||||||
};
|
|
||||||
|
|
||||||
func.import_function(ir::ExtFuncData { name, signature })
|
func.import_function(ir::ExtFuncData { name, signature })
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,6 +146,10 @@ impl FuncEnvironment for DummyRuntime {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl WasmRuntime for DummyRuntime {
|
impl WasmRuntime for DummyRuntime {
|
||||||
|
fn get_name(&self, func_index: FunctionIndex) -> ir::FunctionName {
|
||||||
|
ir::FunctionName::new(format!("wasm_0x{:x}", func_index))
|
||||||
|
}
|
||||||
|
|
||||||
fn declare_signature(&mut self, sig: &ir::Signature) {
|
fn declare_signature(&mut self, sig: &ir::Signature) {
|
||||||
self.signatures.push(sig.clone());
|
self.signatures.push(sig.clone());
|
||||||
}
|
}
|
||||||
@@ -131,19 +158,17 @@ impl WasmRuntime for DummyRuntime {
|
|||||||
&self.signatures[sig_index]
|
&self.signatures[sig_index]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn declare_func_import(&mut self, sig_index: SignatureIndex, module: &[u8], field: &[u8]) {
|
fn declare_func_import(&mut self, sig_index: SignatureIndex, module: &str, field: &str) {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
self.func_types.len(),
|
self.functions.len(),
|
||||||
self.imported_funcs.len(),
|
self.imported_funcs.len(),
|
||||||
"Imported functions must be declared first"
|
"Imported functions must be declared first"
|
||||||
);
|
);
|
||||||
self.func_types.push(sig_index);
|
self.functions.push(Exportable::new(sig_index));
|
||||||
|
self.imported_funcs.push((
|
||||||
let mut name = Vec::new();
|
String::from(module),
|
||||||
name.extend(module.iter().cloned().map(name_fold));
|
String::from(field),
|
||||||
name.push(b'_');
|
));
|
||||||
name.extend(field.iter().cloned().map(name_fold));
|
|
||||||
self.imported_funcs.push(ir::FunctionName::new(name));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_num_func_imports(&self) -> usize {
|
fn get_num_func_imports(&self) -> usize {
|
||||||
@@ -151,40 +176,69 @@ impl WasmRuntime for DummyRuntime {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn declare_func_type(&mut self, sig_index: SignatureIndex) {
|
fn declare_func_type(&mut self, sig_index: SignatureIndex) {
|
||||||
self.func_types.push(sig_index);
|
self.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.func_types[func_index]
|
self.functions[func_index].entity
|
||||||
}
|
}
|
||||||
|
|
||||||
fn declare_global(&mut self, global: Global) {
|
fn declare_global(&mut self, global: Global) {
|
||||||
self.globals.push(global);
|
self.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]
|
&self.globals[global_index].entity
|
||||||
}
|
}
|
||||||
|
|
||||||
fn declare_table(&mut self, _: Table) {
|
fn declare_table(&mut self, table: Table) {
|
||||||
|
self.tables.push(Exportable::new(table));
|
||||||
|
}
|
||||||
|
fn declare_table_elements(
|
||||||
|
&mut self,
|
||||||
|
_table_index: TableIndex,
|
||||||
|
_offset: usize,
|
||||||
|
_elements: &[FunctionIndex],
|
||||||
|
) {
|
||||||
// We do nothing
|
// We do nothing
|
||||||
}
|
}
|
||||||
fn declare_table_elements(&mut self, _: TableIndex, _: usize, _: &[FunctionIndex]) {
|
fn declare_memory(&mut self, memory: Memory) {
|
||||||
//We do nothing
|
self.memories.push(Exportable::new(memory));
|
||||||
}
|
|
||||||
fn declare_memory(&mut self, _: Memory) {
|
|
||||||
//We do nothing
|
|
||||||
}
|
}
|
||||||
fn declare_data_initialization(
|
fn declare_data_initialization(
|
||||||
&mut self,
|
&mut self,
|
||||||
_: MemoryIndex,
|
_memory_index: MemoryIndex,
|
||||||
_: usize,
|
_offset: usize,
|
||||||
_: &[u8],
|
_data: &[u8],
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
// We do nothing
|
// We do nothing
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn declare_func_export(&mut self, func_index: FunctionIndex, name: &str) {
|
||||||
|
self.functions[func_index].export_names.push(
|
||||||
|
String::from(name),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn declare_table_export(&mut self, table_index: TableIndex, name: &str) {
|
||||||
|
self.tables[table_index].export_names.push(
|
||||||
|
String::from(name),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn declare_memory_export(&mut self, memory_index: MemoryIndex, name: &str) {
|
||||||
|
self.memories[memory_index].export_names.push(
|
||||||
|
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.start_func.is_none());
|
||||||
self.start_func = Some(func_index);
|
self.start_func = Some(func_index);
|
||||||
@@ -197,12 +251,3 @@ impl WasmRuntime for DummyRuntime {
|
|||||||
// We do nothing
|
// We do nothing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate characters suitable for printable `FuncName`s.
|
|
||||||
fn name_fold(c: u8) -> u8 {
|
|
||||||
if (c as char).is_alphanumeric() {
|
|
||||||
c
|
|
||||||
} else {
|
|
||||||
b'_'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -150,6 +150,9 @@ pub trait FuncEnvironment {
|
|||||||
/// [`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 WasmRuntime: FuncEnvironment {
|
||||||
|
/// Return the name for the given function index.
|
||||||
|
fn get_name(&self, func_index: FunctionIndex) -> ir::FunctionName;
|
||||||
|
|
||||||
/// Declares a function signature to the runtime.
|
/// Declares a function signature to the runtime.
|
||||||
fn declare_signature(&mut self, sig: &ir::Signature);
|
fn declare_signature(&mut self, sig: &ir::Signature);
|
||||||
|
|
||||||
@@ -157,7 +160,7 @@ pub trait WasmRuntime: FuncEnvironment {
|
|||||||
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 runtime.
|
||||||
fn declare_func_import(&mut self, sig_index: SignatureIndex, module: &[u8], field: &[u8]);
|
fn declare_func_import(&mut self, sig_index: SignatureIndex, module: &str, field: &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;
|
||||||
@@ -193,6 +196,15 @@ pub trait WasmRuntime: FuncEnvironment {
|
|||||||
data: &[u8],
|
data: &[u8],
|
||||||
) -> Result<(), String>;
|
) -> Result<(), String>;
|
||||||
|
|
||||||
|
/// Declares a function export to the runtime.
|
||||||
|
fn declare_func_export(&mut self, func_index: FunctionIndex, name: &str);
|
||||||
|
/// Declares a table export to the runtime.
|
||||||
|
fn declare_table_export(&mut self, table_index: TableIndex, name: &str);
|
||||||
|
/// Declares a memory export to the runtime.
|
||||||
|
fn declare_memory_export(&mut self, memory_index: MemoryIndex, name: &str);
|
||||||
|
/// Declares a global export to the runtime.
|
||||||
|
fn declare_global_export(&mut self, global_index: GlobalIndex, name: &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);
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ use cretonne;
|
|||||||
use wasmparser::{Parser, ParserState, FuncType, ImportSectionEntryType, ExternalKind, WasmDecoder,
|
use wasmparser::{Parser, ParserState, FuncType, ImportSectionEntryType, ExternalKind, WasmDecoder,
|
||||||
MemoryType, Operator};
|
MemoryType, Operator};
|
||||||
use wasmparser;
|
use wasmparser;
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::str::from_utf8;
|
use std::str::from_utf8;
|
||||||
use runtime::WasmRuntime;
|
use runtime::WasmRuntime;
|
||||||
|
|
||||||
@@ -68,7 +67,12 @@ pub fn parse_import_section(
|
|||||||
module,
|
module,
|
||||||
field,
|
field,
|
||||||
} => {
|
} => {
|
||||||
runtime.declare_func_import(sig as SignatureIndex, module, field);
|
// The input has already been validated, so we should be able to
|
||||||
|
// assume valid UTF-8 and use `from_utf8_unchecked` if performance
|
||||||
|
// becomes a concern here.
|
||||||
|
let module_name = from_utf8(module).unwrap();
|
||||||
|
let field_name = from_utf8(field).unwrap();
|
||||||
|
runtime.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 }), ..
|
||||||
@@ -126,8 +130,8 @@ 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,
|
||||||
) -> Result<HashMap<FunctionIndex, String>, SectionParsingError> {
|
runtime: &mut WasmRuntime,
|
||||||
let mut exports: HashMap<FunctionIndex, String> = HashMap::new();
|
) -> Result<(), SectionParsingError> {
|
||||||
loop {
|
loop {
|
||||||
match *parser.read() {
|
match *parser.read() {
|
||||||
ParserState::ExportSectionEntry {
|
ParserState::ExportSectionEntry {
|
||||||
@@ -135,21 +139,23 @@ pub fn parse_export_section(
|
|||||||
ref kind,
|
ref kind,
|
||||||
index,
|
index,
|
||||||
} => {
|
} => {
|
||||||
|
// The input has already been validated, so we should be able to
|
||||||
|
// assume valid UTF-8 and use `from_utf8_unchecked` if performance
|
||||||
|
// becomes a concern here.
|
||||||
|
let name = from_utf8(field).unwrap();
|
||||||
|
let func_index = index as FunctionIndex;
|
||||||
match *kind {
|
match *kind {
|
||||||
ExternalKind::Function => {
|
ExternalKind::Function => runtime.declare_func_export(func_index, name),
|
||||||
exports.insert(
|
ExternalKind::Table => runtime.declare_table_export(func_index, name),
|
||||||
index as FunctionIndex,
|
ExternalKind::Memory => runtime.declare_memory_export(func_index, name),
|
||||||
String::from(from_utf8(field).unwrap()),
|
ExternalKind::Global => runtime.declare_global_export(func_index, name),
|
||||||
);
|
|
||||||
}
|
|
||||||
_ => (),//TODO: deal with other kind of exports
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ParserState::EndSection => break,
|
ParserState::EndSection => break,
|
||||||
ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))),
|
ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
Ok(exports)
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieves the start function index from the start section
|
/// Retrieves the start function index from the start section
|
||||||
|
|||||||
Reference in New Issue
Block a user