| ... | @@ -414,7 +414,7 @@ fn gen(self: *Self) !void { | ... | @@ -414,7 +414,7 @@ fn gen(self: *Self) !void { |
| 414 | // to the stack. | 414 | // to the stack. |
| 415 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); | 415 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); |
| 416 | const ptr_bytes = @divExact(ptr_bits, 8); | 416 | const ptr_bytes = @divExact(ptr_bits, 8); |
| 417 | const ret_ptr_reg = registerAlias(.x0, ptr_bytes); | 417 | const ret_ptr_reg = self.registerAlias(.x0, Type.usize); |
| 418 | | 418 | |
| 419 | const stack_offset = mem.alignForwardGeneric(u32, self.next_stack_offset, ptr_bytes) + ptr_bytes; | 419 | const stack_offset = mem.alignForwardGeneric(u32, self.next_stack_offset, ptr_bytes) + ptr_bytes; |
| 420 | self.next_stack_offset = stack_offset; | 420 | self.next_stack_offset = stack_offset; |
| ... | @@ -927,7 +927,7 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue { | ... | @@ -927,7 +927,7 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue { |
| 927 | // Make sure the type can fit in a register before we try to allocate one. | 927 | // Make sure the type can fit in a register before we try to allocate one. |
| 928 | if (abi_size <= 8) { | 928 | if (abi_size <= 8) { |
| 929 | if (self.register_manager.tryAllocReg(inst, gp)) |reg| { | 929 | if (self.register_manager.tryAllocReg(inst, gp)) |reg| { |
| 930 | return MCValue{ .register = registerAlias(reg, abi_size) }; | 930 | return MCValue{ .register = self.registerAlias(reg, elem_ty) }; |
| 931 | } | 931 | } |
| 932 | } | 932 | } |
| 933 | } | 933 | } |
| ... | @@ -982,7 +982,7 @@ fn spillCompareFlagsIfOccupied(self: *Self) !void { | ... | @@ -982,7 +982,7 @@ fn spillCompareFlagsIfOccupied(self: *Self) !void { |
| 982 | /// This can have a side effect of spilling instructions to the stack to free up a register. | 982 | /// This can have a side effect of spilling instructions to the stack to free up a register. |
| 983 | fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register { | 983 | fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register { |
| 984 | const raw_reg = try self.register_manager.allocReg(null, gp); | 984 | const raw_reg = try self.register_manager.allocReg(null, gp); |
| 985 | const reg = registerAlias(raw_reg, ty.abiSize(self.target.*)); | 985 | const reg = self.registerAlias(raw_reg, ty); |
| 986 | try self.genSetReg(ty, reg, mcv); | 986 | try self.genSetReg(ty, reg, mcv); |
| 987 | return reg; | 987 | return reg; |
| 988 | } | 988 | } |
| ... | @@ -993,7 +993,7 @@ fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register { | ... | @@ -993,7 +993,7 @@ fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register { |
| 993 | fn copyToNewRegister(self: *Self, reg_owner: Air.Inst.Index, mcv: MCValue) !MCValue { | 993 | fn copyToNewRegister(self: *Self, reg_owner: Air.Inst.Index, mcv: MCValue) !MCValue { |
| 994 | const raw_reg = try self.register_manager.allocReg(reg_owner, gp); | 994 | const raw_reg = try self.register_manager.allocReg(reg_owner, gp); |
| 995 | const ty = self.air.typeOfIndex(reg_owner); | 995 | const ty = self.air.typeOfIndex(reg_owner); |
| 996 | const reg = registerAlias(raw_reg, ty.abiSize(self.target.*)); | 996 | const reg = self.registerAlias(raw_reg, ty); |
| 997 | try self.genSetReg(self.air.typeOfIndex(reg_owner), reg, mcv); | 997 | try self.genSetReg(self.air.typeOfIndex(reg_owner), reg, mcv); |
| 998 | return MCValue{ .register = reg }; | 998 | return MCValue{ .register = reg }; |
| 999 | } | 999 | } |
| ... | @@ -1031,7 +1031,6 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1031,7 +1031,6 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void { |
| 1031 | const operand_info = operand_ty.intInfo(self.target.*); | 1031 | const operand_info = operand_ty.intInfo(self.target.*); |
| 1032 | | 1032 | |
| 1033 | const dest_ty = self.air.typeOfIndex(inst); | 1033 | const dest_ty = self.air.typeOfIndex(inst); |
| 1034 | const dest_abi_size = dest_ty.abiSize(self.target.*); | | |
| 1035 | const dest_info = dest_ty.intInfo(self.target.*); | 1034 | const dest_info = dest_ty.intInfo(self.target.*); |
| 1036 | | 1035 | |
| 1037 | const result: MCValue = result: { | 1036 | const result: MCValue = result: { |
| ... | @@ -1042,7 +1041,7 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1042,7 +1041,7 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void { |
| 1042 | defer if (operand_lock) |lock| self.register_manager.unlockReg(lock); | 1041 | defer if (operand_lock) |lock| self.register_manager.unlockReg(lock); |
| 1043 | | 1042 | |
| 1044 | const truncated: MCValue = switch (operand_mcv) { | 1043 | const truncated: MCValue = switch (operand_mcv) { |
| 1045 | .register => |r| MCValue{ .register = registerAlias(r, dest_abi_size) }, | 1044 | .register => |r| MCValue{ .register = self.registerAlias(r, dest_ty) }, |
| 1046 | else => operand_mcv, | 1045 | else => operand_mcv, |
| 1047 | }; | 1046 | }; |
| 1048 | | 1047 | |
| ... | @@ -1117,7 +1116,7 @@ fn trunc( | ... | @@ -1117,7 +1116,7 @@ fn trunc( |
| 1117 | else => operand_reg: { | 1116 | else => operand_reg: { |
| 1118 | if (info_a.bits <= 64) { | 1117 | if (info_a.bits <= 64) { |
| 1119 | const raw_reg = try self.copyToTmpRegister(operand_ty, operand); | 1118 | const raw_reg = try self.copyToTmpRegister(operand_ty, operand); |
| 1120 | break :operand_reg registerAlias(raw_reg, operand_ty.abiSize(self.target.*)); | 1119 | break :operand_reg self.registerAlias(raw_reg, operand_ty); |
| 1121 | } else { | 1120 | } else { |
| 1122 | return self.fail("TODO load least significant word into register", .{}); | 1121 | return self.fail("TODO load least significant word into register", .{}); |
| 1123 | } | 1122 | } |
| ... | @@ -1130,14 +1129,14 @@ fn trunc( | ... | @@ -1130,14 +1129,14 @@ fn trunc( |
| 1130 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 1129 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 1131 | | 1130 | |
| 1132 | if (operand == .register and self.reuseOperand(inst, ty_op.operand, 0, operand)) { | 1131 | if (operand == .register and self.reuseOperand(inst, ty_op.operand, 0, operand)) { |
| 1133 | break :blk registerAlias(operand_reg, dest_ty.abiSize(self.target.*)); | 1132 | break :blk self.registerAlias(operand_reg, dest_ty); |
| 1134 | } else { | 1133 | } else { |
| 1135 | const raw_reg = try self.register_manager.allocReg(inst, gp); | 1134 | const raw_reg = try self.register_manager.allocReg(inst, gp); |
| 1136 | break :blk registerAlias(raw_reg, dest_ty.abiSize(self.target.*)); | 1135 | break :blk self.registerAlias(raw_reg, dest_ty); |
| 1137 | } | 1136 | } |
| 1138 | } else blk: { | 1137 | } else blk: { |
| 1139 | const raw_reg = try self.register_manager.allocReg(null, gp); | 1138 | const raw_reg = try self.register_manager.allocReg(null, gp); |
| 1140 | break :blk registerAlias(raw_reg, dest_ty.abiSize(self.target.*)); | 1139 | break :blk self.registerAlias(raw_reg, dest_ty); |
| 1141 | }; | 1140 | }; |
| 1142 | | 1141 | |
| 1143 | try self.truncRegister(operand_reg, dest_reg, info_b.signedness, info_b.bits); | 1142 | try self.truncRegister(operand_reg, dest_reg, info_b.signedness, info_b.bits); |
| ... | @@ -1194,7 +1193,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1194,7 +1193,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void { |
| 1194 | } | 1193 | } |
| 1195 | | 1194 | |
| 1196 | const raw_reg = try self.register_manager.allocReg(null, gp); | 1195 | const raw_reg = try self.register_manager.allocReg(null, gp); |
| 1197 | break :blk raw_reg.to32(); | 1196 | break :blk self.registerAlias(raw_reg, operand_ty); |
| 1198 | }; | 1197 | }; |
| 1199 | | 1198 | |
| 1200 | _ = try self.addInst(.{ | 1199 | _ = try self.addInst(.{ |
| ... | @@ -1227,7 +1226,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -1227,7 +1226,7 @@ fn airNot(self: *Self, inst: Air.Inst.Index) !void { |
| 1227 | } | 1226 | } |
| 1228 | | 1227 | |
| 1229 | const raw_reg = try self.register_manager.allocReg(null, gp); | 1228 | const raw_reg = try self.register_manager.allocReg(null, gp); |
| 1230 | break :blk registerAlias(raw_reg, operand_ty.abiSize(self.target.*)); | 1229 | break :blk self.registerAlias(raw_reg, operand_ty); |
| 1231 | }; | 1230 | }; |
| 1232 | | 1231 | |
| 1233 | _ = try self.addInst(.{ | 1232 | _ = try self.addInst(.{ |
| ... | @@ -1307,8 +1306,8 @@ fn binOpRegister( | ... | @@ -1307,8 +1306,8 @@ fn binOpRegister( |
| 1307 | const lhs_is_register = lhs == .register; | 1306 | const lhs_is_register = lhs == .register; |
| 1308 | const rhs_is_register = rhs == .register; | 1307 | const rhs_is_register = rhs == .register; |
| 1309 | | 1308 | |
| 1310 | if (lhs_is_register) assert(lhs.register == registerAlias(lhs.register, lhs_ty.abiSize(self.target.*))); | 1309 | if (lhs_is_register) assert(lhs.register == self.registerAlias(lhs.register, lhs_ty)); |
| 1311 | if (rhs_is_register) assert(rhs.register == registerAlias(rhs.register, rhs_ty.abiSize(self.target.*))); | 1310 | if (rhs_is_register) assert(rhs.register == self.registerAlias(rhs.register, rhs_ty)); |
| 1312 | | 1311 | |
| 1313 | const lhs_lock: ?RegisterLock = if (lhs_is_register) | 1312 | const lhs_lock: ?RegisterLock = if (lhs_is_register) |
| 1314 | self.register_manager.lockReg(lhs.register) | 1313 | self.register_manager.lockReg(lhs.register) |
| ... | @@ -1330,7 +1329,7 @@ fn binOpRegister( | ... | @@ -1330,7 +1329,7 @@ fn binOpRegister( |
| 1330 | } else null; | 1329 | } else null; |
| 1331 | | 1330 | |
| 1332 | const raw_reg = try self.register_manager.allocReg(track_inst, gp); | 1331 | const raw_reg = try self.register_manager.allocReg(track_inst, gp); |
| 1333 | const reg = registerAlias(raw_reg, lhs_ty.abiSize(self.target.*)); | 1332 | const reg = self.registerAlias(raw_reg, lhs_ty); |
| 1334 | | 1333 | |
| 1335 | if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg }); | 1334 | if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg }); |
| 1336 | | 1335 | |
| ... | @@ -1344,7 +1343,7 @@ fn binOpRegister( | ... | @@ -1344,7 +1343,7 @@ fn binOpRegister( |
| 1344 | // order to guarantee that registers will have equal sizes, we | 1343 | // order to guarantee that registers will have equal sizes, we |
| 1345 | // use the register alias of rhs corresponding to the size of | 1344 | // use the register alias of rhs corresponding to the size of |
| 1346 | // lhs. | 1345 | // lhs. |
| 1347 | registerAlias(rhs.register, lhs_ty.abiSize(self.target.*)) | 1346 | self.registerAlias(rhs.register, lhs_ty) |
| 1348 | else blk: { | 1347 | else blk: { |
| 1349 | const track_inst: ?Air.Inst.Index = if (metadata) |md| inst: { | 1348 | const track_inst: ?Air.Inst.Index = if (metadata) |md| inst: { |
| 1350 | break :inst Air.refToIndex(md.rhs).?; | 1349 | break :inst Air.refToIndex(md.rhs).?; |
| ... | @@ -1354,7 +1353,7 @@ fn binOpRegister( | ... | @@ -1354,7 +1353,7 @@ fn binOpRegister( |
| 1354 | | 1353 | |
| 1355 | // Here, we deliberately use lhs as lhs and rhs may differ in | 1354 | // Here, we deliberately use lhs as lhs and rhs may differ in |
| 1356 | // the case of shifts. See comment above. | 1355 | // the case of shifts. See comment above. |
| 1357 | const reg = registerAlias(raw_reg, lhs_ty.abiSize(self.target.*)); | 1356 | const reg = self.registerAlias(raw_reg, lhs_ty); |
| 1358 | | 1357 | |
| 1359 | if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg }); | 1358 | if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg }); |
| 1360 | | 1359 | |
| ... | @@ -1372,11 +1371,11 @@ fn binOpRegister( | ... | @@ -1372,11 +1371,11 @@ fn binOpRegister( |
| 1372 | break :blk rhs_reg; | 1371 | break :blk rhs_reg; |
| 1373 | } else { | 1372 | } else { |
| 1374 | const raw_reg = try self.register_manager.allocReg(md.inst, gp); | 1373 | const raw_reg = try self.register_manager.allocReg(md.inst, gp); |
| 1375 | break :blk registerAlias(raw_reg, lhs_ty.abiSize(self.target.*)); | 1374 | break :blk self.registerAlias(raw_reg, lhs_ty); |
| 1376 | } | 1375 | } |
| 1377 | } else blk: { | 1376 | } else blk: { |
| 1378 | const raw_reg = try self.register_manager.allocReg(null, gp); | 1377 | const raw_reg = try self.register_manager.allocReg(null, gp); |
| 1379 | break :blk registerAlias(raw_reg, lhs_ty.abiSize(self.target.*)); | 1378 | break :blk self.registerAlias(raw_reg, lhs_ty); |
| 1380 | }, | 1379 | }, |
| 1381 | }; | 1380 | }; |
| 1382 | | 1381 | |
| ... | @@ -1415,7 +1414,7 @@ fn binOpRegister( | ... | @@ -1415,7 +1414,7 @@ fn binOpRegister( |
| 1415 | .smull, | 1414 | .smull, |
| 1416 | .umull, | 1415 | .umull, |
| 1417 | => .{ .rrr = .{ | 1416 | => .{ .rrr = .{ |
| 1418 | .rd = dest_reg.to64(), | 1417 | .rd = dest_reg.toX(), |
| 1419 | .rn = lhs_reg, | 1418 | .rn = lhs_reg, |
| 1420 | .rm = rhs_reg, | 1419 | .rm = rhs_reg, |
| 1421 | } }, | 1420 | } }, |
| ... | @@ -1463,7 +1462,7 @@ fn binOpImmediate( | ... | @@ -1463,7 +1462,7 @@ fn binOpImmediate( |
| 1463 | ) !MCValue { | 1462 | ) !MCValue { |
| 1464 | const lhs_is_register = lhs == .register; | 1463 | const lhs_is_register = lhs == .register; |
| 1465 | | 1464 | |
| 1466 | if (lhs_is_register) assert(lhs.register == registerAlias(lhs.register, lhs_ty.abiSize(self.target.*))); | 1465 | if (lhs_is_register) assert(lhs.register == self.registerAlias(lhs.register, lhs_ty)); |
| 1467 | | 1466 | |
| 1468 | const lhs_lock: ?RegisterLock = if (lhs_is_register) | 1467 | const lhs_lock: ?RegisterLock = if (lhs_is_register) |
| 1469 | self.register_manager.lockReg(lhs.register) | 1468 | self.register_manager.lockReg(lhs.register) |
| ... | @@ -1481,7 +1480,7 @@ fn binOpImmediate( | ... | @@ -1481,7 +1480,7 @@ fn binOpImmediate( |
| 1481 | } else null; | 1480 | } else null; |
| 1482 | | 1481 | |
| 1483 | const raw_reg = try self.register_manager.allocReg(track_inst, gp); | 1482 | const raw_reg = try self.register_manager.allocReg(track_inst, gp); |
| 1484 | const reg = registerAlias(raw_reg, lhs_ty.abiSize(self.target.*)); | 1483 | const reg = self.registerAlias(raw_reg, lhs_ty); |
| 1485 | | 1484 | |
| 1486 | if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg }); | 1485 | if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg }); |
| 1487 | | 1486 | |
| ... | @@ -1502,11 +1501,11 @@ fn binOpImmediate( | ... | @@ -1502,11 +1501,11 @@ fn binOpImmediate( |
| 1502 | break :blk lhs_reg; | 1501 | break :blk lhs_reg; |
| 1503 | } else { | 1502 | } else { |
| 1504 | const raw_reg = try self.register_manager.allocReg(md.inst, gp); | 1503 | const raw_reg = try self.register_manager.allocReg(md.inst, gp); |
| 1505 | break :blk registerAlias(raw_reg, lhs_ty.abiSize(self.target.*)); | 1504 | break :blk self.registerAlias(raw_reg, lhs_ty); |
| 1506 | } | 1505 | } |
| 1507 | } else blk: { | 1506 | } else blk: { |
| 1508 | const raw_reg = try self.register_manager.allocReg(null, gp); | 1507 | const raw_reg = try self.register_manager.allocReg(null, gp); |
| 1509 | break :blk registerAlias(raw_reg, lhs_ty.abiSize(self.target.*)); | 1508 | break :blk self.registerAlias(raw_reg, lhs_ty); |
| 1510 | }, | 1509 | }, |
| 1511 | }; | 1510 | }; |
| 1512 | | 1511 | |
| ... | @@ -1719,7 +1718,7 @@ fn binOp( | ... | @@ -1719,7 +1718,7 @@ fn binOp( |
| 1719 | } else null; | 1718 | } else null; |
| 1720 | | 1719 | |
| 1721 | const raw_reg = try self.register_manager.allocReg(track_inst, gp); | 1720 | const raw_reg = try self.register_manager.allocReg(track_inst, gp); |
| 1722 | const reg = registerAlias(raw_reg, lhs_ty.abiSize(self.target.*)); | 1721 | const reg = self.registerAlias(raw_reg, lhs_ty); |
| 1723 | | 1722 | |
| 1724 | if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg }); | 1723 | if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg }); |
| 1725 | | 1724 | |
| ... | @@ -1734,7 +1733,7 @@ fn binOp( | ... | @@ -1734,7 +1733,7 @@ fn binOp( |
| 1734 | } else null; | 1733 | } else null; |
| 1735 | | 1734 | |
| 1736 | const raw_reg = try self.register_manager.allocReg(track_inst, gp); | 1735 | const raw_reg = try self.register_manager.allocReg(track_inst, gp); |
| 1737 | const reg = registerAlias(raw_reg, rhs_ty.abiAlignment(self.target.*)); | 1736 | const reg = self.registerAlias(raw_reg, rhs_ty); |
| 1738 | | 1737 | |
| 1739 | if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg }); | 1738 | if (track_inst) |inst| branch.inst_table.putAssumeCapacity(inst, .{ .register = reg }); |
| 1740 | | 1739 | |
| ... | @@ -1745,10 +1744,9 @@ fn binOp( | ... | @@ -1745,10 +1744,9 @@ fn binOp( |
| 1745 | | 1744 | |
| 1746 | const dest_regs: [2]Register = blk: { | 1745 | const dest_regs: [2]Register = blk: { |
| 1747 | const raw_regs = try self.register_manager.allocRegs(2, .{ null, null }, gp); | 1746 | const raw_regs = try self.register_manager.allocRegs(2, .{ null, null }, gp); |
| 1748 | const abi_size = lhs_ty.abiSize(self.target.*); | | |
| 1749 | break :blk .{ | 1747 | break :blk .{ |
| 1750 | registerAlias(raw_regs[0], abi_size), | 1748 | self.registerAlias(raw_regs[0], lhs_ty), |
| 1751 | registerAlias(raw_regs[1], abi_size), | 1749 | self.registerAlias(raw_regs[1], lhs_ty), |
| 1752 | }; | 1750 | }; |
| 1753 | }; | 1751 | }; |
| 1754 | const dest_regs_locks = self.register_manager.lockRegsAssumeUnused(2, dest_regs); | 1752 | const dest_regs_locks = self.register_manager.lockRegsAssumeUnused(2, dest_regs); |
| ... | @@ -2067,7 +2065,7 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2067,7 +2065,7 @@ fn airOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 2067 | defer self.register_manager.unlockReg(dest_reg_lock); | 2065 | defer self.register_manager.unlockReg(dest_reg_lock); |
| 2068 | | 2066 | |
| 2069 | const raw_truncated_reg = try self.register_manager.allocReg(null, gp); | 2067 | const raw_truncated_reg = try self.register_manager.allocReg(null, gp); |
| 2070 | const truncated_reg = registerAlias(raw_truncated_reg, lhs_ty.abiSize(self.target.*)); | 2068 | const truncated_reg = self.registerAlias(raw_truncated_reg, lhs_ty); |
| 2071 | const truncated_reg_lock = self.register_manager.lockRegAssumeUnused(truncated_reg); | 2069 | const truncated_reg_lock = self.register_manager.lockRegAssumeUnused(truncated_reg); |
| 2072 | defer self.register_manager.unlockReg(truncated_reg_lock); | 2070 | defer self.register_manager.unlockReg(truncated_reg_lock); |
| 2073 | | 2071 | |
| ... | @@ -2186,8 +2184,8 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2186,8 +2184,8 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 2186 | defer self.register_manager.unlockReg(truncated_reg_lock); | 2184 | defer self.register_manager.unlockReg(truncated_reg_lock); |
| 2187 | | 2185 | |
| 2188 | try self.truncRegister( | 2186 | try self.truncRegister( |
| 2189 | dest_reg.to32(), | 2187 | dest_reg.toW(), |
| 2190 | truncated_reg.to32(), | 2188 | truncated_reg.toW(), |
| 2191 | int_info.signedness, | 2189 | int_info.signedness, |
| 2192 | int_info.bits, | 2190 | int_info.bits, |
| 2193 | ); | 2191 | ); |
| ... | @@ -2197,8 +2195,8 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2197,8 +2195,8 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 2197 | _ = try self.addInst(.{ | 2195 | _ = try self.addInst(.{ |
| 2198 | .tag = .cmp_extended_register, | 2196 | .tag = .cmp_extended_register, |
| 2199 | .data = .{ .rr_extend_shift = .{ | 2197 | .data = .{ .rr_extend_shift = .{ |
| 2200 | .rn = dest_reg.to64(), | 2198 | .rn = dest_reg.toX(), |
| 2201 | .rm = truncated_reg.to32(), | 2199 | .rm = truncated_reg.toW(), |
| 2202 | .ext_type = .sxtw, | 2200 | .ext_type = .sxtw, |
| 2203 | .imm3 = 0, | 2201 | .imm3 = 0, |
| 2204 | } }, | 2202 | } }, |
| ... | @@ -2208,8 +2206,8 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2208,8 +2206,8 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 2208 | _ = try self.addInst(.{ | 2206 | _ = try self.addInst(.{ |
| 2209 | .tag = .cmp_extended_register, | 2207 | .tag = .cmp_extended_register, |
| 2210 | .data = .{ .rr_extend_shift = .{ | 2208 | .data = .{ .rr_extend_shift = .{ |
| 2211 | .rn = dest_reg.to64(), | 2209 | .rn = dest_reg.toX(), |
| 2212 | .rm = truncated_reg.to32(), | 2210 | .rm = truncated_reg.toW(), |
| 2213 | .ext_type = .uxtw, | 2211 | .ext_type = .uxtw, |
| 2214 | .imm3 = 0, | 2212 | .imm3 = 0, |
| 2215 | } }, | 2213 | } }, |
| ... | @@ -2245,7 +2243,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2245,7 +2243,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 2245 | | 2243 | |
| 2246 | const lhs_reg = if (lhs_is_register) lhs.register else blk: { | 2244 | const lhs_reg = if (lhs_is_register) lhs.register else blk: { |
| 2247 | const raw_reg = try self.register_manager.allocReg(null, gp); | 2245 | const raw_reg = try self.register_manager.allocReg(null, gp); |
| 2248 | const reg = registerAlias(raw_reg, lhs_ty.abiSize(self.target.*)); | 2246 | const reg = self.registerAlias(raw_reg, lhs_ty); |
| 2249 | break :blk reg; | 2247 | break :blk reg; |
| 2250 | }; | 2248 | }; |
| 2251 | const new_lhs_lock = self.register_manager.lockReg(lhs_reg); | 2249 | const new_lhs_lock = self.register_manager.lockReg(lhs_reg); |
| ... | @@ -2253,7 +2251,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2253,7 +2251,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 2253 | | 2251 | |
| 2254 | const rhs_reg = if (rhs_is_register) rhs.register else blk: { | 2252 | const rhs_reg = if (rhs_is_register) rhs.register else blk: { |
| 2255 | const raw_reg = try self.register_manager.allocReg(null, gp); | 2253 | const raw_reg = try self.register_manager.allocReg(null, gp); |
| 2256 | const reg = registerAlias(raw_reg, rhs_ty.abiAlignment(self.target.*)); | 2254 | const reg = self.registerAlias(raw_reg, rhs_ty); |
| 2257 | break :blk reg; | 2255 | break :blk reg; |
| 2258 | }; | 2256 | }; |
| 2259 | const new_rhs_lock = self.register_manager.lockReg(rhs_reg); | 2257 | const new_rhs_lock = self.register_manager.lockReg(rhs_reg); |
| ... | @@ -2264,7 +2262,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2264,7 +2262,7 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 2264 | | 2262 | |
| 2265 | const dest_reg = blk: { | 2263 | const dest_reg = blk: { |
| 2266 | const raw_reg = try self.register_manager.allocReg(null, gp); | 2264 | const raw_reg = try self.register_manager.allocReg(null, gp); |
| 2267 | const reg = registerAlias(raw_reg, lhs_ty.abiSize(self.target.*)); | 2265 | const reg = self.registerAlias(raw_reg, lhs_ty); |
| 2268 | break :blk reg; | 2266 | break :blk reg; |
| 2269 | }; | 2267 | }; |
| 2270 | const dest_reg_lock = self.register_manager.lockRegAssumeUnused(dest_reg); | 2268 | const dest_reg_lock = self.register_manager.lockRegAssumeUnused(dest_reg); |
| ... | @@ -2853,7 +2851,13 @@ fn airUnaryMath(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -2853,7 +2851,13 @@ fn airUnaryMath(self: *Self, inst: Air.Inst.Index) !void { |
| 2853 | return self.finishAir(inst, result, .{ un_op, .none, .none }); | 2851 | return self.finishAir(inst, result, .{ un_op, .none, .none }); |
| 2854 | } | 2852 | } |
| 2855 | | 2853 | |
| 2856 | fn reuseOperand(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, op_index: Liveness.OperandInt, mcv: MCValue) bool { | 2854 | fn reuseOperand( |
| | 2855 | self: *Self, |
| | 2856 | inst: Air.Inst.Index, |
| | 2857 | operand: Air.Inst.Ref, |
| | 2858 | op_index: Liveness.OperandInt, |
| | 2859 | mcv: MCValue, |
| | 2860 | ) bool { |
| 2857 | if (!self.liveness.operandDies(inst, op_index)) | 2861 | if (!self.liveness.operandDies(inst, op_index)) |
| 2858 | return false; | 2862 | return false; |
| 2859 | | 2863 | |
| ... | @@ -2912,7 +2916,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo | ... | @@ -2912,7 +2916,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 2912 | .stack_offset => |off| { | 2916 | .stack_offset => |off| { |
| 2913 | if (elem_size <= 8) { | 2917 | if (elem_size <= 8) { |
| 2914 | const raw_tmp_reg = try self.register_manager.allocReg(null, gp); | 2918 | const raw_tmp_reg = try self.register_manager.allocReg(null, gp); |
| 2915 | const tmp_reg = registerAlias(raw_tmp_reg, elem_size); | 2919 | const tmp_reg = self.registerAlias(raw_tmp_reg, elem_ty); |
| 2916 | const tmp_reg_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); | 2920 | const tmp_reg_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 2917 | defer self.register_manager.unlockReg(tmp_reg_lock); | 2921 | defer self.register_manager.unlockReg(tmp_reg_lock); |
| 2918 | | 2922 | |
| ... | @@ -3050,7 +3054,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3050,7 +3054,7 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 3050 | if (elem_size <= 8 and self.reuseOperand(inst, ty_op.operand, 0, ptr)) { | 3054 | if (elem_size <= 8 and self.reuseOperand(inst, ty_op.operand, 0, ptr)) { |
| 3051 | // The MCValue that holds the pointer can be re-used as the value. | 3055 | // The MCValue that holds the pointer can be re-used as the value. |
| 3052 | break :blk switch (ptr) { | 3056 | break :blk switch (ptr) { |
| 3053 | .register => |r| MCValue{ .register = registerAlias(r, elem_size) }, | 3057 | .register => |reg| MCValue{ .register = self.registerAlias(reg, elem_ty) }, |
| 3054 | else => ptr, | 3058 | else => ptr, |
| 3055 | }; | 3059 | }; |
| 3056 | } else { | 3060 | } else { |
| ... | @@ -3136,7 +3140,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type | ... | @@ -3136,7 +3140,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 3136 | else => { | 3140 | else => { |
| 3137 | if (abi_size <= 8) { | 3141 | if (abi_size <= 8) { |
| 3138 | const raw_tmp_reg = try self.register_manager.allocReg(null, gp); | 3142 | const raw_tmp_reg = try self.register_manager.allocReg(null, gp); |
| 3139 | const tmp_reg = registerAlias(raw_tmp_reg, abi_size); | 3143 | const tmp_reg = self.registerAlias(raw_tmp_reg, value_ty); |
| 3140 | const tmp_reg_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); | 3144 | const tmp_reg_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 3141 | defer self.register_manager.unlockReg(tmp_reg_lock); | 3145 | defer self.register_manager.unlockReg(tmp_reg_lock); |
| 3142 | | 3146 | |
| ... | @@ -3295,7 +3299,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3295,7 +3299,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 3295 | } else { | 3299 | } else { |
| 3296 | // Copy to new register | 3300 | // Copy to new register |
| 3297 | const raw_dest_reg = try self.register_manager.allocReg(null, gp); | 3301 | const raw_dest_reg = try self.register_manager.allocReg(null, gp); |
| 3298 | const dest_reg = registerAlias(raw_dest_reg, struct_field_ty.abiSize(self.target.*)); | 3302 | const dest_reg = self.registerAlias(raw_dest_reg, struct_field_ty); |
| 3299 | try self.genSetReg(struct_field_ty, dest_reg, field); | 3303 | try self.genSetReg(struct_field_ty, dest_reg, field); |
| 3300 | | 3304 | |
| 3301 | break :result MCValue{ .register = dest_reg }; | 3305 | break :result MCValue{ .register = dest_reg }; |
| ... | @@ -3410,9 +3414,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. | ... | @@ -3410,9 +3414,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallOptions. |
| 3410 | const ret_abi_align = @intCast(u32, ret_ty.abiAlignment(self.target.*)); | 3414 | const ret_abi_align = @intCast(u32, ret_ty.abiAlignment(self.target.*)); |
| 3411 | const stack_offset = try self.allocMem(inst, ret_abi_size, ret_abi_align); | 3415 | const stack_offset = try self.allocMem(inst, ret_abi_size, ret_abi_align); |
| 3412 | | 3416 | |
| 3413 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); | 3417 | const ret_ptr_reg = self.registerAlias(.x0, Type.usize); |
| 3414 | const ptr_bytes = @divExact(ptr_bits, 8); | | |
| 3415 | const ret_ptr_reg = registerAlias(.x0, ptr_bytes); | | |
| 3416 | | 3418 | |
| 3417 | var ptr_ty_payload: Type.Payload.ElemType = .{ | 3419 | var ptr_ty_payload: Type.Payload.ElemType = .{ |
| 3418 | .base = .{ .tag = .single_mut_pointer }, | 3420 | .base = .{ .tag = .single_mut_pointer }, |
| ... | @@ -4376,7 +4378,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro | ... | @@ -4376,7 +4378,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 4376 | 4, 8 => .str_stack, | 4378 | 4, 8 => .str_stack, |
| 4377 | else => unreachable, // unexpected abi size | 4379 | else => unreachable, // unexpected abi size |
| 4378 | }; | 4380 | }; |
| 4379 | const rt = registerAlias(reg, abi_size); | 4381 | const rt = self.registerAlias(reg, ty); |
| 4380 | | 4382 | |
| 4381 | _ = try self.addInst(.{ | 4383 | _ = try self.addInst(.{ |
| 4382 | .tag = tag, | 4384 | .tag = tag, |
| ... | @@ -4399,10 +4401,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro | ... | @@ -4399,10 +4401,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 4399 | const overflow_bit_ty = ty.structFieldType(1); | 4401 | const overflow_bit_ty = ty.structFieldType(1); |
| 4400 | const overflow_bit_offset = @intCast(u32, ty.structFieldOffset(1, self.target.*)); | 4402 | const overflow_bit_offset = @intCast(u32, ty.structFieldOffset(1, self.target.*)); |
| 4401 | const raw_cond_reg = try self.register_manager.allocReg(null, gp); | 4403 | const raw_cond_reg = try self.register_manager.allocReg(null, gp); |
| 4402 | const cond_reg = registerAlias( | 4404 | const cond_reg = self.registerAlias(raw_cond_reg, overflow_bit_ty); |
| 4403 | raw_cond_reg, | | |
| 4404 | @intCast(u32, overflow_bit_ty.abiSize(self.target.*)), | | |
| 4405 | ); | | |
| 4406 | | 4405 | |
| 4407 | _ = try self.addInst(.{ | 4406 | _ = try self.addInst(.{ |
| 4408 | .tag = .cset, | 4407 | .tag = .cset, |
| ... | @@ -4599,8 +4598,8 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void | ... | @@ -4599,8 +4598,8 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 4599 | .memory => |addr| { | 4598 | .memory => |addr| { |
| 4600 | // The value is in memory at a hard-coded address. | 4599 | // The value is in memory at a hard-coded address. |
| 4601 | // If the type is a pointer, it means the pointer address is at this memory location. | 4600 | // If the type is a pointer, it means the pointer address is at this memory location. |
| 4602 | try self.genSetReg(ty, reg.to64(), .{ .immediate = addr }); | 4601 | try self.genSetReg(ty, reg.toX(), .{ .immediate = addr }); |
| 4603 | try self.genLdrRegister(reg, reg.to64(), ty); | 4602 | try self.genLdrRegister(reg, reg.toX(), ty); |
| 4604 | }, | 4603 | }, |
| 4605 | .stack_offset => |off| { | 4604 | .stack_offset => |off| { |
| 4606 | const abi_size = ty.abiSize(self.target.*); | 4605 | const abi_size = ty.abiSize(self.target.*); |
| ... | @@ -4679,7 +4678,7 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I | ... | @@ -4679,7 +4678,7 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I |
| 4679 | 4, 8 => .str_immediate, | 4678 | 4, 8 => .str_immediate, |
| 4680 | else => unreachable, // unexpected abi size | 4679 | else => unreachable, // unexpected abi size |
| 4681 | }; | 4680 | }; |
| 4682 | const rt = registerAlias(reg, abi_size); | 4681 | const rt = self.registerAlias(reg, ty); |
| 4683 | const offset = switch (abi_size) { | 4682 | const offset = switch (abi_size) { |
| 4684 | 1 => blk: { | 4683 | 1 => blk: { |
| 4685 | if (math.cast(u12, stack_offset)) |imm| { | 4684 | if (math.cast(u12, stack_offset)) |imm| { |
| ... | @@ -5300,7 +5299,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { | ... | @@ -5300,7 +5299,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { |
| 5300 | assert(ret_ty.isError()); | 5299 | assert(ret_ty.isError()); |
| 5301 | result.return_value = .{ .immediate = 0 }; | 5300 | result.return_value = .{ .immediate = 0 }; |
| 5302 | } else if (ret_ty_size <= 8) { | 5301 | } else if (ret_ty_size <= 8) { |
| 5303 | result.return_value = .{ .register = registerAlias(c_abi_int_return_regs[0], ret_ty_size) }; | 5302 | result.return_value = .{ .register = self.registerAlias(c_abi_int_return_regs[0], ret_ty) }; |
| 5304 | } else { | 5303 | } else { |
| 5305 | return self.fail("TODO support more return types for ARM backend", .{}); | 5304 | return self.fail("TODO support more return types for ARM backend", .{}); |
| 5306 | } | 5305 | } |
| ... | @@ -5322,7 +5321,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { | ... | @@ -5322,7 +5321,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { |
| 5322 | | 5321 | |
| 5323 | if (std.math.divCeil(u32, param_size, 8) catch unreachable <= 8 - ncrn) { | 5322 | if (std.math.divCeil(u32, param_size, 8) catch unreachable <= 8 - ncrn) { |
| 5324 | if (param_size <= 8) { | 5323 | if (param_size <= 8) { |
| 5325 | result.args[i] = .{ .register = registerAlias(c_abi_int_param_regs[ncrn], param_size) }; | 5324 | result.args[i] = .{ .register = self.registerAlias(c_abi_int_param_regs[ncrn], ty) }; |
| 5326 | ncrn += 1; | 5325 | ncrn += 1; |
| 5327 | } else { | 5326 | } else { |
| 5328 | return self.fail("TODO MCValues with multiple registers", .{}); | 5327 | return self.fail("TODO MCValues with multiple registers", .{}); |
| ... | @@ -5358,7 +5357,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { | ... | @@ -5358,7 +5357,7 @@ fn resolveCallingConventionValues(self: *Self, fn_ty: Type) !CallMCValues { |
| 5358 | assert(ret_ty.isError()); | 5357 | assert(ret_ty.isError()); |
| 5359 | result.return_value = .{ .immediate = 0 }; | 5358 | result.return_value = .{ .immediate = 0 }; |
| 5360 | } else if (ret_ty_size <= 8) { | 5359 | } else if (ret_ty_size <= 8) { |
| 5361 | result.return_value = .{ .register = registerAlias(.x0, ret_ty_size) }; | 5360 | result.return_value = .{ .register = self.registerAlias(.x0, ret_ty) }; |
| 5362 | } else { | 5361 | } else { |
| 5363 | // The result is returned by reference, not by | 5362 | // The result is returned by reference, not by |
| 5364 | // value. This means that x0 (or w0 when pointer | 5363 | // value. This means that x0 (or w0 when pointer |
| ... | @@ -5424,14 +5423,30 @@ fn parseRegName(name: []const u8) ?Register { | ... | @@ -5424,14 +5423,30 @@ fn parseRegName(name: []const u8) ?Register { |
| 5424 | return std.meta.stringToEnum(Register, name); | 5423 | return std.meta.stringToEnum(Register, name); |
| 5425 | } | 5424 | } |
| 5426 | | 5425 | |
| 5427 | fn registerAlias(reg: Register, size_bytes: u64) Register { | 5426 | fn registerAlias(self: *Self, reg: Register, ty: Type) Register { |
| 5428 | if (size_bytes == 0) { | 5427 | const abi_size = ty.abiSize(self.target.*); |
| 5429 | unreachable; // should be comptime-known | 5428 | |
| 5430 | } else if (size_bytes <= 4) { | 5429 | switch (reg.class()) { |
| 5431 | return reg.to32(); | 5430 | .general_purpose => { |
| 5432 | } else if (size_bytes <= 8) { | 5431 | if (abi_size == 0) { |
| 5433 | return reg.to64(); | 5432 | unreachable; // should be comptime-known |
| 5434 | } else { | 5433 | } else if (abi_size <= 4) { |
| 5435 | unreachable; // TODO handle floating-point registers | 5434 | return reg.toW(); |
| | 5435 | } else if (abi_size <= 8) { |
| | 5436 | return reg.toX(); |
| | 5437 | } else unreachable; |
| | 5438 | }, |
| | 5439 | .stack_pointer => unreachable, // we can't store/load the sp |
| | 5440 | .floating_point => { |
| | 5441 | return switch (ty.floatBits(self.target.*)) { |
| | 5442 | 16 => reg.toH(), |
| | 5443 | 32 => reg.toS(), |
| | 5444 | 64 => reg.toD(), |
| | 5445 | 128 => reg.toQ(), |
| | 5446 | |
| | 5447 | 80 => unreachable, // f80 registers don't exist |
| | 5448 | else => unreachable, |
| | 5449 | }; |
| | 5450 | }, |
| 5436 | } | 5451 | } |
| 5437 | } | 5452 | } |