Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/tests/all/func.rs
3050 views
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)]
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) -> 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]
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) -> 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)]
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)]
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))]
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)]
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)]
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)]
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)]
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)]
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, gc_types))]
1429
#[cfg_attr(miri, ignore)]
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)]
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)]
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)]
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))]
1679
#[cfg_attr(miri, ignore)]
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))]
1752
#[cfg_attr(miri, ignore)]
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)]
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)]
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)]
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))]
1928
#[cfg_attr(miri, ignore)]
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)]
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)]
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)]
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))]
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)]
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
2357