Commit 6ec6589bd8

Andrew Kelley <superjoe30@gmail.com>
2017-01-05 06:59:37
IR: pass MT19937_64 test
1 parent c32a060
Changed files (4)
src/bignum.cpp
@@ -88,7 +88,10 @@ bool bignum_fits_in_bits(BigNum *bn, int bit_count, bool is_signed) {
 
 void bignum_truncate(BigNum *bn, int bit_count) {
     assert(bn->kind == BigNumKindInt);
-    bn->data.x_uint &= (1LL << bit_count) - 1;
+    // TODO handle case when negative = true
+    if (bit_count < 64) {
+        bn->data.x_uint &= (1LL << bit_count) - 1;
+    }
 }
 
 uint64_t bignum_to_twos_complement(BigNum *bn) {
@@ -142,11 +145,16 @@ void bignum_negate(BigNum *dest, BigNum *op) {
     }
 }
 
-void bignum_not(BigNum *dest, BigNum *op, int bit_count) {
+void bignum_not(BigNum *dest, BigNum *op, int bit_count, bool is_signed) {
     assert(op->kind == BigNumKindInt);
     uint64_t bits = ~bignum_to_twos_complement(op);
-    bits &= (1LL << bit_count) - 1;
-    bignum_init_signed(dest, bits);
+    if (bit_count < 64) {
+        bits &= (1LL << bit_count) - 1;
+    }
+    if (is_signed)
+        bignum_init_signed(dest, bits);
+    else
+        bignum_init_unsigned(dest, bits);
 }
 
 void bignum_cast_to_float(BigNum *dest, BigNum *op) {
src/bignum.hpp
@@ -48,7 +48,7 @@ bool bignum_shr(BigNum *dest, BigNum *op1, BigNum *op2);
 void bignum_negate(BigNum *dest, BigNum *op);
 void bignum_cast_to_float(BigNum *dest, BigNum *op);
 void bignum_cast_to_int(BigNum *dest, BigNum *op);
-void bignum_not(BigNum *dest, BigNum *op, int bit_count);
+void bignum_not(BigNum *dest, BigNum *op, int bit_count, bool is_signed);
 
 void bignum_truncate(BigNum *dest, int bit_count);
 
src/ir.cpp
@@ -7885,7 +7885,8 @@ static TypeTableEntry *ir_analyze_bin_not(IrAnalyze *ira, IrInstructionUnOp *ins
 
             bool depends_on_compile_var = value->value.depends_on_compile_var;
             ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base, depends_on_compile_var);
-            bignum_not(&out_val->data.x_bignum, &target_const_val->data.x_bignum, expr_type->data.integral.bit_count);
+            bignum_not(&out_val->data.x_bignum, &target_const_val->data.x_bignum,
+                    expr_type->data.integral.bit_count, expr_type->data.integral.is_signed);
             return expr_type;
         }
 
test/cases/math.zig
@@ -168,6 +168,7 @@ fn binaryNot() {
     @setFnTest(this);
 
     assert(@staticEval(~u16(0b1010101010101010) == 0b0101010101010101));
+    assert(@staticEval(~u64(2147483647) == 18446744071562067968));
     testBinaryNot(0b1010101010101010);
 }