Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/crates/wizer/tests/all/tests.rs
3073 views
1
use std::process::Command;
2
use wasm_encoder::ConstExpr;
3
use wasmtime::{
4
Config, Engine, Instance, Linker, Module, Result, Store, ToWasmtimeResult as _,
5
error::Context as _,
6
};
7
use wasmtime_wasi::{WasiCtxBuilder, p1};
8
use wasmtime_wizer::Wizer;
9
use wat::parse_str as wat_to_wasm;
10
11
async fn run_wat(args: &[wasmtime::Val], expected: i32, wat: &str) -> Result<()> {
12
let _ = env_logger::try_init();
13
let wasm = wat_to_wasm(wat)?;
14
wizen_and_run_wasm(args, expected, &wasm, get_wizer()).await
15
}
16
17
fn get_wizer() -> Wizer {
18
Wizer::new()
19
}
20
21
fn store() -> Result<Store<p1::WasiP1Ctx>> {
22
let mut wasi = WasiCtxBuilder::new();
23
let mut config = Config::new();
24
config.relaxed_simd_deterministic(true);
25
let engine = Engine::new(&config)?;
26
Ok(Store::new(&engine, wasi.build_p1()))
27
}
28
29
async fn instantiate(store: &mut Store<p1::WasiP1Ctx>, module: &Module) -> Result<Instance> {
30
let mut linker = Linker::new(store.engine());
31
p1::add_to_linker_async(&mut linker, |x| x)?;
32
linker.define_unknown_imports_as_traps(module)?;
33
linker.instantiate_async(store, module).await
34
}
35
36
async fn wizen_and_run_wasm(
37
args: &[wasmtime::Val],
38
expected: i32,
39
wasm: &[u8],
40
wizer: Wizer,
41
) -> Result<()> {
42
let _ = env_logger::try_init();
43
44
log::debug!(
45
"=== PreWizened Wasm ==========================================================\n\
46
{}\n\
47
===========================================================================",
48
wasmprinter::print_bytes(&wasm).unwrap()
49
);
50
let mut store = store()?;
51
let wasm = wizer.run(&mut store, &wasm, instantiate).await?;
52
log::debug!(
53
"=== Wizened Wasm ==========================================================\n\
54
{}\n\
55
===========================================================================",
56
wasmprinter::print_bytes(&wasm).unwrap()
57
);
58
if log::log_enabled!(log::Level::Debug) {
59
std::fs::write("test.wasm", &wasm).unwrap();
60
}
61
62
let module =
63
wasmtime::Module::new(store.engine(), wasm).context("Wasm test case failed to compile")?;
64
65
let mut linker = wasmtime::Linker::new(store.engine());
66
let thunk = wasmtime::Func::wrap(&mut store, || {});
67
linker
68
.define_name(&mut store, "dummy_func", thunk)?
69
.define(&mut store, "env", "f", thunk)?
70
.define_name(&mut store, "f", thunk)?
71
.define(&mut store, "x", "f", thunk)?;
72
73
p1::add_to_linker_async(&mut linker, |wasi| wasi)?;
74
75
let instance = linker.instantiate_async(&mut store, &module).await?;
76
77
let run = instance.get_func(&mut store, "run").ok_or_else(|| {
78
wasmtime::format_err!("the test Wasm module does not export a `run` function")
79
})?;
80
81
let mut actual = vec![wasmtime::Val::I32(0)];
82
run.call_async(&mut store, args, &mut actual).await?;
83
wasmtime::ensure!(actual.len() == 1, "expected one result");
84
let actual = match actual[0] {
85
wasmtime::Val::I32(x) => x,
86
_ => wasmtime::bail!("expected an i32 result"),
87
};
88
wasmtime::ensure!(
89
expected == actual,
90
"expected `{expected}`, found `{actual}`",
91
);
92
93
Ok(())
94
}
95
96
async fn fails_wizening(wat: &str) -> Result<()> {
97
let _ = env_logger::try_init();
98
99
let wasm = wat_to_wasm(wat)?;
100
101
let mut features = wasmparser::WasmFeatures::WASM2;
102
features.set(wasmparser::WasmFeatures::MULTI_MEMORY, true);
103
104
let mut validator = wasmparser::Validator::new_with_features(features);
105
validator
106
.validate_all(&wasm)
107
.context("initial Wasm should be valid")?;
108
109
wasmtime::ensure!(
110
get_wizer()
111
.run(&mut store()?, &wasm, instantiate)
112
.await
113
.is_err(),
114
"Expected an error when wizening, but didn't get one"
115
);
116
Ok(())
117
}
118
119
#[tokio::test]
120
async fn basic_global() -> Result<()> {
121
run_wat(
122
&[],
123
42,
124
r#"
125
(module
126
(global $g (mut i32) i32.const 0)
127
(func (export "wizer-initialize")
128
i32.const 42
129
global.set $g)
130
(func (export "run") (result i32)
131
global.get $g))
132
"#,
133
)
134
.await
135
}
136
137
#[tokio::test]
138
async fn basic_memory() -> Result<()> {
139
run_wat(
140
&[],
141
42,
142
r#"
143
(module
144
(memory 1)
145
(func (export "wizer-initialize")
146
i32.const 0
147
i32.const 42
148
i32.store offset=1337)
149
(func (export "run") (result i32)
150
i32.const 0
151
i32.load offset=1337))
152
"#,
153
)
154
.await
155
}
156
157
#[tokio::test]
158
async fn multi_memory() -> Result<()> {
159
run_wat(
160
&[],
161
42,
162
r#"
163
(module
164
(memory $m1 1)
165
(memory $m2 1)
166
(func (export "wizer-initialize")
167
i32.const 0
168
i32.const 41
169
i32.store $m1 offset=1337
170
i32.const 0
171
i32.const 1
172
i32.store $m2 offset=1337)
173
(func (export "run") (result i32)
174
i32.const 0
175
i32.load $m1 offset=1337
176
i32.const 0
177
i32.load $m2 offset=1337
178
i32.add))
179
"#,
180
)
181
.await
182
}
183
#[tokio::test]
184
async fn reject_imported_memory() -> Result<()> {
185
fails_wizening(
186
r#"
187
(module
188
(import "" "" (memory 1)))
189
"#,
190
)
191
.await
192
}
193
194
#[tokio::test]
195
async fn reject_imported_global() -> Result<()> {
196
fails_wizening(
197
r#"
198
(module
199
(import "" "" (global i32)))
200
"#,
201
)
202
.await
203
}
204
205
#[tokio::test]
206
async fn reject_imported_table() -> Result<()> {
207
fails_wizening(
208
r#"
209
(module
210
(import "" "" (table 0 externref)))
211
"#,
212
)
213
.await
214
}
215
216
#[tokio::test]
217
async fn reject_table_copy() -> Result<()> {
218
let result = run_wat(
219
&[],
220
42,
221
r#"
222
(module
223
(table 3 funcref)
224
225
(func $f (result i32) (i32.const 0))
226
(func $g (result i32) (i32.const 0))
227
(func $h (result i32) (i32.const 0))
228
229
(func (export "main")
230
i32.const 0
231
i32.const 1
232
i32.const 1
233
table.copy)
234
235
(elem (i32.const 0) $f $g $h)
236
)
237
"#,
238
)
239
.await;
240
assert!(result.is_err());
241
242
let err = result.unwrap_err();
243
assert!(
244
err.to_string()
245
.contains("unsupported `table.copy` instruction")
246
);
247
248
Ok(())
249
}
250
251
#[tokio::test]
252
async fn reject_table_get_set() -> Result<()> {
253
let wat = r#"
254
(module
255
(table 3 funcref)
256
257
(func $f (result i32) (i32.const 0))
258
(func $g (result i32) (i32.const 0))
259
(func $h (result i32) (i32.const 0))
260
261
(func (export "main")
262
i32.const 0
263
i32.const 1
264
table.get
265
table.set)
266
267
(elem (i32.const 0) $f $g $h)
268
)
269
"#;
270
271
let _ = env_logger::try_init();
272
let wizer = Wizer::new();
273
let wasm = wat_to_wasm(wat)?;
274
let result = wizen_and_run_wasm(&[], 42, &wasm, wizer).await;
275
276
assert!(result.is_err());
277
278
let err = result.unwrap_err();
279
assert!(
280
err.to_string()
281
.contains("unsupported `table.set` instruction"),
282
"bad error: {err}",
283
);
284
285
Ok(())
286
}
287
288
#[tokio::test]
289
async fn reject_table_get_set_with_reference_types_enabled() -> Result<()> {
290
let result = run_wat(
291
&[],
292
42,
293
r#"
294
(module
295
(table 3 funcref)
296
297
(func $f (result i32) (i32.const 0))
298
(func $g (result i32) (i32.const 0))
299
(func $h (result i32) (i32.const 0))
300
301
(func (export "main")
302
i32.const 0
303
i32.const 1
304
table.get
305
table.set)
306
307
(elem (i32.const 0) $f $g $h)
308
)"#,
309
)
310
.await;
311
assert!(result.is_err());
312
313
let err = result.unwrap_err();
314
assert!(
315
err.to_string()
316
.contains("unsupported `table.set` instruction"),
317
);
318
319
Ok(())
320
}
321
322
#[tokio::test]
323
async fn reject_table_grow_with_reference_types_enabled() -> wasmtime::Result<()> {
324
let wat = r#"
325
(module
326
(elem declare func $f)
327
(func $f)
328
(table 0 funcref)
329
(func (export "_initialize") (result i32)
330
ref.func $f
331
i32.const 1
332
table.grow
333
)
334
)"#;
335
336
let _ = env_logger::try_init();
337
let wizer = Wizer::new();
338
let wasm = wat_to_wasm(wat)?;
339
let result = wizen_and_run_wasm(&[], 42, &wasm, wizer).await;
340
341
assert!(result.is_err());
342
343
let err = result.unwrap_err();
344
assert!(
345
err.to_string()
346
.contains("unsupported `table.grow` instruction")
347
);
348
349
Ok(())
350
}
351
352
#[tokio::test]
353
async fn indirect_call_with_reference_types() -> wasmtime::Result<()> {
354
let wat = r#"
355
(module
356
(type $sig (func (result i32)))
357
(table 0 funcref)
358
(table $table1 1 funcref)
359
(elem (table $table1) (i32.const 0) func $f)
360
(func $f (type $sig)
361
i32.const 42
362
)
363
(func (export "wizer-initialize"))
364
(func (export "run") (result i32)
365
i32.const 0
366
call_indirect $table1 (type $sig)
367
)
368
)"#;
369
370
let _ = env_logger::try_init();
371
let wizer = Wizer::new();
372
let wasm = wat_to_wasm(wat)?;
373
wizen_and_run_wasm(&[], 42, &wasm, wizer).await
374
}
375
376
#[tokio::test]
377
async fn reject_table_init() -> Result<()> {
378
let result = run_wat(
379
&[],
380
42,
381
r#"
382
(module
383
(table 3 funcref)
384
385
(func $f (result i32) (i32.const 0))
386
(func $g (result i32) (i32.const 0))
387
(func $h (result i32) (i32.const 0))
388
389
(elem $elem func $f $g $h)
390
391
(func (export "main")
392
i32.const 0
393
i32.const 0
394
i32.const 3
395
table.init $elem)
396
)
397
"#,
398
)
399
.await;
400
assert!(result.is_err());
401
402
let err = result.unwrap_err();
403
assert!(
404
err.to_string()
405
.contains("unsupported `table.init` instruction")
406
);
407
408
Ok(())
409
}
410
411
#[tokio::test]
412
async fn reject_elem_drop() -> Result<()> {
413
let result = run_wat(
414
&[],
415
42,
416
r#"
417
(module
418
(table 3 funcref)
419
420
(func $f (result i32) (i32.const 0))
421
(func $g (result i32) (i32.const 0))
422
(func $h (result i32) (i32.const 0))
423
424
(elem $elem func $f $g $h)
425
426
(func (export "main")
427
elem.drop $elem)
428
)
429
"#,
430
)
431
.await;
432
assert!(result.is_err());
433
434
let err = result.unwrap_err();
435
assert!(
436
err.to_string()
437
.contains("unsupported `elem.drop` instruction")
438
);
439
440
Ok(())
441
}
442
443
#[tokio::test]
444
async fn reject_data_drop() -> Result<()> {
445
let result = run_wat(
446
&[],
447
42,
448
r#"
449
(module
450
(memory 1)
451
(data $data "hello, wizer!")
452
453
(func (export "main")
454
data.drop $data)
455
)
456
"#,
457
)
458
.await;
459
assert!(result.is_err());
460
461
let err = result.unwrap_err();
462
assert!(
463
err.to_string()
464
.contains("unsupported `data.drop` instruction")
465
);
466
467
Ok(())
468
}
469
470
#[tokio::test]
471
async fn rust_regex() -> Result<()> {
472
let status = Command::new("cargo")
473
.args(&["build", "--target=wasm32-wasip1", "-q"])
474
.current_dir("./tests/regex-test")
475
.env_remove("CARGO_ENCODED_RUSTFLAGS")
476
.env_remove("RUSTFLAGS")
477
.status()
478
.expect("failed to build regex test case");
479
assert!(status.success());
480
wizen_and_run_wasm(
481
&[wasmtime::Val::I32(13)],
482
42,
483
&std::fs::read("../../target/wasm32-wasip1/debug/regex_test.wasm")
484
.expect("failed to read regex test case"),
485
get_wizer(),
486
)
487
.await
488
}
489
490
#[tokio::test]
491
async fn data_segment_at_end_of_memory() -> Result<()> {
492
// Test that we properly synthesize data segments for data at the end of
493
// memory.
494
run_wat(
495
&[],
496
42,
497
r#"
498
(module
499
(memory 1)
500
(func (export "wizer-initialize")
501
;; Store 42 to the last byte in memory.
502
i32.const 0
503
i32.const 42
504
i32.store8 offset=65535
505
)
506
(func (export "run") (result i32)
507
i32.const 0
508
i32.load8_u offset=65535
509
)
510
)
511
"#,
512
)
513
.await
514
}
515
516
#[tokio::test]
517
async fn too_many_data_segments_for_engines() -> Result<()> {
518
run_wat(
519
&[],
520
42,
521
r#"
522
(module
523
;; Enough memory to create more segments than engines will allow:
524
;;
525
;; // The maximum number of segments that engines will allow a module to
526
;; // have.
527
;; let max_segments = 100_000;
528
;;
529
;; // The minimum gap that Wizer won't automatically merge two data
530
;; // segments (see `MIN_ACTIVE_SEGMENT_OVERHEAD`).
531
;; let wizer_min_gap = 6;
532
;;
533
;; // Wasm page size.
534
;; let wasm_page_size = 65_536;
535
;;
536
;; let num_pages = round_up(max_segments * wizer_min_gap / wasm_page_size);
537
(memory 10)
538
539
(func (export "wizer-initialize")
540
(local i32)
541
loop
542
(i32.ge_u (local.get 0) (i32.const 655360)) ;; 10 * wasm_page_size
543
if
544
return
545
end
546
547
(i32.store8 (local.get 0) (i32.const 42))
548
(local.set 0 (i32.add (local.get 0) (i32.const 6)))
549
br 0
550
end
551
)
552
(func (export "run") (result i32)
553
i32.const 0
554
i32.load8_u
555
)
556
)
557
"#,
558
)
559
.await
560
}
561
562
#[tokio::test]
563
async fn rename_functions() -> Result<()> {
564
let wat = r#"
565
(module
566
(func (export "wizer-initialize"))
567
(func (export "func_a") (result i32)
568
i32.const 1)
569
(func (export "func_b") (result i32)
570
i32.const 2)
571
(func (export "func_c") (result i32)
572
i32.const 3))
573
"#;
574
575
let wasm = wat_to_wasm(wat)?;
576
let mut wizer = Wizer::new();
577
wizer.func_rename("func_a", "func_b");
578
wizer.func_rename("func_b", "func_c");
579
let wasm = wizer.run(&mut store()?, &wasm, instantiate).await?;
580
let wat = wasmprinter::print_bytes(&wasm).to_wasmtime_result()?;
581
582
let expected_wat = r#"
583
(module
584
(type (;0;) (func))
585
(type (;1;) (func (result i32)))
586
(export "func_a" (func 2))
587
(export "func_b" (func 3))
588
(func (;0;) (type 0))
589
(func (;1;) (type 1) (result i32)
590
i32.const 1
591
)
592
(func (;2;) (type 1) (result i32)
593
i32.const 2
594
)
595
(func (;3;) (type 1) (result i32)
596
i32.const 3
597
)
598
)
599
"#;
600
601
assert_eq!(wat.trim(), expected_wat.trim());
602
Ok(())
603
}
604
605
#[tokio::test]
606
async fn wasi_reactor() -> wasmtime::Result<()> {
607
run_wat(
608
&[],
609
42,
610
r#"
611
(module
612
(global $g (mut i32) i32.const 0)
613
(func (export "_initialize")
614
i32.const 6
615
global.set $g
616
)
617
(func (export "wizer-initialize")
618
global.get $g
619
i32.const 7
620
i32.mul
621
global.set $g)
622
(func (export "run") (result i32)
623
global.get $g
624
)
625
)
626
"#,
627
)
628
.await
629
}
630
631
#[tokio::test]
632
async fn wasi_reactor_initializer_as_init_func() -> wasmtime::Result<()> {
633
let wat = r#"
634
(module
635
(global $g (mut i32) i32.const 0)
636
(func (export "_initialize")
637
global.get $g
638
i32.const 1
639
i32.add
640
global.set $g
641
)
642
(func (export "run") (result i32)
643
global.get $g
644
)
645
)"#;
646
647
let _ = env_logger::try_init();
648
let mut wizer = Wizer::new();
649
wizer.init_func("_initialize");
650
let wasm = wat_to_wasm(wat)?;
651
// we expect `_initialize` to be called _exactly_ once
652
wizen_and_run_wasm(&[], 1, &wasm, wizer).await
653
}
654
655
#[tokio::test]
656
async fn wasi_reactor_initializer_with_keep_init() -> wasmtime::Result<()> {
657
let wat = r#"
658
(module
659
(global $g (mut i32) i32.const 0)
660
(func (export "_initialize")
661
i32.const 1
662
global.set $g
663
)
664
(func (export "wizer-initialize")
665
i32.const 2
666
global.set $g)
667
(func (export "run") (result i32)
668
global.get $g
669
)
670
)"#;
671
672
let _ = env_logger::try_init();
673
let mut wizer = Wizer::new();
674
wizer.keep_init_func(true);
675
let wasm = wat_to_wasm(wat)?;
676
// we expect `_initialize` to be un-exported and not called at run
677
wizen_and_run_wasm(&[], 2, &wasm, wizer).await
678
}
679
680
#[tokio::test]
681
async fn call_undefined_import_function_during_init() -> Result<()> {
682
fails_wizening(
683
r#"
684
(module
685
(import "x" "f" (func $import))
686
(func (export "wizer-initialize")
687
(call $import)
688
)
689
)
690
"#,
691
)
692
.await
693
}
694
695
#[tokio::test]
696
async fn allow_undefined_import_function() -> Result<()> {
697
run_wat(
698
&[],
699
42,
700
r#"
701
(module
702
(import "x" "f" (func $import))
703
(func (export "wizer-initialize"))
704
(func (export "run") (result i32)
705
i32.const 42
706
)
707
)
708
"#,
709
)
710
.await
711
}
712
713
#[tokio::test]
714
async fn accept_bulk_memory_copy() -> Result<()> {
715
run_wat(
716
&[],
717
('h' as i32) + ('w' as i32),
718
r#"
719
(module
720
(memory $memory (data "hello, wizer!"))
721
(func (export "wizer-initialize")
722
i32.const 42 ;; dst
723
i32.const 0 ;; src
724
i32.const 13 ;; size
725
memory.copy)
726
(func (export "run") (result i32)
727
i32.const 42
728
i32.load8_u
729
i32.const 42
730
i32.load8_u offset=7
731
i32.add))
732
"#,
733
)
734
.await
735
}
736
737
#[tokio::test]
738
async fn accept_bulk_memory_data_count() -> Result<()> {
739
let mut module = wasm_encoder::Module::new();
740
let mut types = wasm_encoder::TypeSection::new();
741
types.ty().func_type(&wasm_encoder::FuncType::new(
742
vec![],
743
vec![wasm_encoder::ValType::I32],
744
));
745
types
746
.ty()
747
.func_type(&wasm_encoder::FuncType::new(vec![], vec![]));
748
module.section(&types);
749
750
let mut functions = wasm_encoder::FunctionSection::new();
751
functions.function(0);
752
functions.function(1);
753
module.section(&functions);
754
755
let mut memory = wasm_encoder::MemorySection::new();
756
memory.memory(wasm_encoder::MemoryType {
757
minimum: 1,
758
maximum: Some(1),
759
memory64: false,
760
shared: false,
761
page_size_log2: None,
762
});
763
module.section(&memory);
764
765
let mut exports = wasm_encoder::ExportSection::new();
766
exports.export("run", wasm_encoder::ExportKind::Func, 0);
767
exports.export("wizer-initialize", wasm_encoder::ExportKind::Func, 1);
768
module.section(&exports);
769
770
module.section(&wasm_encoder::DataCountSection { count: 2 });
771
772
let mut code = wasm_encoder::CodeSection::new();
773
let mut func = wasm_encoder::Function::new(vec![]);
774
func.instruction(&wasm_encoder::Instruction::I32Const(42));
775
func.instruction(&wasm_encoder::Instruction::End);
776
code.function(&func);
777
778
let mut func = wasm_encoder::Function::new(vec![]);
779
func.instruction(&wasm_encoder::Instruction::End);
780
code.function(&func);
781
782
module.section(&code);
783
784
// We're expecting these two data segments to be merge into one, which will exercise wizer's
785
// ability to output the correct data count (1 instead of 2 above).
786
let mut data = wasm_encoder::DataSection::new();
787
data.active(0, &ConstExpr::i32_const(0), vec![0, 1, 2, 3]);
788
data.active(0, &ConstExpr::i32_const(4), vec![5, 6, 7, 8]);
789
module.section(&data);
790
791
wizen_and_run_wasm(&[], 42, &module.finish(), get_wizer())
792
.await
793
.unwrap();
794
Ok(())
795
}
796
797
#[tokio::test]
798
async fn accept_bulk_memory_fill() -> Result<()> {
799
run_wat(
800
&[],
801
77 + 77,
802
r#"
803
(module
804
(memory 1)
805
(func (export "wizer-initialize")
806
i32.const 42 ;; dst
807
i32.const 77 ;; value
808
i32.const 13 ;; size
809
memory.fill)
810
(func (export "run") (result i32)
811
i32.const 42
812
i32.load8_u
813
i32.const 42
814
i32.load8_u offset=7
815
i32.add))
816
"#,
817
)
818
.await
819
}
820
821
#[tokio::test]
822
async fn accept_bulk_memory_init() -> Result<()> {
823
run_wat(
824
&[],
825
('h' as i32) + ('w' as i32),
826
r#"
827
(module
828
(memory 1)
829
(data $data "hello, wizer!")
830
(func (export "wizer-initialize")
831
i32.const 42 ;; dst
832
i32.const 0 ;; offset
833
i32.const 13 ;; size
834
memory.init $data)
835
(func (export "run") (result i32)
836
i32.const 42
837
i32.load8_u
838
i32.const 42
839
i32.load8_u offset=7
840
i32.add))
841
"#,
842
)
843
.await
844
}
845
846
#[tokio::test]
847
async fn accept_simd128() -> Result<()> {
848
run_wat(
849
&[],
850
49,
851
r#"
852
(module
853
(global $g (mut v128) (v128.const i32x4 2 3 5 7))
854
(func (export "wizer-initialize")
855
global.get $g
856
global.get $g
857
i32x4.mul
858
global.set $g)
859
(func (export "run") (result i32)
860
global.get $g
861
i32x4.extract_lane 3))
862
"#,
863
)
864
.await
865
}
866
867
#[tokio::test]
868
async fn relaxed_simd_deterministic() -> Result<()> {
869
let _ = env_logger::try_init();
870
let wasm = wat_to_wasm(
871
r#"
872
(module
873
(global $g (mut i32) i32.const 0)
874
(func (export "wizer-initialize")
875
(v128.const f32x4 2796203.5 0.0 0.0 0.0)
876
(v128.const f32x4 3.0 0.0 0.0 0.0)
877
(v128.const f32x4 8388611.0 0.0 0.0 0.0)
878
f32x4.relaxed_madd
879
f32x4.extract_lane 0
880
i32.reinterpret_f32
881
global.set $g)
882
(func (export "run") (result i32)
883
global.get $g
884
)
885
)
886
"#,
887
)?;
888
let wizer = get_wizer();
889
890
// We'll get 0x4b000003 if we have the deterministic `relaxed_madd`
891
// semantics. We might get 0x4b000002 if we don't.
892
wizen_and_run_wasm(&[], 0x4b800003, &wasm, wizer).await
893
}
894
895
#[tokio::test]
896
async fn reject_mutable_globals_of_reference_types() -> Result<()> {
897
// Non-mutable globals are fine
898
run_wat(
899
&[],
900
42,
901
r#"
902
(module
903
(global funcref (ref.null func))
904
(func (export "wizer-initialize"))
905
(func (export "run") (result i32) i32.const 42)
906
)
907
"#,
908
)
909
.await?;
910
911
// Mutable globals are not fine
912
fails_wizening(
913
r#"
914
(module
915
(global (mut funcref) (ref.null func))
916
(func (export "wizer-initialize"))
917
(func (export "run") (result i32) i32.const 42)
918
)
919
"#,
920
)
921
.await?;
922
Ok(())
923
}
924
925
#[tokio::test]
926
async fn mixture_of_globals() -> Result<()> {
927
let _ = env_logger::try_init();
928
let wasm = wat_to_wasm(
929
r#"
930
(module
931
(global $g1 (mut i32) i32.const 1)
932
(global $g2 i32 i32.const 2)
933
(global $g3 (mut i32) i32.const 3)
934
(global $g4 i32 i32.const 4)
935
(func (export "wizer-initialize")
936
(global.set $g1 (i32.const 42))
937
(global.set $g3 (i32.const 43))
938
)
939
(func (export "run") (result i32)
940
global.get $g1
941
global.get $g2
942
global.get $g3
943
global.get $g4
944
i32.add
945
i32.add
946
i32.add
947
)
948
)
949
"#,
950
)?;
951
let wizer = get_wizer();
952
wizen_and_run_wasm(&[], 42 + 2 + 43 + 4, &wasm, wizer).await
953
}
954
955
#[tokio::test]
956
async fn memory_init_and_data_segments() -> Result<()> {
957
let _ = env_logger::try_init();
958
let wasm = wat_to_wasm(
959
r#"
960
(module
961
(memory 1)
962
963
(func (export "wizer-initialize")
964
i32.const 2
965
i32.const 0
966
i32.const 2
967
memory.init $a
968
)
969
970
(func (export "run") (result i32)
971
i32.const 4
972
i32.const 0
973
i32.const 2
974
memory.init $a
975
i32.const 6
976
i32.const 0
977
i32.const 2
978
memory.init $c
979
980
i32.const 0
981
i32.load
982
i32.const 4
983
i32.load
984
i32.add
985
)
986
987
(data $a "\01\02")
988
(data $b (i32.const 0) "\03\04")
989
(data $c "\05\06")
990
)
991
"#,
992
)?;
993
let wizer = get_wizer();
994
wizen_and_run_wasm(&[], 0x02010403 + 0x06050201, &wasm, wizer).await
995
}
996
997
#[tokio::test]
998
async fn memory64() -> Result<()> {
999
let _ = env_logger::try_init();
1000
let wasm = wat_to_wasm(
1001
r#"
1002
(module
1003
(memory i64 1)
1004
1005
(func (export "wizer-initialize")
1006
i64.const 0
1007
i32.const 10
1008
i32.store
1009
)
1010
1011
(func (export "run") (result i32)
1012
i64.const 0
1013
i32.load
1014
)
1015
)
1016
"#,
1017
)?;
1018
let wizer = get_wizer();
1019
wizen_and_run_wasm(&[], 10, &wasm, wizer).await
1020
}
1021
1022