Commit 2412ac2c5f

joachimschmidt557 <joachim.schmidt557@outlook.com>
2022-03-13 20:54:29
stage2 ARM: fix shl for ints with bits < 32
1 parent 0eebdfc
Changed files (2)
src
arch
test
behavior
src/arch/arm/CodeGen.zig
@@ -1983,8 +1983,8 @@ fn binOpRegister(
     if (!rhs_is_register) try self.genSetReg(rhs_ty, rhs_reg, rhs);
 
     const mir_tag: Mir.Inst.Tag = switch (tag) {
-        .add, .ptr_add => .add,
-        .sub, .ptr_sub => .sub,
+        .add => .add,
+        .sub => .sub,
         .cmp_eq => .cmp,
         .mul => .mul,
         .bit_and,
@@ -1993,12 +1993,8 @@ fn binOpRegister(
         .bit_or,
         .bool_or,
         => .orr,
-        .shl,
-        .shl_exact,
-        => .lsl,
-        .shr,
-        .shr_exact,
-        => switch (lhs_ty.intInfo(self.target.*).signedness) {
+        .shl_exact => .lsl,
+        .shr_exact => switch (lhs_ty.intInfo(self.target.*).signedness) {
             .signed => Mir.Inst.Tag.asr,
             .unsigned => Mir.Inst.Tag.lsr,
         },
@@ -2014,16 +2010,12 @@ fn binOpRegister(
         .bit_or,
         .bool_or,
         .xor,
-        .ptr_add,
-        .ptr_sub,
         => .{ .rr_op = .{
             .rd = dest_reg,
             .rn = lhs_reg,
             .op = Instruction.Operand.reg(rhs_reg, Instruction.Operand.Shift.none),
         } },
-        .shl,
         .shl_exact,
-        .shr,
         .shr_exact,
         => .{ .rr_shift = .{
             .rd = dest_reg,
@@ -2120,12 +2112,8 @@ fn binOpImmediate(
         .bit_or,
         .bool_or,
         => .orr,
-        .shl,
-        .shl_exact,
-        => .lsl,
-        .shr,
-        .shr_exact,
-        => switch (lhs_ty.intInfo(self.target.*).signedness) {
+        .shl_exact => .lsl,
+        .shr_exact => switch (lhs_ty.intInfo(self.target.*).signedness) {
             .signed => Mir.Inst.Tag.asr,
             .unsigned => Mir.Inst.Tag.lsr,
         },
@@ -2146,9 +2134,7 @@ fn binOpImmediate(
             .rn = lhs_reg,
             .op = Instruction.Operand.fromU32(rhs.immediate).?,
         } },
-        .shl,
         .shl_exact,
-        .shr,
         .shr_exact,
         => .{ .rr_shift = .{
             .rd = dest_reg,
@@ -2279,8 +2265,8 @@ fn binOp(
                 else => unreachable,
             }
         },
-        .shl,
-        .shr,
+        .shl_exact,
+        .shr_exact,
         => {
             switch (lhs_ty.zigTypeTag()) {
                 .Vector => return self.fail("TODO ARM binary operations on vectors", .{}),
@@ -2301,6 +2287,41 @@ 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 ARM binary operations on vectors", .{}),
+                    .Int => {
+                        const int_info = lhs_ty.intInfo(self.target.*);
+                        if (int_info.bits <= 32) {
+                            const result_reg = result.register;
+
+                            if (int_info.bits < 32) {
+                                try self.truncRegister(result_reg, result_reg, int_info.signedness, int_info.bits);
+                                return result;
+                            } else return result;
+                        } else {
+                            return self.fail("TODO ARM binary operations on integers > u32/i32", .{});
+                        }
+                    },
+                    else => unreachable,
+                },
+                else => unreachable,
+            }
+        },
         .bool_and,
         .bool_or,
         => {
@@ -2334,7 +2355,13 @@ fn binOp(
                     const elem_size = @intCast(u32, elem_ty.abiSize(self.target.*));
 
                     if (elem_size == 1) {
-                        return try self.binOpRegister(tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
+                        const base_tag: Air.Inst.Tag = switch (tag) {
+                            .ptr_add => .add,
+                            .ptr_sub => .sub,
+                            else => unreachable,
+                        };
+
+                        return try self.binOpRegister(base_tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
                     } else {
                         // convert the offset into a byte offset by
                         // multiplying it with elem_size
test/behavior/math.zig
@@ -864,7 +864,6 @@ test "quad hex float literal parsing accurate" {
 
 test "truncating shift left" {
     if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
-    if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
 
     try testShlTrunc(maxInt(u16));
@@ -877,7 +876,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_arm) return error.SkipZigTest; // TODO
     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
 
     try testShlExact(0b00110101);
@@ -890,7 +888,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_arm) return error.SkipZigTest; // TODO
     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
 
     try testShrExact(0b10110100);