Commit 4b1cd45472

LemonBoy <thatlemon@gmail.com>
2019-09-09 19:09:56
Comptime folding of enum/union comparisons
1 parent cc63760
Changed files (2)
src
test
stage1
behavior
src/ir.cpp
@@ -13247,6 +13247,21 @@ static IrInstruction *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *
         if (type_is_invalid(casted_val->value.type))
             return ira->codegen->invalid_instruction;
 
+        if (instr_is_comptime(casted_union)) {
+            ConstExprValue *const_union_val = ir_resolve_const(ira, casted_union, UndefBad);
+            if (!const_union_val)
+                return ira->codegen->invalid_instruction;
+
+            ConstExprValue *const_enum_val = ir_resolve_const(ira, casted_val, UndefBad);
+            if (!const_enum_val)
+                return ira->codegen->invalid_instruction;
+
+            Cmp cmp_result = bigint_cmp(&const_union_val->data.x_union.tag, &const_enum_val->data.x_enum_tag);
+            bool bool_result = (op_id == IrBinOpCmpEq) ? cmp_result == CmpEQ : cmp_result != CmpEQ;
+
+            return ir_const_bool(ira, &bin_op_instruction->base, bool_result);
+        }
+
         IrInstruction *result = ir_build_bin_op(&ira->new_irb,
             bin_op_instruction->base.scope, bin_op_instruction->base.source_node,
             op_id, casted_union, casted_val, bin_op_instruction->safety_check_on);
test/stage1/behavior/union.zig
@@ -468,7 +468,7 @@ test "union no tag with struct member" {
     u.foo();
 }
 
-test "comparison between union and enum literal" {
+fn testComparison() void {
     var x = Payload{.A = 42};
     expect(x == .A);
     expect(x != .B);
@@ -477,3 +477,8 @@ test "comparison between union and enum literal" {
     expect((x == .C) == false);
     expect((x != .A) == false);
 }
+
+test "comparison between union and enum literal" {
+    testComparison();
+    comptime testComparison();
+}