aboutsummaryrefslogtreecommitdiff
path: root/src/ir.cpp
diff options
context:
space:
mode:
authorLemonBoy <thatlemon@gmail.com>2020-01-21 10:43:05 +0100
committerAndrew Kelley <andrew@ziglang.org>2020-01-29 16:37:55 -0500
commitfe4ef7b461bec5370169063ccf889873161f8c46 (patch)
tree62e89820a4f2161cbc65d199b74609bd8a3e933b /src/ir.cpp
parentd448c3d38af9f8f70daaa2817a5834e30da4b8ca (diff)
downloadzig-fe4ef7b461bec5370169063ccf889873161f8c46.tar.gz
zig-fe4ef7b461bec5370169063ccf889873161f8c46.zip
Fix comptime float-int comparisons
Closes #4259
Diffstat (limited to 'src/ir.cpp')
-rw-r--r--src/ir.cpp59
1 files changed, 39 insertions, 20 deletions
diff --git a/src/ir.cpp b/src/ir.cpp
index 149c8fbdc9..c8c14c8905 100644
--- a/src/ir.cpp
+++ b/src/ir.cpp
@@ -15815,33 +15815,52 @@ never_mind_just_calculate_it_normally:
bool op1_is_int = op1_val->type->id == ZigTypeIdInt || op1_val->type->id == ZigTypeIdComptimeInt;
bool op2_is_int = op2_val->type->id == ZigTypeIdInt || op2_val->type->id == ZigTypeIdComptimeInt;
- BigInt *op1_bigint;
- BigInt *op2_bigint;
- bool need_to_free_op1_bigint = false;
- bool need_to_free_op2_bigint = false;
- if (op1_is_float) {
- op1_bigint = allocate<BigInt>(1, "BigInt");
- need_to_free_op1_bigint = true;
- float_init_bigint(op1_bigint, op1_val);
- } else {
- assert(op1_is_int);
- op1_bigint = &op1_val->data.x_bigint;
+ if (op1_is_int && op2_is_int) {
+ Cmp cmp_result = bigint_cmp(&op1_val->data.x_bigint, &op2_val->data.x_bigint);
+ out_val->special = ConstValSpecialStatic;
+ out_val->data.x_bool = resolve_cmp_op_id(op_id, cmp_result);
+
+ return nullptr;
}
- if (op2_is_float) {
- op2_bigint = allocate<BigInt>(1, "BigInt");
- need_to_free_op2_bigint = true;
- float_init_bigint(op2_bigint, op2_val);
+
+ // Handle the case where one of the two operands is a fp value and the other
+ // is an integer value
+ ZigValue **int_val, **float_val;
+
+ if (op1_is_int && op2_is_float) {
+ int_val = &op1_val;
+ float_val = &op2_val;
+ } else if (op1_is_float && op2_is_int) {
+ int_val = &op2_val;
+ float_val = &op1_val;
} else {
- assert(op2_is_int);
- op2_bigint = &op2_val->data.x_bigint;
+ zig_unreachable();
+ }
+
+ // They can never be equal if the fp value has a non-zero decimal part
+ if (op_id == IrBinOpCmpEq || op_id == IrBinOpCmpNotEq) {
+ if (float_has_fraction(*float_val)) {
+ out_val->special = ConstValSpecialStatic;
+ out_val->data.x_bool = op_id == IrBinOpCmpNotEq;
+
+ return nullptr;
+ }
+ }
+
+ // Cast the integer operand into a fp value to perform the comparison
+ {
+ IrInstruction *tmp = ir_const_noval(ira, source_instr);
+ tmp->value = *int_val;
+ IrInstruction *casted = ir_implicit_cast(ira, tmp, (*float_val)->type);
+ if (casted == ira->codegen->invalid_instruction)
+ return ira->codegen->trace_err;
+ *int_val = casted->value;
}
- Cmp cmp_result = bigint_cmp(op1_bigint, op2_bigint);
+ Cmp cmp_result = bigfloat_cmp(&op1_val->data.x_bigfloat, &op2_val->data.x_bigfloat);
out_val->special = ConstValSpecialStatic;
out_val->data.x_bool = resolve_cmp_op_id(op_id, cmp_result);
- if (need_to_free_op1_bigint) destroy(op1_bigint, "BigInt");
- if (need_to_free_op2_bigint) destroy(op2_bigint, "BigInt");
return nullptr;
}