diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 2cd24f69b3..51b2f30cae 100644 --- a/src/codegen/c.zig +++ b/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"); diff --git a/test/behavior/math.zig b/test/behavior/math.zig index d819743390..763c249c50 100644 --- a/test/behavior/math.zig +++ b/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