authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-05-07 00:57:55+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-05-07 00:57:55+02:00
logac954eb539ec242af568fe3565094cea12c4beea
tree388b3c11137f23393ff877699f86df4b43666501
parentac1aaec9c38eb44b93099ff18579a9401f107100

regalloc: ensure we only freeze/unfreeze at the outermost scope

This prevents a nasty type of bugs where we accidentally unfreeze a register that was frozen purposely in the outer scope, risking accidental realloc of a taken register. Fix CF flags spilling on aarch64 backend.

6 files changed, 735 insertions(+), 413 deletions(-)

src/arch/aarch64/CodeGen.zig+152-67
...@@ -23,6 +23,7 @@ const log = std.log.scoped(.codegen);...@@ -23,6 +23,7 @@ const log = std.log.scoped(.codegen);
23const build_options = @import("build_options");23const build_options = @import("build_options");
24const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;24const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;
25const RegisterManager = RegisterManagerFn(Self, Register, &callee_preserved_regs);25const RegisterManager = RegisterManagerFn(Self, Register, &callee_preserved_regs);
26const RegisterLock = RegisterManager.RegisterLock;
2627
27const GenerateSymbolError = @import("../../codegen.zig").GenerateSymbolError;28const GenerateSymbolError = @import("../../codegen.zig").GenerateSymbolError;
28const FnResult = @import("../../codegen.zig").FnResult;29const FnResult = @import("../../codegen.zig").FnResult;
...@@ -910,16 +911,16 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void...@@ -910,16 +911,16 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void
910fn spillCompareFlagsIfOccupied(self: *Self) !void {911fn spillCompareFlagsIfOccupied(self: *Self) !void {
911 if (self.compare_flags_inst) |inst_to_save| {912 if (self.compare_flags_inst) |inst_to_save| {
912 const mcv = self.getResolvedInstValue(inst_to_save);913 const mcv = self.getResolvedInstValue(inst_to_save);
913 switch (mcv) {914 const new_mcv = switch (mcv) {
914 .compare_flags_signed,915 .compare_flags_signed,
915 .compare_flags_unsigned,916 .compare_flags_unsigned,
917 => try self.allocRegOrMem(inst_to_save, true),
916 .register_c_flag,918 .register_c_flag,
917 .register_v_flag,919 .register_v_flag,
918 => {},920 => try self.allocRegOrMem(inst_to_save, false),
919 else => unreachable, // mcv doesn't occupy the compare flags921 else => unreachable, // mcv doesn't occupy the compare flags
920 }922 };
921923
922 const new_mcv = try self.allocRegOrMem(inst_to_save, true);
923 try self.setRegOrMem(self.air.typeOfIndex(inst_to_save), new_mcv, mcv);924 try self.setRegOrMem(self.air.typeOfIndex(inst_to_save), new_mcv, mcv);
924 log.debug("spilling {d} to mcv {any}", .{ inst_to_save, new_mcv });925 log.debug("spilling {d} to mcv {any}", .{ inst_to_save, new_mcv });
925926
...@@ -927,6 +928,15 @@ fn spillCompareFlagsIfOccupied(self: *Self) !void {...@@ -927,6 +928,15 @@ fn spillCompareFlagsIfOccupied(self: *Self) !void {
927 try branch.inst_table.put(self.gpa, inst_to_save, new_mcv);928 try branch.inst_table.put(self.gpa, inst_to_save, new_mcv);
928929
929 self.compare_flags_inst = null;930 self.compare_flags_inst = null;
931
932 // TODO consolidate with register manager and spillInstruction
933 // this call should really belong in the register manager!
934 switch (mcv) {
935 .register_c_flag,
936 .register_v_flag,
937 => |reg| self.register_manager.freeReg(reg),
938 else => {},
939 }
930 }940 }
931}941}
932942
...@@ -1048,8 +1058,8 @@ fn trunc(...@@ -1048,8 +1058,8 @@ fn trunc(
1048 }1058 }
1049 },1059 },
1050 };1060 };
1051 self.register_manager.freezeRegs(&.{operand_reg});1061 const lock = self.register_manager.freezeReg(operand_reg);
1052 defer self.register_manager.unfreezeRegs(&.{operand_reg});1062 defer if (lock) |reg| self.register_manager.unfreezeReg(reg);
10531063
1054 const dest_reg = if (maybe_inst) |inst| blk: {1064 const dest_reg = if (maybe_inst) |inst| blk: {
1055 const ty_op = self.air.instructions.items(.data)[inst].ty_op;1065 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
...@@ -1135,8 +1145,8 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {...@@ -1135,8 +1145,8 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
1135 .register => |r| r,1145 .register => |r| r,
1136 else => try self.copyToTmpRegister(operand_ty, operand),1146 else => try self.copyToTmpRegister(operand_ty, operand),
1137 };1147 };
1138 self.register_manager.freezeRegs(&.{op_reg});1148 const reg_lock = self.register_manager.freezeRegAssumeUnused(op_reg);
1139 defer self.register_manager.unfreezeRegs(&.{op_reg});1149 defer self.register_manager.unfreezeReg(reg_lock);
11401150
1141 const dest_reg = blk: {1151 const dest_reg = blk: {
1142 if (operand == .register and self.reuseOperand(inst, ty_op.operand, 0, operand)) {1152 if (operand == .register and self.reuseOperand(inst, ty_op.operand, 0, operand)) {
...@@ -1168,8 +1178,8 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {...@@ -1168,8 +1178,8 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
1168 .register => |r| r,1178 .register => |r| r,
1169 else => try self.copyToTmpRegister(operand_ty, operand),1179 else => try self.copyToTmpRegister(operand_ty, operand),
1170 };1180 };
1171 self.register_manager.freezeRegs(&.{op_reg});1181 const reg_lock = self.register_manager.freezeRegAssumeUnused(op_reg);
1172 defer self.register_manager.unfreezeRegs(&.{op_reg});1182 defer self.register_manager.unfreezeReg(reg_lock);
11731183
1174 const dest_reg = blk: {1184 const dest_reg = blk: {
1175 if (operand == .register and self.reuseOperand(inst, ty_op.operand, 0, operand)) {1185 if (operand == .register and self.reuseOperand(inst, ty_op.operand, 0, operand)) {
...@@ -1257,8 +1267,17 @@ fn binOpRegister(...@@ -1257,8 +1267,17 @@ fn binOpRegister(
1257 const lhs_is_register = lhs == .register;1267 const lhs_is_register = lhs == .register;
1258 const rhs_is_register = rhs == .register;1268 const rhs_is_register = rhs == .register;
12591269
1260 if (lhs_is_register) self.register_manager.freezeRegs(&.{lhs.register});1270 const lhs_lock: ?RegisterLock = if (lhs_is_register)
1261 if (rhs_is_register) self.register_manager.freezeRegs(&.{rhs.register});1271 self.register_manager.freezeReg(lhs.register)
1272 else
1273 null;
1274 defer if (lhs_lock) |reg| self.register_manager.unfreezeReg(reg);
1275
1276 const rhs_lock: ?RegisterLock = if (rhs_is_register)
1277 self.register_manager.freezeReg(rhs.register)
1278 else
1279 null;
1280 defer if (rhs_lock) |reg| self.register_manager.unfreezeReg(reg);
12621281
1263 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];1282 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
12641283
...@@ -1270,13 +1289,13 @@ fn binOpRegister(...@@ -1270,13 +1289,13 @@ fn binOpRegister(
12701289
1271 const raw_reg = try self.register_manager.allocReg(track_inst);1290 const raw_reg = try self.register_manager.allocReg(track_inst);
1272 const reg = registerAlias(raw_reg, lhs_ty.abiSize(self.target.*));1291 const reg = registerAlias(raw_reg, lhs_ty.abiSize(self.target.*));
1273 self.register_manager.freezeRegs(&.{reg});
12741292
1275 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });1293 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
12761294
1277 break :blk reg;1295 break :blk reg;
1278 };1296 };
1279 defer self.register_manager.unfreezeRegs(&.{lhs_reg});1297 const new_lhs_lock = self.register_manager.freezeReg(lhs_reg);
1298 defer if (new_lhs_lock) |reg| self.register_manager.unfreezeReg(reg);
12801299
1281 const rhs_reg = if (rhs_is_register) rhs.register else blk: {1300 const rhs_reg = if (rhs_is_register) rhs.register else blk: {
1282 const track_inst: ?Air.Inst.Index = if (maybe_inst) |inst| inst: {1301 const track_inst: ?Air.Inst.Index = if (maybe_inst) |inst| inst: {
...@@ -1286,13 +1305,13 @@ fn binOpRegister(...@@ -1286,13 +1305,13 @@ fn binOpRegister(
12861305
1287 const raw_reg = try self.register_manager.allocReg(track_inst);1306 const raw_reg = try self.register_manager.allocReg(track_inst);
1288 const reg = registerAlias(raw_reg, rhs_ty.abiAlignment(self.target.*));1307 const reg = registerAlias(raw_reg, rhs_ty.abiAlignment(self.target.*));
1289 self.register_manager.freezeRegs(&.{reg});
12901308
1291 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });1309 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
12921310
1293 break :blk reg;1311 break :blk reg;
1294 };1312 };
1295 defer self.register_manager.unfreezeRegs(&.{rhs_reg});1313 const new_rhs_lock = self.register_manager.freezeReg(rhs_reg);
1314 defer if (new_rhs_lock) |reg| self.register_manager.unfreezeReg(reg);
12961315
1297 const dest_reg = switch (mir_tag) {1316 const dest_reg = switch (mir_tag) {
1298 .cmp_shifted_register => undefined, // cmp has no destination register1317 .cmp_shifted_register => undefined, // cmp has no destination register
...@@ -1394,7 +1413,11 @@ fn binOpImmediate(...@@ -1394,7 +1413,11 @@ fn binOpImmediate(
1394) !MCValue {1413) !MCValue {
1395 const lhs_is_register = lhs == .register;1414 const lhs_is_register = lhs == .register;
13961415
1397 if (lhs_is_register) self.register_manager.freezeRegs(&.{lhs.register});1416 const lhs_lock: ?RegisterLock = if (lhs_is_register)
1417 self.register_manager.freezeReg(lhs.register)
1418 else
1419 null;
1420 defer if (lhs_lock) |reg| self.register_manager.unfreezeReg(reg);
13981421
1399 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];1422 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
14001423
...@@ -1408,13 +1431,13 @@ fn binOpImmediate(...@@ -1408,13 +1431,13 @@ fn binOpImmediate(
14081431
1409 const raw_reg = try self.register_manager.allocReg(track_inst);1432 const raw_reg = try self.register_manager.allocReg(track_inst);
1410 const reg = registerAlias(raw_reg, lhs_ty.abiSize(self.target.*));1433 const reg = registerAlias(raw_reg, lhs_ty.abiSize(self.target.*));
1411 self.register_manager.freezeRegs(&.{reg});
14121434
1413 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });1435 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
14141436
1415 break :blk reg;1437 break :blk reg;
1416 };1438 };
1417 defer self.register_manager.unfreezeRegs(&.{lhs_reg});1439 const new_lhs_lock = self.register_manager.freezeReg(lhs_reg);
1440 defer if (new_lhs_lock) |reg| self.register_manager.unfreezeReg(reg);
14181441
1419 const dest_reg = switch (mir_tag) {1442 const dest_reg = switch (mir_tag) {
1420 .cmp_immediate => undefined, // cmp has no destination register1443 .cmp_immediate => undefined, // cmp has no destination register
...@@ -1758,7 +1781,10 @@ fn airBinOp(self: *Self, inst: Air.Inst.Index) !void {...@@ -1758,7 +1781,10 @@ fn airBinOp(self: *Self, inst: Air.Inst.Index) !void {
1758 const lhs_ty = self.air.typeOf(bin_op.lhs);1781 const lhs_ty = self.air.typeOf(bin_op.lhs);
1759 const rhs_ty = self.air.typeOf(bin_op.rhs);1782 const rhs_ty = self.air.typeOf(bin_op.rhs);
17601783
1761 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else try self.binOp(tag, inst, lhs, rhs, lhs_ty, rhs_ty);1784 const result: MCValue = if (self.liveness.isUnused(inst))
1785 .dead
1786 else
1787 try self.binOp(tag, inst, lhs, rhs, lhs_ty, rhs_ty);
1762 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });1788 return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none });
1763}1789}
17641790
...@@ -1815,13 +1841,13 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1815,13 +1841,13 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {
1815 };1841 };
1816 const dest = try self.binOp(base_tag, null, lhs, rhs, lhs_ty, rhs_ty);1842 const dest = try self.binOp(base_tag, null, lhs, rhs, lhs_ty, rhs_ty);
1817 const dest_reg = dest.register;1843 const dest_reg = dest.register;
1818 self.register_manager.freezeRegs(&.{dest_reg});1844 const dest_reg_lock = self.register_manager.freezeRegAssumeUnused(dest_reg);
1819 defer self.register_manager.unfreezeRegs(&.{dest_reg});1845 defer self.register_manager.unfreezeReg(dest_reg_lock);
18201846
1821 const raw_truncated_reg = try self.register_manager.allocReg(null);1847 const raw_truncated_reg = try self.register_manager.allocReg(null);
1822 const truncated_reg = registerAlias(raw_truncated_reg, lhs_ty.abiSize(self.target.*));1848 const truncated_reg = registerAlias(raw_truncated_reg, lhs_ty.abiSize(self.target.*));
1823 self.register_manager.freezeRegs(&.{truncated_reg});1849 const truncated_reg_lock = self.register_manager.freezeRegAssumeUnused(truncated_reg);
1824 defer self.register_manager.unfreezeRegs(&.{truncated_reg});1850 defer self.register_manager.unfreezeReg(truncated_reg_lock);
18251851
1826 // sbfx/ubfx truncated, dest, #0, #bits1852 // sbfx/ubfx truncated, dest, #0, #bits
1827 try self.truncRegister(dest_reg, truncated_reg, int_info.signedness, int_info.bits);1853 try self.truncRegister(dest_reg, truncated_reg, int_info.signedness, int_info.bits);
...@@ -1922,12 +1948,12 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1922,12 +1948,12 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
19221948
1923 const dest = try self.binOpRegister(base_tag, null, lhs, rhs, lhs_ty, rhs_ty);1949 const dest = try self.binOpRegister(base_tag, null, lhs, rhs, lhs_ty, rhs_ty);
1924 const dest_reg = dest.register;1950 const dest_reg = dest.register;
1925 self.register_manager.freezeRegs(&.{dest_reg});1951 const dest_reg_lock = self.register_manager.freezeRegAssumeUnused(dest_reg);
1926 defer self.register_manager.unfreezeRegs(&.{dest_reg});1952 defer self.register_manager.unfreezeReg(dest_reg_lock);
19271953
1928 const truncated_reg = try self.register_manager.allocReg(null);1954 const truncated_reg = try self.register_manager.allocReg(null);
1929 self.register_manager.freezeRegs(&.{truncated_reg});1955 const truncated_reg_lock = self.register_manager.freezeRegAssumeUnused(truncated_reg);
1930 defer self.register_manager.unfreezeRegs(&.{truncated_reg});1956 defer self.register_manager.unfreezeReg(truncated_reg_lock);
19311957
1932 try self.truncRegister(1958 try self.truncRegister(
1933 dest_reg.to32(),1959 dest_reg.to32(),
...@@ -1977,36 +2003,44 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1977,36 +2003,44 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1977 const lhs_is_register = lhs == .register;2003 const lhs_is_register = lhs == .register;
1978 const rhs_is_register = rhs == .register;2004 const rhs_is_register = rhs == .register;
19792005
1980 if (lhs_is_register) self.register_manager.freezeRegs(&.{lhs.register});2006 const lhs_lock: ?RegisterLock = if (lhs_is_register)
1981 if (rhs_is_register) self.register_manager.freezeRegs(&.{rhs.register});2007 self.register_manager.freezeRegAssumeUnused(lhs.register)
2008 else
2009 null;
2010 defer if (lhs_lock) |reg| self.register_manager.unfreezeReg(reg);
2011
2012 const rhs_lock: ?RegisterLock = if (rhs_is_register)
2013 self.register_manager.freezeRegAssumeUnused(rhs.register)
2014 else
2015 null;
2016 defer if (rhs_lock) |reg| self.register_manager.unfreezeReg(reg);
19822017
1983 const lhs_reg = if (lhs_is_register) lhs.register else blk: {2018 const lhs_reg = if (lhs_is_register) lhs.register else blk: {
1984 const raw_reg = try self.register_manager.allocReg(null);2019 const raw_reg = try self.register_manager.allocReg(null);
1985 const reg = registerAlias(raw_reg, lhs_ty.abiSize(self.target.*));2020 const reg = registerAlias(raw_reg, lhs_ty.abiSize(self.target.*));
1986 self.register_manager.freezeRegs(&.{reg});
1987 break :blk reg;2021 break :blk reg;
1988 };2022 };
1989 defer self.register_manager.unfreezeRegs(&.{lhs_reg});2023 const new_lhs_lock = self.register_manager.freezeReg(lhs_reg);
2024 defer if (new_lhs_lock) |reg| self.register_manager.unfreezeReg(reg);
19902025
1991 const rhs_reg = if (rhs_is_register) rhs.register else blk: {2026 const rhs_reg = if (rhs_is_register) rhs.register else blk: {
1992 const raw_reg = try self.register_manager.allocReg(null);2027 const raw_reg = try self.register_manager.allocReg(null);
1993 const reg = registerAlias(raw_reg, rhs_ty.abiAlignment(self.target.*));2028 const reg = registerAlias(raw_reg, rhs_ty.abiAlignment(self.target.*));
1994 self.register_manager.freezeRegs(&.{reg});
1995 break :blk reg;2029 break :blk reg;
1996 };2030 };
1997 defer self.register_manager.unfreezeRegs(&.{rhs_reg});2031 const new_rhs_lock = self.register_manager.freezeReg(rhs_reg);
2032 defer if (new_rhs_lock) |reg| self.register_manager.unfreezeReg(reg);
19982033
1999 if (!lhs_is_register) try self.genSetReg(lhs_ty, lhs_reg, lhs);2034 if (!lhs_is_register) try self.genSetReg(lhs_ty, lhs_reg, lhs);
2000 if (!rhs_is_register) try self.genSetReg(rhs_ty, rhs_reg, rhs);2035 if (!rhs_is_register) try self.genSetReg(rhs_ty, rhs_reg, rhs);
20012036
2002 // TODO reuse operands
2003 const dest_reg = blk: {2037 const dest_reg = blk: {
2004 const raw_reg = try self.register_manager.allocReg(null);2038 const raw_reg = try self.register_manager.allocReg(null);
2005 const reg = registerAlias(raw_reg, lhs_ty.abiSize(self.target.*));2039 const reg = registerAlias(raw_reg, lhs_ty.abiSize(self.target.*));
2006 self.register_manager.freezeRegs(&.{reg});
2007 break :blk reg;2040 break :blk reg;
2008 };2041 };
2009 defer self.register_manager.unfreezeRegs(&.{dest_reg});2042 const dest_reg_lock = self.register_manager.freezeRegAssumeUnused(dest_reg);
2043 defer self.register_manager.unfreezeReg(dest_reg_lock);
20102044
2011 switch (int_info.signedness) {2045 switch (int_info.signedness) {
2012 .signed => {2046 .signed => {
...@@ -2021,8 +2055,8 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -2021,8 +2055,8 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
2021 });2055 });
20222056
2023 const dest_high_reg = try self.register_manager.allocReg(null);2057 const dest_high_reg = try self.register_manager.allocReg(null);
2024 self.register_manager.freezeRegs(&.{dest_high_reg});2058 const dest_high_reg_lock = self.register_manager.freezeRegAssumeUnused(dest_high_reg);
2025 defer self.register_manager.unfreezeRegs(&.{dest_high_reg});2059 defer self.register_manager.unfreezeReg(dest_high_reg_lock);
20262060
2027 // smulh dest_high, lhs, rhs2061 // smulh dest_high, lhs, rhs
2028 _ = try self.addInst(.{2062 _ = try self.addInst(.{
...@@ -2071,8 +2105,8 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -2071,8 +2105,8 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
2071 },2105 },
2072 .unsigned => {2106 .unsigned => {
2073 const dest_high_reg = try self.register_manager.allocReg(null);2107 const dest_high_reg = try self.register_manager.allocReg(null);
2074 self.register_manager.freezeRegs(&.{dest_high_reg});2108 const dest_high_reg_lock = self.register_manager.freezeRegAssumeUnused(dest_high_reg);
2075 defer self.register_manager.unfreezeRegs(&.{dest_high_reg});2109 defer self.register_manager.unfreezeReg(dest_high_reg_lock);
20762110
2077 // umulh dest_high, lhs, rhs2111 // umulh dest_high, lhs, rhs
2078 _ = try self.addInst(.{2112 _ = try self.addInst(.{
...@@ -2127,8 +2161,8 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -2127,8 +2161,8 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
2127 }2161 }
21282162
2129 const truncated_reg = try self.register_manager.allocReg(null);2163 const truncated_reg = try self.register_manager.allocReg(null);
2130 self.register_manager.freezeRegs(&.{truncated_reg});2164 const truncated_reg_lock = self.register_manager.freezeRegAssumeUnused(truncated_reg);
2131 defer self.register_manager.unfreezeRegs(&.{truncated_reg});2165 defer self.register_manager.unfreezeReg(truncated_reg_lock);
21322166
2133 try self.truncRegister(dest_reg, truncated_reg, int_info.signedness, int_info.bits);2167 try self.truncRegister(dest_reg, truncated_reg, int_info.signedness, int_info.bits);
21342168
...@@ -2168,14 +2202,20 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -2168,14 +2202,20 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
2168 if (int_info.bits <= 64) {2202 if (int_info.bits <= 64) {
2169 const stack_offset = try self.allocMem(inst, tuple_size, tuple_align);2203 const stack_offset = try self.allocMem(inst, tuple_size, tuple_align);
21702204
2171 if (lhs == .register) self.register_manager.freezeRegs(&.{lhs.register});2205 const lhs_lock: ?RegisterLock = if (lhs == .register)
2172 defer if (lhs == .register) self.register_manager.unfreezeRegs(&.{lhs.register});2206 self.register_manager.freezeRegAssumeUnused(lhs.register)
2207 else
2208 null;
2209 defer if (lhs_lock) |reg| self.register_manager.unfreezeReg(reg);
21732210
2174 try self.spillCompareFlagsIfOccupied();2211 try self.spillCompareFlagsIfOccupied();
2175 self.compare_flags_inst = null;2212 self.compare_flags_inst = null;
21762213
2177 // lsl dest, lhs, rhs2214 // lsl dest, lhs, rhs
2178 const dest = try self.binOp(.shl, null, lhs, rhs, lhs_ty, rhs_ty);2215 const dest = try self.binOp(.shl, null, lhs, rhs, lhs_ty, rhs_ty);
2216 const dest_reg = dest.register;
2217 const dest_reg_lock = self.register_manager.freezeRegAssumeUnused(dest_reg);
2218 defer self.register_manager.unfreezeReg(dest_reg_lock);
21792219
2180 // asr/lsr reconstructed, dest, rhs2220 // asr/lsr reconstructed, dest, rhs
2181 const reconstructed = try self.binOp(.shr, null, dest, rhs, lhs_ty, rhs_ty);2221 const reconstructed = try self.binOp(.shr, null, dest, rhs, lhs_ty, rhs_ty);
...@@ -2184,7 +2224,9 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -2184,7 +2224,9 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
2184 _ = try self.binOp(.cmp_eq, null, lhs, reconstructed, lhs_ty, lhs_ty);2224 _ = try self.binOp(.cmp_eq, null, lhs, reconstructed, lhs_ty, lhs_ty);
21852225
2186 try self.genSetStack(lhs_ty, stack_offset, dest);2226 try self.genSetStack(lhs_ty, stack_offset, dest);
2187 try self.genSetStack(Type.initTag(.u1), stack_offset - overflow_bit_offset, .{ .compare_flags_unsigned = .neq });2227 try self.genSetStack(Type.initTag(.u1), stack_offset - overflow_bit_offset, .{
2228 .compare_flags_unsigned = .neq,
2229 });
21882230
2189 break :result MCValue{ .stack_offset = stack_offset };2231 break :result MCValue{ .stack_offset = stack_offset };
2190 } else {2232 } else {
...@@ -2411,14 +2453,18 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -2411,14 +2453,18 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {
2411 var buf: Type.SlicePtrFieldTypeBuffer = undefined;2453 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
2412 const slice_ptr_field_type = slice_ty.slicePtrFieldType(&buf);2454 const slice_ptr_field_type = slice_ty.slicePtrFieldType(&buf);
24132455
2414 if (index_is_register) self.register_manager.freezeRegs(&.{index_mcv.register});2456 const index_lock: ?RegisterLock = if (index_is_register)
2415 defer if (index_is_register) self.register_manager.unfreezeRegs(&.{index_mcv.register});2457 self.register_manager.freezeRegAssumeUnused(index_mcv.register)
2458 else
2459 null;
2460 defer if (index_lock) |reg| self.register_manager.unfreezeReg(reg);
24162461
2417 const base_mcv: MCValue = switch (slice_mcv) {2462 const base_mcv: MCValue = switch (slice_mcv) {
2418 .stack_offset => |off| .{ .register = try self.copyToTmpRegister(slice_ptr_field_type, .{ .stack_offset = off }) },2463 .stack_offset => |off| .{ .register = try self.copyToTmpRegister(slice_ptr_field_type, .{ .stack_offset = off }) },
2419 else => return self.fail("TODO slice_elem_val when slice is {}", .{slice_mcv}),2464 else => return self.fail("TODO slice_elem_val when slice is {}", .{slice_mcv}),
2420 };2465 };
2421 self.register_manager.freezeRegs(&.{base_mcv.register});2466 const base_lock = self.register_manager.freezeRegAssumeUnused(base_mcv.register);
2467 defer self.register_manager.unfreezeReg(base_lock);
24222468
2423 switch (elem_size) {2469 switch (elem_size) {
2424 else => {2470 else => {
...@@ -2559,8 +2605,8 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo...@@ -2559,8 +2605,8 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
2559 .immediate => |imm| try self.setRegOrMem(elem_ty, dst_mcv, .{ .memory = imm }),2605 .immediate => |imm| try self.setRegOrMem(elem_ty, dst_mcv, .{ .memory = imm }),
2560 .ptr_stack_offset => |off| try self.setRegOrMem(elem_ty, dst_mcv, .{ .stack_offset = off }),2606 .ptr_stack_offset => |off| try self.setRegOrMem(elem_ty, dst_mcv, .{ .stack_offset = off }),
2561 .register => |addr_reg| {2607 .register => |addr_reg| {
2562 self.register_manager.freezeRegs(&.{addr_reg});2608 const addr_reg_lock = self.register_manager.freezeReg(addr_reg);
2563 defer self.register_manager.unfreezeRegs(&.{addr_reg});2609 defer if (addr_reg_lock) |reg| self.register_manager.unfreezeReg(reg);
25642610
2565 switch (dst_mcv) {2611 switch (dst_mcv) {
2566 .dead => unreachable,2612 .dead => unreachable,
...@@ -2573,16 +2619,19 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo...@@ -2573,16 +2619,19 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
2573 if (elem_size <= 8) {2619 if (elem_size <= 8) {
2574 const raw_tmp_reg = try self.register_manager.allocReg(null);2620 const raw_tmp_reg = try self.register_manager.allocReg(null);
2575 const tmp_reg = registerAlias(raw_tmp_reg, elem_size);2621 const tmp_reg = registerAlias(raw_tmp_reg, elem_size);
2576 self.register_manager.freezeRegs(&.{tmp_reg});2622 const tmp_reg_lock = self.register_manager.freezeRegAssumeUnused(tmp_reg);
2577 defer self.register_manager.unfreezeRegs(&.{tmp_reg});2623 defer self.register_manager.unfreezeReg(tmp_reg_lock);
25782624
2579 try self.load(.{ .register = tmp_reg }, ptr, ptr_ty);2625 try self.load(.{ .register = tmp_reg }, ptr, ptr_ty);
2580 try self.genSetStack(elem_ty, off, MCValue{ .register = tmp_reg });2626 try self.genSetStack(elem_ty, off, MCValue{ .register = tmp_reg });
2581 } else {2627 } else {
2582 // TODO optimize the register allocation2628 // TODO optimize the register allocation
2583 const regs = try self.register_manager.allocRegs(4, .{ null, null, null, null });2629 const regs = try self.register_manager.allocRegs(4, .{ null, null, null, null });
2584 self.register_manager.freezeRegs(&regs);2630 var regs_locks: [4]RegisterLock = undefined;
2585 defer self.register_manager.unfreezeRegs(&regs);2631 self.register_manager.freezeRegsAssumeUnused(4, regs, &regs_locks);
2632 defer for (regs_locks) |reg| {
2633 self.register_manager.unfreezeReg(reg);
2634 };
25862635
2587 const src_reg = addr_reg;2636 const src_reg = addr_reg;
2588 const dst_reg = regs[0];2637 const dst_reg = regs[0];
...@@ -2784,8 +2833,8 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -2784,8 +2833,8 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
2784 try self.genSetStack(value_ty, off, value);2833 try self.genSetStack(value_ty, off, value);
2785 },2834 },
2786 .register => |addr_reg| {2835 .register => |addr_reg| {
2787 self.register_manager.freezeRegs(&.{addr_reg});2836 const addr_reg_lock = self.register_manager.freezeReg(addr_reg);
2788 defer self.register_manager.unfreezeRegs(&.{addr_reg});2837 defer if (addr_reg_lock) |reg| self.register_manager.unfreezeReg(reg);
27892838
2790 switch (value) {2839 switch (value) {
2791 .register => |value_reg| {2840 .register => |value_reg| {
...@@ -2795,8 +2844,8 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -2795,8 +2844,8 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
2795 if (abi_size <= 8) {2844 if (abi_size <= 8) {
2796 const raw_tmp_reg = try self.register_manager.allocReg(null);2845 const raw_tmp_reg = try self.register_manager.allocReg(null);
2797 const tmp_reg = registerAlias(raw_tmp_reg, abi_size);2846 const tmp_reg = registerAlias(raw_tmp_reg, abi_size);
2798 self.register_manager.freezeRegs(&.{tmp_reg});2847 const tmp_reg_lock = self.register_manager.freezeRegAssumeUnused(tmp_reg);
2799 defer self.register_manager.unfreezeRegs(&.{tmp_reg});2848 defer self.register_manager.unfreezeReg(tmp_reg_lock);
28002849
2801 try self.genSetReg(value_ty, tmp_reg, value);2850 try self.genSetReg(value_ty, tmp_reg, value);
2802 try self.store(ptr, .{ .register = tmp_reg }, ptr_ty, value_ty);2851 try self.store(ptr, .{ .register = tmp_reg }, ptr_ty, value_ty);
...@@ -2856,12 +2905,12 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde...@@ -2856,12 +2905,12 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde
2856 const offset_reg = try self.copyToTmpRegister(ptr_ty, .{2905 const offset_reg = try self.copyToTmpRegister(ptr_ty, .{
2857 .immediate = struct_field_offset,2906 .immediate = struct_field_offset,
2858 });2907 });
2859 self.register_manager.freezeRegs(&.{offset_reg});2908 const offset_reg_lock = self.register_manager.freezeRegAssumeUnused(offset_reg);
2860 defer self.register_manager.unfreezeRegs(&.{offset_reg});2909 defer self.register_manager.unfreezeReg(offset_reg_lock);
28612910
2862 const addr_reg = try self.copyToTmpRegister(ptr_ty, mcv);2911 const addr_reg = try self.copyToTmpRegister(ptr_ty, mcv);
2863 self.register_manager.freezeRegs(&.{addr_reg});2912 const addr_reg_lock = self.register_manager.freezeRegAssumeUnused(addr_reg);
2864 defer self.register_manager.unfreezeRegs(&.{addr_reg});2913 defer self.register_manager.unfreezeReg(addr_reg_lock);
28652914
2866 const dest = try self.binOp(2915 const dest = try self.binOp(
2867 .add,2916 .add,
...@@ -3369,6 +3418,9 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {...@@ -3369,6 +3418,9 @@ fn airCondBr(self: *Self, inst: Air.Inst.Index) !void {
3369 const parent_compare_flags_inst = self.compare_flags_inst;3418 const parent_compare_flags_inst = self.compare_flags_inst;
33703419
3371 try self.branch_stack.append(.{});3420 try self.branch_stack.append(.{});
3421 errdefer {
3422 _ = self.branch_stack.pop();
3423 }
33723424
3373 try self.ensureProcessDeathCapacity(liveness_condbr.then_deaths.len);3425 try self.ensureProcessDeathCapacity(liveness_condbr.then_deaths.len);
3374 for (liveness_condbr.then_deaths) |operand| {3426 for (liveness_condbr.then_deaths) |operand| {
...@@ -3955,8 +4007,38 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -3955,8 +4007,38 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
3955 },4007 },
3956 .register_c_flag,4008 .register_c_flag,
3957 .register_v_flag,4009 .register_v_flag,
3958 => {4010 => |reg| {
3959 return self.fail("TODO implement genSetStack {}", .{mcv});4011 const reg_lock = self.register_manager.freezeReg(reg);
4012 defer if (reg_lock) |locked_reg| self.register_manager.unfreezeReg(locked_reg);
4013
4014 const wrapped_ty = ty.structFieldType(0);
4015 try self.genSetStack(wrapped_ty, stack_offset, .{ .register = reg });
4016
4017 const overflow_bit_ty = ty.structFieldType(1);
4018 const overflow_bit_offset = @intCast(u32, ty.structFieldOffset(1, self.target.*));
4019 const raw_cond_reg = try self.register_manager.allocReg(null);
4020 const cond_reg = registerAlias(
4021 raw_cond_reg,
4022 @intCast(u32, overflow_bit_ty.abiSize(self.target.*)),
4023 );
4024
4025 // C flag: cset reg, cs
4026 // V flag: cset reg, vs
4027 _ = try self.addInst(.{
4028 .tag = .cset,
4029 .data = .{ .r_cond = .{
4030 .rd = cond_reg,
4031 .cond = switch (mcv) {
4032 .register_c_flag => .cs,
4033 .register_v_flag => .vs,
4034 else => unreachable,
4035 },
4036 } },
4037 });
4038
4039 try self.genSetStack(overflow_bit_ty, stack_offset - overflow_bit_offset, .{
4040 .register = cond_reg,
4041 });
3960 },4042 },
3961 .got_load,4043 .got_load,
3962 .direct_load,4044 .direct_load,
...@@ -3983,8 +4065,11 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -3983,8 +4065,11 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
39834065
3984 // TODO call extern memcpy4066 // TODO call extern memcpy
3985 const regs = try self.register_manager.allocRegs(5, .{ null, null, null, null, null });4067 const regs = try self.register_manager.allocRegs(5, .{ null, null, null, null, null });
3986 self.register_manager.freezeRegs(&regs);4068 var regs_locks: [5]RegisterLock = undefined;
3987 defer self.register_manager.unfreezeRegs(&regs);4069 self.register_manager.freezeRegsAssumeUnused(5, regs, &regs_locks);
4070 defer for (regs_locks) |reg| {
4071 self.register_manager.unfreezeReg(reg);
4072 };
39884073
3989 const src_reg = regs[0];4074 const src_reg = regs[0];
3990 const dst_reg = regs[1];4075 const dst_reg = regs[1];
src/arch/arm/CodeGen.zig+99-75
...@@ -23,6 +23,7 @@ const log = std.log.scoped(.codegen);...@@ -23,6 +23,7 @@ const log = std.log.scoped(.codegen);
23const build_options = @import("build_options");23const build_options = @import("build_options");
24const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;24const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;
25const RegisterManager = RegisterManagerFn(Self, Register, &allocatable_registers);25const RegisterManager = RegisterManagerFn(Self, Register, &allocatable_registers);
26const RegisterLock = RegisterManager.RegisterLock;
2627
27const FnResult = @import("../../codegen.zig").FnResult;28const FnResult = @import("../../codegen.zig").FnResult;
28const GenerateSymbolError = @import("../../codegen.zig").GenerateSymbolError;29const GenerateSymbolError = @import("../../codegen.zig").GenerateSymbolError;
...@@ -1038,8 +1039,8 @@ fn trunc(...@@ -1038,8 +1039,8 @@ fn trunc(
1038 }1039 }
1039 },1040 },
1040 };1041 };
1041 self.register_manager.freezeRegs(&.{operand_reg});1042 const operand_reg_lock = self.register_manager.freezeReg(operand_reg);
1042 defer self.register_manager.unfreezeRegs(&.{operand_reg});1043 defer if (operand_reg_lock) |reg| self.register_manager.unfreezeReg(reg);
10431044
1044 const dest_reg = if (maybe_inst) |inst| blk: {1045 const dest_reg = if (maybe_inst) |inst| blk: {
1045 const ty_op = self.air.instructions.items(.data)[inst].ty_op;1046 const ty_op = self.air.instructions.items(.data)[inst].ty_op;
...@@ -1127,8 +1128,8 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {...@@ -1127,8 +1128,8 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
1127 .register => |r| r,1128 .register => |r| r,
1128 else => try self.copyToTmpRegister(operand_ty, operand),1129 else => try self.copyToTmpRegister(operand_ty, operand),
1129 };1130 };
1130 self.register_manager.freezeRegs(&.{op_reg});1131 const op_reg_lock = self.register_manager.freezeRegAssumeUnused(op_reg);
1131 defer self.register_manager.unfreezeRegs(&.{op_reg});1132 defer self.register_manager.unfreezeReg(op_reg_lock);
11321133
1133 const dest_reg = blk: {1134 const dest_reg = blk: {
1134 if (operand == .register and self.reuseOperand(inst, ty_op.operand, 0, operand)) {1135 if (operand == .register and self.reuseOperand(inst, ty_op.operand, 0, operand)) {
...@@ -1157,8 +1158,8 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {...@@ -1157,8 +1158,8 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
1157 .register => |r| r,1158 .register => |r| r,
1158 else => try self.copyToTmpRegister(operand_ty, operand),1159 else => try self.copyToTmpRegister(operand_ty, operand),
1159 };1160 };
1160 self.register_manager.freezeRegs(&.{op_reg});1161 const op_reg_lock = self.register_manager.freezeRegAssumeUnused(op_reg);
1161 defer self.register_manager.unfreezeRegs(&.{op_reg});1162 defer self.register_manager.unfreezeReg(op_reg_lock);
11621163
1163 const dest_reg = blk: {1164 const dest_reg = blk: {
1164 if (operand == .register and self.reuseOperand(inst, ty_op.operand, 0, operand)) {1165 if (operand == .register and self.reuseOperand(inst, ty_op.operand, 0, operand)) {
...@@ -1218,15 +1219,15 @@ fn minMax(...@@ -1218,15 +1219,15 @@ fn minMax(
1218 .register => |r| r,1219 .register => |r| r,
1219 else => try self.copyToTmpRegister(lhs_ty, lhs),1220 else => try self.copyToTmpRegister(lhs_ty, lhs),
1220 };1221 };
1221 self.register_manager.freezeRegs(&.{lhs_reg});1222 const lhs_reg_lock = self.register_manager.freezeReg(lhs_reg);
1222 defer self.register_manager.unfreezeRegs(&.{lhs_reg});1223 defer if (lhs_reg_lock) |reg| self.register_manager.unfreezeReg(reg);
12231224
1224 const rhs_reg = switch (rhs) {1225 const rhs_reg = switch (rhs) {
1225 .register => |r| r,1226 .register => |r| r,
1226 else => try self.copyToTmpRegister(rhs_ty, rhs),1227 else => try self.copyToTmpRegister(rhs_ty, rhs),
1227 };1228 };
1228 self.register_manager.freezeRegs(&.{rhs_reg});1229 const rhs_reg_lock = self.register_manager.freezeReg(rhs_reg);
1229 defer self.register_manager.unfreezeRegs(&.{rhs_reg});1230 defer if (rhs_reg_lock) |reg| self.register_manager.unfreezeReg(reg);
12301231
1231 const dest_reg = if (maybe_inst) |inst| blk: {1232 const dest_reg = if (maybe_inst) |inst| blk: {
1232 const bin_op = self.air.instructions.items(.data)[inst].bin_op;1233 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
...@@ -1392,12 +1393,12 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1392,12 +1393,12 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {
1392 };1393 };
1393 const dest = try self.binOp(base_tag, null, lhs, rhs, lhs_ty, rhs_ty);1394 const dest = try self.binOp(base_tag, null, lhs, rhs, lhs_ty, rhs_ty);
1394 const dest_reg = dest.register;1395 const dest_reg = dest.register;
1395 self.register_manager.freezeRegs(&.{dest_reg});1396 const dest_reg_lock = self.register_manager.freezeRegAssumeUnused(dest_reg);
1396 defer self.register_manager.unfreezeRegs(&.{dest_reg});1397 defer self.register_manager.unfreezeReg(dest_reg_lock);
13971398
1398 const truncated_reg = try self.register_manager.allocReg(null);1399 const truncated_reg = try self.register_manager.allocReg(null);
1399 self.register_manager.freezeRegs(&.{truncated_reg});1400 const truncated_reg_lock = self.register_manager.freezeRegAssumeUnused(truncated_reg);
1400 defer self.register_manager.unfreezeRegs(&.{truncated_reg});1401 defer self.register_manager.unfreezeReg(truncated_reg_lock);
14011402
1402 // sbfx/ubfx truncated, dest, #0, #bits1403 // sbfx/ubfx truncated, dest, #0, #bits
1403 try self.truncRegister(dest_reg, truncated_reg, int_info.signedness, int_info.bits);1404 try self.truncRegister(dest_reg, truncated_reg, int_info.signedness, int_info.bits);
...@@ -1493,12 +1494,12 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1493,12 +1494,12 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
14931494
1494 const dest = try self.binOpRegister(base_tag, null, lhs, rhs, lhs_ty, rhs_ty);1495 const dest = try self.binOpRegister(base_tag, null, lhs, rhs, lhs_ty, rhs_ty);
1495 const dest_reg = dest.register;1496 const dest_reg = dest.register;
1496 self.register_manager.freezeRegs(&.{dest_reg});1497 const dest_reg_lock = self.register_manager.freezeRegAssumeUnused(dest_reg);
1497 defer self.register_manager.unfreezeRegs(&.{dest_reg});1498 defer self.register_manager.unfreezeReg(dest_reg_lock);
14981499
1499 const truncated_reg = try self.register_manager.allocReg(null);1500 const truncated_reg = try self.register_manager.allocReg(null);
1500 self.register_manager.freezeRegs(&.{truncated_reg});1501 const truncated_reg_lock = self.register_manager.freezeRegAssumeUnused(truncated_reg);
1501 defer self.register_manager.unfreezeRegs(&.{truncated_reg});1502 defer self.register_manager.unfreezeReg(truncated_reg_lock);
15021503
1503 // sbfx/ubfx truncated, dest, #0, #bits1504 // sbfx/ubfx truncated, dest, #0, #bits
1504 try self.truncRegister(dest_reg, truncated_reg, int_info.signedness, int_info.bits);1505 try self.truncRegister(dest_reg, truncated_reg, int_info.signedness, int_info.bits);
...@@ -1526,28 +1527,32 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1526,28 +1527,32 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1526 const lhs_is_register = lhs == .register;1527 const lhs_is_register = lhs == .register;
1527 const rhs_is_register = rhs == .register;1528 const rhs_is_register = rhs == .register;
15281529
1529 if (lhs_is_register) self.register_manager.freezeRegs(&.{lhs.register});1530 const lhs_lock: ?RegisterLock = if (lhs_is_register)
1530 if (rhs_is_register) self.register_manager.freezeRegs(&.{rhs.register});1531 self.register_manager.freezeReg(lhs.register)
15311532 else
1532 const lhs_reg = if (lhs_is_register) lhs.register else blk: {1533 null;
1533 const reg = try self.register_manager.allocReg(null);1534 defer if (lhs_lock) |reg| self.register_manager.unfreezeReg(reg);
1534 self.register_manager.freezeRegs(&.{reg});
1535
1536 break :blk reg;
1537 };
1538 defer self.register_manager.unfreezeRegs(&.{lhs_reg});
15391535
1540 const rhs_reg = if (rhs_is_register) rhs.register else blk: {1536 const lhs_reg = if (lhs_is_register)
1541 const reg = try self.register_manager.allocReg(null);1537 lhs.register
1542 self.register_manager.freezeRegs(&.{reg});1538 else
1539 try self.register_manager.allocReg(null);
1540 const new_lhs_lock = self.register_manager.freezeReg(lhs_reg);
1541 defer if (new_lhs_lock) |reg| self.register_manager.unfreezeReg(reg);
15431542
1544 break :blk reg;1543 const rhs_reg = if (rhs_is_register)
1545 };1544 rhs.register
1546 defer self.register_manager.unfreezeRegs(&.{rhs_reg});1545 else
1546 try self.register_manager.allocReg(null);
1547 const new_rhs_lock = self.register_manager.freezeReg(rhs_reg);
1548 defer if (new_rhs_lock) |reg| self.register_manager.unfreezeReg(reg);
15471549
1548 const dest_regs = try self.register_manager.allocRegs(2, .{ null, null });1550 const dest_regs = try self.register_manager.allocRegs(2, .{ null, null });
1549 self.register_manager.freezeRegs(&dest_regs);1551 var dest_regs_locks: [2]RegisterLock = undefined;
1550 defer self.register_manager.unfreezeRegs(&dest_regs);1552 self.register_manager.freezeRegsAssumeUnused(2, dest_regs, &dest_regs_locks);
1553 defer for (dest_regs_locks) |reg| {
1554 self.register_manager.unfreezeReg(reg);
1555 };
1551 const rdlo = dest_regs[0];1556 const rdlo = dest_regs[0];
1552 const rdhi = dest_regs[1];1557 const rdhi = dest_regs[1];
15531558
...@@ -1555,8 +1560,8 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1555,8 +1560,8 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1555 if (!rhs_is_register) try self.genSetReg(rhs_ty, rhs_reg, rhs);1560 if (!rhs_is_register) try self.genSetReg(rhs_ty, rhs_reg, rhs);
15561561
1557 const truncated_reg = try self.register_manager.allocReg(null);1562 const truncated_reg = try self.register_manager.allocReg(null);
1558 self.register_manager.freezeRegs(&.{truncated_reg});1563 const truncated_reg_lock = self.register_manager.freezeRegAssumeUnused(truncated_reg);
1559 defer self.register_manager.unfreezeRegs(&.{truncated_reg});1564 defer self.register_manager.unfreezeReg(truncated_reg_lock);
15601565
1561 _ = try self.addInst(.{1566 _ = try self.addInst(.{
1562 .tag = base_tag,1567 .tag = base_tag,
...@@ -1648,8 +1653,11 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1648,8 +1653,11 @@ fn airShlWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1648 if (int_info.bits <= 32) {1653 if (int_info.bits <= 32) {
1649 const stack_offset = try self.allocMem(inst, tuple_size, tuple_align);1654 const stack_offset = try self.allocMem(inst, tuple_size, tuple_align);
16501655
1651 if (lhs == .register) self.register_manager.freezeRegs(&.{lhs.register});1656 const lhs_lock: ?RegisterLock = if (lhs == .register)
1652 defer if (lhs == .register) self.register_manager.unfreezeRegs(&.{lhs.register});1657 self.register_manager.freezeRegAssumeUnused(lhs.register)
1658 else
1659 null;
1660 defer if (lhs_lock) |reg| self.register_manager.unfreezeReg(reg);
16531661
1654 try self.spillCompareFlagsIfOccupied();1662 try self.spillCompareFlagsIfOccupied();
1655 self.compare_flags_inst = null;1663 self.compare_flags_inst = null;
...@@ -1939,8 +1947,11 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -1939,8 +1947,11 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {
1939 var buf: Type.SlicePtrFieldTypeBuffer = undefined;1947 var buf: Type.SlicePtrFieldTypeBuffer = undefined;
1940 const slice_ptr_field_type = slice_ty.slicePtrFieldType(&buf);1948 const slice_ptr_field_type = slice_ty.slicePtrFieldType(&buf);
19411949
1942 if (index_is_register) self.register_manager.freezeRegs(&.{index_mcv.register});1950 const index_lock: ?RegisterLock = if (index_is_register)
1943 defer if (index_is_register) self.register_manager.unfreezeRegs(&.{index_mcv.register});1951 self.register_manager.freezeRegAssumeUnused(index_mcv.register)
1952 else
1953 null;
1954 defer if (index_lock) |reg| self.register_manager.unfreezeReg(reg);
19441955
1945 const base_mcv = slicePtr(slice_mcv);1956 const base_mcv = slicePtr(slice_mcv);
19461957
...@@ -1950,20 +1961,20 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -1950,20 +1961,20 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {
1950 .register => |r| r,1961 .register => |r| r,
1951 else => try self.copyToTmpRegister(slice_ptr_field_type, base_mcv),1962 else => try self.copyToTmpRegister(slice_ptr_field_type, base_mcv),
1952 };1963 };
1953 self.register_manager.freezeRegs(&.{base_reg});1964 const base_reg_lock = self.register_manager.freezeRegAssumeUnused(base_reg);
1954 defer self.register_manager.unfreezeRegs(&.{base_reg});1965 defer self.register_manager.unfreezeReg(base_reg_lock);
19551966
1956 const dst_reg = try self.register_manager.allocReg(inst);1967 const dst_reg = try self.register_manager.allocReg(inst);
1957 const dst_mcv = MCValue{ .register = dst_reg };1968 const dst_mcv = MCValue{ .register = dst_reg };
1958 self.register_manager.freezeRegs(&.{dst_reg});1969 const dst_reg_lock = self.register_manager.freezeRegAssumeUnused(dst_reg);
1959 defer self.register_manager.unfreezeRegs(&.{dst_reg});1970 defer self.register_manager.unfreezeReg(dst_reg_lock);
19601971
1961 const index_reg: Register = switch (index_mcv) {1972 const index_reg: Register = switch (index_mcv) {
1962 .register => |reg| reg,1973 .register => |reg| reg,
1963 else => try self.copyToTmpRegister(Type.usize, index_mcv),1974 else => try self.copyToTmpRegister(Type.usize, index_mcv),
1964 };1975 };
1965 self.register_manager.freezeRegs(&.{index_reg});1976 const index_reg_lock = self.register_manager.freezeRegAssumeUnused(index_reg);
1966 defer self.register_manager.unfreezeRegs(&.{index_reg});1977 defer self.register_manager.unfreezeReg(index_reg_lock);
19671978
1968 const tag: Mir.Inst.Tag = switch (elem_size) {1979 const tag: Mir.Inst.Tag = switch (elem_size) {
1969 1 => .ldrb,1980 1 => .ldrb,
...@@ -2149,8 +2160,8 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo...@@ -2149,8 +2160,8 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
2149 .immediate => |imm| try self.setRegOrMem(elem_ty, dst_mcv, .{ .memory = imm }),2160 .immediate => |imm| try self.setRegOrMem(elem_ty, dst_mcv, .{ .memory = imm }),
2150 .ptr_stack_offset => |off| try self.setRegOrMem(elem_ty, dst_mcv, .{ .stack_offset = off }),2161 .ptr_stack_offset => |off| try self.setRegOrMem(elem_ty, dst_mcv, .{ .stack_offset = off }),
2151 .register => |reg| {2162 .register => |reg| {
2152 self.register_manager.freezeRegs(&.{reg});2163 const reg_lock = self.register_manager.freezeReg(reg);
2153 defer self.register_manager.unfreezeRegs(&.{reg});2164 defer if (reg_lock) |reg_locked| self.register_manager.unfreezeReg(reg_locked);
21542165
2155 switch (dst_mcv) {2166 switch (dst_mcv) {
2156 .dead => unreachable,2167 .dead => unreachable,
...@@ -2162,16 +2173,19 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo...@@ -2162,16 +2173,19 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
2162 .stack_offset => |off| {2173 .stack_offset => |off| {
2163 if (elem_size <= 4) {2174 if (elem_size <= 4) {
2164 const tmp_reg = try self.register_manager.allocReg(null);2175 const tmp_reg = try self.register_manager.allocReg(null);
2165 self.register_manager.freezeRegs(&.{tmp_reg});2176 const tmp_reg_lock = self.register_manager.freezeRegAssumeUnused(tmp_reg);
2166 defer self.register_manager.unfreezeRegs(&.{tmp_reg});2177 defer self.register_manager.unfreezeReg(tmp_reg_lock);
21672178
2168 try self.load(.{ .register = tmp_reg }, ptr, ptr_ty);2179 try self.load(.{ .register = tmp_reg }, ptr, ptr_ty);
2169 try self.genSetStack(elem_ty, off, MCValue{ .register = tmp_reg });2180 try self.genSetStack(elem_ty, off, MCValue{ .register = tmp_reg });
2170 } else {2181 } else {
2171 // TODO optimize the register allocation2182 // TODO optimize the register allocation
2172 const regs = try self.register_manager.allocRegs(4, .{ null, null, null, null });2183 const regs = try self.register_manager.allocRegs(4, .{ null, null, null, null });
2173 self.register_manager.freezeRegs(&regs);2184 var regs_locks: [4]RegisterLock = undefined;
2174 defer self.register_manager.unfreezeRegs(&regs);2185 self.register_manager.freezeRegsAssumeUnused(4, regs, &regs_locks);
2186 defer for (regs_locks) |reg_locked| {
2187 self.register_manager.unfreezeReg(reg_locked);
2188 };
21752189
2176 const src_reg = reg;2190 const src_reg = reg;
2177 const dst_reg = regs[0];2191 const dst_reg = regs[0];
...@@ -2197,8 +2211,8 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo...@@ -2197,8 +2211,8 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
2197 .stack_argument_offset,2211 .stack_argument_offset,
2198 => {2212 => {
2199 const reg = try self.register_manager.allocReg(null);2213 const reg = try self.register_manager.allocReg(null);
2200 self.register_manager.freezeRegs(&.{reg});2214 const reg_lock = self.register_manager.freezeRegAssumeUnused(reg);
2201 defer self.register_manager.unfreezeRegs(&.{reg});2215 defer self.register_manager.unfreezeReg(reg_lock);
22022216
2203 try self.genSetReg(ptr_ty, reg, ptr);2217 try self.genSetReg(ptr_ty, reg, ptr);
2204 try self.load(dst_mcv, .{ .register = reg }, ptr_ty);2218 try self.load(dst_mcv, .{ .register = reg }, ptr_ty);
...@@ -2252,8 +2266,8 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -2252,8 +2266,8 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
2252 try self.genSetStack(value_ty, off, value);2266 try self.genSetStack(value_ty, off, value);
2253 },2267 },
2254 .register => |addr_reg| {2268 .register => |addr_reg| {
2255 self.register_manager.freezeRegs(&.{addr_reg});2269 const addr_reg_lock = self.register_manager.freezeReg(addr_reg);
2256 defer self.register_manager.unfreezeRegs(&.{addr_reg});2270 defer if (addr_reg_lock) |reg| self.register_manager.unfreezeReg(reg);
22572271
2258 switch (value) {2272 switch (value) {
2259 .dead => unreachable,2273 .dead => unreachable,
...@@ -2264,15 +2278,18 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -2264,15 +2278,18 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
2264 else => {2278 else => {
2265 if (elem_size <= 4) {2279 if (elem_size <= 4) {
2266 const tmp_reg = try self.register_manager.allocReg(null);2280 const tmp_reg = try self.register_manager.allocReg(null);
2267 self.register_manager.freezeRegs(&.{tmp_reg});2281 const tmp_reg_lock = self.register_manager.freezeRegAssumeUnused(tmp_reg);
2268 defer self.register_manager.unfreezeRegs(&.{tmp_reg});2282 defer self.register_manager.unfreezeReg(tmp_reg_lock);
22692283
2270 try self.genSetReg(value_ty, tmp_reg, value);2284 try self.genSetReg(value_ty, tmp_reg, value);
2271 try self.store(ptr, .{ .register = tmp_reg }, ptr_ty, value_ty);2285 try self.store(ptr, .{ .register = tmp_reg }, ptr_ty, value_ty);
2272 } else {2286 } else {
2273 const regs = try self.register_manager.allocRegs(4, .{ null, null, null, null });2287 const regs = try self.register_manager.allocRegs(4, .{ null, null, null, null });
2274 self.register_manager.freezeRegs(&regs);2288 var regs_locks: [4]RegisterLock = undefined;
2275 defer self.register_manager.unfreezeRegs(&regs);2289 self.register_manager.freezeRegsAssumeUnused(4, regs, &regs_locks);
2290 defer for (regs_locks) |reg| {
2291 self.register_manager.unfreezeReg(reg);
2292 };
22762293
2277 const src_reg = regs[0];2294 const src_reg = regs[0];
2278 const dst_reg = addr_reg;2295 const dst_reg = addr_reg;
...@@ -2356,12 +2373,12 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde...@@ -2356,12 +2373,12 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde
2356 const offset_reg = try self.copyToTmpRegister(ptr_ty, .{2373 const offset_reg = try self.copyToTmpRegister(ptr_ty, .{
2357 .immediate = struct_field_offset,2374 .immediate = struct_field_offset,
2358 });2375 });
2359 self.register_manager.freezeRegs(&.{offset_reg});2376 const offset_reg_lock = self.register_manager.freezeRegAssumeUnused(offset_reg);
2360 defer self.register_manager.unfreezeRegs(&.{offset_reg});2377 defer self.register_manager.unfreezeReg(offset_reg_lock);
23612378
2362 const addr_reg = try self.copyToTmpRegister(ptr_ty, mcv);2379 const addr_reg = try self.copyToTmpRegister(ptr_ty, mcv);
2363 self.register_manager.freezeRegs(&.{addr_reg});2380 const addr_reg_lock = self.register_manager.freezeRegAssumeUnused(addr_reg);
2364 defer self.register_manager.unfreezeRegs(&.{addr_reg});2381 defer self.register_manager.unfreezeReg(addr_reg_lock);
23652382
2366 const dest = try self.binOp(2383 const dest = try self.binOp(
2367 .add,2384 .add,
...@@ -2477,8 +2494,11 @@ fn binOpRegister(...@@ -2477,8 +2494,11 @@ fn binOpRegister(
2477 const lhs_is_register = lhs == .register;2494 const lhs_is_register = lhs == .register;
2478 const rhs_is_register = rhs == .register;2495 const rhs_is_register = rhs == .register;
24792496
2480 if (lhs_is_register) self.register_manager.freezeRegs(&.{lhs.register});2497 const lhs_lock: ?RegisterLock = if (lhs_is_register)
2481 if (rhs_is_register) self.register_manager.freezeRegs(&.{rhs.register});2498 self.register_manager.freezeReg(lhs.register)
2499 else
2500 null;
2501 defer if (lhs_lock) |reg| self.register_manager.unfreezeReg(reg);
24822502
2483 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];2503 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
24842504
...@@ -2489,13 +2509,13 @@ fn binOpRegister(...@@ -2489,13 +2509,13 @@ fn binOpRegister(
2489 } else null;2509 } else null;
24902510
2491 const reg = try self.register_manager.allocReg(track_inst);2511 const reg = try self.register_manager.allocReg(track_inst);
2492 self.register_manager.freezeRegs(&.{reg});
24932512
2494 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });2513 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
24952514
2496 break :blk reg;2515 break :blk reg;
2497 };2516 };
2498 defer self.register_manager.unfreezeRegs(&.{lhs_reg});2517 const new_lhs_lock = self.register_manager.freezeReg(lhs_reg);
2518 defer if (new_lhs_lock) |reg| self.register_manager.unfreezeReg(reg);
24992519
2500 const rhs_reg = if (rhs_is_register) rhs.register else blk: {2520 const rhs_reg = if (rhs_is_register) rhs.register else blk: {
2501 const track_inst: ?Air.Inst.Index = if (maybe_inst) |inst| inst: {2521 const track_inst: ?Air.Inst.Index = if (maybe_inst) |inst| inst: {
...@@ -2504,13 +2524,13 @@ fn binOpRegister(...@@ -2504,13 +2524,13 @@ fn binOpRegister(
2504 } else null;2524 } else null;
25052525
2506 const reg = try self.register_manager.allocReg(track_inst);2526 const reg = try self.register_manager.allocReg(track_inst);
2507 self.register_manager.freezeRegs(&.{reg});
25082527
2509 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });2528 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
25102529
2511 break :blk reg;2530 break :blk reg;
2512 };2531 };
2513 defer self.register_manager.unfreezeRegs(&.{rhs_reg});2532 const new_rhs_lock = self.register_manager.freezeReg(rhs_reg);
2533 defer if (new_rhs_lock) |reg| self.register_manager.unfreezeReg(reg);
25142534
2515 const dest_reg = switch (mir_tag) {2535 const dest_reg = switch (mir_tag) {
2516 .cmp => .r0, // cmp has no destination regardless2536 .cmp => .r0, // cmp has no destination regardless
...@@ -2593,7 +2613,11 @@ fn binOpImmediate(...@@ -2593,7 +2613,11 @@ fn binOpImmediate(
2593) !MCValue {2613) !MCValue {
2594 const lhs_is_register = lhs == .register;2614 const lhs_is_register = lhs == .register;
25952615
2596 if (lhs_is_register) self.register_manager.freezeRegs(&.{lhs.register});2616 const lhs_lock: ?RegisterLock = if (lhs_is_register)
2617 self.register_manager.freezeReg(lhs.register)
2618 else
2619 null;
2620 defer if (lhs_lock) |reg| self.register_manager.unfreezeReg(reg);
25972621
2598 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];2622 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
25992623
...@@ -2606,13 +2630,13 @@ fn binOpImmediate(...@@ -2606,13 +2630,13 @@ fn binOpImmediate(
2606 } else null;2630 } else null;
26072631
2608 const reg = try self.register_manager.allocReg(track_inst);2632 const reg = try self.register_manager.allocReg(track_inst);
2609 self.register_manager.freezeRegs(&.{reg});
26102633
2611 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });2634 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
26122635
2613 break :blk reg;2636 break :blk reg;
2614 };2637 };
2615 defer self.register_manager.unfreezeRegs(&.{lhs_reg});2638 const new_lhs_lock = self.register_manager.freezeReg(lhs_reg);
2639 defer if (new_lhs_lock) |reg| self.register_manager.unfreezeReg(reg);
26162640
2617 const dest_reg = switch (mir_tag) {2641 const dest_reg = switch (mir_tag) {
2618 .cmp => .r0, // cmp has no destination reg2642 .cmp => .r0, // cmp has no destination reg
src/arch/riscv64/CodeGen.zig+12-8
...@@ -23,6 +23,7 @@ const log = std.log.scoped(.codegen);...@@ -23,6 +23,7 @@ const log = std.log.scoped(.codegen);
23const build_options = @import("build_options");23const build_options = @import("build_options");
24const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;24const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;
25const RegisterManager = RegisterManagerFn(Self, Register, &callee_preserved_regs);25const RegisterManager = RegisterManagerFn(Self, Register, &callee_preserved_regs);
26const RegisterLock = RegisterManager.RegisterLock;
2627
27const FnResult = @import("../../codegen.zig").FnResult;28const FnResult = @import("../../codegen.zig").FnResult;
28const GenerateSymbolError = @import("../../codegen.zig").GenerateSymbolError;29const GenerateSymbolError = @import("../../codegen.zig").GenerateSymbolError;
...@@ -937,8 +938,11 @@ fn binOpRegister(...@@ -937,8 +938,11 @@ fn binOpRegister(
937 const lhs_is_register = lhs == .register;938 const lhs_is_register = lhs == .register;
938 const rhs_is_register = rhs == .register;939 const rhs_is_register = rhs == .register;
939940
940 if (lhs_is_register) self.register_manager.freezeRegs(&.{lhs.register});941 const lhs_lock: ?RegisterLock = if (lhs_is_register)
941 if (rhs_is_register) self.register_manager.freezeRegs(&.{rhs.register});942 self.register_manager.freezeReg(lhs.register)
943 else
944 null;
945 defer if (lhs_lock) |reg| self.register_manager.unfreezeReg(reg);
942946
943 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];947 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
944948
...@@ -949,13 +953,13 @@ fn binOpRegister(...@@ -949,13 +953,13 @@ fn binOpRegister(
949 } else null;953 } else null;
950954
951 const reg = try self.register_manager.allocReg(track_inst);955 const reg = try self.register_manager.allocReg(track_inst);
952 self.register_manager.freezeRegs(&.{reg});
953956
954 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });957 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
955958
956 break :blk reg;959 break :blk reg;
957 };960 };
958 defer self.register_manager.unfreezeRegs(&.{lhs_reg});961 const new_lhs_lock = self.register_manager.freezeReg(lhs_reg);
962 defer if (new_lhs_lock) |reg| self.register_manager.unfreezeReg(reg);
959963
960 const rhs_reg = if (rhs_is_register) rhs.register else blk: {964 const rhs_reg = if (rhs_is_register) rhs.register else blk: {
961 const track_inst: ?Air.Inst.Index = if (maybe_inst) |inst| inst: {965 const track_inst: ?Air.Inst.Index = if (maybe_inst) |inst| inst: {
...@@ -964,13 +968,13 @@ fn binOpRegister(...@@ -964,13 +968,13 @@ fn binOpRegister(
964 } else null;968 } else null;
965969
966 const reg = try self.register_manager.allocReg(track_inst);970 const reg = try self.register_manager.allocReg(track_inst);
967 self.register_manager.freezeRegs(&.{reg});
968971
969 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });972 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
970973
971 break :blk reg;974 break :blk reg;
972 };975 };
973 defer self.register_manager.unfreezeRegs(&.{rhs_reg});976 const new_rhs_lock = self.register_manager.freezeReg(rhs_reg);
977 defer if (new_rhs_lock) |reg| self.register_manager.unfreezeReg(reg);
974978
975 const dest_reg = if (maybe_inst) |inst| blk: {979 const dest_reg = if (maybe_inst) |inst| blk: {
976 const bin_op = self.air.instructions.items(.data)[inst].bin_op;980 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
...@@ -1448,8 +1452,8 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo...@@ -1448,8 +1452,8 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
1448 .stack_offset,1452 .stack_offset,
1449 => {1453 => {
1450 const reg = try self.register_manager.allocReg(null);1454 const reg = try self.register_manager.allocReg(null);
1451 self.register_manager.freezeRegs(&.{reg});1455 const reg_lock = self.register_manager.freezeRegAssumeUnused(reg);
1452 defer self.register_manager.unfreezeRegs(&.{reg});1456 defer self.register_manager.unfreezeReg(reg_lock);
14531457
1454 try self.genSetReg(ptr_ty, reg, ptr);1458 try self.genSetReg(ptr_ty, reg, ptr);
1455 try self.load(dst_mcv, .{ .register = reg }, ptr_ty);1459 try self.load(dst_mcv, .{ .register = reg }, ptr_ty);
src/arch/x86_64/CodeGen.zig+422-241
...@@ -22,6 +22,8 @@ const Liveness = @import("../../Liveness.zig");...@@ -22,6 +22,8 @@ const Liveness = @import("../../Liveness.zig");
22const Mir = @import("Mir.zig");22const Mir = @import("Mir.zig");
23const Module = @import("../../Module.zig");23const Module = @import("../../Module.zig");
24const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;24const RegisterManagerFn = @import("../../register_manager.zig").RegisterManager;
25const RegisterManager = RegisterManagerFn(Self, Register, &allocatable_registers);
26const RegisterLock = RegisterManager.RegisterLock;
25const Target = std.Target;27const Target = std.Target;
26const Type = @import("../../type.zig").Type;28const Type = @import("../../type.zig").Type;
27const TypedValue = @import("../../TypedValue.zig");29const TypedValue = @import("../../TypedValue.zig");
...@@ -42,8 +44,6 @@ const InnerError = error{...@@ -42,8 +44,6 @@ const InnerError = error{
42 OutOfRegisters,44 OutOfRegisters,
43};45};
4446
45const RegisterManager = RegisterManagerFn(Self, Register, &allocatable_registers);
46
47gpa: Allocator,47gpa: Allocator,
48air: Air,48air: Air,
49liveness: Liveness,49liveness: Liveness,
...@@ -211,40 +211,6 @@ pub const MCValue = union(enum) {...@@ -211,40 +211,6 @@ pub const MCValue = union(enum) {
211 else => false,211 else => false,
212 };212 };
213 }213 }
214
215 fn freezeIfRegister(mcv: MCValue, mgr: *RegisterManager) void {
216 switch (mcv) {
217 .register,
218 .register_overflow_signed,
219 .register_overflow_unsigned,
220 => |reg| {
221 mgr.freezeRegs(&.{reg});
222 },
223 else => {},
224 }
225 }
226
227 fn unfreezeIfRegister(mcv: MCValue, mgr: *RegisterManager) void {
228 switch (mcv) {
229 .register,
230 .register_overflow_signed,
231 .register_overflow_unsigned,
232 => |reg| {
233 mgr.unfreezeRegs(&.{reg});
234 },
235 else => {},
236 }
237 }
238
239 fn asRegister(mcv: MCValue) ?Register {
240 return switch (mcv) {
241 .register,
242 .register_overflow_signed,
243 .register_overflow_unsigned,
244 => |reg| reg,
245 else => null,
246 };
247 }
248};214};
249215
250const Branch = struct {216const Branch = struct {
...@@ -876,15 +842,20 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live...@@ -876,15 +842,20 @@ fn finishAir(self: *Self, inst: Air.Inst.Index, result: MCValue, operands: [Live
876 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];842 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
877 branch.inst_table.putAssumeCapacityNoClobber(inst, result);843 branch.inst_table.putAssumeCapacityNoClobber(inst, result);
878844
879 if (result.asRegister()) |reg| {845 switch (result) {
880 // In some cases (such as bitcast), an operand846 .register,
881 // may be the same MCValue as the result. If847 .register_overflow_signed,
882 // that operand died and was a register, it848 .register_overflow_unsigned,
883 // was freed by processDeath. We have to849 => |reg| {
884 // "re-allocate" the register.850 // In some cases (such as bitcast), an operand
885 if (self.register_manager.isRegFree(reg)) {851 // may be the same MCValue as the result. If
886 self.register_manager.getRegAssumeFree(reg, inst);852 // that operand died and was a register, it
887 }853 // was freed by processDeath. We have to
854 // "re-allocate" the register.
855 if (self.register_manager.isRegFree(reg)) {
856 self.register_manager.getRegAssumeFree(reg, inst);
857 }
858 },
888 }859 }
889 }860 }
890 self.finishAirBookkeeping();861 self.finishAirBookkeeping();
...@@ -955,7 +926,15 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void...@@ -955,7 +926,15 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void
955 const stack_mcv = try self.allocRegOrMem(inst, false);926 const stack_mcv = try self.allocRegOrMem(inst, false);
956 log.debug("spilling {d} to stack mcv {any}", .{ inst, stack_mcv });927 log.debug("spilling {d} to stack mcv {any}", .{ inst, stack_mcv });
957 const reg_mcv = self.getResolvedInstValue(inst);928 const reg_mcv = self.getResolvedInstValue(inst);
958 assert(reg.to64() == reg_mcv.asRegister().?.to64());929 switch (reg_mcv) {
930 .register,
931 .register_overflow_unsigned,
932 .register_overflow_signed,
933 => |other| {
934 assert(reg.to64() == other.to64());
935 },
936 else => {},
937 }
959 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];938 const branch = &self.branch_stack.items[self.branch_stack.items.len - 1];
960 try branch.inst_table.put(self.gpa, inst, stack_mcv);939 try branch.inst_table.put(self.gpa, inst, stack_mcv);
961 try self.genSetStack(self.air.typeOfIndex(inst), stack_mcv.stack_offset, reg_mcv, .{});940 try self.genSetStack(self.air.typeOfIndex(inst), stack_mcv.stack_offset, reg_mcv, .{});
...@@ -1043,8 +1022,11 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {...@@ -1043,8 +1022,11 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
1043 return self.fail("TODO implement intCast for abi sizes larger than 8", .{});1022 return self.fail("TODO implement intCast for abi sizes larger than 8", .{});
1044 }1023 }
10451024
1046 operand.freezeIfRegister(&self.register_manager);1025 const operand_lock: ?RegisterLock = switch (operand) {
1047 defer operand.unfreezeIfRegister(&self.register_manager);1026 .register => |reg| self.register_manager.freezeRegAssumeUnused(reg),
1027 else => null,
1028 };
1029 defer if (operand_lock) |reg| self.register_manager.unfreezeReg(reg);
10481030
1049 const reg = try self.register_manager.allocReg(inst);1031 const reg = try self.register_manager.allocReg(inst);
1050 try self.genSetReg(dest_ty, reg, .{ .immediate = 0 });1032 try self.genSetReg(dest_ty, reg, .{ .immediate = 0 });
...@@ -1071,8 +1053,11 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {...@@ -1071,8 +1053,11 @@ fn airTrunc(self: *Self, inst: Air.Inst.Index) !void {
1071 return self.fail("TODO implement trunc for abi sizes larger than 8", .{});1053 return self.fail("TODO implement trunc for abi sizes larger than 8", .{});
1072 }1054 }
10731055
1074 operand.freezeIfRegister(&self.register_manager);1056 const operand_lock: ?RegisterLock = switch (operand) {
1075 defer operand.unfreezeIfRegister(&self.register_manager);1057 .register => |reg| self.register_manager.freezeRegAssumeUnused(reg),
1058 else => null,
1059 };
1060 defer if (operand_lock) |reg| self.register_manager.unfreezeReg(reg);
10761061
1077 const reg: Register = blk: {1062 const reg: Register = blk: {
1078 if (operand.isRegister()) {1063 if (operand.isRegister()) {
...@@ -1156,16 +1141,22 @@ fn airMin(self: *Self, inst: Air.Inst.Index) !void {...@@ -1156,16 +1141,22 @@ fn airMin(self: *Self, inst: Air.Inst.Index) !void {
1156 // TODO improve by checking if any operand can be reused.1141 // TODO improve by checking if any operand can be reused.
1157 // TODO audit register allocation1142 // TODO audit register allocation
1158 const lhs = try self.resolveInst(bin_op.lhs);1143 const lhs = try self.resolveInst(bin_op.lhs);
1159 lhs.freezeIfRegister(&self.register_manager);1144 const lhs_lock: ?RegisterLock = switch (lhs) {
1160 defer lhs.unfreezeIfRegister(&self.register_manager);1145 .register => |reg| self.register_manager.freezeRegAssumeUnused(reg),
1146 else => null,
1147 };
1148 defer if (lhs_lock) |reg| self.register_manager.unfreezeReg(reg);
11611149
1162 const lhs_reg = try self.copyToTmpRegister(ty, lhs);1150 const lhs_reg = try self.copyToTmpRegister(ty, lhs);
1163 self.register_manager.freezeRegs(&.{lhs_reg});1151 const lhs_reg_lock = self.register_manager.freezeRegAssumeUnused(lhs_reg);
1164 defer self.register_manager.unfreezeRegs(&.{lhs_reg});1152 defer self.register_manager.unfreezeReg(lhs_reg_lock);
11651153
1166 const rhs_mcv = try self.limitImmediateType(bin_op.rhs, i32);1154 const rhs_mcv = try self.limitImmediateType(bin_op.rhs, i32);
1167 rhs_mcv.freezeIfRegister(&self.register_manager);1155 const rhs_lock: ?RegisterLock = switch (rhs_mcv) {
1168 defer rhs_mcv.unfreezeIfRegister(&self.register_manager);1156 .register => |reg| self.register_manager.freezeRegAssumeUnused(reg),
1157 else => null,
1158 };
1159 defer if (rhs_lock) |reg| self.register_manager.unfreezeReg(reg);
11691160
1170 try self.genBinMathOpMir(.cmp, ty, .{ .register = lhs_reg }, rhs_mcv);1161 try self.genBinMathOpMir(.cmp, ty, .{ .register = lhs_reg }, rhs_mcv);
11711162
...@@ -1200,8 +1191,11 @@ fn genPtrBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_r...@@ -1200,8 +1191,11 @@ fn genPtrBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_r
1200 const offset = try self.resolveInst(op_rhs);1191 const offset = try self.resolveInst(op_rhs);
1201 const offset_ty = self.air.typeOf(op_rhs);1192 const offset_ty = self.air.typeOf(op_rhs);
12021193
1203 offset.freezeIfRegister(&self.register_manager);1194 const offset_lock: ?RegisterLock = switch (offset) {
1204 defer offset.unfreezeIfRegister(&self.register_manager);1195 .register => |reg| self.register_manager.freezeRegAssumeUnused(reg),
1196 else => null,
1197 };
1198 defer if (offset_lock) |reg| self.register_manager.unfreezeReg(reg);
12051199
1206 const dst_mcv = blk: {1200 const dst_mcv = blk: {
1207 if (self.reuseOperand(inst, op_lhs, 0, ptr)) {1201 if (self.reuseOperand(inst, op_lhs, 0, ptr)) {
...@@ -1210,8 +1204,11 @@ fn genPtrBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_r...@@ -1210,8 +1204,11 @@ fn genPtrBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_r
1210 break :blk MCValue{ .register = try self.copyToTmpRegister(dst_ty, ptr) };1204 break :blk MCValue{ .register = try self.copyToTmpRegister(dst_ty, ptr) };
1211 };1205 };
12121206
1213 dst_mcv.freezeIfRegister(&self.register_manager);1207 const dst_mcv_lock: ?RegisterLock = switch (dst_mcv) {
1214 defer dst_mcv.unfreezeIfRegister(&self.register_manager);1208 .register => |reg| self.register_manager.freezeRegAssumeUnused(reg),
1209 else => null,
1210 };
1211 defer if (dst_mcv_lock) |reg| self.register_manager.unfreezeReg(reg);
12151212
1216 const offset_mcv = blk: {1213 const offset_mcv = blk: {
1217 if (self.reuseOperand(inst, op_rhs, 1, offset)) {1214 if (self.reuseOperand(inst, op_rhs, 1, offset)) {
...@@ -1220,8 +1217,11 @@ fn genPtrBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_r...@@ -1220,8 +1217,11 @@ fn genPtrBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_r
1220 break :blk MCValue{ .register = try self.copyToTmpRegister(offset_ty, offset) };1217 break :blk MCValue{ .register = try self.copyToTmpRegister(offset_ty, offset) };
1221 };1218 };
12221219
1223 offset_mcv.freezeIfRegister(&self.register_manager);1220 const offset_mcv_lock: ?RegisterLock = switch (offset_mcv) {
1224 defer offset_mcv.unfreezeIfRegister(&self.register_manager);1221 .register => |reg| self.register_manager.freezeReg(reg),
1222 else => null,
1223 };
1224 defer if (offset_mcv_lock) |reg| self.register_manager.unfreezeReg(reg);
12251225
1226 try self.genIntMulComplexOpMir(offset_ty, offset_mcv, .{ .immediate = elem_size });1226 try self.genIntMulComplexOpMir(offset_ty, offset_mcv, .{ .immediate = elem_size });
12271227
...@@ -1306,12 +1306,18 @@ fn genSubOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs: Air...@@ -1306,12 +1306,18 @@ fn genSubOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs: Air
1306 const dst_ty = self.air.typeOf(op_lhs);1306 const dst_ty = self.air.typeOf(op_lhs);
13071307
1308 const lhs = try self.resolveInst(op_lhs);1308 const lhs = try self.resolveInst(op_lhs);
1309 lhs.freezeIfRegister(&self.register_manager);1309 const lhs_lock: ?RegisterLock = switch (lhs) {
1310 defer lhs.unfreezeIfRegister(&self.register_manager);1310 .register => |reg| self.register_manager.freezeRegAssumeUnused(reg),
1311 else => null,
1312 };
1313 defer if (lhs_lock) |reg| self.register_manager.unfreezeReg(reg);
13111314
1312 const rhs = try self.resolveInst(op_rhs);1315 const rhs = try self.resolveInst(op_rhs);
1313 rhs.freezeIfRegister(&self.register_manager);1316 const rhs_lock: ?RegisterLock = switch (rhs) {
1314 defer rhs.unfreezeIfRegister(&self.register_manager);1317 .register => |reg| self.register_manager.freezeRegAssumeUnused(reg),
1318 else => null,
1319 };
1320 defer if (rhs_lock) |reg| self.register_manager.unfreezeReg(reg);
13151321
1316 const dst_mcv = blk: {1322 const dst_mcv = blk: {
1317 if (self.reuseOperand(inst, op_lhs, 0, lhs) and lhs.isRegister()) {1323 if (self.reuseOperand(inst, op_lhs, 0, lhs) and lhs.isRegister()) {
...@@ -1319,17 +1325,21 @@ fn genSubOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs: Air...@@ -1319,17 +1325,21 @@ fn genSubOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs: Air
1319 }1325 }
1320 break :blk try self.copyToRegisterWithInstTracking(inst, dst_ty, lhs);1326 break :blk try self.copyToRegisterWithInstTracking(inst, dst_ty, lhs);
1321 };1327 };
13221328 const dst_mcv_lock: ?RegisterLock = switch (dst_mcv) {
1323 dst_mcv.freezeIfRegister(&self.register_manager);1329 .register => |reg| self.register_manager.freezeReg(reg),
1324 defer dst_mcv.unfreezeIfRegister(&self.register_manager);1330 else => null,
1331 };
1332 defer if (dst_mcv_lock) |reg| self.register_manager.unfreezeReg(reg);
13251333
1326 const rhs_mcv = blk: {1334 const rhs_mcv = blk: {
1327 if (rhs.isMemory() or rhs.isRegister()) break :blk rhs;1335 if (rhs.isMemory() or rhs.isRegister()) break :blk rhs;
1328 break :blk MCValue{ .register = try self.copyToTmpRegister(dst_ty, rhs) };1336 break :blk MCValue{ .register = try self.copyToTmpRegister(dst_ty, rhs) };
1329 };1337 };
13301338 const rhs_mcv_lock: ?RegisterLock = switch (rhs_mcv) {
1331 rhs_mcv.freezeIfRegister(&self.register_manager);1339 .register => |reg| self.register_manager.freezeReg(reg),
1332 defer rhs_mcv.unfreezeIfRegister(&self.register_manager);1340 else => null,
1341 };
1342 defer if (rhs_mcv_lock) |reg| self.register_manager.unfreezeReg(reg);
13331343
1334 try self.genBinMathOpMir(.sub, dst_ty, dst_mcv, rhs_mcv);1344 try self.genBinMathOpMir(.sub, dst_ty, dst_mcv, rhs_mcv);
13351345
...@@ -1366,8 +1376,11 @@ fn airMul(self: *Self, inst: Air.Inst.Index) !void {...@@ -1366,8 +1376,11 @@ fn airMul(self: *Self, inst: Air.Inst.Index) !void {
1366 // Spill .rax and .rdx upfront to ensure we don't spill the operands too late.1376 // Spill .rax and .rdx upfront to ensure we don't spill the operands too late.
1367 try self.register_manager.getReg(.rax, inst);1377 try self.register_manager.getReg(.rax, inst);
1368 try self.register_manager.getReg(.rdx, null);1378 try self.register_manager.getReg(.rdx, null);
1369 self.register_manager.freezeRegs(&.{ .rax, .rdx });1379 var reg_locks: [2]RegisterLock = undefined;
1370 defer self.register_manager.unfreezeRegs(&.{ .rax, .rdx });1380 self.register_manager.freezeRegsAssumeUnused(2, .{ .rax, .rdx }, &reg_locks);
1381 defer for (reg_locks) |reg| {
1382 self.register_manager.unfreezeReg(reg);
1383 };
13711384
1372 const lhs = try self.resolveInst(bin_op.lhs);1385 const lhs = try self.resolveInst(bin_op.lhs);
1373 const rhs = try self.resolveInst(bin_op.rhs);1386 const rhs = try self.resolveInst(bin_op.rhs);
...@@ -1477,8 +1490,11 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1477,8 +1490,11 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1477 // Spill .rax and .rdx upfront to ensure we don't spill the operands too late.1490 // Spill .rax and .rdx upfront to ensure we don't spill the operands too late.
1478 try self.register_manager.getReg(.rax, inst);1491 try self.register_manager.getReg(.rax, inst);
1479 try self.register_manager.getReg(.rdx, null);1492 try self.register_manager.getReg(.rdx, null);
1480 self.register_manager.freezeRegs(&.{ .rax, .rdx });1493 var reg_locks: [2]RegisterLock = undefined;
1481 defer self.register_manager.unfreezeRegs(&.{ .rax, .rdx });1494 self.register_manager.freezeRegsAssumeUnused(2, .{ .rax, .rdx }, &reg_locks);
1495 defer for (reg_locks) |reg| {
1496 self.register_manager.unfreezeReg(reg);
1497 };
14821498
1483 const lhs = try self.resolveInst(bin_op.lhs);1499 const lhs = try self.resolveInst(bin_op.lhs);
1484 const rhs = try self.resolveInst(bin_op.rhs);1500 const rhs = try self.resolveInst(bin_op.rhs);
...@@ -1504,21 +1520,28 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1504,21 +1520,28 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1504 const lhs = try self.resolveInst(bin_op.lhs);1520 const lhs = try self.resolveInst(bin_op.lhs);
1505 const rhs = try self.resolveInst(bin_op.rhs);1521 const rhs = try self.resolveInst(bin_op.rhs);
15061522
1507 rhs.freezeIfRegister(&self.register_manager);1523 const rhs_lock: ?RegisterLock = switch (rhs) {
1508 defer rhs.unfreezeIfRegister(&self.register_manager);1524 .register => |reg| self.register_manager.freezeRegAssumeUnused(reg),
1525 else => null,
1526 };
1527 defer if (rhs_lock) |reg| self.register_manager.unfreezeReg(reg);
15091528
1510 const dst_reg: Register = blk: {1529 const dst_reg: Register = blk: {
1511 if (lhs.isRegister()) break :blk lhs.register;1530 if (lhs.isRegister()) break :blk lhs.register;
1512 break :blk try self.copyToTmpRegister(ty, lhs);1531 break :blk try self.copyToTmpRegister(ty, lhs);
1513 };1532 };
1514 self.register_manager.freezeRegs(&.{dst_reg});1533 const dst_reg_lock = self.register_manager.freezeRegAssumeUnused(dst_reg);
1534 defer self.register_manager.unfreezeReg(dst_reg_lock);
15151535
1516 const rhs_mcv = blk: {1536 const rhs_mcv = blk: {
1517 if (rhs.isRegister() or rhs.isMemory()) break :blk rhs;1537 if (rhs.isRegister() or rhs.isMemory()) break :blk rhs;
1518 break :blk MCValue{ .register = try self.copyToTmpRegister(ty, rhs) };1538 break :blk MCValue{ .register = try self.copyToTmpRegister(ty, rhs) };
1519 };1539 };
1520 rhs_mcv.freezeIfRegister(&self.register_manager);1540 const rhs_mcv_lock: ?RegisterLock = switch (rhs_mcv) {
1521 defer rhs_mcv.unfreezeIfRegister(&self.register_manager);1541 .register => |reg| self.register_manager.freezeReg(reg),
1542 else => null,
1543 };
1544 defer if (rhs_mcv_lock) |reg| self.register_manager.unfreezeReg(reg);
15221545
1523 try self.genIntMulComplexOpMir(Type.isize, .{ .register = dst_reg }, rhs_mcv);1546 try self.genIntMulComplexOpMir(Type.isize, .{ .register = dst_reg }, rhs_mcv);
15241547
...@@ -1528,8 +1551,11 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1528,8 +1551,11 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1528 // Spill .rax and .rdx upfront to ensure we don't spill the operands too late.1551 // Spill .rax and .rdx upfront to ensure we don't spill the operands too late.
1529 try self.register_manager.getReg(.rax, null);1552 try self.register_manager.getReg(.rax, null);
1530 try self.register_manager.getReg(.rdx, null);1553 try self.register_manager.getReg(.rdx, null);
1531 self.register_manager.freezeRegs(&.{ .rax, .rdx });1554 var reg_locks: [2]RegisterLock = undefined;
1532 defer self.register_manager.unfreezeRegs(&.{.rdx});1555 self.register_manager.freezeRegsAssumeUnused(2, .{ .rax, .rdx }, &reg_locks);
1556 defer for (reg_locks) |reg| {
1557 self.register_manager.unfreezeReg(reg);
1558 };
15331559
1534 const lhs = try self.resolveInst(bin_op.lhs);1560 const lhs = try self.resolveInst(bin_op.lhs);
1535 const rhs = try self.resolveInst(bin_op.rhs);1561 const rhs = try self.resolveInst(bin_op.rhs);
...@@ -1540,7 +1566,8 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1540,7 +1566,8 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1540 },1566 },
1541 }1567 }
1542 };1568 };
1543 defer self.register_manager.unfreezeRegs(&.{dst_reg});1569 const dst_reg_lock = self.register_manager.freezeRegAssumeUnused(dst_reg);
1570 defer self.register_manager.unfreezeReg(dst_reg_lock);
15441571
1545 const tuple_ty = self.air.typeOfIndex(inst);1572 const tuple_ty = self.air.typeOfIndex(inst);
1546 const tuple_size = @intCast(u32, tuple_ty.abiSize(self.target.*));1573 const tuple_size = @intCast(u32, tuple_ty.abiSize(self.target.*));
...@@ -1554,8 +1581,11 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1554,8 +1581,11 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1554 };1581 };
15551582
1556 const temp_regs = try self.register_manager.allocRegs(3, .{ null, null, null });1583 const temp_regs = try self.register_manager.allocRegs(3, .{ null, null, null });
1557 self.register_manager.freezeRegs(&temp_regs);1584 var temp_regs_locks: [3]RegisterLock = undefined;
1558 defer self.register_manager.unfreezeRegs(&temp_regs);1585 self.register_manager.freezeRegsAssumeUnused(3, temp_regs, &temp_regs_locks);
1586 defer for (temp_regs_locks) |reg| {
1587 self.register_manager.unfreezeReg(reg);
1588 };
15591589
1560 const overflow_reg = temp_regs[0];1590 const overflow_reg = temp_regs[0];
1561 const flags: u2 = switch (int_info.signedness) {1591 const flags: u2 = switch (int_info.signedness) {
...@@ -1703,14 +1733,15 @@ fn genInlineIntDivFloor(self: *Self, ty: Type, lhs: MCValue, rhs: MCValue) !MCVa...@@ -1703,14 +1733,15 @@ fn genInlineIntDivFloor(self: *Self, ty: Type, lhs: MCValue, rhs: MCValue) !MCVa
1703 .register => |reg| reg,1733 .register => |reg| reg,
1704 else => try self.copyToTmpRegister(ty, lhs),1734 else => try self.copyToTmpRegister(ty, lhs),
1705 };1735 };
1706 self.register_manager.freezeRegs(&.{dividend});1736 const dividend_lock = self.register_manager.freezeReg(dividend);
1737 defer if (dividend_lock) |reg| self.register_manager.unfreezeReg(reg);
17071738
1708 const divisor = switch (rhs) {1739 const divisor = switch (rhs) {
1709 .register => |reg| reg,1740 .register => |reg| reg,
1710 else => try self.copyToTmpRegister(ty, rhs),1741 else => try self.copyToTmpRegister(ty, rhs),
1711 };1742 };
1712 self.register_manager.freezeRegs(&.{divisor});1743 const divisor_lock = self.register_manager.freezeReg(divisor);
1713 defer self.register_manager.unfreezeRegs(&.{ dividend, divisor });1744 defer if (divisor_lock) |reg| self.register_manager.unfreezeReg(reg);
17141745
1715 try self.genIntMulDivOpMir(switch (signedness) {1746 try self.genIntMulDivOpMir(switch (signedness) {
1716 .signed => .idiv,1747 .signed => .idiv,
...@@ -1779,20 +1810,30 @@ fn airDiv(self: *Self, inst: Air.Inst.Index) !void {...@@ -1779,20 +1810,30 @@ fn airDiv(self: *Self, inst: Air.Inst.Index) !void {
1779 };1810 };
1780 try self.register_manager.getReg(.rax, track_rax);1811 try self.register_manager.getReg(.rax, track_rax);
1781 try self.register_manager.getReg(.rdx, null);1812 try self.register_manager.getReg(.rdx, null);
1782 self.register_manager.freezeRegs(&.{ .rax, .rdx });1813 var reg_locks: [2]RegisterLock = undefined;
1783 defer self.register_manager.unfreezeRegs(&.{ .rax, .rdx });1814 self.register_manager.freezeRegsAssumeUnused(2, .{ .rax, .rdx }, &reg_locks);
1815 defer for (reg_locks) |reg| {
1816 self.register_manager.unfreezeReg(reg);
1817 };
17841818
1785 const lhs = try self.resolveInst(bin_op.lhs);1819 const lhs = try self.resolveInst(bin_op.lhs);
1786 lhs.freezeIfRegister(&self.register_manager);1820 const lhs_lock: ?RegisterLock = switch (lhs) {
1787 defer lhs.unfreezeIfRegister(&self.register_manager);1821 .register => |reg| self.register_manager.freezeRegAssumeUnused(reg),
1822 else => null,
1823 };
1824 defer if (lhs_lock) |reg| self.register_manager.unfreezeReg(reg);
17881825
1789 const rhs = blk: {1826 const rhs = blk: {
1790 const rhs = try self.resolveInst(bin_op.rhs);1827 const rhs = try self.resolveInst(bin_op.rhs);
1791 if (signedness == .signed) {1828 if (signedness == .signed) {
1792 switch (tag) {1829 switch (tag) {
1793 .div_floor => {1830 .div_floor => {
1794 rhs.freezeIfRegister(&self.register_manager);1831 const rhs_lock: ?RegisterLock = switch (rhs) {
1795 defer rhs.unfreezeIfRegister(&self.register_manager);1832 .register => |reg| self.register_manager.freezeRegAssumeUnused(reg),
1833 else => null,
1834 };
1835 defer if (rhs_lock) |reg| self.register_manager.unfreezeReg(reg);
1836
1796 break :blk try self.copyToRegisterWithInstTracking(inst, ty, rhs);1837 break :blk try self.copyToRegisterWithInstTracking(inst, ty, rhs);
1797 },1838 },
1798 else => {},1839 else => {},
...@@ -1800,8 +1841,11 @@ fn airDiv(self: *Self, inst: Air.Inst.Index) !void {...@@ -1800,8 +1841,11 @@ fn airDiv(self: *Self, inst: Air.Inst.Index) !void {
1800 }1841 }
1801 break :blk rhs;1842 break :blk rhs;
1802 };1843 };
1803 rhs.freezeIfRegister(&self.register_manager);1844 const rhs_lock: ?RegisterLock = switch (rhs) {
1804 defer rhs.unfreezeIfRegister(&self.register_manager);1845 .register => |reg| self.register_manager.freezeReg(reg),
1846 else => null,
1847 };
1848 defer if (rhs_lock) |reg| self.register_manager.unfreezeReg(reg);
18051849
1806 if (signedness == .unsigned) {1850 if (signedness == .unsigned) {
1807 try self.genIntMulDivOpMir(.div, ty, signedness, lhs, rhs);1851 try self.genIntMulDivOpMir(.div, ty, signedness, lhs, rhs);
...@@ -1835,8 +1879,11 @@ fn airRem(self: *Self, inst: Air.Inst.Index) !void {...@@ -1835,8 +1879,11 @@ fn airRem(self: *Self, inst: Air.Inst.Index) !void {
1835 // Spill .rax and .rdx upfront to ensure we don't spill the operands too late.1879 // Spill .rax and .rdx upfront to ensure we don't spill the operands too late.
1836 try self.register_manager.getReg(.rax, null);1880 try self.register_manager.getReg(.rax, null);
1837 try self.register_manager.getReg(.rdx, inst);1881 try self.register_manager.getReg(.rdx, inst);
1838 self.register_manager.freezeRegs(&.{ .rax, .rdx });1882 var reg_locks: [2]RegisterLock = undefined;
1839 defer self.register_manager.unfreezeRegs(&.{ .rax, .rdx });1883 self.register_manager.freezeRegsAssumeUnused(2, .{ .rax, .rdx }, &reg_locks);
1884 defer for (reg_locks) |reg| {
1885 self.register_manager.unfreezeReg(reg);
1886 };
18401887
1841 const lhs = try self.resolveInst(bin_op.lhs);1888 const lhs = try self.resolveInst(bin_op.lhs);
1842 const rhs = try self.resolveInst(bin_op.rhs);1889 const rhs = try self.resolveInst(bin_op.rhs);
...@@ -1863,8 +1910,11 @@ fn airMod(self: *Self, inst: Air.Inst.Index) !void {...@@ -1863,8 +1910,11 @@ fn airMod(self: *Self, inst: Air.Inst.Index) !void {
1863 // Spill .rax and .rdx upfront to ensure we don't spill the operands too late.1910 // Spill .rax and .rdx upfront to ensure we don't spill the operands too late.
1864 try self.register_manager.getReg(.rax, null);1911 try self.register_manager.getReg(.rax, null);
1865 try self.register_manager.getReg(.rdx, if (signedness == .unsigned) inst else null);1912 try self.register_manager.getReg(.rdx, if (signedness == .unsigned) inst else null);
1866 self.register_manager.freezeRegs(&.{ .rax, .rdx });1913 var reg_locks: [2]RegisterLock = undefined;
1867 defer self.register_manager.unfreezeRegs(&.{ .rax, .rdx });1914 self.register_manager.freezeRegsAssumeUnused(2, .{ .rax, .rdx }, &reg_locks);
1915 defer for (reg_locks) |reg| {
1916 self.register_manager.unfreezeReg(reg);
1917 };
18681918
1869 const lhs = try self.resolveInst(bin_op.lhs);1919 const lhs = try self.resolveInst(bin_op.lhs);
1870 const rhs = try self.resolveInst(bin_op.rhs);1920 const rhs = try self.resolveInst(bin_op.rhs);
...@@ -1954,12 +2004,15 @@ fn airShl(self: *Self, inst: Air.Inst.Index) !void {...@@ -1954,12 +2004,15 @@ fn airShl(self: *Self, inst: Air.Inst.Index) !void {
1954 try self.register_manager.getReg(.rcx, null);2004 try self.register_manager.getReg(.rcx, null);
1955 try self.genSetReg(shift_ty, .rcx, shift);2005 try self.genSetReg(shift_ty, .rcx, shift);
1956 }2006 }
1957 self.register_manager.freezeRegs(&.{.rcx});2007 const rcx_lock = self.register_manager.freezeRegAssumeUnused(.rcx);
1958 defer self.register_manager.unfreezeRegs(&.{.rcx});2008 defer self.register_manager.unfreezeReg(rcx_lock);
19592009
1960 const value = try self.resolveInst(bin_op.lhs);2010 const value = try self.resolveInst(bin_op.lhs);
1961 value.freezeIfRegister(&self.register_manager);2011 const value_lock: ?RegisterLock = switch (value) {
1962 defer value.unfreezeIfRegister(&self.register_manager);2012 .register => |reg| self.register_manager.freezeRegAssumeUnused(reg),
2013 else => null,
2014 };
2015 defer if (value_lock) |reg| self.register_manager.unfreezeReg(reg);
19632016
1964 const dst_mcv = try self.copyToRegisterWithInstTracking(inst, ty, value);2017 const dst_mcv = try self.copyToRegisterWithInstTracking(inst, ty, value);
1965 _ = try self.addInst(.{2018 _ = try self.addInst(.{
...@@ -2055,8 +2108,11 @@ fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {...@@ -2055,8 +2108,11 @@ fn airUnwrapErrErr(self: *Self, inst: Air.Inst.Index) !void {
2055 const err_ty = err_union_ty.errorUnionSet();2108 const err_ty = err_union_ty.errorUnionSet();
2056 const payload_ty = err_union_ty.errorUnionPayload();2109 const payload_ty = err_union_ty.errorUnionPayload();
2057 const operand = try self.resolveInst(ty_op.operand);2110 const operand = try self.resolveInst(ty_op.operand);
2058 operand.freezeIfRegister(&self.register_manager);2111 const operand_lock: ?RegisterLock = switch (operand) {
2059 defer operand.unfreezeIfRegister(&self.register_manager);2112 .register => |reg| self.register_manager.freezeRegAssumeUnused(reg),
2113 else => null,
2114 };
2115 defer if (operand_lock) |reg| self.register_manager.unfreezeReg(reg);
20602116
2061 const result: MCValue = result: {2117 const result: MCValue = result: {
2062 if (!payload_ty.hasRuntimeBits()) break :result operand;2118 if (!payload_ty.hasRuntimeBits()) break :result operand;
...@@ -2085,8 +2141,11 @@ fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void {...@@ -2085,8 +2141,11 @@ fn airUnwrapErrPayload(self: *Self, inst: Air.Inst.Index) !void {
2085 if (!payload_ty.hasRuntimeBits()) break :result MCValue.none;2141 if (!payload_ty.hasRuntimeBits()) break :result MCValue.none;
20862142
2087 const operand = try self.resolveInst(ty_op.operand);2143 const operand = try self.resolveInst(ty_op.operand);
2088 operand.freezeIfRegister(&self.register_manager);2144 const operand_lock: ?RegisterLock = switch (operand) {
2089 defer operand.unfreezeIfRegister(&self.register_manager);2145 .register => |reg| self.register_manager.freezeRegAssumeUnused(reg),
2146 else => null,
2147 };
2148 defer if (operand_lock) |reg| self.register_manager.unfreezeReg(reg);
20902149
2091 const abi_align = err_union_ty.abiAlignment(self.target.*);2150 const abi_align = err_union_ty.abiAlignment(self.target.*);
2092 const err_ty = err_union_ty.errorUnionSet();2151 const err_ty = err_union_ty.errorUnionSet();
...@@ -2154,8 +2213,11 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {...@@ -2154,8 +2213,11 @@ fn airWrapOptional(self: *Self, inst: Air.Inst.Index) !void {
21542213
2155 const optional_ty = self.air.typeOfIndex(inst);2214 const optional_ty = self.air.typeOfIndex(inst);
2156 const operand = try self.resolveInst(ty_op.operand);2215 const operand = try self.resolveInst(ty_op.operand);
2157 operand.freezeIfRegister(&self.register_manager);2216 const operand_lock: ?RegisterLock = switch (operand) {
2158 defer operand.unfreezeIfRegister(&self.register_manager);2217 .register => |reg| self.register_manager.freezeRegAssumeUnused(reg),
2218 else => null,
2219 };
2220 defer if (operand_lock) |reg| self.register_manager.unfreezeReg(reg);
21592221
2160 if (optional_ty.isPtrLikeOptional()) {2222 if (optional_ty.isPtrLikeOptional()) {
2161 // TODO should we check if we can reuse the operand?2223 // TODO should we check if we can reuse the operand?
...@@ -2288,8 +2350,11 @@ fn elemOffset(self: *Self, index_ty: Type, index: MCValue, elem_size: u64) !Regi...@@ -2288,8 +2350,11 @@ fn elemOffset(self: *Self, index_ty: Type, index: MCValue, elem_size: u64) !Regi
2288fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue {2350fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue {
2289 const slice_ty = self.air.typeOf(lhs);2351 const slice_ty = self.air.typeOf(lhs);
2290 const slice_mcv = try self.resolveInst(lhs);2352 const slice_mcv = try self.resolveInst(lhs);
2291 slice_mcv.freezeIfRegister(&self.register_manager);2353 const slice_mcv_lock: ?RegisterLock = switch (slice_mcv) {
2292 defer slice_mcv.unfreezeIfRegister(&self.register_manager);2354 .register => |reg| self.register_manager.freezeRegAssumeUnused(reg),
2355 else => null,
2356 };
2357 defer if (slice_mcv_lock) |reg| self.register_manager.unfreezeReg(reg);
22932358
2294 const elem_ty = slice_ty.childType();2359 const elem_ty = slice_ty.childType();
2295 const elem_size = elem_ty.abiSize(self.target.*);2360 const elem_size = elem_ty.abiSize(self.target.*);
...@@ -2298,12 +2363,15 @@ fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue {...@@ -2298,12 +2363,15 @@ fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue {
22982363
2299 const index_ty = self.air.typeOf(rhs);2364 const index_ty = self.air.typeOf(rhs);
2300 const index_mcv = try self.resolveInst(rhs);2365 const index_mcv = try self.resolveInst(rhs);
2301 index_mcv.freezeIfRegister(&self.register_manager);2366 const index_mcv_lock: ?RegisterLock = switch (index_mcv) {
2302 defer index_mcv.unfreezeIfRegister(&self.register_manager);2367 .register => |reg| self.register_manager.freezeRegAssumeUnused(reg),
2368 else => null,
2369 };
2370 defer if (index_mcv_lock) |reg| self.register_manager.unfreezeReg(reg);
23032371
2304 const offset_reg = try self.elemOffset(index_ty, index_mcv, elem_size);2372 const offset_reg = try self.elemOffset(index_ty, index_mcv, elem_size);
2305 self.register_manager.freezeRegs(&.{offset_reg});2373 const offset_reg_lock = self.register_manager.freezeRegAssumeUnused(offset_reg);
2306 defer self.register_manager.unfreezeRegs(&.{offset_reg});2374 defer self.register_manager.unfreezeReg(offset_reg_lock);
23072375
2308 const addr_reg = try self.register_manager.allocReg(null);2376 const addr_reg = try self.register_manager.allocReg(null);
2309 switch (slice_mcv) {2377 switch (slice_mcv) {
...@@ -2359,20 +2427,26 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -2359,20 +2427,26 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
2359 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {2427 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2360 const array_ty = self.air.typeOf(bin_op.lhs);2428 const array_ty = self.air.typeOf(bin_op.lhs);
2361 const array = try self.resolveInst(bin_op.lhs);2429 const array = try self.resolveInst(bin_op.lhs);
2362 array.freezeIfRegister(&self.register_manager);2430 const array_lock: ?RegisterLock = switch (array) {
2363 defer array.unfreezeIfRegister(&self.register_manager);2431 .register => |reg| self.register_manager.freezeRegAssumeUnused(reg),
2432 else => null,
2433 };
2434 defer if (array_lock) |reg| self.register_manager.unfreezeReg(reg);
23642435
2365 const elem_ty = array_ty.childType();2436 const elem_ty = array_ty.childType();
2366 const elem_abi_size = elem_ty.abiSize(self.target.*);2437 const elem_abi_size = elem_ty.abiSize(self.target.*);
23672438
2368 const index_ty = self.air.typeOf(bin_op.rhs);2439 const index_ty = self.air.typeOf(bin_op.rhs);
2369 const index = try self.resolveInst(bin_op.rhs);2440 const index = try self.resolveInst(bin_op.rhs);
2370 index.freezeIfRegister(&self.register_manager);2441 const index_lock: ?RegisterLock = switch (index) {
2371 defer index.unfreezeIfRegister(&self.register_manager);2442 .register => |reg| self.register_manager.freezeRegAssumeUnused(reg),
2443 else => null,
2444 };
2445 defer if (index_lock) |reg| self.register_manager.unfreezeReg(reg);
23722446
2373 const offset_reg = try self.elemOffset(index_ty, index, elem_abi_size);2447 const offset_reg = try self.elemOffset(index_ty, index, elem_abi_size);
2374 self.register_manager.freezeRegs(&.{offset_reg});2448 const offset_reg_lock = self.register_manager.freezeRegAssumeUnused(offset_reg);
2375 defer self.register_manager.unfreezeRegs(&.{offset_reg});2449 defer self.register_manager.unfreezeReg(offset_reg_lock);
23762450
2377 const addr_reg = try self.register_manager.allocReg(null);2451 const addr_reg = try self.register_manager.allocReg(null);
2378 switch (array) {2452 switch (array) {
...@@ -2432,19 +2506,25 @@ fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -2432,19 +2506,25 @@ fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void {
24322506
2433 const ptr_ty = self.air.typeOf(bin_op.lhs);2507 const ptr_ty = self.air.typeOf(bin_op.lhs);
2434 const ptr = try self.resolveInst(bin_op.lhs);2508 const ptr = try self.resolveInst(bin_op.lhs);
2435 ptr.freezeIfRegister(&self.register_manager);2509 const ptr_lock: ?RegisterLock = switch (ptr) {
2436 defer ptr.unfreezeIfRegister(&self.register_manager);2510 .register => |reg| self.register_manager.freezeRegAssumeUnused(reg),
2511 else => null,
2512 };
2513 defer if (ptr_lock) |reg| self.register_manager.unfreezeReg(reg);
24372514
2438 const elem_ty = ptr_ty.elemType2();2515 const elem_ty = ptr_ty.elemType2();
2439 const elem_abi_size = elem_ty.abiSize(self.target.*);2516 const elem_abi_size = elem_ty.abiSize(self.target.*);
2440 const index_ty = self.air.typeOf(bin_op.rhs);2517 const index_ty = self.air.typeOf(bin_op.rhs);
2441 const index = try self.resolveInst(bin_op.rhs);2518 const index = try self.resolveInst(bin_op.rhs);
2442 index.freezeIfRegister(&self.register_manager);2519 const index_lock: ?RegisterLock = switch (index) {
2443 defer index.unfreezeIfRegister(&self.register_manager);2520 .register => |reg| self.register_manager.freezeRegAssumeUnused(reg),
2521 else => null,
2522 };
2523 defer if (index_lock) |reg| self.register_manager.unfreezeReg(reg);
24442524
2445 const offset_reg = try self.elemOffset(index_ty, index, elem_abi_size);2525 const offset_reg = try self.elemOffset(index_ty, index, elem_abi_size);
2446 self.register_manager.freezeRegs(&.{offset_reg});2526 const offset_reg_lock = self.register_manager.freezeRegAssumeUnused(offset_reg);
2447 defer self.register_manager.unfreezeRegs(&.{offset_reg});2527 defer self.register_manager.unfreezeReg(offset_reg_lock);
24482528
2449 const dst_mcv = try self.copyToRegisterWithInstTracking(inst, ptr_ty, ptr);2529 const dst_mcv = try self.copyToRegisterWithInstTracking(inst, ptr_ty, ptr);
2450 try self.genBinMathOpMir(.add, ptr_ty, dst_mcv, .{ .register = offset_reg });2530 try self.genBinMathOpMir(.add, ptr_ty, dst_mcv, .{ .register = offset_reg });
...@@ -2473,19 +2553,25 @@ fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -2473,19 +2553,25 @@ fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void {
2473 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {2553 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
2474 const ptr_ty = self.air.typeOf(extra.lhs);2554 const ptr_ty = self.air.typeOf(extra.lhs);
2475 const ptr = try self.resolveInst(extra.lhs);2555 const ptr = try self.resolveInst(extra.lhs);
2476 ptr.freezeIfRegister(&self.register_manager);2556 const ptr_lock: ?RegisterLock = switch (ptr) {
2477 defer ptr.unfreezeIfRegister(&self.register_manager);2557 .register => |reg| self.register_manager.freezeRegAssumeUnused(reg),
2558 else => null,
2559 };
2560 defer if (ptr_lock) |reg| self.register_manager.unfreezeReg(reg);
24782561
2479 const elem_ty = ptr_ty.elemType2();2562 const elem_ty = ptr_ty.elemType2();
2480 const elem_abi_size = elem_ty.abiSize(self.target.*);2563 const elem_abi_size = elem_ty.abiSize(self.target.*);
2481 const index_ty = self.air.typeOf(extra.rhs);2564 const index_ty = self.air.typeOf(extra.rhs);
2482 const index = try self.resolveInst(extra.rhs);2565 const index = try self.resolveInst(extra.rhs);
2483 index.freezeIfRegister(&self.register_manager);2566 const index_lock: ?RegisterLock = switch (index) {
2484 defer index.unfreezeIfRegister(&self.register_manager);2567 .register => |reg| self.register_manager.freezeRegAssumeUnused(reg),
2568 else => null,
2569 };
2570 defer if (index_lock) |reg| self.register_manager.unfreezeReg(reg);
24852571
2486 const offset_reg = try self.elemOffset(index_ty, index, elem_abi_size);2572 const offset_reg = try self.elemOffset(index_ty, index, elem_abi_size);
2487 self.register_manager.freezeRegs(&.{offset_reg});2573 const offset_reg_lock = self.register_manager.freezeRegAssumeUnused(offset_reg);
2488 defer self.register_manager.unfreezeRegs(&.{offset_reg});2574 defer self.register_manager.unfreezeReg(offset_reg_lock);
24892575
2490 const dst_mcv = try self.copyToRegisterWithInstTracking(inst, ptr_ty, ptr);2576 const dst_mcv = try self.copyToRegisterWithInstTracking(inst, ptr_ty, ptr);
2491 try self.genBinMathOpMir(.add, ptr_ty, dst_mcv, .{ .register = offset_reg });2577 try self.genBinMathOpMir(.add, ptr_ty, dst_mcv, .{ .register = offset_reg });
...@@ -2506,12 +2592,18 @@ fn airSetUnionTag(self: *Self, inst: Air.Inst.Index) !void {...@@ -2506,12 +2592,18 @@ fn airSetUnionTag(self: *Self, inst: Air.Inst.Index) !void {
2506 }2592 }
25072593
2508 const ptr = try self.resolveInst(bin_op.lhs);2594 const ptr = try self.resolveInst(bin_op.lhs);
2509 ptr.freezeIfRegister(&self.register_manager);2595 const ptr_lock: ?RegisterLock = switch (ptr) {
2510 defer ptr.unfreezeIfRegister(&self.register_manager);2596 .register => |reg| self.register_manager.freezeRegAssumeUnused(reg),
2597 else => null,
2598 };
2599 defer if (ptr_lock) |reg| self.register_manager.unfreezeReg(reg);
25112600
2512 const tag = try self.resolveInst(bin_op.rhs);2601 const tag = try self.resolveInst(bin_op.rhs);
2513 tag.freezeIfRegister(&self.register_manager);2602 const tag_lock: ?RegisterLock = switch (tag) {
2514 defer tag.unfreezeIfRegister(&self.register_manager);2603 .register => |reg| self.register_manager.freezeRegAssumeUnused(reg),
2604 else => null,
2605 };
2606 defer if (tag_lock) |reg| self.register_manager.unfreezeReg(reg);
25152607
2516 const adjusted_ptr: MCValue = if (layout.payload_size > 0 and layout.tag_align < layout.payload_align) blk: {2608 const adjusted_ptr: MCValue = if (layout.payload_size > 0 and layout.tag_align < layout.payload_align) blk: {
2517 // TODO reusing the operand2609 // TODO reusing the operand
...@@ -2541,8 +2633,11 @@ fn airGetUnionTag(self: *Self, inst: Air.Inst.Index) !void {...@@ -2541,8 +2633,11 @@ fn airGetUnionTag(self: *Self, inst: Air.Inst.Index) !void {
25412633
2542 // TODO reusing the operand2634 // TODO reusing the operand
2543 const operand = try self.resolveInst(ty_op.operand);2635 const operand = try self.resolveInst(ty_op.operand);
2544 operand.freezeIfRegister(&self.register_manager);2636 const operand_lock: ?RegisterLock = switch (operand) {
2545 defer operand.unfreezeIfRegister(&self.register_manager);2637 .register => |reg| self.register_manager.freezeRegAssumeUnused(reg),
2638 else => null,
2639 };
2640 defer if (operand_lock) |reg| self.register_manager.unfreezeReg(reg);
25462641
2547 const tag_abi_size = tag_ty.abiSize(self.target.*);2642 const tag_abi_size = tag_ty.abiSize(self.target.*);
2548 const dst_mcv: MCValue = blk: {2643 const dst_mcv: MCValue = blk: {
...@@ -2689,8 +2784,8 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo...@@ -2689,8 +2784,8 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
2689 try self.setRegOrMem(elem_ty, dst_mcv, .{ .stack_offset = off });2784 try self.setRegOrMem(elem_ty, dst_mcv, .{ .stack_offset = off });
2690 },2785 },
2691 .register => |reg| {2786 .register => |reg| {
2692 self.register_manager.freezeRegs(&.{reg});2787 const reg_lock = self.register_manager.freezeReg(reg);
2693 defer self.register_manager.unfreezeRegs(&.{reg});2788 defer if (reg_lock) |locked_reg| self.register_manager.unfreezeReg(locked_reg);
26942789
2695 switch (dst_mcv) {2790 switch (dst_mcv) {
2696 .dead => unreachable,2791 .dead => unreachable,
...@@ -2815,8 +2910,8 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -2815,8 +2910,8 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
2815 try self.genSetStack(value_ty, off, value, .{});2910 try self.genSetStack(value_ty, off, value, .{});
2816 },2911 },
2817 .register => |reg| {2912 .register => |reg| {
2818 self.register_manager.freezeRegs(&.{reg});2913 const reg_lock = self.register_manager.freezeReg(reg);
2819 defer self.register_manager.unfreezeRegs(&.{reg});2914 defer if (reg_lock) |locked_reg| self.register_manager.unfreezeReg(locked_reg);
28202915
2821 switch (value) {2916 switch (value) {
2822 .none => unreachable,2917 .none => unreachable,
...@@ -2906,12 +3001,15 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -2906,12 +3001,15 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
2906 .direct_load,3001 .direct_load,
2907 .memory,3002 .memory,
2908 => {3003 => {
2909 value.freezeIfRegister(&self.register_manager);3004 const value_lock: ?RegisterLock = switch (value) {
2910 defer value.unfreezeIfRegister(&self.register_manager);3005 .register => |reg| self.register_manager.freezeReg(reg),
3006 else => null,
3007 };
3008 defer if (value_lock) |reg| self.register_manager.unfreezeReg(reg);
29113009
2912 const addr_reg = try self.register_manager.allocReg(null);3010 const addr_reg = try self.register_manager.allocReg(null);
2913 self.register_manager.freezeRegs(&.{addr_reg});3011 const addr_reg_lock = self.register_manager.freezeRegAssumeUnused(addr_reg);
2914 defer self.register_manager.unfreezeRegs(&.{addr_reg});3012 defer self.register_manager.unfreezeReg(addr_reg_lock);
29153013
2916 try self.loadMemPtrIntoRegister(addr_reg, ptr_ty, ptr);3014 try self.loadMemPtrIntoRegister(addr_reg, ptr_ty, ptr);
29173015
...@@ -2982,8 +3080,8 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -2982,8 +3080,8 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
2982 => {3080 => {
2983 if (abi_size <= 8) {3081 if (abi_size <= 8) {
2984 const tmp_reg = try self.register_manager.allocReg(null);3082 const tmp_reg = try self.register_manager.allocReg(null);
2985 self.register_manager.freezeRegs(&.{tmp_reg});3083 const tmp_reg_lock = self.register_manager.freezeRegAssumeUnused(tmp_reg);
2986 defer self.register_manager.unfreezeRegs(&.{tmp_reg});3084 defer self.register_manager.unfreezeReg(tmp_reg_lock);
29873085
2988 try self.loadMemPtrIntoRegister(tmp_reg, value_ty, value);3086 try self.loadMemPtrIntoRegister(tmp_reg, value_ty, value);
29893087
...@@ -3073,8 +3171,8 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde...@@ -3073,8 +3171,8 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde
3073 const offset_reg = try self.copyToTmpRegister(ptr_ty, .{3171 const offset_reg = try self.copyToTmpRegister(ptr_ty, .{
3074 .immediate = struct_field_offset,3172 .immediate = struct_field_offset,
3075 });3173 });
3076 self.register_manager.freezeRegs(&.{offset_reg});3174 const offset_reg_lock = self.register_manager.freezeRegAssumeUnused(offset_reg);
3077 defer self.register_manager.unfreezeRegs(&.{offset_reg});3175 defer self.register_manager.unfreezeReg(offset_reg_lock);
30783176
3079 const dst_mcv = try self.copyToRegisterWithInstTracking(inst, ptr_ty, mcv);3177 const dst_mcv = try self.copyToRegisterWithInstTracking(inst, ptr_ty, mcv);
3080 try self.genBinMathOpMir(.add, ptr_ty, dst_mcv, .{ .register = offset_reg });3178 try self.genBinMathOpMir(.add, ptr_ty, dst_mcv, .{ .register = offset_reg });
...@@ -3085,24 +3183,27 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde...@@ -3085,24 +3183,27 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde
3085 break :result MCValue{ .ptr_stack_offset = ptr_stack_offset };3183 break :result MCValue{ .ptr_stack_offset = ptr_stack_offset };
3086 },3184 },
3087 .register => |reg| {3185 .register => |reg| {
3186 const reg_lock = self.register_manager.freezeRegAssumeUnused(reg);
3187 defer self.register_manager.unfreezeReg(reg_lock);
3188
3088 const offset_reg = try self.copyToTmpRegister(ptr_ty, .{3189 const offset_reg = try self.copyToTmpRegister(ptr_ty, .{
3089 .immediate = struct_field_offset,3190 .immediate = struct_field_offset,
3090 });3191 });
3091 self.register_manager.freezeRegs(&.{offset_reg});3192 const offset_reg_lock = self.register_manager.freezeRegAssumeUnused(offset_reg);
3092 defer self.register_manager.unfreezeRegs(&.{offset_reg});3193 defer self.register_manager.unfreezeReg(offset_reg_lock);
30933194
3094 const can_reuse_operand = self.reuseOperand(inst, operand, 0, mcv);3195 const can_reuse_operand = self.reuseOperand(inst, operand, 0, mcv);
3095 const result_reg = blk: {3196 const result_reg = blk: {
3096 if (can_reuse_operand) {3197 if (can_reuse_operand) {
3097 break :blk reg;3198 break :blk reg;
3098 } else {3199 } else {
3099 self.register_manager.freezeRegs(&.{reg});
3100 const result_reg = try self.register_manager.allocReg(inst);3200 const result_reg = try self.register_manager.allocReg(inst);
3101 try self.genSetReg(ptr_ty, result_reg, mcv);3201 try self.genSetReg(ptr_ty, result_reg, mcv);
3102 break :blk result_reg;3202 break :blk result_reg;
3103 }3203 }
3104 };3204 };
3105 defer if (!can_reuse_operand) self.register_manager.unfreezeRegs(&.{reg});3205 const result_reg_lock = self.register_manager.freezeReg(result_reg);
3206 defer if (result_reg_lock) |reg_locked| self.register_manager.unfreezeReg(reg_locked);
31063207
3107 try self.genBinMathOpMir(.add, ptr_ty, .{ .register = result_reg }, .{ .register = offset_reg });3208 try self.genBinMathOpMir(.add, ptr_ty, .{ .register = result_reg }, .{ .register = offset_reg });
3108 break :result MCValue{ .register = result_reg };3209 break :result MCValue{ .register = result_reg };
...@@ -3130,8 +3231,8 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -3130,8 +3231,8 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
3130 break :result MCValue{ .stack_offset = stack_offset };3231 break :result MCValue{ .stack_offset = stack_offset };
3131 },3232 },
3132 .register => |reg| {3233 .register => |reg| {
3133 self.register_manager.freezeRegs(&.{reg});3234 const reg_lock = self.register_manager.freezeRegAssumeUnused(reg);
3134 defer self.register_manager.unfreezeRegs(&.{reg});3235 defer self.register_manager.unfreezeReg(reg_lock);
31353236
3136 const dst_mcv = blk: {3237 const dst_mcv = blk: {
3137 if (self.reuseOperand(inst, operand, 0, mcv)) {3238 if (self.reuseOperand(inst, operand, 0, mcv)) {
...@@ -3143,8 +3244,11 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -3143,8 +3244,11 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
3143 break :blk dst_mcv;3244 break :blk dst_mcv;
3144 }3245 }
3145 };3246 };
3146 dst_mcv.freezeIfRegister(&self.register_manager);3247 const dst_mcv_lock: ?RegisterLock = switch (dst_mcv) {
3147 defer dst_mcv.unfreezeIfRegister(&self.register_manager);3248 .register => |reg| self.register_manager.freezeReg(reg),
3249 else => null,
3250 };
3251 defer if (dst_mcv_lock) |reg_locked| self.register_manager.unfreezeReg(reg_locked);
31483252
3149 // Shift by struct_field_offset.3253 // Shift by struct_field_offset.
3150 const shift = @intCast(u8, struct_field_offset * @sizeOf(usize));3254 const shift = @intCast(u8, struct_field_offset * @sizeOf(usize));
...@@ -3186,8 +3290,8 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -3186,8 +3290,8 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
3186 },3290 },
3187 1 => {3291 1 => {
3188 // Get overflow bit.3292 // Get overflow bit.
3189 mcv.freezeIfRegister(&self.register_manager);3293 const reg_lock = self.register_manager.freezeRegAssumeUnused(reg);
3190 defer mcv.unfreezeIfRegister(&self.register_manager);3294 defer self.register_manager.unfreezeReg(reg_lock);
31913295
3192 const dst_reg = try self.register_manager.allocReg(inst);3296 const dst_reg = try self.register_manager.allocReg(inst);
3193 const flags: u2 = switch (mcv) {3297 const flags: u2 = switch (mcv) {
...@@ -3229,12 +3333,18 @@ fn genBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs:...@@ -3229,12 +3333,18 @@ fn genBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs:
3229 const dst_ty = self.air.typeOf(op_lhs);3333 const dst_ty = self.air.typeOf(op_lhs);
32303334
3231 const lhs = try self.resolveInst(op_lhs);3335 const lhs = try self.resolveInst(op_lhs);
3232 lhs.freezeIfRegister(&self.register_manager);3336 const lhs_lock: ?RegisterLock = switch (lhs) {
3233 defer lhs.unfreezeIfRegister(&self.register_manager);3337 .register => |reg| self.register_manager.freezeRegAssumeUnused(reg),
3338 else => null,
3339 };
3340 defer if (lhs_lock) |reg| self.register_manager.unfreezeReg(reg);
32343341
3235 const rhs = try self.resolveInst(op_rhs);3342 const rhs = try self.resolveInst(op_rhs);
3236 rhs.freezeIfRegister(&self.register_manager);3343 const rhs_lock: ?RegisterLock = switch (rhs) {
3237 defer rhs.unfreezeIfRegister(&self.register_manager);3344 .register => |reg| self.register_manager.freezeRegAssumeUnused(reg),
3345 else => null,
3346 };
3347 defer if (rhs_lock) |reg| self.register_manager.unfreezeReg(reg);
32383348
3239 var flipped: bool = false;3349 var flipped: bool = false;
3240 const dst_mcv = blk: {3350 const dst_mcv = blk: {
...@@ -3247,16 +3357,22 @@ fn genBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs:...@@ -3247,16 +3357,22 @@ fn genBinMathOp(self: *Self, inst: Air.Inst.Index, op_lhs: Air.Inst.Ref, op_rhs:
3247 }3357 }
3248 break :blk try self.copyToRegisterWithInstTracking(inst, dst_ty, lhs);3358 break :blk try self.copyToRegisterWithInstTracking(inst, dst_ty, lhs);
3249 };3359 };
3250 dst_mcv.freezeIfRegister(&self.register_manager);3360 const dst_mcv_lock: ?RegisterLock = switch (dst_mcv) {
3251 defer dst_mcv.unfreezeIfRegister(&self.register_manager);3361 .register => |reg| self.register_manager.freezeReg(reg),
3362 else => null,
3363 };
3364 defer if (dst_mcv_lock) |reg| self.register_manager.unfreezeReg(reg);
32523365
3253 const src_mcv = blk: {3366 const src_mcv = blk: {
3254 const mcv = if (flipped) lhs else rhs;3367 const mcv = if (flipped) lhs else rhs;
3255 if (mcv.isRegister() or mcv.isMemory()) break :blk mcv;3368 if (mcv.isRegister() or mcv.isMemory()) break :blk mcv;
3256 break :blk MCValue{ .register = try self.copyToTmpRegister(dst_ty, mcv) };3369 break :blk MCValue{ .register = try self.copyToTmpRegister(dst_ty, mcv) };
3257 };3370 };
3258 src_mcv.freezeIfRegister(&self.register_manager);3371 const src_mcv_lock: ?RegisterLock = switch (src_mcv) {
3259 defer src_mcv.unfreezeIfRegister(&self.register_manager);3372 .register => |reg| self.register_manager.freezeReg(reg),
3373 else => null,
3374 };
3375 defer if (src_mcv_lock) |reg| self.register_manager.unfreezeReg(reg);
32603376
3261 const tag = self.air.instructions.items(.tag)[inst];3377 const tag = self.air.instructions.items(.tag)[inst];
3262 switch (tag) {3378 switch (tag) {
...@@ -3287,8 +3403,9 @@ fn genBinMathOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MC...@@ -3287,8 +3403,9 @@ fn genBinMathOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MC
3287 .register_overflow_unsigned => unreachable,3403 .register_overflow_unsigned => unreachable,
3288 .register_overflow_signed => unreachable,3404 .register_overflow_signed => unreachable,
3289 .ptr_stack_offset => {3405 .ptr_stack_offset => {
3290 self.register_manager.freezeRegs(&.{dst_reg});3406 const dst_reg_lock = self.register_manager.freezeReg(dst_reg);
3291 defer self.register_manager.unfreezeRegs(&.{dst_reg});3407 defer if (dst_reg_lock) |reg_locked| self.register_manager.unfreezeReg(reg_locked);
3408
3292 const reg = try self.copyToTmpRegister(dst_ty, src_mcv);3409 const reg = try self.copyToTmpRegister(dst_ty, src_mcv);
3293 return self.genBinMathOpMir(mir_tag, dst_ty, dst_mcv, .{ .register = reg });3410 return self.genBinMathOpMir(mir_tag, dst_ty, dst_mcv, .{ .register = reg });
3294 },3411 },
...@@ -3318,8 +3435,9 @@ fn genBinMathOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MC...@@ -3318,8 +3435,9 @@ fn genBinMathOpMir(self: *Self, mir_tag: Mir.Inst.Tag, dst_ty: Type, dst_mcv: MC
3318 .compare_flags_unsigned,3435 .compare_flags_unsigned,
3319 => {3436 => {
3320 assert(abi_size <= 8);3437 assert(abi_size <= 8);
3321 self.register_manager.freezeRegs(&.{dst_reg});3438 const dst_reg_lock = self.register_manager.freezeReg(dst_reg);
3322 defer self.register_manager.unfreezeRegs(&.{dst_reg});3439 defer if (dst_reg_lock) |reg_locked| self.register_manager.unfreezeReg(reg_locked);
3440
3323 const reg = try self.copyToTmpRegister(dst_ty, src_mcv);3441 const reg = try self.copyToTmpRegister(dst_ty, src_mcv);
3324 return self.genBinMathOpMir(mir_tag, dst_ty, dst_mcv, .{ .register = reg });3442 return self.genBinMathOpMir(mir_tag, dst_ty, dst_mcv, .{ .register = reg });
3325 },3443 },
...@@ -3659,7 +3777,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions....@@ -3659,7 +3777,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
3659 try self.register_manager.getReg(reg, null);3777 try self.register_manager.getReg(reg, null);
3660 }3778 }
36613779
3662 if (info.return_value == .stack_offset) {3780 const rdi_lock: ?RegisterLock = if (info.return_value == .stack_offset) blk: {
3663 const ret_ty = fn_ty.fnReturnType();3781 const ret_ty = fn_ty.fnReturnType();
3664 const ret_abi_size = @intCast(u32, ret_ty.abiSize(self.target.*));3782 const ret_abi_size = @intCast(u32, ret_ty.abiSize(self.target.*));
3665 const ret_abi_align = @intCast(u32, ret_ty.abiAlignment(self.target.*));3783 const ret_abi_align = @intCast(u32, ret_ty.abiAlignment(self.target.*));
...@@ -3668,11 +3786,13 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions....@@ -3668,11 +3786,13 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions.
36683786
3669 try self.register_manager.getReg(.rdi, null);3787 try self.register_manager.getReg(.rdi, null);
3670 try self.genSetReg(Type.usize, .rdi, .{ .ptr_stack_offset = stack_offset });3788 try self.genSetReg(Type.usize, .rdi, .{ .ptr_stack_offset = stack_offset });
3671 self.register_manager.freezeRegs(&.{.rdi});3789 const rdi_lock = self.register_manager.freezeRegAssumeUnused(.rdi);
36723790
3673 info.return_value.stack_offset = stack_offset;3791 info.return_value.stack_offset = stack_offset;
3674 }3792
3675 defer if (info.return_value == .stack_offset) self.register_manager.unfreezeRegs(&.{.rdi});3793 break :blk rdi_lock;
3794 } else null;
3795 defer if (rdi_lock) |reg| self.register_manager.unfreezeReg(reg);
36763796
3677 for (args) |arg, arg_i| {3797 for (args) |arg, arg_i| {
3678 const mc_arg = info.args[arg_i];3798 const mc_arg = info.args[arg_i];
...@@ -3891,11 +4011,16 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void {...@@ -3891,11 +4011,16 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void {
3891 const ret_ty = self.fn_type.fnReturnType();4011 const ret_ty = self.fn_type.fnReturnType();
3892 switch (self.ret_mcv) {4012 switch (self.ret_mcv) {
3893 .stack_offset => {4013 .stack_offset => {
3894 self.register_manager.freezeRegs(&.{ .rax, .rcx });4014 var reg_locks: [2]RegisterLock = undefined;
3895 defer self.register_manager.unfreezeRegs(&.{ .rax, .rcx });4015 self.register_manager.freezeRegsAssumeUnused(2, .{ .rax, .rcx }, &reg_locks);
4016 defer for (reg_locks) |reg| {
4017 self.register_manager.unfreezeReg(reg);
4018 };
4019
3896 const reg = try self.copyToTmpRegister(Type.usize, self.ret_mcv);4020 const reg = try self.copyToTmpRegister(Type.usize, self.ret_mcv);
3897 self.register_manager.freezeRegs(&.{reg});4021 const reg_lock = self.register_manager.freezeRegAssumeUnused(reg);
3898 defer self.register_manager.unfreezeRegs(&.{reg});4022 defer self.register_manager.unfreezeReg(reg_lock);
4023
3899 try self.genSetStack(ret_ty, 0, operand, .{4024 try self.genSetStack(ret_ty, 0, operand, .{
3900 .source_stack_base = .rbp,4025 .source_stack_base = .rbp,
3901 .dest_stack_base = reg,4026 .dest_stack_base = reg,
...@@ -3926,11 +4051,16 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {...@@ -3926,11 +4051,16 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void {
3926 const elem_ty = ptr_ty.elemType();4051 const elem_ty = ptr_ty.elemType();
3927 switch (self.ret_mcv) {4052 switch (self.ret_mcv) {
3928 .stack_offset => {4053 .stack_offset => {
3929 self.register_manager.freezeRegs(&.{ .rax, .rcx });4054 var reg_locks: [2]RegisterLock = undefined;
3930 defer self.register_manager.unfreezeRegs(&.{ .rax, .rcx });4055 self.register_manager.freezeRegsAssumeUnused(2, .{ .rax, .rcx }, &reg_locks);
4056 defer for (reg_locks) |reg| {
4057 self.register_manager.unfreezeReg(reg);
4058 };
4059
3931 const reg = try self.copyToTmpRegister(Type.usize, self.ret_mcv);4060 const reg = try self.copyToTmpRegister(Type.usize, self.ret_mcv);
3932 self.register_manager.freezeRegs(&.{reg});4061 const reg_lock = self.register_manager.freezeRegAssumeUnused(reg);
3933 defer self.register_manager.unfreezeRegs(&.{reg});4062 defer self.register_manager.unfreezeReg(reg_lock);
4063
3934 try self.genInlineMemcpy(.{ .stack_offset = 0 }, ptr, .{ .immediate = elem_ty.abiSize(self.target.*) }, .{4064 try self.genInlineMemcpy(.{ .stack_offset = 0 }, ptr, .{ .immediate = elem_ty.abiSize(self.target.*) }, .{
3935 .source_stack_base = .rbp,4065 .source_stack_base = .rbp,
3936 .dest_stack_base = reg,4066 .dest_stack_base = reg,
...@@ -3980,12 +4110,15 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {...@@ -3980,12 +4110,15 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void {
3980 // Source operand can be an immediate, 8 bits or 32 bits.4110 // Source operand can be an immediate, 8 bits or 32 bits.
3981 // TODO look into reusing the operand4111 // TODO look into reusing the operand
3982 const lhs = try self.resolveInst(bin_op.lhs);4112 const lhs = try self.resolveInst(bin_op.lhs);
3983 lhs.freezeIfRegister(&self.register_manager);4113 const lhs_lock: ?RegisterLock = switch (lhs) {
3984 defer lhs.unfreezeIfRegister(&self.register_manager);4114 .register => |reg| self.register_manager.freezeRegAssumeUnused(reg),
4115 else => null,
4116 };
4117 defer if (lhs_lock) |reg| self.register_manager.unfreezeReg(reg);
39854118
3986 const dst_reg = try self.copyToTmpRegister(ty, lhs);4119 const dst_reg = try self.copyToTmpRegister(ty, lhs);
3987 self.register_manager.freezeRegs(&.{dst_reg});4120 const dst_reg_lock = self.register_manager.freezeRegAssumeUnused(dst_reg);
3988 defer self.register_manager.unfreezeRegs(&.{dst_reg});4121 defer self.register_manager.unfreezeReg(dst_reg_lock);
39894122
3990 const dst_mcv = MCValue{ .register = dst_reg };4123 const dst_mcv = MCValue{ .register = dst_reg };
39914124
...@@ -4448,8 +4581,13 @@ fn airIsNullPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -4448,8 +4581,13 @@ fn airIsNullPtr(self: *Self, inst: Air.Inst.Index) !void {
4448 const un_op = self.air.instructions.items(.data)[inst].un_op;4581 const un_op = self.air.instructions.items(.data)[inst].un_op;
4449 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {4582 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
4450 const operand_ptr = try self.resolveInst(un_op);4583 const operand_ptr = try self.resolveInst(un_op);
4451 operand_ptr.freezeIfRegister(&self.register_manager);4584
4452 defer operand_ptr.unfreezeIfRegister(&self.register_manager);4585 const operand_ptr_lock: ?RegisterLock = switch (operand_ptr) {
4586 .register => |reg| self.register_manager.freezeRegAssumeUnused(reg),
4587 else => null,
4588 };
4589 defer if (operand_ptr_lock) |reg| self.register_manager.unfreezeReg(reg);
4590
4453 const operand: MCValue = blk: {4591 const operand: MCValue = blk: {
4454 if (self.reuseOperand(inst, un_op, 0, operand_ptr)) {4592 if (self.reuseOperand(inst, un_op, 0, operand_ptr)) {
4455 // The MCValue that holds the pointer can be re-used as the value.4593 // The MCValue that holds the pointer can be re-used as the value.
...@@ -4479,8 +4617,13 @@ fn airIsNonNullPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -4479,8 +4617,13 @@ fn airIsNonNullPtr(self: *Self, inst: Air.Inst.Index) !void {
4479 const un_op = self.air.instructions.items(.data)[inst].un_op;4617 const un_op = self.air.instructions.items(.data)[inst].un_op;
4480 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {4618 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
4481 const operand_ptr = try self.resolveInst(un_op);4619 const operand_ptr = try self.resolveInst(un_op);
4482 operand_ptr.freezeIfRegister(&self.register_manager);4620
4483 defer operand_ptr.unfreezeIfRegister(&self.register_manager);4621 const operand_ptr_lock: ?RegisterLock = switch (operand_ptr) {
4622 .register => |reg| self.register_manager.freezeRegAssumeUnused(reg),
4623 else => null,
4624 };
4625 defer if (operand_ptr_lock) |reg| self.register_manager.unfreezeReg(reg);
4626
4484 const operand: MCValue = blk: {4627 const operand: MCValue = blk: {
4485 if (self.reuseOperand(inst, un_op, 0, operand_ptr)) {4628 if (self.reuseOperand(inst, un_op, 0, operand_ptr)) {
4486 // The MCValue that holds the pointer can be re-used as the value.4629 // The MCValue that holds the pointer can be re-used as the value.
...@@ -4510,8 +4653,13 @@ fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -4510,8 +4653,13 @@ fn airIsErrPtr(self: *Self, inst: Air.Inst.Index) !void {
4510 const un_op = self.air.instructions.items(.data)[inst].un_op;4653 const un_op = self.air.instructions.items(.data)[inst].un_op;
4511 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {4654 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
4512 const operand_ptr = try self.resolveInst(un_op);4655 const operand_ptr = try self.resolveInst(un_op);
4513 operand_ptr.freezeIfRegister(&self.register_manager);4656
4514 defer operand_ptr.unfreezeIfRegister(&self.register_manager);4657 const operand_ptr_lock: ?RegisterLock = switch (operand_ptr) {
4658 .register => |reg| self.register_manager.freezeRegAssumeUnused(reg),
4659 else => null,
4660 };
4661 defer if (operand_ptr_lock) |reg| self.register_manager.unfreezeReg(reg);
4662
4515 const operand: MCValue = blk: {4663 const operand: MCValue = blk: {
4516 if (self.reuseOperand(inst, un_op, 0, operand_ptr)) {4664 if (self.reuseOperand(inst, un_op, 0, operand_ptr)) {
4517 // The MCValue that holds the pointer can be re-used as the value.4665 // The MCValue that holds the pointer can be re-used as the value.
...@@ -4541,8 +4689,13 @@ fn airIsNonErrPtr(self: *Self, inst: Air.Inst.Index) !void {...@@ -4541,8 +4689,13 @@ fn airIsNonErrPtr(self: *Self, inst: Air.Inst.Index) !void {
4541 const un_op = self.air.instructions.items(.data)[inst].un_op;4689 const un_op = self.air.instructions.items(.data)[inst].un_op;
4542 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {4690 const result: MCValue = if (self.liveness.isUnused(inst)) .dead else result: {
4543 const operand_ptr = try self.resolveInst(un_op);4691 const operand_ptr = try self.resolveInst(un_op);
4544 operand_ptr.freezeIfRegister(&self.register_manager);4692
4545 defer operand_ptr.unfreezeIfRegister(&self.register_manager);4693 const operand_ptr_lock: ?RegisterLock = switch (operand_ptr) {
4694 .register => |reg| self.register_manager.freezeRegAssumeUnused(reg),
4695 else => null,
4696 };
4697 defer if (operand_ptr_lock) |reg| self.register_manager.unfreezeReg(reg);
4698
4546 const operand: MCValue = blk: {4699 const operand: MCValue = blk: {
4547 if (self.reuseOperand(inst, un_op, 0, operand_ptr)) {4700 if (self.reuseOperand(inst, un_op, 0, operand_ptr)) {
4548 // The MCValue that holds the pointer can be re-used as the value.4701 // The MCValue that holds the pointer can be re-used as the value.
...@@ -4610,8 +4763,8 @@ fn genCondSwitchMir(self: *Self, ty: Type, condition: MCValue, case: MCValue) !u...@@ -4610,8 +4763,8 @@ fn genCondSwitchMir(self: *Self, ty: Type, condition: MCValue, case: MCValue) !u
4610 .register => |cond_reg| {4763 .register => |cond_reg| {
4611 try self.spillCompareFlagsIfOccupied();4764 try self.spillCompareFlagsIfOccupied();
46124765
4613 self.register_manager.freezeRegs(&.{cond_reg});4766 const cond_reg_lock = self.register_manager.freezeReg(cond_reg);
4614 defer self.register_manager.unfreezeRegs(&.{cond_reg});4767 defer if (cond_reg_lock) |reg| self.register_manager.unfreezeReg(reg);
46154768
4616 switch (case) {4769 switch (case) {
4617 .none => unreachable,4770 .none => unreachable,
...@@ -4670,8 +4823,8 @@ fn genCondSwitchMir(self: *Self, ty: Type, condition: MCValue, case: MCValue) !u...@@ -4670,8 +4823,8 @@ fn genCondSwitchMir(self: *Self, ty: Type, condition: MCValue, case: MCValue) !u
46704823
4671 if (abi_size <= 8) {4824 if (abi_size <= 8) {
4672 const reg = try self.copyToTmpRegister(ty, condition);4825 const reg = try self.copyToTmpRegister(ty, condition);
4673 self.register_manager.freezeRegs(&.{reg});4826 const reg_lock = self.register_manager.freezeRegAssumeUnused(reg);
4674 defer self.register_manager.unfreezeRegs(&.{reg});4827 defer self.register_manager.unfreezeReg(reg_lock);
4675 return self.genCondSwitchMir(ty, .{ .register = reg }, case);4828 return self.genCondSwitchMir(ty, .{ .register = reg }, case);
4676 }4829 }
46774830
...@@ -5158,8 +5311,8 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl...@@ -5158,8 +5311,8 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl
5158 .register_overflow_unsigned,5311 .register_overflow_unsigned,
5159 .register_overflow_signed,5312 .register_overflow_signed,
5160 => |reg| {5313 => |reg| {
5161 self.register_manager.freezeRegs(&.{reg});5314 const reg_lock = self.register_manager.freezeReg(reg);
5162 defer self.register_manager.unfreezeRegs(&.{reg});5315 defer if (reg_lock) |reg_locked| self.register_manager.unfreezeReg(reg_locked);
51635316
5164 const wrapped_ty = ty.structFieldType(0);5317 const wrapped_ty = ty.structFieldType(0);
5165 try self.genSetStack(wrapped_ty, stack_offset, .{ .register = reg }, .{});5318 try self.genSetStack(wrapped_ty, stack_offset, .{ .register = reg }, .{});
...@@ -5260,8 +5413,8 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl...@@ -5260,8 +5413,8 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl
52605413
5261 const base_reg = opts.dest_stack_base orelse .rbp;5414 const base_reg = opts.dest_stack_base orelse .rbp;
5262 if (!math.isPowerOfTwo(abi_size)) {5415 if (!math.isPowerOfTwo(abi_size)) {
5263 self.register_manager.freezeRegs(&.{reg});5416 const reg_lock = self.register_manager.freezeReg(reg);
5264 defer self.register_manager.unfreezeRegs(&.{reg});5417 defer if (reg_lock) |reg_locked| self.register_manager.unfreezeReg(reg_locked);
52655418
5266 const tmp_reg = try self.copyToTmpRegister(ty, mcv);5419 const tmp_reg = try self.copyToTmpRegister(ty, mcv);
52675420
...@@ -5350,13 +5503,26 @@ fn genInlineMemcpy(...@@ -5350,13 +5503,26 @@ fn genInlineMemcpy(
5350 len: MCValue,5503 len: MCValue,
5351 opts: InlineMemcpyOpts,5504 opts: InlineMemcpyOpts,
5352) InnerError!void {5505) InnerError!void {
5353 self.register_manager.freezeRegs(&.{ .rax, .rcx });5506 try self.register_manager.getReg(.rax, null);
5507 try self.register_manager.getReg(.rcx, null);
53545508
5355 if (opts.source_stack_base) |reg| self.register_manager.freezeRegs(&.{reg});5509 var reg_locks: [2]RegisterLock = undefined;
5356 defer if (opts.source_stack_base) |reg| self.register_manager.unfreezeRegs(&.{reg});5510 self.register_manager.freezeRegsAssumeUnused(2, .{ .rax, .rcx }, &reg_locks);
5511 defer for (reg_locks) |reg| {
5512 self.register_manager.unfreezeReg(reg);
5513 };
53575514
5358 if (opts.dest_stack_base) |reg| self.register_manager.freezeRegs(&.{reg});5515 const ssbase_lock: ?RegisterLock = if (opts.source_stack_base) |reg|
5359 defer if (opts.dest_stack_base) |reg| self.register_manager.unfreezeRegs(&.{reg});5516 self.register_manager.freezeReg(reg)
5517 else
5518 null;
5519 defer if (ssbase_lock) |reg| self.register_manager.unfreezeReg(reg);
5520
5521 const dsbase_lock: ?RegisterLock = if (opts.dest_stack_base) |reg|
5522 self.register_manager.freezeReg(reg)
5523 else
5524 null;
5525 defer if (dsbase_lock) |reg| self.register_manager.unfreezeReg(reg);
53605526
5361 const dst_addr_reg = try self.register_manager.allocReg(null);5527 const dst_addr_reg = try self.register_manager.allocReg(null);
5362 switch (dst_ptr) {5528 switch (dst_ptr) {
...@@ -5390,8 +5556,8 @@ fn genInlineMemcpy(...@@ -5390,8 +5556,8 @@ fn genInlineMemcpy(
5390 return self.fail("TODO implement memcpy for setting stack when dest is {}", .{dst_ptr});5556 return self.fail("TODO implement memcpy for setting stack when dest is {}", .{dst_ptr});
5391 },5557 },
5392 }5558 }
5393 self.register_manager.freezeRegs(&.{dst_addr_reg});5559 const dst_addr_reg_lock = self.register_manager.freezeRegAssumeUnused(dst_addr_reg);
5394 defer self.register_manager.unfreezeRegs(&.{dst_addr_reg});5560 defer self.register_manager.unfreezeReg(dst_addr_reg_lock);
53955561
5396 const src_addr_reg = try self.register_manager.allocReg(null);5562 const src_addr_reg = try self.register_manager.allocReg(null);
5397 switch (src_ptr) {5563 switch (src_ptr) {
...@@ -5425,18 +5591,13 @@ fn genInlineMemcpy(...@@ -5425,18 +5591,13 @@ fn genInlineMemcpy(
5425 return self.fail("TODO implement memcpy for setting stack when src is {}", .{src_ptr});5591 return self.fail("TODO implement memcpy for setting stack when src is {}", .{src_ptr});
5426 },5592 },
5427 }5593 }
5428 self.register_manager.freezeRegs(&.{src_addr_reg});5594 const src_addr_reg_lock = self.register_manager.freezeRegAssumeUnused(src_addr_reg);
5429 defer self.register_manager.unfreezeRegs(&.{src_addr_reg});5595 defer self.register_manager.unfreezeReg(src_addr_reg_lock);
54305596
5431 const regs = try self.register_manager.allocRegs(2, .{ null, null });5597 const regs = try self.register_manager.allocRegs(2, .{ null, null });
5432 const count_reg = regs[0].to64();5598 const count_reg = regs[0].to64();
5433 const tmp_reg = regs[1].to8();5599 const tmp_reg = regs[1].to8();
54345600
5435 self.register_manager.unfreezeRegs(&.{ .rax, .rcx });
5436
5437 try self.register_manager.getReg(.rax, null);
5438 try self.register_manager.getReg(.rcx, null);
5439
5440 try self.genSetReg(Type.usize, count_reg, len);5601 try self.genSetReg(Type.usize, count_reg, len);
54415602
5442 // mov rcx, 05603 // mov rcx, 0
...@@ -5540,7 +5701,9 @@ fn genInlineMemset(...@@ -5540,7 +5701,9 @@ fn genInlineMemset(
5540 len: MCValue,5701 len: MCValue,
5541 opts: InlineMemcpyOpts,5702 opts: InlineMemcpyOpts,
5542) InnerError!void {5703) InnerError!void {
5543 self.register_manager.freezeRegs(&.{.rax});5704 try self.register_manager.getReg(.rax, null);
5705 const rax_lock = self.register_manager.freezeRegAssumeUnused(.rax);
5706 defer self.register_manager.unfreezeReg(rax_lock);
55445707
5545 const addr_reg = try self.register_manager.allocReg(null);5708 const addr_reg = try self.register_manager.allocReg(null);
5546 switch (dst_ptr) {5709 switch (dst_ptr) {
...@@ -5574,11 +5737,8 @@ fn genInlineMemset(...@@ -5574,11 +5737,8 @@ fn genInlineMemset(
5574 return self.fail("TODO implement memcpy for setting stack when dest is {}", .{dst_ptr});5737 return self.fail("TODO implement memcpy for setting stack when dest is {}", .{dst_ptr});
5575 },5738 },
5576 }5739 }
5577 self.register_manager.freezeRegs(&.{addr_reg});5740 const addr_reg_lock = self.register_manager.freezeRegAssumeUnused(addr_reg);
5578 defer self.register_manager.unfreezeRegs(&.{addr_reg});5741 defer self.register_manager.unfreezeReg(addr_reg_lock);
5579
5580 self.register_manager.unfreezeRegs(&.{.rax});
5581 try self.register_manager.getReg(.rax, null);
55825742
5583 try self.genSetReg(Type.usize, .rax, len);5743 try self.genSetReg(Type.usize, .rax, len);
5584 try self.genBinMathOpMir(.sub, Type.usize, .{ .register = .rax }, .{ .immediate = 1 });5744 try self.genBinMathOpMir(.sub, Type.usize, .{ .register = .rax }, .{ .immediate = 1 });
...@@ -6017,16 +6177,25 @@ fn airMemset(self: *Self, inst: Air.Inst.Index) !void {...@@ -6017,16 +6177,25 @@ fn airMemset(self: *Self, inst: Air.Inst.Index) !void {
6017 const extra = self.air.extraData(Air.Bin, pl_op.payload).data;6177 const extra = self.air.extraData(Air.Bin, pl_op.payload).data;
60186178
6019 const dst_ptr = try self.resolveInst(pl_op.operand);6179 const dst_ptr = try self.resolveInst(pl_op.operand);
6020 dst_ptr.freezeIfRegister(&self.register_manager);6180 const dst_ptr_lock: ?RegisterLock = switch (dst_ptr) {
6021 defer dst_ptr.unfreezeIfRegister(&self.register_manager);6181 .register => |reg| self.register_manager.freezeRegAssumeUnused(reg),
6182 else => null,
6183 };
6184 defer if (dst_ptr_lock) |reg| self.register_manager.unfreezeReg(reg);
60226185
6023 const src_val = try self.resolveInst(extra.lhs);6186 const src_val = try self.resolveInst(extra.lhs);
6024 src_val.freezeIfRegister(&self.register_manager);6187 const src_val_lock: ?RegisterLock = switch (src_val) {
6025 defer src_val.unfreezeIfRegister(&self.register_manager);6188 .register => |reg| self.register_manager.freezeRegAssumeUnused(reg),
6189 else => null,
6190 };
6191 defer if (src_val_lock) |reg| self.register_manager.unfreezeReg(reg);
60266192
6027 const len = try self.resolveInst(extra.rhs);6193 const len = try self.resolveInst(extra.rhs);
6028 len.freezeIfRegister(&self.register_manager);6194 const len_lock: ?RegisterLock = switch (len) {
6029 defer len.unfreezeIfRegister(&self.register_manager);6195 .register => |reg| self.register_manager.freezeRegAssumeUnused(reg),
6196 else => null,
6197 };
6198 defer if (len_lock) |reg| self.register_manager.unfreezeReg(reg);
60306199
6031 try self.genInlineMemset(dst_ptr, src_val, len, .{});6200 try self.genInlineMemset(dst_ptr, src_val, len, .{});
60326201
...@@ -6038,17 +6207,26 @@ fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void {...@@ -6038,17 +6207,26 @@ fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void {
6038 const extra = self.air.extraData(Air.Bin, pl_op.payload).data;6207 const extra = self.air.extraData(Air.Bin, pl_op.payload).data;
60396208
6040 const dst_ptr = try self.resolveInst(pl_op.operand);6209 const dst_ptr = try self.resolveInst(pl_op.operand);
6041 dst_ptr.freezeIfRegister(&self.register_manager);6210 const dst_ptr_lock: ?RegisterLock = switch (dst_ptr) {
6042 defer dst_ptr.unfreezeIfRegister(&self.register_manager);6211 .register => |reg| self.register_manager.freezeRegAssumeUnused(reg),
6212 else => null,
6213 };
6214 defer if (dst_ptr_lock) |reg| self.register_manager.unfreezeReg(reg);
60436215
6044 const src_ty = self.air.typeOf(extra.lhs);6216 const src_ty = self.air.typeOf(extra.lhs);
6045 const src_ptr = try self.resolveInst(extra.lhs);6217 const src_ptr = try self.resolveInst(extra.lhs);
6046 src_ptr.freezeIfRegister(&self.register_manager);6218 const src_ptr_lock: ?RegisterLock = switch (src_ptr) {
6047 defer src_ptr.unfreezeIfRegister(&self.register_manager);6219 .register => |reg| self.register_manager.freezeRegAssumeUnused(reg),
6220 else => null,
6221 };
6222 defer if (src_ptr_lock) |reg| self.register_manager.unfreezeReg(reg);
60486223
6049 const len = try self.resolveInst(extra.rhs);6224 const len = try self.resolveInst(extra.rhs);
6050 len.freezeIfRegister(&self.register_manager);6225 const len_lock: ?RegisterLock = switch (len) {
6051 defer len.unfreezeIfRegister(&self.register_manager);6226 .register => |reg| self.register_manager.freezeRegAssumeUnused(reg),
6227 else => null,
6228 };
6229 defer if (len_lock) |reg| self.register_manager.unfreezeReg(reg);
60526230
6053 // TODO Is this the only condition for pointer dereference for memcpy?6231 // TODO Is this the only condition for pointer dereference for memcpy?
6054 const src: MCValue = blk: {6232 const src: MCValue = blk: {
...@@ -6070,8 +6248,11 @@ fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void {...@@ -6070,8 +6248,11 @@ fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void {
6070 else => break :blk src_ptr,6248 else => break :blk src_ptr,
6071 }6249 }
6072 };6250 };
6073 src.freezeIfRegister(&self.register_manager);6251 const src_lock: ?RegisterLock = switch (src) {
6074 defer src.unfreezeIfRegister(&self.register_manager);6252 .register => |reg| self.register_manager.freezeReg(reg),
6253 else => null,
6254 };
6255 defer if (src_lock) |reg| self.register_manager.unfreezeReg(reg);
60756256
6076 try self.genInlineMemcpy(dst_ptr, src, len, .{});6257 try self.genInlineMemcpy(dst_ptr, src, len, .{});
60776258
src/register_manager.zig+49-22
...@@ -116,23 +116,52 @@ pub fn RegisterManager(...@@ -116,23 +116,52 @@ pub fn RegisterManager(
116 return self.frozen_registers & mask != 0;116 return self.frozen_registers & mask != 0;
117 }117 }
118118
119 /// Prevents the registers from being allocated until they are119 pub const RegisterLock = struct {
120 /// unfrozen again120 register: Register,
121 pub fn freezeRegs(self: *Self, regs: []const Register) void {121 };
122 for (regs) |reg| {122
123 const mask = getRegisterMask(reg) orelse continue;123 /// Prevents the register from being allocated until they are
124 self.frozen_registers |= mask;124 /// unfrozen again.
125 }125 /// Returns `RegisterLock` if the register was not already
126 /// frozen, or `null` otherwise.
127 /// Only the owner of the `RegisterLock` can unfreeze the
128 /// register later.
129 pub fn freezeReg(self: *Self, reg: Register) ?RegisterLock {
130 if (self.isRegFrozen(reg)) return null;
131 const mask = getRegisterMask(reg) orelse return null;
132 self.frozen_registers |= mask;
133 return RegisterLock{ .register = reg };
134 }
135
136 /// Like `freezeReg` but asserts the register was unused always
137 /// returning a valid lock.
138 pub fn freezeRegAssumeUnused(self: *Self, reg: Register) RegisterLock {
139 assert(!self.isRegFrozen(reg));
140 const mask = getRegisterMask(reg) orelse unreachable;
141 self.frozen_registers |= mask;
142 return RegisterLock{ .register = reg };
126 }143 }
127144
128 /// Enables the allocation of the registers145 /// Like `freezeRegAssumeUnused` but locks multiple registers.
129 pub fn unfreezeRegs(self: *Self, regs: []const Register) void {146 pub fn freezeRegsAssumeUnused(
130 for (regs) |reg| {147 self: *Self,
131 const mask = getRegisterMask(reg) orelse continue;148 comptime count: comptime_int,
132 self.frozen_registers &= ~mask;149 regs: [count]Register,
150 buf: *[count]RegisterLock,
151 ) void {
152 for (&regs) |reg, i| {
153 buf[i] = self.freezeRegAssumeUnused(reg);
133 }154 }
134 }155 }
135156
157 /// Unfreezes the register allowing its re-allocation and re-use.
158 /// Requires `RegisterLock` to unfreeze a register.
159 /// Call `freezeReg` to obtain the lock first.
160 pub fn unfreezeReg(self: *Self, lock: RegisterLock) void {
161 const mask = getRegisterMask(lock.register) orelse return;
162 self.frozen_registers &= ~mask;
163 }
164
136 /// Returns true when at least one register is frozen165 /// Returns true when at least one register is frozen
137 pub fn frozenRegsExist(self: Self) bool {166 pub fn frozenRegsExist(self: Self) bool {
138 return self.frozen_registers != 0;167 return self.frozen_registers != 0;
...@@ -419,8 +448,8 @@ test "allocReg: spilling" {...@@ -419,8 +448,8 @@ test "allocReg: spilling" {
419 // Frozen registers448 // Frozen registers
420 function.register_manager.freeReg(.r3);449 function.register_manager.freeReg(.r3);
421 {450 {
422 function.register_manager.freezeRegs(&.{.r2});451 const lock = function.register_manager.freezeReg(.r2);
423 defer function.register_manager.unfreezeRegs(&.{.r2});452 defer if (lock) |reg| function.register_manager.unfreezeReg(reg);
424453
425 try expectEqual(@as(?MockRegister1, .r3), try function.register_manager.allocReg(mock_instruction));454 try expectEqual(@as(?MockRegister1, .r3), try function.register_manager.allocReg(mock_instruction));
426 }455 }
...@@ -447,8 +476,8 @@ test "tryAllocRegs" {...@@ -447,8 +476,8 @@ test "tryAllocRegs" {
447 function.register_manager.freeReg(.r2);476 function.register_manager.freeReg(.r2);
448 function.register_manager.freeReg(.r3);477 function.register_manager.freeReg(.r3);
449 {478 {
450 function.register_manager.freezeRegs(&.{.r1});479 const lock = function.register_manager.freezeReg(.r1);
451 defer function.register_manager.unfreezeRegs(&.{.r1});480 defer if (lock) |reg| function.register_manager.unfreezeReg(reg);
452481
453 try expectEqual([_]MockRegister2{ .r0, .r2, .r3 }, function.register_manager.tryAllocRegs(3, .{ null, null, null }).?);482 try expectEqual([_]MockRegister2{ .r0, .r2, .r3 }, function.register_manager.tryAllocRegs(3, .{ null, null, null }).?);
454 }483 }
...@@ -486,8 +515,8 @@ test "allocRegs: normal usage" {...@@ -486,8 +515,8 @@ test "allocRegs: normal usage" {
486 // contain any valuable data anymore and can be reused. For an515 // contain any valuable data anymore and can be reused. For an
487 // example of that, see `selectively reducing register516 // example of that, see `selectively reducing register
488 // pressure`.517 // pressure`.
489 function.register_manager.freezeRegs(&.{result_reg});518 const lock = function.register_manager.freezeReg(result_reg);
490 defer function.register_manager.unfreezeRegs(&.{result_reg});519 defer if (lock) |reg| function.register_manager.unfreezeReg(reg);
491520
492 const regs = try function.register_manager.allocRegs(2, .{ null, null });521 const regs = try function.register_manager.allocRegs(2, .{ null, null });
493 try function.genAdd(result_reg, regs[0], regs[1]);522 try function.genAdd(result_reg, regs[0], regs[1]);
...@@ -507,16 +536,14 @@ test "allocRegs: selectively reducing register pressure" {...@@ -507,16 +536,14 @@ test "allocRegs: selectively reducing register pressure" {
507 {536 {
508 const result_reg: MockRegister2 = .r1;537 const result_reg: MockRegister2 = .r1;
509538
510 function.register_manager.freezeRegs(&.{result_reg});539 const lock = function.register_manager.freezeReg(result_reg);
511 defer function.register_manager.unfreezeRegs(&.{result_reg});
512540
513 // Here, we don't defer unfreeze because we manually unfreeze541 // Here, we don't defer unfreeze because we manually unfreeze
514 // after genAdd542 // after genAdd
515 const regs = try function.register_manager.allocRegs(2, .{ null, null });543 const regs = try function.register_manager.allocRegs(2, .{ null, null });
516 function.register_manager.freezeRegs(&.{result_reg});
517544
518 try function.genAdd(result_reg, regs[0], regs[1]);545 try function.genAdd(result_reg, regs[0], regs[1]);
519 function.register_manager.unfreezeRegs(&regs);546 function.register_manager.unfreezeReg(lock.?);
520547
521 const extra_summand_reg = try function.register_manager.allocReg(null);548 const extra_summand_reg = try function.register_manager.allocReg(null);
522 try function.genAdd(result_reg, result_reg, extra_summand_reg);549 try function.genAdd(result_reg, result_reg, extra_summand_reg);
test/behavior/align.zig+1
...@@ -7,6 +7,7 @@ var foo: u8 align(4) = 100;...@@ -7,6 +7,7 @@ var foo: u8 align(4) = 100;
77
8test "global variable alignment" {8test "global variable alignment" {
9 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO9 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
10 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1011
11 comptime try expect(@typeInfo(@TypeOf(&foo)).Pointer.alignment == 4);12 comptime try expect(@typeInfo(@TypeOf(&foo)).Pointer.alignment == 4);
12 comptime try expect(@TypeOf(&foo) == *align(4) u8);13 comptime try expect(@TypeOf(&foo) == *align(4) u8);