| ... | ... | @@ -47,10 +47,6 @@ const RegisterManager = abi.RegisterManager; |
| 47 | 47 | const RegisterLock = RegisterManager.RegisterLock; |
| 48 | 48 | const FrameIndex = bits.FrameIndex; |
| 49 | 49 | |
| 50 | | const gp = abi.RegisterClass.gp; |
| 51 | | const x87 = abi.RegisterClass.x87; |
| 52 | | const sse = abi.RegisterClass.sse; |
| 53 | | |
| 54 | 50 | const InnerError = CodeGenError || error{OutOfRegisters}; |
| 55 | 51 | |
| 56 | 52 | gpa: Allocator, |
| ... | ... | @@ -620,6 +616,7 @@ const InstTracking = struct { |
| 620 | 616 | } |
| 621 | 617 | |
| 622 | 618 | fn die(self: *InstTracking, function: *Self, inst: Air.Inst.Index) !void { |
| 619 | if (self.short == .dead) return; |
| 623 | 620 | try function.freeValue(self.short); |
| 624 | 621 | self.short = .{ .dead = function.scope_generation }; |
| 625 | 622 | tracking_log.debug("%{d} => {} (death)", .{ inst, self.* }); |
| ... | ... | @@ -635,6 +632,40 @@ const InstTracking = struct { |
| 635 | 632 | tracking_log.debug("%{d} => {} (reuse %{d})", .{ new_inst, self.*, old_inst }); |
| 636 | 633 | } |
| 637 | 634 | |
| 635 | fn liveOut(self: *InstTracking, function: *Self, inst: Air.Inst.Index) void { |
| 636 | for (self.short.getRegs()) |reg| { |
| 637 | if (function.register_manager.isRegFree(reg)) { |
| 638 | tracking_log.debug("%{d} => {} (live-out)", .{ inst, self.* }); |
| 639 | continue; |
| 640 | } |
| 641 | |
| 642 | const index = RegisterManager.indexOfRegIntoTracked(reg).?; |
| 643 | const tracked_inst = function.register_manager.registers[index]; |
| 644 | const tracking = function.getResolvedInstValue(tracked_inst); |
| 645 | |
| 646 | // Disable death. |
| 647 | var found_reg = false; |
| 648 | var remaining_reg: Register = .none; |
| 649 | for (tracking.short.getRegs()) |tracked_reg| if (tracked_reg.id() == reg.id()) { |
| 650 | assert(!found_reg); |
| 651 | found_reg = true; |
| 652 | } else { |
| 653 | assert(remaining_reg == .none); |
| 654 | remaining_reg = tracked_reg; |
| 655 | }; |
| 656 | assert(found_reg); |
| 657 | tracking.short = switch (remaining_reg) { |
| 658 | .none => .{ .dead = function.scope_generation }, |
| 659 | else => .{ .register = remaining_reg }, |
| 660 | }; |
| 661 | |
| 662 | // Perform side-effects of freeValue manually. |
| 663 | function.register_manager.freeReg(reg); |
| 664 | |
| 665 | tracking_log.debug("%{d} => {} (live-out %{d})", .{ inst, self.*, tracked_inst }); |
| 666 | } |
| 667 | } |
| 668 | |
| 638 | 669 | pub fn format( |
| 639 | 670 | self: InstTracking, |
| 640 | 671 | comptime _: []const u8, |
| ... | ... | @@ -1144,7 +1175,7 @@ fn asmSetccRegister(self: *Self, reg: Register, cc: bits.Condition) !void { |
| 1144 | 1175 | } }, |
| 1145 | 1176 | .z_and_np, .nz_or_p => .{ .rr = .{ |
| 1146 | 1177 | .r1 = reg, |
| 1147 | | .r2 = (try self.register_manager.allocReg(null, gp)).to8(), |
| 1178 | .r2 = (try self.register_manager.allocReg(null, abi.RegisterClass.gp)).to8(), |
| 1148 | 1179 | } }, |
| 1149 | 1180 | }, |
| 1150 | 1181 | }); |
| ... | ... | @@ -1184,7 +1215,7 @@ fn asmSetccMemory(self: *Self, m: Memory, cc: bits.Condition) !void { |
| 1184 | 1215 | .payload = payload, |
| 1185 | 1216 | } }, |
| 1186 | 1217 | .z_and_np, .nz_or_p => .{ .rx = .{ |
| 1187 | | .r1 = (try self.register_manager.allocReg(null, gp)).to8(), |
| 1218 | .r1 = (try self.register_manager.allocReg(null, abi.RegisterClass.gp)).to8(), |
| 1188 | 1219 | .payload = payload, |
| 1189 | 1220 | } }, |
| 1190 | 1221 | }, |
| ... | ... | @@ -2087,7 +2118,7 @@ fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void { |
| 2087 | 2118 | var exitlude_jump_relocs = try self.gpa.alloc(u32, enum_ty.enumFieldCount(mod)); |
| 2088 | 2119 | defer self.gpa.free(exitlude_jump_relocs); |
| 2089 | 2120 | |
| 2090 | | const data_reg = try self.register_manager.allocReg(null, gp); |
| 2121 | const data_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp); |
| 2091 | 2122 | const data_lock = self.register_manager.lockRegAssumeUnused(data_reg); |
| 2092 | 2123 | defer self.register_manager.unlockReg(data_lock); |
| 2093 | 2124 | try self.genLazySymbolRef(.lea, data_reg, .{ .kind = .const_data, .ty = enum_ty }); |
| ... | ... | @@ -2357,7 +2388,7 @@ fn allocRegOrMemAdvanced(self: *Self, ty: Type, inst: ?Air.Inst.Index, reg_ok: b |
| 2357 | 2388 | }, |
| 2358 | 2389 | else => 8, |
| 2359 | 2390 | })) { |
| 2360 | | if (self.register_manager.tryAllocReg(inst, regClassForType(ty, mod))) |reg| { |
| 2391 | if (self.register_manager.tryAllocReg(inst, self.regClassForType(ty))) |reg| { |
| 2361 | 2392 | return MCValue{ .register = registerAlias(reg, abi_size) }; |
| 2362 | 2393 | } |
| 2363 | 2394 | } |
| ... | ... | @@ -2367,10 +2398,15 @@ fn allocRegOrMemAdvanced(self: *Self, ty: Type, inst: ?Air.Inst.Index, reg_ok: b |
| 2367 | 2398 | return .{ .load_frame = .{ .index = frame_index } }; |
| 2368 | 2399 | } |
| 2369 | 2400 | |
| 2370 | | fn regClassForType(ty: Type, mod: *Module) RegisterManager.RegisterBitSet { |
| 2401 | fn regClassForType(self: *Self, ty: Type) RegisterManager.RegisterBitSet { |
| 2402 | const mod = self.bin_file.options.module.?; |
| 2371 | 2403 | return switch (ty.zigTypeTag(mod)) { |
| 2372 | | .Float, .Vector => sse, |
| 2373 | | else => gp, |
| 2404 | .Float => switch (ty.floatBits(self.target.*)) { |
| 2405 | 80 => abi.RegisterClass.x87, |
| 2406 | else => abi.RegisterClass.sse, |
| 2407 | }, |
| 2408 | .Vector => abi.RegisterClass.sse, |
| 2409 | else => abi.RegisterClass.gp, |
| 2374 | 2410 | }; |
| 2375 | 2411 | } |
| 2376 | 2412 | |
| ... | ... | @@ -2510,8 +2546,7 @@ pub fn spillRegisters(self: *Self, registers: []const Register) !void { |
| 2510 | 2546 | /// allocated. A second call to `copyToTmpRegister` may return the same register. |
| 2511 | 2547 | /// This can have a side effect of spilling instructions to the stack to free up a register. |
| 2512 | 2548 | fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register { |
| 2513 | | const mod = self.bin_file.options.module.?; |
| 2514 | | const reg = try self.register_manager.allocReg(null, regClassForType(ty, mod)); |
| 2549 | const reg = try self.register_manager.allocReg(null, self.regClassForType(ty)); |
| 2515 | 2550 | try self.genSetReg(reg, ty, mcv); |
| 2516 | 2551 | return reg; |
| 2517 | 2552 | } |
| ... | ... | @@ -2526,8 +2561,7 @@ fn copyToRegisterWithInstTracking( |
| 2526 | 2561 | ty: Type, |
| 2527 | 2562 | mcv: MCValue, |
| 2528 | 2563 | ) !MCValue { |
| 2529 | | const mod = self.bin_file.options.module.?; |
| 2530 | | const reg: Register = try self.register_manager.allocReg(reg_owner, regClassForType(ty, mod)); |
| 2564 | const reg: Register = try self.register_manager.allocReg(reg_owner, self.regClassForType(ty)); |
| 2531 | 2565 | try self.genSetReg(reg, ty, mcv); |
| 2532 | 2566 | return MCValue{ .register = reg }; |
| 2533 | 2567 | } |
| ... | ... | @@ -3084,7 +3118,7 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void { |
| 3084 | 3118 | }; |
| 3085 | 3119 | defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock); |
| 3086 | 3120 | |
| 3087 | | const limit_reg = try self.register_manager.allocReg(null, gp); |
| 3121 | const limit_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp); |
| 3088 | 3122 | const limit_mcv = MCValue{ .register = limit_reg }; |
| 3089 | 3123 | const limit_lock = self.register_manager.lockRegAssumeUnused(limit_reg); |
| 3090 | 3124 | defer self.register_manager.unlockReg(limit_lock); |
| ... | ... | @@ -3167,7 +3201,7 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void { |
| 3167 | 3201 | }; |
| 3168 | 3202 | defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock); |
| 3169 | 3203 | |
| 3170 | | const limit_reg = try self.register_manager.allocReg(null, gp); |
| 3204 | const limit_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp); |
| 3171 | 3205 | const limit_mcv = MCValue{ .register = limit_reg }; |
| 3172 | 3206 | const limit_lock = self.register_manager.lockRegAssumeUnused(limit_reg); |
| 3173 | 3207 | defer self.register_manager.unlockReg(limit_lock); |
| ... | ... | @@ -3245,7 +3279,7 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void { |
| 3245 | 3279 | }; |
| 3246 | 3280 | defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock); |
| 3247 | 3281 | |
| 3248 | | const limit_reg = try self.register_manager.allocReg(null, gp); |
| 3282 | const limit_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp); |
| 3249 | 3283 | const limit_mcv = MCValue{ .register = limit_reg }; |
| 3250 | 3284 | const limit_lock = self.register_manager.lockRegAssumeUnused(limit_reg); |
| 3251 | 3285 | defer self.register_manager.unlockReg(limit_lock); |
| ... | ... | @@ -3433,7 +3467,8 @@ fn genSetFrameTruncatedOverflowCompare( |
| 3433 | 3467 | |
| 3434 | 3468 | const rest_ty = try mod.intType(.unsigned, int_info.bits - hi_limb_bits); |
| 3435 | 3469 | |
| 3436 | | const temp_regs = try self.register_manager.allocRegs(3, .{ null, null, null }, gp); |
| 3470 | const temp_regs = |
| 3471 | try self.register_manager.allocRegs(3, .{ null, null, null }, abi.RegisterClass.gp); |
| 3437 | 3472 | const temp_locks = self.register_manager.lockRegsAssumeUnused(3, temp_regs); |
| 3438 | 3473 | defer for (temp_locks) |lock| self.register_manager.unlockReg(lock); |
| 3439 | 3474 | |
| ... | ... | @@ -3851,7 +3886,7 @@ fn airUnwrapErrUnionErrPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 3851 | 3886 | const src_lock = self.register_manager.lockRegAssumeUnused(src_reg); |
| 3852 | 3887 | defer self.register_manager.unlockReg(src_lock); |
| 3853 | 3888 | |
| 3854 | | const dst_reg = try self.register_manager.allocReg(inst, gp); |
| 3889 | const dst_reg = try self.register_manager.allocReg(inst, abi.RegisterClass.gp); |
| 3855 | 3890 | const dst_mcv = MCValue{ .register = dst_reg }; |
| 3856 | 3891 | const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg); |
| 3857 | 3892 | defer self.register_manager.unlockReg(dst_lock); |
| ... | ... | @@ -3891,7 +3926,7 @@ fn airUnwrapErrUnionPayloadPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 3891 | 3926 | const dst_reg = if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) |
| 3892 | 3927 | src_reg |
| 3893 | 3928 | else |
| 3894 | | try self.register_manager.allocReg(inst, gp); |
| 3929 | try self.register_manager.allocReg(inst, abi.RegisterClass.gp); |
| 3895 | 3930 | const dst_mcv = MCValue{ .register = dst_reg }; |
| 3896 | 3931 | const dst_lock = self.register_manager.lockReg(dst_reg); |
| 3897 | 3932 | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); |
| ... | ... | @@ -3942,7 +3977,7 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { |
| 3942 | 3977 | const dst_reg = if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) |
| 3943 | 3978 | src_reg |
| 3944 | 3979 | else |
| 3945 | | try self.register_manager.allocReg(inst, gp); |
| 3980 | try self.register_manager.allocReg(inst, abi.RegisterClass.gp); |
| 3946 | 3981 | const dst_lock = self.register_manager.lockReg(dst_reg); |
| 3947 | 3982 | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); |
| 3948 | 3983 | |
| ... | ... | @@ -4115,7 +4150,7 @@ fn airPtrSliceLenPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 4115 | 4150 | const dst_reg = if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) |
| 4116 | 4151 | src_reg |
| 4117 | 4152 | else |
| 4118 | | try self.register_manager.allocReg(inst, gp); |
| 4153 | try self.register_manager.allocReg(inst, abi.RegisterClass.gp); |
| 4119 | 4154 | const dst_mcv = MCValue{ .register = dst_reg }; |
| 4120 | 4155 | const dst_lock = self.register_manager.lockReg(dst_reg); |
| 4121 | 4156 | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); |
| ... | ... | @@ -4152,7 +4187,7 @@ fn elemOffset(self: *Self, index_ty: Type, index: MCValue, elem_size: u64) !Regi |
| 4152 | 4187 | .immediate => |imm| { |
| 4153 | 4188 | // Optimisation: if index MCValue is an immediate, we can multiply in `comptime` |
| 4154 | 4189 | // and set the register directly to the scaled offset as an immediate. |
| 4155 | | const reg = try self.register_manager.allocReg(null, gp); |
| 4190 | const reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp); |
| 4156 | 4191 | try self.genSetReg(reg, index_ty, .{ .immediate = imm * elem_size }); |
| 4157 | 4192 | break :blk reg; |
| 4158 | 4193 | }, |
| ... | ... | @@ -4192,7 +4227,7 @@ fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue { |
| 4192 | 4227 | const offset_reg_lock = self.register_manager.lockRegAssumeUnused(offset_reg); |
| 4193 | 4228 | defer self.register_manager.unlockReg(offset_reg_lock); |
| 4194 | 4229 | |
| 4195 | | const addr_reg = try self.register_manager.allocReg(null, gp); |
| 4230 | const addr_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp); |
| 4196 | 4231 | try self.genSetReg(addr_reg, Type.usize, slice_mcv); |
| 4197 | 4232 | // TODO we could allocate register here, but need to expect addr register and potentially |
| 4198 | 4233 | // offset register. |
| ... | ... | @@ -4249,7 +4284,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 4249 | 4284 | const offset_reg_lock = self.register_manager.lockRegAssumeUnused(offset_reg); |
| 4250 | 4285 | defer self.register_manager.unlockReg(offset_reg_lock); |
| 4251 | 4286 | |
| 4252 | | const addr_reg = try self.register_manager.allocReg(null, gp); |
| 4287 | const addr_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp); |
| 4253 | 4288 | switch (array) { |
| 4254 | 4289 | .register => { |
| 4255 | 4290 | const frame_index = try self.allocFrameIndex(FrameAlloc.initType(array_ty, mod)); |
| ... | ... | @@ -4486,7 +4521,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void { |
| 4486 | 4521 | }; |
| 4487 | 4522 | defer if (mat_src_lock) |lock| self.register_manager.unlockReg(lock); |
| 4488 | 4523 | |
| 4489 | | const dst_reg = try self.register_manager.allocReg(inst, gp); |
| 4524 | const dst_reg = try self.register_manager.allocReg(inst, abi.RegisterClass.gp); |
| 4490 | 4525 | const dst_mcv = MCValue{ .register = dst_reg }; |
| 4491 | 4526 | const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg); |
| 4492 | 4527 | defer self.register_manager.unlockReg(dst_lock); |
| ... | ... | @@ -4510,7 +4545,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void { |
| 4510 | 4545 | try self.genBinOpMir(.{ ._, .sub }, dst_ty, dst_mcv, .{ .immediate = extra_bits }); |
| 4511 | 4546 | } |
| 4512 | 4547 | } else if (src_bits <= 128) { |
| 4513 | | const tmp_reg = try self.register_manager.allocReg(null, gp); |
| 4548 | const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp); |
| 4514 | 4549 | const tmp_mcv = MCValue{ .register = tmp_reg }; |
| 4515 | 4550 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 4516 | 4551 | defer self.register_manager.unlockReg(tmp_lock); |
| ... | ... | @@ -4616,7 +4651,7 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void { |
| 4616 | 4651 | }; |
| 4617 | 4652 | defer if (mat_src_lock) |lock| self.register_manager.unlockReg(lock); |
| 4618 | 4653 | |
| 4619 | | const dst_reg = try self.register_manager.allocReg(inst, gp); |
| 4654 | const dst_reg = try self.register_manager.allocReg(inst, abi.RegisterClass.gp); |
| 4620 | 4655 | const dst_mcv = MCValue{ .register = dst_reg }; |
| 4621 | 4656 | const dst_lock = self.register_manager.lockReg(dst_reg); |
| 4622 | 4657 | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); |
| ... | ... | @@ -4643,7 +4678,7 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void { |
| 4643 | 4678 | } else mat_src_mcv; |
| 4644 | 4679 | try self.genBinOpMir(.{ ._, .tzcnt }, wide_ty, dst_mcv, masked_mcv); |
| 4645 | 4680 | } else if (src_bits <= 128) { |
| 4646 | | const tmp_reg = try self.register_manager.allocReg(null, gp); |
| 4681 | const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp); |
| 4647 | 4682 | const tmp_mcv = MCValue{ .register = tmp_reg }; |
| 4648 | 4683 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 4649 | 4684 | defer self.register_manager.unlockReg(tmp_lock); |
| ... | ... | @@ -4718,7 +4753,7 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void { |
| 4718 | 4753 | if (src_mcv.isRegister() and self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) |
| 4719 | 4754 | src_mcv |
| 4720 | 4755 | else |
| 4721 | | .{ .register = try self.register_manager.allocReg(inst, gp) }; |
| 4756 | .{ .register = try self.register_manager.allocReg(inst, abi.RegisterClass.gp) }; |
| 4722 | 4757 | |
| 4723 | 4758 | const popcnt_ty = if (src_abi_size > 1) src_ty else Type.u16; |
| 4724 | 4759 | try self.genBinOpMir(.{ ._, .popcnt }, popcnt_ty, dst_mcv, mat_src_mcv); |
| ... | ... | @@ -4739,7 +4774,7 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void { |
| 4739 | 4774 | const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg); |
| 4740 | 4775 | defer self.register_manager.unlockReg(dst_lock); |
| 4741 | 4776 | |
| 4742 | | const tmp_reg = try self.register_manager.allocReg(null, gp); |
| 4777 | const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp); |
| 4743 | 4778 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 4744 | 4779 | defer self.register_manager.unlockReg(tmp_lock); |
| 4745 | 4780 | |
| ... | ... | @@ -4747,7 +4782,7 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void { |
| 4747 | 4782 | const dst = registerAlias(dst_reg, src_abi_size); |
| 4748 | 4783 | const tmp = registerAlias(tmp_reg, src_abi_size); |
| 4749 | 4784 | const imm = if (src_abi_size > 4) |
| 4750 | | try self.register_manager.allocReg(null, gp) |
| 4785 | try self.register_manager.allocReg(null, abi.RegisterClass.gp) |
| 4751 | 4786 | else |
| 4752 | 4787 | undefined; |
| 4753 | 4788 | |
| ... | ... | @@ -4848,7 +4883,7 @@ fn byteSwap(self: *Self, inst: Air.Inst.Index, src_ty: Type, src_mcv: MCValue, m |
| 4848 | 4883 | const dst_mcv: MCValue = if (mem_ok) |
| 4849 | 4884 | try self.allocRegOrMem(inst, true) |
| 4850 | 4885 | else |
| 4851 | | .{ .register = try self.register_manager.allocReg(inst, gp) }; |
| 4886 | .{ .register = try self.register_manager.allocReg(inst, abi.RegisterClass.gp) }; |
| 4852 | 4887 | if (dst_mcv.isRegister()) { |
| 4853 | 4888 | const dst_lock = self.register_manager.lockRegAssumeUnused(dst_mcv.register); |
| 4854 | 4889 | defer self.register_manager.unlockReg(dst_lock); |
| ... | ... | @@ -4863,7 +4898,7 @@ fn byteSwap(self: *Self, inst: Air.Inst.Index, src_ty: Type, src_mcv: MCValue, m |
| 4863 | 4898 | return dst_mcv; |
| 4864 | 4899 | } |
| 4865 | 4900 | |
| 4866 | | const dst_reg = try self.register_manager.allocReg(inst, gp); |
| 4901 | const dst_reg = try self.register_manager.allocReg(inst, abi.RegisterClass.gp); |
| 4867 | 4902 | const dst_mcv = MCValue{ .register = dst_reg }; |
| 4868 | 4903 | const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg); |
| 4869 | 4904 | defer self.register_manager.unlockReg(dst_lock); |
| ... | ... | @@ -4906,7 +4941,7 @@ fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void { |
| 4906 | 4941 | const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg); |
| 4907 | 4942 | defer self.register_manager.unlockReg(dst_lock); |
| 4908 | 4943 | |
| 4909 | | const tmp_reg = try self.register_manager.allocReg(null, gp); |
| 4944 | const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp); |
| 4910 | 4945 | const tmp_lock = self.register_manager.lockReg(tmp_reg); |
| 4911 | 4946 | defer if (tmp_lock) |lock| self.register_manager.unlockReg(lock); |
| 4912 | 4947 | |
| ... | ... | @@ -4914,7 +4949,7 @@ fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void { |
| 4914 | 4949 | const dst = registerAlias(dst_reg, src_abi_size); |
| 4915 | 4950 | const tmp = registerAlias(tmp_reg, src_abi_size); |
| 4916 | 4951 | const imm = if (src_abi_size > 4) |
| 4917 | | try self.register_manager.allocReg(null, gp) |
| 4952 | try self.register_manager.allocReg(null, abi.RegisterClass.gp) |
| 4918 | 4953 | else |
| 4919 | 4954 | undefined; |
| 4920 | 4955 | |
| ... | ... | @@ -5006,109 +5041,133 @@ fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void { |
| 5006 | 5041 | fn floatSign(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, ty: Type) !void { |
| 5007 | 5042 | const mod = self.bin_file.options.module.?; |
| 5008 | 5043 | const tag = self.air.instructions.items(.tag)[inst]; |
| 5009 | | const abi_size: u32 = switch (ty.abiSize(mod)) { |
| 5010 | | 1...16 => 16, |
| 5011 | | 17...32 => 32, |
| 5012 | | else => return self.fail("TODO implement floatSign for {}", .{ |
| 5013 | | ty.fmt(mod), |
| 5014 | | }), |
| 5015 | | }; |
| 5016 | | const scalar_bits = ty.scalarType(mod).floatBits(self.target.*); |
| 5017 | | if (scalar_bits == 80) return self.fail("TODO implement floatSign for {}", .{ |
| 5018 | | ty.fmt(mod), |
| 5019 | | }); |
| 5020 | 5044 | |
| 5021 | | const src_mcv = try self.resolveInst(operand); |
| 5022 | | const src_lock = if (src_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null; |
| 5023 | | defer if (src_lock) |lock| self.register_manager.unlockReg(lock); |
| 5045 | const result = result: { |
| 5046 | const scalar_bits = ty.scalarType(mod).floatBits(self.target.*); |
| 5047 | if (scalar_bits == 80) { |
| 5048 | if (ty.zigTypeTag(mod) != .Float) return self.fail("TODO implement floatSign for {}", .{ |
| 5049 | ty.fmt(mod), |
| 5050 | }); |
| 5024 | 5051 | |
| 5025 | | const dst_mcv: MCValue = if (src_mcv.isRegister() and self.reuseOperand(inst, operand, 0, src_mcv)) |
| 5026 | | src_mcv |
| 5027 | | else if (self.hasFeature(.avx)) |
| 5028 | | .{ .register = try self.register_manager.allocReg(inst, sse) } |
| 5029 | | else |
| 5030 | | try self.copyToRegisterWithInstTracking(inst, ty, src_mcv); |
| 5031 | | const dst_reg = dst_mcv.getReg().?; |
| 5032 | | const dst_lock = self.register_manager.lockReg(dst_reg); |
| 5033 | | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); |
| 5052 | const src_mcv = try self.resolveInst(operand); |
| 5053 | const src_lock = if (src_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null; |
| 5054 | defer if (src_lock) |lock| self.register_manager.unlockReg(lock); |
| 5034 | 5055 | |
| 5035 | | const vec_ty = try mod.vectorType(.{ |
| 5036 | | .len = @divExact(abi_size * 8, scalar_bits), |
| 5037 | | .child = (try mod.intType(.signed, scalar_bits)).ip_index, |
| 5038 | | }); |
| 5056 | const dst_mcv: MCValue = .{ .register = .st0 }; |
| 5057 | if (std.meta.eql(src_mcv, dst_mcv) and self.reuseOperand(inst, operand, 0, src_mcv)) |
| 5058 | try self.register_manager.getReg(.st0, inst); |
| 5039 | 5059 | |
| 5040 | | const sign_val = switch (tag) { |
| 5041 | | .neg => try vec_ty.minInt(mod, vec_ty), |
| 5042 | | .abs => try vec_ty.maxInt(mod, vec_ty), |
| 5043 | | else => unreachable, |
| 5044 | | }; |
| 5060 | try self.genCopy(ty, dst_mcv, src_mcv); |
| 5061 | switch (tag) { |
| 5062 | .neg => try self.asmOpOnly(.{ .f_, .chs }), |
| 5063 | .abs => try self.asmOpOnly(.{ .f_, .abs }), |
| 5064 | else => unreachable, |
| 5065 | } |
| 5066 | break :result dst_mcv; |
| 5067 | } |
| 5045 | 5068 | |
| 5046 | | const sign_mcv = try self.genTypedValue(.{ .ty = vec_ty, .val = sign_val }); |
| 5047 | | const sign_mem = if (sign_mcv.isMemory()) |
| 5048 | | sign_mcv.mem(Memory.PtrSize.fromSize(abi_size)) |
| 5049 | | else |
| 5050 | | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ |
| 5051 | | .base = .{ .reg = try self.copyToTmpRegister(Type.usize, sign_mcv.address()) }, |
| 5069 | const abi_size: u32 = switch (ty.abiSize(mod)) { |
| 5070 | 1...16 => 16, |
| 5071 | 17...32 => 32, |
| 5072 | else => return self.fail("TODO implement floatSign for {}", .{ |
| 5073 | ty.fmt(mod), |
| 5074 | }), |
| 5075 | }; |
| 5076 | |
| 5077 | const src_mcv = try self.resolveInst(operand); |
| 5078 | const src_lock = if (src_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null; |
| 5079 | defer if (src_lock) |lock| self.register_manager.unlockReg(lock); |
| 5080 | |
| 5081 | const dst_mcv: MCValue = if (src_mcv.isRegister() and |
| 5082 | self.reuseOperand(inst, operand, 0, src_mcv)) |
| 5083 | src_mcv |
| 5084 | else if (self.hasFeature(.avx)) |
| 5085 | .{ .register = try self.register_manager.allocReg(inst, abi.RegisterClass.sse) } |
| 5086 | else |
| 5087 | try self.copyToRegisterWithInstTracking(inst, ty, src_mcv); |
| 5088 | const dst_reg = dst_mcv.getReg().?; |
| 5089 | const dst_lock = self.register_manager.lockReg(dst_reg); |
| 5090 | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); |
| 5091 | |
| 5092 | const vec_ty = try mod.vectorType(.{ |
| 5093 | .len = @divExact(abi_size * 8, scalar_bits), |
| 5094 | .child = (try mod.intType(.signed, scalar_bits)).ip_index, |
| 5052 | 5095 | }); |
| 5053 | 5096 | |
| 5054 | | if (self.hasFeature(.avx)) try self.asmRegisterRegisterMemory( |
| 5055 | | switch (scalar_bits) { |
| 5056 | | 16, 128 => if (abi_size <= 16 or self.hasFeature(.avx2)) switch (tag) { |
| 5057 | | .neg => .{ .vp_, .xor }, |
| 5058 | | .abs => .{ .vp_, .@"and" }, |
| 5059 | | else => unreachable, |
| 5060 | | } else switch (tag) { |
| 5061 | | .neg => .{ .v_ps, .xor }, |
| 5062 | | .abs => .{ .v_ps, .@"and" }, |
| 5063 | | else => unreachable, |
| 5064 | | }, |
| 5065 | | 32 => switch (tag) { |
| 5066 | | .neg => .{ .v_ps, .xor }, |
| 5067 | | .abs => .{ .v_ps, .@"and" }, |
| 5068 | | else => unreachable, |
| 5069 | | }, |
| 5070 | | 64 => switch (tag) { |
| 5071 | | .neg => .{ .v_pd, .xor }, |
| 5072 | | .abs => .{ .v_pd, .@"and" }, |
| 5073 | | else => unreachable, |
| 5074 | | }, |
| 5075 | | 80 => return self.fail("TODO implement floatSign for {}", .{ |
| 5076 | | ty.fmt(self.bin_file.options.module.?), |
| 5077 | | }), |
| 5097 | const sign_val = switch (tag) { |
| 5098 | .neg => try vec_ty.minInt(mod, vec_ty), |
| 5099 | .abs => try vec_ty.maxInt(mod, vec_ty), |
| 5078 | 5100 | else => unreachable, |
| 5079 | | }, |
| 5080 | | registerAlias(dst_reg, abi_size), |
| 5081 | | registerAlias(if (src_mcv.isRegister()) |
| 5082 | | src_mcv.getReg().? |
| 5101 | }; |
| 5102 | |
| 5103 | const sign_mcv = try self.genTypedValue(.{ .ty = vec_ty, .val = sign_val }); |
| 5104 | const sign_mem = if (sign_mcv.isMemory()) |
| 5105 | sign_mcv.mem(Memory.PtrSize.fromSize(abi_size)) |
| 5083 | 5106 | else |
| 5084 | | try self.copyToTmpRegister(ty, src_mcv), abi_size), |
| 5085 | | sign_mem, |
| 5086 | | ) else try self.asmRegisterMemory( |
| 5087 | | switch (scalar_bits) { |
| 5088 | | 16, 128 => switch (tag) { |
| 5089 | | .neg => .{ .p_, .xor }, |
| 5090 | | .abs => .{ .p_, .@"and" }, |
| 5091 | | else => unreachable, |
| 5092 | | }, |
| 5093 | | 32 => switch (tag) { |
| 5094 | | .neg => .{ ._ps, .xor }, |
| 5095 | | .abs => .{ ._ps, .@"and" }, |
| 5107 | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ |
| 5108 | .base = .{ .reg = try self.copyToTmpRegister(Type.usize, sign_mcv.address()) }, |
| 5109 | }); |
| 5110 | |
| 5111 | if (self.hasFeature(.avx)) try self.asmRegisterRegisterMemory( |
| 5112 | switch (scalar_bits) { |
| 5113 | 16, 128 => if (abi_size <= 16 or self.hasFeature(.avx2)) switch (tag) { |
| 5114 | .neg => .{ .vp_, .xor }, |
| 5115 | .abs => .{ .vp_, .@"and" }, |
| 5116 | else => unreachable, |
| 5117 | } else switch (tag) { |
| 5118 | .neg => .{ .v_ps, .xor }, |
| 5119 | .abs => .{ .v_ps, .@"and" }, |
| 5120 | else => unreachable, |
| 5121 | }, |
| 5122 | 32 => switch (tag) { |
| 5123 | .neg => .{ .v_ps, .xor }, |
| 5124 | .abs => .{ .v_ps, .@"and" }, |
| 5125 | else => unreachable, |
| 5126 | }, |
| 5127 | 64 => switch (tag) { |
| 5128 | .neg => .{ .v_pd, .xor }, |
| 5129 | .abs => .{ .v_pd, .@"and" }, |
| 5130 | else => unreachable, |
| 5131 | }, |
| 5132 | 80 => return self.fail("TODO implement floatSign for {}", .{ |
| 5133 | ty.fmt(self.bin_file.options.module.?), |
| 5134 | }), |
| 5096 | 5135 | else => unreachable, |
| 5097 | 5136 | }, |
| 5098 | | 64 => switch (tag) { |
| 5099 | | .neg => .{ ._pd, .xor }, |
| 5100 | | .abs => .{ ._pd, .@"and" }, |
| 5137 | registerAlias(dst_reg, abi_size), |
| 5138 | registerAlias(if (src_mcv.isRegister()) |
| 5139 | src_mcv.getReg().? |
| 5140 | else |
| 5141 | try self.copyToTmpRegister(ty, src_mcv), abi_size), |
| 5142 | sign_mem, |
| 5143 | ) else try self.asmRegisterMemory( |
| 5144 | switch (scalar_bits) { |
| 5145 | 16, 128 => switch (tag) { |
| 5146 | .neg => .{ .p_, .xor }, |
| 5147 | .abs => .{ .p_, .@"and" }, |
| 5148 | else => unreachable, |
| 5149 | }, |
| 5150 | 32 => switch (tag) { |
| 5151 | .neg => .{ ._ps, .xor }, |
| 5152 | .abs => .{ ._ps, .@"and" }, |
| 5153 | else => unreachable, |
| 5154 | }, |
| 5155 | 64 => switch (tag) { |
| 5156 | .neg => .{ ._pd, .xor }, |
| 5157 | .abs => .{ ._pd, .@"and" }, |
| 5158 | else => unreachable, |
| 5159 | }, |
| 5160 | 80 => return self.fail("TODO implement floatSign for {}", .{ |
| 5161 | ty.fmt(self.bin_file.options.module.?), |
| 5162 | }), |
| 5101 | 5163 | else => unreachable, |
| 5102 | 5164 | }, |
| 5103 | | 80 => return self.fail("TODO implement floatSign for {}", .{ |
| 5104 | | ty.fmt(self.bin_file.options.module.?), |
| 5105 | | }), |
| 5106 | | else => unreachable, |
| 5107 | | }, |
| 5108 | | registerAlias(dst_reg, abi_size), |
| 5109 | | sign_mem, |
| 5110 | | ); |
| 5111 | | return self.finishAir(inst, dst_mcv, .{ operand, .none, .none }); |
| 5165 | registerAlias(dst_reg, abi_size), |
| 5166 | sign_mem, |
| 5167 | ); |
| 5168 | break :result dst_mcv; |
| 5169 | }; |
| 5170 | return self.finishAir(inst, result, .{ operand, .none, .none }); |
| 5112 | 5171 | } |
| 5113 | 5172 | |
| 5114 | 5173 | fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void { |
| ... | ... | @@ -5292,19 +5351,43 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void { |
| 5292 | 5351 | const ty = self.typeOf(un_op); |
| 5293 | 5352 | const abi_size: u32 = @intCast(ty.abiSize(mod)); |
| 5294 | 5353 | |
| 5295 | | const src_mcv = try self.resolveInst(un_op); |
| 5296 | | const dst_mcv = if (src_mcv.isRegister() and self.reuseOperand(inst, un_op, 0, src_mcv)) |
| 5297 | | src_mcv |
| 5298 | | else |
| 5299 | | try self.copyToRegisterWithInstTracking(inst, ty, src_mcv); |
| 5300 | | const dst_reg = registerAlias(dst_mcv.getReg().?, abi_size); |
| 5301 | | const dst_lock = self.register_manager.lockReg(dst_reg); |
| 5302 | | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); |
| 5303 | | |
| 5304 | 5354 | const result: MCValue = result: { |
| 5355 | switch (ty.zigTypeTag(mod)) { |
| 5356 | .Float => { |
| 5357 | const float_bits = ty.floatBits(self.target.*); |
| 5358 | if (switch (float_bits) { |
| 5359 | 16 => !self.hasFeature(.f16c), |
| 5360 | 32, 64 => false, |
| 5361 | 80, 128 => true, |
| 5362 | else => unreachable, |
| 5363 | }) { |
| 5364 | var callee: ["__sqrt?".len]u8 = undefined; |
| 5365 | break :result try self.genCall(.{ .lib = .{ |
| 5366 | .return_type = ty.toIntern(), |
| 5367 | .param_types = &.{ty.toIntern()}, |
| 5368 | .callee = std.fmt.bufPrint(&callee, "{s}sqrt{s}", .{ |
| 5369 | floatLibcAbiPrefix(ty), |
| 5370 | floatLibcAbiSuffix(ty), |
| 5371 | }) catch unreachable, |
| 5372 | } }, &.{ty}, &.{.{ .air_ref = un_op }}); |
| 5373 | } |
| 5374 | }, |
| 5375 | else => {}, |
| 5376 | } |
| 5377 | |
| 5378 | const src_mcv = try self.resolveInst(un_op); |
| 5379 | const dst_mcv = if (src_mcv.isRegister() and self.reuseOperand(inst, un_op, 0, src_mcv)) |
| 5380 | src_mcv |
| 5381 | else |
| 5382 | try self.copyToRegisterWithInstTracking(inst, ty, src_mcv); |
| 5383 | const dst_reg = registerAlias(dst_mcv.getReg().?, abi_size); |
| 5384 | const dst_lock = self.register_manager.lockReg(dst_reg); |
| 5385 | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); |
| 5386 | |
| 5305 | 5387 | const mir_tag = @as(?Mir.Inst.FixedTag, switch (ty.zigTypeTag(mod)) { |
| 5306 | 5388 | .Float => switch (ty.floatBits(self.target.*)) { |
| 5307 | | 16 => if (self.hasFeature(.f16c)) { |
| 5389 | 16 => { |
| 5390 | assert(self.hasFeature(.f16c)); |
| 5308 | 5391 | const mat_src_reg = if (src_mcv.isRegister()) |
| 5309 | 5392 | src_mcv.getReg().? |
| 5310 | 5393 | else |
| ... | ... | @@ -5318,10 +5401,9 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void { |
| 5318 | 5401 | Immediate.u(0b1_00), |
| 5319 | 5402 | ); |
| 5320 | 5403 | break :result dst_mcv; |
| 5321 | | } else null, |
| 5404 | }, |
| 5322 | 5405 | 32 => if (self.hasFeature(.avx)) .{ .v_ss, .sqrt } else .{ ._ss, .sqrt }, |
| 5323 | 5406 | 64 => if (self.hasFeature(.avx)) .{ .v_sd, .sqrt } else .{ ._sd, .sqrt }, |
| 5324 | | 80, 128 => null, |
| 5325 | 5407 | else => unreachable, |
| 5326 | 5408 | }, |
| 5327 | 5409 | .Vector => switch (ty.childType(mod).zigTypeTag(mod)) { |
| ... | ... | @@ -5395,21 +5477,9 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void { |
| 5395 | 5477 | else => unreachable, |
| 5396 | 5478 | }, |
| 5397 | 5479 | else => unreachable, |
| 5398 | | }) orelse { |
| 5399 | | if (ty.zigTypeTag(mod) != .Float) return self.fail("TODO implement airSqrt for {}", .{ |
| 5400 | | ty.fmt(mod), |
| 5401 | | }); |
| 5402 | | |
| 5403 | | var callee: ["__sqrt?".len]u8 = undefined; |
| 5404 | | break :result try self.genCall(.{ .lib = .{ |
| 5405 | | .return_type = ty.toIntern(), |
| 5406 | | .param_types = &.{ty.toIntern()}, |
| 5407 | | .callee = std.fmt.bufPrint(&callee, "{s}sqrt{s}", .{ |
| 5408 | | floatLibcAbiPrefix(ty), |
| 5409 | | floatLibcAbiSuffix(ty), |
| 5410 | | }) catch unreachable, |
| 5411 | | } }, &.{ty}, &.{src_mcv}); |
| 5412 | | }; |
| 5480 | }) orelse return self.fail("TODO implement airSqrt for {}", .{ |
| 5481 | ty.fmt(mod), |
| 5482 | }); |
| 5413 | 5483 | switch (mir_tag[0]) { |
| 5414 | 5484 | .v_ss, .v_sd => if (src_mcv.isMemory()) try self.asmRegisterRegisterMemory( |
| 5415 | 5485 | mir_tag, |
| ... | ... | @@ -5536,7 +5606,7 @@ fn packedLoad(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) Inn |
| 5536 | 5606 | |
| 5537 | 5607 | const dst_reg = switch (dst_mcv) { |
| 5538 | 5608 | .register => |reg| reg, |
| 5539 | | else => try self.register_manager.allocReg(null, gp), |
| 5609 | else => try self.register_manager.allocReg(null, abi.RegisterClass.gp), |
| 5540 | 5610 | }; |
| 5541 | 5611 | const dst_lock = self.register_manager.lockReg(dst_reg); |
| 5542 | 5612 | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); |
| ... | ... | @@ -5555,7 +5625,8 @@ fn packedLoad(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) Inn |
| 5555 | 5625 | ); |
| 5556 | 5626 | try self.asmRegisterImmediate(.{ ._r, .sh }, load_reg, Immediate.u(val_bit_off)); |
| 5557 | 5627 | } else { |
| 5558 | | const tmp_reg = registerAlias(try self.register_manager.allocReg(null, gp), val_abi_size); |
| 5628 | const tmp_reg = |
| 5629 | registerAlias(try self.register_manager.allocReg(null, abi.RegisterClass.gp), val_abi_size); |
| 5559 | 5630 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 5560 | 5631 | defer self.register_manager.unlockReg(tmp_lock); |
| 5561 | 5632 | |
| ... | ... | @@ -5640,8 +5711,8 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 5640 | 5711 | const ptr_ty = self.typeOf(ty_op.operand); |
| 5641 | 5712 | const elem_size = elem_ty.abiSize(mod); |
| 5642 | 5713 | |
| 5643 | | const elem_rc = regClassForType(elem_ty, mod); |
| 5644 | | const ptr_rc = regClassForType(ptr_ty, mod); |
| 5714 | const elem_rc = self.regClassForType(elem_ty); |
| 5715 | const ptr_rc = self.regClassForType(ptr_ty); |
| 5645 | 5716 | |
| 5646 | 5717 | const ptr_mcv = try self.resolveInst(ty_op.operand); |
| 5647 | 5718 | const dst_mcv = if (elem_size <= 8 and elem_rc.supersetOf(ptr_rc) and |
| ... | ... | @@ -5696,13 +5767,13 @@ fn packedStore(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) In |
| 5696 | 5767 | } else if (math.cast(i32, @as(i64, @bitCast(part_mask_not)))) |small| { |
| 5697 | 5768 | try self.asmMemoryImmediate(.{ ._, .@"and" }, limb_mem, Immediate.s(small)); |
| 5698 | 5769 | } else { |
| 5699 | | const part_mask_reg = try self.register_manager.allocReg(null, gp); |
| 5770 | const part_mask_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp); |
| 5700 | 5771 | try self.asmRegisterImmediate(.{ ._, .mov }, part_mask_reg, Immediate.u(part_mask_not)); |
| 5701 | 5772 | try self.asmMemoryRegister(.{ ._, .@"and" }, limb_mem, part_mask_reg); |
| 5702 | 5773 | } |
| 5703 | 5774 | |
| 5704 | 5775 | if (src_bit_size <= 64) { |
| 5705 | | const tmp_reg = try self.register_manager.allocReg(null, gp); |
| 5776 | const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp); |
| 5706 | 5777 | const tmp_mcv = MCValue{ .register = tmp_reg }; |
| 5707 | 5778 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 5708 | 5779 | defer self.register_manager.unlockReg(tmp_lock); |
| ... | ... | @@ -5840,11 +5911,11 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 5840 | 5911 | const index = extra.field_index; |
| 5841 | 5912 | |
| 5842 | 5913 | const container_ty = self.typeOf(operand); |
| 5843 | | const container_rc = regClassForType(container_ty, mod); |
| 5914 | const container_rc = self.regClassForType(container_ty); |
| 5844 | 5915 | const field_ty = container_ty.structFieldType(index, mod); |
| 5845 | 5916 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result .none; |
| 5846 | | const field_rc = regClassForType(field_ty, mod); |
| 5847 | | const field_is_gp = field_rc.supersetOf(gp); |
| 5917 | const field_rc = self.regClassForType(field_ty); |
| 5918 | const field_is_gp = field_rc.supersetOf(abi.RegisterClass.gp); |
| 5848 | 5919 | |
| 5849 | 5920 | const src_mcv = try self.resolveInst(operand); |
| 5850 | 5921 | const field_off: u32 = switch (container_ty.containerLayout(mod)) { |
| ... | ... | @@ -5868,8 +5939,10 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 5868 | 5939 | @intCast(field_ty.bitSize(mod)), |
| 5869 | 5940 | ); |
| 5870 | 5941 | |
| 5871 | | const dst_reg = |
| 5872 | | try self.register_manager.allocReg(if (field_is_gp) inst else null, gp); |
| 5942 | const dst_reg = try self.register_manager.allocReg( |
| 5943 | if (field_is_gp) inst else null, |
| 5944 | abi.RegisterClass.gp, |
| 5945 | ); |
| 5873 | 5946 | const dst_mcv = MCValue{ .register = dst_reg }; |
| 5874 | 5947 | const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg); |
| 5875 | 5948 | defer self.register_manager.unlockReg(dst_lock); |
| ... | ... | @@ -5898,7 +5971,10 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 5898 | 5971 | return self.fail("TODO implement struct_field_val with large packed field", .{}); |
| 5899 | 5972 | } |
| 5900 | 5973 | |
| 5901 | | const dst_reg = try self.register_manager.allocReg(if (field_is_gp) inst else null, gp); |
| 5974 | const dst_reg = try self.register_manager.allocReg( |
| 5975 | if (field_is_gp) inst else null, |
| 5976 | abi.RegisterClass.gp, |
| 5977 | ); |
| 5902 | 5978 | const field_extra_bits = self.regExtraBits(field_ty); |
| 5903 | 5979 | const load_abi_size = |
| 5904 | 5980 | if (field_bit_off < field_extra_bits) field_abi_size else field_abi_size * 2; |
| ... | ... | @@ -5915,7 +5991,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 5915 | 5991 | try self.asmRegisterImmediate(.{ ._r, .sh }, load_reg, Immediate.u(field_bit_off)); |
| 5916 | 5992 | } else { |
| 5917 | 5993 | const tmp_reg = registerAlias( |
| 5918 | | try self.register_manager.allocReg(null, gp), |
| 5994 | try self.register_manager.allocReg(null, abi.RegisterClass.gp), |
| 5919 | 5995 | field_abi_size, |
| 5920 | 5996 | ); |
| 5921 | 5997 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| ... | ... | @@ -5975,7 +6051,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 5975 | 6051 | ); |
| 5976 | 6052 | if (self.regExtraBits(field_ty) > 0) try self.truncateRegister(field_ty, dst_reg); |
| 5977 | 6053 | |
| 5978 | | break :result if (field_rc.supersetOf(gp)) |
| 6054 | break :result if (field_rc.supersetOf(abi.RegisterClass.gp)) |
| 5979 | 6055 | dst_mcv |
| 5980 | 6056 | else |
| 5981 | 6057 | try self.copyToRegisterWithInstTracking(inst, field_ty, dst_mcv); |
| ... | ... | @@ -5996,7 +6072,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 5996 | 6072 | self.eflags_inst = inst; |
| 5997 | 6073 | break :result .{ .eflags = ro.eflags }; |
| 5998 | 6074 | } else { |
| 5999 | | const dst_reg = try self.register_manager.allocReg(inst, gp); |
| 6075 | const dst_reg = try self.register_manager.allocReg(inst, abi.RegisterClass.gp); |
| 6000 | 6076 | try self.asmSetccRegister(dst_reg.to8(), ro.eflags); |
| 6001 | 6077 | break :result .{ .register = dst_reg.to8() }; |
| 6002 | 6078 | }, |
| ... | ... | @@ -6117,7 +6193,7 @@ fn genUnOpMir(self: *Self, mir_tag: Mir.Inst.FixedTag, dst_ty: Type, dst_mcv: MC |
| 6117 | 6193 | .register => |dst_reg| try self.asmRegister(mir_tag, registerAlias(dst_reg, abi_size)), |
| 6118 | 6194 | .register_pair => unreachable, // unimplemented |
| 6119 | 6195 | .memory, .load_got, .load_direct, .load_tlv => { |
| 6120 | | const addr_reg = try self.register_manager.allocReg(null, gp); |
| 6196 | const addr_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp); |
| 6121 | 6197 | const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg); |
| 6122 | 6198 | defer self.register_manager.unlockReg(addr_reg_lock); |
| 6123 | 6199 | |
| ... | ... | @@ -6219,7 +6295,7 @@ fn genShiftBinOpMir( |
| 6219 | 6295 | }), |
| 6220 | 6296 | } |
| 6221 | 6297 | } else if (abi_size <= 16) { |
| 6222 | | const tmp_reg = try self.register_manager.allocReg(null, gp); |
| 6298 | const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp); |
| 6223 | 6299 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 6224 | 6300 | defer self.register_manager.unlockReg(tmp_lock); |
| 6225 | 6301 | |
| ... | ... | @@ -6297,11 +6373,11 @@ fn genShiftBinOpMir( |
| 6297 | 6373 | } |
| 6298 | 6374 | }, |
| 6299 | 6375 | else => { |
| 6300 | | const first_reg = try self.register_manager.allocReg(null, gp); |
| 6376 | const first_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp); |
| 6301 | 6377 | const first_lock = self.register_manager.lockRegAssumeUnused(first_reg); |
| 6302 | 6378 | defer self.register_manager.unlockReg(first_lock); |
| 6303 | 6379 | |
| 6304 | | const second_reg = try self.register_manager.allocReg(null, gp); |
| 6380 | const second_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp); |
| 6305 | 6381 | const second_lock = self.register_manager.lockRegAssumeUnused(second_reg); |
| 6306 | 6382 | defer self.register_manager.unlockReg(second_lock); |
| 6307 | 6383 | |
| ... | ... | @@ -6663,7 +6739,7 @@ fn genBinOp( |
| 6663 | 6739 | if (!self.hasFeature(.avx) and self.hasFeature(.sse4_1)) mask: { |
| 6664 | 6740 | try self.register_manager.getReg(.xmm0, null); |
| 6665 | 6741 | break :mask .xmm0; |
| 6666 | | } else try self.register_manager.allocReg(null, sse), |
| 6742 | } else try self.register_manager.allocReg(null, abi.RegisterClass.sse), |
| 6667 | 6743 | abi_size, |
| 6668 | 6744 | ) else null, |
| 6669 | 6745 | .rem, .mod => return self.fail("TODO implement genBinOp for {s} {}", .{ |
| ... | ... | @@ -6916,7 +6992,8 @@ fn genBinOp( |
| 6916 | 6992 | .Float => switch (lhs_ty.floatBits(self.target.*)) { |
| 6917 | 6993 | 16 => { |
| 6918 | 6994 | assert(self.hasFeature(.f16c)); |
| 6919 | | const tmp_reg = (try self.register_manager.allocReg(null, sse)).to128(); |
| 6995 | const tmp_reg = |
| 6996 | (try self.register_manager.allocReg(null, abi.RegisterClass.sse)).to128(); |
| 6920 | 6997 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 6921 | 6998 | defer self.register_manager.unlockReg(tmp_lock); |
| 6922 | 6999 | |
| ... | ... | @@ -7223,7 +7300,10 @@ fn genBinOp( |
| 7223 | 7300 | assert(self.hasFeature(.f16c)); |
| 7224 | 7301 | switch (lhs_ty.vectorLen(mod)) { |
| 7225 | 7302 | 1 => { |
| 7226 | | const tmp_reg = (try self.register_manager.allocReg(null, sse)).to128(); |
| 7303 | const tmp_reg = (try self.register_manager.allocReg( |
| 7304 | null, |
| 7305 | abi.RegisterClass.sse, |
| 7306 | )).to128(); |
| 7227 | 7307 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 7228 | 7308 | defer self.register_manager.unlockReg(tmp_lock); |
| 7229 | 7309 | |
| ... | ... | @@ -7267,7 +7347,10 @@ fn genBinOp( |
| 7267 | 7347 | return dst_mcv; |
| 7268 | 7348 | }, |
| 7269 | 7349 | 2 => { |
| 7270 | | const tmp_reg = (try self.register_manager.allocReg(null, sse)).to128(); |
| 7350 | const tmp_reg = (try self.register_manager.allocReg( |
| 7351 | null, |
| 7352 | abi.RegisterClass.sse, |
| 7353 | )).to128(); |
| 7271 | 7354 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 7272 | 7355 | defer self.register_manager.unlockReg(tmp_lock); |
| 7273 | 7356 | |
| ... | ... | @@ -7315,7 +7398,10 @@ fn genBinOp( |
| 7315 | 7398 | return dst_mcv; |
| 7316 | 7399 | }, |
| 7317 | 7400 | 3...4 => { |
| 7318 | | const tmp_reg = (try self.register_manager.allocReg(null, sse)).to128(); |
| 7401 | const tmp_reg = (try self.register_manager.allocReg( |
| 7402 | null, |
| 7403 | abi.RegisterClass.sse, |
| 7404 | )).to128(); |
| 7319 | 7405 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 7320 | 7406 | defer self.register_manager.unlockReg(tmp_lock); |
| 7321 | 7407 | |
| ... | ... | @@ -7355,7 +7441,10 @@ fn genBinOp( |
| 7355 | 7441 | return dst_mcv; |
| 7356 | 7442 | }, |
| 7357 | 7443 | 5...8 => { |
| 7358 | | const tmp_reg = (try self.register_manager.allocReg(null, sse)).to256(); |
| 7444 | const tmp_reg = (try self.register_manager.allocReg( |
| 7445 | null, |
| 7446 | abi.RegisterClass.sse, |
| 7447 | )).to256(); |
| 7359 | 7448 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 7360 | 7449 | defer self.register_manager.unlockReg(tmp_lock); |
| 7361 | 7450 | |
| ... | ... | @@ -7948,7 +8037,8 @@ fn genBinOpMir( |
| 7948 | 8037 | const dst_info: OpInfo = switch (dst_mcv) { |
| 7949 | 8038 | else => unreachable, |
| 7950 | 8039 | .memory, .load_got, .load_direct, .load_tlv => dst: { |
| 7951 | | const dst_addr_reg = (try self.register_manager.allocReg(null, gp)).to64(); |
| 8040 | const dst_addr_reg = |
| 8041 | (try self.register_manager.allocReg(null, abi.RegisterClass.gp)).to64(); |
| 7952 | 8042 | const dst_addr_lock = self.register_manager.lockRegAssumeUnused(dst_addr_reg); |
| 7953 | 8043 | errdefer self.register_manager.unlockReg(dst_addr_lock); |
| 7954 | 8044 | |
| ... | ... | @@ -7993,7 +8083,8 @@ fn genBinOpMir( |
| 7993 | 8083 | else => unreachable, |
| 7994 | 8084 | } |
| 7995 | 8085 | |
| 7996 | | const src_addr_reg = (try self.register_manager.allocReg(null, gp)).to64(); |
| 8086 | const src_addr_reg = |
| 8087 | (try self.register_manager.allocReg(null, abi.RegisterClass.gp)).to64(); |
| 7997 | 8088 | const src_addr_lock = self.register_manager.lockRegAssumeUnused(src_addr_reg); |
| 7998 | 8089 | errdefer self.register_manager.unlockReg(src_addr_lock); |
| 7999 | 8090 | |
| ... | ... | @@ -8619,6 +8710,7 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void { |
| 8619 | 8710 | const mod = self.bin_file.options.module.?; |
| 8620 | 8711 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 8621 | 8712 | const operand = try self.resolveInst(un_op); |
| 8713 | |
| 8622 | 8714 | const ret_ty = self.fn_type.fnReturnType(mod); |
| 8623 | 8715 | switch (self.ret_mcv.short) { |
| 8624 | 8716 | .none => {}, |
| ... | ... | @@ -8633,6 +8725,8 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void { |
| 8633 | 8725 | }, |
| 8634 | 8726 | else => unreachable, |
| 8635 | 8727 | } |
| 8728 | self.ret_mcv.liveOut(self, inst); |
| 8729 | |
| 8636 | 8730 | // TODO optimization opportunity: figure out when we can emit this as a 2 byte instruction |
| 8637 | 8731 | // which is available if the jump is 127 bytes or less forward. |
| 8638 | 8732 | const jmp_reloc = try self.asmJmpReloc(undefined); |
| ... | ... | @@ -8643,6 +8737,7 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void { |
| 8643 | 8737 | fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 8644 | 8738 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 8645 | 8739 | const ptr = try self.resolveInst(un_op); |
| 8740 | |
| 8646 | 8741 | const ptr_ty = self.typeOf(un_op); |
| 8647 | 8742 | switch (self.ret_mcv.short) { |
| 8648 | 8743 | .none => {}, |
| ... | ... | @@ -8650,6 +8745,8 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 8650 | 8745 | .indirect => |reg_off| try self.genSetReg(reg_off.reg, ptr_ty, ptr), |
| 8651 | 8746 | else => unreachable, |
| 8652 | 8747 | } |
| 8748 | self.ret_mcv.liveOut(self, inst); |
| 8749 | |
| 8653 | 8750 | // TODO optimization opportunity: figure out when we can emit this as a 2 byte instruction |
| 8654 | 8751 | // which is available if the jump is 127 bytes or less forward. |
| 8655 | 8752 | const jmp_reloc = try self.asmJmpReloc(undefined); |
| ... | ... | @@ -8800,8 +8897,10 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 8800 | 8897 | else => unreachable, |
| 8801 | 8898 | } |
| 8802 | 8899 | |
| 8803 | | const dst_addr_reg = |
| 8804 | | (try self.register_manager.allocReg(null, gp)).to64(); |
| 8900 | const dst_addr_reg = (try self.register_manager.allocReg( |
| 8901 | null, |
| 8902 | abi.RegisterClass.gp, |
| 8903 | )).to64(); |
| 8805 | 8904 | const dst_addr_lock = |
| 8806 | 8905 | self.register_manager.lockRegAssumeUnused(dst_addr_reg); |
| 8807 | 8906 | errdefer self.register_manager.unlockReg(dst_addr_lock); |
| ... | ... | @@ -8856,8 +8955,10 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 8856 | 8955 | else => unreachable, |
| 8857 | 8956 | } |
| 8858 | 8957 | |
| 8859 | | const src_addr_reg = |
| 8860 | | (try self.register_manager.allocReg(null, gp)).to64(); |
| 8958 | const src_addr_reg = (try self.register_manager.allocReg( |
| 8959 | null, |
| 8960 | abi.RegisterClass.gp, |
| 8961 | )).to64(); |
| 8861 | 8962 | const src_addr_lock = |
| 8862 | 8963 | self.register_manager.lockRegAssumeUnused(src_addr_reg); |
| 8863 | 8964 | errdefer self.register_manager.unlockReg(src_addr_lock); |
| ... | ... | @@ -8876,8 +8977,11 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 8876 | 8977 | defer if (src_info) |info| |
| 8877 | 8978 | self.register_manager.unlockReg(info.addr_lock); |
| 8878 | 8979 | |
| 8879 | | const regs = |
| 8880 | | try self.register_manager.allocRegs(2, .{ null, null }, gp); |
| 8980 | const regs = try self.register_manager.allocRegs( |
| 8981 | 2, |
| 8982 | .{ null, null }, |
| 8983 | abi.RegisterClass.gp, |
| 8984 | ); |
| 8881 | 8985 | const acc_reg = regs[0].to64(); |
| 8882 | 8986 | const locks = self.register_manager.lockRegsAssumeUnused(2, regs); |
| 8883 | 8987 | defer for (locks) |lock| self.register_manager.unlockReg(lock); |
| ... | ... | @@ -8964,12 +9068,14 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 8964 | 9068 | switch (ty.floatBits(self.target.*)) { |
| 8965 | 9069 | 16 => { |
| 8966 | 9070 | assert(self.hasFeature(.f16c)); |
| 8967 | | const tmp1_reg = (try self.register_manager.allocReg(null, sse)).to128(); |
| 9071 | const tmp1_reg = |
| 9072 | (try self.register_manager.allocReg(null, abi.RegisterClass.sse)).to128(); |
| 8968 | 9073 | const tmp1_mcv = MCValue{ .register = tmp1_reg }; |
| 8969 | 9074 | const tmp1_lock = self.register_manager.lockRegAssumeUnused(tmp1_reg); |
| 8970 | 9075 | defer self.register_manager.unlockReg(tmp1_lock); |
| 8971 | 9076 | |
| 8972 | | const tmp2_reg = (try self.register_manager.allocReg(null, sse)).to128(); |
| 9077 | const tmp2_reg = |
| 9078 | (try self.register_manager.allocReg(null, abi.RegisterClass.sse)).to128(); |
| 8973 | 9079 | const tmp2_mcv = MCValue{ .register = tmp2_reg }; |
| 8974 | 9080 | const tmp2_lock = self.register_manager.lockRegAssumeUnused(tmp2_reg); |
| 8975 | 9081 | defer self.register_manager.unlockReg(tmp2_lock); |
| ... | ... | @@ -9032,7 +9138,7 @@ fn airCmpLtErrorsLen(self: *Self, inst: Air.Inst.Index) !void { |
| 9032 | 9138 | const mod = self.bin_file.options.module.?; |
| 9033 | 9139 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 9034 | 9140 | |
| 9035 | | const addr_reg = try self.register_manager.allocReg(null, gp); |
| 9141 | const addr_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp); |
| 9036 | 9142 | const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg); |
| 9037 | 9143 | defer self.register_manager.unlockReg(addr_lock); |
| 9038 | 9144 | try self.genLazySymbolRef(.lea, addr_reg, link.File.LazySymbol.initDecl(.const_data, null, mod)); |
| ... | ... | @@ -9293,7 +9399,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC |
| 9293 | 9399 | .load_direct, |
| 9294 | 9400 | .load_tlv, |
| 9295 | 9401 | => { |
| 9296 | | const addr_reg = (try self.register_manager.allocReg(null, gp)).to64(); |
| 9402 | const addr_reg = (try self.register_manager.allocReg(null, abi.RegisterClass.gp)).to64(); |
| 9297 | 9403 | const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg); |
| 9298 | 9404 | defer self.register_manager.unlockReg(addr_reg_lock); |
| 9299 | 9405 | |
| ... | ... | @@ -9778,7 +9884,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { |
| 9778 | 9884 | else => self.typeOf(output).childType(mod), |
| 9779 | 9885 | }; |
| 9780 | 9886 | const arg_maybe_reg: ?Register = if (mem.eql(u8, constraint, "=r")) |
| 9781 | | self.register_manager.tryAllocReg(maybe_inst, regClassForType(ty, mod)) orelse |
| 9887 | self.register_manager.tryAllocReg(maybe_inst, self.regClassForType(ty)) orelse |
| 9782 | 9888 | return self.fail("ran out of registers lowering inline asm", .{}) |
| 9783 | 9889 | else if (mem.eql(u8, constraint, "=m")) |
| 9784 | 9890 | if (output != .none) null else return self.fail( |
| ... | ... | @@ -9786,7 +9892,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { |
| 9786 | 9892 | .{}, |
| 9787 | 9893 | ) |
| 9788 | 9894 | else if (mem.eql(u8, constraint, "=g")) |
| 9789 | | self.register_manager.tryAllocReg(maybe_inst, regClassForType(ty, mod)) orelse |
| 9895 | self.register_manager.tryAllocReg(maybe_inst, self.regClassForType(ty)) orelse |
| 9790 | 9896 | if (output != .none) null else return self.fail( |
| 9791 | 9897 | "ran out of register lowering inline asm", |
| 9792 | 9898 | .{}, |
| ... | ... | @@ -9840,7 +9946,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { |
| 9840 | 9946 | break :arg temp_mcv; |
| 9841 | 9947 | }, |
| 9842 | 9948 | } |
| 9843 | | const addr_reg = self.register_manager.tryAllocReg(null, gp) orelse { |
| 9949 | const addr_reg = self.register_manager.tryAllocReg(null, abi.RegisterClass.gp) orelse { |
| 9844 | 9950 | const temp_mcv = try self.allocTempRegOrMem(ty, false); |
| 9845 | 9951 | try self.genCopy(ty, temp_mcv, input_mcv); |
| 9846 | 9952 | break :arg temp_mcv; |
| ... | ... | @@ -10946,8 +11052,8 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void { |
| 10946 | 11052 | const src_ty = self.typeOf(ty_op.operand); |
| 10947 | 11053 | |
| 10948 | 11054 | const result = result: { |
| 10949 | | const dst_rc = regClassForType(dst_ty, mod); |
| 10950 | | const src_rc = regClassForType(src_ty, mod); |
| 11055 | const dst_rc = self.regClassForType(dst_ty); |
| 11056 | const src_rc = self.regClassForType(src_ty); |
| 10951 | 11057 | const src_mcv = try self.resolveInst(ty_op.operand); |
| 10952 | 11058 | |
| 10953 | 11059 | const src_lock = if (src_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null; |
| ... | ... | @@ -11074,7 +11180,7 @@ fn airFloatFromInt(self: *Self, inst: Air.Inst.Index) !void { |
| 11074 | 11180 | |
| 11075 | 11181 | if (src_bits < src_size * 8) try self.truncateRegister(src_ty, src_reg); |
| 11076 | 11182 | |
| 11077 | | const dst_reg = try self.register_manager.allocReg(inst, regClassForType(dst_ty, mod)); |
| 11183 | const dst_reg = try self.register_manager.allocReg(inst, self.regClassForType(dst_ty)); |
| 11078 | 11184 | const dst_mcv = MCValue{ .register = dst_reg }; |
| 11079 | 11185 | const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg); |
| 11080 | 11186 | defer self.register_manager.unlockReg(dst_lock); |
| ... | ... | @@ -11151,7 +11257,7 @@ fn airIntFromFloat(self: *Self, inst: Air.Inst.Index) !void { |
| 11151 | 11257 | const src_lock = self.register_manager.lockRegAssumeUnused(src_reg); |
| 11152 | 11258 | defer self.register_manager.unlockReg(src_lock); |
| 11153 | 11259 | |
| 11154 | | const dst_reg = try self.register_manager.allocReg(inst, regClassForType(dst_ty, mod)); |
| 11260 | const dst_reg = try self.register_manager.allocReg(inst, self.regClassForType(dst_ty)); |
| 11155 | 11261 | const dst_mcv = MCValue{ .register = dst_reg }; |
| 11156 | 11262 | const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg); |
| 11157 | 11263 | defer self.register_manager.unlockReg(dst_lock); |
| ... | ... | @@ -11332,7 +11438,7 @@ fn atomicOp( |
| 11332 | 11438 | .SeqCst => .xchg, |
| 11333 | 11439 | }; |
| 11334 | 11440 | |
| 11335 | | const dst_reg = try self.register_manager.allocReg(null, gp); |
| 11441 | const dst_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp); |
| 11336 | 11442 | const dst_mcv = MCValue{ .register = dst_reg }; |
| 11337 | 11443 | const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg); |
| 11338 | 11444 | defer self.register_manager.unlockReg(dst_lock); |
| ... | ... | @@ -11354,7 +11460,7 @@ fn atomicOp( |
| 11354 | 11460 | return if (unused) .unreach else dst_mcv; |
| 11355 | 11461 | }, |
| 11356 | 11462 | .loop => _ = if (val_abi_size <= 8) { |
| 11357 | | const tmp_reg = try self.register_manager.allocReg(null, gp); |
| 11463 | const tmp_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp); |
| 11358 | 11464 | const tmp_mcv = MCValue{ .register = tmp_reg }; |
| 11359 | 11465 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 11360 | 11466 | defer self.register_manager.unlockReg(tmp_lock); |
| ... | ... | @@ -11628,7 +11734,7 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void { |
| 11628 | 11734 | |
| 11629 | 11735 | // Used to store the number of elements for comparison. |
| 11630 | 11736 | // After comparison, updated to store number of bytes needed to copy. |
| 11631 | | const len_reg = try self.register_manager.allocReg(null, gp); |
| 11737 | const len_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp); |
| 11632 | 11738 | const len_mcv: MCValue = .{ .register = len_reg }; |
| 11633 | 11739 | const len_lock = self.register_manager.lockRegAssumeUnused(len_reg); |
| 11634 | 11740 | defer self.register_manager.unlockReg(len_lock); |
| ... | ... | @@ -11638,7 +11744,7 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void { |
| 11638 | 11744 | const skip_reloc = try self.asmJccReloc(undefined, .z); |
| 11639 | 11745 | try self.store(slice_ptr_ty, ptr, src_val); |
| 11640 | 11746 | |
| 11641 | | const second_elem_ptr_reg = try self.register_manager.allocReg(null, gp); |
| 11747 | const second_elem_ptr_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp); |
| 11642 | 11748 | const second_elem_ptr_mcv: MCValue = .{ .register = second_elem_ptr_reg }; |
| 11643 | 11749 | const second_elem_ptr_lock = self.register_manager.lockRegAssumeUnused(second_elem_ptr_reg); |
| 11644 | 11750 | defer self.register_manager.unlockReg(second_elem_ptr_lock); |
| ... | ... | @@ -11667,7 +11773,7 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void { |
| 11667 | 11773 | assert(len != 0); // prevented by Sema |
| 11668 | 11774 | try self.store(elem_ptr_ty, dst_ptr, src_val); |
| 11669 | 11775 | |
| 11670 | | const second_elem_ptr_reg = try self.register_manager.allocReg(null, gp); |
| 11776 | const second_elem_ptr_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp); |
| 11671 | 11777 | const second_elem_ptr_mcv: MCValue = .{ .register = second_elem_ptr_reg }; |
| 11672 | 11778 | const second_elem_ptr_lock = self.register_manager.lockRegAssumeUnused(second_elem_ptr_reg); |
| 11673 | 11779 | defer self.register_manager.unlockReg(second_elem_ptr_lock); |
| ... | ... | @@ -11774,16 +11880,16 @@ fn airErrorName(self: *Self, inst: Air.Inst.Index) !void { |
| 11774 | 11880 | const err_lock = self.register_manager.lockRegAssumeUnused(err_reg); |
| 11775 | 11881 | defer self.register_manager.unlockReg(err_lock); |
| 11776 | 11882 | |
| 11777 | | const addr_reg = try self.register_manager.allocReg(null, gp); |
| 11883 | const addr_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp); |
| 11778 | 11884 | const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg); |
| 11779 | 11885 | defer self.register_manager.unlockReg(addr_lock); |
| 11780 | 11886 | try self.genLazySymbolRef(.lea, addr_reg, link.File.LazySymbol.initDecl(.const_data, null, mod)); |
| 11781 | 11887 | |
| 11782 | | const start_reg = try self.register_manager.allocReg(null, gp); |
| 11888 | const start_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp); |
| 11783 | 11889 | const start_lock = self.register_manager.lockRegAssumeUnused(start_reg); |
| 11784 | 11890 | defer self.register_manager.unlockReg(start_lock); |
| 11785 | 11891 | |
| 11786 | | const end_reg = try self.register_manager.allocReg(null, gp); |
| 11892 | const end_reg = try self.register_manager.allocReg(null, abi.RegisterClass.gp); |
| 11787 | 11893 | const end_lock = self.register_manager.lockRegAssumeUnused(end_reg); |
| 11788 | 11894 | defer self.register_manager.unlockReg(end_lock); |
| 11789 | 11895 | |
| ... | ... | @@ -11851,7 +11957,7 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void { |
| 11851 | 11957 | const mod = self.bin_file.options.module.?; |
| 11852 | 11958 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 11853 | 11959 | const vector_ty = self.typeOfIndex(inst); |
| 11854 | | const dst_rc = regClassForType(vector_ty, mod); |
| 11960 | const dst_rc = self.regClassForType(vector_ty); |
| 11855 | 11961 | const scalar_ty = vector_ty.scalarType(mod); |
| 11856 | 11962 | |
| 11857 | 11963 | const src_mcv = try self.resolveInst(ty_op.operand); |