From 7ed2f2156f4e93fa6463fb81f134c0d5e7e7cc89 Mon Sep 17 00:00:00 2001 From: David Rubin Date: Fri, 10 May 2024 23:21:53 -0700 Subject: [PATCH] riscv: fix register clobber in certain edge cases --- src/arch/riscv64/CodeGen.zig | 24 ++++++++++++------------ test/behavior/cast.zig | 1 - test/behavior/enum.zig | 2 -- test/behavior/switch.zig | 1 - 4 files changed, 12 insertions(+), 16 deletions(-) diff --git a/src/arch/riscv64/CodeGen.zig b/src/arch/riscv64/CodeGen.zig index 13652a7bca..af620ef365 100644 --- a/src/arch/riscv64/CodeGen.zig +++ b/src/arch/riscv64/CodeGen.zig @@ -1841,7 +1841,7 @@ fn airMinMax( if (int_info.bits > 64) return self.fail("TODO: > 64 bit @min", .{}); const lhs_reg, const lhs_lock = blk: { - if (lhs == .register) break :blk .{ lhs.register, null }; + if (lhs == .register) break :blk .{ lhs.register, self.register_manager.lockReg(lhs.register) }; const lhs_reg, const lhs_lock = try self.allocReg(); try self.genSetReg(lhs_ty, lhs_reg, lhs); @@ -1850,7 +1850,7 @@ fn airMinMax( defer if (lhs_lock) |lock| self.register_manager.unlockReg(lock); const rhs_reg, const rhs_lock = blk: { - if (rhs == .register) break :blk .{ rhs.register, null }; + if (rhs == .register) break :blk .{ rhs.register, self.register_manager.lockReg(rhs.register) }; const rhs_reg, const rhs_lock = try self.allocReg(); try self.genSetReg(rhs_ty, rhs_reg, rhs); @@ -2088,7 +2088,7 @@ fn binOpRegister( rhs_ty: Type, ) !MCValue { const lhs_reg, const lhs_lock = blk: { - if (lhs == .register) break :blk .{ lhs.register, null }; + if (lhs == .register) break :blk .{ lhs.register, self.register_manager.lockReg(lhs.register) }; const lhs_reg, const lhs_lock = try self.allocReg(); try self.genSetReg(lhs_ty, lhs_reg, lhs); @@ -2097,7 +2097,7 @@ fn binOpRegister( defer if (lhs_lock) |lock| self.register_manager.unlockReg(lock); const rhs_reg, const rhs_lock = blk: { - if (rhs == .register) break :blk .{ rhs.register, null }; + if (rhs == .register) break :blk .{ rhs.register, self.register_manager.lockReg(rhs.register) }; const rhs_reg, const rhs_lock = try self.allocReg(); try self.genSetReg(rhs_ty, rhs_reg, rhs); @@ -2358,7 +2358,7 @@ fn airSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void { const offset = result_mcv.load_frame; const lhs_reg, const lhs_lock = blk: { - if (lhs == .register) break :blk .{ lhs.register, null }; + if (lhs == .register) break :blk .{ lhs.register, self.register_manager.lockReg(lhs.register) }; const lhs_reg, const lhs_lock = try self.allocReg(); try self.genSetReg(lhs_ty, lhs_reg, lhs); @@ -2367,7 +2367,7 @@ fn airSubWithOverflow(self: *Self, inst: Air.Inst.Index) !void { defer if (lhs_lock) |lock| self.register_manager.unlockReg(lock); const rhs_reg, const rhs_lock = blk: { - if (rhs == .register) break :blk .{ rhs.register, null }; + if (rhs == .register) break :blk .{ rhs.register, self.register_manager.lockReg(rhs.register) }; const rhs_reg, const rhs_lock = try self.allocReg(); try self.genSetReg(rhs_ty, rhs_reg, rhs); @@ -2596,7 +2596,7 @@ fn airBitAnd(self: *Self, inst: Air.Inst.Index) !void { const rhs_ty = self.typeOf(bin_op.rhs); const lhs_reg, const lhs_lock = blk: { - if (lhs == .register) break :blk .{ lhs.register, null }; + if (lhs == .register) break :blk .{ lhs.register, self.register_manager.lockReg(lhs.register) }; const lhs_reg, const lhs_lock = try self.allocReg(); try self.genSetReg(lhs_ty, lhs_reg, lhs); @@ -2605,7 +2605,7 @@ fn airBitAnd(self: *Self, inst: Air.Inst.Index) !void { defer if (lhs_lock) |lock| self.register_manager.unlockReg(lock); const rhs_reg, const rhs_lock = blk: { - if (rhs == .register) break :blk .{ rhs.register, null }; + if (rhs == .register) break :blk .{ rhs.register, self.register_manager.lockReg(rhs.register) }; const rhs_reg, const rhs_lock = try self.allocReg(); try self.genSetReg(rhs_ty, rhs_reg, rhs); @@ -2641,7 +2641,7 @@ fn airBitOr(self: *Self, inst: Air.Inst.Index) !void { const rhs_ty = self.typeOf(bin_op.rhs); const lhs_reg, const lhs_lock = blk: { - if (lhs == .register) break :blk .{ lhs.register, null }; + if (lhs == .register) break :blk .{ lhs.register, self.register_manager.lockReg(lhs.register) }; const lhs_reg, const lhs_lock = try self.allocReg(); try self.genSetReg(lhs_ty, lhs_reg, lhs); @@ -2650,7 +2650,7 @@ fn airBitOr(self: *Self, inst: Air.Inst.Index) !void { defer if (lhs_lock) |lock| self.register_manager.unlockReg(lock); const rhs_reg, const rhs_lock = blk: { - if (rhs == .register) break :blk .{ rhs.register, null }; + if (rhs == .register) break :blk .{ rhs.register, self.register_manager.lockReg(rhs.register) }; const rhs_reg, const rhs_lock = try self.allocReg(); try self.genSetReg(rhs_ty, rhs_reg, rhs); @@ -4717,7 +4717,7 @@ fn airBoolOp(self: *Self, inst: Air.Inst.Index) !void { const rhs_ty = Type.bool; const lhs_reg, const lhs_lock = blk: { - if (lhs == .register) break :blk .{ lhs.register, null }; + if (lhs == .register) break :blk .{ lhs.register, self.register_manager.lockReg(lhs.register) }; const lhs_reg, const lhs_lock = try self.allocReg(); try self.genSetReg(lhs_ty, lhs_reg, lhs); @@ -4726,7 +4726,7 @@ fn airBoolOp(self: *Self, inst: Air.Inst.Index) !void { defer if (lhs_lock) |lock| self.register_manager.unlockReg(lock); const rhs_reg, const rhs_lock = blk: { - if (rhs == .register) break :blk .{ rhs.register, null }; + if (rhs == .register) break :blk .{ rhs.register, self.register_manager.lockReg(rhs.register) }; const rhs_reg, const rhs_lock = try self.allocReg(); try self.genSetReg(rhs_ty, rhs_reg, rhs); diff --git a/test/behavior/cast.zig b/test/behavior/cast.zig index a671010740..8ea564ad13 100644 --- a/test/behavior/cast.zig +++ b/test/behavior/cast.zig @@ -677,7 +677,6 @@ test "@floatCast cast down" { test "peer type resolution: unreachable, error set, unreachable" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; const Error = error{ FileDescriptorAlreadyPresentInSet, diff --git a/test/behavior/enum.zig b/test/behavior/enum.zig index cf899ed3ca..42138c1c15 100644 --- a/test/behavior/enum.zig +++ b/test/behavior/enum.zig @@ -618,7 +618,6 @@ test "enum with specified tag values" { test "non-exhaustive enum" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; const S = struct { const E = enum(u8) { a, b, _ }; @@ -683,7 +682,6 @@ test "empty non-exhaustive enum" { test "single field non-exhaustive enum" { if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; const S = struct { const E = enum(u8) { a, _ }; diff --git a/test/behavior/switch.zig b/test/behavior/switch.zig index 8db6989b98..6d82392958 100644 --- a/test/behavior/switch.zig +++ b/test/behavior/switch.zig @@ -216,7 +216,6 @@ fn poll() void { test "switch on global mutable var isn't constant-folded" { if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_riscv64) return error.SkipZigTest; while (state < 2) { poll();