Commit a52dcdd3c5

Jacob Young <jacobly0@users.noreply.github.com>
2022-12-21 03:31:44
CBE: fix bitwise not
Closes #13911
1 parent 471f3c4
Changed files (2)
src
codegen
test
behavior
src/codegen/c.zig
@@ -3591,6 +3591,10 @@ fn airOverflow(f: *Function, inst: Air.Inst.Index, operation: []const u8, info:
 }
 
 fn airNot(f: *Function, inst: Air.Inst.Index) !CValue {
+    const inst_ty = f.air.typeOfIndex(inst);
+    if (inst_ty.tag() != .bool)
+        return try airUnBuiltinCall(f, inst, "not", .Bits);
+
     const ty_op = f.air.instructions.items(.data)[inst].ty_op;
 
     if (f.liveness.isUnused(inst)) {
@@ -3602,11 +3606,10 @@ fn airNot(f: *Function, inst: Air.Inst.Index) !CValue {
     try reap(f, inst, &.{ty_op.operand});
 
     const writer = f.object.writer();
-    const inst_ty = f.air.typeOfIndex(inst);
     const local = try f.allocLocal(inst, inst_ty);
     try f.writeCValue(writer, local, .Other);
     try writer.writeAll(" = ");
-    try writer.writeByte(if (inst_ty.tag() == .bool) '!' else '~');
+    try writer.writeByte('!');
     try f.writeCValue(writer, op, .Other);
     try writer.writeAll(";\n");
 
test/behavior/math.zig
@@ -532,6 +532,19 @@ fn testUnsignedNegationWrappingEval(x: u16) !void {
     try expect(neg == maxInt(u16));
 }
 
+test "negation wrapping" {
+    if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+    if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
+
+    try expectEqual(@as(u1, 1), negateWrap(u1, 1));
+}
+
+fn negateWrap(comptime T: type, x: T) T {
+    // This is specifically testing a safety-checked add, so
+    // special case minInt(T) which would overflow otherwise.
+    return if (x == minInt(T)) minInt(T) else ~x + 1;
+}
+
 test "unsigned 64-bit division" {
     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
     if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO