aboutsummaryrefslogtreecommitdiff
path: root/src/ir.cpp
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2019-04-04 22:07:15 -0400
committerAndrew Kelley <andrew@ziglang.org>2019-04-04 22:07:15 -0400
commit1dc6751721a2fe9990ea8fab4eadc95a29f53304 (patch)
treefb85f1874651709f419567327241e94748d63bb8 /src/ir.cpp
parent8e6ff8d615820f7f732724a5db1639ae5f12fb4e (diff)
downloadzig-1dc6751721a2fe9990ea8fab4eadc95a29f53304.tar.gz
zig-1dc6751721a2fe9990ea8fab4eadc95a29f53304.zip
fix NaN comparing equal to itself
This was broken both in comptime code and in runtime code. closes #1174
Diffstat (limited to 'src/ir.cpp')
-rw-r--r--src/ir.cpp25
1 files changed, 25 insertions, 0 deletions
diff --git a/src/ir.cpp b/src/ir.cpp
index ea7a27f312..3f02d18e8e 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -17,6 +17,7 @@
#include "util.hpp"
#include <errno.h>
+#include <math.h>
struct IrExecContext {
ZigList<ConstExprValue *> mem_slot_list;
@@ -8242,6 +8243,27 @@ static void float_init_float(ConstExprValue *dest_val, ConstExprValue *src_val)
}
}
+static bool float_is_nan(ConstExprValue *op) {
+ if (op->type->id == ZigTypeIdComptimeFloat) {
+ return bigfloat_is_nan(&op->data.x_bigfloat);
+ } else if (op->type->id == ZigTypeIdFloat) {
+ switch (op->type->data.floating.bit_count) {
+ case 16:
+ return f16_isSignalingNaN(op->data.x_f16);
+ case 32:
+ return isnan(op->data.x_f32);
+ case 64:
+ return isnan(op->data.x_f64);
+ case 128:
+ return f128M_isSignalingNaN(&op->data.x_f128);
+ default:
+ zig_unreachable();
+ }
+ } else {
+ zig_unreachable();
+ }
+}
+
static Cmp float_cmp(ConstExprValue *op1, ConstExprValue *op2) {
assert(op1->type == op2->type);
if (op1->type->id == ZigTypeIdComptimeFloat) {
@@ -12378,6 +12400,9 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
return ira->codegen->invalid_instruction;
if (resolved_type->id == ZigTypeIdComptimeFloat || resolved_type->id == ZigTypeIdFloat) {
+ if (float_is_nan(op1_val) || float_is_nan(op2_val)) {
+ return ir_const_bool(ira, &bin_op_instruction->base, op_id == IrBinOpCmpNotEq);
+ }
Cmp cmp_result = float_cmp(op1_val, op2_val);
bool answer = resolve_cmp_op_id(op_id, cmp_result);
return ir_const_bool(ira, &bin_op_instruction->base, answer);