Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/tests/all/func.rs
1690 views
1
use anyhow::bail;
2
use std::sync::Arc;
3
use std::sync::atomic::Ordering;
4
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering::SeqCst};
5
use wasmtime::*;
6
use wasmtime_test_macros::wasmtime_test;
7
8
#[wasmtime_test]
9
#[cfg_attr(miri, ignore)]
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)]
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)]
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)]
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]
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)]
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)]
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]
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)]
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)]
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)]
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)]
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)]
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)]
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]
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]
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)]
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]
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)]
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)]
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)]
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]
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)]
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)]
926
fn get_from_module(config: &mut Config) -> anyhow::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]
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)]
999
fn caller_memory(config: &mut Config) -> anyhow::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)]
1066
fn func_write_nothing() -> anyhow::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)]
1080
fn return_cross_store_value(config: &mut Config) -> anyhow::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))]
1112
fn pass_cross_store_arg(config: &mut Config) -> anyhow::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)]
1140
fn externref_signature_no_reference_types() -> anyhow::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)]
1156
fn trampolines_always_valid(config: &mut Config) -> anyhow::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)]
1184
fn typed_multiple_results(config: &mut Config) -> anyhow::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)]
1222
fn trap_doesnt_leak() -> anyhow::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)]
1264
fn wrap_multiple_results(config: &mut Config) -> anyhow::Result<()> {
1265
fn test<T>(store: &mut Store<()>, t: T) -> anyhow::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, gc_types))]
1429
#[cfg_attr(miri, ignore)]
1430
fn trampoline_for_declared_elem(config: &mut Config) -> anyhow::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)]
1458
fn wasm_ty_roundtrip(config: &mut Config) -> Result<(), anyhow::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)]
1515
fn typed_funcs_count_params_correctly_in_error_messages(config: &mut Config) -> anyhow::Result<()> {
1516
let engine = Engine::new(&config)?;
1517
let mut store = Store::<()>::new(&engine, ());
1518
let module = Module::new(
1519
store.engine(),
1520
r#"
1521
(module
1522
(func (export "f") (param i32 i32))
1523
)
1524
1525
"#,
1526
)?;
1527
let instance = Instance::new(&mut store, &module, &[])?;
1528
1529
// Too few parameters.
1530
match instance.get_typed_func::<(), ()>(&mut store, "f") {
1531
Ok(_) => panic!("should be wrong signature"),
1532
Err(e) => {
1533
let msg = format!("{e:?}");
1534
assert!(dbg!(msg).contains("expected 0 types, found 2"))
1535
}
1536
}
1537
match instance.get_typed_func::<(i32,), ()>(&mut store, "f") {
1538
Ok(_) => panic!("should be wrong signature"),
1539
Err(e) => {
1540
let msg = format!("{e:?}");
1541
assert!(dbg!(msg).contains("expected 1 types, found 2"))
1542
}
1543
}
1544
1545
// Too many parameters.
1546
match instance.get_typed_func::<(i32, i32, i32), ()>(&mut store, "f") {
1547
Ok(_) => panic!("should be wrong signature"),
1548
Err(e) => {
1549
let msg = format!("{e:?}");
1550
assert!(dbg!(msg).contains("expected 3 types, found 2"))
1551
}
1552
}
1553
1554
Ok(())
1555
}
1556
1557
#[wasmtime_test(wasm_features(reference_types, gc_types))]
1558
#[cfg_attr(miri, ignore)]
1559
fn calls_with_funcref_and_externref(config: &mut Config) -> anyhow::Result<()> {
1560
let engine = Engine::new(&config)?;
1561
let mut store = Store::<()>::new(&engine, ());
1562
let module = Module::new(
1563
store.engine(),
1564
r#"
1565
(module
1566
(import "" "witness" (func $witness (param funcref externref)))
1567
(func (export "f") (param funcref externref) (result externref funcref)
1568
local.get 0
1569
local.get 1
1570
call $witness
1571
local.get 1
1572
local.get 0
1573
)
1574
)
1575
1576
"#,
1577
)?;
1578
let mut linker = Linker::new(store.engine());
1579
linker.func_wrap(
1580
"",
1581
"witness",
1582
|mut caller: Caller<'_, ()>, func: Option<Func>, externref: Option<Rooted<ExternRef>>| {
1583
if func.is_some() {
1584
assert_my_funcref(&mut caller, func.as_ref())?;
1585
}
1586
if externref.is_some() {
1587
assert_my_externref(&caller, externref);
1588
}
1589
Ok(())
1590
},
1591
)?;
1592
let instance = linker.instantiate(&mut store, &module)?;
1593
1594
let typed = instance
1595
.get_typed_func::<(Option<Func>, Option<Rooted<ExternRef>>), (Option<Rooted<ExternRef>>, Option<Func>)>(
1596
&mut store, "f",
1597
)?;
1598
let untyped = typed.func();
1599
1600
let my_funcref = Func::wrap(&mut store, || 100u32);
1601
let my_externref = ExternRef::new(&mut store, 99u32)?;
1602
let mut results = [Val::I32(0), Val::I32(0)];
1603
1604
fn assert_my_funcref(mut store: impl AsContextMut, func: Option<&Func>) -> Result<()> {
1605
let mut store = store.as_context_mut();
1606
let func = func.unwrap();
1607
assert_eq!(func.typed::<(), u32>(&store)?.call(&mut store, ())?, 100);
1608
Ok(())
1609
}
1610
fn assert_my_externref(store: impl AsContext, externref: Option<Rooted<ExternRef>>) {
1611
assert_eq!(
1612
externref
1613
.unwrap()
1614
.data(&store)
1615
.unwrap()
1616
.unwrap()
1617
.downcast_ref(),
1618
Some(&99u32)
1619
);
1620
}
1621
1622
// funcref=null, externref=null
1623
let (a, b) = typed.call(&mut store, (None, None))?;
1624
assert!(a.is_none());
1625
assert!(b.is_none());
1626
untyped.call(
1627
&mut store,
1628
&[Val::FuncRef(None), Val::ExternRef(None)],
1629
&mut results,
1630
)?;
1631
assert!(results[0].unwrap_externref().is_none());
1632
assert!(results[1].unwrap_funcref().is_none());
1633
1634
// funcref=Some, externref=null
1635
let (a, b) = typed.call(&mut store, (Some(my_funcref), None))?;
1636
assert!(a.is_none());
1637
assert_my_funcref(&mut store, b.as_ref())?;
1638
untyped.call(
1639
&mut store,
1640
&[Val::FuncRef(Some(my_funcref)), Val::ExternRef(None)],
1641
&mut results,
1642
)?;
1643
assert!(results[0].unwrap_externref().is_none());
1644
assert_my_funcref(&mut store, results[1].unwrap_funcref())?;
1645
1646
// funcref=null, externref=Some
1647
let (a, b) = typed.call(&mut store, (None, Some(my_externref)))?;
1648
assert_my_externref(&store, a);
1649
assert!(b.is_none());
1650
untyped.call(
1651
&mut store,
1652
&[Val::FuncRef(None), Val::ExternRef(Some(my_externref))],
1653
&mut results,
1654
)?;
1655
assert_my_externref(&store, results[0].unwrap_externref().copied());
1656
assert!(results[1].unwrap_funcref().is_none());
1657
1658
// funcref=Some, externref=Some
1659
let (a, b) = typed.call(&mut store, (Some(my_funcref), Some(my_externref)))?;
1660
assert_my_externref(&store, a);
1661
assert_my_funcref(&mut store, b.as_ref())?;
1662
untyped.call(
1663
&mut store,
1664
&[
1665
Val::FuncRef(Some(my_funcref)),
1666
Val::ExternRef(Some(my_externref)),
1667
],
1668
&mut results,
1669
)?;
1670
assert_my_externref(&store, results[0].unwrap_externref().copied());
1671
assert_my_funcref(&mut store, results[1].unwrap_funcref())?;
1672
1673
Ok(())
1674
}
1675
1676
#[wasmtime_test(wasm_features(function_references))]
1677
#[cfg_attr(miri, ignore)]
1678
fn typed_concrete_param(config: &mut Config) -> anyhow::Result<()> {
1679
let engine = Engine::new(&config)?;
1680
let module = Module::new(
1681
&engine,
1682
r#"
1683
(module
1684
(type $t (func))
1685
(func (export "f") (param (ref null $t)))
1686
)
1687
"#,
1688
)?;
1689
let mut store = Store::new(&engine, ());
1690
let instance = Instance::new(&mut store, &module, &[])?;
1691
1692
let nop = Func::new(
1693
&mut store,
1694
FuncType::new(&engine, None, None),
1695
|_caller, _params, _results| Ok(()),
1696
);
1697
1698
let f = instance.get_func(&mut store, "f").unwrap();
1699
1700
// Can type with a subtype, which should avoid all dynamic type checks after
1701
// successful construction.
1702
let a = f.typed::<Option<NoFunc>, ()>(&store)?;
1703
a.call(&mut store, None)?;
1704
// NB: Cannot call with Some(_) as `NoFunc` is uninhabited.
1705
1706
// Can call `typed` with a supertype, falling back to dynamic type checks on
1707
// each call.
1708
let a = f.typed::<Option<Func>, ()>(&store)?;
1709
a.call(&mut store, None)?;
1710
a.call(&mut store, Some(nop))?;
1711
let e = a.call(&mut store, Some(f)).expect_err(
1712
"should return an error because while we did pass an instance of \
1713
`Option<Func>`, it was not an instance of `(ref null $t)`",
1714
);
1715
let e = format!("{e:?}");
1716
assert!(e.contains("argument type mismatch for reference to concrete type"));
1717
assert!(e.contains(
1718
"type mismatch: expected (type (func)), \
1719
found (type (func (param (ref null (concrete func VMSharedTypeIndex(0))))))"
1720
));
1721
1722
// And dynamic checks also work with a non-nullable super type.
1723
let a = f.typed::<Func, ()>(&store)?;
1724
a.call(&mut store, nop)?;
1725
let e = a.call(&mut store, f).expect_err(
1726
"should return an error because while we did pass an instance of \
1727
`Func`, it was not an instance of `(ref null $t)`",
1728
);
1729
let e = format!("{e:?}");
1730
assert!(e.contains("argument type mismatch for reference to concrete type"));
1731
assert!(e.contains(
1732
"type mismatch: expected (type (func)), \
1733
found (type (func (param (ref null (concrete func VMSharedTypeIndex(0))))))"
1734
));
1735
1736
// Calling `typed` with a type that is not a supertype nor a subtype fails
1737
// the initial type check.
1738
let e = f
1739
.typed::<Option<Rooted<ExternRef>>, ()>(&store)
1740
.err()
1741
.unwrap();
1742
let e = format!("{e:?}");
1743
assert!(e.contains("type mismatch with parameters"));
1744
assert!(e.contains("type mismatch: expected func, found extern"));
1745
1746
Ok(())
1747
}
1748
1749
#[wasmtime_test(wasm_features(function_references))]
1750
#[cfg_attr(miri, ignore)]
1751
fn typed_concrete_result(config: &mut Config) -> anyhow::Result<()> {
1752
let engine = Engine::new(&config)?;
1753
let module = Module::new(
1754
&engine,
1755
r#"
1756
(module
1757
(type $t (func))
1758
(func $nop)
1759
(elem declare func $nop)
1760
(func (export "f") (result (ref $t))
1761
ref.func $nop
1762
)
1763
)
1764
"#,
1765
)?;
1766
let mut store = Store::new(&engine, ());
1767
let instance = Instance::new(&mut store, &module, &[])?;
1768
1769
let f = instance.get_func(&mut store, "f").unwrap();
1770
1771
// Can type `f` with a supertype of the declared result type, and we get the
1772
// expected return value.
1773
let a = f.typed::<(), Func>(&store)?;
1774
let g = a.call(&mut store, ())?;
1775
g.typed::<(), ()>(&store)?.call(&mut store, ())?;
1776
1777
// Also works with a nullable supertype.
1778
let a = f.typed::<(), Option<Func>>(&store)?;
1779
let g = a.call(&mut store, ())?;
1780
g.unwrap().typed::<(), ()>(&store)?.call(&mut store, ())?;
1781
1782
// But we can't claim that `f` returns a particular subtype of its actual
1783
// return type.
1784
let e = f.typed::<(), NoFunc>(&store).err().unwrap();
1785
let e = format!("{e:?}");
1786
assert!(e.contains("type mismatch with results"));
1787
assert!(e.contains(
1788
"type mismatch: expected (ref nofunc), found (ref (concrete func VMSharedTypeIndex(0)))"
1789
));
1790
1791
// Nor some unrelated type that it is neither a subtype or supertype of.
1792
let e = f.typed::<(), Rooted<ExternRef>>(&store).err().unwrap();
1793
let e = format!("{e:?}");
1794
assert!(e.contains("type mismatch with results"));
1795
assert!(e.contains(
1796
"type mismatch: expected (ref extern), found (ref (concrete func VMSharedTypeIndex(0)))"
1797
));
1798
1799
Ok(())
1800
}
1801
1802
#[test]
1803
#[cfg_attr(miri, ignore)]
1804
fn wrap_subtype_param() -> anyhow::Result<()> {
1805
let mut store = Store::<()>::default();
1806
let f = Func::wrap(&mut store, |_caller: Caller<'_, ()>, _: Option<Func>| {
1807
// No-op.
1808
});
1809
1810
// Precise type.
1811
let a = f.typed::<Option<Func>, ()>(&store)?;
1812
a.call(&mut store, None)?;
1813
a.call(&mut store, Some(f))?;
1814
1815
// Subtype via heap type.
1816
let a = f.typed::<Option<NoFunc>, ()>(&store)?;
1817
a.call(&mut store, None)?;
1818
1819
// Subtype via non-null.
1820
let a = f.typed::<Func, ()>(&store)?;
1821
a.call(&mut store, f)?;
1822
1823
Ok(())
1824
}
1825
1826
#[test]
1827
#[cfg_attr(miri, ignore)]
1828
fn wrap_supertype_result() -> anyhow::Result<()> {
1829
let mut store = Store::<()>::default();
1830
let f = Func::wrap(&mut store, |_caller: Caller<'_, ()>| -> NoFunc {
1831
unreachable!()
1832
});
1833
1834
// Precise type.
1835
let _ = f.typed::<(), NoFunc>(&store)?;
1836
1837
// Supertype via heap type.
1838
let _ = f.typed::<(), Func>(&store)?;
1839
1840
// Supertype via nullability.
1841
let _ = f.typed::<(), Option<NoFunc>>(&store)?;
1842
1843
Ok(())
1844
}
1845
1846
#[wasmtime_test(wasm_features(function_references))]
1847
#[cfg_attr(miri, ignore)]
1848
fn call_wasm_passing_subtype_func_param(config: &mut Config) -> anyhow::Result<()> {
1849
config.wasm_function_references(true);
1850
let engine = Engine::new(&config)?;
1851
let mut store = Store::new(&engine, ());
1852
1853
let module = Module::new(
1854
&engine,
1855
r#"
1856
(module
1857
(type $ty (func (result funcref)))
1858
(func (export "f") (param (ref null $ty)) (result funcref)
1859
;; Return null if the funcref is null.
1860
ref.null func
1861
local.get 0
1862
ref.is_null
1863
br_if 0
1864
drop
1865
1866
;; Otherwise, call it.
1867
local.get 0
1868
call_ref $ty
1869
)
1870
)
1871
"#,
1872
)?;
1873
1874
let instance = Instance::new(&mut store, &module, &[])?;
1875
let f = instance.get_func(&mut store, "f").unwrap();
1876
1877
let g_ty = FuncType::new(&engine, None, Some(ValType::I32));
1878
let g = Func::new(&mut store, g_ty.clone(), |_caller, _params, results| {
1879
results[0] = Val::I32(0x1234_5678);
1880
Ok(())
1881
});
1882
1883
// h's type is a subtype of the Wasm-defined `$ty`:
1884
//
1885
// (func (result (ref null g_ty))) <: (func (result funcref))
1886
let h_ty = FuncType::new(
1887
&engine,
1888
None,
1889
Some(ValType::Ref(RefType::new(
1890
true,
1891
HeapType::ConcreteFunc(g_ty),
1892
))),
1893
);
1894
let h = Func::new(&mut store, h_ty, move |_caller, _params, results| {
1895
results[0] = Val::FuncRef(Some(g));
1896
Ok(())
1897
});
1898
1899
// Array call, passing in a subtype of the expected parameter.
1900
1901
let mut results = vec![Val::I32(0)];
1902
f.call(&mut store, &[Val::null_func_ref()], &mut results)?;
1903
assert!(results[0].unwrap_func_ref().is_none());
1904
1905
f.call(&mut store, &[h.into()], &mut results)?;
1906
let g = results[0];
1907
let g = g.unwrap_func_ref().unwrap();
1908
g.call(&mut store, &[], &mut results)?;
1909
assert_eq!(results[0].unwrap_i32(), 0x1234_5678);
1910
1911
// Native call, passing in a subtype of the expected parameter.
1912
1913
let f = f.typed::<Option<Func>, Option<Func>>(&store)?;
1914
let r = f.call(&mut store, None)?;
1915
assert!(r.is_none());
1916
1917
let g = f.call(&mut store, Some(h))?;
1918
let g = g.unwrap().typed::<(), u32>(&mut store)?;
1919
let x = g.call(&mut store, ())?;
1920
assert_eq!(x, 0x1234_5678);
1921
1922
Ok(())
1923
}
1924
1925
#[wasmtime_test(wasm_features(gc, function_references))]
1926
#[cfg_attr(miri, ignore)]
1927
fn call_wasm_getting_subtype_func_return(config: &mut Config) -> anyhow::Result<()> {
1928
let engine = Engine::new(&config)?;
1929
let mut store = Store::new(&engine, ());
1930
1931
let module = Module::new(
1932
&engine,
1933
r#"
1934
(module
1935
(type $ty (func (result funcref)))
1936
1937
(func $a (result i32)
1938
i32.const 0x12345678
1939
)
1940
1941
(func $b (result funcref)
1942
ref.func $a
1943
)
1944
1945
(elem declare func $a $b)
1946
1947
;; Returns a `(ref null nofunc)` if called with `0`, otherwise
1948
;; returns `(ref null $ty)`, both of which are subtypes of
1949
;; `funcref`.
1950
(func (export "f") (param i32) (result funcref)
1951
block
1952
local.get 0
1953
br_if 0
1954
ref.null nofunc
1955
return
1956
end
1957
ref.func $b
1958
)
1959
)
1960
"#,
1961
)?;
1962
1963
let instance = Instance::new(&mut store, &module, &[])?;
1964
let f = instance.get_func(&mut store, "f").unwrap();
1965
1966
// Array call, receiving a subtype of the expected result.
1967
1968
let mut results = vec![Val::I32(0)];
1969
f.call(&mut store, &[Val::I32(0)], &mut results)?;
1970
assert!(results[0].unwrap_func_ref().is_none());
1971
1972
f.call(&mut store, &[Val::I32(1)], &mut results)?;
1973
let b = results[0];
1974
let b = b.unwrap_func_ref().unwrap();
1975
b.call(&mut store, &[], &mut results)?;
1976
let a = results[0];
1977
let a = a.unwrap_func_ref().unwrap();
1978
a.call(&mut store, &[], &mut results)?;
1979
assert_eq!(results[0].unwrap_i32(), 0x1234_5678);
1980
1981
// Native call, receiving a subtype of the expected result.
1982
1983
let f = f.typed::<u32, Option<Func>>(&store)?;
1984
let r = f.call(&mut store, 0)?;
1985
assert!(r.is_none());
1986
1987
let b = f.call(&mut store, 1)?;
1988
let b = b.unwrap().typed::<(), Option<Func>>(&store)?;
1989
let a = b.call(&mut store, ())?;
1990
let a = a.unwrap().typed::<(), u32>(&store)?;
1991
let x = a.call(&mut store, ())?;
1992
assert_eq!(x, 0x1234_5678);
1993
1994
Ok(())
1995
}
1996
1997
#[wasmtime_test(wasm_features(simd), strategies(not(Winch)))]
1998
#[cfg_attr(miri, ignore)]
1999
fn typed_v128(config: &mut Config) -> anyhow::Result<()> {
2000
let engine = Engine::new(&config)?;
2001
let mut store = Store::<()>::new(&engine, ());
2002
let module = Module::new(
2003
store.engine(),
2004
r#"
2005
(module
2006
(func (export "a") (param v128) (result v128)
2007
local.get 0)
2008
(func (export "b") (param v128 v128) (result v128 v128)
2009
local.get 0
2010
local.get 1)
2011
(func (export "c") (param v128 v128 v128 v128 v128 v128 v128 v128) (result v128)
2012
local.get 0
2013
local.get 1
2014
local.get 2
2015
local.get 3
2016
local.get 4
2017
local.get 5
2018
local.get 6
2019
local.get 7
2020
i64x2.add
2021
i64x2.add
2022
i64x2.add
2023
i64x2.add
2024
i64x2.add
2025
i64x2.add
2026
i64x2.add)
2027
)
2028
2029
"#,
2030
)?;
2031
let instance = Instance::new(&mut store, &module, &[])?;
2032
2033
let a = instance.get_typed_func::<V128, V128>(&mut store, "a")?;
2034
assert_eq!(a.call(&mut store, V128::from(1))?, V128::from(1));
2035
assert_eq!(a.call(&mut store, V128::from(2))?, V128::from(2));
2036
2037
let b = instance.get_typed_func::<(V128, V128), (V128, V128)>(&mut store, "b")?;
2038
assert_eq!(
2039
b.call(&mut store, (V128::from(1), V128::from(2)))?,
2040
(V128::from(1), V128::from(2))
2041
);
2042
2043
let c = instance.get_typed_func::<(V128, V128, V128, V128, V128, V128, V128, V128), V128>(
2044
&mut store, "c",
2045
)?;
2046
assert_eq!(
2047
c.call(
2048
&mut store,
2049
(
2050
V128::from(1),
2051
V128::from(2),
2052
V128::from(3),
2053
V128::from(4),
2054
V128::from(5),
2055
V128::from(6),
2056
V128::from(7),
2057
V128::from(8),
2058
)
2059
)?,
2060
V128::from(1 + 2 + 3 + 4 + 5 + 6 + 7 + 8),
2061
);
2062
2063
Ok(())
2064
}
2065
2066
#[wasmtime_test(wasm_features(simd))]
2067
#[cfg_attr(miri, ignore)]
2068
fn typed_v128_imports(config: &mut Config) -> anyhow::Result<()> {
2069
let engine = Engine::new(&config)?;
2070
let mut store = Store::<()>::new(&engine, ());
2071
let module = Module::new(
2072
store.engine(),
2073
r#"
2074
(module
2075
(import "" "a" (func $a (param v128) (result i32)))
2076
(import "" "b" (func $b (param i32) (result v128)))
2077
(import "" "c" (func $c (param v128 f64 v128) (result v128 i32 v128)))
2078
(import "" "d" (func $d (param v128 v128 v128 v128 v128 v128 v128 v128) (result i32)))
2079
2080
(func (export "a") (param v128) (result i32)
2081
local.get 0
2082
call $a)
2083
2084
(func (export "b") (param i32) (result v128)
2085
local.get 0
2086
call $b)
2087
2088
(func (export "c") (param v128 f64 v128) (result v128 i32 v128)
2089
local.get 0
2090
local.get 1
2091
local.get 2
2092
call $c)
2093
2094
(func (export "d") (param v128 v128 v128 v128 v128 v128 v128 v128) (result i32)
2095
local.get 0
2096
local.get 1
2097
local.get 2
2098
local.get 3
2099
local.get 4
2100
local.get 5
2101
local.get 6
2102
local.get 7
2103
call $d)
2104
)
2105
2106
"#,
2107
)?;
2108
2109
let mut l = Linker::new(store.engine());
2110
l.func_wrap("", "a", |x: V128| {
2111
let x = x.as_u128();
2112
(x >> 0) as u32 + (x >> 32) as u32 + (x >> 64) as u32 + (x >> 96) as u32
2113
})?;
2114
l.func_wrap("", "b", |x: u32| {
2115
let x = u128::from(x);
2116
V128::from(x | ((x + 1) << 32) | ((x + 2) << 64) | ((x + 3) << 96))
2117
})?;
2118
l.func_wrap("", "c", |x: V128, y: f64, z: V128| (x, y as i32, z))?;
2119
l.func_wrap(
2120
"",
2121
"d",
2122
|a0: V128, a1: V128, a2: V128, a3: V128, a4: V128, a5: V128, a6: V128, a7: V128| {
2123
let tmp = a0.as_u128()
2124
+ a1.as_u128()
2125
+ a2.as_u128()
2126
+ a3.as_u128()
2127
+ a4.as_u128()
2128
+ a5.as_u128()
2129
+ a6.as_u128()
2130
+ a7.as_u128();
2131
(tmp >> 0) as u32 + (tmp >> 32) as u32 + (tmp >> 64) as u32 + (tmp >> 96) as u32
2132
},
2133
)?;
2134
2135
let i = l.instantiate(&mut store, &module)?;
2136
let a = i.get_typed_func::<V128, i32>(&mut store, "a")?;
2137
let b = i.get_typed_func::<i32, V128>(&mut store, "b")?;
2138
let c = i.get_typed_func::<(V128, f64, V128), (V128, i32, V128)>(&mut store, "c")?;
2139
let d =
2140
i.get_typed_func::<(V128, V128, V128, V128, V128, V128, V128, V128), i32>(&mut store, "d")?;
2141
2142
assert_eq!(
2143
a.call(&mut store, 0x00000004_00000003_00000002_00000001.into())?,
2144
1 + 2 + 3 + 4
2145
);
2146
assert_eq!(
2147
b.call(&mut store, 0x10)?,
2148
V128::from(0x00000013_00000012_00000011_00000010),
2149
);
2150
assert_eq!(
2151
c.call(&mut store, (1.into(), 2., 3.into()))?,
2152
(V128::from(1), 2, V128::from(3)),
2153
);
2154
assert_eq!(
2155
d.call(
2156
&mut store,
2157
(
2158
1.into(),
2159
2.into(),
2160
3.into(),
2161
4.into(),
2162
5.into(),
2163
6.into(),
2164
7.into(),
2165
8.into(),
2166
)
2167
)?,
2168
1 + 2 + 3 + 4 + 5 + 6 + 7 + 8
2169
);
2170
2171
Ok(())
2172
}
2173
2174
#[wasmtime_test(wasm_features(function_references, gc))]
2175
#[cfg_attr(miri, ignore)]
2176
fn wrap_and_typed_i31ref(config: &mut Config) -> Result<()> {
2177
let engine = Engine::new(&config)?;
2178
let mut store = Store::<AtomicUsize>::new(&engine, AtomicUsize::new(0));
2179
2180
let mut linker = Linker::new(&engine);
2181
linker.func_wrap(
2182
"env",
2183
"i31ref",
2184
|caller: Caller<'_, AtomicUsize>, x: Option<I31>| -> Option<I31> {
2185
assert_eq!(caller.data().fetch_add(1, Ordering::SeqCst), 0);
2186
x
2187
},
2188
)?;
2189
linker.func_wrap(
2190
"env",
2191
"ref-i31",
2192
|caller: Caller<'_, AtomicUsize>, x: I31| -> I31 {
2193
assert_eq!(caller.data().fetch_add(1, Ordering::SeqCst), 1);
2194
x
2195
},
2196
)?;
2197
2198
let module = Module::new(
2199
&engine,
2200
r#"
2201
(module
2202
(import "env" "i31ref" (func (param i31ref) (result i31ref)))
2203
(import "env" "ref-i31" (func (param (ref i31)) (result (ref i31))))
2204
2205
(func (export "i31ref") (param i31ref) (result i31ref)
2206
local.get 0
2207
call 0
2208
)
2209
2210
(func (export "ref-i31") (param (ref i31)) (result (ref i31))
2211
local.get 0
2212
call 1
2213
)
2214
)
2215
"#,
2216
)?;
2217
2218
let instance = linker.instantiate(&mut store, &module)?;
2219
2220
let i31ref = instance.get_typed_func::<Option<I31>, Option<I31>>(&mut store, "i31ref")?;
2221
let x = i31ref.call(&mut store, Some(I31::wrapping_u32(42)))?;
2222
assert_eq!(x, Some(I31::wrapping_u32(42)));
2223
2224
let ref_i31 = instance.get_typed_func::<I31, I31>(&mut store, "ref-i31")?;
2225
let x = ref_i31.call(&mut store, I31::wrapping_u32(0x1234))?;
2226
assert_eq!(x, I31::wrapping_u32(0x1234));
2227
2228
assert_eq!(store.data().load(Ordering::SeqCst), 2);
2229
Ok(())
2230
}
2231
2232
#[wasmtime_test(wasm_features(function_references, gc))]
2233
fn call_func_with_funcref_both_typed_and_untyped(config: &mut Config) -> Result<()> {
2234
let engine = Engine::new(&config)?;
2235
let mut store = Store::new(&engine, ());
2236
2237
let f1 = Func::wrap(&mut store, |_: Option<Func>| {});
2238
let f2 = Func::wrap(&mut store, || {});
2239
2240
f1.typed::<Func, ()>(&mut store)?.call(&mut store, f2)?;
2241
f1.call(&mut store, &[Val::FuncRef(Some(f2))], &mut [])?;
2242
Ok(())
2243
}
2244
2245
#[wasmtime_test(wasm_features(function_references, gc))]
2246
#[cfg_attr(miri, ignore)]
2247
fn wasm_to_host_trampolines_and_subtyping(config: &mut Config) -> Result<()> {
2248
let _ = env_logger::try_init();
2249
2250
let engine = Engine::new(&config)?;
2251
2252
let ft0 = FuncType::with_finality_and_supertype(
2253
&engine,
2254
Finality::NonFinal,
2255
None,
2256
[],
2257
[ValType::Ref(RefType::new(true, HeapType::Extern))],
2258
)?;
2259
let ft1 = FuncType::with_finality_and_supertype(
2260
&engine,
2261
Finality::NonFinal,
2262
Some(&ft0),
2263
[],
2264
[ValType::Ref(RefType::new(false, HeapType::Extern))],
2265
)?;
2266
2267
let module = Module::new(
2268
&engine,
2269
r#"
2270
(module
2271
(type $ft0 (sub (func (result (ref null extern)))))
2272
2273
(import "" "a" (func $imported_func (type $ft0)))
2274
(import "" "return_func" (func $return_func (result (ref $ft0))))
2275
(global $g (export "g") (mut (ref null $ft0)) (ref.null $ft0))
2276
(table $t (export "t") 10 10 (ref null $ft0))
2277
2278
(func (export "f")
2279
(drop (call $imported_func))
2280
(drop (call_ref $ft0 (call $return_func)))
2281
(drop (call_ref $ft0 (global.get $g)))
2282
(drop (call_ref $ft0 (table.get $t (i32.const 0))))
2283
)
2284
)
2285
"#,
2286
)?;
2287
2288
// This defines a function of type `(func (result (ref extern)))` and not of
2289
// type `(func (result (ref null extern)))` that the Wasm imports. But it is
2290
// still a subtype of the Wasm import's type, so we should be able to use
2291
// the Wasm's precompiled trampolines with this host function.
2292
//
2293
// But this means we also need to look up the trampoline by the caller's
2294
// type, rather than the callee's type.
2295
//
2296
// So give it to Wasm in every way that Wasm can receive a function, and
2297
// make sure we find the correct trampolines in all cases and everything
2298
// works.
2299
let make_func = |store: &mut Store<_>| {
2300
Func::new(
2301
store,
2302
ft1.clone(),
2303
|mut caller: Caller<'_, ()>, _args, results| {
2304
results[0] = ExternRef::new(&mut caller, 200)?.into();
2305
Ok(())
2306
},
2307
)
2308
};
2309
2310
let return_func_ty = module.imports().nth(1).unwrap().ty().unwrap_func().clone();
2311
2312
let mut store = Store::new(&engine, ());
2313
2314
let imported_func = make_func(&mut store);
2315
assert!(FuncType::eq(&imported_func.ty(&store), &ft1));
2316
2317
let returned_func = make_func(&mut store);
2318
assert!(FuncType::eq(&returned_func.ty(&store), &ft1));
2319
2320
let return_func = Func::new(
2321
&mut store,
2322
return_func_ty.clone(),
2323
move |_caller, _args, results| {
2324
results[0] = returned_func.into();
2325
Ok(())
2326
},
2327
);
2328
2329
let instance = Instance::new(
2330
&mut store,
2331
&module,
2332
&[imported_func.into(), return_func.into()],
2333
)?;
2334
2335
let g = make_func(&mut store);
2336
assert!(FuncType::eq(&g.ty(&store), &ft1));
2337
instance
2338
.get_global(&mut store, "g")
2339
.unwrap()
2340
.set(&mut store, g.into())?;
2341
2342
let t = make_func(&mut store);
2343
assert!(FuncType::eq(&t.ty(&store), &ft1));
2344
instance
2345
.get_table(&mut store, "t")
2346
.unwrap()
2347
.set(&mut store, 0, t.into())?;
2348
2349
let f = instance.get_typed_func::<(), ()>(&mut store, "f")?;
2350
f.call(&mut store, ())?;
2351
2352
Ok(())
2353
}
2354
2355