authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-05-18 11:15:04+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-05-19 19:39:32+02:00
log549174f743d3b56544e2d3d6993f4d43bba1e7fd
tree90be8877e03f93fd30a95120fd8db774e53b4898
parent9e5c8cb008f75c2e570a0e48d5d014e936c103ca

regalloc: allow for optional selector mask when allocating


6 files changed, 113 insertions(+), 106 deletions(-)

src/arch/aarch64/CodeGen.zig+28-28
...@@ -888,7 +888,7 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {...@@ -888,7 +888,7 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {
888 if (reg_ok) {888 if (reg_ok) {
889 // Make sure the type can fit in a register before we try to allocate one.889 // Make sure the type can fit in a register before we try to allocate one.
890 if (abi_size <= 8) {890 if (abi_size <= 8) {
891 if (self.register_manager.tryAllocReg(inst)) |reg| {891 if (self.register_manager.tryAllocReg(inst, .{})) |reg| {
892 return MCValue{ .register = registerAlias(reg, abi_size) };892 return MCValue{ .register = registerAlias(reg, abi_size) };
893 }893 }
894 }894 }
...@@ -951,7 +951,7 @@ fn spillCompareFlagsIfOccupied(self: *Self) !void {...@@ -951,7 +951,7 @@ fn spillCompareFlagsIfOccupied(self: *Self) !void {
951/// allocated. A second call to `copyToTmpRegister` may return the same register.951/// allocated. A second call to `copyToTmpRegister` may return the same register.
952/// This can have a side effect of spilling instructions to the stack to free up a register.952/// This can have a side effect of spilling instructions to the stack to free up a register.
953fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {953fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {
954 const raw_reg = try self.register_manager.allocReg(null);954 const raw_reg = try self.register_manager.allocReg(null, .{});
955 const reg = registerAlias(raw_reg, ty.abiSize(self.target.*));955 const reg = registerAlias(raw_reg, ty.abiSize(self.target.*));
956 try self.genSetReg(ty, reg, mcv);956 try self.genSetReg(ty, reg, mcv);
957 return reg;957 return reg;
...@@ -961,7 +961,7 @@ fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {...@@ -961,7 +961,7 @@ fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {
961/// `reg_owner` is the instruction that gets associated with the register in the register table.961/// `reg_owner` is the instruction that gets associated with the register in the register table.
962/// This can have a side effect of spilling instructions to the stack to free up a register.962/// This can have a side effect of spilling instructions to the stack to free up a register.
963fn copyToNewRegister(self: *Self, reg_owner: Air.Inst.Index, mcv: MCValue) !MCValue {963fn copyToNewRegister(self: *Self, reg_owner: Air.Inst.Index, mcv: MCValue) !MCValue {
964 const raw_reg = try self.register_manager.allocReg(reg_owner);964 const raw_reg = try self.register_manager.allocReg(reg_owner, .{});
965 const ty = self.air.typeOfIndex(reg_owner);965 const ty = self.air.typeOfIndex(reg_owner);
966 const reg = registerAlias(raw_reg, ty.abiSize(self.target.*));966 const reg = registerAlias(raw_reg, ty.abiSize(self.target.*));
967 try self.genSetReg(self.air.typeOfIndex(reg_owner), reg, mcv);967 try self.genSetReg(self.air.typeOfIndex(reg_owner), reg, mcv);
...@@ -1074,11 +1074,11 @@ fn trunc(...@@ -1074,11 +1074,11 @@ fn trunc(
1074 if (operand == .register and self.reuseOperand(inst, ty_op.operand, 0, operand)) {1074 if (operand == .register and self.reuseOperand(inst, ty_op.operand, 0, operand)) {
1075 break :blk registerAlias(operand_reg, dest_ty.abiSize(self.target.*));1075 break :blk registerAlias(operand_reg, dest_ty.abiSize(self.target.*));
1076 } else {1076 } else {
1077 const raw_reg = try self.register_manager.allocReg(inst);1077 const raw_reg = try self.register_manager.allocReg(inst, .{});
1078 break :blk registerAlias(raw_reg, dest_ty.abiSize(self.target.*));1078 break :blk registerAlias(raw_reg, dest_ty.abiSize(self.target.*));
1079 }1079 }
1080 } else blk: {1080 } else blk: {
1081 const raw_reg = try self.register_manager.allocReg(null);1081 const raw_reg = try self.register_manager.allocReg(null, .{});
1082 break :blk registerAlias(raw_reg, dest_ty.abiSize(self.target.*));1082 break :blk registerAlias(raw_reg, dest_ty.abiSize(self.target.*));
1083 };1083 };
10841084
...@@ -1160,7 +1160,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {...@@ -1160,7 +1160,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
1160 break :blk op_reg;1160 break :blk op_reg;
1161 }1161 }
11621162
1163 const raw_reg = try self.register_manager.allocReg(null);1163 const raw_reg = try self.register_manager.allocReg(null, .{});
1164 break :blk raw_reg.to32();1164 break :blk raw_reg.to32();
1165 };1165 };
11661166
...@@ -1193,7 +1193,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {...@@ -1193,7 +1193,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
1193 break :blk op_reg;1193 break :blk op_reg;
1194 }1194 }
11951195
1196 const raw_reg = try self.register_manager.allocReg(null);1196 const raw_reg = try self.register_manager.allocReg(null, .{});
1197 break :blk registerAlias(raw_reg, operand_ty.abiSize(self.target.*));1197 break :blk registerAlias(raw_reg, operand_ty.abiSize(self.target.*));
1198 };1198 };
11991199
...@@ -1293,7 +1293,7 @@ fn binOpRegister(...@@ -1293,7 +1293,7 @@ fn binOpRegister(
1293 break :inst Air.refToIndex(md.lhs).?;1293 break :inst Air.refToIndex(md.lhs).?;
1294 } else null;1294 } else null;
12951295
1296 const raw_reg = try self.register_manager.allocReg(track_inst);1296 const raw_reg = try self.register_manager.allocReg(track_inst, .{});
1297 const reg = registerAlias(raw_reg, lhs_ty.abiSize(self.target.*));1297 const reg = registerAlias(raw_reg, lhs_ty.abiSize(self.target.*));
12981298
1299 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });1299 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
...@@ -1308,7 +1308,7 @@ fn binOpRegister(...@@ -1308,7 +1308,7 @@ fn binOpRegister(
1308 break :inst Air.refToIndex(md.rhs).?;1308 break :inst Air.refToIndex(md.rhs).?;
1309 } else null;1309 } else null;
13101310
1311 const raw_reg = try self.register_manager.allocReg(track_inst);1311 const raw_reg = try self.register_manager.allocReg(track_inst, .{});
1312 const reg = registerAlias(raw_reg, rhs_ty.abiAlignment(self.target.*));1312 const reg = registerAlias(raw_reg, rhs_ty.abiAlignment(self.target.*));
13131313
1314 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });1314 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
...@@ -1326,11 +1326,11 @@ fn binOpRegister(...@@ -1326,11 +1326,11 @@ fn binOpRegister(
1326 } else if (rhs_is_register and self.reuseOperand(md.inst, md.rhs, 1, rhs)) {1326 } else if (rhs_is_register and self.reuseOperand(md.inst, md.rhs, 1, rhs)) {
1327 break :blk rhs_reg;1327 break :blk rhs_reg;
1328 } else {1328 } else {
1329 const raw_reg = try self.register_manager.allocReg(md.inst);1329 const raw_reg = try self.register_manager.allocReg(md.inst, .{});
1330 break :blk registerAlias(raw_reg, lhs_ty.abiSize(self.target.*));1330 break :blk registerAlias(raw_reg, lhs_ty.abiSize(self.target.*));
1331 }1331 }
1332 } else blk: {1332 } else blk: {
1333 const raw_reg = try self.register_manager.allocReg(null);1333 const raw_reg = try self.register_manager.allocReg(null, .{});
1334 break :blk registerAlias(raw_reg, lhs_ty.abiSize(self.target.*));1334 break :blk registerAlias(raw_reg, lhs_ty.abiSize(self.target.*));
1335 },1335 },
1336 };1336 };
...@@ -1431,7 +1431,7 @@ fn binOpImmediate(...@@ -1431,7 +1431,7 @@ fn binOpImmediate(
1431 ).?;1431 ).?;
1432 } else null;1432 } else null;
14331433
1434 const raw_reg = try self.register_manager.allocReg(track_inst);1434 const raw_reg = try self.register_manager.allocReg(track_inst, .{});
1435 const reg = registerAlias(raw_reg, lhs_ty.abiSize(self.target.*));1435 const reg = registerAlias(raw_reg, lhs_ty.abiSize(self.target.*));
14361436
1437 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });1437 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
...@@ -1452,11 +1452,11 @@ fn binOpImmediate(...@@ -1452,11 +1452,11 @@ fn binOpImmediate(
1452 )) {1452 )) {
1453 break :blk lhs_reg;1453 break :blk lhs_reg;
1454 } else {1454 } else {
1455 const raw_reg = try self.register_manager.allocReg(md.inst);1455 const raw_reg = try self.register_manager.allocReg(md.inst, .{});
1456 break :blk registerAlias(raw_reg, lhs_ty.abiSize(self.target.*));1456 break :blk registerAlias(raw_reg, lhs_ty.abiSize(self.target.*));
1457 }1457 }
1458 } else blk: {1458 } else blk: {
1459 const raw_reg = try self.register_manager.allocReg(null);1459 const raw_reg = try self.register_manager.allocReg(null, .{});
1460 break :blk registerAlias(raw_reg, lhs_ty.abiSize(self.target.*));1460 break :blk registerAlias(raw_reg, lhs_ty.abiSize(self.target.*));
1461 },1461 },
1462 };1462 };
...@@ -1872,7 +1872,7 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1872,7 +1872,7 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {
1872 const dest_reg_lock = self.register_manager.lockRegAssumeUnused(dest_reg);1872 const dest_reg_lock = self.register_manager.lockRegAssumeUnused(dest_reg);
1873 defer self.register_manager.unlockReg(dest_reg_lock);1873 defer self.register_manager.unlockReg(dest_reg_lock);
18741874
1875 const raw_truncated_reg = try self.register_manager.allocReg(null);1875 const raw_truncated_reg = try self.register_manager.allocReg(null, .{});
1876 const truncated_reg = registerAlias(raw_truncated_reg, lhs_ty.abiSize(self.target.*));1876 const truncated_reg = registerAlias(raw_truncated_reg, lhs_ty.abiSize(self.target.*));
1877 const truncated_reg_lock = self.register_manager.lockRegAssumeUnused(truncated_reg);1877 const truncated_reg_lock = self.register_manager.lockRegAssumeUnused(truncated_reg);
1878 defer self.register_manager.unlockReg(truncated_reg_lock);1878 defer self.register_manager.unlockReg(truncated_reg_lock);
...@@ -1983,7 +1983,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1983,7 +1983,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1983 const dest_reg_lock = self.register_manager.lockRegAssumeUnused(dest_reg);1983 const dest_reg_lock = self.register_manager.lockRegAssumeUnused(dest_reg);
1984 defer self.register_manager.unlockReg(dest_reg_lock);1984 defer self.register_manager.unlockReg(dest_reg_lock);
19851985
1986 const truncated_reg = try self.register_manager.allocReg(null);1986 const truncated_reg = try self.register_manager.allocReg(null, .{});
1987 const truncated_reg_lock = self.register_manager.lockRegAssumeUnused(truncated_reg);1987 const truncated_reg_lock = self.register_manager.lockRegAssumeUnused(truncated_reg);
1988 defer self.register_manager.unlockReg(truncated_reg_lock);1988 defer self.register_manager.unlockReg(truncated_reg_lock);
19891989
...@@ -2048,7 +2048,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -2048,7 +2048,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
2048 defer if (rhs_lock) |reg| self.register_manager.unlockReg(reg);2048 defer if (rhs_lock) |reg| self.register_manager.unlockReg(reg);
20492049
2050 const lhs_reg = if (lhs_is_register) lhs.register else blk: {2050 const lhs_reg = if (lhs_is_register) lhs.register else blk: {
2051 const raw_reg = try self.register_manager.allocReg(null);2051 const raw_reg = try self.register_manager.allocReg(null, .{});
2052 const reg = registerAlias(raw_reg, lhs_ty.abiSize(self.target.*));2052 const reg = registerAlias(raw_reg, lhs_ty.abiSize(self.target.*));
2053 break :blk reg;2053 break :blk reg;
2054 };2054 };
...@@ -2056,7 +2056,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -2056,7 +2056,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
2056 defer if (new_lhs_lock) |reg| self.register_manager.unlockReg(reg);2056 defer if (new_lhs_lock) |reg| self.register_manager.unlockReg(reg);
20572057
2058 const rhs_reg = if (rhs_is_register) rhs.register else blk: {2058 const rhs_reg = if (rhs_is_register) rhs.register else blk: {
2059 const raw_reg = try self.register_manager.allocReg(null);2059 const raw_reg = try self.register_manager.allocReg(null, .{});
2060 const reg = registerAlias(raw_reg, rhs_ty.abiAlignment(self.target.*));2060 const reg = registerAlias(raw_reg, rhs_ty.abiAlignment(self.target.*));
2061 break :blk reg;2061 break :blk reg;
2062 };2062 };
...@@ -2067,7 +2067,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -2067,7 +2067,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
2067 if (!rhs_is_register) try self.genSetReg(rhs_ty, rhs_reg, rhs);2067 if (!rhs_is_register) try self.genSetReg(rhs_ty, rhs_reg, rhs);
20682068
2069 const dest_reg = blk: {2069 const dest_reg = blk: {
2070 const raw_reg = try self.register_manager.allocReg(null);2070 const raw_reg = try self.register_manager.allocReg(null, .{});
2071 const reg = registerAlias(raw_reg, lhs_ty.abiSize(self.target.*));2071 const reg = registerAlias(raw_reg, lhs_ty.abiSize(self.target.*));
2072 break :blk reg;2072 break :blk reg;
2073 };2073 };
...@@ -2086,7 +2086,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -2086,7 +2086,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
2086 } },2086 } },
2087 });2087 });
20882088
2089 const dest_high_reg = try self.register_manager.allocReg(null);2089 const dest_high_reg = try self.register_manager.allocReg(null, .{});
2090 const dest_high_reg_lock = self.register_manager.lockRegAssumeUnused(dest_high_reg);2090 const dest_high_reg_lock = self.register_manager.lockRegAssumeUnused(dest_high_reg);
2091 defer self.register_manager.unlockReg(dest_high_reg_lock);2091 defer self.register_manager.unlockReg(dest_high_reg_lock);
20922092
...@@ -2136,7 +2136,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -2136,7 +2136,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
2136 }2136 }
2137 },2137 },
2138 .unsigned => {2138 .unsigned => {
2139 const dest_high_reg = try self.register_manager.allocReg(null);2139 const dest_high_reg = try self.register_manager.allocReg(null, .{});
2140 const dest_high_reg_lock = self.register_manager.lockRegAssumeUnused(dest_high_reg);2140 const dest_high_reg_lock = self.register_manager.lockRegAssumeUnused(dest_high_reg);
2141 defer self.register_manager.unlockReg(dest_high_reg_lock);2141 defer self.register_manager.unlockReg(dest_high_reg_lock);
21422142
...@@ -2192,7 +2192,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -2192,7 +2192,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
2192 },2192 },
2193 }2193 }
21942194
2195 const truncated_reg = try self.register_manager.allocReg(null);2195 const truncated_reg = try self.register_manager.allocReg(null, .{});
2196 const truncated_reg_lock = self.register_manager.lockRegAssumeUnused(truncated_reg);2196 const truncated_reg_lock = self.register_manager.lockRegAssumeUnused(truncated_reg);
2197 defer self.register_manager.unlockReg(truncated_reg_lock);2197 defer self.register_manager.unlockReg(truncated_reg_lock);
21982198
...@@ -2663,7 +2663,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo...@@ -2663,7 +2663,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
2663 },2663 },
2664 .stack_offset => |off| {2664 .stack_offset => |off| {
2665 if (elem_size <= 8) {2665 if (elem_size <= 8) {
2666 const raw_tmp_reg = try self.register_manager.allocReg(null);2666 const raw_tmp_reg = try self.register_manager.allocReg(null, .{});
2667 const tmp_reg = registerAlias(raw_tmp_reg, elem_size);2667 const tmp_reg = registerAlias(raw_tmp_reg, elem_size);
2668 const tmp_reg_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);2668 const tmp_reg_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
2669 defer self.register_manager.unlockReg(tmp_reg_lock);2669 defer self.register_manager.unlockReg(tmp_reg_lock);
...@@ -2672,7 +2672,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo...@@ -2672,7 +2672,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
2672 try self.genSetStack(elem_ty, off, MCValue{ .register = tmp_reg });2672 try self.genSetStack(elem_ty, off, MCValue{ .register = tmp_reg });
2673 } else {2673 } else {
2674 // TODO optimize the register allocation2674 // TODO optimize the register allocation
2675 const regs = try self.register_manager.allocRegs(4, .{ null, null, null, null });2675 const regs = try self.register_manager.allocRegs(4, .{ null, null, null, null }, .{});
2676 const regs_locks = self.register_manager.lockRegsAssumeUnused(4, regs);2676 const regs_locks = self.register_manager.lockRegsAssumeUnused(4, regs);
2677 defer for (regs_locks) |reg| {2677 defer for (regs_locks) |reg| {
2678 self.register_manager.unlockReg(reg);2678 self.register_manager.unlockReg(reg);
...@@ -2887,7 +2887,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -2887,7 +2887,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
2887 },2887 },
2888 else => {2888 else => {
2889 if (abi_size <= 8) {2889 if (abi_size <= 8) {
2890 const raw_tmp_reg = try self.register_manager.allocReg(null);2890 const raw_tmp_reg = try self.register_manager.allocReg(null, .{});
2891 const tmp_reg = registerAlias(raw_tmp_reg, abi_size);2891 const tmp_reg = registerAlias(raw_tmp_reg, abi_size);
2892 const tmp_reg_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);2892 const tmp_reg_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
2893 defer self.register_manager.unlockReg(tmp_reg_lock);2893 defer self.register_manager.unlockReg(tmp_reg_lock);
...@@ -3002,7 +3002,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -3002,7 +3002,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
3002 // TODO return special MCValue condition flags3002 // TODO return special MCValue condition flags
3003 // get overflow bit: set register to C flag3003 // get overflow bit: set register to C flag
3004 // resp. V flag3004 // resp. V flag
3005 const raw_dest_reg = try self.register_manager.allocReg(null);3005 const raw_dest_reg = try self.register_manager.allocReg(null, .{});
3006 const dest_reg = raw_dest_reg.to32();3006 const dest_reg = raw_dest_reg.to32();
30073007
3008 // C flag: cset reg, cs3008 // C flag: cset reg, cs
...@@ -4065,7 +4065,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -4065,7 +4065,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
40654065
4066 const overflow_bit_ty = ty.structFieldType(1);4066 const overflow_bit_ty = ty.structFieldType(1);
4067 const overflow_bit_offset = @intCast(u32, ty.structFieldOffset(1, self.target.*));4067 const overflow_bit_offset = @intCast(u32, ty.structFieldOffset(1, self.target.*));
4068 const raw_cond_reg = try self.register_manager.allocReg(null);4068 const raw_cond_reg = try self.register_manager.allocReg(null, .{});
4069 const cond_reg = registerAlias(4069 const cond_reg = registerAlias(
4070 raw_cond_reg,4070 raw_cond_reg,
4071 @intCast(u32, overflow_bit_ty.abiSize(self.target.*)),4071 @intCast(u32, overflow_bit_ty.abiSize(self.target.*)),
...@@ -4113,7 +4113,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -4113,7 +4113,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
4113 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);4113 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
41144114
4115 // TODO call extern memcpy4115 // TODO call extern memcpy
4116 const regs = try self.register_manager.allocRegs(5, .{ null, null, null, null, null });4116 const regs = try self.register_manager.allocRegs(5, .{ null, null, null, null, null }, .{});
4117 const regs_locks = self.register_manager.lockRegsAssumeUnused(5, regs);4117 const regs_locks = self.register_manager.lockRegsAssumeUnused(5, regs);
4118 defer for (regs_locks) |reg| {4118 defer for (regs_locks) |reg| {
4119 self.register_manager.unlockReg(reg);4119 self.register_manager.unlockReg(reg);
src/arch/arm/CodeGen.zig+32-32
...@@ -874,7 +874,7 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {...@@ -874,7 +874,7 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {
874 const ptr_bits = self.target.cpu.arch.ptrBitWidth();874 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
875 const ptr_bytes: u64 = @divExact(ptr_bits, 8);875 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
876 if (abi_size <= ptr_bytes) {876 if (abi_size <= ptr_bytes) {
877 if (self.register_manager.tryAllocReg(inst)) |reg| {877 if (self.register_manager.tryAllocReg(inst, .{})) |reg| {
878 return MCValue{ .register = reg };878 return MCValue{ .register = reg };
879 }879 }
880 }880 }
...@@ -939,7 +939,7 @@ fn spillCompareFlagsIfOccupied(self: *Self) !void {...@@ -939,7 +939,7 @@ fn spillCompareFlagsIfOccupied(self: *Self) !void {
939/// allocated. A second call to `copyToTmpRegister` may return the same register.939/// allocated. A second call to `copyToTmpRegister` may return the same register.
940/// This can have a side effect of spilling instructions to the stack to free up a register.940/// This can have a side effect of spilling instructions to the stack to free up a register.
941fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {941fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {
942 const reg = try self.register_manager.allocReg(null);942 const reg = try self.register_manager.allocReg(null, .{});
943 try self.genSetReg(ty, reg, mcv);943 try self.genSetReg(ty, reg, mcv);
944 return reg;944 return reg;
945}945}
...@@ -948,7 +948,7 @@ fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {...@@ -948,7 +948,7 @@ fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {
948/// `reg_owner` is the instruction that gets associated with the register in the register table.948/// `reg_owner` is the instruction that gets associated with the register in the register table.
949/// This can have a side effect of spilling instructions to the stack to free up a register.949/// This can have a side effect of spilling instructions to the stack to free up a register.
950fn copyToNewRegister(self: *Self, reg_owner: Air.Inst.Index, mcv: MCValue) !MCValue {950fn copyToNewRegister(self: *Self, reg_owner: Air.Inst.Index, mcv: MCValue) !MCValue {
951 const reg = try self.register_manager.allocReg(reg_owner);951 const reg = try self.register_manager.allocReg(reg_owner, .{});
952 try self.genSetReg(self.air.typeOfIndex(reg_owner), reg, mcv);952 try self.genSetReg(self.air.typeOfIndex(reg_owner), reg, mcv);
953 return MCValue{ .register = reg };953 return MCValue{ .register = reg };
954}954}
...@@ -1065,9 +1065,9 @@ fn trunc(...@@ -1065,9 +1065,9 @@ fn trunc(
1065 if (operand == .register and self.reuseOperand(inst, ty_op.operand, 0, operand)) {1065 if (operand == .register and self.reuseOperand(inst, ty_op.operand, 0, operand)) {
1066 break :blk operand_reg;1066 break :blk operand_reg;
1067 } else {1067 } else {
1068 break :blk try self.register_manager.allocReg(inst);1068 break :blk try self.register_manager.allocReg(inst, .{});
1069 }1069 }
1070 } else try self.register_manager.allocReg(null);1070 } else try self.register_manager.allocReg(null, .{});
10711071
1072 switch (info_b.bits) {1072 switch (info_b.bits) {
1073 32 => {1073 32 => {
...@@ -1153,7 +1153,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {...@@ -1153,7 +1153,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
1153 break :blk op_reg;1153 break :blk op_reg;
1154 }1154 }
11551155
1156 break :blk try self.register_manager.allocReg(null);1156 break :blk try self.register_manager.allocReg(null, .{});
1157 };1157 };
11581158
1159 _ = try self.addInst(.{1159 _ = try self.addInst(.{
...@@ -1183,7 +1183,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {...@@ -1183,7 +1183,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void {
1183 break :blk op_reg;1183 break :blk op_reg;
1184 }1184 }
11851185
1186 break :blk try self.register_manager.allocReg(null);1186 break :blk try self.register_manager.allocReg(null, .{});
1187 };1187 };
11881188
1189 _ = try self.addInst(.{1189 _ = try self.addInst(.{
...@@ -1254,9 +1254,9 @@ fn minMax(...@@ -1254,9 +1254,9 @@ fn minMax(
1254 } else if (rhs_is_register and self.reuseOperand(inst, bin_op.rhs, 1, rhs)) {1254 } else if (rhs_is_register and self.reuseOperand(inst, bin_op.rhs, 1, rhs)) {
1255 break :blk rhs_reg;1255 break :blk rhs_reg;
1256 } else {1256 } else {
1257 break :blk try self.register_manager.allocReg(inst);1257 break :blk try self.register_manager.allocReg(inst, .{});
1258 }1258 }
1259 } else try self.register_manager.allocReg(null);1259 } else try self.register_manager.allocReg(null, .{});
12601260
1261 // lhs == reg should have been checked by airMinMax1261 // lhs == reg should have been checked by airMinMax
1262 //1262 //
...@@ -1438,7 +1438,7 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1438,7 +1438,7 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void {
1438 const dest_reg_lock = self.register_manager.lockRegAssumeUnused(dest_reg);1438 const dest_reg_lock = self.register_manager.lockRegAssumeUnused(dest_reg);
1439 defer self.register_manager.unlockReg(dest_reg_lock);1439 defer self.register_manager.unlockReg(dest_reg_lock);
14401440
1441 const truncated_reg = try self.register_manager.allocReg(null);1441 const truncated_reg = try self.register_manager.allocReg(null, .{});
1442 const truncated_reg_lock = self.register_manager.lockRegAssumeUnused(truncated_reg);1442 const truncated_reg_lock = self.register_manager.lockRegAssumeUnused(truncated_reg);
1443 defer self.register_manager.unlockReg(truncated_reg_lock);1443 defer self.register_manager.unlockReg(truncated_reg_lock);
14441444
...@@ -1543,7 +1543,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1543,7 +1543,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1543 const dest_reg_lock = self.register_manager.lockRegAssumeUnused(dest_reg);1543 const dest_reg_lock = self.register_manager.lockRegAssumeUnused(dest_reg);
1544 defer self.register_manager.unlockReg(dest_reg_lock);1544 defer self.register_manager.unlockReg(dest_reg_lock);
15451545
1546 const truncated_reg = try self.register_manager.allocReg(null);1546 const truncated_reg = try self.register_manager.allocReg(null, .{});
1547 const truncated_reg_lock = self.register_manager.lockRegAssumeUnused(truncated_reg);1547 const truncated_reg_lock = self.register_manager.lockRegAssumeUnused(truncated_reg);
1548 defer self.register_manager.unlockReg(truncated_reg_lock);1548 defer self.register_manager.unlockReg(truncated_reg_lock);
15491549
...@@ -1582,18 +1582,18 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1582,18 +1582,18 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1582 const lhs_reg = if (lhs_is_register)1582 const lhs_reg = if (lhs_is_register)
1583 lhs.register1583 lhs.register
1584 else1584 else
1585 try self.register_manager.allocReg(null);1585 try self.register_manager.allocReg(null, .{});
1586 const new_lhs_lock = self.register_manager.lockReg(lhs_reg);1586 const new_lhs_lock = self.register_manager.lockReg(lhs_reg);
1587 defer if (new_lhs_lock) |reg| self.register_manager.unlockReg(reg);1587 defer if (new_lhs_lock) |reg| self.register_manager.unlockReg(reg);
15881588
1589 const rhs_reg = if (rhs_is_register)1589 const rhs_reg = if (rhs_is_register)
1590 rhs.register1590 rhs.register
1591 else1591 else
1592 try self.register_manager.allocReg(null);1592 try self.register_manager.allocReg(null, .{});
1593 const new_rhs_lock = self.register_manager.lockReg(rhs_reg);1593 const new_rhs_lock = self.register_manager.lockReg(rhs_reg);
1594 defer if (new_rhs_lock) |reg| self.register_manager.unlockReg(reg);1594 defer if (new_rhs_lock) |reg| self.register_manager.unlockReg(reg);
15951595
1596 const dest_regs = try self.register_manager.allocRegs(2, .{ null, null });1596 const dest_regs = try self.register_manager.allocRegs(2, .{ null, null }, .{});
1597 const dest_regs_locks = self.register_manager.lockRegsAssumeUnused(2, dest_regs);1597 const dest_regs_locks = self.register_manager.lockRegsAssumeUnused(2, dest_regs);
1598 defer for (dest_regs_locks) |reg| {1598 defer for (dest_regs_locks) |reg| {
1599 self.register_manager.unlockReg(reg);1599 self.register_manager.unlockReg(reg);
...@@ -1604,7 +1604,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {...@@ -1604,7 +1604,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void {
1604 if (!lhs_is_register) try self.genSetReg(lhs_ty, lhs_reg, lhs);1604 if (!lhs_is_register) try self.genSetReg(lhs_ty, lhs_reg, lhs);
1605 if (!rhs_is_register) try self.genSetReg(rhs_ty, rhs_reg, rhs);1605 if (!rhs_is_register) try self.genSetReg(rhs_ty, rhs_reg, rhs);
16061606
1607 const truncated_reg = try self.register_manager.allocReg(null);1607 const truncated_reg = try self.register_manager.allocReg(null, .{});
1608 const truncated_reg_lock = self.register_manager.lockRegAssumeUnused(truncated_reg);1608 const truncated_reg_lock = self.register_manager.lockRegAssumeUnused(truncated_reg);
1609 defer self.register_manager.unlockReg(truncated_reg_lock);1609 defer self.register_manager.unlockReg(truncated_reg_lock);
16101610
...@@ -2026,7 +2026,7 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -2026,7 +2026,7 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void {
2026 const base_reg_lock = self.register_manager.lockRegAssumeUnused(base_reg);2026 const base_reg_lock = self.register_manager.lockRegAssumeUnused(base_reg);
2027 defer self.register_manager.unlockReg(base_reg_lock);2027 defer self.register_manager.unlockReg(base_reg_lock);
20282028
2029 const dst_reg = try self.register_manager.allocReg(inst);2029 const dst_reg = try self.register_manager.allocReg(inst, .{});
2030 const dst_mcv = MCValue{ .register = dst_reg };2030 const dst_mcv = MCValue{ .register = dst_reg };
2031 const dst_reg_lock = self.register_manager.lockRegAssumeUnused(dst_reg);2031 const dst_reg_lock = self.register_manager.lockRegAssumeUnused(dst_reg);
2032 defer self.register_manager.unlockReg(dst_reg_lock);2032 defer self.register_manager.unlockReg(dst_reg_lock);
...@@ -2234,7 +2234,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo...@@ -2234,7 +2234,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
2234 },2234 },
2235 .stack_offset => |off| {2235 .stack_offset => |off| {
2236 if (elem_size <= 4) {2236 if (elem_size <= 4) {
2237 const tmp_reg = try self.register_manager.allocReg(null);2237 const tmp_reg = try self.register_manager.allocReg(null, .{});
2238 const tmp_reg_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);2238 const tmp_reg_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
2239 defer self.register_manager.unlockReg(tmp_reg_lock);2239 defer self.register_manager.unlockReg(tmp_reg_lock);
22402240
...@@ -2242,7 +2242,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo...@@ -2242,7 +2242,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
2242 try self.genSetStack(elem_ty, off, MCValue{ .register = tmp_reg });2242 try self.genSetStack(elem_ty, off, MCValue{ .register = tmp_reg });
2243 } else {2243 } else {
2244 // TODO optimize the register allocation2244 // TODO optimize the register allocation
2245 const regs = try self.register_manager.allocRegs(4, .{ null, null, null, null });2245 const regs = try self.register_manager.allocRegs(4, .{ null, null, null, null }, .{});
2246 const regs_locks = self.register_manager.lockRegsAssumeUnused(4, regs);2246 const regs_locks = self.register_manager.lockRegsAssumeUnused(4, regs);
2247 defer for (regs_locks) |reg_locked| {2247 defer for (regs_locks) |reg_locked| {
2248 self.register_manager.unlockReg(reg_locked);2248 self.register_manager.unlockReg(reg_locked);
...@@ -2271,7 +2271,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo...@@ -2271,7 +2271,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
2271 .stack_offset,2271 .stack_offset,
2272 .stack_argument_offset,2272 .stack_argument_offset,
2273 => {2273 => {
2274 const reg = try self.register_manager.allocReg(null);2274 const reg = try self.register_manager.allocReg(null, .{});
2275 const reg_lock = self.register_manager.lockRegAssumeUnused(reg);2275 const reg_lock = self.register_manager.lockRegAssumeUnused(reg);
2276 defer self.register_manager.unlockReg(reg_lock);2276 defer self.register_manager.unlockReg(reg_lock);
22772277
...@@ -2338,14 +2338,14 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -2338,14 +2338,14 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
2338 },2338 },
2339 else => {2339 else => {
2340 if (elem_size <= 4) {2340 if (elem_size <= 4) {
2341 const tmp_reg = try self.register_manager.allocReg(null);2341 const tmp_reg = try self.register_manager.allocReg(null, .{});
2342 const tmp_reg_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);2342 const tmp_reg_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
2343 defer self.register_manager.unlockReg(tmp_reg_lock);2343 defer self.register_manager.unlockReg(tmp_reg_lock);
23442344
2345 try self.genSetReg(value_ty, tmp_reg, value);2345 try self.genSetReg(value_ty, tmp_reg, value);
2346 try self.store(ptr, .{ .register = tmp_reg }, ptr_ty, value_ty);2346 try self.store(ptr, .{ .register = tmp_reg }, ptr_ty, value_ty);
2347 } else {2347 } else {
2348 const regs = try self.register_manager.allocRegs(4, .{ null, null, null, null });2348 const regs = try self.register_manager.allocRegs(4, .{ null, null, null, null }, .{});
2349 const regs_locks = self.register_manager.lockRegsAssumeUnused(4, regs);2349 const regs_locks = self.register_manager.lockRegsAssumeUnused(4, regs);
2350 defer for (regs_locks) |reg| {2350 defer for (regs_locks) |reg| {
2351 self.register_manager.unlockReg(reg);2351 self.register_manager.unlockReg(reg);
...@@ -2487,7 +2487,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -2487,7 +2487,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
2487 1 => {2487 1 => {
2488 // get overflow bit: set register to C flag2488 // get overflow bit: set register to C flag
2489 // resp. V flag2489 // resp. V flag
2490 const dest_reg = try self.register_manager.allocReg(null);2490 const dest_reg = try self.register_manager.allocReg(null, .{});
24912491
2492 // mov reg, #02492 // mov reg, #0
2493 _ = try self.addInst(.{2493 _ = try self.addInst(.{
...@@ -2567,7 +2567,7 @@ fn binOpRegister(...@@ -2567,7 +2567,7 @@ fn binOpRegister(
2567 break :inst Air.refToIndex(md.lhs).?;2567 break :inst Air.refToIndex(md.lhs).?;
2568 } else null;2568 } else null;
25692569
2570 const reg = try self.register_manager.allocReg(track_inst);2570 const reg = try self.register_manager.allocReg(track_inst, .{});
25712571
2572 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });2572 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
25732573
...@@ -2581,7 +2581,7 @@ fn binOpRegister(...@@ -2581,7 +2581,7 @@ fn binOpRegister(
2581 break :inst Air.refToIndex(md.rhs).?;2581 break :inst Air.refToIndex(md.rhs).?;
2582 } else null;2582 } else null;
25832583
2584 const reg = try self.register_manager.allocReg(track_inst);2584 const reg = try self.register_manager.allocReg(track_inst, .{});
25852585
2586 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });2586 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
25872587
...@@ -2598,9 +2598,9 @@ fn binOpRegister(...@@ -2598,9 +2598,9 @@ fn binOpRegister(
2598 } else if (rhs_is_register and self.reuseOperand(md.inst, md.rhs, 1, rhs)) {2598 } else if (rhs_is_register and self.reuseOperand(md.inst, md.rhs, 1, rhs)) {
2599 break :blk rhs_reg;2599 break :blk rhs_reg;
2600 } else {2600 } else {
2601 break :blk try self.register_manager.allocReg(md.inst);2601 break :blk try self.register_manager.allocReg(md.inst, .{});
2602 }2602 }
2603 } else try self.register_manager.allocReg(null),2603 } else try self.register_manager.allocReg(null, .{}),
2604 };2604 };
26052605
2606 if (!lhs_is_register) try self.genSetReg(lhs_ty, lhs_reg, lhs);2606 if (!lhs_is_register) try self.genSetReg(lhs_ty, lhs_reg, lhs);
...@@ -2684,7 +2684,7 @@ fn binOpImmediate(...@@ -2684,7 +2684,7 @@ fn binOpImmediate(
2684 ).?;2684 ).?;
2685 } else null;2685 } else null;
26862686
2687 const reg = try self.register_manager.allocReg(track_inst);2687 const reg = try self.register_manager.allocReg(track_inst, .{});
26882688
2689 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });2689 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
26902690
...@@ -2704,9 +2704,9 @@ fn binOpImmediate(...@@ -2704,9 +2704,9 @@ fn binOpImmediate(
2704 )) {2704 )) {
2705 break :blk lhs_reg;2705 break :blk lhs_reg;
2706 } else {2706 } else {
2707 break :blk try self.register_manager.allocReg(md.inst);2707 break :blk try self.register_manager.allocReg(md.inst, .{});
2708 }2708 }
2709 } else try self.register_manager.allocReg(null),2709 } else try self.register_manager.allocReg(null, .{}),
2710 };2710 };
27112711
2712 if (!lhs_is_register) try self.genSetReg(lhs_ty, lhs_reg, lhs);2712 if (!lhs_is_register) try self.genSetReg(lhs_ty, lhs_reg, lhs);
...@@ -4363,7 +4363,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -4363,7 +4363,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
43634363
4364 const overflow_bit_ty = ty.structFieldType(1);4364 const overflow_bit_ty = ty.structFieldType(1);
4365 const overflow_bit_offset = @intCast(u32, ty.structFieldOffset(1, self.target.*));4365 const overflow_bit_offset = @intCast(u32, ty.structFieldOffset(1, self.target.*));
4366 const cond_reg = try self.register_manager.allocReg(null);4366 const cond_reg = try self.register_manager.allocReg(null, .{});
43674367
4368 // C flag: movcs reg, #14368 // C flag: movcs reg, #1
4369 // V flag: movvs reg, #14369 // V flag: movvs reg, #1
...@@ -4408,7 +4408,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -4408,7 +4408,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
4408 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);4408 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
44094409
4410 // TODO call extern memcpy4410 // TODO call extern memcpy
4411 const regs = try self.register_manager.allocRegs(5, .{ null, null, null, null, null });4411 const regs = try self.register_manager.allocRegs(5, .{ null, null, null, null, null }, .{});
4412 const src_reg = regs[0];4412 const src_reg = regs[0];
4413 const dst_reg = regs[1];4413 const dst_reg = regs[1];
4414 const len_reg = regs[2];4414 const len_reg = regs[2];
...@@ -4782,7 +4782,7 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I...@@ -4782,7 +4782,7 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I
4782 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);4782 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
47834783
4784 // TODO call extern memcpy4784 // TODO call extern memcpy
4785 const regs = try self.register_manager.allocRegs(5, .{ null, null, null, null, null });4785 const regs = try self.register_manager.allocRegs(5, .{ null, null, null, null, null }, .{});
4786 const src_reg = regs[0];4786 const src_reg = regs[0];
4787 const dst_reg = regs[1];4787 const dst_reg = regs[1];
4788 const len_reg = regs[2];4788 const len_reg = regs[2];
src/arch/riscv64/CodeGen.zig+8-8
...@@ -803,7 +803,7 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {...@@ -803,7 +803,7 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {
803 const ptr_bits = self.target.cpu.arch.ptrBitWidth();803 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
804 const ptr_bytes: u64 = @divExact(ptr_bits, 8);804 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
805 if (abi_size <= ptr_bytes) {805 if (abi_size <= ptr_bytes) {
806 if (self.register_manager.tryAllocReg(inst)) |reg| {806 if (self.register_manager.tryAllocReg(inst, .{})) |reg| {
807 return MCValue{ .register = reg };807 return MCValue{ .register = reg };
808 }808 }
809 }809 }
...@@ -826,7 +826,7 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void...@@ -826,7 +826,7 @@ pub fn spillInstruction(self: *Self, reg: Register, inst: Air.Inst.Index) !void
826/// allocated. A second call to `copyToTmpRegister` may return the same register.826/// allocated. A second call to `copyToTmpRegister` may return the same register.
827/// This can have a side effect of spilling instructions to the stack to free up a register.827/// This can have a side effect of spilling instructions to the stack to free up a register.
828fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {828fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {
829 const reg = try self.register_manager.allocReg(null);829 const reg = try self.register_manager.allocReg(null, .{});
830 try self.genSetReg(ty, reg, mcv);830 try self.genSetReg(ty, reg, mcv);
831 return reg;831 return reg;
832}832}
...@@ -835,7 +835,7 @@ fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {...@@ -835,7 +835,7 @@ fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {
835/// `reg_owner` is the instruction that gets associated with the register in the register table.835/// `reg_owner` is the instruction that gets associated with the register in the register table.
836/// This can have a side effect of spilling instructions to the stack to free up a register.836/// This can have a side effect of spilling instructions to the stack to free up a register.
837fn copyToNewRegister(self: *Self, reg_owner: Air.Inst.Index, mcv: MCValue) !MCValue {837fn copyToNewRegister(self: *Self, reg_owner: Air.Inst.Index, mcv: MCValue) !MCValue {
838 const reg = try self.register_manager.allocReg(reg_owner);838 const reg = try self.register_manager.allocReg(reg_owner, .{});
839 try self.genSetReg(self.air.typeOfIndex(reg_owner), reg, mcv);839 try self.genSetReg(self.air.typeOfIndex(reg_owner), reg, mcv);
840 return MCValue{ .register = reg };840 return MCValue{ .register = reg };
841}841}
...@@ -958,7 +958,7 @@ fn binOpRegister(...@@ -958,7 +958,7 @@ fn binOpRegister(
958 break :inst Air.refToIndex(bin_op.lhs).?;958 break :inst Air.refToIndex(bin_op.lhs).?;
959 } else null;959 } else null;
960960
961 const reg = try self.register_manager.allocReg(track_inst);961 const reg = try self.register_manager.allocReg(track_inst, .{});
962962
963 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });963 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
964964
...@@ -973,7 +973,7 @@ fn binOpRegister(...@@ -973,7 +973,7 @@ fn binOpRegister(
973 break :inst Air.refToIndex(bin_op.rhs).?;973 break :inst Air.refToIndex(bin_op.rhs).?;
974 } else null;974 } else null;
975975
976 const reg = try self.register_manager.allocReg(track_inst);976 const reg = try self.register_manager.allocReg(track_inst, .{});
977977
978 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });978 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
979979
...@@ -990,9 +990,9 @@ fn binOpRegister(...@@ -990,9 +990,9 @@ fn binOpRegister(
990 } else if (rhs_is_register and self.reuseOperand(inst, bin_op.rhs, 1, rhs)) {990 } else if (rhs_is_register and self.reuseOperand(inst, bin_op.rhs, 1, rhs)) {
991 break :blk rhs_reg;991 break :blk rhs_reg;
992 } else {992 } else {
993 break :blk try self.register_manager.allocReg(inst);993 break :blk try self.register_manager.allocReg(inst, .{});
994 }994 }
995 } else try self.register_manager.allocReg(null);995 } else try self.register_manager.allocReg(null, .{});
996996
997 if (!lhs_is_register) try self.genSetReg(lhs_ty, lhs_reg, lhs);997 if (!lhs_is_register) try self.genSetReg(lhs_ty, lhs_reg, lhs);
998 if (!rhs_is_register) try self.genSetReg(rhs_ty, rhs_reg, rhs);998 if (!rhs_is_register) try self.genSetReg(rhs_ty, rhs_reg, rhs);
...@@ -1482,7 +1482,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo...@@ -1482,7 +1482,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
1482 .memory,1482 .memory,
1483 .stack_offset,1483 .stack_offset,
1484 => {1484 => {
1485 const reg = try self.register_manager.allocReg(null);1485 const reg = try self.register_manager.allocReg(null, .{});
1486 const reg_lock = self.register_manager.lockRegAssumeUnused(reg);1486 const reg_lock = self.register_manager.lockRegAssumeUnused(reg);
1487 defer self.register_manager.unlockReg(reg_lock);1487 defer self.register_manager.unlockReg(reg_lock);
14881488
src/arch/sparc64/CodeGen.zig+13-13
...@@ -1613,7 +1613,7 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {...@@ -1613,7 +1613,7 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {
1613 if (reg_ok) {1613 if (reg_ok) {
1614 // Make sure the type can fit in a register before we try to allocate one.1614 // Make sure the type can fit in a register before we try to allocate one.
1615 if (abi_size <= 8) {1615 if (abi_size <= 8) {
1616 if (self.register_manager.tryAllocReg(inst)) |reg| {1616 if (self.register_manager.tryAllocReg(inst, .{})) |reg| {
1617 return MCValue{ .register = reg };1617 return MCValue{ .register = reg };
1618 }1618 }
1619 }1619 }
...@@ -1854,7 +1854,7 @@ fn binOpImmediate(...@@ -1854,7 +1854,7 @@ fn binOpImmediate(
1854 ).?;1854 ).?;
1855 } else null;1855 } else null;
18561856
1857 const reg = try self.register_manager.allocReg(track_inst);1857 const reg = try self.register_manager.allocReg(track_inst, .{});
18581858
1859 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });1859 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
18601860
...@@ -1873,10 +1873,10 @@ fn binOpImmediate(...@@ -1873,10 +1873,10 @@ fn binOpImmediate(
1873 )) {1873 )) {
1874 break :blk lhs_reg;1874 break :blk lhs_reg;
1875 } else {1875 } else {
1876 break :blk try self.register_manager.allocReg(md.inst);1876 break :blk try self.register_manager.allocReg(md.inst, .{});
1877 }1877 }
1878 } else blk: {1878 } else blk: {
1879 break :blk try self.register_manager.allocReg(null);1879 break :blk try self.register_manager.allocReg(null, .{});
1880 },1880 },
1881 };1881 };
18821882
...@@ -1953,7 +1953,7 @@ fn binOpRegister(...@@ -1953,7 +1953,7 @@ fn binOpRegister(
1953 break :inst Air.refToIndex(md.lhs).?;1953 break :inst Air.refToIndex(md.lhs).?;
1954 } else null;1954 } else null;
19551955
1956 const reg = try self.register_manager.allocReg(track_inst);1956 const reg = try self.register_manager.allocReg(track_inst, .{});
1957 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });1957 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
19581958
1959 break :blk reg;1959 break :blk reg;
...@@ -1966,7 +1966,7 @@ fn binOpRegister(...@@ -1966,7 +1966,7 @@ fn binOpRegister(
1966 break :inst Air.refToIndex(md.rhs).?;1966 break :inst Air.refToIndex(md.rhs).?;
1967 } else null;1967 } else null;
19681968
1969 const reg = try self.register_manager.allocReg(track_inst);1969 const reg = try self.register_manager.allocReg(track_inst, .{});
1970 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });1970 if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg });
19711971
1972 break :blk reg;1972 break :blk reg;
...@@ -1981,10 +1981,10 @@ fn binOpRegister(...@@ -1981,10 +1981,10 @@ fn binOpRegister(
1981 } else if (rhs_is_register and self.reuseOperand(md.inst, md.rhs, 1, rhs)) {1981 } else if (rhs_is_register and self.reuseOperand(md.inst, md.rhs, 1, rhs)) {
1982 break :blk rhs_reg;1982 break :blk rhs_reg;
1983 } else {1983 } else {
1984 break :blk try self.register_manager.allocReg(md.inst);1984 break :blk try self.register_manager.allocReg(md.inst, .{});
1985 }1985 }
1986 } else blk: {1986 } else blk: {
1987 break :blk try self.register_manager.allocReg(null);1987 break :blk try self.register_manager.allocReg(null, .{});
1988 },1988 },
1989 };1989 };
19901990
...@@ -2077,7 +2077,7 @@ fn brVoid(self: *Self, block: Air.Inst.Index) !void {...@@ -2077,7 +2077,7 @@ fn brVoid(self: *Self, block: Air.Inst.Index) !void {
2077/// allocated. A second call to `copyToTmpRegister` may return the same register.2077/// allocated. A second call to `copyToTmpRegister` may return the same register.
2078/// This can have a side effect of spilling instructions to the stack to free up a register.2078/// This can have a side effect of spilling instructions to the stack to free up a register.
2079fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {2079fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {
2080 const reg = try self.register_manager.allocReg(null);2080 const reg = try self.register_manager.allocReg(null, .{});
2081 try self.genSetReg(ty, reg, mcv);2081 try self.genSetReg(ty, reg, mcv);
2082 return reg;2082 return reg;
2083}2083}
...@@ -2364,7 +2364,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -2364,7 +2364,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
2364 });2364 });
2365 } else {2365 } else {
2366 // Need to allocate a temporary register to load 64-bit immediates.2366 // Need to allocate a temporary register to load 64-bit immediates.
2367 const tmp_reg = try self.register_manager.allocReg(null);2367 const tmp_reg = try self.register_manager.allocReg(null, .{});
23682368
2369 try self.genSetReg(ty, tmp_reg, .{ .immediate = @truncate(u32, x) });2369 try self.genSetReg(ty, tmp_reg, .{ .immediate = @truncate(u32, x) });
2370 try self.genSetReg(ty, reg, .{ .immediate = @truncate(u32, x >> 32) });2370 try self.genSetReg(ty, reg, .{ .immediate = @truncate(u32, x >> 32) });
...@@ -2478,7 +2478,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -2478,7 +2478,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
2478 };2478 };
2479 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);2479 const ptr_ty = Type.initPayload(&ptr_ty_payload.base);
24802480
2481 const regs = try self.register_manager.allocRegs(4, .{ null, null, null, null });2481 const regs = try self.register_manager.allocRegs(4, .{ null, null, null, null }, .{});
2482 const regs_locks = self.register_manager.lockRegsAssumeUnused(4, regs);2482 const regs_locks = self.register_manager.lockRegsAssumeUnused(4, regs);
2483 defer for (regs_locks) |reg| {2483 defer for (regs_locks) |reg| {
2484 self.register_manager.unlockReg(reg);2484 self.register_manager.unlockReg(reg);
...@@ -2717,14 +2717,14 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo...@@ -2717,14 +2717,14 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
2717 },2717 },
2718 .stack_offset => |off| {2718 .stack_offset => |off| {
2719 if (elem_size <= 8) {2719 if (elem_size <= 8) {
2720 const tmp_reg = try self.register_manager.allocReg(null);2720 const tmp_reg = try self.register_manager.allocReg(null, .{});
2721 const tmp_reg_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);2721 const tmp_reg_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
2722 defer self.register_manager.unlockReg(tmp_reg_lock);2722 defer self.register_manager.unlockReg(tmp_reg_lock);
27232723
2724 try self.load(.{ .register = tmp_reg }, ptr, ptr_ty);2724 try self.load(.{ .register = tmp_reg }, ptr, ptr_ty);
2725 try self.genSetStack(elem_ty, off, MCValue{ .register = tmp_reg });2725 try self.genSetStack(elem_ty, off, MCValue{ .register = tmp_reg });
2726 } else {2726 } else {
2727 const regs = try self.register_manager.allocRegs(3, .{ null, null, null });2727 const regs = try self.register_manager.allocRegs(3, .{ null, null, null }, .{});
2728 const regs_locks = self.register_manager.lockRegsAssumeUnused(3, regs);2728 const regs_locks = self.register_manager.lockRegsAssumeUnused(3, regs);
2729 defer for (regs_locks) |reg| {2729 defer for (regs_locks) |reg| {
2730 self.register_manager.unlockReg(reg);2730 self.register_manager.unlockReg(reg);
src/arch/x86_64/CodeGen.zig+20-20
...@@ -882,7 +882,7 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {...@@ -882,7 +882,7 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {
882 // TODO check if AVX available882 // TODO check if AVX available
883 const ptr_bytes: u64 = 32;883 const ptr_bytes: u64 = 32;
884 if (abi_size <= ptr_bytes) {884 if (abi_size <= ptr_bytes) {
885 if (self.register_manager.tryAllocReg(inst)) |reg| {885 if (self.register_manager.tryAllocReg(inst, .{})) |reg| {
886 return MCValue{ .register = registerAlias(reg, abi_size) };886 return MCValue{ .register = registerAlias(reg, abi_size) };
887 }887 }
888 }888 }
...@@ -892,7 +892,7 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {...@@ -892,7 +892,7 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue {
892 const ptr_bits = self.target.cpu.arch.ptrBitWidth();892 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
893 const ptr_bytes: u64 = @divExact(ptr_bits, 8);893 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
894 if (abi_size <= ptr_bytes) {894 if (abi_size <= ptr_bytes) {
895 if (self.register_manager.tryAllocReg(inst)) |reg| {895 if (self.register_manager.tryAllocReg(inst, .{})) |reg| {
896 return MCValue{ .register = registerAlias(reg, abi_size) };896 return MCValue{ .register = registerAlias(reg, abi_size) };
897 }897 }
898 }898 }
...@@ -963,7 +963,7 @@ pub fn spillRegisters(self: *Self, comptime count: comptime_int, registers: [cou...@@ -963,7 +963,7 @@ pub fn spillRegisters(self: *Self, comptime count: comptime_int, registers: [cou
963/// allocated. A second call to `copyToTmpRegister` may return the same register.963/// allocated. A second call to `copyToTmpRegister` may return the same register.
964/// This can have a side effect of spilling instructions to the stack to free up a register.964/// This can have a side effect of spilling instructions to the stack to free up a register.
965fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {965fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {
966 const reg = try self.register_manager.allocReg(null);966 const reg = try self.register_manager.allocReg(null, .{});
967 try self.genSetReg(ty, reg, mcv);967 try self.genSetReg(ty, reg, mcv);
968 return reg;968 return reg;
969}969}
...@@ -973,7 +973,7 @@ fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {...@@ -973,7 +973,7 @@ fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register {
973/// This can have a side effect of spilling instructions to the stack to free up a register.973/// This can have a side effect of spilling instructions to the stack to free up a register.
974/// WARNING make sure that the allocated register matches the returned MCValue from an instruction!974/// WARNING make sure that the allocated register matches the returned MCValue from an instruction!
975fn copyToRegisterWithInstTracking(self: *Self, reg_owner: Air.Inst.Index, ty: Type, mcv: MCValue) !MCValue {975fn copyToRegisterWithInstTracking(self: *Self, reg_owner: Air.Inst.Index, ty: Type, mcv: MCValue) !MCValue {
976 const reg = try self.register_manager.allocReg(reg_owner);976 const reg = try self.register_manager.allocReg(reg_owner, .{});
977 try self.genSetReg(ty, reg, mcv);977 try self.genSetReg(ty, reg, mcv);
978 return MCValue{ .register = reg };978 return MCValue{ .register = reg };
979}979}
...@@ -1029,7 +1029,7 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {...@@ -1029,7 +1029,7 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void {
1029 };1029 };
1030 defer if (operand_lock) |lock| self.register_manager.unlockReg(lock);1030 defer if (operand_lock) |lock| self.register_manager.unlockReg(lock);
10311031
1032 const reg = try self.register_manager.allocReg(inst);1032 const reg = try self.register_manager.allocReg(inst, .{});
1033 try self.genSetReg(dest_ty, reg, .{ .immediate = 0 });1033 try self.genSetReg(dest_ty, reg, .{ .immediate = 0 });
1034 try self.genSetReg(operand_ty, reg, operand);1034 try self.genSetReg(operand_ty, reg, operand);
1035 break :blk MCValue{ .register = reg };1035 break :blk MCValue{ .register = reg };
...@@ -1384,7 +1384,7 @@ fn genSetStackTruncatedOverflowCompare(...@@ -1384,7 +1384,7 @@ fn genSetStackTruncatedOverflowCompare(
1384 .unsigned => ty,1384 .unsigned => ty,
1385 };1385 };
13861386
1387 const temp_regs = try self.register_manager.allocRegs(3, .{ null, null, null });1387 const temp_regs = try self.register_manager.allocRegs(3, .{ null, null, null }, .{});
1388 const temp_regs_locks = self.register_manager.lockRegsAssumeUnused(3, temp_regs);1388 const temp_regs_locks = self.register_manager.lockRegsAssumeUnused(3, temp_regs);
1389 defer for (temp_regs_locks) |rreg| {1389 defer for (temp_regs_locks) |rreg| {
1390 self.register_manager.unlockReg(rreg);1390 self.register_manager.unlockReg(rreg);
...@@ -2046,7 +2046,7 @@ fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue {...@@ -2046,7 +2046,7 @@ fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue {
2046 const offset_reg_lock = self.register_manager.lockRegAssumeUnused(offset_reg);2046 const offset_reg_lock = self.register_manager.lockRegAssumeUnused(offset_reg);
2047 defer self.register_manager.unlockReg(offset_reg_lock);2047 defer self.register_manager.unlockReg(offset_reg_lock);
20482048
2049 const addr_reg = try self.register_manager.allocReg(null);2049 const addr_reg = try self.register_manager.allocReg(null, .{});
2050 switch (slice_mcv) {2050 switch (slice_mcv) {
2051 .stack_offset => |off| {2051 .stack_offset => |off| {
2052 // mov reg, [rbp - 8]2052 // mov reg, [rbp - 8]
...@@ -2125,7 +2125,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -2125,7 +2125,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void {
2125 const offset_reg_lock = self.register_manager.lockRegAssumeUnused(offset_reg);2125 const offset_reg_lock = self.register_manager.lockRegAssumeUnused(offset_reg);
2126 defer self.register_manager.unlockReg(offset_reg_lock);2126 defer self.register_manager.unlockReg(offset_reg_lock);
21272127
2128 const addr_reg = try self.register_manager.allocReg(null);2128 const addr_reg = try self.register_manager.allocReg(null, .{});
2129 switch (array) {2129 switch (array) {
2130 .register => {2130 .register => {
2131 const off = @intCast(i32, try self.allocMem(2131 const off = @intCast(i32, try self.allocMem(
...@@ -2492,7 +2492,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo...@@ -2492,7 +2492,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo
2492 },2492 },
2493 .stack_offset => |off| {2493 .stack_offset => |off| {
2494 if (abi_size <= 8) {2494 if (abi_size <= 8) {
2495 const tmp_reg = try self.register_manager.allocReg(null);2495 const tmp_reg = try self.register_manager.allocReg(null, .{});
2496 try self.load(.{ .register = tmp_reg }, ptr, ptr_ty);2496 try self.load(.{ .register = tmp_reg }, ptr, ptr_ty);
2497 return self.genSetStack(elem_ty, off, MCValue{ .register = tmp_reg }, .{});2497 return self.genSetStack(elem_ty, off, MCValue{ .register = tmp_reg }, .{});
2498 }2498 }
...@@ -2693,7 +2693,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -2693,7 +2693,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
2693 };2693 };
2694 defer if (value_lock) |lock| self.register_manager.unlockReg(lock);2694 defer if (value_lock) |lock| self.register_manager.unlockReg(lock);
26952695
2696 const addr_reg = try self.register_manager.allocReg(null);2696 const addr_reg = try self.register_manager.allocReg(null, .{});
2697 const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);2697 const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
2698 defer self.register_manager.unlockReg(addr_reg_lock);2698 defer self.register_manager.unlockReg(addr_reg_lock);
26992699
...@@ -2765,7 +2765,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -2765,7 +2765,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
2765 .memory,2765 .memory,
2766 => {2766 => {
2767 if (abi_size <= 8) {2767 if (abi_size <= 8) {
2768 const tmp_reg = try self.register_manager.allocReg(null);2768 const tmp_reg = try self.register_manager.allocReg(null, .{});
2769 const tmp_reg_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);2769 const tmp_reg_lock = self.register_manager.lockRegAssumeUnused(tmp_reg);
2770 defer self.register_manager.unlockReg(tmp_reg_lock);2770 defer self.register_manager.unlockReg(tmp_reg_lock);
27712771
...@@ -2883,7 +2883,7 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde...@@ -2883,7 +2883,7 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde
2883 if (can_reuse_operand) {2883 if (can_reuse_operand) {
2884 break :blk reg;2884 break :blk reg;
2885 } else {2885 } else {
2886 const result_reg = try self.register_manager.allocReg(inst);2886 const result_reg = try self.register_manager.allocReg(inst, .{});
2887 try self.genSetReg(ptr_ty, result_reg, mcv);2887 try self.genSetReg(ptr_ty, result_reg, mcv);
2888 break :blk result_reg;2888 break :blk result_reg;
2889 }2889 }
...@@ -2984,7 +2984,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {...@@ -2984,7 +2984,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void {
2984 const reg_lock = self.register_manager.lockRegAssumeUnused(reg);2984 const reg_lock = self.register_manager.lockRegAssumeUnused(reg);
2985 defer self.register_manager.unlockReg(reg_lock);2985 defer self.register_manager.unlockReg(reg_lock);
29862986
2987 const dst_reg = try self.register_manager.allocReg(inst);2987 const dst_reg = try self.register_manager.allocReg(inst, .{});
2988 const flags: u2 = switch (mcv) {2988 const flags: u2 = switch (mcv) {
2989 .register_overflow_unsigned => 0b10,2989 .register_overflow_unsigned => 0b10,
2990 .register_overflow_signed => 0b00,2990 .register_overflow_signed => 0b00,
...@@ -5362,7 +5362,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl...@@ -5362,7 +5362,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl
53625362
5363 const overflow_bit_ty = ty.structFieldType(1);5363 const overflow_bit_ty = ty.structFieldType(1);
5364 const overflow_bit_offset = ty.structFieldOffset(1, self.target.*);5364 const overflow_bit_offset = ty.structFieldOffset(1, self.target.*);
5365 const tmp_reg = try self.register_manager.allocReg(null);5365 const tmp_reg = try self.register_manager.allocReg(null, .{});
5366 const flags: u2 = switch (mcv) {5366 const flags: u2 = switch (mcv) {
5367 .register_overflow_unsigned => 0b10,5367 .register_overflow_unsigned => 0b10,
5368 .register_overflow_signed => 0b00,5368 .register_overflow_signed => 0b00,
...@@ -5580,7 +5580,7 @@ fn genInlineMemcpy(...@@ -5580,7 +5580,7 @@ fn genInlineMemcpy(
5580 null;5580 null;
5581 defer if (dsbase_lock) |lock| self.register_manager.unlockReg(lock);5581 defer if (dsbase_lock) |lock| self.register_manager.unlockReg(lock);
55825582
5583 const dst_addr_reg = try self.register_manager.allocReg(null);5583 const dst_addr_reg = try self.register_manager.allocReg(null, .{});
5584 switch (dst_ptr) {5584 switch (dst_ptr) {
5585 .memory,5585 .memory,
5586 .got_load,5586 .got_load,
...@@ -5615,7 +5615,7 @@ fn genInlineMemcpy(...@@ -5615,7 +5615,7 @@ fn genInlineMemcpy(
5615 const dst_addr_reg_lock = self.register_manager.lockRegAssumeUnused(dst_addr_reg);5615 const dst_addr_reg_lock = self.register_manager.lockRegAssumeUnused(dst_addr_reg);
5616 defer self.register_manager.unlockReg(dst_addr_reg_lock);5616 defer self.register_manager.unlockReg(dst_addr_reg_lock);
56175617
5618 const src_addr_reg = try self.register_manager.allocReg(null);5618 const src_addr_reg = try self.register_manager.allocReg(null, .{});
5619 switch (src_ptr) {5619 switch (src_ptr) {
5620 .memory,5620 .memory,
5621 .got_load,5621 .got_load,
...@@ -5650,7 +5650,7 @@ fn genInlineMemcpy(...@@ -5650,7 +5650,7 @@ fn genInlineMemcpy(
5650 const src_addr_reg_lock = self.register_manager.lockRegAssumeUnused(src_addr_reg);5650 const src_addr_reg_lock = self.register_manager.lockRegAssumeUnused(src_addr_reg);
5651 defer self.register_manager.unlockReg(src_addr_reg_lock);5651 defer self.register_manager.unlockReg(src_addr_reg_lock);
56525652
5653 const regs = try self.register_manager.allocRegs(2, .{ null, null });5653 const regs = try self.register_manager.allocRegs(2, .{ null, null }, .{});
5654 const count_reg = regs[0].to64();5654 const count_reg = regs[0].to64();
5655 const tmp_reg = regs[1].to8();5655 const tmp_reg = regs[1].to8();
56565656
...@@ -5750,7 +5750,7 @@ fn genInlineMemset(...@@ -5750,7 +5750,7 @@ fn genInlineMemset(
5750 const rax_lock = self.register_manager.lockRegAssumeUnused(.rax);5750 const rax_lock = self.register_manager.lockRegAssumeUnused(.rax);
5751 defer self.register_manager.unlockReg(rax_lock);5751 defer self.register_manager.unlockReg(rax_lock);
57525752
5753 const addr_reg = try self.register_manager.allocReg(null);5753 const addr_reg = try self.register_manager.allocReg(null, .{});
5754 switch (dst_ptr) {5754 switch (dst_ptr) {
5755 .memory,5755 .memory,
5756 .got_load,5756 .got_load,
...@@ -6018,7 +6018,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -6018,7 +6018,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
6018 switch (ty.tag()) {6018 switch (ty.tag()) {
6019 .f32 => return self.fail("TODO genSetReg from memory for f32", .{}),6019 .f32 => return self.fail("TODO genSetReg from memory for f32", .{}),
6020 .f64 => {6020 .f64 => {
6021 const base_reg = try self.register_manager.allocReg(null);6021 const base_reg = try self.register_manager.allocReg(null, .{});
6022 try self.loadMemPtrIntoRegister(base_reg, Type.usize, mcv);6022 try self.loadMemPtrIntoRegister(base_reg, Type.usize, mcv);
6023 _ = try self.addInst(.{6023 _ = try self.addInst(.{
6024 .tag = .mov_f64,6024 .tag = .mov_f64,
...@@ -6328,7 +6328,7 @@ fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void {...@@ -6328,7 +6328,7 @@ fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void {
6328 const src: MCValue = blk: {6328 const src: MCValue = blk: {
6329 switch (src_ptr) {6329 switch (src_ptr) {
6330 .got_load, .direct_load, .memory => {6330 .got_load, .direct_load, .memory => {
6331 const reg = try self.register_manager.allocReg(null);6331 const reg = try self.register_manager.allocReg(null, .{});
6332 try self.loadMemPtrIntoRegister(reg, src_ty, src_ptr);6332 try self.loadMemPtrIntoRegister(reg, src_ty, src_ptr);
6333 _ = try self.addInst(.{6333 _ = try self.addInst(.{
6334 .tag = .mov,6334 .tag = .mov,
src/register_manager.zig+12-5
...@@ -173,6 +173,10 @@ pub fn RegisterManager(...@@ -173,6 +173,10 @@ pub fn RegisterManager(
173 return self.locked_registers != 0;173 return self.locked_registers != 0;
174 }174 }
175175
176 const AllocOpts = struct {
177 selector_mask: ?FreeRegInt = null,
178 };
179
176 /// Allocates a specified number of registers, optionally180 /// Allocates a specified number of registers, optionally
177 /// tracking them. Returns `null` if not enough registers are181 /// tracking them. Returns `null` if not enough registers are
178 /// free.182 /// free.
...@@ -180,7 +184,9 @@ pub fn RegisterManager(...@@ -180,7 +184,9 @@ pub fn RegisterManager(
180 self: *Self,184 self: *Self,
181 comptime count: comptime_int,185 comptime count: comptime_int,
182 insts: [count]?Air.Inst.Index,186 insts: [count]?Air.Inst.Index,
187 opts: AllocOpts,
183 ) ?[count]Register {188 ) ?[count]Register {
189 _ = opts;
184 comptime assert(count > 0 and count <= tracked_registers.len);190 comptime assert(count > 0 and count <= tracked_registers.len);
185191
186 const free_and_not_locked_registers = self.free_registers & ~self.locked_registers;192 const free_and_not_locked_registers = self.free_registers & ~self.locked_registers;
...@@ -216,8 +222,8 @@ pub fn RegisterManager(...@@ -216,8 +222,8 @@ pub fn RegisterManager(
216 /// Allocates a register and optionally tracks it with a222 /// Allocates a register and optionally tracks it with a
217 /// corresponding instruction. Returns `null` if all registers223 /// corresponding instruction. Returns `null` if all registers
218 /// are allocated.224 /// are allocated.
219 pub fn tryAllocReg(self: *Self, inst: ?Air.Inst.Index) ?Register {225 pub fn tryAllocReg(self: *Self, inst: ?Air.Inst.Index, opts: AllocOpts) ?Register {
220 return if (tryAllocRegs(self, 1, .{inst})) |regs| regs[0] else null;226 return if (tryAllocRegs(self, 1, .{inst}, opts)) |regs| regs[0] else null;
221 }227 }
222228
223 /// Allocates a specified number of registers, optionally229 /// Allocates a specified number of registers, optionally
...@@ -227,12 +233,13 @@ pub fn RegisterManager(...@@ -227,12 +233,13 @@ pub fn RegisterManager(
227 self: *Self,233 self: *Self,
228 comptime count: comptime_int,234 comptime count: comptime_int,
229 insts: [count]?Air.Inst.Index,235 insts: [count]?Air.Inst.Index,
236 opts: AllocOpts,
230 ) AllocateRegistersError![count]Register {237 ) AllocateRegistersError![count]Register {
231 comptime assert(count > 0 and count <= tracked_registers.len);238 comptime assert(count > 0 and count <= tracked_registers.len);
232 const locked_registers_count = @popCount(FreeRegInt, self.locked_registers);239 const locked_registers_count = @popCount(FreeRegInt, self.locked_registers);
233 if (count > tracked_registers.len - locked_registers_count) return error.OutOfRegisters;240 if (count > tracked_registers.len - locked_registers_count) return error.OutOfRegisters;
234241
235 const result = self.tryAllocRegs(count, insts) orelse blk: {242 const result = self.tryAllocRegs(count, insts, opts) orelse blk: {
236 // We'll take over the first count registers. Spill243 // We'll take over the first count registers. Spill
237 // the instructions that were previously there to a244 // the instructions that were previously there to a
238 // stack allocations.245 // stack allocations.
...@@ -275,8 +282,8 @@ pub fn RegisterManager(...@@ -275,8 +282,8 @@ pub fn RegisterManager(
275282
276 /// Allocates a register and optionally tracks it with a283 /// Allocates a register and optionally tracks it with a
277 /// corresponding instruction.284 /// corresponding instruction.
278 pub fn allocReg(self: *Self, inst: ?Air.Inst.Index) AllocateRegistersError!Register {285 pub fn allocReg(self: *Self, inst: ?Air.Inst.Index, opts: AllocOpts) AllocateRegistersError!Register {
279 return (try self.allocRegs(1, .{inst}))[0];286 return (try self.allocRegs(1, .{inst}, opts))[0];
280 }287 }
281288
282 /// Spills the register if it is currently allocated. If a289 /// Spills the register if it is currently allocated. If a