| author | |
| committer | |
| log | 549174f743d3b56544e2d3d6993f4d43bba1e7fd |
| tree | 90be8877e03f93fd30a95120fd8db774e53b4898 |
| parent | 9e5c8cb008f75c2e570a0e48d5d014e936c103ca |
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 | 888 | if (reg_ok) { |
| 889 | 889 | // Make sure the type can fit in a register before we try to allocate one. |
| 890 | 890 | if (abi_size <= 8) { |
| 891 | if (self.register_manager.tryAllocReg(inst)) |reg| { | |
| 891 | if (self.register_manager.tryAllocReg(inst, .{})) |reg| { | |
| 892 | 892 | return MCValue{ .register = registerAlias(reg, abi_size) }; |
| 893 | 893 | } |
| 894 | 894 | } |
| ... | ... | @@ -951,7 +951,7 @@ fn spillCompareFlagsIfOccupied(self: *Self) !void { |
| 951 | 951 | /// allocated. A second call to `copyToTmpRegister` may return the same register. |
| 952 | 952 | /// This can have a side effect of spilling instructions to the stack to free up a register. |
| 953 | 953 | fn 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 | 955 | const reg = registerAlias(raw_reg, ty.abiSize(self.target.*)); |
| 956 | 956 | try self.genSetReg(ty, reg, mcv); |
| 957 | 957 | return reg; |
| ... | ... | @@ -961,7 +961,7 @@ fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register { |
| 961 | 961 | /// `reg_owner` is the instruction that gets associated with the register in the register table. |
| 962 | 962 | /// This can have a side effect of spilling instructions to the stack to free up a register. |
| 963 | 963 | fn 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 | 965 | const ty = self.air.typeOfIndex(reg_owner); |
| 966 | 966 | const reg = registerAlias(raw_reg, ty.abiSize(self.target.*)); |
| 967 | 967 | try self.genSetReg(self.air.typeOfIndex(reg_owner), reg, mcv); |
| ... | ... | @@ -1074,11 +1074,11 @@ fn trunc( |
| 1074 | 1074 | if (operand == .register and self.reuseOperand(inst, ty_op.operand, 0, operand)) { |
| 1075 | 1075 | break :blk registerAlias(operand_reg, dest_ty.abiSize(self.target.*)); |
| 1076 | 1076 | } else { |
| 1077 | const raw_reg = try self.register_manager.allocReg(inst); | |
| 1077 | const raw_reg = try self.register_manager.allocReg(inst, .{}); | |
| 1078 | 1078 | break :blk registerAlias(raw_reg, dest_ty.abiSize(self.target.*)); |
| 1079 | 1079 | } |
| 1080 | 1080 | } else blk: { |
| 1081 | const raw_reg = try self.register_manager.allocReg(null); | |
| 1081 | const raw_reg = try self.register_manager.allocReg(null, .{}); | |
| 1082 | 1082 | break :blk registerAlias(raw_reg, dest_ty.abiSize(self.target.*)); |
| 1083 | 1083 | }; |
| 1084 | 1084 | |
| ... | ... | @@ -1160,7 +1160,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void { |
| 1160 | 1160 | break :blk op_reg; |
| 1161 | 1161 | } |
| 1162 | 1162 | |
| 1163 | const raw_reg = try self.register_manager.allocReg(null); | |
| 1163 | const raw_reg = try self.register_manager.allocReg(null, .{}); | |
| 1164 | 1164 | break :blk raw_reg.to32(); |
| 1165 | 1165 | }; |
| 1166 | 1166 | |
| ... | ... | @@ -1193,7 +1193,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void { |
| 1193 | 1193 | break :blk op_reg; |
| 1194 | 1194 | } |
| 1195 | 1195 | |
| 1196 | const raw_reg = try self.register_manager.allocReg(null); | |
| 1196 | const raw_reg = try self.register_manager.allocReg(null, .{}); | |
| 1197 | 1197 | break :blk registerAlias(raw_reg, operand_ty.abiSize(self.target.*)); |
| 1198 | 1198 | }; |
| 1199 | 1199 | |
| ... | ... | @@ -1293,7 +1293,7 @@ fn binOpRegister( |
| 1293 | 1293 | break :inst Air.refToIndex(md.lhs).?; |
| 1294 | 1294 | } else null; |
| 1295 | 1295 | |
| 1296 | const raw_reg = try self.register_manager.allocReg(track_inst); | |
| 1296 | const raw_reg = try self.register_manager.allocReg(track_inst, .{}); | |
| 1297 | 1297 | const reg = registerAlias(raw_reg, lhs_ty.abiSize(self.target.*)); |
| 1298 | 1298 | |
| 1299 | 1299 | if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg }); |
| ... | ... | @@ -1308,7 +1308,7 @@ fn binOpRegister( |
| 1308 | 1308 | break :inst Air.refToIndex(md.rhs).?; |
| 1309 | 1309 | } else null; |
| 1310 | 1310 | |
| 1311 | const raw_reg = try self.register_manager.allocReg(track_inst); | |
| 1311 | const raw_reg = try self.register_manager.allocReg(track_inst, .{}); | |
| 1312 | 1312 | const reg = registerAlias(raw_reg, rhs_ty.abiAlignment(self.target.*)); |
| 1313 | 1313 | |
| 1314 | 1314 | if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg }); |
| ... | ... | @@ -1326,11 +1326,11 @@ fn binOpRegister( |
| 1326 | 1326 | } else if (rhs_is_register and self.reuseOperand(md.inst, md.rhs, 1, rhs)) { |
| 1327 | 1327 | break :blk rhs_reg; |
| 1328 | 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 | 1330 | break :blk registerAlias(raw_reg, lhs_ty.abiSize(self.target.*)); |
| 1331 | 1331 | } |
| 1332 | 1332 | } else blk: { |
| 1333 | const raw_reg = try self.register_manager.allocReg(null); | |
| 1333 | const raw_reg = try self.register_manager.allocReg(null, .{}); | |
| 1334 | 1334 | break :blk registerAlias(raw_reg, lhs_ty.abiSize(self.target.*)); |
| 1335 | 1335 | }, |
| 1336 | 1336 | }; |
| ... | ... | @@ -1431,7 +1431,7 @@ fn binOpImmediate( |
| 1431 | 1431 | ).?; |
| 1432 | 1432 | } else null; |
| 1433 | 1433 | |
| 1434 | const raw_reg = try self.register_manager.allocReg(track_inst); | |
| 1434 | const raw_reg = try self.register_manager.allocReg(track_inst, .{}); | |
| 1435 | 1435 | const reg = registerAlias(raw_reg, lhs_ty.abiSize(self.target.*)); |
| 1436 | 1436 | |
| 1437 | 1437 | if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg }); |
| ... | ... | @@ -1452,11 +1452,11 @@ fn binOpImmediate( |
| 1452 | 1452 | )) { |
| 1453 | 1453 | break :blk lhs_reg; |
| 1454 | 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 | 1456 | break :blk registerAlias(raw_reg, lhs_ty.abiSize(self.target.*)); |
| 1457 | 1457 | } |
| 1458 | 1458 | } else blk: { |
| 1459 | const raw_reg = try self.register_manager.allocReg(null); | |
| 1459 | const raw_reg = try self.register_manager.allocReg(null, .{}); | |
| 1460 | 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 | 1872 | const dest_reg_lock = self.register_manager.lockRegAssumeUnused(dest_reg); |
| 1873 | 1873 | defer self.register_manager.unlockReg(dest_reg_lock); |
| 1874 | 1874 | |
| 1875 | const raw_truncated_reg = try self.register_manager.allocReg(null); | |
| 1875 | const raw_truncated_reg = try self.register_manager.allocReg(null, .{}); | |
| 1876 | 1876 | const truncated_reg = registerAlias(raw_truncated_reg, lhs_ty.abiSize(self.target.*)); |
| 1877 | 1877 | const truncated_reg_lock = self.register_manager.lockRegAssumeUnused(truncated_reg); |
| 1878 | 1878 | defer self.register_manager.unlockReg(truncated_reg_lock); |
| ... | ... | @@ -1983,7 +1983,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 1983 | 1983 | const dest_reg_lock = self.register_manager.lockRegAssumeUnused(dest_reg); |
| 1984 | 1984 | defer self.register_manager.unlockReg(dest_reg_lock); |
| 1985 | 1985 | |
| 1986 | const truncated_reg = try self.register_manager.allocReg(null); | |
| 1986 | const truncated_reg = try self.register_manager.allocReg(null, .{}); | |
| 1987 | 1987 | const truncated_reg_lock = self.register_manager.lockRegAssumeUnused(truncated_reg); |
| 1988 | 1988 | defer self.register_manager.unlockReg(truncated_reg_lock); |
| 1989 | 1989 | |
| ... | ... | @@ -2048,7 +2048,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 2048 | 2048 | defer if (rhs_lock) |reg| self.register_manager.unlockReg(reg); |
| 2049 | 2049 | |
| 2050 | 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 | 2052 | const reg = registerAlias(raw_reg, lhs_ty.abiSize(self.target.*)); |
| 2053 | 2053 | break :blk reg; |
| 2054 | 2054 | }; |
| ... | ... | @@ -2056,7 +2056,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 2056 | 2056 | defer if (new_lhs_lock) |reg| self.register_manager.unlockReg(reg); |
| 2057 | 2057 | |
| 2058 | 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 | 2060 | const reg = registerAlias(raw_reg, rhs_ty.abiAlignment(self.target.*)); |
| 2061 | 2061 | break :blk reg; |
| 2062 | 2062 | }; |
| ... | ... | @@ -2067,7 +2067,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 2067 | 2067 | if (!rhs_is_register) try self.genSetReg(rhs_ty, rhs_reg, rhs); |
| 2068 | 2068 | |
| 2069 | 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 | 2071 | const reg = registerAlias(raw_reg, lhs_ty.abiSize(self.target.*)); |
| 2072 | 2072 | break :blk reg; |
| 2073 | 2073 | }; |
| ... | ... | @@ -2086,7 +2086,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 2086 | 2086 | } }, |
| 2087 | 2087 | }); |
| 2088 | 2088 | |
| 2089 | const dest_high_reg = try self.register_manager.allocReg(null); | |
| 2089 | const dest_high_reg = try self.register_manager.allocReg(null, .{}); | |
| 2090 | 2090 | const dest_high_reg_lock = self.register_manager.lockRegAssumeUnused(dest_high_reg); |
| 2091 | 2091 | defer self.register_manager.unlockReg(dest_high_reg_lock); |
| 2092 | 2092 | |
| ... | ... | @@ -2136,7 +2136,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 2136 | 2136 | } |
| 2137 | 2137 | }, |
| 2138 | 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 | 2140 | const dest_high_reg_lock = self.register_manager.lockRegAssumeUnused(dest_high_reg); |
| 2141 | 2141 | defer self.register_manager.unlockReg(dest_high_reg_lock); |
| 2142 | 2142 | |
| ... | ... | @@ -2192,7 +2192,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 2192 | 2192 | }, |
| 2193 | 2193 | } |
| 2194 | 2194 | |
| 2195 | const truncated_reg = try self.register_manager.allocReg(null); | |
| 2195 | const truncated_reg = try self.register_manager.allocReg(null, .{}); | |
| 2196 | 2196 | const truncated_reg_lock = self.register_manager.lockRegAssumeUnused(truncated_reg); |
| 2197 | 2197 | defer self.register_manager.unlockReg(truncated_reg_lock); |
| 2198 | 2198 | |
| ... | ... | @@ -2663,7 +2663,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 2663 | 2663 | }, |
| 2664 | 2664 | .stack_offset => |off| { |
| 2665 | 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 | 2667 | const tmp_reg = registerAlias(raw_tmp_reg, elem_size); |
| 2668 | 2668 | const tmp_reg_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 2669 | 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 | 2672 | try self.genSetStack(elem_ty, off, MCValue{ .register = tmp_reg }); |
| 2673 | 2673 | } else { |
| 2674 | 2674 | // 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 | 2676 | const regs_locks = self.register_manager.lockRegsAssumeUnused(4, regs); |
| 2677 | 2677 | defer for (regs_locks) |reg| { |
| 2678 | 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 | 2887 | }, |
| 2888 | 2888 | else => { |
| 2889 | 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 | 2891 | const tmp_reg = registerAlias(raw_tmp_reg, abi_size); |
| 2892 | 2892 | const tmp_reg_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 2893 | 2893 | defer self.register_manager.unlockReg(tmp_reg_lock); |
| ... | ... | @@ -3002,7 +3002,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 3002 | 3002 | // TODO return special MCValue condition flags |
| 3003 | 3003 | // get overflow bit: set register to C flag |
| 3004 | 3004 | // 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 | 3006 | const dest_reg = raw_dest_reg.to32(); |
| 3007 | 3007 | |
| 3008 | 3008 | // C flag: cset reg, cs |
| ... | ... | @@ -4065,7 +4065,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 4065 | 4065 | |
| 4066 | 4066 | const overflow_bit_ty = ty.structFieldType(1); |
| 4067 | 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 | 4069 | const cond_reg = registerAlias( |
| 4070 | 4070 | raw_cond_reg, |
| 4071 | 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 | 4113 | const ptr_ty = Type.initPayload(&ptr_ty_payload.base); |
| 4114 | 4114 | |
| 4115 | 4115 | // 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 | 4117 | const regs_locks = self.register_manager.lockRegsAssumeUnused(5, regs); |
| 4118 | 4118 | defer for (regs_locks) |reg| { |
| 4119 | 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 | 874 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); |
| 875 | 875 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); |
| 876 | 876 | if (abi_size <= ptr_bytes) { |
| 877 | if (self.register_manager.tryAllocReg(inst)) |reg| { | |
| 877 | if (self.register_manager.tryAllocReg(inst, .{})) |reg| { | |
| 878 | 878 | return MCValue{ .register = reg }; |
| 879 | 879 | } |
| 880 | 880 | } |
| ... | ... | @@ -939,7 +939,7 @@ fn spillCompareFlagsIfOccupied(self: *Self) !void { |
| 939 | 939 | /// allocated. A second call to `copyToTmpRegister` may return the same register. |
| 940 | 940 | /// This can have a side effect of spilling instructions to the stack to free up a register. |
| 941 | 941 | fn 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 | 943 | try self.genSetReg(ty, reg, mcv); |
| 944 | 944 | return reg; |
| 945 | 945 | } |
| ... | ... | @@ -948,7 +948,7 @@ fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register { |
| 948 | 948 | /// `reg_owner` is the instruction that gets associated with the register in the register table. |
| 949 | 949 | /// This can have a side effect of spilling instructions to the stack to free up a register. |
| 950 | 950 | fn 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 | 952 | try self.genSetReg(self.air.typeOfIndex(reg_owner), reg, mcv); |
| 953 | 953 | return MCValue{ .register = reg }; |
| 954 | 954 | } |
| ... | ... | @@ -1065,9 +1065,9 @@ fn trunc( |
| 1065 | 1065 | if (operand == .register and self.reuseOperand(inst, ty_op.operand, 0, operand)) { |
| 1066 | 1066 | break :blk operand_reg; |
| 1067 | 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, .{}); | |
| 1071 | 1071 | |
| 1072 | 1072 | switch (info_b.bits) { |
| 1073 | 1073 | 32 => { |
| ... | ... | @@ -1153,7 +1153,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void { |
| 1153 | 1153 | break :blk op_reg; |
| 1154 | 1154 | } |
| 1155 | 1155 | |
| 1156 | break :blk try self.register_manager.allocReg(null); | |
| 1156 | break :blk try self.register_manager.allocReg(null, .{}); | |
| 1157 | 1157 | }; |
| 1158 | 1158 | |
| 1159 | 1159 | _ = try self.addInst(.{ |
| ... | ... | @@ -1183,7 +1183,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void { |
| 1183 | 1183 | break :blk op_reg; |
| 1184 | 1184 | } |
| 1185 | 1185 | |
| 1186 | break :blk try self.register_manager.allocReg(null); | |
| 1186 | break :blk try self.register_manager.allocReg(null, .{}); | |
| 1187 | 1187 | }; |
| 1188 | 1188 | |
| 1189 | 1189 | _ = try self.addInst(.{ |
| ... | ... | @@ -1254,9 +1254,9 @@ fn minMax( |
| 1254 | 1254 | } else if (rhs_is_register and self.reuseOperand(inst, bin_op.rhs, 1, rhs)) { |
| 1255 | 1255 | break :blk rhs_reg; |
| 1256 | 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, .{}); | |
| 1260 | 1260 | |
| 1261 | 1261 | // lhs == reg should have been checked by airMinMax |
| 1262 | 1262 | // |
| ... | ... | @@ -1438,7 +1438,7 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 1438 | 1438 | const dest_reg_lock = self.register_manager.lockRegAssumeUnused(dest_reg); |
| 1439 | 1439 | defer self.register_manager.unlockReg(dest_reg_lock); |
| 1440 | 1440 | |
| 1441 | const truncated_reg = try self.register_manager.allocReg(null); | |
| 1441 | const truncated_reg = try self.register_manager.allocReg(null, .{}); | |
| 1442 | 1442 | const truncated_reg_lock = self.register_manager.lockRegAssumeUnused(truncated_reg); |
| 1443 | 1443 | defer self.register_manager.unlockReg(truncated_reg_lock); |
| 1444 | 1444 | |
| ... | ... | @@ -1543,7 +1543,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 1543 | 1543 | const dest_reg_lock = self.register_manager.lockRegAssumeUnused(dest_reg); |
| 1544 | 1544 | defer self.register_manager.unlockReg(dest_reg_lock); |
| 1545 | 1545 | |
| 1546 | const truncated_reg = try self.register_manager.allocReg(null); | |
| 1546 | const truncated_reg = try self.register_manager.allocReg(null, .{}); | |
| 1547 | 1547 | const truncated_reg_lock = self.register_manager.lockRegAssumeUnused(truncated_reg); |
| 1548 | 1548 | defer self.register_manager.unlockReg(truncated_reg_lock); |
| 1549 | 1549 | |
| ... | ... | @@ -1582,18 +1582,18 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 1582 | 1582 | const lhs_reg = if (lhs_is_register) |
| 1583 | 1583 | lhs.register |
| 1584 | 1584 | else |
| 1585 | try self.register_manager.allocReg(null); | |
| 1585 | try self.register_manager.allocReg(null, .{}); | |
| 1586 | 1586 | const new_lhs_lock = self.register_manager.lockReg(lhs_reg); |
| 1587 | 1587 | defer if (new_lhs_lock) |reg| self.register_manager.unlockReg(reg); |
| 1588 | 1588 | |
| 1589 | 1589 | const rhs_reg = if (rhs_is_register) |
| 1590 | 1590 | rhs.register |
| 1591 | 1591 | else |
| 1592 | try self.register_manager.allocReg(null); | |
| 1592 | try self.register_manager.allocReg(null, .{}); | |
| 1593 | 1593 | const new_rhs_lock = self.register_manager.lockReg(rhs_reg); |
| 1594 | 1594 | defer if (new_rhs_lock) |reg| self.register_manager.unlockReg(reg); |
| 1595 | 1595 | |
| 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 | 1597 | const dest_regs_locks = self.register_manager.lockRegsAssumeUnused(2, dest_regs); |
| 1598 | 1598 | defer for (dest_regs_locks) |reg| { |
| 1599 | 1599 | self.register_manager.unlockReg(reg); |
| ... | ... | @@ -1604,7 +1604,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 1604 | 1604 | if (!lhs_is_register) try self.genSetReg(lhs_ty, lhs_reg, lhs); |
| 1605 | 1605 | if (!rhs_is_register) try self.genSetReg(rhs_ty, rhs_reg, rhs); |
| 1606 | 1606 | |
| 1607 | const truncated_reg = try self.register_manager.allocReg(null); | |
| 1607 | const truncated_reg = try self.register_manager.allocReg(null, .{}); | |
| 1608 | 1608 | const truncated_reg_lock = self.register_manager.lockRegAssumeUnused(truncated_reg); |
| 1609 | 1609 | defer self.register_manager.unlockReg(truncated_reg_lock); |
| 1610 | 1610 | |
| ... | ... | @@ -2026,7 +2026,7 @@ fn airSliceElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2026 | 2026 | const base_reg_lock = self.register_manager.lockRegAssumeUnused(base_reg); |
| 2027 | 2027 | defer self.register_manager.unlockReg(base_reg_lock); |
| 2028 | 2028 | |
| 2029 | const dst_reg = try self.register_manager.allocReg(inst); | |
| 2029 | const dst_reg = try self.register_manager.allocReg(inst, .{}); | |
| 2030 | 2030 | const dst_mcv = MCValue{ .register = dst_reg }; |
| 2031 | 2031 | const dst_reg_lock = self.register_manager.lockRegAssumeUnused(dst_reg); |
| 2032 | 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 | 2234 | }, |
| 2235 | 2235 | .stack_offset => |off| { |
| 2236 | 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 | 2238 | const tmp_reg_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 2239 | 2239 | defer self.register_manager.unlockReg(tmp_reg_lock); |
| 2240 | 2240 | |
| ... | ... | @@ -2242,7 +2242,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 2242 | 2242 | try self.genSetStack(elem_ty, off, MCValue{ .register = tmp_reg }); |
| 2243 | 2243 | } else { |
| 2244 | 2244 | // 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 | 2246 | const regs_locks = self.register_manager.lockRegsAssumeUnused(4, regs); |
| 2247 | 2247 | defer for (regs_locks) |reg_locked| { |
| 2248 | 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 | 2271 | .stack_offset, |
| 2272 | 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 | 2275 | const reg_lock = self.register_manager.lockRegAssumeUnused(reg); |
| 2276 | 2276 | defer self.register_manager.unlockReg(reg_lock); |
| 2277 | 2277 | |
| ... | ... | @@ -2338,14 +2338,14 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2338 | 2338 | }, |
| 2339 | 2339 | else => { |
| 2340 | 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 | 2342 | const tmp_reg_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 2343 | 2343 | defer self.register_manager.unlockReg(tmp_reg_lock); |
| 2344 | 2344 | |
| 2345 | 2345 | try self.genSetReg(value_ty, tmp_reg, value); |
| 2346 | 2346 | try self.store(ptr, .{ .register = tmp_reg }, ptr_ty, value_ty); |
| 2347 | 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 | 2349 | const regs_locks = self.register_manager.lockRegsAssumeUnused(4, regs); |
| 2350 | 2350 | defer for (regs_locks) |reg| { |
| 2351 | 2351 | self.register_manager.unlockReg(reg); |
| ... | ... | @@ -2487,7 +2487,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2487 | 2487 | 1 => { |
| 2488 | 2488 | // get overflow bit: set register to C flag |
| 2489 | 2489 | // resp. V flag |
| 2490 | const dest_reg = try self.register_manager.allocReg(null); | |
| 2490 | const dest_reg = try self.register_manager.allocReg(null, .{}); | |
| 2491 | 2491 | |
| 2492 | 2492 | // mov reg, #0 |
| 2493 | 2493 | _ = try self.addInst(.{ |
| ... | ... | @@ -2567,7 +2567,7 @@ fn binOpRegister( |
| 2567 | 2567 | break :inst Air.refToIndex(md.lhs).?; |
| 2568 | 2568 | } else null; |
| 2569 | 2569 | |
| 2570 | const reg = try self.register_manager.allocReg(track_inst); | |
| 2570 | const reg = try self.register_manager.allocReg(track_inst, .{}); | |
| 2571 | 2571 | |
| 2572 | 2572 | if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg }); |
| 2573 | 2573 | |
| ... | ... | @@ -2581,7 +2581,7 @@ fn binOpRegister( |
| 2581 | 2581 | break :inst Air.refToIndex(md.rhs).?; |
| 2582 | 2582 | } else null; |
| 2583 | 2583 | |
| 2584 | const reg = try self.register_manager.allocReg(track_inst); | |
| 2584 | const reg = try self.register_manager.allocReg(track_inst, .{}); | |
| 2585 | 2585 | |
| 2586 | 2586 | if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg }); |
| 2587 | 2587 | |
| ... | ... | @@ -2598,9 +2598,9 @@ fn binOpRegister( |
| 2598 | 2598 | } else if (rhs_is_register and self.reuseOperand(md.inst, md.rhs, 1, rhs)) { |
| 2599 | 2599 | break :blk rhs_reg; |
| 2600 | 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 | }; |
| 2605 | 2605 | |
| 2606 | 2606 | if (!lhs_is_register) try self.genSetReg(lhs_ty, lhs_reg, lhs); |
| ... | ... | @@ -2684,7 +2684,7 @@ fn binOpImmediate( |
| 2684 | 2684 | ).?; |
| 2685 | 2685 | } else null; |
| 2686 | 2686 | |
| 2687 | const reg = try self.register_manager.allocReg(track_inst); | |
| 2687 | const reg = try self.register_manager.allocReg(track_inst, .{}); | |
| 2688 | 2688 | |
| 2689 | 2689 | if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg }); |
| 2690 | 2690 | |
| ... | ... | @@ -2704,9 +2704,9 @@ fn binOpImmediate( |
| 2704 | 2704 | )) { |
| 2705 | 2705 | break :blk lhs_reg; |
| 2706 | 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 | }; |
| 2711 | 2711 | |
| 2712 | 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 | 4363 | |
| 4364 | 4364 | const overflow_bit_ty = ty.structFieldType(1); |
| 4365 | 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, .{}); | |
| 4367 | 4367 | |
| 4368 | 4368 | // C flag: movcs reg, #1 |
| 4369 | 4369 | // V flag: movvs reg, #1 |
| ... | ... | @@ -4408,7 +4408,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 4408 | 4408 | const ptr_ty = Type.initPayload(&ptr_ty_payload.base); |
| 4409 | 4409 | |
| 4410 | 4410 | // 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 | 4412 | const src_reg = regs[0]; |
| 4413 | 4413 | const dst_reg = regs[1]; |
| 4414 | 4414 | const len_reg = regs[2]; |
| ... | ... | @@ -4782,7 +4782,7 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I |
| 4782 | 4782 | const ptr_ty = Type.initPayload(&ptr_ty_payload.base); |
| 4783 | 4783 | |
| 4784 | 4784 | // 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 | 4786 | const src_reg = regs[0]; |
| 4787 | 4787 | const dst_reg = regs[1]; |
| 4788 | 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 | 803 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); |
| 804 | 804 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); |
| 805 | 805 | if (abi_size <= ptr_bytes) { |
| 806 | if (self.register_manager.tryAllocReg(inst)) |reg| { | |
| 806 | if (self.register_manager.tryAllocReg(inst, .{})) |reg| { | |
| 807 | 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 | 826 | /// allocated. A second call to `copyToTmpRegister` may return the same register. |
| 827 | 827 | /// This can have a side effect of spilling instructions to the stack to free up a register. |
| 828 | 828 | fn 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 | 830 | try self.genSetReg(ty, reg, mcv); |
| 831 | 831 | return reg; |
| 832 | 832 | } |
| ... | ... | @@ -835,7 +835,7 @@ fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register { |
| 835 | 835 | /// `reg_owner` is the instruction that gets associated with the register in the register table. |
| 836 | 836 | /// This can have a side effect of spilling instructions to the stack to free up a register. |
| 837 | 837 | fn 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 | 839 | try self.genSetReg(self.air.typeOfIndex(reg_owner), reg, mcv); |
| 840 | 840 | return MCValue{ .register = reg }; |
| 841 | 841 | } |
| ... | ... | @@ -958,7 +958,7 @@ fn binOpRegister( |
| 958 | 958 | break :inst Air.refToIndex(bin_op.lhs).?; |
| 959 | 959 | } else null; |
| 960 | 960 | |
| 961 | const reg = try self.register_manager.allocReg(track_inst); | |
| 961 | const reg = try self.register_manager.allocReg(track_inst, .{}); | |
| 962 | 962 | |
| 963 | 963 | if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg }); |
| 964 | 964 | |
| ... | ... | @@ -973,7 +973,7 @@ fn binOpRegister( |
| 973 | 973 | break :inst Air.refToIndex(bin_op.rhs).?; |
| 974 | 974 | } else null; |
| 975 | 975 | |
| 976 | const reg = try self.register_manager.allocReg(track_inst); | |
| 976 | const reg = try self.register_manager.allocReg(track_inst, .{}); | |
| 977 | 977 | |
| 978 | 978 | if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg }); |
| 979 | 979 | |
| ... | ... | @@ -990,9 +990,9 @@ fn binOpRegister( |
| 990 | 990 | } else if (rhs_is_register and self.reuseOperand(inst, bin_op.rhs, 1, rhs)) { |
| 991 | 991 | break :blk rhs_reg; |
| 992 | 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, .{}); | |
| 996 | 996 | |
| 997 | 997 | if (!lhs_is_register) try self.genSetReg(lhs_ty, lhs_reg, lhs); |
| 998 | 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 | 1482 | .memory, |
| 1483 | 1483 | .stack_offset, |
| 1484 | 1484 | => { |
| 1485 | const reg = try self.register_manager.allocReg(null); | |
| 1485 | const reg = try self.register_manager.allocReg(null, .{}); | |
| 1486 | 1486 | const reg_lock = self.register_manager.lockRegAssumeUnused(reg); |
| 1487 | 1487 | defer self.register_manager.unlockReg(reg_lock); |
| 1488 | 1488 |
src/arch/sparc64/CodeGen.zig+13-13| ... | ... | @@ -1613,7 +1613,7 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue { |
| 1613 | 1613 | if (reg_ok) { |
| 1614 | 1614 | // Make sure the type can fit in a register before we try to allocate one. |
| 1615 | 1615 | if (abi_size <= 8) { |
| 1616 | if (self.register_manager.tryAllocReg(inst)) |reg| { | |
| 1616 | if (self.register_manager.tryAllocReg(inst, .{})) |reg| { | |
| 1617 | 1617 | return MCValue{ .register = reg }; |
| 1618 | 1618 | } |
| 1619 | 1619 | } |
| ... | ... | @@ -1854,7 +1854,7 @@ fn binOpImmediate( |
| 1854 | 1854 | ).?; |
| 1855 | 1855 | } else null; |
| 1856 | 1856 | |
| 1857 | const reg = try self.register_manager.allocReg(track_inst); | |
| 1857 | const reg = try self.register_manager.allocReg(track_inst, .{}); | |
| 1858 | 1858 | |
| 1859 | 1859 | if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg }); |
| 1860 | 1860 | |
| ... | ... | @@ -1873,10 +1873,10 @@ fn binOpImmediate( |
| 1873 | 1873 | )) { |
| 1874 | 1874 | break :blk lhs_reg; |
| 1875 | 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 | 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 | }; |
| 1882 | 1882 | |
| ... | ... | @@ -1953,7 +1953,7 @@ fn binOpRegister( |
| 1953 | 1953 | break :inst Air.refToIndex(md.lhs).?; |
| 1954 | 1954 | } else null; |
| 1955 | 1955 | |
| 1956 | const reg = try self.register_manager.allocReg(track_inst); | |
| 1956 | const reg = try self.register_manager.allocReg(track_inst, .{}); | |
| 1957 | 1957 | if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg }); |
| 1958 | 1958 | |
| 1959 | 1959 | break :blk reg; |
| ... | ... | @@ -1966,7 +1966,7 @@ fn binOpRegister( |
| 1966 | 1966 | break :inst Air.refToIndex(md.rhs).?; |
| 1967 | 1967 | } else null; |
| 1968 | 1968 | |
| 1969 | const reg = try self.register_manager.allocReg(track_inst); | |
| 1969 | const reg = try self.register_manager.allocReg(track_inst, .{}); | |
| 1970 | 1970 | if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg }); |
| 1971 | 1971 | |
| 1972 | 1972 | break :blk reg; |
| ... | ... | @@ -1981,10 +1981,10 @@ fn binOpRegister( |
| 1981 | 1981 | } else if (rhs_is_register and self.reuseOperand(md.inst, md.rhs, 1, rhs)) { |
| 1982 | 1982 | break :blk rhs_reg; |
| 1983 | 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 | 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 | }; |
| 1990 | 1990 | |
| ... | ... | @@ -2077,7 +2077,7 @@ fn brVoid(self: *Self, block: Air.Inst.Index) !void { |
| 2077 | 2077 | /// allocated. A second call to `copyToTmpRegister` may return the same register. |
| 2078 | 2078 | /// This can have a side effect of spilling instructions to the stack to free up a register. |
| 2079 | 2079 | fn 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 | 2081 | try self.genSetReg(ty, reg, mcv); |
| 2082 | 2082 | return reg; |
| 2083 | 2083 | } |
| ... | ... | @@ -2364,7 +2364,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 2364 | 2364 | }); |
| 2365 | 2365 | } else { |
| 2366 | 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, .{}); | |
| 2368 | 2368 | |
| 2369 | 2369 | try self.genSetReg(ty, tmp_reg, .{ .immediate = @truncate(u32, x) }); |
| 2370 | 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 | 2478 | }; |
| 2479 | 2479 | const ptr_ty = Type.initPayload(&ptr_ty_payload.base); |
| 2480 | 2480 | |
| 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 | 2482 | const regs_locks = self.register_manager.lockRegsAssumeUnused(4, regs); |
| 2483 | 2483 | defer for (regs_locks) |reg| { |
| 2484 | 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 | 2717 | }, |
| 2718 | 2718 | .stack_offset => |off| { |
| 2719 | 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 | 2721 | const tmp_reg_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 2722 | 2722 | defer self.register_manager.unlockReg(tmp_reg_lock); |
| 2723 | 2723 | |
| 2724 | 2724 | try self.load(.{ .register = tmp_reg }, ptr, ptr_ty); |
| 2725 | 2725 | try self.genSetStack(elem_ty, off, MCValue{ .register = tmp_reg }); |
| 2726 | 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 | 2728 | const regs_locks = self.register_manager.lockRegsAssumeUnused(3, regs); |
| 2729 | 2729 | defer for (regs_locks) |reg| { |
| 2730 | 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 | 882 | // TODO check if AVX available |
| 883 | 883 | const ptr_bytes: u64 = 32; |
| 884 | 884 | if (abi_size <= ptr_bytes) { |
| 885 | if (self.register_manager.tryAllocReg(inst)) |reg| { | |
| 885 | if (self.register_manager.tryAllocReg(inst, .{})) |reg| { | |
| 886 | 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 | 892 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); |
| 893 | 893 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); |
| 894 | 894 | if (abi_size <= ptr_bytes) { |
| 895 | if (self.register_manager.tryAllocReg(inst)) |reg| { | |
| 895 | if (self.register_manager.tryAllocReg(inst, .{})) |reg| { | |
| 896 | 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 | 963 | /// allocated. A second call to `copyToTmpRegister` may return the same register. |
| 964 | 964 | /// This can have a side effect of spilling instructions to the stack to free up a register. |
| 965 | 965 | fn 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 | 967 | try self.genSetReg(ty, reg, mcv); |
| 968 | 968 | return reg; |
| 969 | 969 | } |
| ... | ... | @@ -973,7 +973,7 @@ fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register { |
| 973 | 973 | /// This can have a side effect of spilling instructions to the stack to free up a register. |
| 974 | 974 | /// WARNING make sure that the allocated register matches the returned MCValue from an instruction! |
| 975 | 975 | fn 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 | 977 | try self.genSetReg(ty, reg, mcv); |
| 978 | 978 | return MCValue{ .register = reg }; |
| 979 | 979 | } |
| ... | ... | @@ -1029,7 +1029,7 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void { |
| 1029 | 1029 | }; |
| 1030 | 1030 | defer if (operand_lock) |lock| self.register_manager.unlockReg(lock); |
| 1031 | 1031 | |
| 1032 | const reg = try self.register_manager.allocReg(inst); | |
| 1032 | const reg = try self.register_manager.allocReg(inst, .{}); | |
| 1033 | 1033 | try self.genSetReg(dest_ty, reg, .{ .immediate = 0 }); |
| 1034 | 1034 | try self.genSetReg(operand_ty, reg, operand); |
| 1035 | 1035 | break :blk MCValue{ .register = reg }; |
| ... | ... | @@ -1384,7 +1384,7 @@ fn genSetStackTruncatedOverflowCompare( |
| 1384 | 1384 | .unsigned => ty, |
| 1385 | 1385 | }; |
| 1386 | 1386 | |
| 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 | 1388 | const temp_regs_locks = self.register_manager.lockRegsAssumeUnused(3, temp_regs); |
| 1389 | 1389 | defer for (temp_regs_locks) |rreg| { |
| 1390 | 1390 | self.register_manager.unlockReg(rreg); |
| ... | ... | @@ -2046,7 +2046,7 @@ fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue { |
| 2046 | 2046 | const offset_reg_lock = self.register_manager.lockRegAssumeUnused(offset_reg); |
| 2047 | 2047 | defer self.register_manager.unlockReg(offset_reg_lock); |
| 2048 | 2048 | |
| 2049 | const addr_reg = try self.register_manager.allocReg(null); | |
| 2049 | const addr_reg = try self.register_manager.allocReg(null, .{}); | |
| 2050 | 2050 | switch (slice_mcv) { |
| 2051 | 2051 | .stack_offset => |off| { |
| 2052 | 2052 | // mov reg, [rbp - 8] |
| ... | ... | @@ -2125,7 +2125,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2125 | 2125 | const offset_reg_lock = self.register_manager.lockRegAssumeUnused(offset_reg); |
| 2126 | 2126 | defer self.register_manager.unlockReg(offset_reg_lock); |
| 2127 | 2127 | |
| 2128 | const addr_reg = try self.register_manager.allocReg(null); | |
| 2128 | const addr_reg = try self.register_manager.allocReg(null, .{}); | |
| 2129 | 2129 | switch (array) { |
| 2130 | 2130 | .register => { |
| 2131 | 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 | 2492 | }, |
| 2493 | 2493 | .stack_offset => |off| { |
| 2494 | 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 | 2496 | try self.load(.{ .register = tmp_reg }, ptr, ptr_ty); |
| 2497 | 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 | 2693 | }; |
| 2694 | 2694 | defer if (value_lock) |lock| self.register_manager.unlockReg(lock); |
| 2695 | 2695 | |
| 2696 | const addr_reg = try self.register_manager.allocReg(null); | |
| 2696 | const addr_reg = try self.register_manager.allocReg(null, .{}); | |
| 2697 | 2697 | const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg); |
| 2698 | 2698 | defer self.register_manager.unlockReg(addr_reg_lock); |
| 2699 | 2699 | |
| ... | ... | @@ -2765,7 +2765,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2765 | 2765 | .memory, |
| 2766 | 2766 | => { |
| 2767 | 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 | 2769 | const tmp_reg_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 2770 | 2770 | defer self.register_manager.unlockReg(tmp_reg_lock); |
| 2771 | 2771 | |
| ... | ... | @@ -2883,7 +2883,7 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde |
| 2883 | 2883 | if (can_reuse_operand) { |
| 2884 | 2884 | break :blk reg; |
| 2885 | 2885 | } else { |
| 2886 | const result_reg = try self.register_manager.allocReg(inst); | |
| 2886 | const result_reg = try self.register_manager.allocReg(inst, .{}); | |
| 2887 | 2887 | try self.genSetReg(ptr_ty, result_reg, mcv); |
| 2888 | 2888 | break :blk result_reg; |
| 2889 | 2889 | } |
| ... | ... | @@ -2984,7 +2984,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2984 | 2984 | const reg_lock = self.register_manager.lockRegAssumeUnused(reg); |
| 2985 | 2985 | defer self.register_manager.unlockReg(reg_lock); |
| 2986 | 2986 | |
| 2987 | const dst_reg = try self.register_manager.allocReg(inst); | |
| 2987 | const dst_reg = try self.register_manager.allocReg(inst, .{}); | |
| 2988 | 2988 | const flags: u2 = switch (mcv) { |
| 2989 | 2989 | .register_overflow_unsigned => 0b10, |
| 2990 | 2990 | .register_overflow_signed => 0b00, |
| ... | ... | @@ -5362,7 +5362,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl |
| 5362 | 5362 | |
| 5363 | 5363 | const overflow_bit_ty = ty.structFieldType(1); |
| 5364 | 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 | 5366 | const flags: u2 = switch (mcv) { |
| 5367 | 5367 | .register_overflow_unsigned => 0b10, |
| 5368 | 5368 | .register_overflow_signed => 0b00, |
| ... | ... | @@ -5580,7 +5580,7 @@ fn genInlineMemcpy( |
| 5580 | 5580 | null; |
| 5581 | 5581 | defer if (dsbase_lock) |lock| self.register_manager.unlockReg(lock); |
| 5582 | 5582 | |
| 5583 | const dst_addr_reg = try self.register_manager.allocReg(null); | |
| 5583 | const dst_addr_reg = try self.register_manager.allocReg(null, .{}); | |
| 5584 | 5584 | switch (dst_ptr) { |
| 5585 | 5585 | .memory, |
| 5586 | 5586 | .got_load, |
| ... | ... | @@ -5615,7 +5615,7 @@ fn genInlineMemcpy( |
| 5615 | 5615 | const dst_addr_reg_lock = self.register_manager.lockRegAssumeUnused(dst_addr_reg); |
| 5616 | 5616 | defer self.register_manager.unlockReg(dst_addr_reg_lock); |
| 5617 | 5617 | |
| 5618 | const src_addr_reg = try self.register_manager.allocReg(null); | |
| 5618 | const src_addr_reg = try self.register_manager.allocReg(null, .{}); | |
| 5619 | 5619 | switch (src_ptr) { |
| 5620 | 5620 | .memory, |
| 5621 | 5621 | .got_load, |
| ... | ... | @@ -5650,7 +5650,7 @@ fn genInlineMemcpy( |
| 5650 | 5650 | const src_addr_reg_lock = self.register_manager.lockRegAssumeUnused(src_addr_reg); |
| 5651 | 5651 | defer self.register_manager.unlockReg(src_addr_reg_lock); |
| 5652 | 5652 | |
| 5653 | const regs = try self.register_manager.allocRegs(2, .{ null, null }); | |
| 5653 | const regs = try self.register_manager.allocRegs(2, .{ null, null }, .{}); | |
| 5654 | 5654 | const count_reg = regs[0].to64(); |
| 5655 | 5655 | const tmp_reg = regs[1].to8(); |
| 5656 | 5656 | |
| ... | ... | @@ -5750,7 +5750,7 @@ fn genInlineMemset( |
| 5750 | 5750 | const rax_lock = self.register_manager.lockRegAssumeUnused(.rax); |
| 5751 | 5751 | defer self.register_manager.unlockReg(rax_lock); |
| 5752 | 5752 | |
| 5753 | const addr_reg = try self.register_manager.allocReg(null); | |
| 5753 | const addr_reg = try self.register_manager.allocReg(null, .{}); | |
| 5754 | 5754 | switch (dst_ptr) { |
| 5755 | 5755 | .memory, |
| 5756 | 5756 | .got_load, |
| ... | ... | @@ -6018,7 +6018,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 6018 | 6018 | switch (ty.tag()) { |
| 6019 | 6019 | .f32 => return self.fail("TODO genSetReg from memory for f32", .{}), |
| 6020 | 6020 | .f64 => { |
| 6021 | const base_reg = try self.register_manager.allocReg(null); | |
| 6021 | const base_reg = try self.register_manager.allocReg(null, .{}); | |
| 6022 | 6022 | try self.loadMemPtrIntoRegister(base_reg, Type.usize, mcv); |
| 6023 | 6023 | _ = try self.addInst(.{ |
| 6024 | 6024 | .tag = .mov_f64, |
| ... | ... | @@ -6328,7 +6328,7 @@ fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void { |
| 6328 | 6328 | const src: MCValue = blk: { |
| 6329 | 6329 | switch (src_ptr) { |
| 6330 | 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 | 6332 | try self.loadMemPtrIntoRegister(reg, src_ty, src_ptr); |
| 6333 | 6333 | _ = try self.addInst(.{ |
| 6334 | 6334 | .tag = .mov, |
src/register_manager.zig+12-5| ... | ... | @@ -173,6 +173,10 @@ pub fn RegisterManager( |
| 173 | 173 | return self.locked_registers != 0; |
| 174 | 174 | } |
| 175 | 175 | |
| 176 | const AllocOpts = struct { | |
| 177 | selector_mask: ?FreeRegInt = null, | |
| 178 | }; | |
| 179 | ||
| 176 | 180 | /// Allocates a specified number of registers, optionally |
| 177 | 181 | /// tracking them. Returns `null` if not enough registers are |
| 178 | 182 | /// free. |
| ... | ... | @@ -180,7 +184,9 @@ pub fn RegisterManager( |
| 180 | 184 | self: *Self, |
| 181 | 185 | comptime count: comptime_int, |
| 182 | 186 | insts: [count]?Air.Inst.Index, |
| 187 | opts: AllocOpts, | |
| 183 | 188 | ) ?[count]Register { |
| 189 | _ = opts; | |
| 184 | 190 | comptime assert(count > 0 and count <= tracked_registers.len); |
| 185 | 191 | |
| 186 | 192 | const free_and_not_locked_registers = self.free_registers & ~self.locked_registers; |
| ... | ... | @@ -216,8 +222,8 @@ pub fn RegisterManager( |
| 216 | 222 | /// Allocates a register and optionally tracks it with a |
| 217 | 223 | /// corresponding instruction. Returns `null` if all registers |
| 218 | 224 | /// are allocated. |
| 219 | pub fn tryAllocReg(self: *Self, inst: ?Air.Inst.Index) ?Register { | |
| 220 | return if (tryAllocRegs(self, 1, .{inst})) |regs| regs[0] else null; | |
| 225 | pub fn tryAllocReg(self: *Self, inst: ?Air.Inst.Index, opts: AllocOpts) ?Register { | |
| 226 | return if (tryAllocRegs(self, 1, .{inst}, opts)) |regs| regs[0] else null; | |
| 221 | 227 | } |
| 222 | 228 | |
| 223 | 229 | /// Allocates a specified number of registers, optionally |
| ... | ... | @@ -227,12 +233,13 @@ pub fn RegisterManager( |
| 227 | 233 | self: *Self, |
| 228 | 234 | comptime count: comptime_int, |
| 229 | 235 | insts: [count]?Air.Inst.Index, |
| 236 | opts: AllocOpts, | |
| 230 | 237 | ) AllocateRegistersError![count]Register { |
| 231 | 238 | comptime assert(count > 0 and count <= tracked_registers.len); |
| 232 | 239 | const locked_registers_count = @popCount(FreeRegInt, self.locked_registers); |
| 233 | 240 | if (count > tracked_registers.len - locked_registers_count) return error.OutOfRegisters; |
| 234 | 241 | |
| 235 | const result = self.tryAllocRegs(count, insts) orelse blk: { | |
| 242 | const result = self.tryAllocRegs(count, insts, opts) orelse blk: { | |
| 236 | 243 | // We'll take over the first count registers. Spill |
| 237 | 244 | // the instructions that were previously there to a |
| 238 | 245 | // stack allocations. |
| ... | ... | @@ -275,8 +282,8 @@ pub fn RegisterManager( |
| 275 | 282 | |
| 276 | 283 | /// Allocates a register and optionally tracks it with a |
| 277 | 284 | /// corresponding instruction. |
| 278 | pub fn allocReg(self: *Self, inst: ?Air.Inst.Index) AllocateRegistersError!Register { | |
| 279 | return (try self.allocRegs(1, .{inst}))[0]; | |
| 285 | pub fn allocReg(self: *Self, inst: ?Air.Inst.Index, opts: AllocOpts) AllocateRegistersError!Register { | |
| 286 | return (try self.allocRegs(1, .{inst}, opts))[0]; | |
| 280 | 287 | } |
| 281 | 288 | |
| 282 | 289 | /// Spills the register if it is currently allocated. If a |