Line data Source code
1 : // Copyright 2014 the V8 project authors. All rights reserved. Use of this
2 : // source code is governed by a BSD-style license that can be found in the
3 : // LICENSE file.
4 :
5 : #include "src/objects-inl.h"
6 : #include "src/wasm/wasm-external-refs.h"
7 : #include "test/cctest/cctest.h"
8 : #include "test/cctest/compiler/codegen-tester.h"
9 : #include "test/cctest/compiler/value-helper.h"
10 :
11 : namespace v8 {
12 : namespace internal {
13 : namespace compiler {
14 :
15 : template <typename InType, typename OutType, typename Iterable>
16 20 : void TestExternalReference_ConvertOp(
17 : BufferedRawMachineAssemblerTester<int32_t>* m, ExternalReference ref,
18 : void (*wrapper)(Address), Iterable inputs) {
19 : constexpr size_t kBufferSize = Max(sizeof(InType), sizeof(OutType));
20 20 : uint8_t buffer[kBufferSize] = {0};
21 20 : Address buffer_addr = reinterpret_cast<Address>(buffer);
22 :
23 20 : Node* function = m->ExternalConstant(ref);
24 20 : m->CallCFunction1(MachineType::Pointer(), MachineType::Pointer(), function,
25 : m->PointerConstant(buffer));
26 20 : m->Return(m->Int32Constant(4356));
27 :
28 1640 : for (InType input : inputs) {
29 : WriteUnalignedValue<InType>(buffer_addr, input);
30 :
31 1620 : CHECK_EQ(4356, m->Call());
32 : OutType output = ReadUnalignedValue<OutType>(buffer_addr);
33 :
34 : WriteUnalignedValue<InType>(buffer_addr, input);
35 1620 : wrapper(buffer_addr);
36 : OutType expected_output = ReadUnalignedValue<OutType>(buffer_addr);
37 :
38 1620 : CHECK_EQ(expected_output, output);
39 : }
40 20 : }
41 :
42 : template <typename InType, typename OutType, typename Iterable>
43 20 : void TestExternalReference_ConvertOpWithOutputAndReturn(
44 : BufferedRawMachineAssemblerTester<int32_t>* m, ExternalReference ref,
45 : int32_t (*wrapper)(Address), Iterable inputs) {
46 : constexpr size_t kBufferSize = Max(sizeof(InType), sizeof(OutType));
47 20 : uint8_t buffer[kBufferSize] = {0};
48 20 : Address buffer_addr = reinterpret_cast<Address>(buffer);
49 :
50 20 : Node* function = m->ExternalConstant(ref);
51 20 : m->Return(m->CallCFunction1(MachineType::Int32(), MachineType::Pointer(),
52 : function, m->PointerConstant(buffer)));
53 :
54 1660 : for (InType input : inputs) {
55 : WriteUnalignedValue<InType>(buffer_addr, input);
56 :
57 : int32_t ret = m->Call();
58 : OutType output = ReadUnalignedValue<OutType>(buffer_addr);
59 :
60 : WriteUnalignedValue<InType>(buffer_addr, input);
61 1640 : int32_t expected_ret = wrapper(buffer_addr);
62 : OutType expected_output = ReadUnalignedValue<OutType>(buffer_addr);
63 :
64 1640 : CHECK_EQ(expected_ret, ret);
65 1640 : CHECK_EQ(expected_output, output);
66 : }
67 20 : }
68 :
69 : template <typename InType, typename OutType, typename Iterable>
70 20 : void TestExternalReference_ConvertOpWithReturn(
71 : BufferedRawMachineAssemblerTester<OutType>* m, ExternalReference ref,
72 : OutType (*wrapper)(Address), Iterable inputs) {
73 : constexpr size_t kBufferSize = sizeof(InType);
74 20 : uint8_t buffer[kBufferSize] = {0};
75 20 : Address buffer_addr = reinterpret_cast<Address>(buffer);
76 :
77 20 : Node* function = m->ExternalConstant(ref);
78 20 : m->Return(m->CallCFunction1(MachineType::Int32(), MachineType::Pointer(),
79 : function, m->PointerConstant(buffer)));
80 :
81 1410 : for (InType input : inputs) {
82 : WriteUnalignedValue<InType>(buffer_addr, input);
83 :
84 : OutType ret = m->Call();
85 :
86 : WriteUnalignedValue<InType>(buffer_addr, input);
87 1390 : OutType expected_ret = wrapper(buffer_addr);
88 :
89 1390 : CHECK_EQ(expected_ret, ret);
90 : }
91 20 : }
92 :
93 : template <typename Type>
94 : bool isnan(Type value) {
95 : return false;
96 : }
97 : template <>
98 0 : bool isnan<float>(float value) {
99 0 : return std::isnan(value);
100 : }
101 : template <>
102 0 : bool isnan<double>(double value) {
103 0 : return std::isnan(value);
104 : }
105 :
106 : template <typename Type, typename Iterable>
107 40 : void TestExternalReference_UnOp(BufferedRawMachineAssemblerTester<int32_t>* m,
108 : ExternalReference ref, void (*wrapper)(Address),
109 : Iterable inputs) {
110 : constexpr size_t kBufferSize = sizeof(Type);
111 40 : uint8_t buffer[kBufferSize] = {0};
112 40 : Address buffer_addr = reinterpret_cast<Address>(buffer);
113 :
114 40 : Node* function = m->ExternalConstant(ref);
115 40 : m->CallCFunction1(MachineType::Int32(), MachineType::Pointer(), function,
116 : m->PointerConstant(buffer));
117 40 : m->Return(m->Int32Constant(4356));
118 :
119 3320 : for (Type input : inputs) {
120 : WriteUnalignedValue<Type>(buffer_addr, input);
121 3280 : CHECK_EQ(4356, m->Call());
122 : Type output = ReadUnalignedValue<Type>(buffer_addr);
123 :
124 : WriteUnalignedValue<Type>(buffer_addr, input);
125 3280 : wrapper(buffer_addr);
126 : Type expected_output = ReadUnalignedValue<Type>(buffer_addr);
127 :
128 3280 : if (isnan(expected_output) && isnan(output)) continue;
129 3200 : CHECK_EQ(expected_output, output);
130 : }
131 40 : }
132 :
133 : template <typename Type, typename Iterable>
134 5 : void TestExternalReference_BinOp(BufferedRawMachineAssemblerTester<int32_t>* m,
135 : ExternalReference ref,
136 : void (*wrapper)(Address), Iterable inputs) {
137 : constexpr size_t kBufferSize = 2 * sizeof(Type);
138 5 : uint8_t buffer[kBufferSize] = {0};
139 5 : Address buffer_addr = reinterpret_cast<Address>(buffer);
140 :
141 5 : Node* function = m->ExternalConstant(ref);
142 5 : m->CallCFunction1(MachineType::Int32(), MachineType::Pointer(), function,
143 : m->PointerConstant(buffer));
144 5 : m->Return(m->Int32Constant(4356));
145 :
146 250 : for (Type input1 : inputs) {
147 12250 : for (Type input2 : inputs) {
148 : WriteUnalignedValue<Type>(buffer_addr, input1);
149 12005 : WriteUnalignedValue<Type>(buffer_addr + sizeof(Type), input2);
150 12005 : CHECK_EQ(4356, m->Call());
151 : Type output = ReadUnalignedValue<Type>(buffer_addr);
152 :
153 : WriteUnalignedValue<Type>(buffer_addr, input1);
154 : WriteUnalignedValue<Type>(buffer_addr + sizeof(Type), input2);
155 12005 : wrapper(buffer_addr);
156 : Type expected_output = ReadUnalignedValue<Type>(buffer_addr);
157 :
158 12005 : if (isnan(expected_output) && isnan(output)) continue;
159 8965 : CHECK_EQ(expected_output, output);
160 : }
161 : }
162 5 : }
163 :
164 : template <typename Type, typename Iterable>
165 20 : void TestExternalReference_BinOpWithReturn(
166 : BufferedRawMachineAssemblerTester<int32_t>* m, ExternalReference ref,
167 : int32_t (*wrapper)(Address), Iterable inputs) {
168 : constexpr size_t kBufferSize = 2 * sizeof(Type);
169 20 : uint8_t buffer[kBufferSize] = {0};
170 20 : Address buffer_addr = reinterpret_cast<Address>(buffer);
171 :
172 20 : Node* function = m->ExternalConstant(ref);
173 20 : m->Return(m->CallCFunction1(MachineType::Int32(), MachineType::Pointer(),
174 : function, m->PointerConstant(buffer)));
175 :
176 1640 : for (Type input1 : inputs) {
177 132840 : for (Type input2 : inputs) {
178 : WriteUnalignedValue<Type>(buffer_addr, input1);
179 131220 : WriteUnalignedValue<Type>(buffer_addr + sizeof(Type), input2);
180 : int32_t ret = m->Call();
181 : Type output = ReadUnalignedValue<Type>(buffer_addr);
182 :
183 : WriteUnalignedValue<Type>(buffer_addr, input1);
184 : WriteUnalignedValue<Type>(buffer_addr + sizeof(Type), input2);
185 131220 : int32_t expected_ret = wrapper(buffer_addr);
186 : Type expected_output = ReadUnalignedValue<Type>(buffer_addr);
187 :
188 131220 : CHECK_EQ(expected_ret, ret);
189 : if (isnan(expected_output) && isnan(output)) continue;
190 131220 : CHECK_EQ(expected_output, output);
191 : }
192 : }
193 20 : }
194 :
195 28342 : TEST(RunCallF32Trunc) {
196 5 : BufferedRawMachineAssemblerTester<int32_t> m;
197 5 : ExternalReference ref = ExternalReference::wasm_f32_trunc();
198 : TestExternalReference_UnOp<float>(&m, ref, wasm::f32_trunc_wrapper,
199 5 : ValueHelper::float32_vector());
200 5 : }
201 :
202 28342 : TEST(RunCallF32Floor) {
203 5 : BufferedRawMachineAssemblerTester<int32_t> m;
204 5 : ExternalReference ref = ExternalReference::wasm_f32_floor();
205 : TestExternalReference_UnOp<float>(&m, ref, wasm::f32_floor_wrapper,
206 5 : ValueHelper::float32_vector());
207 5 : }
208 :
209 28342 : TEST(RunCallF32Ceil) {
210 5 : BufferedRawMachineAssemblerTester<int32_t> m;
211 5 : ExternalReference ref = ExternalReference::wasm_f32_ceil();
212 : TestExternalReference_UnOp<float>(&m, ref, wasm::f32_ceil_wrapper,
213 5 : ValueHelper::float32_vector());
214 5 : }
215 :
216 28342 : TEST(RunCallF32RoundTiesEven) {
217 5 : BufferedRawMachineAssemblerTester<int32_t> m;
218 5 : ExternalReference ref = ExternalReference::wasm_f32_nearest_int();
219 : TestExternalReference_UnOp<float>(&m, ref, wasm::f32_nearest_int_wrapper,
220 5 : ValueHelper::float32_vector());
221 5 : }
222 :
223 28342 : TEST(RunCallF64Trunc) {
224 5 : BufferedRawMachineAssemblerTester<int32_t> m;
225 5 : ExternalReference ref = ExternalReference::wasm_f64_trunc();
226 : TestExternalReference_UnOp<double>(&m, ref, wasm::f64_trunc_wrapper,
227 5 : ValueHelper::float64_vector());
228 5 : }
229 :
230 28342 : TEST(RunCallF64Floor) {
231 5 : BufferedRawMachineAssemblerTester<int32_t> m;
232 5 : ExternalReference ref = ExternalReference::wasm_f64_floor();
233 : TestExternalReference_UnOp<double>(&m, ref, wasm::f64_floor_wrapper,
234 5 : ValueHelper::float64_vector());
235 5 : }
236 :
237 28342 : TEST(RunCallF64Ceil) {
238 5 : BufferedRawMachineAssemblerTester<int32_t> m;
239 5 : ExternalReference ref = ExternalReference::wasm_f64_ceil();
240 : TestExternalReference_UnOp<double>(&m, ref, wasm::f64_ceil_wrapper,
241 5 : ValueHelper::float64_vector());
242 5 : }
243 :
244 28342 : TEST(RunCallF64RoundTiesEven) {
245 5 : BufferedRawMachineAssemblerTester<int32_t> m;
246 5 : ExternalReference ref = ExternalReference::wasm_f64_nearest_int();
247 : TestExternalReference_UnOp<double>(&m, ref, wasm::f64_nearest_int_wrapper,
248 5 : ValueHelper::float64_vector());
249 5 : }
250 :
251 28342 : TEST(RunCallInt64ToFloat32) {
252 5 : BufferedRawMachineAssemblerTester<int32_t> m;
253 5 : ExternalReference ref = ExternalReference::wasm_int64_to_float32();
254 : TestExternalReference_ConvertOp<int64_t, float>(
255 5 : &m, ref, wasm::int64_to_float32_wrapper, ValueHelper::int64_vector());
256 5 : }
257 :
258 28342 : TEST(RunCallUint64ToFloat32) {
259 5 : BufferedRawMachineAssemblerTester<int32_t> m;
260 5 : ExternalReference ref = ExternalReference::wasm_uint64_to_float32();
261 : TestExternalReference_ConvertOp<uint64_t, float>(
262 5 : &m, ref, wasm::uint64_to_float32_wrapper, ValueHelper::uint64_vector());
263 5 : }
264 :
265 28342 : TEST(RunCallInt64ToFloat64) {
266 5 : BufferedRawMachineAssemblerTester<int32_t> m;
267 5 : ExternalReference ref = ExternalReference::wasm_int64_to_float64();
268 : TestExternalReference_ConvertOp<int64_t, double>(
269 5 : &m, ref, wasm::int64_to_float64_wrapper, ValueHelper::int64_vector());
270 5 : }
271 :
272 28342 : TEST(RunCallUint64ToFloat64) {
273 5 : BufferedRawMachineAssemblerTester<int32_t> m;
274 5 : ExternalReference ref = ExternalReference::wasm_uint64_to_float64();
275 : TestExternalReference_ConvertOp<uint64_t, double>(
276 5 : &m, ref, wasm::uint64_to_float64_wrapper, ValueHelper::uint64_vector());
277 5 : }
278 :
279 28342 : TEST(RunCallFloat32ToInt64) {
280 5 : BufferedRawMachineAssemblerTester<int32_t> m;
281 5 : ExternalReference ref = ExternalReference::wasm_float32_to_int64();
282 : TestExternalReference_ConvertOpWithOutputAndReturn<float, int64_t>(
283 5 : &m, ref, wasm::float32_to_int64_wrapper, ValueHelper::float32_vector());
284 5 : }
285 :
286 28342 : TEST(RunCallFloat32ToUint64) {
287 5 : BufferedRawMachineAssemblerTester<int32_t> m;
288 5 : ExternalReference ref = ExternalReference::wasm_float32_to_uint64();
289 : TestExternalReference_ConvertOpWithOutputAndReturn<float, uint64_t>(
290 5 : &m, ref, wasm::float32_to_uint64_wrapper, ValueHelper::float32_vector());
291 5 : }
292 :
293 28342 : TEST(RunCallFloat64ToInt64) {
294 5 : BufferedRawMachineAssemblerTester<int32_t> m;
295 5 : ExternalReference ref = ExternalReference::wasm_float64_to_int64();
296 : TestExternalReference_ConvertOpWithOutputAndReturn<double, int64_t>(
297 5 : &m, ref, wasm::float64_to_int64_wrapper, ValueHelper::float64_vector());
298 5 : }
299 :
300 28342 : TEST(RunCallFloat64ToUint64) {
301 5 : BufferedRawMachineAssemblerTester<int32_t> m;
302 5 : ExternalReference ref = ExternalReference::wasm_float64_to_uint64();
303 : TestExternalReference_ConvertOpWithOutputAndReturn<double, uint64_t>(
304 5 : &m, ref, wasm::float64_to_uint64_wrapper, ValueHelper::float64_vector());
305 5 : }
306 :
307 28342 : TEST(RunCallInt64Div) {
308 5 : BufferedRawMachineAssemblerTester<int32_t> m;
309 5 : ExternalReference ref = ExternalReference::wasm_int64_div();
310 : TestExternalReference_BinOpWithReturn<int64_t>(
311 5 : &m, ref, wasm::int64_div_wrapper, ValueHelper::int64_vector());
312 5 : }
313 :
314 28342 : TEST(RunCallInt64Mod) {
315 5 : BufferedRawMachineAssemblerTester<int32_t> m;
316 5 : ExternalReference ref = ExternalReference::wasm_int64_mod();
317 : TestExternalReference_BinOpWithReturn<int64_t>(
318 5 : &m, ref, wasm::int64_mod_wrapper, ValueHelper::int64_vector());
319 5 : }
320 :
321 28342 : TEST(RunCallUint64Div) {
322 5 : BufferedRawMachineAssemblerTester<int32_t> m;
323 5 : ExternalReference ref = ExternalReference::wasm_uint64_div();
324 : TestExternalReference_BinOpWithReturn<uint64_t>(
325 5 : &m, ref, wasm::uint64_div_wrapper, ValueHelper::uint64_vector());
326 5 : }
327 :
328 28342 : TEST(RunCallUint64Mod) {
329 5 : BufferedRawMachineAssemblerTester<int32_t> m;
330 5 : ExternalReference ref = ExternalReference::wasm_uint64_mod();
331 : TestExternalReference_BinOpWithReturn<uint64_t>(
332 5 : &m, ref, wasm::uint64_mod_wrapper, ValueHelper::uint64_vector());
333 5 : }
334 :
335 28342 : TEST(RunCallWord32Ctz) {
336 5 : BufferedRawMachineAssemblerTester<uint32_t> m;
337 5 : ExternalReference ref = ExternalReference::wasm_word32_ctz();
338 : TestExternalReference_ConvertOpWithReturn<int32_t, uint32_t>(
339 5 : &m, ref, wasm::word32_ctz_wrapper, ValueHelper::int32_vector());
340 5 : }
341 :
342 28342 : TEST(RunCallWord64Ctz) {
343 5 : BufferedRawMachineAssemblerTester<uint32_t> m;
344 5 : ExternalReference ref = ExternalReference::wasm_word64_ctz();
345 : TestExternalReference_ConvertOpWithReturn<int64_t, uint32_t>(
346 5 : &m, ref, wasm::word64_ctz_wrapper, ValueHelper::int64_vector());
347 5 : }
348 :
349 28342 : TEST(RunCallWord32Popcnt) {
350 5 : BufferedRawMachineAssemblerTester<uint32_t> m;
351 5 : ExternalReference ref = ExternalReference::wasm_word32_popcnt();
352 : TestExternalReference_ConvertOpWithReturn<uint32_t, uint32_t>(
353 5 : &m, ref, wasm::word32_popcnt_wrapper, ValueHelper::int32_vector());
354 5 : }
355 :
356 28342 : TEST(RunCallWord64Popcnt) {
357 5 : BufferedRawMachineAssemblerTester<uint32_t> m;
358 5 : ExternalReference ref = ExternalReference::wasm_word64_popcnt();
359 : TestExternalReference_ConvertOpWithReturn<int64_t, uint32_t>(
360 5 : &m, ref, wasm::word64_popcnt_wrapper, ValueHelper::int64_vector());
361 5 : }
362 :
363 28342 : TEST(RunCallFloat64Pow) {
364 5 : BufferedRawMachineAssemblerTester<int32_t> m;
365 5 : ExternalReference ref = ExternalReference::wasm_float64_pow();
366 : TestExternalReference_BinOp<double>(&m, ref, wasm::float64_pow_wrapper,
367 5 : ValueHelper::float64_vector());
368 5 : }
369 :
370 : } // namespace compiler
371 : } // namespace internal
372 85011 : } // namespace v8
|