2 * Copyright 2016 WebAssembly Community Group participants
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "wabt/literal.h"
26 #include <type_traits>
33 struct FloatTraitsBase
{};
35 // The "PlusOne" values are used because normal IEEE floats have an implicit
36 // leading one, so they have an additional bit of precision.
39 struct FloatTraitsBase
<float> {
40 using Uint
= uint32_t;
41 static constexpr int kBits
= sizeof(Uint
) * 8;
42 static constexpr int kSigBits
= 23;
43 static constexpr float kHugeVal
= HUGE_VALF
;
44 static constexpr int kMaxHexBufferSize
= WABT_MAX_FLOAT_HEX
;
46 static float Strto(const char* s
, char** endptr
) { return strtof(s
, endptr
); }
50 struct FloatTraitsBase
<double> {
51 using Uint
= uint64_t;
52 static constexpr int kBits
= sizeof(Uint
) * 8;
53 static constexpr int kSigBits
= 52;
54 static constexpr float kHugeVal
= HUGE_VAL
;
55 static constexpr int kMaxHexBufferSize
= WABT_MAX_DOUBLE_HEX
;
57 static double Strto(const char* s
, char** endptr
) {
58 return strtod(s
, endptr
);
63 struct FloatTraits
: FloatTraitsBase
<T
> {
64 using Uint
= typename FloatTraitsBase
<T
>::Uint
;
65 using FloatTraitsBase
<T
>::kBits
;
66 using FloatTraitsBase
<T
>::kSigBits
;
68 static constexpr int kExpBits
= kBits
- kSigBits
- 1;
69 static constexpr int kSignShift
= kBits
- 1;
70 static constexpr Uint kSigMask
= (Uint(1) << kSigBits
) - 1;
71 static constexpr int kSigPlusOneBits
= kSigBits
+ 1;
72 static constexpr Uint kSigPlusOneMask
= (Uint(1) << kSigPlusOneBits
) - 1;
73 static constexpr int kExpMask
= (1 << kExpBits
) - 1;
74 static constexpr int kMaxExp
= 1 << (kExpBits
- 1);
75 static constexpr int kMinExp
= -kMaxExp
+ 1;
76 static constexpr int kExpBias
= -kMinExp
;
77 static constexpr Uint kQuietNanTag
= Uint(1) << (kSigBits
- 1);
83 using Traits
= FloatTraits
<T
>;
84 using Uint
= typename
Traits::Uint
;
87 static Result
Parse(LiteralType
,
93 static bool StringStartsWith(const char* start
,
96 static Uint
Make(bool sign
, int exp
, Uint sig
);
97 static Uint
ShiftAndRoundToNearest(Uint significand
,
99 bool seen_trailing_non_zero
);
101 static Result
ParseFloat(const char* s
, const char* end
, Uint
* out_bits
);
102 static Result
ParseNan(const char* s
, const char* end
, Uint
* out_bits
);
103 static Result
ParseHex(const char* s
, const char* end
, Uint
* out_bits
);
104 static void ParseInfinity(const char* s
, const char* end
, Uint
* out_bits
);
107 template <typename T
>
110 using Traits
= FloatTraits
<T
>;
111 using Uint
= typename
Traits::Uint
;
113 static void WriteHex(char* out
, size_t size
, Uint bits
);
116 // Return 1 if the non-NULL-terminated string starting with |start| and ending
117 // with |end| starts with the NULL-terminated string |prefix|.
118 template <typename T
>
120 bool FloatParser
<T
>::StringStartsWith(const char* start
,
122 const char* prefix
) {
123 while (start
< end
&& *prefix
) {
124 if (*start
!= *prefix
) {
134 template <typename T
>
135 Result FloatParser
<T
>::ParseFloat(const char* s
,
138 // Here is the normal behavior for strtof/strtod:
140 // input | errno | output |
141 // ---------------------------------
142 // overflow | ERANGE | +-HUGE_VAL |
143 // underflow | ERANGE | 0.0 |
144 // otherwise | 0 | value |
146 // So normally we need to clear errno before calling strto{f,d}, and check
147 // afterward whether it was set to ERANGE.
149 // glibc seems to have a bug where
150 // strtof("340282356779733661637539395458142568448") will return HUGE_VAL,
151 // but will not set errno to ERANGE. Since this function is only called when
152 // we know that we have parsed a "normal" number (i.e. not "inf"), we know
153 // that if we ever get HUGE_VAL, it must be overflow.
155 // The WebAssembly spec also ignores underflow, so we don't need to check for
158 // WebAssembly floats can contain underscores, but strto* can't parse those,
159 // so remove them first.
161 const size_t kBufferSize
= end
- s
+ 1; // +1 for \0.
162 char* buffer
= static_cast<char*>(alloca(kBufferSize
));
164 std::copy_if(s
, end
, buffer
, [](char c
) -> bool { return c
!= '_'; });
165 assert(buffer_end
< buffer
+ kBufferSize
);
169 Float value
= Traits::Strto(buffer
, &endptr
);
170 if (endptr
!= buffer_end
||
171 (value
== Traits::kHugeVal
|| value
== -Traits::kHugeVal
)) {
172 return Result::Error
;
175 memcpy(out_bits
, &value
, sizeof(value
));
180 template <typename T
>
181 typename FloatParser
<T
>::Uint FloatParser
<T
>::Make(bool sign
,
184 assert(exp
>= Traits::kMinExp
&& exp
<= Traits::kMaxExp
);
185 assert(sig
<= Traits::kSigMask
);
186 return (Uint(sign
) << Traits::kSignShift
) |
187 (Uint(exp
+ Traits::kExpBias
) << Traits::kSigBits
) | sig
;
191 template <typename T
>
192 typename FloatParser
<T
>::Uint FloatParser
<T
>::ShiftAndRoundToNearest(
195 bool seen_trailing_non_zero
) {
197 // Round ties to even.
198 if ((significand
& (Uint(1) << shift
)) || seen_trailing_non_zero
) {
199 significand
+= Uint(1) << (shift
- 1);
201 significand
>>= shift
;
206 template <typename T
>
207 Result FloatParser
<T
>::ParseNan(const char* s
,
214 } else if (*s
== '+') {
217 assert(StringStartsWith(s
, end
, "nan"));
223 assert(StringStartsWith(s
, end
, ":0x"));
226 for (; s
< end
; ++s
) {
231 CHECK_RESULT(ParseHexdigit(*s
, &digit
));
232 tag
= tag
* 16 + digit
;
233 // Check for overflow.
234 if (tag
> Traits::kSigMask
) {
235 return Result::Error
;
239 // NaN cannot have a zero tag, that is reserved for infinity.
241 return Result::Error
;
244 tag
= Traits::kQuietNanTag
;
247 *out_bits
= Make(is_neg
, Traits::kMaxExp
, tag
);
252 template <typename T
>
253 Result FloatParser
<T
>::ParseHex(const char* s
,
260 } else if (*s
== '+') {
263 assert(StringStartsWith(s
, end
, "0x"));
266 // Loop over the significand; everything up to the 'p'.
267 // This code is a bit nasty because we want to support extra zeroes anywhere
268 // without having to use many significand bits.
270 // 0x00000001.0p0 => significand = 1, significand_exponent = 0
271 // 0x10000000.0p0 => significand = 1, significand_exponent = 28
272 // 0x0.000001p0 => significand = 1, significand_exponent = -24
273 bool seen_dot
= false;
274 bool seen_trailing_non_zero
= false;
275 Uint significand
= 0;
276 int significand_exponent
= 0; // Exponent adjustment due to dot placement.
277 for (; s
< end
; ++s
) {
281 } else if (*s
== '.') {
283 } else if (Succeeded(ParseHexdigit(*s
, &digit
))) {
284 if (Traits::kBits
- Clz(significand
) <= Traits::kSigPlusOneBits
) {
285 significand
= (significand
<< 4) + digit
;
287 significand_exponent
-= 4;
290 if (!seen_trailing_non_zero
&& digit
!= 0) {
291 seen_trailing_non_zero
= true;
294 significand_exponent
+= 4;
302 if (significand
== 0) {
304 *out_bits
= Make(is_neg
, Traits::kMinExp
, 0);
309 bool exponent_is_neg
= false;
311 assert(*s
== 'p' || *s
== 'P');
313 // Exponent is always positive, but significand_exponent is signed.
314 // significand_exponent_add is negated if exponent will be negative, so it
315 // can be easily summed to see if the exponent is too large (see below).
316 int significand_exponent_add
= 0;
318 exponent_is_neg
= true;
319 significand_exponent_add
= -significand_exponent
;
321 } else if (*s
== '+') {
323 significand_exponent_add
= significand_exponent
;
326 for (; s
< end
; ++s
) {
331 uint32_t digit
= (*s
- '0');
333 exponent
= exponent
* 10 + digit
;
334 if (exponent
+ significand_exponent_add
>= Traits::kMaxExp
) {
340 if (exponent_is_neg
) {
341 exponent
= -exponent
;
344 int significand_bits
= Traits::kBits
- Clz(significand
);
345 // -1 for the implicit 1 bit of the significand.
346 exponent
+= significand_exponent
+ significand_bits
- 1;
348 if (exponent
<= Traits::kMinExp
) {
350 auto update_seen_trailing_non_zero
= [&](int shift
) {
352 auto mask
= (Uint(1) << (shift
- 1)) - 1;
353 seen_trailing_non_zero
|= (significand
& mask
) != 0;
356 // Normalize significand.
357 if (significand_bits
> Traits::kSigBits
) {
358 int shift
= significand_bits
- Traits::kSigBits
;
359 update_seen_trailing_non_zero(shift
);
360 significand
>>= shift
;
361 } else if (significand_bits
< Traits::kSigBits
) {
362 significand
<<= (Traits::kSigBits
- significand_bits
);
365 int shift
= Traits::kMinExp
- exponent
;
366 if (shift
<= Traits::kSigBits
) {
368 update_seen_trailing_non_zero(shift
);
370 ShiftAndRoundToNearest(significand
, shift
, seen_trailing_non_zero
) &
373 exponent
= Traits::kMinExp
;
375 if (significand
!= 0) {
376 *out_bits
= Make(is_neg
, exponent
, significand
);
381 // Not subnormal, too small; return 0 or -0.
382 *out_bits
= Make(is_neg
, Traits::kMinExp
, 0);
384 // Maybe Normal value.
385 if (significand_bits
> Traits::kSigPlusOneBits
) {
386 significand
= ShiftAndRoundToNearest(
387 significand
, significand_bits
- Traits::kSigPlusOneBits
,
388 seen_trailing_non_zero
);
389 if (significand
> Traits::kSigPlusOneMask
) {
392 } else if (significand_bits
< Traits::kSigPlusOneBits
) {
393 significand
<<= (Traits::kSigPlusOneBits
- significand_bits
);
396 if (exponent
>= Traits::kMaxExp
) {
397 // Would be inf or -inf, but the spec doesn't allow rounding hex-floats to
399 return Result::Error
;
402 *out_bits
= Make(is_neg
, exponent
, significand
& Traits::kSigMask
);
409 template <typename T
>
410 void FloatParser
<T
>::ParseInfinity(const char* s
,
417 } else if (*s
== '+') {
420 assert(StringStartsWith(s
, end
, "inf"));
421 *out_bits
= Make(is_neg
, Traits::kMaxExp
, 0);
425 template <typename T
>
426 Result FloatParser
<T
>::Parse(LiteralType literal_type
,
431 if (literal_type
== LiteralType::Int
&& StringStartsWith(s
, end
, "0x")) {
432 // Some MSVC crt implementation of strtof doesn't support hex strings
433 literal_type
= LiteralType::Hexfloat
;
436 switch (literal_type
) {
437 case LiteralType::Int
:
438 case LiteralType::Float
:
439 return ParseFloat(s
, end
, out_bits
);
441 case LiteralType::Hexfloat
:
442 return ParseHex(s
, end
, out_bits
);
444 case LiteralType::Infinity
:
445 ParseInfinity(s
, end
, out_bits
);
448 case LiteralType::Nan
:
449 return ParseNan(s
, end
, out_bits
);
456 template <typename T
>
457 void FloatWriter
<T
>::WriteHex(char* out
, size_t size
, Uint bits
) {
458 static constexpr int kNumNybbles
= Traits::kBits
/ 4;
459 static constexpr int kTopNybbleShift
= Traits::kBits
- 4;
460 static constexpr Uint kTopNybble
= Uint(0xf) << kTopNybbleShift
;
461 static const char s_hex_digits
[] = "0123456789abcdef";
463 char buffer
[Traits::kMaxHexBufferSize
];
465 bool is_neg
= (bits
>> Traits::kSignShift
);
466 int exp
= ((bits
>> Traits::kSigBits
) & Traits::kExpMask
) - Traits::kExpBias
;
467 Uint sig
= bits
& Traits::kSigMask
;
472 if (exp
== Traits::kMaxExp
) {
480 if (sig
!= Traits::kQuietNanTag
) {
483 // Skip leading zeroes.
484 int num_nybbles
= kNumNybbles
;
485 while ((sig
& kTopNybble
) == 0) {
489 while (num_nybbles
) {
490 Uint nybble
= (sig
>> kTopNybbleShift
) & 0xf;
491 *p
++ = s_hex_digits
[nybble
];
498 bool is_zero
= sig
== 0 && exp
== Traits::kMinExp
;
501 *p
++ = is_zero
? '0' : '1';
503 // Shift sig up so the top 4-bits are at the top of the Uint.
504 sig
<<= Traits::kBits
- Traits::kSigBits
;
507 if (exp
== Traits::kMinExp
) {
508 // Subnormal; shift the significand up, and shift out the implicit 1.
509 Uint leading_zeroes
= Clz(sig
);
510 if (leading_zeroes
< Traits::kSignShift
) {
511 sig
<<= leading_zeroes
+ 1;
515 exp
-= leading_zeroes
;
520 int nybble
= (sig
>> kTopNybbleShift
) & 0xf;
521 *p
++ = s_hex_digits
[nybble
];
540 *p
++ = '0' + (exp
/ 100) % 10;
543 *p
++ = '0' + (exp
/ 10) % 10;
545 *p
++ = '0' + exp
% 10;
549 size_t len
= p
- buffer
;
553 memcpy(out
, buffer
, len
);
557 } // end anonymous namespace
559 Result
ParseHexdigit(char c
, uint32_t* out
) {
560 if (static_cast<unsigned int>(c
- '0') <= 9) {
563 } else if (static_cast<unsigned int>(c
- 'a') < 6) {
564 *out
= 10 + (c
- 'a');
566 } else if (static_cast<unsigned int>(c
- 'A') < 6) {
567 *out
= 10 + (c
- 'A');
570 return Result::Error
;
573 Result
ParseUint64(const char* s
, const char* end
, uint64_t* out
) {
575 return Result::Error
;
578 if (*s
== '0' && s
+ 1 < end
&& s
[1] == 'x') {
581 return Result::Error
;
583 constexpr uint64_t kMaxDiv16
= UINT64_MAX
/ 16;
584 constexpr uint64_t kMaxMod16
= UINT64_MAX
% 16;
585 for (; s
< end
; ++s
) {
590 CHECK_RESULT(ParseHexdigit(*s
, &digit
));
591 // Check for overflow.
592 if (value
> kMaxDiv16
|| (value
== kMaxDiv16
&& digit
> kMaxMod16
)) {
593 return Result::Error
;
595 value
= value
* 16 + digit
;
598 constexpr uint64_t kMaxDiv10
= UINT64_MAX
/ 10;
599 constexpr uint64_t kMaxMod10
= UINT64_MAX
% 10;
600 for (; s
< end
; ++s
) {
604 uint32_t digit
= (*s
- '0');
606 return Result::Error
;
608 // Check for overflow.
609 if (value
> kMaxDiv10
|| (value
== kMaxDiv10
&& digit
> kMaxMod10
)) {
610 return Result::Error
;
612 value
= value
* 10 + digit
;
616 return Result::Error
;
622 Result
ParseInt64(const char* s
,
625 ParseIntType parse_type
) {
626 bool has_sign
= false;
627 if (*s
== '-' || *s
== '+') {
628 if (parse_type
== ParseIntType::UnsignedOnly
) {
629 return Result::Error
;
637 Result result
= ParseUint64(s
, end
, &value
);
639 // abs(INT64_MIN) == INT64_MAX + 1.
640 if (value
> static_cast<uint64_t>(INT64_MAX
) + 1) {
641 return Result::Error
;
643 value
= UINT64_MAX
- value
+ 1;
650 uint32_t AddWithCarry(uint32_t x
, uint32_t y
, uint32_t* carry
) {
651 // Increments *carry if the addition overflows, otherwise leaves carry alone.
652 if ((0xffffffff - x
) < y
) {
658 void Mul10(v128
* v
) {
659 // Multiply-by-10 decomposes into (x << 3) + (x << 1). We implement those
660 // operations with carrying from smaller quads of the v128 to the larger
663 constexpr uint32_t kTopThreeBits
= 0xe0000000;
664 constexpr uint32_t kTopBit
= 0x80000000;
666 uint32_t carry_into_v1
=
667 ((v
->u32(0) & kTopThreeBits
) >> 29) + ((v
->u32(0) & kTopBit
) >> 31);
668 v
->set_u32(0, AddWithCarry(v
->u32(0) << 3, v
->u32(0) << 1, &carry_into_v1
));
669 uint32_t carry_into_v2
=
670 ((v
->u32(1) & kTopThreeBits
) >> 29) + ((v
->u32(1) & kTopBit
) >> 31);
671 v
->set_u32(1, AddWithCarry(v
->u32(1) << 3, v
->u32(1) << 1, &carry_into_v2
));
672 v
->set_u32(1, AddWithCarry(v
->u32(1), carry_into_v1
, &carry_into_v2
));
673 uint32_t carry_into_v3
=
674 ((v
->u32(2) & kTopThreeBits
) >> 29) + ((v
->u32(2) & kTopBit
) >> 31);
675 v
->set_u32(2, AddWithCarry(v
->u32(2) << 3, v
->u32(2) << 1, &carry_into_v3
));
676 v
->set_u32(2, AddWithCarry(v
->u32(2), carry_into_v2
, &carry_into_v3
));
677 v
->set_u32(3, v
->u32(3) * 10 + carry_into_v3
);
681 Result
ParseUint128(const char* s
, const char* end
, v128
* out
) {
683 return Result::Error
;
689 uint32_t digit
= (*s
- '0');
691 return Result::Error
;
694 uint32_t carry_into_v1
= 0;
695 uint32_t carry_into_v2
= 0;
696 uint32_t carry_into_v3
= 0;
697 uint32_t overflow
= 0;
698 out
->set_u32(0, AddWithCarry(out
->u32(0), digit
, &carry_into_v1
));
699 out
->set_u32(1, AddWithCarry(out
->u32(1), carry_into_v1
, &carry_into_v2
));
700 out
->set_u32(2, AddWithCarry(out
->u32(2), carry_into_v2
, &carry_into_v3
));
701 out
->set_u32(3, AddWithCarry(out
->u32(3), carry_into_v3
, &overflow
));
703 return Result::Error
;
717 template <typename U
>
718 Result
ParseInt(const char* s
,
721 ParseIntType parse_type
) {
722 using S
= typename
std::make_signed
<U
>::type
;
724 bool has_sign
= false;
725 if (*s
== '-' || *s
== '+') {
726 if (parse_type
== ParseIntType::UnsignedOnly
) {
727 return Result::Error
;
734 CHECK_RESULT(ParseUint64(s
, end
, &value
));
737 // abs(INTN_MIN) == INTN_MAX + 1.
738 if (value
> static_cast<uint64_t>(std::numeric_limits
<S
>::max()) + 1) {
739 return Result::Error
;
741 value
= std::numeric_limits
<U
>::max() - value
+ 1;
743 if (value
> static_cast<uint64_t>(std::numeric_limits
<U
>::max())) {
744 return Result::Error
;
747 *out
= static_cast<U
>(value
);
751 Result
ParseInt8(const char* s
,
754 ParseIntType parse_type
) {
755 return ParseInt(s
, end
, out
, parse_type
);
758 Result
ParseInt16(const char* s
,
761 ParseIntType parse_type
) {
762 return ParseInt(s
, end
, out
, parse_type
);
765 Result
ParseInt32(const char* s
,
768 ParseIntType parse_type
) {
769 return ParseInt(s
, end
, out
, parse_type
);
772 Result
ParseFloat(LiteralType literal_type
,
775 uint32_t* out_bits
) {
776 return FloatParser
<float>::Parse(literal_type
, s
, end
, out_bits
);
779 Result
ParseDouble(LiteralType literal_type
,
782 uint64_t* out_bits
) {
783 return FloatParser
<double>::Parse(literal_type
, s
, end
, out_bits
);
786 void WriteFloatHex(char* buffer
, size_t size
, uint32_t bits
) {
787 return FloatWriter
<float>::WriteHex(buffer
, size
, bits
);
790 void WriteDoubleHex(char* buffer
, size_t size
, uint64_t bits
) {
791 return FloatWriter
<double>::WriteHex(buffer
, size
, bits
);
794 void WriteUint128(char* buffer
, size_t size
, v128 bits
) {
797 char reversed_buffer
[40];
800 remainder
= bits
.u32(3);
802 for (int i
= 3; i
!= 0; --i
) {
803 digits
= remainder
/ 10;
804 remainder
= ((remainder
- digits
* 10) << 32) + bits
.u32(i
- 1);
805 bits
.set_u32(i
, digits
);
808 digits
= remainder
/ 10;
809 remainder
= remainder
- digits
* 10;
810 bits
.set_u32(0, digits
);
812 char remainder_buffer
[21];
813 snprintf(remainder_buffer
, 21, "%" PRIu64
, remainder
);
814 int remainder_buffer_len
= strlen(remainder_buffer
);
815 assert(len
+ remainder_buffer_len
< sizeof(reversed_buffer
));
816 memcpy(&reversed_buffer
[len
], remainder_buffer
, remainder_buffer_len
);
817 len
+= remainder_buffer_len
;
818 } while (!bits
.is_zero());
819 size_t truncated_tail
= 0;
821 truncated_tail
= len
- size
+ 1;
824 std::reverse_copy(reversed_buffer
+ truncated_tail
,
825 reversed_buffer
+ len
+ truncated_tail
, buffer
);