authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-04-18 13:50:54+02:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-04-19 22:40:51+02:00
logfa85a739d9a85084fbb6d934c2c8803042fa7d48
tree7db631a9fb4d353eae4f6394629611f33c8573de
parentcbb13c023eb24d08b7f46119fad5e2aa1c7a63bb
signaturelock-open Commit is signed but in an unrecognized format.

stage2 AArch64: fix shl, shr, shl_exact, shr_exact

Introduces the necessary truncation after shift

2 files changed, 42 insertions(+), 17 deletions(-)

src/arch/aarch64/CodeGen.zig+42-11
...@@ -1138,6 +1138,8 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {...@@ -1138,6 +1138,8 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
1138 } },1138 } },
1139 });1139 });
11401140
1141 try self.truncRegister(dest_reg, dest_reg, int_info.signedness, int_info.bits);
1142
1141 break :result MCValue{ .register = dest_reg };1143 break :result MCValue{ .register = dest_reg };
1142 } else {1144 } else {
1143 return self.fail("TODO AArch64 not on integers > u64/i64", .{});1145 return self.fail("TODO AArch64 not on integers > u64/i64", .{});
...@@ -1516,11 +1518,8 @@ fn binOp(...@@ -1516,11 +1518,8 @@ fn binOp(
1516 const int_info = lhs_ty.intInfo(self.target.*);1518 const int_info = lhs_ty.intInfo(self.target.*);
1517 if (int_info.bits <= 64) {1519 if (int_info.bits <= 64) {
1518 const result_reg = result.register;1520 const result_reg = result.register;
15191521 try self.truncRegister(result_reg, result_reg, int_info.signedness, int_info.bits);
1520 if (int_info.bits < 64) {1522 return result;
1521 try self.truncRegister(result_reg, result_reg, int_info.signedness, int_info.bits);
1522 return result;
1523 } else return result;
1524 } else {1523 } else {
1525 return self.fail("TODO binary operations on integers > u64/i64", .{});1524 return self.fail("TODO binary operations on integers > u64/i64", .{});
1526 }1525 }
...@@ -1554,8 +1553,8 @@ fn binOp(...@@ -1554,8 +1553,8 @@ fn binOp(
1554 else => unreachable,1553 else => unreachable,
1555 }1554 }
1556 },1555 },
1557 .shl,1556 .shl_exact,
1558 .shr,1557 .shr_exact,
1559 => {1558 => {
1560 switch (lhs_ty.zigTypeTag()) {1559 switch (lhs_ty.zigTypeTag()) {
1561 .Vector => return self.fail("TODO binary operations on vectors", .{}),1560 .Vector => return self.fail("TODO binary operations on vectors", .{}),
...@@ -1565,16 +1564,16 @@ fn binOp(...@@ -1565,16 +1564,16 @@ fn binOp(
1565 const rhs_immediate_ok = rhs == .immediate;1564 const rhs_immediate_ok = rhs == .immediate;
15661565
1567 const mir_tag_register: Mir.Inst.Tag = switch (tag) {1566 const mir_tag_register: Mir.Inst.Tag = switch (tag) {
1568 .shl => .lsl_register,1567 .shl_exact => .lsl_register,
1569 .shr => switch (lhs_ty.intInfo(self.target.*).signedness) {1568 .shr_exact => switch (int_info.signedness) {
1570 .signed => Mir.Inst.Tag.asr_register,1569 .signed => Mir.Inst.Tag.asr_register,
1571 .unsigned => Mir.Inst.Tag.lsr_register,1570 .unsigned => Mir.Inst.Tag.lsr_register,
1572 },1571 },
1573 else => unreachable,1572 else => unreachable,
1574 };1573 };
1575 const mir_tag_immediate: Mir.Inst.Tag = switch (tag) {1574 const mir_tag_immediate: Mir.Inst.Tag = switch (tag) {
1576 .shl => .lsl_immediate,1575 .shl_exact => .lsl_immediate,
1577 .shr => switch (lhs_ty.intInfo(self.target.*).signedness) {1576 .shr_exact => switch (int_info.signedness) {
1578 .signed => Mir.Inst.Tag.asr_immediate,1577 .signed => Mir.Inst.Tag.asr_immediate,
1579 .unsigned => Mir.Inst.Tag.lsr_immediate,1578 .unsigned => Mir.Inst.Tag.lsr_immediate,
1580 },1579 },
...@@ -1593,6 +1592,38 @@ fn binOp(...@@ -1593,6 +1592,38 @@ fn binOp(
1593 else => unreachable,1592 else => unreachable,
1594 }1593 }
1595 },1594 },
1595 .shl,
1596 .shr,
1597 => {
1598 const base_tag: Air.Inst.Tag = switch (tag) {
1599 .shl => .shl_exact,
1600 .shr => .shr_exact,
1601 else => unreachable,
1602 };
1603
1604 // Generate a shl_exact/shr_exact
1605 const result = try self.binOp(base_tag, maybe_inst, lhs, rhs, lhs_ty, rhs_ty);
1606
1607 // Truncate if necessary
1608 switch (tag) {
1609 .shr => return result,
1610 .shl => switch (lhs_ty.zigTypeTag()) {
1611 .Vector => return self.fail("TODO binary operations on vectors", .{}),
1612 .Int => {
1613 const int_info = lhs_ty.intInfo(self.target.*);
1614 if (int_info.bits <= 64) {
1615 const result_reg = result.register;
1616 try self.truncRegister(result_reg, result_reg, int_info.signedness, int_info.bits);
1617 return result;
1618 } else {
1619 return self.fail("TODO binary operations on integers > u64/i64", .{});
1620 }
1621 },
1622 else => unreachable,
1623 },
1624 else => unreachable,
1625 }
1626 },
1596 .bool_and,1627 .bool_and,
1597 .bool_or,1628 .bool_or,
1598 => {1629 => {
test/behavior/math.zig-6
...@@ -363,7 +363,6 @@ fn comptimeAdd(comptime a: comptime_int, comptime b: comptime_int) comptime_int...@@ -363,7 +363,6 @@ fn comptimeAdd(comptime a: comptime_int, comptime b: comptime_int) comptime_int
363test "binary not" {363test "binary not" {
364 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO364 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
365 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO365 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
366 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
367366
368 try expect(comptime x: {367 try expect(comptime x: {
369 break :x ~@as(u16, 0b1010101010101010) == 0b0101010101010101;368 break :x ~@as(u16, 0b1010101010101010) == 0b0101010101010101;
...@@ -851,8 +850,6 @@ test "quad hex float literal parsing accurate" {...@@ -851,8 +850,6 @@ test "quad hex float literal parsing accurate" {
851}850}
852851
853test "truncating shift left" {852test "truncating shift left" {
854 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
855
856 try testShlTrunc(maxInt(u16));853 try testShlTrunc(maxInt(u16));
857 comptime try testShlTrunc(maxInt(u16));854 comptime try testShlTrunc(maxInt(u16));
858}855}
...@@ -863,7 +860,6 @@ fn testShlTrunc(x: u16) !void {...@@ -863,7 +860,6 @@ fn testShlTrunc(x: u16) !void {
863860
864test "exact shift left" {861test "exact shift left" {
865 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO862 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
866 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
867863
868 try testShlExact(0b00110101);864 try testShlExact(0b00110101);
869 comptime try testShlExact(0b00110101);865 comptime try testShlExact(0b00110101);
...@@ -875,7 +871,6 @@ fn testShlExact(x: u8) !void {...@@ -875,7 +871,6 @@ fn testShlExact(x: u8) !void {
875871
876test "exact shift right" {872test "exact shift right" {
877 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO873 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
878 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
879874
880 try testShrExact(0b10110100);875 try testShrExact(0b10110100);
881 comptime try testShrExact(0b10110100);876 comptime try testShrExact(0b10110100);
...@@ -887,7 +882,6 @@ fn testShrExact(x: u8) !void {...@@ -887,7 +882,6 @@ fn testShrExact(x: u8) !void {
887882
888test "shift left/right on u0 operand" {883test "shift left/right on u0 operand" {
889 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO884 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
890 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
891885
892 const S = struct {886 const S = struct {
893 fn doTheTest() !void {887 fn doTheTest() !void {