Skip to content

Commit 74099ad

Browse files
committed
Get tests working for globals and shims
1 parent 4313624 commit 74099ad

File tree

9 files changed

+142
-170
lines changed

9 files changed

+142
-170
lines changed

compiler-rs/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ wee_alloc = { version = "0.4.5", optional = true }
3232

3333

3434
[dev-dependencies]
35-
wasmi = "0.8.0"
35+
# https://github.com/paritytech/wasmi/issues/252
36+
wasmi = { git = "https://github.com/paritytech/wasmi", branch = "master" }
3637
wabt = "0.9.0"
3738
wasm-bindgen-test = "0.3.13"
3839
wasmprinter = "0.2.0"

compiler-rs/src/emitter.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,9 @@ impl Emitter {
5454
imports.push(make_import_entry(self.current_pool.clone(), global.clone()));
5555
}
5656

57-
let (function_exports, function_bodies, funcs) = self.emit_programs(programs)?;
57+
self.shims.get(Shim::Sin);
58+
59+
let (function_exports, function_bodies, funcs) = self.emit_programs(programs, 1)?;
5860

5961
for shim in self.shims.keys() {
6062
let type_index = self.function_types.get(shim.get_type());
@@ -143,13 +145,17 @@ impl Emitter {
143145
fn emit_programs(
144146
&mut self,
145147
programs: Vec<(String, Program, String)>,
148+
offset: u32,
146149
) -> EmitterResult<(Vec<ExportEntry>, Vec<FuncBody>, Vec<Func>)> {
147150
let mut exports = Vec::new();
148151
let mut function_bodies = Vec::new();
149152
let mut function_definitions = Vec::new();
150153
for (i, (name, program, pool_name)) in programs.into_iter().enumerate() {
151154
self.current_pool = pool_name;
152-
exports.push(ExportEntry::new(name, Internal::Function(i as u32)));
155+
exports.push(ExportEntry::new(
156+
name,
157+
Internal::Function(i as u32 + offset),
158+
));
153159
let locals = Vec::new();
154160
function_bodies.push(FuncBody::new(locals, self.emit_program(program)?));
155161

compiler-rs/src/index_store.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,18 @@ impl<T: Eq + Hash> IndexStore<T> {
2929
self.map.keys().collect()
3030
}
3131
}
32+
33+
#[cfg(test)]
34+
mod tests {
35+
use super::*;
36+
use crate::EelFunctionType;
37+
#[test]
38+
fn tuple() {
39+
let mut function_types: IndexStore<EelFunctionType> = IndexStore::new();
40+
let one_arg_one_return = function_types.get((1, 1));
41+
let no_arg_one_return = function_types.get((0, 1));
42+
43+
assert_eq!(one_arg_one_return, 0);
44+
assert_eq!(no_arg_one_return, 1);
45+
}
46+
}

compiler-rs/tests/common/mod.rs

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
extern crate eel_wasm;
2+
3+
use wasmi::nan_preserving_float::F64;
4+
use wasmi::RuntimeValue;
5+
use wasmi::{
6+
Error as WasmiError, Externals, FuncInstance, FuncRef, GlobalDescriptor, GlobalInstance,
7+
GlobalRef, ModuleImportResolver, RuntimeArgs, Signature, Trap, ValueType,
8+
};
9+
10+
pub struct GlobalPool {}
11+
12+
impl GlobalPool {
13+
fn check_signature(&self, index: usize, signature: &Signature) -> bool {
14+
let (params, ret_ty): (&[ValueType], Option<ValueType>) = match index {
15+
SIN_FUNC_INDEX => (&[ValueType::F64], Some(ValueType::F64)),
16+
_ => return false,
17+
};
18+
signature.params() == params && signature.return_type() == ret_ty
19+
}
20+
}
21+
22+
impl ModuleImportResolver for GlobalPool {
23+
fn resolve_global(
24+
&self,
25+
_field_name: &str,
26+
_global_type: &GlobalDescriptor,
27+
) -> Result<GlobalRef, WasmiError> {
28+
let global = GlobalInstance::alloc(RuntimeValue::F64(F64::from_float(0.0)), true);
29+
Ok(global)
30+
}
31+
fn resolve_func(&self, field_name: &str, signature: &Signature) -> Result<FuncRef, WasmiError> {
32+
let index = match field_name {
33+
"sin" => SIN_FUNC_INDEX,
34+
_ => {
35+
return Err(WasmiError::Instantiation(format!(
36+
"Export {} not found",
37+
field_name
38+
)))
39+
}
40+
};
41+
42+
if !self.check_signature(index, signature) {
43+
return Err(WasmiError::Instantiation(format!(
44+
"Export {} has a bad signature",
45+
field_name
46+
)));
47+
}
48+
49+
Ok(FuncInstance::alloc_host(
50+
Signature::new(&[ValueType::F64][..], Some(ValueType::F64)),
51+
index,
52+
))
53+
}
54+
}
55+
56+
const SIN_FUNC_INDEX: usize = 0;
57+
58+
impl Externals for GlobalPool {
59+
fn invoke_index(
60+
&mut self,
61+
index: usize,
62+
args: RuntimeArgs,
63+
) -> Result<Option<RuntimeValue>, Trap> {
64+
match index {
65+
SIN_FUNC_INDEX => {
66+
let a: F64 = args.nth_checked(0)?;
67+
68+
let result = a.to_float().sin();
69+
70+
Ok(Some(RuntimeValue::F64(F64::from(result))))
71+
}
72+
_ => panic!("Unimplemented function at {}", index),
73+
}
74+
}
75+
}

compiler-rs/tests/compatibility_test.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,23 @@
1+
use common::GlobalPool;
12
use eel_wasm::compile;
2-
use wasmi::{ImportsBuilder, ModuleInstance, NopExternals, RuntimeValue};
3+
use wasmi::{ImportsBuilder, ModuleInstance, RuntimeValue};
4+
mod common;
35

46
fn run(body: &[u8]) -> Result<f64, String> {
57
let wasm_binary = body;
68
let module = wasmi::Module::from_buffer(&wasm_binary).expect("failed to load wasm");
7-
let instance = ModuleInstance::new(&module, &ImportsBuilder::default())
9+
let mut global_imports = GlobalPool {};
10+
let mut imports = ImportsBuilder::default();
11+
imports.push_resolver("pool", &global_imports);
12+
imports.push_resolver("shims", &global_imports);
13+
let instance = ModuleInstance::new(&module, &imports)
814
.expect("failed to instantiate wasm module")
915
.assert_no_start();
1016

1117
// Finally, invoke the exported function "test" with no parameters
1218
// and empty external function executor.
1319
match instance
14-
.invoke_export("test", &[], &mut NopExternals)
20+
.invoke_export("test", &[], &mut global_imports)
1521
.expect("failed to execute export")
1622
{
1723
Some(RuntimeValue::F64(val)) => Ok(val.into()),
@@ -540,7 +546,10 @@ fn compatibility_tests() {
540546
];
541547

542548
for (name, code, expected) in test_cases {
543-
match compile(vec![("test".to_string(), code, "pool".to_string())], vec![]) {
549+
match compile(
550+
vec![("test".to_string(), code, "pool".to_string())],
551+
vec![("pool".to_string(), "g".to_string())],
552+
) {
544553
Ok(binary) => {
545554
if expected_failing.contains(name) {
546555
panic!(format!("Expected {} to fail, but it passed!", name));

compiler-rs/tests/fixtures/wat/one_plus_one.snapshot

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22
========================================================================
33
(module
44
(type (;0;) (func (result f64)))
5-
(func (;0;) (type 0) (result f64)
5+
(type (;1;) (func (param f64) (result f64)))
6+
(import "shims" "sin" (func (;0;) (type 1)))
7+
(func (;1;) (type 0) (result f64)
68
f64.const 0x1p+0 (;=1;)
79
f64.const 0x1p+0 (;=1;)
810
f64.add)
9-
(export "test" (func 0)))
11+
(export "test" (func 1)))

compiler-rs/tests/fixtures/wat/reg.snapshot

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@ reg00=10
22
========================================================================
33
(module
44
(type (;0;) (func (result f64)))
5-
(func (;0;) (type 0) (result f64)
5+
(type (;1;) (func (param f64) (result f64)))
6+
(import "shims" "sin" (func (;0;) (type 1)))
7+
(func (;1;) (type 0) (result f64)
68
f64.const 0x1.4p+3 (;=10;)
79
global.set 0
810
global.get 0)
911
(global (;0;) (mut f64) (f64.const 0x0p+0 (;=0;)))
10-
(export "test" (func 0)))
12+
(export "test" (func 1)))

compiler-rs/tests/fixtures/wat/sin.snapshot

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,4 @@ sin(100)
77
(func (;1;) (type 0) (result f64)
88
f64.const 0x1.9p+6 (;=100;)
99
call 0)
10-
(export "test" (func 0)))
10+
(export "test" (func 1)))

0 commit comments

Comments
 (0)