diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2019-03-21 16:17:29 -0400 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2019-03-21 16:17:29 -0400 |
| commit | af509c68b01c8645e5efaeec7ea11e809f34ba7d (patch) | |
| tree | dad7a1a927522c19f547a910d68647e0ce989a57 /src/tokenizer.cpp | |
| parent | b5cc92f16391b1ff5d75e5e6b072b8338b3e8218 (diff) | |
| download | zig-af509c68b01c8645e5efaeec7ea11e809f34ba7d.tar.gz zig-af509c68b01c8645e5efaeec7ea11e809f34ba7d.zip | |
fix parsing of large hex float literals
closes #2083
Diffstat (limited to 'src/tokenizer.cpp')
| -rw-r--r-- | src/tokenizer.cpp | 28 |
1 files changed, 18 insertions, 10 deletions
diff --git a/src/tokenizer.cpp b/src/tokenizer.cpp index 9ff6ed3bbe..07ea4bf55a 100644 --- a/src/tokenizer.cpp +++ b/src/tokenizer.cpp @@ -326,7 +326,7 @@ static void end_float_token(Tokenize *t) { return; } - // A SoftFloat-3d float128 is represented internally as a standard + // A SoftFloat-3e float128 is represented internally as a standard // quad-precision float with 15bit exponent and 113bit fractional. union { uint64_t repr[2]; float128_t actual; } f_bits; @@ -345,29 +345,37 @@ static void end_float_token(Tokenize *t) { return; } - uint64_t sig_bits[2] = {0, 0}; - bigint_write_twos_complement(&t->significand, (uint8_t*) sig_bits, 128, false); - - const uint64_t shift = 112 - significand_magnitude_in_bin; - const uint64_t exp_shift = 48; - // Mask the sign bit to 0 since always non-negative lex - const uint64_t exp_mask = 0xffffull << exp_shift; + const int shift = 112 - significand_magnitude_in_bin; // must be special-cased to avoid undefined behavior on shift == 64 if (shift == 128) { + uint64_t sig_bits[2] = {0, 0}; + bigint_write_twos_complement(&t->significand, (uint8_t*) sig_bits, 128, false); f_bits.repr[0] = 0; f_bits.repr[1] = sig_bits[0]; } else if (shift == 0) { - f_bits.repr[0] = sig_bits[0]; - f_bits.repr[1] = sig_bits[1]; + bigint_write_twos_complement(&t->significand, (uint8_t*) f_bits.repr, 128, false); } else if (shift >= 64) { + uint64_t sig_bits[2] = {0, 0}; + bigint_write_twos_complement(&t->significand, (uint8_t*) sig_bits, 128, false); f_bits.repr[0] = 0; f_bits.repr[1] = sig_bits[0] << (shift - 64); + } else if (shift < 0) { + BigInt shift_bigint; + bigint_init_unsigned(&shift_bigint, -shift); + BigInt shifted_significand; + bigint_shr(&shifted_significand, &t->significand, &shift_bigint); + bigint_write_twos_complement(&shifted_significand, (uint8_t*) f_bits.repr, 128, false); } else { + uint64_t sig_bits[2] = {0, 0}; + bigint_write_twos_complement(&t->significand, (uint8_t*) sig_bits, 128, false); f_bits.repr[0] = sig_bits[0] << shift; f_bits.repr[1] = (sig_bits[1] << shift) | (sig_bits[0] >> (64 - shift)); } + const uint64_t exp_shift = 48; + // Mask the sign bit to 0 since always non-negative lex + const uint64_t exp_mask = 0xffffull << exp_shift; f_bits.repr[1] &= ~exp_mask; f_bits.repr[1] |= (uint64_t)(t->exponent_in_bin_or_dec + 16383) << exp_shift; } |
