1/*
2 * Copyright 2017 WebAssembly Community Group participants
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef wasm_literal_h
18#define wasm_literal_h
19
20#include <array>
21#include <iostream>
22#include <variant>
23
24#include "compiler-support.h"
25#include "support/hash.h"
26#include "support/name.h"
27#include "support/small_vector.h"
28#include "support/utilities.h"
29#include "wasm-type.h"
30
31namespace wasm {
32
33class Literals;
34struct GCData;
35
36class Literal {
37 // store only integers, whose bits are deterministic. floats
38 // can have their signalling bit set, for example.
39 union {
40 // Note: i31 is stored in the |i32| field, with the lower 31 bits containing
41 // the value if there is one, and the highest bit containing whether there
42 // is a value. Thus, a null is |i32 === 0|.
43 int32_t i32;
44 int64_t i64;
45 uint8_t v128[16];
46 // funcref function name. `isNull()` indicates a `null` value.
47 Name func;
48 // A reference to GC data, either a Struct or an Array. For both of those we
49 // store the referred data as a Literals object (which is natural for an
50 // Array, and for a Struct, is just the fields in order). The type is used
51 // to indicate whether this is a Struct or an Array, and of what type. We
52 // also use this to store String data, as it is similarly stored on the
53 // heap. For externrefs, the gcData is the same as for the corresponding
54 // internal references and the values are only differentiated by the type.
55 // Externalized i31 references have a gcData containing the internal i31
56 // reference as its sole value even though internal i31 references do not
57 // have a gcData.
58 std::shared_ptr<GCData> gcData;
59 };
60
61public:
62 // Type of the literal. Immutable because the literal's payload depends on it.
63 const Type type;
64
65 Literal() : v128(), type(Type::none) {}
66 explicit Literal(Type type);
67 explicit Literal(Type::BasicType type) : Literal(Type(type)) {}
68 explicit Literal(int32_t init) : i32(init), type(Type::i32) {}
69 explicit Literal(uint32_t init) : i32(init), type(Type::i32) {}
70 explicit Literal(int64_t init) : i64(init), type(Type::i64) {}
71 explicit Literal(uint64_t init) : i64(init), type(Type::i64) {}
72 explicit Literal(float init)
73 : i32(bit_cast<int32_t>(init)), type(Type::f32) {}
74 explicit Literal(double init)
75 : i64(bit_cast<int64_t>(init)), type(Type::f64) {}
76 // v128 literal from bytes
77 explicit Literal(const uint8_t init[16]);
78 // v128 literal from lane value literals
79 explicit Literal(const std::array<Literal, 16>&);
80 explicit Literal(const std::array<Literal, 8>&);
81 explicit Literal(const std::array<Literal, 4>&);
82 explicit Literal(const std::array<Literal, 2>&);
83 explicit Literal(Name func, HeapType type)
84 : func(func), type(type, NonNullable) {
85 assert(type.isSignature());
86 }
87 explicit Literal(std::shared_ptr<GCData> gcData, HeapType type);
88 explicit Literal(std::string string);
89 Literal(const Literal& other);
90 Literal& operator=(const Literal& other);
91 ~Literal();
92
93 bool isConcrete() const { return type.isConcrete(); }
94 bool isNone() const { return type == Type::none; }
95 bool isFunction() const { return type.isFunction(); }
96 // Whether this is GC data, that is, something stored on the heap (aside from
97 // a null or i31). This includes structs, arrays, and also strings.
98 bool isData() const { return type.isData(); }
99 bool isString() const { return type.isString(); }
100
101 bool isNull() const { return type.isNull(); }
102
103 bool isZero() const {
104 switch (type.getBasic()) {
105 case Type::i32:
106 return i32 == 0;
107 case Type::i64:
108 return i64 == 0LL;
109 case Type::f32:
110 return bit_cast<float>(i32) == 0.0f;
111 case Type::f64:
112 return bit_cast<double>(i64) == 0.0;
113 case Type::v128: {
114 uint8_t zeros[16] = {0};
115 return memcmp(&v128, zeros, 16) == 0;
116 }
117 default:
118 WASM_UNREACHABLE("unexpected type");
119 }
120 }
121 bool isNegative() const {
122 switch (type.getBasic()) {
123 case Type::i32:
124 case Type::f32:
125 return i32 < 0;
126 case Type::i64:
127 case Type::f64:
128 return i64 < 0;
129 default:
130 WASM_UNREACHABLE("unexpected type");
131 }
132 }
133 bool isSignedMin() const {
134 switch (type.getBasic()) {
135 case Type::i32:
136 return i32 == std::numeric_limits<int32_t>::min();
137 case Type::i64:
138 return i64 == std::numeric_limits<int64_t>::min();
139 default:
140 WASM_UNREACHABLE("unexpected type");
141 }
142 }
143 bool isSignedMax() const {
144 switch (type.getBasic()) {
145 case Type::i32:
146 return i32 == std::numeric_limits<int32_t>::max();
147 case Type::i64:
148 return i64 == std::numeric_limits<int64_t>::max();
149 default:
150 WASM_UNREACHABLE("unexpected type");
151 }
152 }
153 bool isUnsignedMax() const {
154 switch (type.getBasic()) {
155 case Type::i32:
156 return uint32_t(i32) == std::numeric_limits<uint32_t>::max();
157 case Type::i64:
158 return uint64_t(i64) == std::numeric_limits<uint64_t>::max();
159 default:
160 WASM_UNREACHABLE("unexpected type");
161 }
162 }
163
164 static Literals makeZeros(Type type);
165 static Literals makeOnes(Type type);
166 static Literals makeNegOnes(Type type);
167 static Literal makeZero(Type type);
168 static Literal makeOne(Type type);
169 static Literal makeNegOne(Type type);
170 static Literal makeFromInt32(int32_t x, Type type) {
171 switch (type.getBasic()) {
172 case Type::i32:
173 return Literal(int32_t(x));
174 case Type::i64:
175 return Literal(int64_t(x));
176 case Type::f32:
177 return Literal(float(x));
178 case Type::f64:
179 return Literal(double(x));
180 case Type::v128:
181 return Literal(std::array<Literal, 4>{{Literal(x),
182 Literal(int32_t(0)),
183 Literal(int32_t(0)),
184 Literal(int32_t(0))}});
185 default:
186 WASM_UNREACHABLE("unexpected type");
187 }
188 }
189 static Literal makeFromInt64(int64_t x, Type type) {
190 switch (type.getBasic()) {
191 case Type::i32:
192 return Literal(int32_t(x));
193 case Type::i64:
194 return Literal(int64_t(x));
195 case Type::f32:
196 return Literal(float(x));
197 case Type::f64:
198 return Literal(double(x));
199 case Type::v128:
200 return Literal(
201 std::array<Literal, 2>{{Literal(x), Literal(int64_t(0))}});
202 default:
203 WASM_UNREACHABLE("unexpected type");
204 }
205 }
206
207 static Literal makeFromMemory(void* p, Type type);
208 static Literal makeFromMemory(void* p, const Field& field);
209
210 static Literal makeSignedMin(Type type) {
211 switch (type.getBasic()) {
212 case Type::i32:
213 return Literal(std::numeric_limits<int32_t>::min());
214 case Type::i64:
215 return Literal(std::numeric_limits<int64_t>::min());
216 default:
217 WASM_UNREACHABLE("unexpected type");
218 }
219 }
220 static Literal makeSignedMax(Type type) {
221 switch (type.getBasic()) {
222 case Type::i32:
223 return Literal(std::numeric_limits<int32_t>::max());
224 case Type::i64:
225 return Literal(std::numeric_limits<int64_t>::max());
226 default:
227 WASM_UNREACHABLE("unexpected type");
228 }
229 }
230 static Literal makeUnsignedMax(Type type) {
231 switch (type.getBasic()) {
232 case Type::i32:
233 return Literal(std::numeric_limits<uint32_t>::max());
234 case Type::i64:
235 return Literal(std::numeric_limits<uint64_t>::max());
236 default:
237 WASM_UNREACHABLE("unexpected type");
238 }
239 }
240 static Literal makeNull(HeapType type) {
241 return Literal(Type(type.getBottom(), Nullable));
242 }
243 static Literal makeFunc(Name func, HeapType type) {
244 return Literal(func, type);
245 }
246 static Literal makeI31(int32_t value) {
247 auto lit = Literal(Type(HeapType::i31, NonNullable));
248 lit.i32 = value | 0x80000000;
249 return lit;
250 }
251 // Wasm has nondeterministic rules for NaN propagation in some operations. For
252 // example. f32.neg is deterministic and just flips the sign, even of a NaN,
253 // but f32.add is nondeterministic, and if one or more of the inputs is a NaN,
254 // then
255 //
256 // * if all NaNs are canonical, the output is some arbitrary canonical NaN
257 // * otherwise the output is some arbitrary arithmetic NaN
258 //
259 // (canonical = NaN payload is 1000..000; arithmetic: 1???..???, that is, the
260 // high bit is 1 and all others can be 0 or 1)
261 //
262 // For many things we don't need to care, and can just do a normal C++ add for
263 // an f32.add, for example - the wasm rules are specified so that things like
264 // that just work (in order for such math to be fast). However, for our
265 // optimizer, it is useful to "standardize" NaNs when there is nondeterminism.
266 // That is, when there are multiple valid outputs, it's nice to emit the same
267 // one consistently, so that it doesn't look like the optimization changed
268 // something. In other words, if the valid output of an expression is a set of
269 // valid NaNs, and after optimization the output is still that same set, then
270 // the optimization is valid. And if the interpreter picks the same NaN in
271 // both cases from that identical set then nothing looks wrong to the fuzzer.
272 static Literal standardizeNaN(const Literal& input);
273
274 Literal castToF32();
275 Literal castToF64();
276 Literal castToI32();
277 Literal castToI64();
278
279 int32_t geti32() const {
280 assert(type == Type::i32);
281 return i32;
282 }
283 int32_t geti31(bool signed_ = true) const {
284 assert(type.getHeapType() == HeapType::i31);
285 // Cast to unsigned for the left shift to avoid undefined behavior.
286 return signed_ ? int32_t((uint32_t(i32) << 1)) >> 1 : (i32 & 0x7fffffff);
287 }
288 int64_t geti64() const {
289 assert(type == Type::i64);
290 return i64;
291 }
292 float getf32() const {
293 assert(type == Type::f32);
294 return bit_cast<float>(i32);
295 }
296 double getf64() const {
297 assert(type == Type::f64);
298 return bit_cast<double>(i64);
299 }
300 std::array<uint8_t, 16> getv128() const;
301 Name getFunc() const {
302 assert(type.isFunction() && !func.isNull());
303 return func;
304 }
305 std::shared_ptr<GCData> getGCData() const;
306
307 // careful!
308 int32_t* geti32Ptr() {
309 assert(type == Type::i32);
310 return &i32;
311 }
312 uint8_t* getv128Ptr() {
313 assert(type == Type::v128);
314 return v128;
315 }
316 const uint8_t* getv128Ptr() const {
317 assert(type == Type::v128);
318 return v128;
319 }
320
321 int32_t reinterpreti32() const {
322 assert(type == Type::f32);
323 return i32;
324 }
325 int64_t reinterpreti64() const {
326 assert(type == Type::f64);
327 return i64;
328 }
329 float reinterpretf32() const {
330 assert(type == Type::i32);
331 return bit_cast<float>(i32);
332 }
333 double reinterpretf64() const {
334 assert(type == Type::i64);
335 return bit_cast<double>(i64);
336 }
337
338 int64_t getInteger() const;
339 uint64_t getUnsigned() const;
340 double getFloat() const;
341 // Obtains the bits of a basic value typed literal.
342 void getBits(uint8_t (&buf)[16]) const;
343 // Equality checks for the type and the bits, so a nan float would
344 // be compared bitwise (which means that a Literal containing a nan
345 // would be equal to itself, if the bits are equal).
346 bool operator==(const Literal& other) const;
347 bool operator!=(const Literal& other) const;
348
349 bool isNaN();
350
351 static uint32_t NaNPayload(float f);
352 static uint64_t NaNPayload(double f);
353 static float setQuietNaN(float f);
354 static double setQuietNaN(double f);
355
356 static void printFloat(std::ostream& o, float f);
357 static void printDouble(std::ostream& o, double d);
358 static void printVec128(std::ostream& o, const std::array<uint8_t, 16>& v);
359
360 Literal countLeadingZeroes() const;
361 Literal countTrailingZeroes() const;
362 Literal popCount() const;
363
364 Literal extendToSI64() const;
365 Literal extendToUI64() const;
366 Literal extendToF64() const;
367 Literal extendS8() const;
368 Literal extendS16() const;
369 Literal extendS32() const;
370 Literal wrapToI32() const;
371
372 Literal convertSIToF32() const;
373 Literal convertUIToF32() const;
374 Literal convertSIToF64() const;
375 Literal convertUIToF64() const;
376
377 Literal truncSatToSI32() const;
378 Literal truncSatToSI64() const;
379 Literal truncSatToUI32() const;
380 Literal truncSatToUI64() const;
381
382 Literal eqz() const;
383 Literal neg() const;
384 Literal abs() const;
385 Literal ceil() const;
386 Literal floor() const;
387 Literal trunc() const;
388 Literal nearbyint() const;
389 Literal sqrt() const;
390 Literal demote() const;
391
392 Literal add(const Literal& other) const;
393 Literal sub(const Literal& other) const;
394 Literal mul(const Literal& other) const;
395 Literal div(const Literal& other) const;
396 Literal divS(const Literal& other) const;
397 Literal divU(const Literal& other) const;
398 Literal remS(const Literal& other) const;
399 Literal remU(const Literal& other) const;
400 Literal and_(const Literal& other) const;
401 Literal or_(const Literal& other) const;
402 Literal xor_(const Literal& other) const;
403 Literal shl(const Literal& other) const;
404 Literal shrS(const Literal& other) const;
405 Literal shrU(const Literal& other) const;
406 Literal rotL(const Literal& other) const;
407 Literal rotR(const Literal& other) const;
408
409 // Note that these functions perform equality checks based
410 // on the type of the literal, so that (unlike the == operator)
411 // a float nan would not be identical to itself.
412 Literal eq(const Literal& other) const;
413 Literal ne(const Literal& other) const;
414 Literal ltS(const Literal& other) const;
415 Literal ltU(const Literal& other) const;
416 Literal lt(const Literal& other) const;
417 Literal leS(const Literal& other) const;
418 Literal leU(const Literal& other) const;
419 Literal le(const Literal& other) const;
420
421 Literal gtS(const Literal& other) const;
422 Literal gtU(const Literal& other) const;
423 Literal gt(const Literal& other) const;
424 Literal geS(const Literal& other) const;
425 Literal geU(const Literal& other) const;
426 Literal ge(const Literal& other) const;
427
428 Literal min(const Literal& other) const;
429 Literal max(const Literal& other) const;
430 Literal pmin(const Literal& other) const;
431 Literal pmax(const Literal& other) const;
432 Literal copysign(const Literal& other) const;
433
434 // Fused multiply add and subtract.
435 // Computes this + (left * right) to infinite precision then round once.
436 Literal fma(const Literal& left, const Literal& right) const;
437 Literal fms(const Literal& left, const Literal& right) const;
438
439 std::array<Literal, 16> getLanesSI8x16() const;
440 std::array<Literal, 16> getLanesUI8x16() const;
441 std::array<Literal, 8> getLanesSI16x8() const;
442 std::array<Literal, 8> getLanesUI16x8() const;
443 std::array<Literal, 4> getLanesI32x4() const;
444 std::array<Literal, 2> getLanesI64x2() const;
445 std::array<Literal, 4> getLanesF32x4() const;
446 std::array<Literal, 2> getLanesF64x2() const;
447
448 Literal shuffleV8x16(const Literal& other,
449 const std::array<uint8_t, 16>& mask) const;
450 Literal splatI8x16() const;
451 Literal extractLaneSI8x16(uint8_t index) const;
452 Literal extractLaneUI8x16(uint8_t index) const;
453 Literal replaceLaneI8x16(const Literal& other, uint8_t index) const;
454 Literal splatI16x8() const;
455 Literal extractLaneSI16x8(uint8_t index) const;
456 Literal extractLaneUI16x8(uint8_t index) const;
457 Literal replaceLaneI16x8(const Literal& other, uint8_t index) const;
458 Literal splatI32x4() const;
459 Literal extractLaneI32x4(uint8_t index) const;
460 Literal replaceLaneI32x4(const Literal& other, uint8_t index) const;
461 Literal splatI64x2() const;
462 Literal extractLaneI64x2(uint8_t index) const;
463 Literal replaceLaneI64x2(const Literal& other, uint8_t index) const;
464 Literal splatF32x4() const;
465 Literal extractLaneF32x4(uint8_t index) const;
466 Literal replaceLaneF32x4(const Literal& other, uint8_t index) const;
467 Literal splatF64x2() const;
468 Literal extractLaneF64x2(uint8_t index) const;
469 Literal replaceLaneF64x2(const Literal& other, uint8_t index) const;
470 Literal eqI8x16(const Literal& other) const;
471 Literal neI8x16(const Literal& other) const;
472 Literal ltSI8x16(const Literal& other) const;
473 Literal ltUI8x16(const Literal& other) const;
474 Literal gtSI8x16(const Literal& other) const;
475 Literal gtUI8x16(const Literal& other) const;
476 Literal leSI8x16(const Literal& other) const;
477 Literal leUI8x16(const Literal& other) const;
478 Literal geSI8x16(const Literal& other) const;
479 Literal geUI8x16(const Literal& other) const;
480 Literal eqI16x8(const Literal& other) const;
481 Literal neI16x8(const Literal& other) const;
482 Literal ltSI16x8(const Literal& other) const;
483 Literal ltUI16x8(const Literal& other) const;
484 Literal gtSI16x8(const Literal& other) const;
485 Literal gtUI16x8(const Literal& other) const;
486 Literal leSI16x8(const Literal& other) const;
487 Literal leUI16x8(const Literal& other) const;
488 Literal geSI16x8(const Literal& other) const;
489 Literal geUI16x8(const Literal& other) const;
490 Literal eqI32x4(const Literal& other) const;
491 Literal neI32x4(const Literal& other) const;
492 Literal ltSI32x4(const Literal& other) const;
493 Literal ltUI32x4(const Literal& other) const;
494 Literal gtSI32x4(const Literal& other) const;
495 Literal gtUI32x4(const Literal& other) const;
496 Literal leSI32x4(const Literal& other) const;
497 Literal leUI32x4(const Literal& other) const;
498 Literal geSI32x4(const Literal& other) const;
499 Literal geUI32x4(const Literal& other) const;
500 Literal eqI64x2(const Literal& other) const;
501 Literal neI64x2(const Literal& other) const;
502 Literal ltSI64x2(const Literal& other) const;
503 Literal gtSI64x2(const Literal& other) const;
504 Literal leSI64x2(const Literal& other) const;
505 Literal geSI64x2(const Literal& other) const;
506 Literal eqF32x4(const Literal& other) const;
507 Literal neF32x4(const Literal& other) const;
508 Literal ltF32x4(const Literal& other) const;
509 Literal gtF32x4(const Literal& other) const;
510 Literal leF32x4(const Literal& other) const;
511 Literal geF32x4(const Literal& other) const;
512 Literal eqF64x2(const Literal& other) const;
513 Literal neF64x2(const Literal& other) const;
514 Literal ltF64x2(const Literal& other) const;
515 Literal gtF64x2(const Literal& other) const;
516 Literal leF64x2(const Literal& other) const;
517 Literal geF64x2(const Literal& other) const;
518 Literal notV128() const;
519 Literal andV128(const Literal& other) const;
520 Literal orV128(const Literal& other) const;
521 Literal xorV128(const Literal& other) const;
522 Literal anyTrueV128() const;
523 Literal bitselectV128(const Literal& left, const Literal& right) const;
524 Literal absI8x16() const;
525 Literal negI8x16() const;
526 Literal allTrueI8x16() const;
527 Literal bitmaskI8x16() const;
528 Literal shlI8x16(const Literal& other) const;
529 Literal shrSI8x16(const Literal& other) const;
530 Literal shrUI8x16(const Literal& other) const;
531 Literal addI8x16(const Literal& other) const;
532 Literal addSaturateSI8x16(const Literal& other) const;
533 Literal addSaturateUI8x16(const Literal& other) const;
534 Literal subI8x16(const Literal& other) const;
535 Literal subSaturateSI8x16(const Literal& other) const;
536 Literal subSaturateUI8x16(const Literal& other) const;
537 Literal minSI8x16(const Literal& other) const;
538 Literal minUI8x16(const Literal& other) const;
539 Literal maxSI8x16(const Literal& other) const;
540 Literal maxUI8x16(const Literal& other) const;
541 Literal avgrUI8x16(const Literal& other) const;
542 Literal popcntI8x16() const;
543 Literal absI16x8() const;
544 Literal negI16x8() const;
545 Literal allTrueI16x8() const;
546 Literal bitmaskI16x8() const;
547 Literal shlI16x8(const Literal& other) const;
548 Literal shrSI16x8(const Literal& other) const;
549 Literal shrUI16x8(const Literal& other) const;
550 Literal addI16x8(const Literal& other) const;
551 Literal addSaturateSI16x8(const Literal& other) const;
552 Literal addSaturateUI16x8(const Literal& other) const;
553 Literal subI16x8(const Literal& other) const;
554 Literal subSaturateSI16x8(const Literal& other) const;
555 Literal subSaturateUI16x8(const Literal& other) const;
556 Literal mulI16x8(const Literal& other) const;
557 Literal minSI16x8(const Literal& other) const;
558 Literal minUI16x8(const Literal& other) const;
559 Literal maxSI16x8(const Literal& other) const;
560 Literal maxUI16x8(const Literal& other) const;
561 Literal avgrUI16x8(const Literal& other) const;
562 Literal q15MulrSatSI16x8(const Literal& other) const;
563 Literal extMulLowSI16x8(const Literal& other) const;
564 Literal extMulHighSI16x8(const Literal& other) const;
565 Literal extMulLowUI16x8(const Literal& other) const;
566 Literal extMulHighUI16x8(const Literal& other) const;
567 Literal absI32x4() const;
568 Literal negI32x4() const;
569 Literal allTrueI32x4() const;
570 Literal bitmaskI32x4() const;
571 Literal shlI32x4(const Literal& other) const;
572 Literal shrSI32x4(const Literal& other) const;
573 Literal shrUI32x4(const Literal& other) const;
574 Literal addI32x4(const Literal& other) const;
575 Literal subI32x4(const Literal& other) const;
576 Literal mulI32x4(const Literal& other) const;
577 Literal minSI32x4(const Literal& other) const;
578 Literal minUI32x4(const Literal& other) const;
579 Literal maxSI32x4(const Literal& other) const;
580 Literal maxUI32x4(const Literal& other) const;
581 Literal dotSI8x16toI16x8(const Literal& other) const;
582 Literal dotUI8x16toI16x8(const Literal& other) const;
583 Literal dotSI16x8toI32x4(const Literal& other) const;
584 Literal extMulLowSI32x4(const Literal& other) const;
585 Literal extMulHighSI32x4(const Literal& other) const;
586 Literal extMulLowUI32x4(const Literal& other) const;
587 Literal extMulHighUI32x4(const Literal& other) const;
588 Literal absI64x2() const;
589 Literal negI64x2() const;
590 Literal bitmaskI64x2() const;
591 Literal allTrueI64x2() const;
592 Literal shlI64x2(const Literal& other) const;
593 Literal shrSI64x2(const Literal& other) const;
594 Literal shrUI64x2(const Literal& other) const;
595 Literal addI64x2(const Literal& other) const;
596 Literal subI64x2(const Literal& other) const;
597 Literal mulI64x2(const Literal& other) const;
598 Literal extMulLowSI64x2(const Literal& other) const;
599 Literal extMulHighSI64x2(const Literal& other) const;
600 Literal extMulLowUI64x2(const Literal& other) const;
601 Literal extMulHighUI64x2(const Literal& other) const;
602 Literal absF32x4() const;
603 Literal negF32x4() const;
604 Literal sqrtF32x4() const;
605 Literal addF32x4(const Literal& other) const;
606 Literal subF32x4(const Literal& other) const;
607 Literal mulF32x4(const Literal& other) const;
608 Literal divF32x4(const Literal& other) const;
609 Literal minF32x4(const Literal& other) const;
610 Literal maxF32x4(const Literal& other) const;
611 Literal pminF32x4(const Literal& other) const;
612 Literal pmaxF32x4(const Literal& other) const;
613 Literal ceilF32x4() const;
614 Literal floorF32x4() const;
615 Literal truncF32x4() const;
616 Literal nearestF32x4() const;
617 Literal absF64x2() const;
618 Literal negF64x2() const;
619 Literal sqrtF64x2() const;
620 Literal addF64x2(const Literal& other) const;
621 Literal subF64x2(const Literal& other) const;
622 Literal mulF64x2(const Literal& other) const;
623 Literal divF64x2(const Literal& other) const;
624 Literal minF64x2(const Literal& other) const;
625 Literal maxF64x2(const Literal& other) const;
626 Literal pminF64x2(const Literal& other) const;
627 Literal pmaxF64x2(const Literal& other) const;
628 Literal ceilF64x2() const;
629 Literal floorF64x2() const;
630 Literal truncF64x2() const;
631 Literal nearestF64x2() const;
632 Literal extAddPairwiseToSI16x8() const;
633 Literal extAddPairwiseToUI16x8() const;
634 Literal extAddPairwiseToSI32x4() const;
635 Literal extAddPairwiseToUI32x4() const;
636 Literal truncSatToSI32x4() const;
637 Literal truncSatToUI32x4() const;
638 Literal convertSToF32x4() const;
639 Literal convertUToF32x4() const;
640 Literal narrowSToI8x16(const Literal& other) const;
641 Literal narrowUToI8x16(const Literal& other) const;
642 Literal narrowSToI16x8(const Literal& other) const;
643 Literal narrowUToI16x8(const Literal& other) const;
644 Literal extendLowSToI16x8() const;
645 Literal extendHighSToI16x8() const;
646 Literal extendLowUToI16x8() const;
647 Literal extendHighUToI16x8() const;
648 Literal extendLowSToI32x4() const;
649 Literal extendHighSToI32x4() const;
650 Literal extendLowUToI32x4() const;
651 Literal extendHighUToI32x4() const;
652 Literal extendLowSToI64x2() const;
653 Literal extendHighSToI64x2() const;
654 Literal extendLowUToI64x2() const;
655 Literal extendHighUToI64x2() const;
656 Literal convertLowSToF64x2() const;
657 Literal convertLowUToF64x2() const;
658 Literal truncSatZeroSToI32x4() const;
659 Literal truncSatZeroUToI32x4() const;
660 Literal demoteZeroToF32x4() const;
661 Literal promoteLowToF64x2() const;
662 Literal swizzleI8x16(const Literal& other) const;
663 Literal relaxedFmaF32x4(const Literal& left, const Literal& right) const;
664 Literal relaxedFmsF32x4(const Literal& left, const Literal& right) const;
665 Literal relaxedFmaF64x2(const Literal& left, const Literal& right) const;
666 Literal relaxedFmsF64x2(const Literal& left, const Literal& right) const;
667
668 Literal externalize() const;
669 Literal internalize() const;
670
671private:
672 Literal addSatSI8(const Literal& other) const;
673 Literal addSatUI8(const Literal& other) const;
674 Literal addSatSI16(const Literal& other) const;
675 Literal addSatUI16(const Literal& other) const;
676 Literal subSatSI8(const Literal& other) const;
677 Literal subSatUI8(const Literal& other) const;
678 Literal subSatSI16(const Literal& other) const;
679 Literal subSatUI16(const Literal& other) const;
680 Literal q15MulrSatSI16(const Literal& other) const;
681 Literal minInt(const Literal& other) const;
682 Literal maxInt(const Literal& other) const;
683 Literal minUInt(const Literal& other) const;
684 Literal maxUInt(const Literal& other) const;
685 Literal avgrUInt(const Literal& other) const;
686};
687
688class Literals : public SmallVector<Literal, 1> {
689public:
690 Literals() = default;
691 Literals(std::initializer_list<Literal> init)
692 : SmallVector<Literal, 1>(init) {
693#ifndef NDEBUG
694 for (auto& lit : init) {
695 assert(lit.isConcrete());
696 }
697#endif
698 }
699 Literals(size_t initialSize) : SmallVector(initialSize) {}
700
701 Type getType() {
702 if (empty()) {
703 return Type::none;
704 }
705 if (size() == 1) {
706 return (*this)[0].type;
707 }
708 std::vector<Type> types;
709 for (auto& val : *this) {
710 types.push_back(val.type);
711 }
712 return Type(types);
713 }
714 bool isNone() { return size() == 0; }
715 bool isConcrete() { return size() != 0; }
716};
717
718std::ostream& operator<<(std::ostream& o, wasm::Literal literal);
719std::ostream& operator<<(std::ostream& o, wasm::Literals literals);
720
721// A GC Struct, Array, or String is a set of values with a type saying how it
722// should be interpreted.
723struct GCData {
724 // The type of this struct, array, or string.
725 HeapType type;
726
727 // The element or field values.
728 Literals values;
729
730 GCData(HeapType type, Literals values) : type(type), values(values) {}
731};
732
733} // namespace wasm
734
735namespace std {
736template<> struct hash<wasm::Literal> {
737 size_t operator()(const wasm::Literal& a) const {
738 auto digest = wasm::hash(a.type);
739 if (a.type.isBasic()) {
740 switch (a.type.getBasic()) {
741 case wasm::Type::i32:
742 wasm::rehash(digest, a.geti32());
743 return digest;
744 case wasm::Type::f32:
745 wasm::rehash(digest, a.reinterpreti32());
746 return digest;
747 case wasm::Type::i64:
748 wasm::rehash(digest, a.geti64());
749 return digest;
750 case wasm::Type::f64:
751 wasm::rehash(digest, a.reinterpreti64());
752 return digest;
753 case wasm::Type::v128:
754 uint64_t chunks[2];
755 memcpy(&chunks, a.getv128Ptr(), 16);
756 wasm::rehash(digest, chunks[0]);
757 wasm::rehash(digest, chunks[1]);
758 return digest;
759 case wasm::Type::none:
760 case wasm::Type::unreachable:
761 break;
762 }
763 } else if (a.type.isRef()) {
764 if (a.isNull()) {
765 return digest;
766 }
767 if (a.type.isFunction()) {
768 wasm::rehash(digest, a.getFunc());
769 return digest;
770 }
771 if (a.type.getHeapType() == wasm::HeapType::i31) {
772 wasm::rehash(digest, a.geti31(true));
773 return digest;
774 }
775 if (a.type.isString()) {
776 auto& values = a.getGCData()->values;
777 wasm::rehash(digest, values.size());
778 for (auto c : values) {
779 wasm::rehash(digest, c.getInteger());
780 }
781 return digest;
782 }
783 // other non-null reference type literals cannot represent concrete
784 // values, i.e. there is no concrete anyref or eqref other than null.
785 WASM_UNREACHABLE("unexpected type");
786 }
787 WASM_UNREACHABLE("unexpected type");
788 }
789};
790template<> struct hash<wasm::Literals> {
791 size_t operator()(const wasm::Literals& a) const {
792 auto digest = wasm::hash(a.size());
793 for (const auto& lit : a) {
794 wasm::rehash(digest, lit);
795 }
796 return digest;
797 }
798};
799
800} // namespace std
801
802#endif // wasm_literal_h
803

source code of dart_sdk/third_party/binaryen/src/src/literal.h