1 use std::sync::Arc;
2 use std::sync::atomic::Ordering;
3 use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering::SeqCst};
4 use wasmtime::bail;
5 use wasmtime::*;
6 use wasmtime_test_macros::wasmtime_test;
7
8 #[wasmtime_test]
9 #[cfg_attr(miri, ignore)]
call_wasm_to_wasm(config: &mut Config) -> Result<()>10 fn call_wasm_to_wasm(config: &mut Config) -> Result<()> {
11 let wasm = wat::parse_str(
12 r#"
13 (module
14 (func (result i32 i32 i32)
15 i32.const 1
16 i32.const 2
17 i32.const 3
18 )
19 (func (export "run") (result i32 i32 i32)
20 call 0
21 )
22 )
23 "#,
24 )?;
25 let engine = Engine::new(&config)?;
26 let mut store = Store::<()>::new(&engine, ());
27 let module = Module::new(store.engine(), &wasm)?;
28 let instance = Instance::new(&mut store, &module, &[])?;
29 let func = instance
30 .get_typed_func::<(), (i32, i32, i32)>(&mut store, "run")
31 .unwrap();
32 let results = func.call(&mut store, ())?;
33 assert_eq!(results, (1, 2, 3));
34 Ok(())
35 }
36
37 #[wasmtime_test]
38 #[cfg_attr(miri, ignore)]
call_wasm_to_native(config: &mut Config) -> Result<()>39 fn call_wasm_to_native(config: &mut Config) -> Result<()> {
40 let wasm = wat::parse_str(
41 r#"
42 (module
43 (import "" "" (func (result i32 i32 i32)))
44 (func (export "run") (result i32 i32 i32)
45 call 0
46 )
47 )
48 "#,
49 )?;
50 let engine = Engine::new(&config)?;
51 let mut store = Store::<()>::new(&engine, ());
52 let module = Module::new(store.engine(), &wasm)?;
53 let import_func = Func::wrap(&mut store, || (1_i32, 2_i32, 3_i32));
54 let instance = Instance::new(&mut store, &module, &[import_func.into()])?;
55 let func = instance
56 .get_typed_func::<(), (i32, i32, i32)>(&mut store, "run")
57 .unwrap();
58 let results = func.call(&mut store, ())?;
59 assert_eq!(results, (1, 2, 3));
60 Ok(())
61 }
62
63 #[wasmtime_test]
64 #[cfg_attr(miri, ignore)]
call_wasm_to_array(config: &mut Config) -> Result<()>65 fn call_wasm_to_array(config: &mut Config) -> Result<()> {
66 let wasm = wat::parse_str(
67 r#"
68 (module
69 (import "" "" (func (result i32 i32 i32)))
70 (func (export "run") (result i32 i32 i32)
71 call 0
72 )
73 )
74 "#,
75 )?;
76 let engine = Engine::new(&config)?;
77 let mut store = Store::<()>::new(&engine, ());
78 let module = Module::new(store.engine(), &wasm)?;
79 let func_ty = FuncType::new(
80 store.engine(),
81 vec![],
82 vec![ValType::I32, ValType::I32, ValType::I32],
83 );
84 let import_func = Func::new(&mut store, func_ty, |_, _params, results| {
85 results[0] = Val::I32(1);
86 results[1] = Val::I32(2);
87 results[2] = Val::I32(3);
88 Ok(())
89 });
90 let instance = Instance::new(&mut store, &module, &[import_func.into()])?;
91 let func = instance
92 .get_typed_func::<(), (i32, i32, i32)>(&mut store, "run")
93 .unwrap();
94 let results = func.call(&mut store, ())?;
95 assert_eq!(results, (1, 2, 3));
96 Ok(())
97 }
98
99 #[wasmtime_test]
100 #[cfg_attr(miri, ignore)]
call_native_to_wasm(config: &mut Config) -> Result<()>101 fn call_native_to_wasm(config: &mut Config) -> Result<()> {
102 let wasm = wat::parse_str(
103 r#"
104 (module
105 (func (export "run") (result i32 i32 i32)
106 i32.const 42
107 i32.const 420
108 i32.const 4200
109 )
110 )
111 "#,
112 )?;
113 let engine = Engine::new(&config)?;
114 let mut store = Store::<()>::new(&engine, ());
115 let module = Module::new(store.engine(), &wasm)?;
116 let instance = Instance::new(&mut store, &module, &[])?;
117 let func = instance
118 .get_typed_func::<(), (i32, i32, i32)>(&mut store, "run")
119 .unwrap();
120 let results = func.call(&mut store, ())?;
121 assert_eq!(results, (42, 420, 4200));
122 Ok(())
123 }
124
125 #[test]
call_native_to_native() -> Result<()>126 fn call_native_to_native() -> Result<()> {
127 let mut store = Store::<()>::default();
128
129 let func = Func::wrap(&mut store, |a: i32, b: i32, c: i32| -> (i32, i32, i32) {
130 (b, c, a)
131 });
132 let func = func.typed::<(i32, i32, i32), (i32, i32, i32)>(&store)?;
133 let results = func.call(&mut store, (1, 2, 3))?;
134 assert_eq!(results, (2, 3, 1));
135 Ok(())
136 }
137
138 #[test]
139 #[cfg_attr(miri, ignore)]
call_native_to_array() -> Result<()>140 fn call_native_to_array() -> Result<()> {
141 let mut store = Store::<()>::default();
142
143 let func_ty = FuncType::new(
144 store.engine(),
145 [ValType::I32, ValType::I32, ValType::I32],
146 [ValType::I32, ValType::I32, ValType::I32],
147 );
148 let func = Func::new(&mut store, func_ty, |_caller, params, results| {
149 results[0] = params[2];
150 results[1] = params[0];
151 results[2] = params[1];
152 Ok(())
153 });
154 let func = func.typed::<(i32, i32, i32), (i32, i32, i32)>(&store)?;
155 let results = func.call(&mut store, (1, 2, 3))?;
156 assert_eq!(results, (3, 1, 2));
157 Ok(())
158 }
159
160 #[wasmtime_test]
161 #[cfg_attr(miri, ignore)]
call_array_to_wasm(config: &mut Config) -> Result<()>162 fn call_array_to_wasm(config: &mut Config) -> Result<()> {
163 let wasm = wat::parse_str(
164 r#"
165 (module
166 (func (export "run") (param i32 i32 i32) (result i32 i32 i32)
167 local.get 1
168 local.get 2
169 local.get 0
170 )
171 )
172 "#,
173 )?;
174 let engine = Engine::new(&config)?;
175 let mut store = Store::<()>::new(&engine, ());
176 let module = Module::new(store.engine(), &wasm)?;
177 let instance = Instance::new(&mut store, &module, &[])?;
178 let func = instance.get_func(&mut store, "run").unwrap();
179 let mut results = [Val::I32(0), Val::I32(0), Val::I32(0)];
180 func.call(
181 &mut store,
182 &[Val::I32(10), Val::I32(20), Val::I32(30)],
183 &mut results,
184 )?;
185 assert_eq!(results[0].i32(), Some(20));
186 assert_eq!(results[1].i32(), Some(30));
187 assert_eq!(results[2].i32(), Some(10));
188 Ok(())
189 }
190
191 #[test]
call_array_to_native() -> Result<()>192 fn call_array_to_native() -> Result<()> {
193 let mut store = Store::<()>::default();
194 let func = Func::wrap(&mut store, |a: i32, b: i32, c: i32| -> (i32, i32, i32) {
195 (a * 10, b * 10, c * 10)
196 });
197 let mut results = [Val::I32(0), Val::I32(0), Val::I32(0)];
198 func.call(
199 &mut store,
200 &[Val::I32(10), Val::I32(20), Val::I32(30)],
201 &mut results,
202 )?;
203 assert_eq!(results[0].i32(), Some(100));
204 assert_eq!(results[1].i32(), Some(200));
205 assert_eq!(results[2].i32(), Some(300));
206 Ok(())
207 }
208
209 #[test]
210 #[cfg_attr(miri, ignore)]
call_array_to_array() -> Result<()>211 fn call_array_to_array() -> Result<()> {
212 let mut store = Store::<()>::default();
213 let func_ty = FuncType::new(
214 store.engine(),
215 [ValType::I32, ValType::I32, ValType::I32],
216 [ValType::I32, ValType::I32, ValType::I32],
217 );
218 let func = Func::new(&mut store, func_ty, |_caller, params, results| {
219 results[0] = params[2];
220 results[1] = params[0];
221 results[2] = params[1];
222 Ok(())
223 });
224 let mut results = [Val::I32(0), Val::I32(0), Val::I32(0)];
225 func.call(
226 &mut store,
227 &[Val::I32(10), Val::I32(20), Val::I32(30)],
228 &mut results,
229 )?;
230 assert_eq!(results[0].i32(), Some(30));
231 assert_eq!(results[1].i32(), Some(10));
232 assert_eq!(results[2].i32(), Some(20));
233 Ok(())
234 }
235
236 #[wasmtime_test(wasm_features(reference_types))]
237 #[cfg_attr(miri, ignore)]
call_indirect_native_from_wasm_import_global(config: &mut Config) -> Result<()>238 fn call_indirect_native_from_wasm_import_global(config: &mut Config) -> Result<()> {
239 let wasm = wat::parse_str(
240 r#"
241 (module
242 (import "" "" (global funcref))
243 (table 1 1 funcref)
244 (func (export "run") (result i32 i32 i32)
245 i32.const 0
246 global.get 0
247 table.set
248 i32.const 0
249 call_indirect (result i32 i32 i32)
250 )
251 )
252 "#,
253 )?;
254 let engine = Engine::new(&config)?;
255 let mut store = Store::<()>::new(&engine, ());
256 let module = Module::new(store.engine(), &wasm)?;
257 let func = Func::wrap(&mut store, || -> (i32, i32, i32) { (10, 20, 30) });
258 let global = Global::new(
259 &mut store,
260 GlobalType::new(ValType::FUNCREF, Mutability::Const),
261 Val::FuncRef(Some(func)),
262 )?;
263 let instance = Instance::new(&mut store, &module, &[global.into()])?;
264 let func = instance.get_typed_func::<(), (i32, i32, i32)>(&mut store, "run")?;
265 let results = func.call(&mut store, ())?;
266 assert_eq!(results, (10, 20, 30));
267 Ok(())
268 }
269
270 #[wasmtime_test]
271 #[cfg_attr(miri, ignore)]
call_indirect_native_from_wasm_import_table(config: &mut Config) -> Result<()>272 fn call_indirect_native_from_wasm_import_table(config: &mut Config) -> Result<()> {
273 let wasm = wat::parse_str(
274 r#"
275 (module
276 (import "" "" (table 1 1 funcref))
277 (func (export "run") (result i32 i32 i32)
278 i32.const 0
279 call_indirect (result i32 i32 i32)
280 )
281 )
282 "#,
283 )?;
284 let engine = Engine::new(&config)?;
285 let mut store = Store::<()>::new(&engine, ());
286 let module = Module::new(store.engine(), &wasm)?;
287 let func = Func::wrap(&mut store, || -> (i32, i32, i32) { (10, 20, 30) });
288 let table = Table::new(
289 &mut store,
290 TableType::new(RefType::FUNCREF, 1, Some(1)),
291 Ref::Func(Some(func)),
292 )?;
293 let instance = Instance::new(&mut store, &module, &[table.into()])?;
294 let func = instance.get_typed_func::<(), (i32, i32, i32)>(&mut store, "run")?;
295 let results = func.call(&mut store, ())?;
296 assert_eq!(results, (10, 20, 30));
297 Ok(())
298 }
299
300 #[wasmtime_test(wasm_features(reference_types))]
301 #[cfg_attr(miri, ignore)]
call_indirect_native_from_wasm_import_func_returns_funcref(config: &mut Config) -> Result<()>302 fn call_indirect_native_from_wasm_import_func_returns_funcref(config: &mut Config) -> Result<()> {
303 let wasm = wat::parse_str(
304 r#"
305 (module
306 (import "" "" (func (result funcref)))
307 (table 1 1 funcref)
308 (func (export "run") (result i32 i32 i32)
309 i32.const 0
310 call 0
311 table.set
312 i32.const 0
313 call_indirect (result i32 i32 i32)
314 )
315 )
316 "#,
317 )?;
318 let engine = Engine::new(&config)?;
319 let mut store = Store::<()>::new(&engine, ());
320 let module = Module::new(store.engine(), &wasm)?;
321 let func = Func::wrap(&mut store, || -> (i32, i32, i32) { (10, 20, 30) });
322 let get_func = Func::wrap(&mut store, move || -> Option<Func> { Some(func) });
323 let instance = Instance::new(&mut store, &module, &[get_func.into()])?;
324 let func = instance.get_typed_func::<(), (i32, i32, i32)>(&mut store, "run")?;
325 let results = func.call(&mut store, ())?;
326 assert_eq!(results, (10, 20, 30));
327 Ok(())
328 }
329
330 #[wasmtime_test]
331 #[cfg_attr(miri, ignore)]
call_indirect_native_from_exported_table(config: &mut Config) -> Result<()>332 fn call_indirect_native_from_exported_table(config: &mut Config) -> Result<()> {
333 let wasm = wat::parse_str(
334 r#"
335 (module
336 (table (export "table") 1 1 funcref)
337 (func (export "run") (result i32 i32 i32)
338 i32.const 0
339 call_indirect (result i32 i32 i32)
340 )
341 )
342 "#,
343 )?;
344 let engine = Engine::new(&config)?;
345 let mut store = Store::<()>::new(&engine, ());
346 let module = Module::new(store.engine(), &wasm)?;
347 let func = Func::wrap(&mut store, || -> (i32, i32, i32) { (10, 20, 30) });
348 let instance = Instance::new(&mut store, &module, &[])?;
349 let table = instance.get_table(&mut store, "table").unwrap();
350 table.set(&mut store, 0, func.into())?;
351 let run = instance.get_typed_func::<(), (i32, i32, i32)>(&mut store, "run")?;
352 let results = run.call(&mut store, ())?;
353 assert_eq!(results, (10, 20, 30));
354 Ok(())
355 }
356
357 // wasm exports global, host puts native-call funcref in global, wasm calls funcref
358 #[wasmtime_test(wasm_features(reference_types))]
359 #[cfg_attr(miri, ignore)]
call_indirect_native_from_exported_global(config: &mut Config) -> Result<()>360 fn call_indirect_native_from_exported_global(config: &mut Config) -> Result<()> {
361 let wasm = wat::parse_str(
362 r#"
363 (module
364 (global (export "global") (mut funcref) (ref.null func))
365 (table 1 1 funcref)
366 (func (export "run") (result i32 i32 i32)
367 i32.const 0
368 global.get 0
369 table.set
370 i32.const 0
371 call_indirect (result i32 i32 i32)
372 )
373 )
374 "#,
375 )?;
376 let engine = Engine::new(&config)?;
377 let mut store = Store::<()>::new(&engine, ());
378 let module = Module::new(store.engine(), &wasm)?;
379 let func = Func::wrap(&mut store, || -> (i32, i32, i32) { (10, 20, 30) });
380 let instance = Instance::new(&mut store, &module, &[])?;
381 let global = instance.get_global(&mut store, "global").unwrap();
382 global.set(&mut store, func.into())?;
383 let run = instance.get_typed_func::<(), (i32, i32, i32)>(&mut store, "run")?;
384 let results = run.call(&mut store, ())?;
385 assert_eq!(results, (10, 20, 30));
386 Ok(())
387 }
388
389 #[test]
func_constructors()390 fn func_constructors() {
391 let mut store = Store::<()>::default();
392 Func::wrap(&mut store, || {});
393 Func::wrap(&mut store, |_: i32| {});
394 Func::wrap(&mut store, |_: i32, _: i64| {});
395 Func::wrap(&mut store, |_: f32, _: f64| {});
396 Func::wrap(&mut store, || -> i32 { 0 });
397 Func::wrap(&mut store, || -> i64 { 0 });
398 Func::wrap(&mut store, || -> f32 { 0.0 });
399 Func::wrap(&mut store, || -> f64 { 0.0 });
400 Func::wrap(&mut store, || -> Rooted<ExternRef> {
401 loop {}
402 });
403 Func::wrap(&mut store, || -> Option<Rooted<ExternRef>> { None });
404 Func::wrap(&mut store, || -> OwnedRooted<ExternRef> {
405 loop {}
406 });
407 Func::wrap(&mut store, || -> Option<OwnedRooted<ExternRef>> { None });
408 Func::wrap(&mut store, || -> Rooted<AnyRef> {
409 loop {}
410 });
411 Func::wrap(&mut store, || -> Option<Rooted<AnyRef>> { None });
412 Func::wrap(&mut store, || -> OwnedRooted<AnyRef> {
413 loop {}
414 });
415 Func::wrap(&mut store, || -> Option<OwnedRooted<AnyRef>> { None });
416 Func::wrap(&mut store, || -> I31 {
417 loop {}
418 });
419 Func::wrap(&mut store, || -> Option<I31> { None });
420 Func::wrap(&mut store, || -> Func {
421 loop {}
422 });
423 Func::wrap(&mut store, || -> Option<Func> { None });
424 Func::wrap(&mut store, || -> NoFunc {
425 loop {}
426 });
427 Func::wrap(&mut store, || -> Option<NoFunc> { None });
428 Func::wrap(&mut store, || -> NoExtern {
429 loop {}
430 });
431 Func::wrap(&mut store, || -> Option<NoExtern> { None });
432 Func::wrap(&mut store, || -> NoneRef {
433 loop {}
434 });
435 Func::wrap(&mut store, || -> Option<NoneRef> { None });
436
437 Func::wrap(&mut store, || -> Result<()> {
438 loop {}
439 });
440 Func::wrap(&mut store, || -> Result<i32> {
441 loop {}
442 });
443 Func::wrap(&mut store, || -> Result<i64> {
444 loop {}
445 });
446 Func::wrap(&mut store, || -> Result<f32> {
447 loop {}
448 });
449 Func::wrap(&mut store, || -> Result<f64> {
450 loop {}
451 });
452 Func::wrap(&mut store, || -> Result<Rooted<ExternRef>> {
453 loop {}
454 });
455 Func::wrap(&mut store, || -> Result<Option<Rooted<ExternRef>>> {
456 loop {}
457 });
458 Func::wrap(&mut store, || -> Result<OwnedRooted<ExternRef>> {
459 loop {}
460 });
461 Func::wrap(&mut store, || -> Result<Option<OwnedRooted<ExternRef>>> {
462 loop {}
463 });
464 Func::wrap(&mut store, || -> Result<Rooted<AnyRef>> {
465 loop {}
466 });
467 Func::wrap(&mut store, || -> Result<Option<Rooted<AnyRef>>> {
468 loop {}
469 });
470 Func::wrap(&mut store, || -> Result<OwnedRooted<AnyRef>> {
471 loop {}
472 });
473 Func::wrap(&mut store, || -> Result<Option<OwnedRooted<AnyRef>>> {
474 loop {}
475 });
476 Func::wrap(&mut store, || -> Result<I31> {
477 loop {}
478 });
479 Func::wrap(&mut store, || -> Result<Option<I31>> {
480 loop {}
481 });
482 Func::wrap(&mut store, || -> Result<Func> {
483 loop {}
484 });
485 Func::wrap(&mut store, || -> Result<Option<Func>> {
486 loop {}
487 });
488 Func::wrap(&mut store, || -> Result<NoFunc> {
489 loop {}
490 });
491 Func::wrap(&mut store, || -> Result<Option<NoFunc>> {
492 loop {}
493 });
494 Func::wrap(&mut store, || -> Result<NoExtern> {
495 loop {}
496 });
497 Func::wrap(&mut store, || -> Result<Option<NoExtern>> {
498 loop {}
499 });
500 Func::wrap(&mut store, || -> Result<NoneRef> {
501 loop {}
502 });
503 Func::wrap(&mut store, || -> Result<Option<NoneRef>> {
504 loop {}
505 });
506 }
507
508 #[test]
dtor_runs()509 fn dtor_runs() {
510 static HITS: AtomicUsize = AtomicUsize::new(0);
511
512 struct A;
513
514 impl Drop for A {
515 fn drop(&mut self) {
516 HITS.fetch_add(1, SeqCst);
517 }
518 }
519
520 let mut store = Store::<()>::default();
521 let a = A;
522 assert_eq!(HITS.load(SeqCst), 0);
523 Func::wrap(&mut store, move || {
524 let _ = &a;
525 });
526 drop(store);
527 assert_eq!(HITS.load(SeqCst), 1);
528 }
529
530 #[test]
531 #[cfg_attr(miri, ignore)]
dtor_delayed() -> Result<()>532 fn dtor_delayed() -> Result<()> {
533 static HITS: AtomicUsize = AtomicUsize::new(0);
534
535 struct A;
536
537 impl Drop for A {
538 fn drop(&mut self) {
539 HITS.fetch_add(1, SeqCst);
540 }
541 }
542
543 let mut store = Store::<()>::default();
544 let a = A;
545 let func = Func::wrap(&mut store, move || {
546 let _ = &a;
547 });
548
549 assert_eq!(HITS.load(SeqCst), 0);
550 let wasm = wat::parse_str(r#"(import "" "" (func))"#)?;
551 let module = Module::new(store.engine(), &wasm)?;
552 let _instance = Instance::new(&mut store, &module, &[func.into()])?;
553 assert_eq!(HITS.load(SeqCst), 0);
554 drop(store);
555 assert_eq!(HITS.load(SeqCst), 1);
556 Ok(())
557 }
558
559 #[test]
signatures_match()560 fn signatures_match() {
561 let mut store = Store::<()>::default();
562
563 let f = Func::wrap(&mut store, || {});
564 assert_eq!(f.ty(&store).params().len(), 0);
565 assert_eq!(f.ty(&store).results().len(), 0);
566
567 let f = Func::wrap(&mut store, || -> i32 {
568 loop {}
569 });
570 assert_eq!(f.ty(&store).params().len(), 0);
571 assert_eq!(f.ty(&store).results().len(), 1);
572 assert!(f.ty(&store).results().nth(0).unwrap().is_i32());
573
574 let f = Func::wrap(&mut store, || -> i64 {
575 loop {}
576 });
577 assert_eq!(f.ty(&store).params().len(), 0);
578 assert_eq!(f.ty(&store).results().len(), 1);
579 assert!(f.ty(&store).results().nth(0).unwrap().is_i64());
580
581 let f = Func::wrap(&mut store, || -> f32 {
582 loop {}
583 });
584 assert_eq!(f.ty(&store).params().len(), 0);
585 assert_eq!(f.ty(&store).results().len(), 1);
586 assert!(f.ty(&store).results().nth(0).unwrap().is_f32());
587
588 let f = Func::wrap(&mut store, || -> f64 {
589 loop {}
590 });
591 assert_eq!(f.ty(&store).params().len(), 0);
592 assert_eq!(f.ty(&store).results().len(), 1);
593 assert!(f.ty(&store).results().nth(0).unwrap().is_f64());
594
595 let f = Func::wrap(
596 &mut store,
597 |_: f32,
598 _: f64,
599 _: i32,
600 _: i64,
601 _: i32,
602 _: Option<Rooted<ExternRef>>,
603 _: Option<OwnedRooted<ExternRef>>,
604 _: Option<Rooted<AnyRef>>,
605 _: Option<OwnedRooted<AnyRef>>,
606 _: Option<Func>|
607 -> f64 { loop {} },
608 );
609
610 assert_eq!(f.ty(&store).params().len(), 10);
611 assert!(f.ty(&store).params().nth(0).unwrap().is_f32());
612 assert!(f.ty(&store).params().nth(1).unwrap().is_f64());
613 assert!(f.ty(&store).params().nth(2).unwrap().is_i32());
614 assert!(f.ty(&store).params().nth(3).unwrap().is_i64());
615 assert!(f.ty(&store).params().nth(4).unwrap().is_i32());
616 assert!(f.ty(&store).params().nth(5).unwrap().is_externref());
617 assert!(f.ty(&store).params().nth(6).unwrap().is_externref());
618 assert!(f.ty(&store).params().nth(7).unwrap().is_anyref());
619 assert!(f.ty(&store).params().nth(8).unwrap().is_anyref());
620 assert!(f.ty(&store).params().nth(9).unwrap().is_funcref());
621
622 assert_eq!(f.ty(&store).results().len(), 1);
623 assert!(f.ty(&store).results().nth(0).unwrap().is_f64());
624 }
625
626 #[test]
627 #[cfg_attr(miri, ignore)]
import_works() -> Result<()>628 fn import_works() -> Result<()> {
629 let _ = env_logger::try_init();
630
631 static HITS: AtomicUsize = AtomicUsize::new(0);
632
633 let wasm = wat::parse_str(
634 r#"
635 (import "" "" (func))
636 (import "" "" (func (param i32) (result i32)))
637 (import "" "" (func (param i32) (param i64)))
638 (import "" "" (func (param i32 i64 i32 f32 f64 externref externref funcref anyref anyref i31ref)))
639
640 (func (export "run") (param externref externref funcref)
641 call 0
642 i32.const 0
643 call 1
644 i32.const 1
645 i32.add
646 i64.const 3
647 call 2
648
649 i32.const 100
650 i64.const 200
651 i32.const 300
652 f32.const 400
653 f64.const 500
654 local.get 0
655 local.get 1
656 local.get 2
657 (ref.i31 (i32.const 36))
658 (ref.i31 (i32.const 42))
659 (ref.i31 (i32.const 0x1234))
660 call 3
661 )
662 "#,
663 )?;
664
665 let mut config = Config::new();
666 config.wasm_reference_types(true);
667 config.wasm_function_references(true);
668 config.wasm_gc(true);
669
670 let engine = Engine::new(&config)?;
671 let mut store = Store::new(&engine, ());
672 let module = Module::new(&engine, &wasm)?;
673
674 let imports = [
675 Func::wrap(&mut store, || {
676 assert_eq!(HITS.fetch_add(1, SeqCst), 0);
677 })
678 .into(),
679 Func::wrap(&mut store, |x: i32| -> i32 {
680 assert_eq!(x, 0);
681 assert_eq!(HITS.fetch_add(1, SeqCst), 1);
682 1
683 })
684 .into(),
685 Func::wrap(&mut store, |x: i32, y: i64| {
686 assert_eq!(x, 2);
687 assert_eq!(y, 3);
688 assert_eq!(HITS.fetch_add(1, SeqCst), 2);
689 })
690 .into(),
691 Func::wrap(
692 &mut store,
693 |mut caller: Caller<'_, ()>,
694 a: i32,
695 b: i64,
696 c: i32,
697 d: f32,
698 e: f64,
699 f: Option<Rooted<ExternRef>>,
700 g: Option<OwnedRooted<ExternRef>>,
701 h: Option<Func>,
702 i: Option<Rooted<AnyRef>>,
703 j: Option<OwnedRooted<AnyRef>>,
704 k: Option<I31>|
705 -> Result<()> {
706 assert_eq!(a, 100);
707 assert_eq!(b, 200);
708 assert_eq!(c, 300);
709 assert_eq!(d, 400.0);
710 assert_eq!(e, 500.0);
711 assert_eq!(
712 f.as_ref()
713 .unwrap()
714 .data(&caller)?
715 .unwrap()
716 .downcast_ref::<String>()
717 .unwrap(),
718 "hello"
719 );
720 assert_eq!(
721 g.as_ref()
722 .unwrap()
723 .data(&caller)?
724 .unwrap()
725 .downcast_ref::<String>()
726 .unwrap(),
727 "goodbye"
728 );
729 assert_eq!(
730 i.unwrap().as_i31(&caller).unwrap().unwrap(),
731 I31::wrapping_u32(36)
732 );
733 assert_eq!(
734 j.unwrap().as_i31(&caller).unwrap().unwrap(),
735 I31::wrapping_u32(42)
736 );
737 assert_eq!(k, Some(I31::wrapping_u32(0x1234)));
738 let mut results = [Val::I32(0)];
739 h.as_ref()
740 .unwrap()
741 .call(&mut caller, &[], &mut results)
742 .unwrap();
743 assert_eq!(results[0].unwrap_i32(), 42);
744 assert_eq!(HITS.fetch_add(1, SeqCst), 3);
745 Ok(())
746 },
747 )
748 .into(),
749 ];
750
751 let instance = Instance::new(&mut store, &module, &imports)?;
752 let run = instance.get_func(&mut store, "run").unwrap();
753 let hello = Val::ExternRef(Some(ExternRef::new(&mut store, "hello".to_string())?));
754 let goodbye = Val::ExternRef(Some(ExternRef::new(&mut store, "goodbye".to_string())?));
755 let funcref = Val::FuncRef(Some(Func::wrap(&mut store, || -> i32 { 42 })));
756 run.call(&mut store, &[hello, goodbye, funcref], &mut [])?;
757
758 assert_eq!(HITS.load(SeqCst), 4);
759 Ok(())
760 }
761
762 #[test]
763 #[cfg_attr(miri, ignore)]
trap_smoke() -> Result<()>764 fn trap_smoke() -> Result<()> {
765 let mut store = Store::<()>::default();
766 let f = Func::wrap(&mut store, || -> Result<()> { bail!("test") });
767 let err = f.call(&mut store, &[], &mut []).unwrap_err();
768 assert!(err.to_string().contains("test"));
769 Ok(())
770 }
771
772 #[wasmtime_test]
773 #[cfg_attr(miri, ignore)]
trap_import(config: &mut Config) -> Result<()>774 fn trap_import(config: &mut Config) -> Result<()> {
775 let wasm = wat::parse_str(
776 r#"
777 (import "" "" (func))
778 (start 0)
779 "#,
780 )?;
781 let engine = Engine::new(&config)?;
782 let mut store = Store::<()>::new(&engine, ());
783 let module = Module::new(store.engine(), &wasm)?;
784 let import = Func::wrap(&mut store, || -> Result<()> { bail!("foo") });
785 let trap = Instance::new(&mut store, &module, &[import.into()]).unwrap_err();
786 assert!(trap.to_string().contains("foo"));
787 Ok(())
788 }
789
790 #[test]
get_from_wrapper()791 fn get_from_wrapper() {
792 let mut store = Store::<()>::default();
793 let f = Func::wrap(&mut store, || {});
794 assert!(f.typed::<(), ()>(&store).is_ok());
795 assert!(f.typed::<(), i32>(&store).is_err());
796 assert!(f.typed::<(), ()>(&store).is_ok());
797 assert!(f.typed::<i32, ()>(&store).is_err());
798 assert!(f.typed::<i32, i32>(&store).is_err());
799 assert!(f.typed::<(i32, i32), ()>(&store).is_err());
800 assert!(f.typed::<(i32, i32), i32>(&store).is_err());
801
802 let f = Func::wrap(&mut store, || -> i32 {
803 loop {}
804 });
805 assert!(f.typed::<(), i32>(&store).is_ok());
806 let f = Func::wrap(&mut store, || -> f32 {
807 loop {}
808 });
809 assert!(f.typed::<(), f32>(&store).is_ok());
810 let f = Func::wrap(&mut store, || -> f64 {
811 loop {}
812 });
813 assert!(f.typed::<(), f64>(&store).is_ok());
814 let f = Func::wrap(&mut store, || -> Rooted<ExternRef> {
815 loop {}
816 });
817 assert!(f.typed::<(), Rooted<ExternRef>>(&store).is_ok());
818 let f = Func::wrap(&mut store, || -> Option<Rooted<ExternRef>> {
819 loop {}
820 });
821 assert!(f.typed::<(), Option<Rooted<ExternRef>>>(&store).is_ok());
822 let f = Func::wrap(&mut store, || -> OwnedRooted<ExternRef> {
823 loop {}
824 });
825 assert!(f.typed::<(), OwnedRooted<ExternRef>>(&store).is_ok());
826 let f = Func::wrap(&mut store, || -> Option<OwnedRooted<ExternRef>> {
827 loop {}
828 });
829 assert!(
830 f.typed::<(), Option<OwnedRooted<ExternRef>>>(&store)
831 .is_ok()
832 );
833 let f = Func::wrap(&mut store, || -> Rooted<AnyRef> {
834 loop {}
835 });
836 assert!(f.typed::<(), Rooted<AnyRef>>(&store).is_ok());
837 let f = Func::wrap(&mut store, || -> Option<Rooted<AnyRef>> {
838 loop {}
839 });
840 assert!(f.typed::<(), Option<Rooted<AnyRef>>>(&store).is_ok());
841 let f = Func::wrap(&mut store, || -> OwnedRooted<AnyRef> {
842 loop {}
843 });
844 assert!(f.typed::<(), OwnedRooted<AnyRef>>(&store).is_ok());
845 let f = Func::wrap(&mut store, || -> Option<OwnedRooted<AnyRef>> {
846 loop {}
847 });
848 assert!(f.typed::<(), Option<OwnedRooted<AnyRef>>>(&store).is_ok());
849 let f = Func::wrap(&mut store, || -> I31 {
850 loop {}
851 });
852 assert!(f.typed::<(), I31>(&store).is_ok());
853 let f = Func::wrap(&mut store, || -> Option<I31> {
854 loop {}
855 });
856 assert!(f.typed::<(), Option<I31>>(&store).is_ok());
857 let f = Func::wrap(&mut store, || -> Func {
858 loop {}
859 });
860 assert!(f.typed::<(), Func>(&store).is_ok());
861 let f = Func::wrap(&mut store, || -> Option<Func> {
862 loop {}
863 });
864 assert!(f.typed::<(), Option<Func>>(&store).is_ok());
865
866 let f = Func::wrap(&mut store, |_: i32| {});
867 assert!(f.typed::<i32, ()>(&store).is_ok());
868 assert!(f.typed::<i64, ()>(&store).is_err());
869 assert!(f.typed::<f32, ()>(&store).is_err());
870 assert!(f.typed::<f64, ()>(&store).is_err());
871 let f = Func::wrap(&mut store, |_: i64| {});
872 assert!(f.typed::<i64, ()>(&store).is_ok());
873 let f = Func::wrap(&mut store, |_: f32| {});
874 assert!(f.typed::<f32, ()>(&store).is_ok());
875 let f = Func::wrap(&mut store, |_: f64| {});
876 assert!(f.typed::<f64, ()>(&store).is_ok());
877 let f = Func::wrap(&mut store, |_: Rooted<ExternRef>| {});
878 assert!(f.typed::<Rooted<ExternRef>, ()>(&store).is_ok());
879 let f = Func::wrap(&mut store, |_: Option<Rooted<ExternRef>>| {});
880 assert!(f.typed::<Option<Rooted<ExternRef>>, ()>(&store).is_ok());
881 let f = Func::wrap(&mut store, |_: OwnedRooted<ExternRef>| {});
882 assert!(f.typed::<OwnedRooted<ExternRef>, ()>(&store).is_ok());
883 let f = Func::wrap(&mut store, |_: Option<OwnedRooted<ExternRef>>| {});
884 assert!(
885 f.typed::<Option<OwnedRooted<ExternRef>>, ()>(&store)
886 .is_ok()
887 );
888 let f = Func::wrap(&mut store, |_: Rooted<AnyRef>| {});
889 assert!(f.typed::<Rooted<AnyRef>, ()>(&store).is_ok());
890 let f = Func::wrap(&mut store, |_: Option<Rooted<AnyRef>>| {});
891 assert!(f.typed::<Option<Rooted<AnyRef>>, ()>(&store).is_ok());
892 let f = Func::wrap(&mut store, |_: OwnedRooted<AnyRef>| {});
893 assert!(f.typed::<OwnedRooted<AnyRef>, ()>(&store).is_ok());
894 let f = Func::wrap(&mut store, |_: Option<OwnedRooted<AnyRef>>| {});
895 assert!(f.typed::<Option<OwnedRooted<AnyRef>>, ()>(&store).is_ok());
896 let f = Func::wrap(&mut store, |_: I31| {});
897 assert!(f.typed::<I31, ()>(&store).is_ok());
898 let f = Func::wrap(&mut store, |_: Option<I31>| {});
899 assert!(f.typed::<Option<I31>, ()>(&store).is_ok());
900 let f = Func::wrap(&mut store, |_: Func| {});
901 assert!(f.typed::<Func, ()>(&store).is_ok());
902 let f = Func::wrap(&mut store, |_: Option<Func>| {});
903 assert!(f.typed::<Option<Func>, ()>(&store).is_ok());
904 }
905
906 #[test]
907 #[cfg_attr(miri, ignore)]
get_from_signature()908 fn get_from_signature() {
909 let mut store = Store::<()>::default();
910 let ty = FuncType::new(store.engine(), None, None);
911 let f = Func::new(&mut store, ty, |_, _, _| panic!());
912 assert!(f.typed::<(), ()>(&store).is_ok());
913 assert!(f.typed::<(), i32>(&store).is_err());
914 assert!(f.typed::<i32, ()>(&store).is_err());
915
916 let ty = FuncType::new(store.engine(), Some(ValType::I32), Some(ValType::F64));
917 let f = Func::new(&mut store, ty, |_, _, _| panic!());
918 assert!(f.typed::<(), ()>(&store).is_err());
919 assert!(f.typed::<(), i32>(&store).is_err());
920 assert!(f.typed::<i32, ()>(&store).is_err());
921 assert!(f.typed::<i32, f64>(&store).is_ok());
922 }
923
924 #[wasmtime_test]
925 #[cfg_attr(miri, ignore)]
get_from_module(config: &mut Config) -> wasmtime::Result<()>926 fn get_from_module(config: &mut Config) -> wasmtime::Result<()> {
927 let engine = Engine::new(&config)?;
928 let mut store = Store::<()>::new(&engine, ());
929 let module = Module::new(
930 store.engine(),
931 r#"
932 (module
933 (func (export "f0"))
934 (func (export "f1") (param i32))
935 (func (export "f2") (result i32)
936 i32.const 0)
937 )
938
939 "#,
940 )?;
941 let instance = Instance::new(&mut store, &module, &[])?;
942 let f0 = instance.get_func(&mut store, "f0").unwrap();
943 assert!(f0.typed::<(), ()>(&store).is_ok());
944 assert!(f0.typed::<(), i32>(&store).is_err());
945 let f1 = instance.get_func(&mut store, "f1").unwrap();
946 assert!(f1.typed::<(), ()>(&store).is_err());
947 assert!(f1.typed::<i32, ()>(&store).is_ok());
948 assert!(f1.typed::<i32, f32>(&store).is_err());
949 let f2 = instance.get_func(&mut store, "f2").unwrap();
950 assert!(f2.typed::<(), ()>(&store).is_err());
951 assert!(f2.typed::<(), i32>(&store).is_ok());
952 assert!(f2.typed::<i32, ()>(&store).is_err());
953 assert!(f2.typed::<i32, f32>(&store).is_err());
954 Ok(())
955 }
956
957 #[test]
call_wrapped_func() -> Result<()>958 fn call_wrapped_func() -> Result<()> {
959 let mut store = Store::<()>::default();
960 let f = Func::wrap(&mut store, |a: i32, b: i64, c: f32, d: f64| {
961 assert_eq!(a, 1);
962 assert_eq!(b, 2);
963 assert_eq!(c, 3.0);
964 assert_eq!(d, 4.0);
965 });
966 f.call(
967 &mut store,
968 &[Val::I32(1), Val::I64(2), 3.0f32.into(), 4.0f64.into()],
969 &mut [],
970 )?;
971 f.typed::<(i32, i64, f32, f64), ()>(&store)?
972 .call(&mut store, (1, 2, 3.0, 4.0))?;
973
974 let mut results = [Val::I32(0)];
975 let f = Func::wrap(&mut store, || 1i32);
976 f.call(&mut store, &[], &mut results)?;
977 assert_eq!(results[0].unwrap_i32(), 1);
978 assert_eq!(f.typed::<(), i32>(&store)?.call(&mut store, ())?, 1);
979
980 let f = Func::wrap(&mut store, || 2i64);
981 f.call(&mut store, &[], &mut results)?;
982 assert_eq!(results[0].unwrap_i64(), 2);
983 assert_eq!(f.typed::<(), i64>(&store)?.call(&mut store, ())?, 2);
984
985 let f = Func::wrap(&mut store, || 3.0f32);
986 f.call(&mut store, &[], &mut results)?;
987 assert_eq!(results[0].unwrap_f32(), 3.0);
988 assert_eq!(f.typed::<(), f32>(&store)?.call(&mut store, ())?, 3.0);
989
990 let f = Func::wrap(&mut store, || 4.0f64);
991 f.call(&mut store, &[], &mut results)?;
992 assert_eq!(results[0].unwrap_f64(), 4.0);
993 assert_eq!(f.typed::<(), f64>(&store)?.call(&mut store, ())?, 4.0);
994 Ok(())
995 }
996
997 #[wasmtime_test]
998 #[cfg_attr(miri, ignore)]
caller_memory(config: &mut Config) -> wasmtime::Result<()>999 fn caller_memory(config: &mut Config) -> wasmtime::Result<()> {
1000 let engine = Engine::new(config)?;
1001 let mut store = Store::<()>::new(&engine, ());
1002 let f = Func::wrap(&mut store, |mut c: Caller<'_, ()>| {
1003 assert!(c.get_export("x").is_none());
1004 assert!(c.get_export("y").is_none());
1005 assert!(c.get_export("z").is_none());
1006 });
1007 f.call(&mut store, &[], &mut [])?;
1008
1009 let f = Func::wrap(&mut store, |mut c: Caller<'_, ()>| {
1010 assert!(c.get_export("x").is_none());
1011 });
1012 let module = Module::new(
1013 store.engine(),
1014 r#"
1015 (module
1016 (import "" "" (func $f))
1017 (start $f)
1018 )
1019
1020 "#,
1021 )?;
1022 Instance::new(&mut store, &module, &[f.into()])?;
1023
1024 let f = Func::wrap(&mut store, |mut c: Caller<'_, ()>| {
1025 assert!(c.get_export("memory").is_some());
1026 });
1027 let module = Module::new(
1028 store.engine(),
1029 r#"
1030 (module
1031 (import "" "" (func $f))
1032 (memory (export "memory") 1)
1033 (start $f)
1034 )
1035
1036 "#,
1037 )?;
1038 Instance::new(&mut store, &module, &[f.into()])?;
1039
1040 let f = Func::wrap(&mut store, |mut c: Caller<'_, ()>| {
1041 assert!(c.get_export("m").is_some());
1042 assert!(c.get_export("f").is_some());
1043 assert!(c.get_export("g").is_some());
1044 assert!(c.get_export("t").is_some());
1045 });
1046 let module = Module::new(
1047 store.engine(),
1048 r#"
1049 (module
1050 (import "" "" (func $f))
1051 (memory (export "m") 1)
1052 (func (export "f"))
1053 (global (export "g") i32 (i32.const 0))
1054 (table (export "t") 1 funcref)
1055 (start $f)
1056 )
1057
1058 "#,
1059 )?;
1060 Instance::new(&mut store, &module, &[f.into()])?;
1061 Ok(())
1062 }
1063
1064 #[test]
1065 #[cfg_attr(miri, ignore)]
func_write_nothing() -> wasmtime::Result<()>1066 fn func_write_nothing() -> wasmtime::Result<()> {
1067 let mut store = Store::<()>::default();
1068 let ty = FuncType::new(store.engine(), None, Some(ValType::I32));
1069 let f = Func::new(&mut store, ty, |_, _, _| Ok(()));
1070 let err = f.call(&mut store, &[], &mut [Val::I32(0)]).unwrap_err();
1071 assert!(
1072 err.to_string()
1073 .contains("function attempted to return an incompatible value")
1074 );
1075 Ok(())
1076 }
1077
1078 #[wasmtime_test(wasm_features(reference_types))]
1079 #[cfg_attr(miri, ignore)]
return_cross_store_value(config: &mut Config) -> wasmtime::Result<()>1080 fn return_cross_store_value(config: &mut Config) -> wasmtime::Result<()> {
1081 let _ = env_logger::try_init();
1082
1083 let wasm = wat::parse_str(
1084 r#"
1085 (import "" "" (func (result funcref)))
1086
1087 (func (export "run") (result funcref)
1088 call 0
1089 )
1090 "#,
1091 )?;
1092 let engine = Engine::new(&config)?;
1093 let module = Module::new(&engine, &wasm)?;
1094
1095 let mut store1 = Store::new(&engine, ());
1096 let mut store2 = Store::new(&engine, ());
1097
1098 let store2_func = Func::wrap(&mut store2, || {});
1099 let return_cross_store_func = Func::wrap(&mut store1, move || Some(store2_func));
1100
1101 let instance = Instance::new(&mut store1, &module, &[return_cross_store_func.into()])?;
1102
1103 let run = instance.get_func(&mut store1, "run").unwrap();
1104 let result = run.call(&mut store1, &[], &mut [Val::I32(0)]);
1105 assert!(result.is_err());
1106 assert!(format!("{:?}", result.unwrap_err()).contains("cross-`Store`"));
1107
1108 Ok(())
1109 }
1110
1111 #[wasmtime_test(wasm_features(reference_types))]
pass_cross_store_arg(config: &mut Config) -> wasmtime::Result<()>1112 fn pass_cross_store_arg(config: &mut Config) -> wasmtime::Result<()> {
1113 let engine = Engine::new(&config)?;
1114
1115 let mut store1 = Store::new(&engine, ());
1116 let mut store2 = Store::new(&engine, ());
1117
1118 let store1_func = Func::wrap(&mut store1, |_: Option<Func>| {});
1119 let store2_func = Func::wrap(&mut store2, || {});
1120
1121 // Using regular `.call` fails with cross-Store arguments.
1122 assert!(
1123 store1_func
1124 .call(&mut store1, &[Val::FuncRef(Some(store2_func))], &mut [])
1125 .is_err()
1126 );
1127
1128 // And using `.get` followed by a function call also fails with cross-Store
1129 // arguments.
1130 let f = store1_func.typed::<Option<Func>, ()>(&store1)?;
1131 let result = f.call(&mut store1, Some(store2_func));
1132 assert!(result.is_err());
1133 assert!(result.unwrap_err().to_string().contains("cross-`Store`"));
1134
1135 Ok(())
1136 }
1137
1138 #[test]
1139 #[cfg_attr(miri, ignore)]
externref_signature_no_reference_types() -> wasmtime::Result<()>1140 fn externref_signature_no_reference_types() -> wasmtime::Result<()> {
1141 let mut config = Config::new();
1142 config.wasm_reference_types(false);
1143 let mut store = Store::new(&Engine::new(&config)?, ());
1144 Func::wrap(&mut store, |_: Option<Func>| {});
1145 let func_ty = FuncType::new(
1146 store.engine(),
1147 [ValType::FUNCREF, ValType::EXTERNREF].iter().cloned(),
1148 [ValType::FUNCREF, ValType::EXTERNREF].iter().cloned(),
1149 );
1150 Func::new(&mut store, func_ty, |_, _, _| Ok(()));
1151 Ok(())
1152 }
1153
1154 #[wasmtime_test]
1155 #[cfg_attr(miri, ignore)]
trampolines_always_valid(config: &mut Config) -> wasmtime::Result<()>1156 fn trampolines_always_valid(config: &mut Config) -> wasmtime::Result<()> {
1157 // Compile two modules up front
1158 let engine = Engine::new(&config)?;
1159 let mut store = Store::<()>::new(&engine, ());
1160 let module1 = Module::new(store.engine(), "(module (import \"\" \"\" (func)))")?;
1161 let module2 = Module::new(store.engine(), "(module (func (export \"\")))")?;
1162 // Start instantiating the first module, but this will fail.
1163 // Historically this registered the module's trampolines with `Store`
1164 // before the failure, but then after the failure the `Store` didn't
1165 // hold onto the trampoline.
1166 drop(Instance::new(&mut store, &module1, &[]));
1167 drop(module1);
1168
1169 // Then instantiate another module which has the same function type (no
1170 // parameters or results) which tries to use the trampoline defined in
1171 // the previous module. Then we extract the function and, after we drop the
1172 // module's reference, we call the func.
1173 let i = Instance::new(&mut store, &module2, &[])?;
1174 let func = i.get_func(&mut store, "").unwrap();
1175 drop(module2);
1176
1177 // ... and no segfaults! right? right? ...
1178 func.call(&mut store, &[], &mut [])?;
1179 Ok(())
1180 }
1181
1182 #[wasmtime_test]
1183 #[cfg_attr(miri, ignore)]
typed_multiple_results(config: &mut Config) -> wasmtime::Result<()>1184 fn typed_multiple_results(config: &mut Config) -> wasmtime::Result<()> {
1185 let engine = Engine::new(&config)?;
1186 let mut store = Store::<()>::new(&engine, ());
1187 let module = Module::new(
1188 store.engine(),
1189 r#"
1190 (module
1191 (func (export "f0") (result i32 i64)
1192 i32.const 0
1193 i64.const 1)
1194 (func (export "f1") (param i32 i32 i32) (result f32 f64)
1195 f32.const 2
1196 f64.const 3)
1197 )
1198
1199 "#,
1200 )?;
1201 let instance = Instance::new(&mut store, &module, &[])?;
1202 let f0 = instance.get_func(&mut store, "f0").unwrap();
1203 assert!(f0.typed::<(), ()>(&store).is_err());
1204 assert!(f0.typed::<(), (i32, f32)>(&store).is_err());
1205 assert!(f0.typed::<(), i32>(&store).is_err());
1206 assert_eq!(
1207 f0.typed::<(), (i32, i64)>(&store)?.call(&mut store, ())?,
1208 (0, 1)
1209 );
1210
1211 let f1 = instance.get_func(&mut store, "f1").unwrap();
1212 assert_eq!(
1213 f1.typed::<(i32, i32, i32), (f32, f64)>(&store)?
1214 .call(&mut store, (1, 2, 3))?,
1215 (2., 3.)
1216 );
1217 Ok(())
1218 }
1219
1220 #[test]
1221 #[cfg_attr(miri, ignore)]
trap_doesnt_leak() -> wasmtime::Result<()>1222 fn trap_doesnt_leak() -> wasmtime::Result<()> {
1223 #[derive(Default)]
1224 struct Canary(Arc<AtomicBool>);
1225
1226 impl Drop for Canary {
1227 fn drop(&mut self) {
1228 self.0.store(true, SeqCst);
1229 }
1230 }
1231
1232 let mut store = Store::<()>::default();
1233
1234 // test that `Func::wrap` is correct
1235 let canary1 = Canary::default();
1236 let dtor1_run = canary1.0.clone();
1237 let f1 = Func::wrap(&mut store, move || -> Result<()> {
1238 let _ = &canary1;
1239 bail!("")
1240 });
1241 assert!(f1.typed::<(), ()>(&store)?.call(&mut store, ()).is_err());
1242 assert!(f1.call(&mut store, &[], &mut []).is_err());
1243
1244 // test that `Func::new` is correct
1245 let canary2 = Canary::default();
1246 let dtor2_run = canary2.0.clone();
1247 let func_ty = FuncType::new(store.engine(), None, None);
1248 let f2 = Func::new(&mut store, func_ty, move |_, _, _| {
1249 let _ = &canary2;
1250 bail!("")
1251 });
1252 assert!(f2.typed::<(), ()>(&store)?.call(&mut store, ()).is_err());
1253 assert!(f2.call(&mut store, &[], &mut []).is_err());
1254
1255 // drop everything and ensure dtors are run
1256 drop(store);
1257 assert!(dtor1_run.load(SeqCst));
1258 assert!(dtor2_run.load(SeqCst));
1259 Ok(())
1260 }
1261
1262 #[wasmtime_test]
1263 #[cfg_attr(miri, ignore)]
wrap_multiple_results(config: &mut Config) -> wasmtime::Result<()>1264 fn wrap_multiple_results(config: &mut Config) -> wasmtime::Result<()> {
1265 fn test<T>(store: &mut Store<()>, t: T) -> wasmtime::Result<()>
1266 where
1267 T: WasmRet
1268 + WasmResults
1269 + PartialEq
1270 + Copy
1271 + std::fmt::Debug
1272 + EqualToValues
1273 + 'static
1274 + Send
1275 + Sync,
1276 {
1277 let f = Func::wrap(&mut *store, move || t);
1278 let mut results = vec![Val::I32(0); f.ty(&store).results().len()];
1279 assert_eq!(f.typed::<(), T>(&store)?.call(&mut *store, ())?, t);
1280 f.call(&mut *store, &[], &mut results)?;
1281 assert!(t.eq_values(&results));
1282
1283 let module = Module::new(store.engine(), &T::gen_wasm())?;
1284 let instance = Instance::new(&mut *store, &module, &[f.into()])?;
1285 let f = instance.get_func(&mut *store, "foo").unwrap();
1286
1287 assert_eq!(f.typed::<(), T>(&store)?.call(&mut *store, ())?, t);
1288 f.call(&mut *store, &[], &mut results)?;
1289 assert!(t.eq_values(&results));
1290 Ok(())
1291 }
1292
1293 let engine = Engine::new(&config)?;
1294 let mut store = Store::new(&engine, ());
1295 // 0 element
1296 test(&mut store, ())?;
1297
1298 // 1 element
1299 test(&mut store, (1i32,))?;
1300 test(&mut store, (2u32,))?;
1301 test(&mut store, (3i64,))?;
1302 test(&mut store, (4u64,))?;
1303 test(&mut store, (5.0f32,))?;
1304 test(&mut store, (6.0f64,))?;
1305
1306 // 2 element ...
1307 test(&mut store, (7i32, 8i32))?;
1308 test(&mut store, (7i32, 8i64))?;
1309 test(&mut store, (7i32, 8f32))?;
1310 test(&mut store, (7i32, 8f64))?;
1311
1312 test(&mut store, (7i64, 8i32))?;
1313 test(&mut store, (7i64, 8i64))?;
1314 test(&mut store, (7i64, 8f32))?;
1315 test(&mut store, (7i64, 8f64))?;
1316
1317 test(&mut store, (7f32, 8i32))?;
1318 test(&mut store, (7f32, 8i64))?;
1319 test(&mut store, (7f32, 8f32))?;
1320 test(&mut store, (7f32, 8f64))?;
1321
1322 test(&mut store, (7f64, 8i32))?;
1323 test(&mut store, (7f64, 8i64))?;
1324 test(&mut store, (7f64, 8f32))?;
1325 test(&mut store, (7f64, 8f64))?;
1326
1327 // and beyond...
1328 test(&mut store, (1i32, 2i32, 3i32))?;
1329 test(&mut store, (1i32, 2f32, 3i32))?;
1330 test(&mut store, (1f64, 2f32, 3i32))?;
1331 test(&mut store, (1f64, 2i64, 3i32))?;
1332 test(&mut store, (1f32, 2f32, 3i64, 4f64))?;
1333 test(&mut store, (1f64, 2i64, 3i32, 4i64, 5f32))?;
1334 test(&mut store, (1i32, 2f64, 3i64, 4f64, 5f64, 6f32))?;
1335 test(&mut store, (1i64, 2i32, 3i64, 4f32, 5f32, 6i32, 7u64))?;
1336 test(&mut store, (1u32, 2f32, 3u64, 4f64, 5i32, 6f32, 7u64, 8u32))?;
1337 test(
1338 &mut store,
1339 (1f32, 2f64, 3f32, 4i32, 5u32, 6i64, 7f32, 8i32, 9u64),
1340 )?;
1341 return Ok(());
1342
1343 trait EqualToValues {
1344 fn eq_values(&self, values: &[Val]) -> bool;
1345 fn gen_wasm() -> String;
1346 }
1347
1348 macro_rules! equal_tuples {
1349 ($($cnt:tt ($($a:ident),*))*) => ($(
1350 #[allow(non_snake_case, reason = "macro-generated code")]
1351 impl<$($a: EqualToValue,)*> EqualToValues for ($($a,)*) {
1352 fn eq_values(&self, values: &[Val]) -> bool {
1353 let ($($a,)*) = self;
1354 let mut _values = values.iter();
1355 _values.len() == $cnt &&
1356 $($a.eq_value(_values.next().unwrap()) &&)*
1357 true
1358 }
1359
1360 fn gen_wasm() -> String {
1361 let mut wasm = String::new();
1362 wasm.push_str("(module ");
1363 wasm.push_str("(type $t (func (result ");
1364 $(
1365 wasm.push_str($a::wasm_ty());
1366 wasm.push_str(" ");
1367 )*
1368 wasm.push_str(")))");
1369
1370 wasm.push_str("(import \"\" \"\" (func $host (type $t)))");
1371 wasm.push_str("(func (export \"foo\") (type $t)");
1372 wasm.push_str("call $host");
1373 wasm.push_str(")");
1374 wasm.push_str(")");
1375
1376 wasm
1377 }
1378 }
1379 )*)
1380 }
1381
1382 equal_tuples! {
1383 0 ()
1384 1 (A1)
1385 2 (A1, A2)
1386 3 (A1, A2, A3)
1387 4 (A1, A2, A3, A4)
1388 5 (A1, A2, A3, A4, A5)
1389 6 (A1, A2, A3, A4, A5, A6)
1390 7 (A1, A2, A3, A4, A5, A6, A7)
1391 8 (A1, A2, A3, A4, A5, A6, A7, A8)
1392 9 (A1, A2, A3, A4, A5, A6, A7, A8, A9)
1393 }
1394
1395 trait EqualToValue {
1396 fn eq_value(&self, value: &Val) -> bool;
1397 fn wasm_ty() -> &'static str;
1398 }
1399
1400 macro_rules! equal_values {
1401 ($a:ident $($ty:ident $wasm:tt $variant:ident $e:expr,)*) => ($(
1402 impl EqualToValue for $ty {
1403 fn eq_value(&self, val: &Val) -> bool {
1404 if let Val::$variant($a) = *val {
1405 return *self == $e;
1406 }
1407 false
1408 }
1409
1410 fn wasm_ty() -> &'static str {
1411 $wasm
1412 }
1413 }
1414 )*)
1415 }
1416
1417 equal_values! {
1418 a
1419 i32 "i32" I32 a,
1420 u32 "i32" I32 a as u32,
1421 i64 "i64" I64 a,
1422 u64 "i64" I64 a as u64,
1423 f32 "f32" F32 f32::from_bits(a),
1424 f64 "f64" F64 f64::from_bits(a),
1425 }
1426 }
1427
1428 #[wasmtime_test(wasm_features(reference_types, bulk_memory))]
1429 #[cfg_attr(miri, ignore)]
trampoline_for_declared_elem(config: &mut Config) -> wasmtime::Result<()>1430 fn trampoline_for_declared_elem(config: &mut Config) -> wasmtime::Result<()> {
1431 let engine = Engine::new(&config)?;
1432
1433 let module = Module::new(
1434 &engine,
1435 r#"
1436 (module
1437 (elem declare func $f)
1438 (func $f)
1439 (func (export "g") (result funcref)
1440 (ref.func $f)
1441 )
1442 )
1443 "#,
1444 )?;
1445
1446 let mut store = Store::new(&engine, ());
1447 let instance = Instance::new(&mut store, &module, &[])?;
1448
1449 let g = instance.get_typed_func::<(), Option<Func>>(&mut store, "g")?;
1450
1451 let func = g.call(&mut store, ())?;
1452 func.unwrap().call(&mut store, &[], &mut [])?;
1453 Ok(())
1454 }
1455
1456 #[wasmtime_test]
1457 #[cfg_attr(miri, ignore)]
wasm_ty_roundtrip(config: &mut Config) -> Result<(), wasmtime::Error>1458 fn wasm_ty_roundtrip(config: &mut Config) -> Result<(), wasmtime::Error> {
1459 let engine = Engine::new(&config)?;
1460 let mut store = Store::<()>::new(&engine, ());
1461 let debug = Func::wrap(
1462 &mut store,
1463 |a: i32, b: u32, c: f32, d: i64, e: u64, f: f64| {
1464 assert_eq!(a, -1);
1465 assert_eq!(b, 1);
1466 assert_eq!(c, 2.0);
1467 assert_eq!(d, -3);
1468 assert_eq!(e, 3);
1469 assert_eq!(f, 4.0);
1470 },
1471 );
1472 let module = Module::new(
1473 store.engine(),
1474 r#"
1475 (module
1476 (import "" "" (func $debug (param i32 i32 f32 i64 i64 f64)))
1477 (func (export "foo") (param i32 i32 f32 i64 i64 f64)
1478 (if (i32.ne (local.get 0) (i32.const -1))
1479 (then unreachable)
1480 )
1481 (if (i32.ne (local.get 1) (i32.const 1))
1482 (then unreachable)
1483 )
1484 (if (f32.ne (local.get 2) (f32.const 2))
1485 (then unreachable)
1486 )
1487 (if (i64.ne (local.get 3) (i64.const -3))
1488 (then unreachable)
1489 )
1490 (if (i64.ne (local.get 4) (i64.const 3))
1491 (then unreachable)
1492 )
1493 (if (f64.ne (local.get 5) (f64.const 4))
1494 (then unreachable)
1495 )
1496 local.get 0
1497 local.get 1
1498 local.get 2
1499 local.get 3
1500 local.get 4
1501 local.get 5
1502 call $debug
1503 )
1504 )
1505 "#,
1506 )?;
1507 let instance = Instance::new(&mut store, &module, &[debug.into()])?;
1508 let foo = instance.get_typed_func::<(i32, u32, f32, i64, u64, f64), ()>(&mut store, "foo")?;
1509 foo.call(&mut store, (-1, 1, 2.0, -3, 3, 4.0))?;
1510 Ok(())
1511 }
1512
1513 #[wasmtime_test]
1514 #[cfg_attr(miri, ignore)]
typed_funcs_count_params_correctly_in_error_messages( config: &mut Config, ) -> wasmtime::Result<()>1515 fn typed_funcs_count_params_correctly_in_error_messages(
1516 config: &mut Config,
1517 ) -> wasmtime::Result<()> {
1518 let engine = Engine::new(&config)?;
1519 let mut store = Store::<()>::new(&engine, ());
1520 let module = Module::new(
1521 store.engine(),
1522 r#"
1523 (module
1524 (func (export "f") (param i32 i32))
1525 )
1526
1527 "#,
1528 )?;
1529 let instance = Instance::new(&mut store, &module, &[])?;
1530
1531 // Too few parameters.
1532 match instance.get_typed_func::<(), ()>(&mut store, "f") {
1533 Ok(_) => panic!("should be wrong signature"),
1534 Err(e) => {
1535 let msg = format!("{e:?}");
1536 assert!(dbg!(msg).contains("expected 0 types, found 2"))
1537 }
1538 }
1539 match instance.get_typed_func::<(i32,), ()>(&mut store, "f") {
1540 Ok(_) => panic!("should be wrong signature"),
1541 Err(e) => {
1542 let msg = format!("{e:?}");
1543 assert!(dbg!(msg).contains("expected 1 types, found 2"))
1544 }
1545 }
1546
1547 // Too many parameters.
1548 match instance.get_typed_func::<(i32, i32, i32), ()>(&mut store, "f") {
1549 Ok(_) => panic!("should be wrong signature"),
1550 Err(e) => {
1551 let msg = format!("{e:?}");
1552 assert!(dbg!(msg).contains("expected 3 types, found 2"))
1553 }
1554 }
1555
1556 Ok(())
1557 }
1558
1559 #[wasmtime_test(wasm_features(reference_types, gc_types))]
1560 #[cfg_attr(miri, ignore)]
calls_with_funcref_and_externref(config: &mut Config) -> wasmtime::Result<()>1561 fn calls_with_funcref_and_externref(config: &mut Config) -> wasmtime::Result<()> {
1562 let engine = Engine::new(&config)?;
1563 let mut store = Store::<()>::new(&engine, ());
1564 let module = Module::new(
1565 store.engine(),
1566 r#"
1567 (module
1568 (import "" "witness" (func $witness (param funcref externref)))
1569 (func (export "f") (param funcref externref) (result externref funcref)
1570 local.get 0
1571 local.get 1
1572 call $witness
1573 local.get 1
1574 local.get 0
1575 )
1576 )
1577
1578 "#,
1579 )?;
1580 let mut linker = Linker::new(store.engine());
1581 linker.func_wrap(
1582 "",
1583 "witness",
1584 |mut caller: Caller<'_, ()>, func: Option<Func>, externref: Option<Rooted<ExternRef>>| {
1585 if func.is_some() {
1586 assert_my_funcref(&mut caller, func.as_ref())?;
1587 }
1588 if externref.is_some() {
1589 assert_my_externref(&caller, externref);
1590 }
1591 Ok(())
1592 },
1593 )?;
1594 let instance = linker.instantiate(&mut store, &module)?;
1595
1596 let typed = instance
1597 .get_typed_func::<(Option<Func>, Option<Rooted<ExternRef>>), (Option<Rooted<ExternRef>>, Option<Func>)>(
1598 &mut store, "f",
1599 )?;
1600 let untyped = typed.func();
1601
1602 let my_funcref = Func::wrap(&mut store, || 100u32);
1603 let my_externref = ExternRef::new(&mut store, 99u32)?;
1604 let mut results = [Val::I32(0), Val::I32(0)];
1605
1606 fn assert_my_funcref(mut store: impl AsContextMut, func: Option<&Func>) -> Result<()> {
1607 let mut store = store.as_context_mut();
1608 let func = func.unwrap();
1609 assert_eq!(func.typed::<(), u32>(&store)?.call(&mut store, ())?, 100);
1610 Ok(())
1611 }
1612 fn assert_my_externref(store: impl AsContext, externref: Option<Rooted<ExternRef>>) {
1613 assert_eq!(
1614 externref
1615 .unwrap()
1616 .data(&store)
1617 .unwrap()
1618 .unwrap()
1619 .downcast_ref(),
1620 Some(&99u32)
1621 );
1622 }
1623
1624 // funcref=null, externref=null
1625 let (a, b) = typed.call(&mut store, (None, None))?;
1626 assert!(a.is_none());
1627 assert!(b.is_none());
1628 untyped.call(
1629 &mut store,
1630 &[Val::FuncRef(None), Val::ExternRef(None)],
1631 &mut results,
1632 )?;
1633 assert!(results[0].unwrap_externref().is_none());
1634 assert!(results[1].unwrap_funcref().is_none());
1635
1636 // funcref=Some, externref=null
1637 let (a, b) = typed.call(&mut store, (Some(my_funcref), None))?;
1638 assert!(a.is_none());
1639 assert_my_funcref(&mut store, b.as_ref())?;
1640 untyped.call(
1641 &mut store,
1642 &[Val::FuncRef(Some(my_funcref)), Val::ExternRef(None)],
1643 &mut results,
1644 )?;
1645 assert!(results[0].unwrap_externref().is_none());
1646 assert_my_funcref(&mut store, results[1].unwrap_funcref())?;
1647
1648 // funcref=null, externref=Some
1649 let (a, b) = typed.call(&mut store, (None, Some(my_externref)))?;
1650 assert_my_externref(&store, a);
1651 assert!(b.is_none());
1652 untyped.call(
1653 &mut store,
1654 &[Val::FuncRef(None), Val::ExternRef(Some(my_externref))],
1655 &mut results,
1656 )?;
1657 assert_my_externref(&store, results[0].unwrap_externref().copied());
1658 assert!(results[1].unwrap_funcref().is_none());
1659
1660 // funcref=Some, externref=Some
1661 let (a, b) = typed.call(&mut store, (Some(my_funcref), Some(my_externref)))?;
1662 assert_my_externref(&store, a);
1663 assert_my_funcref(&mut store, b.as_ref())?;
1664 untyped.call(
1665 &mut store,
1666 &[
1667 Val::FuncRef(Some(my_funcref)),
1668 Val::ExternRef(Some(my_externref)),
1669 ],
1670 &mut results,
1671 )?;
1672 assert_my_externref(&store, results[0].unwrap_externref().copied());
1673 assert_my_funcref(&mut store, results[1].unwrap_funcref())?;
1674
1675 Ok(())
1676 }
1677
1678 #[wasmtime_test(wasm_features(function_references, bulk_memory))]
1679 #[cfg_attr(miri, ignore)]
typed_concrete_param(config: &mut Config) -> wasmtime::Result<()>1680 fn typed_concrete_param(config: &mut Config) -> wasmtime::Result<()> {
1681 let engine = Engine::new(&config)?;
1682 let module = Module::new(
1683 &engine,
1684 r#"
1685 (module
1686 (type $t (func))
1687 (func (export "f") (param (ref null $t)))
1688 )
1689 "#,
1690 )?;
1691 let mut store = Store::new(&engine, ());
1692 let instance = Instance::new(&mut store, &module, &[])?;
1693
1694 let nop = Func::new(
1695 &mut store,
1696 FuncType::new(&engine, None, None),
1697 |_caller, _params, _results| Ok(()),
1698 );
1699
1700 let f = instance.get_func(&mut store, "f").unwrap();
1701
1702 // Can type with a subtype, which should avoid all dynamic type checks after
1703 // successful construction.
1704 let a = f.typed::<Option<NoFunc>, ()>(&store)?;
1705 a.call(&mut store, None)?;
1706 // NB: Cannot call with Some(_) as `NoFunc` is uninhabited.
1707
1708 // Can call `typed` with a supertype, falling back to dynamic type checks on
1709 // each call.
1710 let a = f.typed::<Option<Func>, ()>(&store)?;
1711 a.call(&mut store, None)?;
1712 a.call(&mut store, Some(nop))?;
1713 let e = a.call(&mut store, Some(f)).expect_err(
1714 "should return an error because while we did pass an instance of \
1715 `Option<Func>`, it was not an instance of `(ref null $t)`",
1716 );
1717 let e = format!("{e:?}");
1718 assert!(e.contains("argument type mismatch for reference to concrete type"));
1719 assert!(e.contains(
1720 "type mismatch: expected (type (func)), \
1721 found (type (func (param (ref null (concrete func VMSharedTypeIndex(0))))))"
1722 ));
1723
1724 // And dynamic checks also work with a non-nullable super type.
1725 let a = f.typed::<Func, ()>(&store)?;
1726 a.call(&mut store, nop)?;
1727 let e = a.call(&mut store, f).expect_err(
1728 "should return an error because while we did pass an instance of \
1729 `Func`, it was not an instance of `(ref null $t)`",
1730 );
1731 let e = format!("{e:?}");
1732 assert!(e.contains("argument type mismatch for reference to concrete type"));
1733 assert!(e.contains(
1734 "type mismatch: expected (type (func)), \
1735 found (type (func (param (ref null (concrete func VMSharedTypeIndex(0))))))"
1736 ));
1737
1738 // Calling `typed` with a type that is not a supertype nor a subtype fails
1739 // the initial type check.
1740 let e = f
1741 .typed::<Option<Rooted<ExternRef>>, ()>(&store)
1742 .err()
1743 .unwrap();
1744 let e = format!("{e:?}");
1745 assert!(e.contains("type mismatch with parameters"));
1746 assert!(e.contains("type mismatch: expected func, found extern"));
1747
1748 Ok(())
1749 }
1750
1751 #[wasmtime_test(wasm_features(function_references, bulk_memory))]
1752 #[cfg_attr(miri, ignore)]
typed_concrete_result(config: &mut Config) -> wasmtime::Result<()>1753 fn typed_concrete_result(config: &mut Config) -> wasmtime::Result<()> {
1754 let engine = Engine::new(&config)?;
1755 let module = Module::new(
1756 &engine,
1757 r#"
1758 (module
1759 (type $t (func))
1760 (func $nop)
1761 (elem declare func $nop)
1762 (func (export "f") (result (ref $t))
1763 ref.func $nop
1764 )
1765 )
1766 "#,
1767 )?;
1768 let mut store = Store::new(&engine, ());
1769 let instance = Instance::new(&mut store, &module, &[])?;
1770
1771 let f = instance.get_func(&mut store, "f").unwrap();
1772
1773 // Can type `f` with a supertype of the declared result type, and we get the
1774 // expected return value.
1775 let a = f.typed::<(), Func>(&store)?;
1776 let g = a.call(&mut store, ())?;
1777 g.typed::<(), ()>(&store)?.call(&mut store, ())?;
1778
1779 // Also works with a nullable supertype.
1780 let a = f.typed::<(), Option<Func>>(&store)?;
1781 let g = a.call(&mut store, ())?;
1782 g.unwrap().typed::<(), ()>(&store)?.call(&mut store, ())?;
1783
1784 // But we can't claim that `f` returns a particular subtype of its actual
1785 // return type.
1786 let e = f.typed::<(), NoFunc>(&store).err().unwrap();
1787 let e = format!("{e:?}");
1788 assert!(e.contains("type mismatch with results"));
1789 assert!(e.contains(
1790 "type mismatch: expected (ref nofunc), found (ref (concrete func VMSharedTypeIndex(0)))"
1791 ));
1792
1793 // Nor some unrelated type that it is neither a subtype or supertype of.
1794 let e = f.typed::<(), Rooted<ExternRef>>(&store).err().unwrap();
1795 let e = format!("{e:?}");
1796 assert!(e.contains("type mismatch with results"));
1797 assert!(e.contains(
1798 "type mismatch: expected (ref extern), found (ref (concrete func VMSharedTypeIndex(0)))"
1799 ));
1800
1801 Ok(())
1802 }
1803
1804 #[test]
1805 #[cfg_attr(miri, ignore)]
wrap_subtype_param() -> wasmtime::Result<()>1806 fn wrap_subtype_param() -> wasmtime::Result<()> {
1807 let mut store = Store::<()>::default();
1808 let f = Func::wrap(&mut store, |_caller: Caller<'_, ()>, _: Option<Func>| {
1809 // No-op.
1810 });
1811
1812 // Precise type.
1813 let a = f.typed::<Option<Func>, ()>(&store)?;
1814 a.call(&mut store, None)?;
1815 a.call(&mut store, Some(f))?;
1816
1817 // Subtype via heap type.
1818 let a = f.typed::<Option<NoFunc>, ()>(&store)?;
1819 a.call(&mut store, None)?;
1820
1821 // Subtype via non-null.
1822 let a = f.typed::<Func, ()>(&store)?;
1823 a.call(&mut store, f)?;
1824
1825 Ok(())
1826 }
1827
1828 #[test]
1829 #[cfg_attr(miri, ignore)]
wrap_supertype_result() -> wasmtime::Result<()>1830 fn wrap_supertype_result() -> wasmtime::Result<()> {
1831 let mut store = Store::<()>::default();
1832 let f = Func::wrap(&mut store, |_caller: Caller<'_, ()>| -> NoFunc {
1833 unreachable!()
1834 });
1835
1836 // Precise type.
1837 let _ = f.typed::<(), NoFunc>(&store)?;
1838
1839 // Supertype via heap type.
1840 let _ = f.typed::<(), Func>(&store)?;
1841
1842 // Supertype via nullability.
1843 let _ = f.typed::<(), Option<NoFunc>>(&store)?;
1844
1845 Ok(())
1846 }
1847
1848 #[wasmtime_test(wasm_features(function_references))]
1849 #[cfg_attr(miri, ignore)]
call_wasm_passing_subtype_func_param(config: &mut Config) -> wasmtime::Result<()>1850 fn call_wasm_passing_subtype_func_param(config: &mut Config) -> wasmtime::Result<()> {
1851 config.wasm_function_references(true);
1852 let engine = Engine::new(&config)?;
1853 let mut store = Store::new(&engine, ());
1854
1855 let module = Module::new(
1856 &engine,
1857 r#"
1858 (module
1859 (type $ty (func (result funcref)))
1860 (func (export "f") (param (ref null $ty)) (result funcref)
1861 ;; Return null if the funcref is null.
1862 ref.null func
1863 local.get 0
1864 ref.is_null
1865 br_if 0
1866 drop
1867
1868 ;; Otherwise, call it.
1869 local.get 0
1870 call_ref $ty
1871 )
1872 )
1873 "#,
1874 )?;
1875
1876 let instance = Instance::new(&mut store, &module, &[])?;
1877 let f = instance.get_func(&mut store, "f").unwrap();
1878
1879 let g_ty = FuncType::new(&engine, None, Some(ValType::I32));
1880 let g = Func::new(&mut store, g_ty.clone(), |_caller, _params, results| {
1881 results[0] = Val::I32(0x1234_5678);
1882 Ok(())
1883 });
1884
1885 // h's type is a subtype of the Wasm-defined `$ty`:
1886 //
1887 // (func (result (ref null g_ty))) <: (func (result funcref))
1888 let h_ty = FuncType::new(
1889 &engine,
1890 None,
1891 Some(ValType::Ref(RefType::new(
1892 true,
1893 HeapType::ConcreteFunc(g_ty),
1894 ))),
1895 );
1896 let h = Func::new(&mut store, h_ty, move |_caller, _params, results| {
1897 results[0] = Val::FuncRef(Some(g));
1898 Ok(())
1899 });
1900
1901 // Array call, passing in a subtype of the expected parameter.
1902
1903 let mut results = vec![Val::I32(0)];
1904 f.call(&mut store, &[Val::null_func_ref()], &mut results)?;
1905 assert!(results[0].unwrap_func_ref().is_none());
1906
1907 f.call(&mut store, &[h.into()], &mut results)?;
1908 let g = results[0];
1909 let g = g.unwrap_func_ref().unwrap();
1910 g.call(&mut store, &[], &mut results)?;
1911 assert_eq!(results[0].unwrap_i32(), 0x1234_5678);
1912
1913 // Native call, passing in a subtype of the expected parameter.
1914
1915 let f = f.typed::<Option<Func>, Option<Func>>(&store)?;
1916 let r = f.call(&mut store, None)?;
1917 assert!(r.is_none());
1918
1919 let g = f.call(&mut store, Some(h))?;
1920 let g = g.unwrap().typed::<(), u32>(&mut store)?;
1921 let x = g.call(&mut store, ())?;
1922 assert_eq!(x, 0x1234_5678);
1923
1924 Ok(())
1925 }
1926
1927 #[wasmtime_test(wasm_features(gc, function_references, bulk_memory))]
1928 #[cfg_attr(miri, ignore)]
call_wasm_getting_subtype_func_return(config: &mut Config) -> wasmtime::Result<()>1929 fn call_wasm_getting_subtype_func_return(config: &mut Config) -> wasmtime::Result<()> {
1930 let engine = Engine::new(&config)?;
1931 let mut store = Store::new(&engine, ());
1932
1933 let module = Module::new(
1934 &engine,
1935 r#"
1936 (module
1937 (type $ty (func (result funcref)))
1938
1939 (func $a (result i32)
1940 i32.const 0x12345678
1941 )
1942
1943 (func $b (result funcref)
1944 ref.func $a
1945 )
1946
1947 (elem declare func $a $b)
1948
1949 ;; Returns a `(ref null nofunc)` if called with `0`, otherwise
1950 ;; returns `(ref null $ty)`, both of which are subtypes of
1951 ;; `funcref`.
1952 (func (export "f") (param i32) (result funcref)
1953 block
1954 local.get 0
1955 br_if 0
1956 ref.null nofunc
1957 return
1958 end
1959 ref.func $b
1960 )
1961 )
1962 "#,
1963 )?;
1964
1965 let instance = Instance::new(&mut store, &module, &[])?;
1966 let f = instance.get_func(&mut store, "f").unwrap();
1967
1968 // Array call, receiving a subtype of the expected result.
1969
1970 let mut results = vec![Val::I32(0)];
1971 f.call(&mut store, &[Val::I32(0)], &mut results)?;
1972 assert!(results[0].unwrap_func_ref().is_none());
1973
1974 f.call(&mut store, &[Val::I32(1)], &mut results)?;
1975 let b = results[0];
1976 let b = b.unwrap_func_ref().unwrap();
1977 b.call(&mut store, &[], &mut results)?;
1978 let a = results[0];
1979 let a = a.unwrap_func_ref().unwrap();
1980 a.call(&mut store, &[], &mut results)?;
1981 assert_eq!(results[0].unwrap_i32(), 0x1234_5678);
1982
1983 // Native call, receiving a subtype of the expected result.
1984
1985 let f = f.typed::<u32, Option<Func>>(&store)?;
1986 let r = f.call(&mut store, 0)?;
1987 assert!(r.is_none());
1988
1989 let b = f.call(&mut store, 1)?;
1990 let b = b.unwrap().typed::<(), Option<Func>>(&store)?;
1991 let a = b.call(&mut store, ())?;
1992 let a = a.unwrap().typed::<(), u32>(&store)?;
1993 let x = a.call(&mut store, ())?;
1994 assert_eq!(x, 0x1234_5678);
1995
1996 Ok(())
1997 }
1998
1999 #[wasmtime_test(wasm_features(simd), strategies(not(Winch)))]
2000 #[cfg_attr(miri, ignore)]
typed_v128(config: &mut Config) -> wasmtime::Result<()>2001 fn typed_v128(config: &mut Config) -> wasmtime::Result<()> {
2002 let engine = Engine::new(&config)?;
2003 let mut store = Store::<()>::new(&engine, ());
2004 let module = Module::new(
2005 store.engine(),
2006 r#"
2007 (module
2008 (func (export "a") (param v128) (result v128)
2009 local.get 0)
2010 (func (export "b") (param v128 v128) (result v128 v128)
2011 local.get 0
2012 local.get 1)
2013 (func (export "c") (param v128 v128 v128 v128 v128 v128 v128 v128) (result v128)
2014 local.get 0
2015 local.get 1
2016 local.get 2
2017 local.get 3
2018 local.get 4
2019 local.get 5
2020 local.get 6
2021 local.get 7
2022 i64x2.add
2023 i64x2.add
2024 i64x2.add
2025 i64x2.add
2026 i64x2.add
2027 i64x2.add
2028 i64x2.add)
2029 )
2030
2031 "#,
2032 )?;
2033 let instance = Instance::new(&mut store, &module, &[])?;
2034
2035 let a = instance.get_typed_func::<V128, V128>(&mut store, "a")?;
2036 assert_eq!(a.call(&mut store, V128::from(1))?, V128::from(1));
2037 assert_eq!(a.call(&mut store, V128::from(2))?, V128::from(2));
2038
2039 let b = instance.get_typed_func::<(V128, V128), (V128, V128)>(&mut store, "b")?;
2040 assert_eq!(
2041 b.call(&mut store, (V128::from(1), V128::from(2)))?,
2042 (V128::from(1), V128::from(2))
2043 );
2044
2045 let c = instance.get_typed_func::<(V128, V128, V128, V128, V128, V128, V128, V128), V128>(
2046 &mut store, "c",
2047 )?;
2048 assert_eq!(
2049 c.call(
2050 &mut store,
2051 (
2052 V128::from(1),
2053 V128::from(2),
2054 V128::from(3),
2055 V128::from(4),
2056 V128::from(5),
2057 V128::from(6),
2058 V128::from(7),
2059 V128::from(8),
2060 )
2061 )?,
2062 V128::from(1 + 2 + 3 + 4 + 5 + 6 + 7 + 8),
2063 );
2064
2065 Ok(())
2066 }
2067
2068 #[wasmtime_test(wasm_features(simd))]
2069 #[cfg_attr(miri, ignore)]
typed_v128_imports(config: &mut Config) -> wasmtime::Result<()>2070 fn typed_v128_imports(config: &mut Config) -> wasmtime::Result<()> {
2071 let engine = Engine::new(&config)?;
2072 let mut store = Store::<()>::new(&engine, ());
2073 let module = Module::new(
2074 store.engine(),
2075 r#"
2076 (module
2077 (import "" "a" (func $a (param v128) (result i32)))
2078 (import "" "b" (func $b (param i32) (result v128)))
2079 (import "" "c" (func $c (param v128 f64 v128) (result v128 i32 v128)))
2080 (import "" "d" (func $d (param v128 v128 v128 v128 v128 v128 v128 v128) (result i32)))
2081
2082 (func (export "a") (param v128) (result i32)
2083 local.get 0
2084 call $a)
2085
2086 (func (export "b") (param i32) (result v128)
2087 local.get 0
2088 call $b)
2089
2090 (func (export "c") (param v128 f64 v128) (result v128 i32 v128)
2091 local.get 0
2092 local.get 1
2093 local.get 2
2094 call $c)
2095
2096 (func (export "d") (param v128 v128 v128 v128 v128 v128 v128 v128) (result i32)
2097 local.get 0
2098 local.get 1
2099 local.get 2
2100 local.get 3
2101 local.get 4
2102 local.get 5
2103 local.get 6
2104 local.get 7
2105 call $d)
2106 )
2107
2108 "#,
2109 )?;
2110
2111 let mut l = Linker::new(store.engine());
2112 l.func_wrap("", "a", |x: V128| {
2113 let x = x.as_u128();
2114 (x >> 0) as u32 + (x >> 32) as u32 + (x >> 64) as u32 + (x >> 96) as u32
2115 })?;
2116 l.func_wrap("", "b", |x: u32| {
2117 let x = u128::from(x);
2118 V128::from(x | ((x + 1) << 32) | ((x + 2) << 64) | ((x + 3) << 96))
2119 })?;
2120 l.func_wrap("", "c", |x: V128, y: f64, z: V128| (x, y as i32, z))?;
2121 l.func_wrap(
2122 "",
2123 "d",
2124 |a0: V128, a1: V128, a2: V128, a3: V128, a4: V128, a5: V128, a6: V128, a7: V128| {
2125 let tmp = a0.as_u128()
2126 + a1.as_u128()
2127 + a2.as_u128()
2128 + a3.as_u128()
2129 + a4.as_u128()
2130 + a5.as_u128()
2131 + a6.as_u128()
2132 + a7.as_u128();
2133 (tmp >> 0) as u32 + (tmp >> 32) as u32 + (tmp >> 64) as u32 + (tmp >> 96) as u32
2134 },
2135 )?;
2136
2137 let i = l.instantiate(&mut store, &module)?;
2138 let a = i.get_typed_func::<V128, i32>(&mut store, "a")?;
2139 let b = i.get_typed_func::<i32, V128>(&mut store, "b")?;
2140 let c = i.get_typed_func::<(V128, f64, V128), (V128, i32, V128)>(&mut store, "c")?;
2141 let d =
2142 i.get_typed_func::<(V128, V128, V128, V128, V128, V128, V128, V128), i32>(&mut store, "d")?;
2143
2144 assert_eq!(
2145 a.call(&mut store, 0x00000004_00000003_00000002_00000001.into())?,
2146 1 + 2 + 3 + 4
2147 );
2148 assert_eq!(
2149 b.call(&mut store, 0x10)?,
2150 V128::from(0x00000013_00000012_00000011_00000010),
2151 );
2152 assert_eq!(
2153 c.call(&mut store, (1.into(), 2., 3.into()))?,
2154 (V128::from(1), 2, V128::from(3)),
2155 );
2156 assert_eq!(
2157 d.call(
2158 &mut store,
2159 (
2160 1.into(),
2161 2.into(),
2162 3.into(),
2163 4.into(),
2164 5.into(),
2165 6.into(),
2166 7.into(),
2167 8.into(),
2168 )
2169 )?,
2170 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8
2171 );
2172
2173 Ok(())
2174 }
2175
2176 #[wasmtime_test(wasm_features(function_references, gc))]
2177 #[cfg_attr(miri, ignore)]
wrap_and_typed_i31ref(config: &mut Config) -> Result<()>2178 fn wrap_and_typed_i31ref(config: &mut Config) -> Result<()> {
2179 let engine = Engine::new(&config)?;
2180 let mut store = Store::<AtomicUsize>::new(&engine, AtomicUsize::new(0));
2181
2182 let mut linker = Linker::new(&engine);
2183 linker.func_wrap(
2184 "env",
2185 "i31ref",
2186 |caller: Caller<'_, AtomicUsize>, x: Option<I31>| -> Option<I31> {
2187 assert_eq!(caller.data().fetch_add(1, Ordering::SeqCst), 0);
2188 x
2189 },
2190 )?;
2191 linker.func_wrap(
2192 "env",
2193 "ref-i31",
2194 |caller: Caller<'_, AtomicUsize>, x: I31| -> I31 {
2195 assert_eq!(caller.data().fetch_add(1, Ordering::SeqCst), 1);
2196 x
2197 },
2198 )?;
2199
2200 let module = Module::new(
2201 &engine,
2202 r#"
2203 (module
2204 (import "env" "i31ref" (func (param i31ref) (result i31ref)))
2205 (import "env" "ref-i31" (func (param (ref i31)) (result (ref i31))))
2206
2207 (func (export "i31ref") (param i31ref) (result i31ref)
2208 local.get 0
2209 call 0
2210 )
2211
2212 (func (export "ref-i31") (param (ref i31)) (result (ref i31))
2213 local.get 0
2214 call 1
2215 )
2216 )
2217 "#,
2218 )?;
2219
2220 let instance = linker.instantiate(&mut store, &module)?;
2221
2222 let i31ref = instance.get_typed_func::<Option<I31>, Option<I31>>(&mut store, "i31ref")?;
2223 let x = i31ref.call(&mut store, Some(I31::wrapping_u32(42)))?;
2224 assert_eq!(x, Some(I31::wrapping_u32(42)));
2225
2226 let ref_i31 = instance.get_typed_func::<I31, I31>(&mut store, "ref-i31")?;
2227 let x = ref_i31.call(&mut store, I31::wrapping_u32(0x1234))?;
2228 assert_eq!(x, I31::wrapping_u32(0x1234));
2229
2230 assert_eq!(store.data().load(Ordering::SeqCst), 2);
2231 Ok(())
2232 }
2233
2234 #[wasmtime_test(wasm_features(function_references, gc))]
call_func_with_funcref_both_typed_and_untyped(config: &mut Config) -> Result<()>2235 fn call_func_with_funcref_both_typed_and_untyped(config: &mut Config) -> Result<()> {
2236 let engine = Engine::new(&config)?;
2237 let mut store = Store::new(&engine, ());
2238
2239 let f1 = Func::wrap(&mut store, |_: Option<Func>| {});
2240 let f2 = Func::wrap(&mut store, || {});
2241
2242 f1.typed::<Func, ()>(&mut store)?.call(&mut store, f2)?;
2243 f1.call(&mut store, &[Val::FuncRef(Some(f2))], &mut [])?;
2244 Ok(())
2245 }
2246
2247 #[wasmtime_test(wasm_features(function_references, gc))]
2248 #[cfg_attr(miri, ignore)]
wasm_to_host_trampolines_and_subtyping(config: &mut Config) -> Result<()>2249 fn wasm_to_host_trampolines_and_subtyping(config: &mut Config) -> Result<()> {
2250 let _ = env_logger::try_init();
2251
2252 let engine = Engine::new(&config)?;
2253
2254 let ft0 = FuncType::with_finality_and_supertype(
2255 &engine,
2256 Finality::NonFinal,
2257 None,
2258 [],
2259 [ValType::Ref(RefType::new(true, HeapType::Extern))],
2260 )?;
2261 let ft1 = FuncType::with_finality_and_supertype(
2262 &engine,
2263 Finality::NonFinal,
2264 Some(&ft0),
2265 [],
2266 [ValType::Ref(RefType::new(false, HeapType::Extern))],
2267 )?;
2268
2269 let module = Module::new(
2270 &engine,
2271 r#"
2272 (module
2273 (type $ft0 (sub (func (result (ref null extern)))))
2274
2275 (import "" "a" (func $imported_func (type $ft0)))
2276 (import "" "return_func" (func $return_func (result (ref $ft0))))
2277 (global $g (export "g") (mut (ref null $ft0)) (ref.null $ft0))
2278 (table $t (export "t") 10 10 (ref null $ft0))
2279
2280 (func (export "f")
2281 (drop (call $imported_func))
2282 (drop (call_ref $ft0 (call $return_func)))
2283 (drop (call_ref $ft0 (global.get $g)))
2284 (drop (call_ref $ft0 (table.get $t (i32.const 0))))
2285 )
2286 )
2287 "#,
2288 )?;
2289
2290 // This defines a function of type `(func (result (ref extern)))` and not of
2291 // type `(func (result (ref null extern)))` that the Wasm imports. But it is
2292 // still a subtype of the Wasm import's type, so we should be able to use
2293 // the Wasm's precompiled trampolines with this host function.
2294 //
2295 // But this means we also need to look up the trampoline by the caller's
2296 // type, rather than the callee's type.
2297 //
2298 // So give it to Wasm in every way that Wasm can receive a function, and
2299 // make sure we find the correct trampolines in all cases and everything
2300 // works.
2301 let make_func = |store: &mut Store<_>| {
2302 Func::new(
2303 store,
2304 ft1.clone(),
2305 |mut caller: Caller<'_, ()>, _args, results| {
2306 results[0] = ExternRef::new(&mut caller, 200)?.into();
2307 Ok(())
2308 },
2309 )
2310 };
2311
2312 let return_func_ty = module.imports().nth(1).unwrap().ty().unwrap_func().clone();
2313
2314 let mut store = Store::new(&engine, ());
2315
2316 let imported_func = make_func(&mut store);
2317 assert!(FuncType::eq(&imported_func.ty(&store), &ft1));
2318
2319 let returned_func = make_func(&mut store);
2320 assert!(FuncType::eq(&returned_func.ty(&store), &ft1));
2321
2322 let return_func = Func::new(
2323 &mut store,
2324 return_func_ty.clone(),
2325 move |_caller, _args, results| {
2326 results[0] = returned_func.into();
2327 Ok(())
2328 },
2329 );
2330
2331 let instance = Instance::new(
2332 &mut store,
2333 &module,
2334 &[imported_func.into(), return_func.into()],
2335 )?;
2336
2337 let g = make_func(&mut store);
2338 assert!(FuncType::eq(&g.ty(&store), &ft1));
2339 instance
2340 .get_global(&mut store, "g")
2341 .unwrap()
2342 .set(&mut store, g.into())?;
2343
2344 let t = make_func(&mut store);
2345 assert!(FuncType::eq(&t.ty(&store), &ft1));
2346 instance
2347 .get_table(&mut store, "t")
2348 .unwrap()
2349 .set(&mut store, 0, t.into())?;
2350
2351 let f = instance.get_typed_func::<(), ()>(&mut store, "f")?;
2352 f.call(&mut store, ())?;
2353
2354 Ok(())
2355 }
2356