Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/pulley/tests/all/interp.rs
1692 views
1
//! Interpreter tests.
2
3
use interp::Val;
4
use pulley_interpreter::{
5
interp::{DoneReason, Vm},
6
*,
7
};
8
use std::{cell::UnsafeCell, fmt::Debug, ptr::NonNull};
9
10
fn encoded(ops: &[Op]) -> Vec<u8> {
11
let mut encoded = vec![];
12
for op in ops {
13
op.encode(&mut encoded);
14
}
15
log::trace!("encoded: {encoded:?}");
16
encoded
17
}
18
19
unsafe fn run(vm: &mut Vm, ops: &[Op]) -> Result<(), NonNull<u8>> {
20
let _ = env_logger::try_init();
21
let ops = encoded(ops);
22
match unsafe { vm.call(NonNull::from(&ops[..]).cast(), &[], []) } {
23
DoneReason::ReturnToHost(_) => Ok(()),
24
DoneReason::Trap { pc, .. } => Err(pc),
25
DoneReason::CallIndirectHost { .. } => unimplemented!(),
26
}
27
}
28
29
unsafe fn assert_one<R0, R1, V>(
30
xs: impl IntoIterator<Item = (R0, V)>,
31
op: impl Into<Op> + Debug,
32
result: R1,
33
expected: u64,
34
) where
35
R0: Into<AnyReg>,
36
R1: Into<AnyReg>,
37
V: Into<Val>,
38
{
39
eprintln!("=======================================================");
40
let mut vm = Vm::new();
41
42
for (reg, val) in xs {
43
let reg = reg.into();
44
let val = val.into();
45
eprintln!("{reg} = {val:#018x}");
46
match (reg, val) {
47
(AnyReg::X(r), Val::XReg(v)) => vm.state_mut()[r] = v,
48
(AnyReg::F(r), Val::FReg(v)) => vm.state_mut()[r] = v,
49
(AnyReg::V(_), Val::VReg(_)) => todo!(),
50
(kind, val) => panic!("register kind and value mismatch: {kind:?} and {val:?}"),
51
}
52
}
53
54
eprintln!("op = {op:?}");
55
let op = op.into();
56
57
unsafe {
58
run(&mut vm, &[op, Op::Ret(Ret {})]).expect("should not trap");
59
}
60
61
eprintln!("expected = {expected:#018x}");
62
63
let actual = match result.into() {
64
AnyReg::X(r) => vm.state_mut()[r].get_u64(),
65
AnyReg::F(r) => vm.state_mut()[r].get_f64().to_bits(),
66
AnyReg::V(_) => todo!(),
67
};
68
eprintln!("actual = {actual:#018x}");
69
70
assert_eq!(expected, actual);
71
}
72
73
fn x(x: u8) -> XReg {
74
XReg::new(x).unwrap()
75
}
76
77
fn f(f: u8) -> FReg {
78
FReg::new(f).unwrap()
79
}
80
81
#[test]
82
fn xconst8() {
83
for (expected, imm) in [(42u64, 42i8), (u64::MAX, -1i8)] {
84
unsafe {
85
assert_one(
86
[(x(0), 0x1234567812345678u64)],
87
Xconst8 { dst: x(0), imm },
88
x(0),
89
expected,
90
);
91
}
92
}
93
}
94
95
#[test]
96
fn xconst16() {
97
for (expected, imm) in [(42u64, 42i16), (u64::MAX, -1i16)] {
98
unsafe {
99
assert_one(
100
[(x(0), 0x1234567812345678u64)],
101
Xconst16 { dst: x(0), imm },
102
x(0),
103
expected,
104
);
105
}
106
}
107
}
108
109
#[test]
110
fn xconst32() {
111
for (expected, imm) in [(42u64, 42i32), (u64::MAX, -1i32)] {
112
unsafe {
113
assert_one(
114
[(x(0), 0x1234567812345678u64)],
115
Xconst32 { dst: x(0), imm },
116
x(0),
117
expected,
118
);
119
}
120
}
121
}
122
123
#[test]
124
fn xconst64() {
125
for (expected, imm) in [(42u64, 42i64), (u64::MAX, -1i64)] {
126
unsafe {
127
assert_one(
128
[(x(0), 0x1234567812345678u64)],
129
Xconst64 { dst: x(0), imm },
130
x(0),
131
expected,
132
);
133
}
134
}
135
}
136
137
#[test]
138
fn xadd32() {
139
for (expected, a, b) in [
140
(42u64 | 0x1234567800000000, 10u64, 32u64),
141
(0x1234567800000000, u32::MAX as _, 1),
142
] {
143
unsafe {
144
assert_one(
145
[(x(0), 0x1234567812345678), (x(1), a), (x(2), b)],
146
Xadd32 {
147
operands: BinaryOperands {
148
dst: x(0),
149
src1: x(1),
150
src2: x(2),
151
},
152
},
153
x(0),
154
expected,
155
);
156
}
157
}
158
}
159
160
#[test]
161
fn xadd64() {
162
for (expected, a, b) in [(42u64, 10u64, 32u64), (0, u64::MAX, 1)] {
163
unsafe {
164
assert_one(
165
[(x(0), 0x1234567812345678), (x(1), a), (x(2), b)],
166
Xadd64 {
167
operands: BinaryOperands {
168
dst: x(0),
169
src1: x(1),
170
src2: x(2),
171
},
172
},
173
x(0),
174
expected,
175
);
176
}
177
}
178
}
179
180
#[test]
181
fn xeq64() {
182
for (expected, a, b) in [
183
(1u64, 0u64, 0u64),
184
(0, 0, 1),
185
(1, u64::MAX, u64::MAX),
186
(0, u64::MAX, u64::MAX - 1),
187
] {
188
unsafe {
189
assert_one(
190
[(x(0), 0x1234567812345678), (x(1), a), (x(2), b)],
191
Xeq64 {
192
operands: BinaryOperands {
193
dst: x(0),
194
src1: x(1),
195
src2: x(2),
196
},
197
},
198
x(0),
199
expected | 0x1234567800000000,
200
);
201
}
202
}
203
}
204
205
#[test]
206
fn xneq64() {
207
for (expected, a, b) in [
208
(0u64, 0u64, 0u64),
209
(1, 0, 1),
210
(0, u64::MAX, u64::MAX),
211
(1, u64::MAX, u64::MAX - 1),
212
] {
213
unsafe {
214
assert_one(
215
[(x(0), 0x1234567812345678), (x(1), a), (x(2), b)],
216
Xneq64 {
217
operands: BinaryOperands {
218
dst: x(0),
219
src1: x(1),
220
src2: x(2),
221
},
222
},
223
x(0),
224
expected | 0x1234567800000000,
225
);
226
}
227
}
228
}
229
230
#[test]
231
fn xslt64() {
232
for (expected, a, b) in [
233
(0u64, 0u64, 0u64),
234
(0, 1, 0),
235
(1, 0, 1),
236
(0, 0, -1 as _),
237
(1, -1 as _, 0),
238
(0, i64::MAX as u64, i64::MAX as u64),
239
(0, i64::MAX as u64, i64::MAX as u64 - 1),
240
(1, i64::MAX as u64 - 1, i64::MAX as u64),
241
(0, i64::MIN as u64, i64::MIN as u64),
242
(0, i64::MIN as u64 + 1, i64::MIN as u64),
243
(1, i64::MIN as u64, i64::MIN as u64 + 1),
244
] {
245
unsafe {
246
assert_one(
247
[(x(0), 0x1234567812345678), (x(1), a), (x(2), b)],
248
Xslt64 {
249
operands: BinaryOperands {
250
dst: x(0),
251
src1: x(1),
252
src2: x(2),
253
},
254
},
255
x(0),
256
expected | 0x1234567800000000,
257
);
258
}
259
}
260
}
261
262
#[test]
263
fn xslteq64() {
264
for (expected, a, b) in [
265
(1u64, 0u64, 0u64),
266
(0, 1, 0),
267
(1, 0, 1),
268
(0, 0, -1 as _),
269
(1, -1 as _, 0),
270
(1, i64::MAX as u64, i64::MAX as u64),
271
(0, i64::MAX as u64, i64::MAX as u64 - 1),
272
(1, i64::MAX as u64 - 1, i64::MAX as u64),
273
(1, i64::MIN as u64, i64::MIN as u64),
274
(0, i64::MIN as u64 + 1, i64::MIN as u64),
275
(1, i64::MIN as u64, i64::MIN as u64 + 1),
276
] {
277
unsafe {
278
assert_one(
279
[(x(0), 0x1234567812345678), (x(1), a), (x(2), b)],
280
Xslteq64 {
281
operands: BinaryOperands {
282
dst: x(0),
283
src1: x(1),
284
src2: x(2),
285
},
286
},
287
x(0),
288
expected | 0x1234567800000000,
289
);
290
}
291
}
292
}
293
294
#[test]
295
fn xult64() {
296
for (expected, a, b) in [
297
(0u64, 0u64, 0u64),
298
(0, 1, 0),
299
(1, 0, 1),
300
(0, u64::MAX, u64::MAX),
301
(0, u64::MAX, u64::MAX - 1),
302
(1, u64::MAX - 1, u64::MAX),
303
(0, i64::MIN as u64, 0),
304
(1, 0, i64::MIN as u64),
305
] {
306
unsafe {
307
assert_one(
308
[(x(0), 0x1234567812345678), (x(1), a), (x(2), b)],
309
Xult64 {
310
operands: BinaryOperands {
311
dst: x(0),
312
src1: x(1),
313
src2: x(2),
314
},
315
},
316
x(0),
317
expected | 0x1234567800000000,
318
);
319
}
320
}
321
}
322
323
#[test]
324
fn xulteq64() {
325
for (expected, a, b) in [
326
(1u64, 0u64, 0u64),
327
(0, 1, 0),
328
(1, 0, 1),
329
(1, u64::MAX, u64::MAX),
330
(0, u64::MAX, u64::MAX - 1),
331
(1, u64::MAX - 1, u64::MAX),
332
(0, i64::MIN as u64, 0),
333
(1, 0, i64::MIN as u64),
334
] {
335
unsafe {
336
assert_one(
337
[(x(0), 0x1234567812345678), (x(1), a), (x(2), b)],
338
Xulteq64 {
339
operands: BinaryOperands {
340
dst: x(0),
341
src1: x(1),
342
src2: x(2),
343
},
344
},
345
x(0),
346
expected | 0x1234567800000000,
347
);
348
}
349
}
350
}
351
352
#[test]
353
fn xeq32() {
354
for (expected, a, b) in [
355
(1u64, 0u64, 0u64),
356
(0, 0, 1),
357
(1, u64::MAX, u64::MAX),
358
(0, u64::MAX, u64::MAX - 1),
359
(1, 0xffffffff00000001, 1),
360
(0, 0xffffffff00000000, 1),
361
(0, 0xffffffff00000001, 0),
362
(1, 0xffffffff00000000, 0),
363
] {
364
unsafe {
365
assert_one(
366
[(x(0), 0x1234567812345678), (x(1), a), (x(2), b)],
367
Xeq32 {
368
operands: BinaryOperands {
369
dst: x(0),
370
src1: x(1),
371
src2: x(2),
372
},
373
},
374
x(0),
375
expected | 0x1234567800000000,
376
);
377
}
378
}
379
}
380
381
#[test]
382
fn xneq32() {
383
for (expected, a, b) in [
384
(0u64, 0u64, 0u64),
385
(1, 0, 1),
386
(0, u64::MAX, u64::MAX),
387
(1, u64::MAX, u64::MAX - 1),
388
(0, 0xffffffff00000000, 0),
389
] {
390
unsafe {
391
assert_one(
392
[(x(0), 0x1234567812345678), (x(1), a), (x(2), b)],
393
Xneq32 {
394
operands: BinaryOperands {
395
dst: x(0),
396
src1: x(1),
397
src2: x(2),
398
},
399
},
400
x(0),
401
expected | 0x1234567800000000,
402
);
403
}
404
}
405
}
406
407
#[test]
408
fn xslt32() {
409
for (expected, a, b) in [
410
(0u64, 0u64, 0u64),
411
(0, 1, 0),
412
(1, 0, 1),
413
(0, 0, -1 as _),
414
(1, -1 as _, 0),
415
(0, i64::MAX as u64, i64::MAX as u64),
416
(0, i64::MAX as u64, i64::MAX as u64 - 1),
417
(1, i64::MAX as u64 - 1, i64::MAX as u64),
418
(0, i64::MIN as u64, i64::MIN as u64),
419
(0, i64::MIN as u64 + 1, i64::MIN as u64),
420
(1, i64::MIN as u64, i64::MIN as u64 + 1),
421
(1, 0x00000000ffffffff, 0),
422
(0, 0, 0x00000000ffffffff),
423
] {
424
unsafe {
425
assert_one(
426
[(x(0), 0x1234567812345678), (x(1), a), (x(2), b)],
427
Xslt32 {
428
operands: BinaryOperands {
429
dst: x(0),
430
src1: x(1),
431
src2: x(2),
432
},
433
},
434
x(0),
435
expected | 0x1234567800000000,
436
);
437
}
438
}
439
}
440
441
#[test]
442
fn xslteq32() {
443
for (expected, a, b) in [
444
(1u64, 0u64, 0u64),
445
(0, 1, 0),
446
(1, 0, 1),
447
(0, 0, -1 as _),
448
(1, -1 as _, 0),
449
(1, i64::MAX as u64, i64::MAX as u64),
450
(0, i64::MAX as u64, i64::MAX as u64 - 1),
451
(1, i64::MAX as u64 - 1, i64::MAX as u64),
452
(1, i64::MIN as u64, i64::MIN as u64),
453
(0, i64::MIN as u64 + 1, i64::MIN as u64),
454
(1, i64::MIN as u64, i64::MIN as u64 + 1),
455
] {
456
unsafe {
457
assert_one(
458
[(x(0), 0x1234567812345678), (x(1), a), (x(2), b)],
459
Xslteq32 {
460
operands: BinaryOperands {
461
dst: x(0),
462
src1: x(1),
463
src2: x(2),
464
},
465
},
466
x(0),
467
expected | 0x1234567800000000,
468
);
469
}
470
}
471
}
472
473
#[test]
474
fn xult32() {
475
for (expected, a, b) in [
476
(0u64, 0u64, 0u64),
477
(0, 1, 0),
478
(1, 0, 1),
479
(0, 0x00000000ffffffff, 0xfffffffffffffffe),
480
(1, 0xfffffffffffffffe, 0x00000000ffffffff),
481
(0, 0x00000000ffffffff, 0xffffffffffffffff),
482
(0, 0xfffffffffffffffe, 0x00000000fffffffe),
483
] {
484
unsafe {
485
assert_one(
486
[(x(0), 0x1234567812345678), (x(1), a), (x(2), b)],
487
Xult32 {
488
operands: BinaryOperands {
489
dst: x(0),
490
src1: x(1),
491
src2: x(2),
492
},
493
},
494
x(0),
495
expected | 0x1234567800000000,
496
);
497
}
498
}
499
}
500
501
#[test]
502
fn xulteq32() {
503
for (expected, a, b) in [
504
(1u64, 0u64, 0u64),
505
(0, 1, 0),
506
(1, 0, 1),
507
(0, 0x00000000ffffffff, 0xfffffffffffffffe),
508
(1, 0xfffffffffffffffe, 0x00000000ffffffff),
509
(1, 0x00000000ffffffff, 0xffffffffffffffff),
510
(1, 0xfffffffffffffffe, 0x00000000fffffffe),
511
] {
512
unsafe {
513
assert_one(
514
[(x(0), 0x1234567812345678), (x(1), a), (x(2), b)],
515
Xulteq32 {
516
operands: BinaryOperands {
517
dst: x(0),
518
src1: x(1),
519
src2: x(2),
520
},
521
},
522
x(0),
523
expected | 0x1234567800000000,
524
);
525
}
526
}
527
}
528
529
#[test]
530
fn xload32le_o32() {
531
let a = UnsafeCell::new([11u32.to_le(), 22u32.to_le()]);
532
let b = UnsafeCell::new([33u32.to_le(), 44u32.to_le()]);
533
let c = UnsafeCell::new([55u32.to_le(), 66u32.to_le()]);
534
let d = UnsafeCell::new([(i32::MIN as u32).to_le(), (i32::MAX as u32).to_le()]);
535
536
for (expected, addr, offset) in [
537
(11, a.get(), 0),
538
(22, a.get(), 4),
539
(33, b.get(), 0),
540
(44, b.get(), 4),
541
(55, c.get(), 0),
542
(66, c.get(), 4),
543
(i32::MIN as u32 as u64, d.get(), 0),
544
(i32::MAX as u32 as u64, d.get(), 4),
545
] {
546
let init = 0x1234567812345678u64;
547
let expected = init & !u64::from(u32::MAX) | expected;
548
unsafe {
549
assert_one(
550
[
551
(x(0), Val::from(init)),
552
(x(1), Val::from(addr.cast::<u8>())),
553
],
554
XLoad32LeO32 {
555
dst: x(0),
556
addr: AddrO32 { addr: x(1), offset },
557
},
558
x(0),
559
expected,
560
);
561
}
562
}
563
}
564
565
#[test]
566
fn xload64le_o32() {
567
let a = UnsafeCell::new([11u64.to_le(), 22u64.to_le()]);
568
let b = UnsafeCell::new([33u64.to_le(), 44u64.to_le()]);
569
let c = UnsafeCell::new([55u64.to_le(), 66u64.to_le()]);
570
let d = UnsafeCell::new([(-1i64 as u64).to_le(), (i64::MAX as u64).to_le()]);
571
572
for (expected, addr, offset) in [
573
(11, a.get(), 0),
574
(22, a.get(), 8),
575
(33, b.get(), 0),
576
(44, b.get(), 8),
577
(55, c.get(), 0),
578
(66, c.get(), 8),
579
(-1i64 as u64, d.get(), 0),
580
(i64::MAX as u64, d.get(), 8),
581
] {
582
unsafe {
583
assert_one(
584
[
585
(x(0), Val::from(0x1234567812345678u64)),
586
(x(1), Val::from(addr)),
587
],
588
XLoad64LeO32 {
589
dst: x(0),
590
addr: AddrO32 { addr: x(1), offset },
591
},
592
x(0),
593
expected,
594
);
595
}
596
}
597
}
598
599
#[test]
600
fn xstore32_le_o32() {
601
let a = UnsafeCell::new([0x12u8, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78]);
602
let b = UnsafeCell::new([0x12u8, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78]);
603
let c = UnsafeCell::new([0x12u8, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78]);
604
605
unsafe {
606
for (val, addr, offset) in [
607
(0x11111111u32, a.get(), 0),
608
(0x22222222, b.get(), 4),
609
(0x33333333, c.get(), 2),
610
] {
611
let val = val as u64;
612
assert_one(
613
[(x(0), Val::from(addr)), (x(1), Val::from(val))],
614
XStore32LeO32 {
615
addr: AddrO32 { addr: x(0), offset },
616
src: x(1),
617
},
618
x(1),
619
val,
620
);
621
}
622
}
623
624
let a = u64::from_be_bytes(a.into_inner());
625
let expected = 0x1111111112345678u64;
626
eprintln!("expected(a) = {expected:#018x}");
627
eprintln!("actual(a) = {a:#018x}");
628
assert_eq!(a, expected);
629
630
let b = u64::from_be_bytes(b.into_inner());
631
let expected = 0x1234567822222222u64;
632
eprintln!("expected(b) = {expected:#018x}");
633
eprintln!("actual(b) = {b:#018x}");
634
assert_eq!(b, expected);
635
636
let c = u64::from_be_bytes(c.into_inner());
637
let expected = 0x1234333333335678u64;
638
eprintln!("expected(c) = {expected:#018x}");
639
eprintln!("actual(c) = {c:#018x}");
640
assert_eq!(c, expected);
641
}
642
643
#[test]
644
645
fn xstore64_le_o32() {
646
let a = UnsafeCell::new([0x1234567812345678, 0x1234567812345678, 0x1234567812345678]);
647
648
unsafe {
649
for (val, addr, offset) in [
650
(0x1111111111111111u64, a.get(), 0),
651
(0x2222222222222222, a.get(), 8),
652
(0x3333333333333333, a.get(), 16),
653
] {
654
assert_one(
655
[(x(0), Val::from(addr)), (x(1), Val::from(val))],
656
XStore64LeO32 {
657
src: x(1),
658
addr: AddrO32 { addr: x(0), offset },
659
},
660
x(1),
661
val,
662
);
663
}
664
}
665
666
let [a, b, c] = a.into_inner();
667
668
let expected = 0x1111111111111111u64;
669
eprintln!("expected(a) = {expected:#018x}");
670
eprintln!("actual(a) = {a:#018x}");
671
assert_eq!(a, expected);
672
673
let expected = 0x2222222222222222u64;
674
eprintln!("expected(b) = {expected:#018x}");
675
eprintln!("actual(b) = {b:#018x}");
676
assert_eq!(b, expected);
677
678
let expected = 0x3333333333333333u64;
679
eprintln!("expected(c) = {expected:#018x}");
680
eprintln!("actual(c) = {c:#018x}");
681
assert_eq!(c, expected);
682
}
683
684
#[test]
685
fn bitcast_int_from_float_32() {
686
for val in [
687
0.0,
688
1.0,
689
9.87654321,
690
f32::MAX,
691
f32::MIN,
692
f32::NAN,
693
f32::INFINITY,
694
f32::NEG_INFINITY,
695
f32::EPSILON,
696
f32::MIN_POSITIVE,
697
] {
698
unsafe {
699
assert_one(
700
[(f(0), val)],
701
BitcastIntFromFloat32 {
702
dst: x(0),
703
src: f(0),
704
},
705
x(0),
706
val.to_bits() as u64,
707
);
708
}
709
}
710
}
711
712
#[test]
713
fn bitcast_int_from_float_64() {
714
for val in [
715
0.0,
716
1.0,
717
9.87654321,
718
f64::MAX,
719
f64::MIN,
720
f64::NAN,
721
f64::INFINITY,
722
f64::NEG_INFINITY,
723
f64::EPSILON,
724
f64::MIN_POSITIVE,
725
] {
726
unsafe {
727
assert_one(
728
[(f(0), val)],
729
BitcastIntFromFloat64 {
730
dst: x(0),
731
src: f(0),
732
},
733
x(0),
734
val.to_bits(),
735
);
736
}
737
}
738
}
739
740
#[test]
741
fn bitcast_float_from_int_32() {
742
for val in [
743
0.0,
744
1.0,
745
9.87654321,
746
f32::MAX,
747
f32::MIN,
748
f32::NAN,
749
f32::INFINITY,
750
f32::NEG_INFINITY,
751
f32::EPSILON,
752
f32::MIN_POSITIVE,
753
] {
754
let val = val.to_bits() as u64;
755
unsafe {
756
assert_one(
757
[(x(0), val)],
758
BitcastFloatFromInt32 {
759
dst: f(0),
760
src: x(0),
761
},
762
f(0),
763
val,
764
);
765
}
766
}
767
}
768
769
#[test]
770
fn bitcast_float_from_int_64() {
771
for val in [
772
0.0,
773
1.0,
774
9.87654321,
775
f64::MAX,
776
f64::MIN,
777
f64::NAN,
778
f64::INFINITY,
779
f64::NEG_INFINITY,
780
f64::EPSILON,
781
f64::MIN_POSITIVE,
782
] {
783
let val = val.to_bits();
784
unsafe {
785
assert_one(
786
[(x(0), val)],
787
BitcastFloatFromInt64 {
788
dst: f(0),
789
src: x(0),
790
},
791
f(0),
792
val,
793
);
794
}
795
}
796
}
797
798
#[test]
799
fn trap() {
800
let mut vm = Vm::new();
801
let dst = XReg::new(0).unwrap();
802
803
unsafe {
804
run(
805
&mut vm,
806
&[
807
Op::Xconst16(Xconst16 { dst, imm: 1 }),
808
Op::ExtendedOp(ExtendedOp::Trap(Trap {})),
809
Op::Xconst16(Xconst16 { dst, imm: 2 }),
810
Op::Ret(Ret {}),
811
],
812
)
813
.unwrap_err();
814
}
815
816
// `dst` should not have been written to the second time.
817
assert_eq!(vm.state()[dst].get_u32(), 1);
818
}
819
820