diff --git a/src/arch/aarch64/CodeGen.zig b/src/arch/aarch64/CodeGen.zig index b328c70f06..688f59e804 100644 --- a/src/arch/aarch64/CodeGen.zig +++ b/src/arch/aarch64/CodeGen.zig @@ -1138,6 +1138,8 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void { } }, }); + try self.truncRegister(dest_reg, dest_reg, int_info.signedness, int_info.bits); + break :result MCValue{ .register = dest_reg }; } else { return self.fail("TODO AArch64 not on integers > u64/i64", .{}); @@ -1516,11 +1518,8 @@ fn binOp( const int_info = lhs_ty.intInfo(self.target.*); if (int_info.bits <= 64) { const result_reg = result.register; - - if (int_info.bits < 64) { - try self.truncRegister(result_reg, result_reg, int_info.signedness, int_info.bits); - return result; - } else return result; + try self.truncRegister(result_reg, result_reg, int_info.signedness, int_info.bits); + return result; } else { return self.fail("TODO binary operations on integers > u64/i64", .{}); } @@ -1554,8 +1553,8 @@ fn binOp( else => unreachable, } }, - .shl, - .shr, + .shl_exact, + .shr_exact, => { switch (lhs_ty.zigTypeTag()) { .Vector => return self.fail("TODO binary operations on vectors", .{}), @@ -1565,16 +1564,16 @@ fn binOp( const rhs_immediate_ok = rhs == .immediate; const mir_tag_register: Mir.Inst.Tag = switch (tag) { - .shl => .lsl_register, - .shr => switch (lhs_ty.intInfo(self.target.*).signedness) { + .shl_exact => .lsl_register, + .shr_exact => switch (int_info.signedness) { .signed => Mir.Inst.Tag.asr_register, .unsigned => Mir.Inst.Tag.lsr_register, }, else => unreachable, }; const mir_tag_immediate: Mir.Inst.Tag = switch (tag) { - .shl => .lsl_immediate, - .shr => switch (lhs_ty.intInfo(self.target.*).signedness) { + .shl_exact => .lsl_immediate, + .shr_exact => switch (int_info.signedness) { .signed => Mir.Inst.Tag.asr_immediate, .unsigned => Mir.Inst.Tag.lsr_immediate, }, @@ -1593,6 +1592,38 @@ fn binOp( else => unreachable, } }, + .shl, + .shr, + => { + const base_tag: Air.Inst.Tag = switch (tag) { + .shl => .shl_exact, + .shr => .shr_exact, + else => unreachable, + }; + + // Generate a shl_exact/shr_exact + const result = try self.binOp(base_tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty); + + // Truncate if necessary + switch (tag) { + .shr => return result, + .shl => switch (lhs_ty.zigTypeTag()) { + .Vector => return self.fail("TODO binary operations on vectors", .{}), + .Int => { + const int_info = lhs_ty.intInfo(self.target.*); + if (int_info.bits <= 64) { + const result_reg = result.register; + try self.truncRegister(result_reg, result_reg, int_info.signedness, int_info.bits); + return result; + } else { + return self.fail("TODO binary operations on integers > u64/i64", .{}); + } + }, + else => unreachable, + }, + else => unreachable, + } + }, .bool_and, .bool_or, => { diff --git a/test/behavior/math.zig b/test/behavior/math.zig index ce316aeea2..f5494adfeb 100644 --- a/test/behavior/math.zig +++ b/test/behavior/math.zig @@ -363,7 +363,6 @@ fn comptimeAdd(comptime a: comptime_int, comptime b: comptime_int) comptime_int test "binary not" { if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO try expect(comptime x: { break :x ~@as(u16, 0b1010101010101010) == 0b0101010101010101; @@ -851,8 +850,6 @@ test "quad hex float literal parsing accurate" { } test "truncating shift left" { - if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO - try testShlTrunc(maxInt(u16)); comptime try testShlTrunc(maxInt(u16)); } @@ -863,7 +860,6 @@ fn testShlTrunc(x: u16) !void { test "exact shift left" { if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO try testShlExact(0b00110101); comptime try testShlExact(0b00110101); @@ -875,7 +871,6 @@ fn testShlExact(x: u8) !void { test "exact shift right" { if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO try testShrExact(0b10110100); comptime try testShrExact(0b10110100); @@ -887,7 +882,6 @@ fn testShrExact(x: u8) !void { test "shift left/right on u0 operand" { if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO const S = struct { fn doTheTest() !void {