aboutsummaryrefslogtreecommitdiff
path: root/src/analyze.cpp
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2017-08-20 00:33:05 -0400
committerAndrew Kelley <superjoe30@gmail.com>2017-08-20 01:04:51 -0400
commit09bd4a9a8693485fa87a5f62af90540ca8ce9d47 (patch)
tree295ed2543f174d014dd85acd95181e615d2f24f8 /src/analyze.cpp
parentc73a0c92d0b8736b0473b10bd5deacf62e0753d8 (diff)
downloadzig-09bd4a9a8693485fa87a5f62af90540ca8ce9d47.tar.gz
zig-09bd4a9a8693485fa87a5f62af90540ca8ce9d47.zip
compile-time f32, f64 operations are now correctly lossy
previously we used the bigfloat abstraction to do all compile-time float math. but runtime code and comptime code are supposed to get the same result. so now if you add a f32 to a f32 at compile time it does it with f32 math instead of the bigfloat. float literals still get the bigfloat math. closes #424
Diffstat (limited to 'src/analyze.cpp')
-rw-r--r--src/analyze.cpp87
1 files changed, 82 insertions, 5 deletions
diff --git a/src/analyze.cpp b/src/analyze.cpp
index a59c77a1c5..05ec20aced 100644
--- a/src/analyze.cpp
+++ b/src/analyze.cpp
@@ -13,6 +13,7 @@
#include "ir_print.hpp"
#include "os.hpp"
#include "parser.hpp"
+#include "quadmath.hpp"
#include "zig_llvm.hpp"
static const size_t default_backward_branch_quota = 1000;
@@ -3273,8 +3274,35 @@ static uint32_t hash_const_val(ConstExprValue *const_val) {
return result;
}
case TypeTableEntryIdFloat:
+ switch (const_val->type->data.floating.bit_count) {
+ case 32:
+ {
+ uint32_t result;
+ memcpy(&result, &const_val->data.x_f32, 4);
+ return result ^ 4084870010;
+ }
+ case 64:
+ {
+ uint32_t ints[2];
+ memcpy(&ints[0], &const_val->data.x_f64, 8);
+ return ints[0] ^ ints[1] ^ 0x22ed43c6;
+ }
+ case 128:
+ {
+ uint32_t ints[4];
+ memcpy(&ints[0], &const_val->data.x_f128, 16);
+ return ints[0] ^ ints[1] ^ ints[2] ^ ints[3] ^ 0xb5ffef27;
+ }
+ default:
+ zig_unreachable();
+ }
case TypeTableEntryIdNumLitFloat:
- return (uint32_t)(const_val->data.x_bigfloat.value * (uint32_t)UINT32_MAX);
+ {
+ __float128 f128 = bigfloat_to_f128(&const_val->data.x_bigfloat);
+ uint32_t ints[4];
+ memcpy(&ints[0], &f128, 16);
+ return ints[0] ^ ints[1] ^ ints[2] ^ ints[3] ^ 0xed8b3dfb;
+ }
case TypeTableEntryIdArgTuple:
return (uint32_t)const_val->data.x_arg_tuple.start_index * (uint32_t)281907309 +
(uint32_t)const_val->data.x_arg_tuple.end_index * (uint32_t)2290442768;
@@ -3575,7 +3603,25 @@ ConstExprValue *create_const_signed(TypeTableEntry *type, int64_t x) {
void init_const_float(ConstExprValue *const_val, TypeTableEntry *type, double value) {
const_val->special = ConstValSpecialStatic;
const_val->type = type;
- bigfloat_init_float(&const_val->data.x_bigfloat, value);
+ if (type->id == TypeTableEntryIdNumLitFloat) {
+ bigfloat_init_64(&const_val->data.x_bigfloat, value);
+ } else if (type->id == TypeTableEntryIdFloat) {
+ switch (type->data.floating.bit_count) {
+ case 32:
+ const_val->data.x_f32 = value;
+ break;
+ case 64:
+ const_val->data.x_f64 = value;
+ break;
+ case 128:
+ // if we need this, we should add a function that accepts a __float128 param
+ zig_unreachable();
+ default:
+ zig_unreachable();
+ }
+ } else {
+ zig_unreachable();
+ }
}
ConstExprValue *create_const_float(TypeTableEntry *type, double value) {
@@ -3816,6 +3862,17 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) {
case TypeTableEntryIdBool:
return a->data.x_bool == b->data.x_bool;
case TypeTableEntryIdFloat:
+ assert(a->type->data.floating.bit_count == b->type->data.floating.bit_count);
+ switch (a->type->data.floating.bit_count) {
+ case 32:
+ return a->data.x_f32 == b->data.x_f32;
+ case 64:
+ return a->data.x_f64 == b->data.x_f64;
+ case 128:
+ return a->data.x_f128 == b->data.x_f128;
+ default:
+ zig_unreachable();
+ }
case TypeTableEntryIdNumLitFloat:
return bigfloat_cmp(&a->data.x_bigfloat, &b->data.x_bigfloat) == CmpEQ;
case TypeTableEntryIdInt:
@@ -3984,12 +4041,32 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
buf_appendf(buf, "{}");
return;
case TypeTableEntryIdNumLitFloat:
- case TypeTableEntryIdFloat:
- bigfloat_write_buf(buf, &const_val->data.x_bigfloat);
+ bigfloat_append_buf(buf, &const_val->data.x_bigfloat);
return;
+ case TypeTableEntryIdFloat:
+ switch (type_entry->data.floating.bit_count) {
+ case 32:
+ buf_appendf(buf, "%f", const_val->data.x_f32);
+ return;
+ case 64:
+ buf_appendf(buf, "%f", const_val->data.x_f64);
+ return;
+ case 128:
+ {
+ const size_t extra_len = 100;
+ size_t old_len = buf_len(buf);
+ buf_resize(buf, old_len + extra_len);
+ int len = quadmath_snprintf(buf_ptr(buf) + old_len, extra_len, "%Qf", const_val->data.x_f128);
+ assert(len > 0);
+ buf_resize(buf, old_len + len);
+ return;
+ }
+ default:
+ zig_unreachable();
+ }
case TypeTableEntryIdNumLitInt:
case TypeTableEntryIdInt:
- bigint_write_buf(buf, &const_val->data.x_bigint, 10);
+ bigint_append_buf(buf, &const_val->data.x_bigint, 10);
return;
case TypeTableEntryIdMetaType:
buf_appendf(buf, "%s", buf_ptr(&const_val->data.x_type->name));