1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
// |jit-test| skip-if: !wasmExtendedConstEnabled()
function testPrivateGlobal(valtype, expr, result) {
// Immutable private globals have a single cell for wasm.
let { get } = wasmEvalText(`(module
(global $global ${valtype} ${expr})
(func (export "get") (result ${valtype})
global.get $global
)
)`).exports;
assertEq(get(), result);
}
function testExportedGlobal(valtype, expr, result) {
// Immutable exported globals have a separate cell for wasm and the exported
// global object.
let { global, get } = wasmEvalText(`(module
(global $global (export "global") ${valtype} ${expr})
(func (export "get") (result ${valtype})
global.get $global
)
)`).exports;
assertEq(get(), result);
assertEq(global.value, result);
}
function testIndirectGlobal(valtype, expr, result) {
// Mutable exported globals share an indirect cell for wasm and the exported
// global object.
let { global } = wasmEvalText(`(module
(global (export "global") (mut ${valtype}) ${expr})
)`).exports;
assertEq(global.value, result);
}
// i32 tests
const I32_SQ_OVERFLOW = 0xFFFF + 1;
const MAX_I32 = 0xFFFF_FFFF;
function testI32(expr, result) {
testPrivateGlobal('i32', expr, result);
testExportedGlobal('i32', expr, result);
testIndirectGlobal('i32', expr, result);
}
testI32('i32.const 1', 1);
testI32('i32.const 1 i32.const 2 i32.add', 3);
testI32(`i32.const ${MAX_I32} i32.const 1 i32.add`, 0);
testI32('i32.const 1 i32.const 2 i32.sub', -1);
testI32(`i32.const 1 i32.const 0 i32.sub`, 1);
testI32('i32.const 1 i32.const 2 i32.mul', 2);
testI32(`i32.const ${I32_SQ_OVERFLOW} i32.const ${I32_SQ_OVERFLOW} i32.mul`, 0);
// i64 tests
const I64_SQ_OVERFLOW = 0xFFFF_FFFFn + 1n;
const MAX_I64 = 0xFFFF_FFFF_FFFF_FFFFn;
function testI64(expr, result) {
testPrivateGlobal('i64', expr, result);
testExportedGlobal('i64', expr, result);
testIndirectGlobal('i64', expr, result);
}
testI64('i64.const 1', 1n);
testI64('i64.const 1 i64.const 2 i64.add', 3n);
testI64(`i64.const ${MAX_I64} i64.const 1 i64.add`, 0n);
testI64('i64.const 1 i64.const 2 i64.sub', -1n);
testI64(`i64.const 1 i64.const 0 i64.sub`, 1n);
testI64('i64.const 1 i64.const 2 i64.mul', 2n);
testI64(`i64.const ${I64_SQ_OVERFLOW} i64.const ${I64_SQ_OVERFLOW} i64.mul`, 0n);
// test global.get
function testGlobalGet(valtype, aExpr, bExpr, cExpr, cResult) {
let { a, b } = wasmEvalText(`(module
(global (export "a") ${valtype} ${aExpr})
(global (export "b") ${valtype} ${bExpr})
)`).exports;
let { c } = wasmEvalText(`(module
(global $a (import "" "a") ${valtype})
(global $b (import "" "b") ${valtype})
(global (export "c") ${valtype} ${cExpr})
)`, {"": {a, b}}).exports;
assertEq(c.value, cResult);
}
testGlobalGet('i32', 'i32.const 2', 'i32.const 3', 'global.get $a global.get $b i32.add', 5);
testGlobalGet('i32', 'i32.const 2', 'i32.const 3', 'global.get $a global.get $b i32.sub', -1);
testGlobalGet('i32', 'i32.const 2', 'i32.const 3', 'global.get $a global.get $b i32.mul', 6);
testGlobalGet('i64', 'i64.const 2', 'i64.const 3', 'global.get $a global.get $b i64.add', 5n);
testGlobalGet('i64', 'i64.const 2', 'i64.const 3', 'global.get $a global.get $b i64.sub', -1n);
testGlobalGet('i64', 'i64.const 2', 'i64.const 3', 'global.get $a global.get $b i64.mul', 6n);
|