aboutsummaryrefslogtreecommitdiff
path: root/src/tokenizer.cpp
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2019-03-21 16:17:29 -0400
committerAndrew Kelley <andrew@ziglang.org>2019-03-21 16:17:29 -0400
commitaf509c68b01c8645e5efaeec7ea11e809f34ba7d (patch)
treedad7a1a927522c19f547a910d68647e0ce989a57 /src/tokenizer.cpp
parentb5cc92f16391b1ff5d75e5e6b072b8338b3e8218 (diff)
downloadzig-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.cpp28
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;
}