Add a FuncEnvironment::make_direct_func() callback.
This allows the environment to control the signatures used for direct
function calls. The signature and calling convention may depend on
whether the function is imported or local.
Also add WasmRuntime::declare_func_{import,type} to notify the runtime
about imported and local functions. This is necessary so the runtime
knows what function indexes are referring to .
Since imported and local functions are now declared to the runtime, it
is no longer necessary to return hashes mapping between WebAssembly
indexes and Cretonne entities.
Also stop return null entries for the imported functions in the
TranslationResult. Just return a vector of local functions.
This commit is contained in:
@@ -21,40 +21,19 @@
|
||||
//!
|
||||
//! That is why `translate_function_body` takes an object having the `WasmRuntime` trait as
|
||||
//! argument.
|
||||
use cretonne::ir::{self, Function, Signature, Type, InstBuilder, FunctionName, Ebb, FuncRef,
|
||||
SigRef, ExtFuncData, MemFlags};
|
||||
use cretonne::ir::{self, Function, Signature, Type, InstBuilder, FunctionName, Ebb, MemFlags};
|
||||
use cretonne::ir::types::*;
|
||||
use cretonne::ir::immediates::{Ieee32, Ieee64};
|
||||
use cretonne::ir::condcodes::{IntCC, FloatCC};
|
||||
use cton_frontend::{ILBuilder, FunctionBuilder};
|
||||
use wasmparser::{Parser, ParserState, Operator, WasmDecoder, MemoryImmediate};
|
||||
use translation_utils::{f32_translation, f64_translation, type_to_type, translate_type, Local,
|
||||
FunctionIndex, SignatureIndex};
|
||||
FunctionIndex};
|
||||
use state::{TranslationState, ControlStackFrame};
|
||||
use std::collections::HashMap;
|
||||
use runtime::{FuncEnvironment, GlobalValue, WasmRuntime};
|
||||
use std::u32;
|
||||
|
||||
|
||||
/// Holds mappings between the function and signatures indexes in the Wasm module and their
|
||||
/// references as imports of the Cretonne IL function.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct FunctionImports {
|
||||
/// Mappings index in function index space -> index in function local imports
|
||||
pub functions: HashMap<FunctionIndex, FuncRef>,
|
||||
/// Mappings index in signature index space -> index in signature local imports
|
||||
pub signatures: HashMap<SignatureIndex, SigRef>,
|
||||
}
|
||||
|
||||
impl FunctionImports {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
functions: HashMap::new(),
|
||||
signatures: HashMap::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a well-formed Cretonne IL function from a wasm function body and a signature.
|
||||
pub fn translate_function_body(
|
||||
parser: &mut Parser,
|
||||
@@ -62,11 +41,9 @@ pub fn translate_function_body(
|
||||
sig: &Signature,
|
||||
locals: &[(usize, Type)],
|
||||
exports: &Option<HashMap<FunctionIndex, String>>,
|
||||
signatures: &[Signature],
|
||||
functions: &[SignatureIndex],
|
||||
il_builder: &mut ILBuilder<Local>,
|
||||
runtime: &mut WasmRuntime,
|
||||
) -> Result<(Function, FunctionImports), String> {
|
||||
) -> Result<Function, String> {
|
||||
runtime.next_function();
|
||||
// First we build the Function object with its name and signature
|
||||
let mut func = Function::new();
|
||||
@@ -77,7 +54,6 @@ pub fn translate_function_body(
|
||||
func.name = FunctionName::new(name.clone());
|
||||
}
|
||||
}
|
||||
let mut func_imports = FunctionImports::new();
|
||||
// We introduce an arbitrary scope for the FunctionBuilder object
|
||||
{
|
||||
let mut builder = FunctionBuilder::new(&mut func, il_builder);
|
||||
@@ -121,16 +97,7 @@ pub fn translate_function_body(
|
||||
if state.in_unreachable_code() {
|
||||
translate_unreachable_operator(op, &mut builder, &mut state)
|
||||
} else {
|
||||
translate_operator(
|
||||
op,
|
||||
&mut builder,
|
||||
runtime,
|
||||
&mut state,
|
||||
functions,
|
||||
signatures,
|
||||
exports,
|
||||
&mut func_imports,
|
||||
)
|
||||
translate_operator(op, &mut builder, &mut state, runtime)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,7 +127,7 @@ pub fn translate_function_body(
|
||||
state.stack.truncate(cut_index);
|
||||
}
|
||||
}
|
||||
Ok((func, func_imports))
|
||||
Ok(func)
|
||||
}
|
||||
|
||||
/// Translates wasm operators into Cretonne IL instructions. Returns `true` if it inserted
|
||||
@@ -168,12 +135,8 @@ pub fn translate_function_body(
|
||||
fn translate_operator(
|
||||
op: &Operator,
|
||||
builder: &mut FunctionBuilder<Local>,
|
||||
runtime: &mut WasmRuntime,
|
||||
state: &mut TranslationState,
|
||||
functions: &[SignatureIndex],
|
||||
signatures: &[Signature],
|
||||
exports: &Option<HashMap<FunctionIndex, String>>,
|
||||
func_imports: &mut FunctionImports,
|
||||
runtime: &mut WasmRuntime,
|
||||
) {
|
||||
// This big match treats all Wasm code operators.
|
||||
match *op {
|
||||
@@ -465,25 +428,13 @@ fn translate_operator(
|
||||
* argument referring to an index in the external functions table of the module.
|
||||
************************************************************************************/
|
||||
Operator::Call { function_index } => {
|
||||
let args_num = args_count(function_index as usize, functions, signatures);
|
||||
let cut_index = state.stack.len() - args_num;
|
||||
let internal_function_index = find_function_import(
|
||||
function_index as usize,
|
||||
builder,
|
||||
func_imports,
|
||||
functions,
|
||||
exports,
|
||||
signatures,
|
||||
);
|
||||
let call_inst = builder.ins().call(
|
||||
internal_function_index,
|
||||
&state.stack[cut_index..],
|
||||
);
|
||||
state.stack.truncate(cut_index);
|
||||
let (fref, num_args) = state.get_direct_func(builder.func, function_index, runtime);
|
||||
// TODO: Let the function environment override the call instruction. It may want to add
|
||||
// arguments.
|
||||
let call_inst = builder.ins().call(fref, &state.peekn(num_args));
|
||||
state.popn(num_args);
|
||||
let ret_values = builder.inst_results(call_inst);
|
||||
for val in ret_values {
|
||||
state.push1(*val);
|
||||
}
|
||||
state.pushn(ret_values);
|
||||
}
|
||||
Operator::CallIndirect {
|
||||
index,
|
||||
@@ -1098,60 +1049,3 @@ fn translate_store<FE: FuncEnvironment + ?Sized>(
|
||||
base,
|
||||
);
|
||||
}
|
||||
fn args_count(
|
||||
index: FunctionIndex,
|
||||
functions: &[SignatureIndex],
|
||||
signatures: &[Signature],
|
||||
) -> usize {
|
||||
signatures[functions[index]].argument_types.len()
|
||||
}
|
||||
|
||||
// Given an index in the function index space, search for it in the function imports and if it is
|
||||
// not there add it to the function imports.
|
||||
fn find_function_import(
|
||||
index: FunctionIndex,
|
||||
builder: &mut FunctionBuilder<Local>,
|
||||
func_imports: &mut FunctionImports,
|
||||
functions: &[SignatureIndex],
|
||||
exports: &Option<HashMap<FunctionIndex, String>>,
|
||||
signatures: &[Signature],
|
||||
) -> FuncRef {
|
||||
if let Some(local_index) = func_imports.functions.get(&index) {
|
||||
return *local_index;
|
||||
}
|
||||
// We have to import the function
|
||||
let sig_index = functions[index];
|
||||
if let Some(local_sig_index) = func_imports.signatures.get(&sig_index) {
|
||||
let local_func_index = builder.import_function(ExtFuncData {
|
||||
name: match *exports {
|
||||
None => FunctionName::new(""),
|
||||
Some(ref exports) => {
|
||||
match exports.get(&index) {
|
||||
None => FunctionName::new(""),
|
||||
Some(name) => FunctionName::new(name.clone()),
|
||||
}
|
||||
}
|
||||
},
|
||||
signature: *local_sig_index,
|
||||
});
|
||||
func_imports.functions.insert(index, local_func_index);
|
||||
return local_func_index;
|
||||
}
|
||||
// We have to import the signature
|
||||
let sig_local_index = builder.import_signature(signatures[sig_index].clone());
|
||||
func_imports.signatures.insert(sig_index, sig_local_index);
|
||||
let local_func_index = builder.import_function(ExtFuncData {
|
||||
name: match *exports {
|
||||
None => FunctionName::new(""),
|
||||
Some(ref exports) => {
|
||||
match exports.get(&index) {
|
||||
None => FunctionName::new(""),
|
||||
Some(name) => FunctionName::new(name.clone()),
|
||||
}
|
||||
}
|
||||
},
|
||||
signature: sig_local_index,
|
||||
});
|
||||
func_imports.functions.insert(index, local_func_index);
|
||||
local_func_index
|
||||
}
|
||||
|
||||
@@ -23,8 +23,7 @@ mod sections_translator;
|
||||
mod state;
|
||||
mod translation_utils;
|
||||
|
||||
pub use module_translator::{translate_module, TranslationResult, FunctionTranslation,
|
||||
ImportMappings};
|
||||
pub use runtime::{WasmRuntime, DummyRuntime};
|
||||
pub use module_translator::{translate_module, TranslationResult};
|
||||
pub use runtime::{FuncEnvironment, WasmRuntime, DummyRuntime};
|
||||
pub use translation_utils::{Local, FunctionIndex, GlobalIndex, TableIndex, MemoryIndex, RawByte,
|
||||
MemoryAddress, SignatureIndex, Global, GlobalInit, Table, Memory};
|
||||
|
||||
@@ -5,8 +5,8 @@ use sections_translator::{SectionParsingError, parse_function_signatures, parse_
|
||||
parse_function_section, parse_export_section, parse_memory_section,
|
||||
parse_global_section, parse_table_section, parse_elements_section,
|
||||
parse_data_section};
|
||||
use translation_utils::{type_to_type, Import, SignatureIndex, FunctionIndex, invert_hashmaps};
|
||||
use cretonne::ir::{Function, Type, FuncRef, SigRef};
|
||||
use translation_utils::{type_to_type, Import, SignatureIndex, FunctionIndex};
|
||||
use cretonne::ir::{Function, Type};
|
||||
use code_translator::translate_function_body;
|
||||
use cton_frontend::ILBuilder;
|
||||
use std::collections::HashMap;
|
||||
@@ -15,45 +15,14 @@ use runtime::WasmRuntime;
|
||||
/// Output of the [`translate_module`](fn.translate_module.html) function.
|
||||
pub struct TranslationResult {
|
||||
/// The translated functions.
|
||||
pub functions: Vec<FunctionTranslation>,
|
||||
pub functions: Vec<Function>,
|
||||
/// When present, the index of the function defined as `start` of the module.
|
||||
///
|
||||
/// Note that this is a WebAssembly function index and not an index into the `functions` vector
|
||||
/// above. The imported functions are numbered before the local functions.
|
||||
pub start_index: Option<FunctionIndex>,
|
||||
}
|
||||
|
||||
/// A function in a WebAssembly module can be either imported, or defined inside it.
|
||||
#[derive(Clone)]
|
||||
pub enum FunctionTranslation {
|
||||
/// A function defined inside the WebAssembly module.
|
||||
Code {
|
||||
/// The translation in Cretonne IL.
|
||||
il: Function,
|
||||
/// The mappings between Cretonne imports and indexes in the function index space.
|
||||
imports: ImportMappings,
|
||||
},
|
||||
/// An imported function.
|
||||
Import(),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
/// Mappings describing the relations between imports of the Cretonne IL functions and the
|
||||
/// functions in the WebAssembly module.
|
||||
pub struct ImportMappings {
|
||||
/// Find the index of a function in the WebAssembly module thanks to a `FuncRef`.
|
||||
pub functions: HashMap<FuncRef, FunctionIndex>,
|
||||
/// Find the index of a signature in the WebAssembly module thanks to a `SigRef`.
|
||||
pub signatures: HashMap<SigRef, SignatureIndex>,
|
||||
}
|
||||
|
||||
impl ImportMappings {
|
||||
/// Create a new empty `ImportMappings`.
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
functions: HashMap::new(),
|
||||
signatures: HashMap::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Translate a sequence of bytes forming a valid Wasm binary into a list of valid Cretonne IL
|
||||
/// [`Function`](../cretonne/ir/function/struct.Function.html).
|
||||
/// Returns the functions and also the mappings for imported functions and signature between the
|
||||
@@ -76,7 +45,6 @@ pub fn translate_module(
|
||||
let mut exports: Option<HashMap<FunctionIndex, String>> = None;
|
||||
let mut next_input = ParserInput::Default;
|
||||
let mut function_index: FunctionIndex = 0;
|
||||
let mut function_imports_count = 0;
|
||||
let mut start_index: Option<FunctionIndex> = None;
|
||||
loop {
|
||||
match *parser.read_with_input(next_input) {
|
||||
@@ -90,7 +58,7 @@ pub fn translate_module(
|
||||
next_input = ParserInput::Default;
|
||||
}
|
||||
ParserState::BeginSection { code: SectionCode::Import, .. } => {
|
||||
match parse_import_section(&mut parser) {
|
||||
match parse_import_section(&mut parser, runtime) {
|
||||
Ok(imps) => {
|
||||
for import in imps {
|
||||
match import {
|
||||
@@ -121,11 +89,10 @@ pub fn translate_module(
|
||||
return Err(format!("wrong content in the import section: {}", s))
|
||||
}
|
||||
}
|
||||
function_imports_count = function_index;
|
||||
next_input = ParserInput::Default;
|
||||
}
|
||||
ParserState::BeginSection { code: SectionCode::Function, .. } => {
|
||||
match parse_function_section(&mut parser) {
|
||||
match parse_function_section(&mut parser, runtime) {
|
||||
Ok(funcs) => {
|
||||
match functions {
|
||||
None => functions = Some(funcs),
|
||||
@@ -233,8 +200,7 @@ pub fn translate_module(
|
||||
None => return Err(String::from("missing a function section")),
|
||||
Some(functions) => functions,
|
||||
};
|
||||
let mut il_functions: Vec<FunctionTranslation> = Vec::new();
|
||||
il_functions.resize(function_imports_count, FunctionTranslation::Import());
|
||||
let mut il_functions: Vec<Function> = Vec::new();
|
||||
let mut il_builder = ILBuilder::new();
|
||||
runtime.begin_translation();
|
||||
loop {
|
||||
@@ -263,17 +229,10 @@ pub fn translate_module(
|
||||
&signature,
|
||||
&locals,
|
||||
&exports,
|
||||
&signatures,
|
||||
&functions,
|
||||
&mut il_builder,
|
||||
runtime,
|
||||
) {
|
||||
Ok((il_func, imports)) => {
|
||||
il_functions.push(FunctionTranslation::Code {
|
||||
il: il_func,
|
||||
imports: invert_hashmaps(&imports),
|
||||
})
|
||||
}
|
||||
Ok(il_func) => il_functions.push(il_func),
|
||||
Err(s) => return Err(s),
|
||||
}
|
||||
function_index += 1;
|
||||
|
||||
@@ -12,6 +12,12 @@ pub struct DummyRuntime {
|
||||
// Unprocessed signatures exactly as provided by `declare_signature()`.
|
||||
signatures: Vec<ir::Signature>,
|
||||
globals: Vec<Global>,
|
||||
|
||||
// Types of functions, imported and local.
|
||||
func_types: Vec<SignatureIndex>,
|
||||
|
||||
// Names of imported functions.
|
||||
imported_funcs: Vec<ir::FunctionName>,
|
||||
}
|
||||
|
||||
impl DummyRuntime {
|
||||
@@ -20,6 +26,8 @@ impl DummyRuntime {
|
||||
Self {
|
||||
signatures: Vec::new(),
|
||||
globals: Vec::new(),
|
||||
func_types: Vec::new(),
|
||||
imported_funcs: Vec::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -53,6 +61,20 @@ impl FuncEnvironment for DummyRuntime {
|
||||
// signature index arguments.
|
||||
func.dfg.signatures.push(self.signatures[index].clone())
|
||||
}
|
||||
|
||||
fn make_direct_func(&self, func: &mut ir::Function, index: FunctionIndex) -> ir::FuncRef {
|
||||
let sigidx = self.func_types[index];
|
||||
// A real implementation would probably add a `vmctx` argument.
|
||||
// And maybe attempt some signature de-duplication.
|
||||
let signature = func.dfg.signatures.push(self.signatures[sigidx].clone());
|
||||
|
||||
let name = match self.imported_funcs.get(index) {
|
||||
Some(name) => name.clone(),
|
||||
None => ir::FunctionName::new(format!("localfunc{}", index)),
|
||||
};
|
||||
|
||||
func.dfg.ext_funcs.push(ir::ExtFuncData { name, signature })
|
||||
}
|
||||
}
|
||||
|
||||
impl WasmRuntime for DummyRuntime {
|
||||
@@ -77,6 +99,25 @@ impl WasmRuntime for DummyRuntime {
|
||||
self.signatures.push(sig.clone());
|
||||
}
|
||||
|
||||
fn declare_func_import(&mut self, sig_index: SignatureIndex, module: &[u8], field: &[u8]) {
|
||||
assert_eq!(
|
||||
self.func_types.len(),
|
||||
self.imported_funcs.len(),
|
||||
"Imported functions must be declared first"
|
||||
);
|
||||
self.func_types.push(sig_index);
|
||||
|
||||
let mut name = Vec::new();
|
||||
name.extend(module.iter().cloned().map(name_fold));
|
||||
name.push(b'_');
|
||||
name.extend(field.iter().cloned().map(name_fold));
|
||||
self.imported_funcs.push(ir::FunctionName::new(name));
|
||||
}
|
||||
|
||||
fn declare_func_type(&mut self, sig_index: SignatureIndex) {
|
||||
self.func_types.push(sig_index);
|
||||
}
|
||||
|
||||
fn declare_global(&mut self, global: Global) {
|
||||
self.globals.push(global);
|
||||
}
|
||||
@@ -106,3 +147,12 @@ impl WasmRuntime for DummyRuntime {
|
||||
// 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'_'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,6 +51,19 @@ pub trait FuncEnvironment {
|
||||
/// The signature will only be used for indirect calls, even if the module has direct function
|
||||
/// calls with the same WebAssembly type.
|
||||
fn make_indirect_sig(&self, func: &mut ir::Function, index: SignatureIndex) -> ir::SigRef;
|
||||
|
||||
/// Set up an external function definition in the preamble of `func` that can be used to
|
||||
/// directly call the function `index`.
|
||||
///
|
||||
/// The index space covers both imported functions and functions defined in the current module.
|
||||
///
|
||||
/// The function's signature may contain additional arguments needed for a direct call, but the
|
||||
/// arguments marked as `ArgumentPurpose::Normal` must correspond to the WebAssembly signature
|
||||
/// arguments.
|
||||
///
|
||||
/// The function's signature will only be used for direct calls, even if the module has
|
||||
/// indirect calls with the same WebAssembly type.
|
||||
fn make_direct_func(&self, func: &mut ir::Function, index: FunctionIndex) -> ir::FuncRef;
|
||||
}
|
||||
|
||||
/// An object satisfyng the `WasmRuntime` trait can be passed as argument to the
|
||||
@@ -60,6 +73,12 @@ pub trait WasmRuntime: FuncEnvironment {
|
||||
/// Declares a function signature to the runtime.
|
||||
fn declare_signature(&mut self, sig: &ir::Signature);
|
||||
|
||||
/// Declares a function import to the runtime.
|
||||
fn declare_func_import(&mut self, sig_index: SignatureIndex, module: &[u8], field: &[u8]);
|
||||
|
||||
/// Declares the type (signature) of a local function in the module.
|
||||
fn declare_func_type(&mut self, sig_index: SignatureIndex);
|
||||
|
||||
/// Declares a global to the runtime.
|
||||
fn declare_global(&mut self, global: Global);
|
||||
/// Declares a table to the runtime.
|
||||
|
||||
@@ -64,13 +64,21 @@ pub fn parse_function_signatures(
|
||||
}
|
||||
|
||||
/// Retrieves the imports from the imports section of the binary.
|
||||
pub fn parse_import_section(parser: &mut Parser) -> Result<Vec<Import>, SectionParsingError> {
|
||||
pub fn parse_import_section(
|
||||
parser: &mut Parser,
|
||||
runtime: &mut WasmRuntime,
|
||||
) -> Result<Vec<Import>, SectionParsingError> {
|
||||
let mut imports = Vec::new();
|
||||
loop {
|
||||
match *parser.read() {
|
||||
ParserState::ImportSectionEntry {
|
||||
ty: ImportSectionEntryType::Function(sig), ..
|
||||
} => imports.push(Import::Function { sig_index: sig }),
|
||||
ty: ImportSectionEntryType::Function(sig),
|
||||
module,
|
||||
field,
|
||||
} => {
|
||||
runtime.declare_func_import(sig as SignatureIndex, module, field);
|
||||
imports.push(Import::Function { sig_index: sig });
|
||||
}
|
||||
ParserState::ImportSectionEntry {
|
||||
ty: ImportSectionEntryType::Memory(MemoryType { limits: ref memlimits }), ..
|
||||
} => {
|
||||
@@ -110,11 +118,15 @@ pub fn parse_import_section(parser: &mut Parser) -> Result<Vec<Import>, SectionP
|
||||
/// Retrieves the correspondances between functions and signatures from the function section
|
||||
pub fn parse_function_section(
|
||||
parser: &mut Parser,
|
||||
runtime: &mut WasmRuntime,
|
||||
) -> Result<Vec<SignatureIndex>, SectionParsingError> {
|
||||
let mut funcs = Vec::new();
|
||||
loop {
|
||||
match *parser.read() {
|
||||
ParserState::FunctionSectionEntry(sigindex) => funcs.push(sigindex as SignatureIndex),
|
||||
ParserState::FunctionSectionEntry(sigindex) => {
|
||||
runtime.declare_func_type(sigindex as SignatureIndex);
|
||||
funcs.push(sigindex as SignatureIndex);
|
||||
}
|
||||
ParserState::EndSection => break,
|
||||
ref s => return Err(SectionParsingError::WrongSectionContent(format!("{:?}", s))),
|
||||
};
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
use cretonne::ir::{self, Ebb, Inst, Type, Value};
|
||||
use runtime::{FuncEnvironment, GlobalValue};
|
||||
use std::collections::HashMap;
|
||||
use translation_utils::{GlobalIndex, MemoryIndex, SignatureIndex};
|
||||
use translation_utils::{GlobalIndex, MemoryIndex, SignatureIndex, FunctionIndex};
|
||||
|
||||
/// A control stack frame can be an `if`, a `block` or a `loop`, each one having the following
|
||||
/// fields:
|
||||
@@ -118,6 +118,11 @@ pub struct TranslationState {
|
||||
// `FuncEnvironment::make_indirect_sig()`.
|
||||
// Stores both the signature reference and the number of WebAssembly arguments
|
||||
signatures: HashMap<SignatureIndex, (ir::SigRef, usize)>,
|
||||
|
||||
// Imported and local functions that have been created by
|
||||
// `FuncEnvironment::make_direct_func()`.
|
||||
// Stores both the function reference and the number of WebAssembly arguments
|
||||
functions: HashMap<FunctionIndex, (ir::FuncRef, usize)>,
|
||||
}
|
||||
|
||||
impl TranslationState {
|
||||
@@ -130,6 +135,7 @@ impl TranslationState {
|
||||
globals: HashMap::new(),
|
||||
heaps: HashMap::new(),
|
||||
signatures: HashMap::new(),
|
||||
functions: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,6 +147,7 @@ impl TranslationState {
|
||||
self.globals.clear();
|
||||
self.heaps.clear();
|
||||
self.signatures.clear();
|
||||
self.functions.clear();
|
||||
}
|
||||
|
||||
/// Initialize the state for compiling a function with the given signature.
|
||||
@@ -291,17 +298,37 @@ impl TranslationState {
|
||||
index: u32,
|
||||
environ: &FE,
|
||||
) -> (ir::SigRef, usize) {
|
||||
let index = index as MemoryIndex;
|
||||
let index = index as SignatureIndex;
|
||||
*self.signatures.entry(index).or_insert_with(|| {
|
||||
let sig = environ.make_indirect_sig(func, index);
|
||||
// Count the number of normal arguments.
|
||||
// The environment is allowed to add special purpose arguments to the signature.
|
||||
let args = func.dfg.signatures[sig]
|
||||
.argument_types
|
||||
.iter()
|
||||
.filter(|arg| arg.purpose == ir::ArgumentPurpose::Normal)
|
||||
.count();
|
||||
(sig, args)
|
||||
(sig, normal_args(&func.dfg.signatures[sig]))
|
||||
})
|
||||
}
|
||||
|
||||
/// Get the `FuncRef` reference that should be used to make a direct call to function
|
||||
/// `index`. Also return the number of WebAssembly arguments in the signature.
|
||||
///
|
||||
/// Create the function reference if necessary.
|
||||
pub fn get_direct_func<FE: FuncEnvironment + ?Sized>(
|
||||
&mut self,
|
||||
func: &mut ir::Function,
|
||||
index: u32,
|
||||
environ: &FE,
|
||||
) -> (ir::FuncRef, usize) {
|
||||
let index = index as FunctionIndex;
|
||||
*self.functions.entry(index).or_insert_with(|| {
|
||||
let fref = environ.make_direct_func(func, index);
|
||||
let sig = func.dfg.ext_funcs[fref].signature;
|
||||
(fref, normal_args(&func.dfg.signatures[sig]))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Count the number of normal arguments in a signature.
|
||||
/// Exclude special-purpose arguments that represent runtime stuff and not WebAssembly arguments.
|
||||
fn normal_args(sig: &ir::Signature) -> usize {
|
||||
sig.argument_types
|
||||
.iter()
|
||||
.filter(|arg| arg.purpose == ir::ArgumentPurpose::Normal)
|
||||
.count()
|
||||
}
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
use wasmparser;
|
||||
use cretonne;
|
||||
use std::u32;
|
||||
use code_translator;
|
||||
use module_translator;
|
||||
|
||||
/// Index of a function (imported or defined) inside the WebAssembly module.
|
||||
pub type FunctionIndex = usize;
|
||||
@@ -135,19 +133,3 @@ pub fn translate_type(ty: wasmparser::Type) -> Result<Vec<cretonne::ir::Type>, (
|
||||
_ => panic!("unsupported return value type"),
|
||||
}
|
||||
}
|
||||
|
||||
/// Inverts the key-value relation in the imports hashmap. Indeed, these hashmaps are built by
|
||||
/// feeding the function indexes in the module but are used by the runtime with the `FuncRef` as
|
||||
/// keys.
|
||||
pub fn invert_hashmaps(
|
||||
imports: &code_translator::FunctionImports,
|
||||
) -> module_translator::ImportMappings {
|
||||
let mut new_imports = module_translator::ImportMappings::new();
|
||||
for (func_index, func_ref) in &imports.functions {
|
||||
new_imports.functions.insert(*func_ref, *func_index);
|
||||
}
|
||||
for (sig_index, sig_ref) in &imports.signatures {
|
||||
new_imports.signatures.insert(*sig_ref, *sig_index);
|
||||
}
|
||||
new_imports
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user