Skip to content

Commit 144bed9

Browse files
committed
Get tests working for globals and shims
1 parent 4313624 commit 144bed9

8 files changed

+67
-170
lines changed

compiler-rs/Cargo.toml

+2-1
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

+8-2
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

+15
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/compatibility_test.rs

+13-4
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

+4-2
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

+4-2
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

+1-1
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)))

compiler-rs/tests/intagration_test.rs

+20-158
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,24 @@
11
extern crate eel_wasm;
2+
mod common;
23

3-
use std::{collections::HashMap, io};
4-
4+
use common::GlobalPool;
55
use eel_wasm::compile;
6-
use wasmi::nan_preserving_float::F64;
7-
use wasmi::RuntimeValue;
8-
use wasmi::{
9-
Error as WasmiError, Externals, FuncInstance, FuncRef, GlobalDescriptor, GlobalInstance,
10-
GlobalRef, ImportsBuilder, ModuleImportResolver, ModuleInstance, NopExternals, RuntimeArgs,
11-
Signature, Trap, ValueType,
12-
};
6+
use wasmi::{ImportsBuilder, ModuleInstance, RuntimeValue};
137

148
fn run(body: &[u8]) -> Result<f64, String> {
159
let wasm_binary = body;
1610
let module = wasmi::Module::from_buffer(&wasm_binary).expect("failed to load wasm");
17-
let instance = ModuleInstance::new(&module, &ImportsBuilder::default())
11+
12+
let mut global_imports = GlobalPool {};
13+
let mut imports = ImportsBuilder::default();
14+
imports.push_resolver("pool", &global_imports);
15+
imports.push_resolver("shims", &global_imports);
16+
let instance = ModuleInstance::new(&module, &imports)
1817
.expect("failed to instantiate wasm module")
1918
.assert_no_start();
2019

21-
// Finally, invoke the exported function "test" with no parameters
22-
// and empty external function executor.
2320
match instance
24-
.invoke_export("test", &[], &mut NopExternals)
21+
.invoke_export("test", &[], &mut global_imports)
2522
.expect("failed to execute export")
2623
{
2724
Some(RuntimeValue::F64(val)) => Ok(val.into()),
@@ -42,18 +39,6 @@ fn test_run(program: &str, expected_output: f64) {
4239
);
4340
}
4441

45-
#[test]
46-
fn build_one() -> io::Result<()> {
47-
assert_eq!(
48-
&compile(vec![("test".to_string(), "1", "pool".to_string())], vec![]).unwrap(),
49-
&[
50-
0, 97, 115, 109, 1, 0, 0, 0, 1, 5, 1, 96, 0, 1, 124, 3, 2, 1, 0, 7, 8, 1, 4, 116, 101,
51-
115, 116, 0, 0, 10, 13, 1, 11, 0, 68, 0, 0, 0, 0, 0, 0, 240, 63, 11,
52-
]
53-
);
54-
Ok(())
55-
}
56-
5742
#[test]
5843
fn execute_one() {
5944
test_run("1", 1.0);
@@ -65,142 +50,14 @@ fn execute_one() {
6550
test_run("1+1*2", 3.0);
6651
}
6752

68-
struct GlobalPool {
69-
globals: HashMap<String, GlobalRef>,
70-
}
71-
72-
impl ModuleImportResolver for GlobalPool {
73-
fn resolve_global(
74-
&self,
75-
field_name: &str,
76-
_global_type: &GlobalDescriptor,
77-
) -> Result<GlobalRef, WasmiError> {
78-
let global = GlobalInstance::alloc(RuntimeValue::F64(F64::from_float(0.0)), true);
79-
Ok(global)
80-
}
81-
fn resolve_func(&self, field_name: &str, signature: &Signature) -> Result<FuncRef, WasmiError> {
82-
println!("Calling function: {}", field_name);
83-
let index = match field_name {
84-
"sin" => SIN_FUNC_INDEX,
85-
_ => {
86-
return Err(WasmiError::Instantiation(format!(
87-
"Export {} not found",
88-
field_name
89-
)))
90-
}
91-
};
92-
93-
if !self.check_signature(index, signature) {
94-
return Err(WasmiError::Instantiation(format!(
95-
"Export {} has a bad signature",
96-
field_name
97-
)));
98-
}
99-
100-
println!("PAssed sig check: {}", field_name);
101-
102-
Ok(FuncInstance::alloc_host(
103-
Signature::new(&[ValueType::F64][..], Some(ValueType::F64)),
104-
index,
105-
))
106-
}
107-
}
108-
109-
const SIN_FUNC_INDEX: usize = 0;
110-
111-
impl Externals for GlobalPool {
112-
fn invoke_index(
113-
&mut self,
114-
index: usize,
115-
args: RuntimeArgs,
116-
) -> Result<Option<RuntimeValue>, Trap> {
117-
println!("Calling index {}", index);
118-
match index {
119-
SIN_FUNC_INDEX => {
120-
let a: F64 = args.nth_checked(0)?;
121-
println!("First arg was {:?}", a);
122-
123-
let result = a * 2;
124-
125-
Ok(Some(RuntimeValue::F64(F64::from(result))))
126-
}
127-
_ => panic!("Unimplemented function at {}", index),
128-
}
129-
}
130-
}
131-
132-
impl GlobalPool {
133-
fn check_signature(&self, index: usize, signature: &Signature) -> bool {
134-
println!("Checking sig of {}", index);
135-
let (params, ret_ty): (&[ValueType], Option<ValueType>) = match index {
136-
SIN_FUNC_INDEX => (&[ValueType::F64], Some(ValueType::F64)),
137-
_ => return false,
138-
};
139-
signature.params() == params && signature.return_type() == ret_ty
140-
}
141-
}
142-
14353
#[test]
144-
#[ignore]
14554
fn with_global() {
146-
let global_imports = GlobalPool {
147-
globals: HashMap::default(),
148-
};
149-
let wasm_binary = compile(
150-
vec![("test".to_string(), "g=1", "pool".to_string())],
151-
vec![("g".to_string(), "pool".to_string())],
152-
)
153-
.expect("Expect to compile");
154-
// TODO: This will fail becuase wasmi 0.8.0 depends upon wasmi-validaiton
155-
// 0.3.0 which does not include https://github.com/paritytech/wasmi/pull/228
156-
// which allows mutable globals.
157-
// 0.3.1 has the PR, but wasmi has not shipped a new version that includes it.
158-
// parity-wasm already depends upon 0.3.1 (I _think_)
159-
let module = wasmi::Module::from_buffer(&wasm_binary).expect("No validation errors");
160-
let mut imports = ImportsBuilder::default();
161-
imports.push_resolver("pool", &global_imports);
162-
let instance = ModuleInstance::new(&module, &imports)
163-
.expect("failed to instantiate wasm module")
164-
.assert_no_start();
165-
166-
// Finally, invoke the exported function "test" with no parameters
167-
// and empty external function executor.
168-
instance
169-
.invoke_export("test", &[], &mut NopExternals)
170-
.expect("failed to execute export")
171-
.expect("Ran");
55+
test_run("g=1", 1.0);
17256
}
17357

17458
#[test]
175-
#[ignore]
17659
fn with_shims() {
177-
let global_imports = GlobalPool {
178-
globals: HashMap::default(),
179-
};
180-
let wasm_binary = compile(
181-
vec![("test".to_string(), "sin(10)", "pool".to_string())],
182-
vec![],
183-
)
184-
.expect("Expect to compile");
185-
// TODO: This will fail becuase wasmi 0.8.0 depends upon wasmi-validaiton
186-
// 0.3.0 which does not include https://github.com/paritytech/wasmi/pull/228
187-
// which allows mutable globals.
188-
// 0.3.1 has the PR, but wasmi has not shipped a new version that includes it.
189-
// parity-wasm already depends upon 0.3.1 (I _think_)
190-
let module = wasmi::Module::from_buffer(&wasm_binary).expect("No validation errors");
191-
let mut imports = ImportsBuilder::default();
192-
imports.push_resolver("pool", &global_imports);
193-
imports.push_resolver("shims", &global_imports);
194-
let instance = ModuleInstance::new(&module, &imports)
195-
.expect("failed to instantiate wasm module")
196-
.assert_no_start();
197-
198-
// Finally, invoke the exported function "test" with no parameters
199-
// and empty external function executor.
200-
instance
201-
.invoke_export("test", &[], &mut NopExternals)
202-
.expect("failed to execute export")
203-
.expect("Ran");
60+
test_run("sin(10)", 10.0_f64.sin());
20461
}
20562

20663
#[test]
@@ -219,17 +76,22 @@ fn multiple_functions() {
21976
// 0.3.1 has the PR, but wasmi has not shipped a new version that includes it.
22077
// parity-wasm already depends upon 0.3.1 (I _think_)
22178
let module = wasmi::Module::from_buffer(&wasm_binary).expect("No validation errors");
222-
let instance = ModuleInstance::new(&module, &ImportsBuilder::default())
79+
let mut global_imports = GlobalPool {};
80+
let mut imports = ImportsBuilder::default();
81+
imports.push_resolver("pool", &global_imports);
82+
imports.push_resolver("shims", &global_imports);
83+
84+
let instance = ModuleInstance::new(&module, &imports)
22385
.expect("failed to instantiate wasm module")
22486
.assert_no_start();
22587

22688
instance
227-
.invoke_export("one", &[], &mut NopExternals)
89+
.invoke_export("one", &[], &mut global_imports)
22890
.expect("failed to execute export")
22991
.expect("Ran");
23092

23193
instance
232-
.invoke_export("two", &[], &mut NopExternals)
94+
.invoke_export("two", &[], &mut global_imports)
23395
.expect("failed to execute export")
23496
.expect("Ran");
23597
}

0 commit comments

Comments
 (0)