1 // Copyright 2016 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "test/unittests/test-utils.h"
6
7 #include "src/v8.h"
8
9 #include "test/cctest/wasm/test-signatures.h"
10
11 #include "src/bit-vector.h"
12 #include "src/objects.h"
13
14 #include "src/wasm/ast-decoder.h"
15 #include "src/wasm/wasm-macro-gen.h"
16 #include "src/wasm/wasm-module.h"
17
18 #define WASM_SET_ZERO(i) WASM_SET_LOCAL(i, WASM_ZERO)
19
20 namespace v8 {
21 namespace internal {
22 namespace wasm {
23
24 class WasmLoopAssignmentAnalyzerTest : public TestWithZone {
25 public:
WasmLoopAssignmentAnalyzerTest()26 WasmLoopAssignmentAnalyzerTest() : num_locals(0) {}
27 TestSignatures sigs;
28 uint32_t num_locals;
29
Analyze(const byte * start,const byte * end)30 BitVector* Analyze(const byte* start, const byte* end) {
31 return AnalyzeLoopAssignmentForTesting(zone(), num_locals, start, end);
32 }
33 };
34
TEST_F(WasmLoopAssignmentAnalyzerTest,Empty0)35 TEST_F(WasmLoopAssignmentAnalyzerTest, Empty0) {
36 byte code[] = { 0 };
37 BitVector* assigned = Analyze(code, code);
38 CHECK_NULL(assigned);
39 }
40
TEST_F(WasmLoopAssignmentAnalyzerTest,Empty1)41 TEST_F(WasmLoopAssignmentAnalyzerTest, Empty1) {
42 byte code[] = {kExprLoop, 0};
43 for (int i = 0; i < 5; i++) {
44 BitVector* assigned = Analyze(code, code + arraysize(code));
45 for (int j = 0; j < assigned->length(); j++) {
46 CHECK_EQ(false, assigned->Contains(j));
47 }
48 num_locals++;
49 }
50 }
51
TEST_F(WasmLoopAssignmentAnalyzerTest,One)52 TEST_F(WasmLoopAssignmentAnalyzerTest, One) {
53 num_locals = 5;
54 for (int i = 0; i < 5; i++) {
55 byte code[] = {WASM_LOOP(1, WASM_SET_ZERO(i))};
56 BitVector* assigned = Analyze(code, code + arraysize(code));
57 for (int j = 0; j < assigned->length(); j++) {
58 CHECK_EQ(j == i, assigned->Contains(j));
59 }
60 }
61 }
62
TEST_F(WasmLoopAssignmentAnalyzerTest,OneBeyond)63 TEST_F(WasmLoopAssignmentAnalyzerTest, OneBeyond) {
64 num_locals = 5;
65 for (int i = 0; i < 5; i++) {
66 byte code[] = {WASM_LOOP(1, WASM_SET_ZERO(i)), WASM_SET_ZERO(1)};
67 BitVector* assigned = Analyze(code, code + arraysize(code));
68 for (int j = 0; j < assigned->length(); j++) {
69 CHECK_EQ(j == i, assigned->Contains(j));
70 }
71 }
72 }
73
TEST_F(WasmLoopAssignmentAnalyzerTest,Two)74 TEST_F(WasmLoopAssignmentAnalyzerTest, Two) {
75 num_locals = 5;
76 for (int i = 0; i < 5; i++) {
77 for (int j = 0; j < 5; j++) {
78 byte code[] = {WASM_LOOP(2, WASM_SET_ZERO(i), WASM_SET_ZERO(j))};
79 BitVector* assigned = Analyze(code, code + arraysize(code));
80 for (int k = 0; k < assigned->length(); k++) {
81 bool expected = k == i || k == j;
82 CHECK_EQ(expected, assigned->Contains(k));
83 }
84 }
85 }
86 }
87
TEST_F(WasmLoopAssignmentAnalyzerTest,NestedIf)88 TEST_F(WasmLoopAssignmentAnalyzerTest, NestedIf) {
89 num_locals = 5;
90 for (int i = 0; i < 5; i++) {
91 byte code[] = {WASM_LOOP(
92 1, WASM_IF_ELSE(WASM_SET_ZERO(0), WASM_SET_ZERO(i), WASM_SET_ZERO(1)))};
93 BitVector* assigned = Analyze(code, code + arraysize(code));
94 for (int j = 0; j < assigned->length(); j++) {
95 bool expected = i == j || j == 0 || j == 1;
96 CHECK_EQ(expected, assigned->Contains(j));
97 }
98 }
99 }
100
LEBByte(uint32_t val,byte which)101 static byte LEBByte(uint32_t val, byte which) {
102 byte b = (val >> (which * 7)) & 0x7F;
103 if (val >> ((which + 1) * 7)) b |= 0x80;
104 return b;
105 }
106
TEST_F(WasmLoopAssignmentAnalyzerTest,BigLocal)107 TEST_F(WasmLoopAssignmentAnalyzerTest, BigLocal) {
108 num_locals = 65000;
109 for (int i = 13; i < 65000; i = static_cast<int>(i * 1.5)) {
110 byte code[] = {kExprLoop,
111 1,
112 kExprSetLocal,
113 LEBByte(i, 0),
114 LEBByte(i, 1),
115 LEBByte(i, 2),
116 11,
117 12,
118 13};
119
120 BitVector* assigned = Analyze(code, code + arraysize(code));
121 for (int j = 0; j < assigned->length(); j++) {
122 bool expected = i == j;
123 CHECK_EQ(expected, assigned->Contains(j));
124 }
125 }
126 }
127
TEST_F(WasmLoopAssignmentAnalyzerTest,Break)128 TEST_F(WasmLoopAssignmentAnalyzerTest, Break) {
129 num_locals = 3;
130 byte code[] = {
131 WASM_LOOP(1, WASM_IF(WASM_GET_LOCAL(0), WASM_BRV(1, WASM_SET_ZERO(1)))),
132 WASM_SET_ZERO(0)};
133
134 BitVector* assigned = Analyze(code, code + arraysize(code));
135 for (int j = 0; j < assigned->length(); j++) {
136 bool expected = j == 1;
137 CHECK_EQ(expected, assigned->Contains(j));
138 }
139 }
140
TEST_F(WasmLoopAssignmentAnalyzerTest,Loop1)141 TEST_F(WasmLoopAssignmentAnalyzerTest, Loop1) {
142 num_locals = 5;
143 byte code[] = {
144 WASM_LOOP(1, WASM_IF(WASM_GET_LOCAL(0),
145 WASM_BRV(0, WASM_SET_LOCAL(
146 3, WASM_I32_SUB(WASM_GET_LOCAL(0),
147 WASM_I8(1)))))),
148 WASM_GET_LOCAL(0)};
149
150 BitVector* assigned = Analyze(code, code + arraysize(code));
151 for (int j = 0; j < assigned->length(); j++) {
152 bool expected = j == 3;
153 CHECK_EQ(expected, assigned->Contains(j));
154 }
155 }
156
TEST_F(WasmLoopAssignmentAnalyzerTest,Loop2)157 TEST_F(WasmLoopAssignmentAnalyzerTest, Loop2) {
158 num_locals = 6;
159 const byte kIter = 0;
160 const byte kSum = 3;
161
162 byte code[] = {WASM_BLOCK(
163 3,
164 WASM_WHILE(
165 WASM_GET_LOCAL(kIter),
166 WASM_BLOCK(2, WASM_SET_LOCAL(
167 kSum, WASM_F32_ADD(
168 WASM_GET_LOCAL(kSum),
169 WASM_LOAD_MEM(MachineType::Float32(),
170 WASM_GET_LOCAL(kIter)))),
171 WASM_SET_LOCAL(kIter, WASM_I32_SUB(WASM_GET_LOCAL(kIter),
172 WASM_I8(4))))),
173 WASM_STORE_MEM(MachineType::Float32(), WASM_ZERO, WASM_GET_LOCAL(kSum)),
174 WASM_GET_LOCAL(kIter))};
175
176 BitVector* assigned = Analyze(code + 1, code + arraysize(code));
177 for (int j = 0; j < assigned->length(); j++) {
178 bool expected = j == kIter || j == kSum;
179 CHECK_EQ(expected, assigned->Contains(j));
180 }
181 }
182
TEST_F(WasmLoopAssignmentAnalyzerTest,Malformed)183 TEST_F(WasmLoopAssignmentAnalyzerTest, Malformed) {
184 byte code[] = {kExprLoop, kExprF32Neg, kExprBrTable, 0x0e, 'h', 'e',
185 'l', 'l', 'o', ',', ' ', 'w',
186 'o', 'r', 'l', 'd', '!'};
187 BitVector* assigned = Analyze(code, code + arraysize(code));
188 CHECK_NULL(assigned);
189 }
190
191 } // namespace wasm
192 } // namespace internal
193 } // namespace v8
194