Commit fa85a739d9

joachimschmidt557 <joachim.schmidt557@outlook.com>
2022-04-18 13:50:54
stage2 AArch64: fix shl, shr, shl_exact, shr_exact
Introduces the necessary truncation after shift
1 parent cbb13c0
Changed files (2)
src
arch
aarch64
test
behavior
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,
         => {
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 {