Browse Source

Fix bit field bug

Ginger Bill 8 years ago
parent
commit
af2736daec
3 changed files with 78 additions and 33 deletions
  1. 27 28
      src/exact_value.cpp
  2. 47 3
      src/integer128.cpp
  3. 4 2
      src/ir.cpp

+ 27 - 28
src/exact_value.cpp

@@ -317,7 +317,7 @@ ExactValue exact_unary_operator_value(TokenKind op, ExactValue v, i32 precision)
 			return v;
 		case ExactValue_Integer: {
 			ExactValue i = v;
-			i.value_integer = i128_neg(i.value_integer);
+			i.value_integer = -i.value_integer;
 			return i;
 		}
 		case ExactValue_Float: {
@@ -339,7 +339,7 @@ ExactValue exact_unary_operator_value(TokenKind op, ExactValue v, i32 precision)
 		case ExactValue_Invalid:
 			return v;
 		case ExactValue_Integer:
-			i = i128_not(v.value_integer);
+			i = ~v.value_integer;
 			break;
 		default:
 			goto failure;
@@ -349,7 +349,7 @@ ExactValue exact_unary_operator_value(TokenKind op, ExactValue v, i32 precision)
 		// limited to the types precision
 		// IMPORTANT NOTE(bill): Max precision is 64 bits as that's how integers are stored
 		if (0 < precision && precision < 128) {
-			i = i128_and(i, i128_not(i128_shl(I128_NEG_ONE, precision)));
+			i = i & ~(I128_NEG_ONE << precision);
 		}
 
 		return exact_value_i128(i);
@@ -461,19 +461,19 @@ ExactValue exact_binary_operator_value(TokenKind op, ExactValue x, ExactValue y)
 		i128 b = y.value_integer;
 		i128 c = I128_ZERO;
 		switch (op) {
-		case Token_Add:    c = i128_add(a, b);                           break;
-		case Token_Sub:    c = i128_sub(a, b);                           break;
-		case Token_Mul:    c = i128_mul(a, b);                           break;
+		case Token_Add:    c = a + b;               break;
+		case Token_Sub:    c = a - b;               break;
+		case Token_Mul:    c = a * b;               break;
 		case Token_Quo:    return exact_value_float(fmod(i128_to_f64(a), i128_to_f64(b)));
-		case Token_QuoEq:  c = i128_quo(a, b);                           break; // NOTE(bill): Integer division
-		case Token_Mod:    c = i128_mod(a, b);                           break;
-		case Token_ModMod: c = i128_mod(i128_add(i128_mod(a, b), b), b); break;
-		case Token_And:    c = i128_and    (a, b);                       break;
-		case Token_Or:     c = i128_or     (a, b);                       break;
-		case Token_Xor:    c = i128_xor    (a, b);                       break;
-		case Token_AndNot: c = i128_and_not(a, b);                       break;
-		case Token_Shl:    c = i128_shl    (a, i128_to_u64(b));          break;
-		case Token_Shr:    c = i128_shr    (a, i128_to_u64(b));          break;
+		case Token_QuoEq:  c = a / b;               break; // NOTE(bill): Integer division
+		case Token_Mod:    c = a % b;               break;
+		case Token_ModMod: c = ((a % b) + b) % b;   break;
+		case Token_And:    c = a & b;               break;
+		case Token_Or:     c = a | b;               break;
+		case Token_Xor:    c = a ^ b;               break;
+		case Token_AndNot: c = i128_and_not(a, b);  break;
+		case Token_Shl:    c = a << i128_to_u64(b); break;
+		case Token_Shr:    c = a >> i128_to_u64(b); break;
 		default: goto error;
 		}
 
@@ -560,12 +560,12 @@ bool compare_exact_values(TokenKind op, ExactValue x, ExactValue y) {
 		i128 a = x.value_integer;
 		i128 b = y.value_integer;
 		switch (op) {
-		case Token_CmpEq: return i128_eq(a, b);
-		case Token_NotEq: return i128_ne(a, b);
-		case Token_Lt:    return i128_lt(a, b);
-		case Token_LtEq:  return i128_le(a, b);
-		case Token_Gt:    return i128_gt(a, b);
-		case Token_GtEq:  return i128_ge(a, b);
+		case Token_CmpEq: return a == b;
+		case Token_NotEq: return a != b;
+		case Token_Lt:    return a <  b;
+		case Token_LtEq:  return a <= b;
+		case Token_Gt:    return a >  b;
+		case Token_GtEq:  return a >= b;
 		}
 	} break;
 
@@ -596,15 +596,14 @@ bool compare_exact_values(TokenKind op, ExactValue x, ExactValue y) {
 	case ExactValue_String: {
 		String a = x.value_string;
 		String b = y.value_string;
-		isize len = gb_min(a.len, b.len);
 		// TODO(bill): gb_memcompare is used because the strings are UTF-8
 		switch (op) {
-		case Token_CmpEq: return gb_memcompare(a.text, b.text, len) == 0;
-		case Token_NotEq: return gb_memcompare(a.text, b.text, len) != 0;
-		case Token_Lt:    return gb_memcompare(a.text, b.text, len) <  0;
-		case Token_LtEq:  return gb_memcompare(a.text, b.text, len) <= 0;
-		case Token_Gt:    return gb_memcompare(a.text, b.text, len) >  0;
-		case Token_GtEq:  return gb_memcompare(a.text, b.text, len) >= 0;
+		case Token_CmpEq: return a == b;
+		case Token_NotEq: return a != b;
+		case Token_Lt:    return a <  b;
+		case Token_LtEq:  return a <= b;
+		case Token_Gt:    return a >  b;
+		case Token_GtEq:  return a >= b;
 		}
 	} break;
 	}

+ 47 - 3
src/integer128.cpp

@@ -1,10 +1,12 @@
-typedef struct u128 {u64 lo; u64 hi;} u128;
-typedef struct i128 {u64 lo; i64 hi;} i128;
-
 #define BIT128_U64_HIGHBIT 0x8000000000000000ull
 #define BIT128_U64_BITS62  0x7fffffffffffffffull
 #define BIT128_U64_ALLBITS 0xffffffffffffffffull
 
+
+typedef struct u128 { u64 lo; u64 hi; } u128;
+typedef struct i128 { u64 lo; i64 hi; } i128;
+
+
 static u128 const U128_ZERO = {0, 0};
 static u128 const U128_ONE  = {1, 0};
 static i128 const I128_ZERO = {0, 0};
@@ -84,6 +86,48 @@ void i128_divide (i128 num, i128 den, i128 *quo, i128 *rem);
 i128 i128_quo    (i128 a, i128 b);
 i128 i128_mod    (i128 a, i128 b);
 
+bool operator==(u128 a, u128 b) { return u128_eq(a, b); }
+bool operator!=(u128 a, u128 b) { return u128_ne(a, b); }
+bool operator< (u128 a, u128 b) { return u128_lt(a, b); }
+bool operator> (u128 a, u128 b) { return u128_gt(a, b); }
+bool operator<=(u128 a, u128 b) { return u128_le(a, b); }
+bool operator>=(u128 a, u128 b) { return u128_ge(a, b); }
+
+u128 operator+(u128 a, u128 b) { return u128_add(a, b); }
+u128 operator-(u128 a, u128 b) { return u128_sub(a, b); }
+u128 operator*(u128 a, u128 b) { return u128_mul(a, b); }
+u128 operator/(u128 a, u128 b) { return u128_quo(a, b); }
+u128 operator%(u128 a, u128 b) { return u128_mod(a, b); }
+u128 operator&(u128 a, u128 b) { return u128_and(a, b); }
+u128 operator|(u128 a, u128 b) { return u128_or (a, b); }
+u128 operator^(u128 a, u128 b) { return u128_xor(a, b); }
+u128 operator~(u128 a)         { return u128_not(a); }
+u128 operator+(u128 a)         { return a; }
+u128 operator-(u128 a)         { return u128_neg(a); }
+u128 operator<<(u128 a, u32 b) { return u128_shl(a, b); }
+u128 operator>>(u128 a, u32 b) { return u128_shr(a, b); }
+
+
+bool operator==(i128 a, i128 b) { return i128_eq(a, b); }
+bool operator!=(i128 a, i128 b) { return i128_ne(a, b); }
+bool operator< (i128 a, i128 b) { return i128_lt(a, b); }
+bool operator> (i128 a, i128 b) { return i128_gt(a, b); }
+bool operator<=(i128 a, i128 b) { return i128_le(a, b); }
+bool operator>=(i128 a, i128 b) { return i128_ge(a, b); }
+
+i128 operator+(i128 a, i128 b) { return i128_add(a, b); }
+i128 operator-(i128 a, i128 b) { return i128_sub(a, b); }
+i128 operator*(i128 a, i128 b) { return i128_mul(a, b); }
+i128 operator/(i128 a, i128 b) { return i128_quo(a, b); }
+i128 operator%(i128 a, i128 b) { return i128_mod(a, b); }
+i128 operator&(i128 a, i128 b) { return i128_and(a, b); }
+i128 operator|(i128 a, i128 b) { return i128_or (a, b); }
+i128 operator^(i128 a, i128 b) { return i128_xor(a, b); }
+i128 operator~(i128 a)         { return i128_not(a); }
+i128 operator+(i128 a)         { return a; }
+i128 operator-(i128 a)         { return i128_neg(a); }
+i128 operator<<(i128 a, u32 b) { return i128_shl(a, b); }
+i128 operator>>(i128 a, u32 b) { return i128_shr(a, b); }
 
 ////////////////////////////////////////////////////////////////
 

+ 4 - 2
src/ir.cpp

@@ -1902,12 +1902,14 @@ irValue *ir_addr_load(irProcedure *proc, irAddr addr) {
 			return v;
 		}
 
+		GB_ASSERT(8 > bit_inset);
 
+		irValue *shift_amount = ir_value_constant(a, int_type, exact_value_i64(bit_inset));
 		irValue *first_byte = ir_emit_load(proc, bytes);
-		irValue *res = ir_emit_arith(proc, Token_Shr, first_byte, ir_const_int(a, 8 - bit_inset), int_type);
+		irValue *res = ir_emit_arith(proc, Token_Shr, first_byte, shift_amount, int_type);
 
 		irValue *remaining_bytes = ir_emit_load(proc, ir_emit_conv(proc, ir_emit_ptr_offset(proc, bytes, v_one), int_ptr));
-		remaining_bytes = ir_emit_arith(proc, Token_Shl, remaining_bytes, ir_const_int(a, bit_inset), int_type);
+		remaining_bytes = ir_emit_arith(proc, Token_Shl, remaining_bytes, shift_amount, int_type);
 		return ir_emit_arith(proc, Token_Or, res, remaining_bytes, int_type);
 
 	}