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 16 : 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 16 : uint8_t buffer[kBufferSize] = {0};
21 16 : Address buffer_addr = reinterpret_cast<Address>(buffer);
22 :
23 16 : Node* function = m->ExternalConstant(ref);
24 16 : m->CallCFunction1(MachineType::Pointer(), MachineType::Pointer(), function,
25 : m->PointerConstant(buffer));
26 16 : m->Return(m->Int32Constant(4356));
27 :
28 2608 : for (InType input : inputs) {
29 : WriteUnalignedValue<InType>(buffer_addr, input);
30 :
31 1296 : CHECK_EQ(4356, m->Call());
32 : OutType output = ReadUnalignedValue<OutType>(buffer_addr);
33 :
34 : WriteUnalignedValue<InType>(buffer_addr, input);
35 1296 : wrapper(buffer_addr);
36 : OutType expected_output = ReadUnalignedValue<OutType>(buffer_addr);
37 :
38 1296 : CHECK_EQ(expected_output, output);
39 : }
40 16 : }
41 :
42 : template <typename InType, typename OutType, typename Iterable>
43 16 : 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 16 : uint8_t buffer[kBufferSize] = {0};
48 16 : Address buffer_addr = reinterpret_cast<Address>(buffer);
49 :
50 16 : Node* function = m->ExternalConstant(ref);
51 16 : m->Return(m->CallCFunction1(MachineType::Int32(), MachineType::Pointer(),
52 : function, m->PointerConstant(buffer)));
53 :
54 2640 : 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 1312 : int32_t expected_ret = wrapper(buffer_addr);
62 : OutType expected_output = ReadUnalignedValue<OutType>(buffer_addr);
63 :
64 1312 : CHECK_EQ(expected_ret, ret);
65 1312 : CHECK_EQ(expected_output, output);
66 : }
67 16 : }
68 :
69 : template <typename InType, typename OutType, typename Iterable>
70 16 : void TestExternalReference_ConvertOpWithReturn(
71 : BufferedRawMachineAssemblerTester<OutType>* m, ExternalReference ref,
72 : OutType (*wrapper)(Address), Iterable inputs) {
73 : constexpr size_t kBufferSize = sizeof(InType);
74 16 : uint8_t buffer[kBufferSize] = {0};
75 16 : Address buffer_addr = reinterpret_cast<Address>(buffer);
76 :
77 16 : Node* function = m->ExternalConstant(ref);
78 16 : m->Return(m->CallCFunction1(MachineType::Int32(), MachineType::Pointer(),
79 : function, m->PointerConstant(buffer)));
80 :
81 2240 : for (InType input : inputs) {
82 : WriteUnalignedValue<InType>(buffer_addr, input);
83 :
84 : OutType ret = m->Call();
85 :
86 : WriteUnalignedValue<InType>(buffer_addr, input);
87 1112 : OutType expected_ret = wrapper(buffer_addr);
88 :
89 1112 : CHECK_EQ(expected_ret, ret);
90 : }
91 16 : }
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 32 : void TestExternalReference_UnOp(BufferedRawMachineAssemblerTester<int32_t>* m,
108 : ExternalReference ref, void (*wrapper)(Address),
109 : Iterable inputs) {
110 : constexpr size_t kBufferSize = sizeof(Type);
111 32 : uint8_t buffer[kBufferSize] = {0};
112 32 : Address buffer_addr = reinterpret_cast<Address>(buffer);
113 :
114 32 : Node* function = m->ExternalConstant(ref);
115 32 : m->CallCFunction1(MachineType::Int32(), MachineType::Pointer(), function,
116 : m->PointerConstant(buffer));
117 32 : m->Return(m->Int32Constant(4356));
118 :
119 5280 : for (Type input : inputs) {
120 : WriteUnalignedValue<Type>(buffer_addr, input);
121 2624 : CHECK_EQ(4356, m->Call());
122 : Type output = ReadUnalignedValue<Type>(buffer_addr);
123 :
124 : WriteUnalignedValue<Type>(buffer_addr, input);
125 2624 : wrapper(buffer_addr);
126 : Type expected_output = ReadUnalignedValue<Type>(buffer_addr);
127 :
128 2624 : if (isnan(expected_output) && isnan(output)) continue;
129 2560 : CHECK_EQ(expected_output, output);
130 : }
131 32 : }
132 :
133 : template <typename Type, typename Iterable>
134 4 : 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 4 : uint8_t buffer[kBufferSize] = {0};
139 4 : Address buffer_addr = reinterpret_cast<Address>(buffer);
140 :
141 4 : Node* function = m->ExternalConstant(ref);
142 4 : m->CallCFunction1(MachineType::Int32(), MachineType::Pointer(), function,
143 : m->PointerConstant(buffer));
144 4 : m->Return(m->Int32Constant(4356));
145 :
146 396 : for (Type input1 : inputs) {
147 19404 : for (Type input2 : inputs) {
148 : WriteUnalignedValue<Type>(buffer_addr, input1);
149 9604 : WriteUnalignedValue<Type>(buffer_addr + sizeof(Type), input2);
150 9604 : 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 9604 : wrapper(buffer_addr);
156 : Type expected_output = ReadUnalignedValue<Type>(buffer_addr);
157 :
158 9604 : if (isnan(expected_output) && isnan(output)) continue;
159 7172 : CHECK_EQ(expected_output, output);
160 : }
161 : }
162 4 : }
163 :
164 : template <typename Type, typename Iterable>
165 16 : 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 16 : uint8_t buffer[kBufferSize] = {0};
170 16 : Address buffer_addr = reinterpret_cast<Address>(buffer);
171 :
172 16 : Node* function = m->ExternalConstant(ref);
173 16 : m->Return(m->CallCFunction1(MachineType::Int32(), MachineType::Pointer(),
174 : function, m->PointerConstant(buffer)));
175 :
176 2608 : for (Type input1 : inputs) {
177 211248 : for (Type input2 : inputs) {
178 : WriteUnalignedValue<Type>(buffer_addr, input1);
179 104976 : 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 104976 : int32_t expected_ret = wrapper(buffer_addr);
186 : Type expected_output = ReadUnalignedValue<Type>(buffer_addr);
187 :
188 104976 : CHECK_EQ(expected_ret, ret);
189 : if (isnan(expected_output) && isnan(output)) continue;
190 104976 : CHECK_EQ(expected_output, output);
191 : }
192 : }
193 16 : }
194 :
195 26067 : TEST(RunCallF32Trunc) {
196 4 : BufferedRawMachineAssemblerTester<int32_t> m;
197 4 : ExternalReference ref = ExternalReference::wasm_f32_trunc();
198 : TestExternalReference_UnOp<float>(&m, ref, wasm::f32_trunc_wrapper,
199 4 : ValueHelper::float32_vector());
200 4 : }
201 :
202 26067 : TEST(RunCallF32Floor) {
203 4 : BufferedRawMachineAssemblerTester<int32_t> m;
204 4 : ExternalReference ref = ExternalReference::wasm_f32_floor();
205 : TestExternalReference_UnOp<float>(&m, ref, wasm::f32_floor_wrapper,
206 4 : ValueHelper::float32_vector());
207 4 : }
208 :
209 26067 : TEST(RunCallF32Ceil) {
210 4 : BufferedRawMachineAssemblerTester<int32_t> m;
211 4 : ExternalReference ref = ExternalReference::wasm_f32_ceil();
212 : TestExternalReference_UnOp<float>(&m, ref, wasm::f32_ceil_wrapper,
213 4 : ValueHelper::float32_vector());
214 4 : }
215 :
216 26067 : TEST(RunCallF32RoundTiesEven) {
217 4 : BufferedRawMachineAssemblerTester<int32_t> m;
218 4 : ExternalReference ref = ExternalReference::wasm_f32_nearest_int();
219 : TestExternalReference_UnOp<float>(&m, ref, wasm::f32_nearest_int_wrapper,
220 4 : ValueHelper::float32_vector());
221 4 : }
222 :
223 26067 : TEST(RunCallF64Trunc) {
224 4 : BufferedRawMachineAssemblerTester<int32_t> m;
225 4 : ExternalReference ref = ExternalReference::wasm_f64_trunc();
226 : TestExternalReference_UnOp<double>(&m, ref, wasm::f64_trunc_wrapper,
227 4 : ValueHelper::float64_vector());
228 4 : }
229 :
230 26067 : TEST(RunCallF64Floor) {
231 4 : BufferedRawMachineAssemblerTester<int32_t> m;
232 4 : ExternalReference ref = ExternalReference::wasm_f64_floor();
233 : TestExternalReference_UnOp<double>(&m, ref, wasm::f64_floor_wrapper,
234 4 : ValueHelper::float64_vector());
235 4 : }
236 :
237 26067 : TEST(RunCallF64Ceil) {
238 4 : BufferedRawMachineAssemblerTester<int32_t> m;
239 4 : ExternalReference ref = ExternalReference::wasm_f64_ceil();
240 : TestExternalReference_UnOp<double>(&m, ref, wasm::f64_ceil_wrapper,
241 4 : ValueHelper::float64_vector());
242 4 : }
243 :
244 26067 : TEST(RunCallF64RoundTiesEven) {
245 4 : BufferedRawMachineAssemblerTester<int32_t> m;
246 4 : ExternalReference ref = ExternalReference::wasm_f64_nearest_int();
247 : TestExternalReference_UnOp<double>(&m, ref, wasm::f64_nearest_int_wrapper,
248 4 : ValueHelper::float64_vector());
249 4 : }
250 :
251 26067 : TEST(RunCallInt64ToFloat32) {
252 4 : BufferedRawMachineAssemblerTester<int32_t> m;
253 4 : ExternalReference ref = ExternalReference::wasm_int64_to_float32();
254 : TestExternalReference_ConvertOp<int64_t, float>(
255 4 : &m, ref, wasm::int64_to_float32_wrapper, ValueHelper::int64_vector());
256 4 : }
257 :
258 26067 : TEST(RunCallUint64ToFloat32) {
259 4 : BufferedRawMachineAssemblerTester<int32_t> m;
260 4 : ExternalReference ref = ExternalReference::wasm_uint64_to_float32();
261 : TestExternalReference_ConvertOp<uint64_t, float>(
262 4 : &m, ref, wasm::uint64_to_float32_wrapper, ValueHelper::uint64_vector());
263 4 : }
264 :
265 26067 : TEST(RunCallInt64ToFloat64) {
266 4 : BufferedRawMachineAssemblerTester<int32_t> m;
267 4 : ExternalReference ref = ExternalReference::wasm_int64_to_float64();
268 : TestExternalReference_ConvertOp<int64_t, double>(
269 4 : &m, ref, wasm::int64_to_float64_wrapper, ValueHelper::int64_vector());
270 4 : }
271 :
272 26067 : TEST(RunCallUint64ToFloat64) {
273 4 : BufferedRawMachineAssemblerTester<int32_t> m;
274 4 : ExternalReference ref = ExternalReference::wasm_uint64_to_float64();
275 : TestExternalReference_ConvertOp<uint64_t, double>(
276 4 : &m, ref, wasm::uint64_to_float64_wrapper, ValueHelper::uint64_vector());
277 4 : }
278 :
279 26067 : TEST(RunCallFloat32ToInt64) {
280 4 : BufferedRawMachineAssemblerTester<int32_t> m;
281 4 : ExternalReference ref = ExternalReference::wasm_float32_to_int64();
282 : TestExternalReference_ConvertOpWithOutputAndReturn<float, int64_t>(
283 4 : &m, ref, wasm::float32_to_int64_wrapper, ValueHelper::float32_vector());
284 4 : }
285 :
286 26067 : TEST(RunCallFloat32ToUint64) {
287 4 : BufferedRawMachineAssemblerTester<int32_t> m;
288 4 : ExternalReference ref = ExternalReference::wasm_float32_to_uint64();
289 : TestExternalReference_ConvertOpWithOutputAndReturn<float, uint64_t>(
290 4 : &m, ref, wasm::float32_to_uint64_wrapper, ValueHelper::float32_vector());
291 4 : }
292 :
293 26067 : TEST(RunCallFloat64ToInt64) {
294 4 : BufferedRawMachineAssemblerTester<int32_t> m;
295 4 : ExternalReference ref = ExternalReference::wasm_float64_to_int64();
296 : TestExternalReference_ConvertOpWithOutputAndReturn<double, int64_t>(
297 4 : &m, ref, wasm::float64_to_int64_wrapper, ValueHelper::float64_vector());
298 4 : }
299 :
300 26067 : TEST(RunCallFloat64ToUint64) {
301 4 : BufferedRawMachineAssemblerTester<int32_t> m;
302 4 : ExternalReference ref = ExternalReference::wasm_float64_to_uint64();
303 : TestExternalReference_ConvertOpWithOutputAndReturn<double, uint64_t>(
304 4 : &m, ref, wasm::float64_to_uint64_wrapper, ValueHelper::float64_vector());
305 4 : }
306 :
307 26067 : TEST(RunCallInt64Div) {
308 4 : BufferedRawMachineAssemblerTester<int32_t> m;
309 4 : ExternalReference ref = ExternalReference::wasm_int64_div();
310 : TestExternalReference_BinOpWithReturn<int64_t>(
311 4 : &m, ref, wasm::int64_div_wrapper, ValueHelper::int64_vector());
312 4 : }
313 :
314 26067 : TEST(RunCallInt64Mod) {
315 4 : BufferedRawMachineAssemblerTester<int32_t> m;
316 4 : ExternalReference ref = ExternalReference::wasm_int64_mod();
317 : TestExternalReference_BinOpWithReturn<int64_t>(
318 4 : &m, ref, wasm::int64_mod_wrapper, ValueHelper::int64_vector());
319 4 : }
320 :
321 26067 : TEST(RunCallUint64Div) {
322 4 : BufferedRawMachineAssemblerTester<int32_t> m;
323 4 : ExternalReference ref = ExternalReference::wasm_uint64_div();
324 : TestExternalReference_BinOpWithReturn<uint64_t>(
325 4 : &m, ref, wasm::uint64_div_wrapper, ValueHelper::uint64_vector());
326 4 : }
327 :
328 26067 : TEST(RunCallUint64Mod) {
329 4 : BufferedRawMachineAssemblerTester<int32_t> m;
330 4 : ExternalReference ref = ExternalReference::wasm_uint64_mod();
331 : TestExternalReference_BinOpWithReturn<uint64_t>(
332 4 : &m, ref, wasm::uint64_mod_wrapper, ValueHelper::uint64_vector());
333 4 : }
334 :
335 26067 : TEST(RunCallWord32Ctz) {
336 4 : BufferedRawMachineAssemblerTester<uint32_t> m;
337 4 : ExternalReference ref = ExternalReference::wasm_word32_ctz();
338 : TestExternalReference_ConvertOpWithReturn<int32_t, uint32_t>(
339 4 : &m, ref, wasm::word32_ctz_wrapper, ValueHelper::int32_vector());
340 4 : }
341 :
342 26067 : TEST(RunCallWord64Ctz) {
343 4 : BufferedRawMachineAssemblerTester<uint32_t> m;
344 4 : ExternalReference ref = ExternalReference::wasm_word64_ctz();
345 : TestExternalReference_ConvertOpWithReturn<int64_t, uint32_t>(
346 4 : &m, ref, wasm::word64_ctz_wrapper, ValueHelper::int64_vector());
347 4 : }
348 :
349 26067 : TEST(RunCallWord32Popcnt) {
350 4 : BufferedRawMachineAssemblerTester<uint32_t> m;
351 4 : ExternalReference ref = ExternalReference::wasm_word32_popcnt();
352 : TestExternalReference_ConvertOpWithReturn<uint32_t, uint32_t>(
353 4 : &m, ref, wasm::word32_popcnt_wrapper, ValueHelper::int32_vector());
354 4 : }
355 :
356 26067 : TEST(RunCallWord64Popcnt) {
357 4 : BufferedRawMachineAssemblerTester<uint32_t> m;
358 4 : ExternalReference ref = ExternalReference::wasm_word64_popcnt();
359 : TestExternalReference_ConvertOpWithReturn<int64_t, uint32_t>(
360 4 : &m, ref, wasm::word64_popcnt_wrapper, ValueHelper::int64_vector());
361 4 : }
362 :
363 26067 : TEST(RunCallFloat64Pow) {
364 4 : BufferedRawMachineAssemblerTester<int32_t> m;
365 4 : ExternalReference ref = ExternalReference::wasm_float64_pow();
366 : TestExternalReference_BinOp<double>(&m, ref, wasm::float64_pow_wrapper,
367 4 : ValueHelper::float64_vector());
368 4 : }
369 :
370 : } // namespace compiler
371 : } // namespace internal
372 78189 : } // namespace v8
|