Propagate module-linking types to wasmtime (#2115)

This commit adds lots of plumbing to get the type section from the
module linking proposal plumbed all the way through to the `wasmtime`
crate and the `wasmtime-c-api` crate. This isn't all that useful right
now because Wasmtime doesn't support imported/exported
modules/instances, but this is all necessary groundwork to getting that
exported at some point. I've added some light tests but I suspect the
bulk of the testing will come in a future commit.

One major change in this commit is that `SignatureIndex` no longer
follows type type index space in a wasm module. Instead a new
`TypeIndex` type is used to track that. Function signatures, still
indexed by `SignatureIndex`, are then packed together tightly.
This commit is contained in:
Alex Crichton
2020-11-06 14:48:09 -06:00
committed by GitHub
parent 77827a48a9
commit 73cda83548
27 changed files with 782 additions and 213 deletions

View File

@@ -1,13 +1,13 @@
use crate::module::{EntityIndex, MemoryPlan, Module, TableElements, TablePlan};
use crate::module::{MemoryPlan, Module, ModuleType, TableElements, TablePlan};
use crate::tunables::Tunables;
use cranelift_codegen::ir;
use cranelift_codegen::ir::{AbiParam, ArgumentPurpose};
use cranelift_codegen::isa::TargetFrontendConfig;
use cranelift_entity::PrimaryMap;
use cranelift_wasm::{
self, translate_module, DataIndex, DefinedFuncIndex, ElemIndex, FuncIndex, Global, GlobalIndex,
Memory, MemoryIndex, SignatureIndex, Table, TableIndex, TargetEnvironment, WasmError,
WasmFuncType, WasmResult,
self, translate_module, DataIndex, DefinedFuncIndex, ElemIndex, EntityIndex, EntityType,
FuncIndex, Global, GlobalIndex, Memory, MemoryIndex, SignatureIndex, Table, TableIndex,
TargetEnvironment, TypeIndex, WasmError, WasmFuncType, WasmResult,
};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
@@ -201,18 +201,54 @@ impl<'data> TargetEnvironment for ModuleEnvironment<'data> {
/// This trait is useful for `translate_module` because it tells how to translate
/// environment-dependent wasm instructions. These functions should not be called by the user.
impl<'data> cranelift_wasm::ModuleEnvironment<'data> for ModuleEnvironment<'data> {
fn reserve_signatures(&mut self, num: u32) -> WasmResult<()> {
fn reserve_types(&mut self, num: u32) -> WasmResult<()> {
let num = usize::try_from(num).unwrap();
self.result.module.signatures.reserve_exact(num);
self.result.module.types.reserve_exact(num);
self.result.native_signatures.reserve_exact(num);
Ok(())
}
fn declare_signature(&mut self, wasm: WasmFuncType, sig: ir::Signature) -> WasmResult<()> {
fn declare_type_func(&mut self, wasm: WasmFuncType, sig: ir::Signature) -> WasmResult<()> {
let sig = translate_signature(sig, self.pointer_type());
// TODO: Deduplicate signatures.
self.result.module.signatures.push(wasm);
self.result.native_signatures.push(sig);
let sig_index = self.result.module.signatures.push(wasm);
self.result
.module
.types
.push(ModuleType::Function(sig_index));
Ok(())
}
fn declare_type_module(
&mut self,
imports: &[(&'data str, Option<&'data str>, EntityType)],
exports: &[(&'data str, EntityType)],
) -> WasmResult<()> {
let imports = imports
.iter()
.map(|i| (i.0.to_string(), i.1.map(|s| s.to_string()), i.2.clone()))
.collect();
let exports = exports
.iter()
.map(|e| (e.0.to_string(), e.1.clone()))
.collect();
self.result
.module
.types
.push(ModuleType::Module { imports, exports });
Ok(())
}
fn declare_type_instance(&mut self, exports: &[(&'data str, EntityType)]) -> WasmResult<()> {
let exports = exports
.iter()
.map(|e| (e.0.to_string(), e.1.clone()))
.collect();
self.result
.module
.types
.push(ModuleType::Instance { exports });
Ok(())
}
@@ -226,7 +262,7 @@ impl<'data> cranelift_wasm::ModuleEnvironment<'data> for ModuleEnvironment<'data
fn declare_func_import(
&mut self,
sig_index: SignatureIndex,
index: TypeIndex,
module: &str,
field: &str,
) -> WasmResult<()> {
@@ -235,6 +271,7 @@ impl<'data> cranelift_wasm::ModuleEnvironment<'data> for ModuleEnvironment<'data
self.result.module.num_imported_funcs,
"Imported functions must be declared first"
);
let sig_index = self.result.module.types[index].unwrap_function();
let func_index = self.result.module.functions.push(sig_index);
self.result.module.imports.push((
module.to_owned(),
@@ -320,7 +357,8 @@ impl<'data> cranelift_wasm::ModuleEnvironment<'data> for ModuleEnvironment<'data
Ok(())
}
fn declare_func_type(&mut self, sig_index: SignatureIndex) -> WasmResult<()> {
fn declare_func_type(&mut self, index: TypeIndex) -> WasmResult<()> {
let sig_index = self.result.module.types[index].unwrap_function();
self.result.module.functions.push(sig_index);
Ok(())
}