| ... | @@ -47,10 +47,6 @@ const RegisterManager = abi.RegisterManager; | ... | @@ -47,10 +47,6 @@ const RegisterManager = abi.RegisterManager; |
| 47 | const RegisterLock = RegisterManager.RegisterLock; | 47 | const RegisterLock = RegisterManager.RegisterLock; |
| 48 | const FrameIndex = bits.FrameIndex; | 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 | const InnerError = CodeGenError || error{OutOfRegisters}; | 50 | const InnerError = CodeGenError || error{OutOfRegisters}; |
| 55 | | 51 | |
| 56 | gpa: Allocator, | 52 | gpa: Allocator, |
| ... | @@ -620,6 +616,7 @@ const InstTracking = struct { | ... | @@ -620,6 +616,7 @@ const InstTracking = struct { |
| 620 | } | 616 | } |
| 621 | | 617 | |
| 622 | fn die(self: *InstTracking, function: *Self, inst: Air.Inst.Index) !void { | 618 | fn die(self: *InstTracking, function: *Self, inst: Air.Inst.Index) !void { |
| | 619 | if (self.short == .dead) return; |
| 623 | try function.freeValue(self.short); | 620 | try function.freeValue(self.short); |
| 624 | self.short = .{ .dead = function.scope_generation }; | 621 | self.short = .{ .dead = function.scope_generation }; |
| 625 | tracking_log.debug("%{d} => {} (death)", .{ inst, self.* }); | 622 | tracking_log.debug("%{d} => {} (death)", .{ inst, self.* }); |
| ... | @@ -635,6 +632,40 @@ const InstTracking = struct { | ... | @@ -635,6 +632,40 @@ const InstTracking = struct { |
| 635 | tracking_log.debug("%{d} => {} (reuse %{d})", .{ new_inst, self.*, old_inst }); | 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 | pub fn format( | 669 | pub fn format( |
| 639 | self: InstTracking, | 670 | self: InstTracking, |
| 640 | comptime _: []const u8, | 671 | comptime _: []const u8, |
| ... | @@ -1144,7 +1175,7 @@ fn asmSetccRegister(self: *Self, reg: Register, cc: bits.Condition) !void { | ... | @@ -1144,7 +1175,7 @@ fn asmSetccRegister(self: *Self, reg: Register, cc: bits.Condition) !void { |
| 1144 | } }, | 1175 | } }, |
| 1145 | .z_and_np, .nz_or_p => .{ .rr = .{ | 1176 | .z_and_np, .nz_or_p => .{ .rr = .{ |
| 1146 | .r1 = reg, | 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,7 +1215,7 @@ fn asmSetccMemory(self: *Self, m: Memory, cc: bits.Condition) !void { |
| 1184 | .payload = payload, | 1215 | .payload = payload, |
| 1185 | } }, | 1216 | } }, |
| 1186 | .z_and_np, .nz_or_p => .{ .rx = .{ | 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 | .payload = payload, | 1219 | .payload = payload, |
| 1189 | } }, | 1220 | } }, |
| 1190 | }, | 1221 | }, |
| ... | @@ -2087,7 +2118,7 @@ fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void { | ... | @@ -2087,7 +2118,7 @@ fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void { |
| 2087 | var exitlude_jump_relocs = try self.gpa.alloc(u32, enum_ty.enumFieldCount(mod)); | 2118 | var exitlude_jump_relocs = try self.gpa.alloc(u32, enum_ty.enumFieldCount(mod)); |
| 2088 | defer self.gpa.free(exitlude_jump_relocs); | 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 | const data_lock = self.register_manager.lockRegAssumeUnused(data_reg); | 2122 | const data_lock = self.register_manager.lockRegAssumeUnused(data_reg); |
| 2092 | defer self.register_manager.unlockReg(data_lock); | 2123 | defer self.register_manager.unlockReg(data_lock); |
| 2093 | try self.genLazySymbolRef(.lea, data_reg, .{ .kind = .const_data, .ty = enum_ty }); | 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,7 +2388,7 @@ fn allocRegOrMemAdvanced(self: *Self, ty: Type, inst: ?Air.Inst.Index, reg_ok: b |
| 2357 | }, | 2388 | }, |
| 2358 | else => 8, | 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 | return MCValue{ .register = registerAlias(reg, abi_size) }; | 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,10 +2398,15 @@ fn allocRegOrMemAdvanced(self: *Self, ty: Type, inst: ?Air.Inst.Index, reg_ok: b |
| 2367 | return .{ .load_frame = .{ .index = frame_index } }; | 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 | return switch (ty.zigTypeTag(mod)) { | 2403 | return switch (ty.zigTypeTag(mod)) { |
| 2372 | .Float, .Vector => sse, | 2404 | .Float => switch (ty.floatBits(self.target.*)) { |
| 2373 | else => gp, | 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,8 +2546,7 @@ pub fn spillRegisters(self: *Self, registers: []const Register) !void { |
| 2510 | /// allocated. A second call to `copyToTmpRegister` may return the same register. | 2546 | /// allocated. A second call to `copyToTmpRegister` may return the same register. |
| 2511 | /// This can have a side effect of spilling instructions to the stack to free up a register. | 2547 | /// This can have a side effect of spilling instructions to the stack to free up a register. |
| 2512 | fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register { | 2548 | fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register { |
| 2513 | const mod = self.bin_file.options.module.?; | 2549 | const reg = try self.register_manager.allocReg(null, self.regClassForType(ty)); |
| 2514 | const reg = try self.register_manager.allocReg(null, regClassForType(ty, mod)); | | |
| 2515 | try self.genSetReg(reg, ty, mcv); | 2550 | try self.genSetReg(reg, ty, mcv); |
| 2516 | return reg; | 2551 | return reg; |
| 2517 | } | 2552 | } |
| ... | @@ -2526,8 +2561,7 @@ fn copyToRegisterWithInstTracking( | ... | @@ -2526,8 +2561,7 @@ fn copyToRegisterWithInstTracking( |
| 2526 | ty: Type, | 2561 | ty: Type, |
| 2527 | mcv: MCValue, | 2562 | mcv: MCValue, |
| 2528 | ) !MCValue { | 2563 | ) !MCValue { |
| 2529 | const mod = self.bin_file.options.module.?; | 2564 | const reg: Register = try self.register_manager.allocReg(reg_owner, self.regClassForType(ty)); |
| 2530 | const reg: Register = try self.register_manager.allocReg(reg_owner, regClassForType(ty, mod)); | | |
| 2531 | try self.genSetReg(reg, ty, mcv); | 2565 | try self.genSetReg(reg, ty, mcv); |
| 2532 | return MCValue{ .register = reg }; | 2566 | return MCValue{ .register = reg }; |
| 2533 | } | 2567 | } |
| ... | @@ -3084,7 +3118,7 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3084,7 +3118,7 @@ fn airAddSat(self: *Self, inst: Air.Inst.Index) !void { |
| 3084 | }; | 3118 | }; |
| 3085 | defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock); | 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 | const limit_mcv = MCValue{ .register = limit_reg }; | 3122 | const limit_mcv = MCValue{ .register = limit_reg }; |
| 3089 | const limit_lock = self.register_manager.lockRegAssumeUnused(limit_reg); | 3123 | const limit_lock = self.register_manager.lockRegAssumeUnused(limit_reg); |
| 3090 | defer self.register_manager.unlockReg(limit_lock); | 3124 | defer self.register_manager.unlockReg(limit_lock); |
| ... | @@ -3167,7 +3201,7 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3167,7 +3201,7 @@ fn airSubSat(self: *Self, inst: Air.Inst.Index) !void { |
| 3167 | }; | 3201 | }; |
| 3168 | defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock); | 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 | const limit_mcv = MCValue{ .register = limit_reg }; | 3205 | const limit_mcv = MCValue{ .register = limit_reg }; |
| 3172 | const limit_lock = self.register_manager.lockRegAssumeUnused(limit_reg); | 3206 | const limit_lock = self.register_manager.lockRegAssumeUnused(limit_reg); |
| 3173 | defer self.register_manager.unlockReg(limit_lock); | 3207 | defer self.register_manager.unlockReg(limit_lock); |
| ... | @@ -3245,7 +3279,7 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3245,7 +3279,7 @@ fn airMulSat(self: *Self, inst: Air.Inst.Index) !void { |
| 3245 | }; | 3279 | }; |
| 3246 | defer if (rhs_lock) |lock| self.register_manager.unlockReg(lock); | 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 | const limit_mcv = MCValue{ .register = limit_reg }; | 3283 | const limit_mcv = MCValue{ .register = limit_reg }; |
| 3250 | const limit_lock = self.register_manager.lockRegAssumeUnused(limit_reg); | 3284 | const limit_lock = self.register_manager.lockRegAssumeUnused(limit_reg); |
| 3251 | defer self.register_manager.unlockReg(limit_lock); | 3285 | defer self.register_manager.unlockReg(limit_lock); |
| ... | @@ -3433,7 +3467,8 @@ fn genSetFrameTruncatedOverflowCompare( | ... | @@ -3433,7 +3467,8 @@ fn genSetFrameTruncatedOverflowCompare( |
| 3433 | | 3467 | |
| 3434 | const rest_ty = try mod.intType(.unsigned, int_info.bits - hi_limb_bits); | 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 | const temp_locks = self.register_manager.lockRegsAssumeUnused(3, temp_regs); | 3472 | const temp_locks = self.register_manager.lockRegsAssumeUnused(3, temp_regs); |
| 3438 | defer for (temp_locks) |lock| self.register_manager.unlockReg(lock); | 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,7 +3886,7 @@ fn airUnwrapErrUnionErrPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 3851 | const src_lock = self.register_manager.lockRegAssumeUnused(src_reg); | 3886 | const src_lock = self.register_manager.lockRegAssumeUnused(src_reg); |
| 3852 | defer self.register_manager.unlockReg(src_lock); | 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 | const dst_mcv = MCValue{ .register = dst_reg }; | 3890 | const dst_mcv = MCValue{ .register = dst_reg }; |
| 3856 | const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg); | 3891 | const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg); |
| 3857 | defer self.register_manager.unlockReg(dst_lock); | 3892 | defer self.register_manager.unlockReg(dst_lock); |
| ... | @@ -3891,7 +3926,7 @@ fn airUnwrapErrUnionPayloadPtr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -3891,7 +3926,7 @@ fn airUnwrapErrUnionPayloadPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 3891 | const dst_reg = if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) | 3926 | const dst_reg = if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) |
| 3892 | src_reg | 3927 | src_reg |
| 3893 | else | 3928 | else |
| 3894 | try self.register_manager.allocReg(inst, gp); | 3929 | try self.register_manager.allocReg(inst, abi.RegisterClass.gp); |
| 3895 | const dst_mcv = MCValue{ .register = dst_reg }; | 3930 | const dst_mcv = MCValue{ .register = dst_reg }; |
| 3896 | const dst_lock = self.register_manager.lockReg(dst_reg); | 3931 | const dst_lock = self.register_manager.lockReg(dst_reg); |
| 3897 | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); | 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,7 +3977,7 @@ fn airErrUnionPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void { |
| 3942 | const dst_reg = if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) | 3977 | const dst_reg = if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) |
| 3943 | src_reg | 3978 | src_reg |
| 3944 | else | 3979 | else |
| 3945 | try self.register_manager.allocReg(inst, gp); | 3980 | try self.register_manager.allocReg(inst, abi.RegisterClass.gp); |
| 3946 | const dst_lock = self.register_manager.lockReg(dst_reg); | 3981 | const dst_lock = self.register_manager.lockReg(dst_reg); |
| 3947 | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); | 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,7 +4150,7 @@ fn airPtrSliceLenPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 4115 | const dst_reg = if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) | 4150 | const dst_reg = if (self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) |
| 4116 | src_reg | 4151 | src_reg |
| 4117 | else | 4152 | else |
| 4118 | try self.register_manager.allocReg(inst, gp); | 4153 | try self.register_manager.allocReg(inst, abi.RegisterClass.gp); |
| 4119 | const dst_mcv = MCValue{ .register = dst_reg }; | 4154 | const dst_mcv = MCValue{ .register = dst_reg }; |
| 4120 | const dst_lock = self.register_manager.lockReg(dst_reg); | 4155 | const dst_lock = self.register_manager.lockReg(dst_reg); |
| 4121 | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); | 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,7 +4187,7 @@ fn elemOffset(self: *Self, index_ty: Type, index: MCValue, elem_size: u64) !Regi |
| 4152 | .immediate => |imm| { | 4187 | .immediate => |imm| { |
| 4153 | // Optimisation: if index MCValue is an immediate, we can multiply in `comptime` | 4188 | // Optimisation: if index MCValue is an immediate, we can multiply in `comptime` |
| 4154 | // and set the register directly to the scaled offset as an immediate. | 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 | try self.genSetReg(reg, index_ty, .{ .immediate = imm * elem_size }); | 4191 | try self.genSetReg(reg, index_ty, .{ .immediate = imm * elem_size }); |
| 4157 | break :blk reg; | 4192 | break :blk reg; |
| 4158 | }, | 4193 | }, |
| ... | @@ -4192,7 +4227,7 @@ fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue { | ... | @@ -4192,7 +4227,7 @@ fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue { |
| 4192 | const offset_reg_lock = self.register_manager.lockRegAssumeUnused(offset_reg); | 4227 | const offset_reg_lock = self.register_manager.lockRegAssumeUnused(offset_reg); |
| 4193 | defer self.register_manager.unlockReg(offset_reg_lock); | 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 | try self.genSetReg(addr_reg, Type.usize, slice_mcv); | 4231 | try self.genSetReg(addr_reg, Type.usize, slice_mcv); |
| 4197 | // TODO we could allocate register here, but need to expect addr register and potentially | 4232 | // TODO we could allocate register here, but need to expect addr register and potentially |
| 4198 | // offset register. | 4233 | // offset register. |
| ... | @@ -4249,7 +4284,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4249,7 +4284,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 4249 | const offset_reg_lock = self.register_manager.lockRegAssumeUnused(offset_reg); | 4284 | const offset_reg_lock = self.register_manager.lockRegAssumeUnused(offset_reg); |
| 4250 | defer self.register_manager.unlockReg(offset_reg_lock); | 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 | switch (array) { | 4288 | switch (array) { |
| 4254 | .register => { | 4289 | .register => { |
| 4255 | const frame_index = try self.allocFrameIndex(FrameAlloc.initType(array_ty, mod)); | 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,7 +4521,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void { |
| 4486 | }; | 4521 | }; |
| 4487 | defer if (mat_src_lock) |lock| self.register_manager.unlockReg(lock); | 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 | const dst_mcv = MCValue{ .register = dst_reg }; | 4525 | const dst_mcv = MCValue{ .register = dst_reg }; |
| 4491 | const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg); | 4526 | const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg); |
| 4492 | defer self.register_manager.unlockReg(dst_lock); | 4527 | defer self.register_manager.unlockReg(dst_lock); |
| ... | @@ -4510,7 +4545,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4510,7 +4545,7 @@ fn airClz(self: *Self, inst: Air.Inst.Index) !void { |
| 4510 | try self.genBinOpMir(.{ ._, .sub }, dst_ty, dst_mcv, .{ .immediate = extra_bits }); | 4545 | try self.genBinOpMir(.{ ._, .sub }, dst_ty, dst_mcv, .{ .immediate = extra_bits }); |
| 4511 | } | 4546 | } |
| 4512 | } else if (src_bits <= 128) { | 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 | const tmp_mcv = MCValue{ .register = tmp_reg }; | 4549 | const tmp_mcv = MCValue{ .register = tmp_reg }; |
| 4515 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); | 4550 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 4516 | defer self.register_manager.unlockReg(tmp_lock); | 4551 | defer self.register_manager.unlockReg(tmp_lock); |
| ... | @@ -4616,7 +4651,7 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4616,7 +4651,7 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void { |
| 4616 | }; | 4651 | }; |
| 4617 | defer if (mat_src_lock) |lock| self.register_manager.unlockReg(lock); | 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 | const dst_mcv = MCValue{ .register = dst_reg }; | 4655 | const dst_mcv = MCValue{ .register = dst_reg }; |
| 4621 | const dst_lock = self.register_manager.lockReg(dst_reg); | 4656 | const dst_lock = self.register_manager.lockReg(dst_reg); |
| 4622 | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); | 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,7 +4678,7 @@ fn airCtz(self: *Self, inst: Air.Inst.Index) !void { |
| 4643 | } else mat_src_mcv; | 4678 | } else mat_src_mcv; |
| 4644 | try self.genBinOpMir(.{ ._, .tzcnt }, wide_ty, dst_mcv, masked_mcv); | 4679 | try self.genBinOpMir(.{ ._, .tzcnt }, wide_ty, dst_mcv, masked_mcv); |
| 4645 | } else if (src_bits <= 128) { | 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 | const tmp_mcv = MCValue{ .register = tmp_reg }; | 4682 | const tmp_mcv = MCValue{ .register = tmp_reg }; |
| 4648 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); | 4683 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 4649 | defer self.register_manager.unlockReg(tmp_lock); | 4684 | defer self.register_manager.unlockReg(tmp_lock); |
| ... | @@ -4718,7 +4753,7 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4718,7 +4753,7 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void { |
| 4718 | if (src_mcv.isRegister() and self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) | 4753 | if (src_mcv.isRegister() and self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) |
| 4719 | src_mcv | 4754 | src_mcv |
| 4720 | else | 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 | const popcnt_ty = if (src_abi_size > 1) src_ty else Type.u16; | 4758 | const popcnt_ty = if (src_abi_size > 1) src_ty else Type.u16; |
| 4724 | try self.genBinOpMir(.{ ._, .popcnt }, popcnt_ty, dst_mcv, mat_src_mcv); | 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,7 +4774,7 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void { |
| 4739 | const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg); | 4774 | const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg); |
| 4740 | defer self.register_manager.unlockReg(dst_lock); | 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 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); | 4778 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 4744 | defer self.register_manager.unlockReg(tmp_lock); | 4779 | defer self.register_manager.unlockReg(tmp_lock); |
| 4745 | | 4780 | |
| ... | @@ -4747,7 +4782,7 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4747,7 +4782,7 @@ fn airPopcount(self: *Self, inst: Air.Inst.Index) !void { |
| 4747 | const dst = registerAlias(dst_reg, src_abi_size); | 4782 | const dst = registerAlias(dst_reg, src_abi_size); |
| 4748 | const tmp = registerAlias(tmp_reg, src_abi_size); | 4783 | const tmp = registerAlias(tmp_reg, src_abi_size); |
| 4749 | const imm = if (src_abi_size > 4) | 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 | else | 4786 | else |
| 4752 | undefined; | 4787 | undefined; |
| 4753 | | 4788 | |
| ... | @@ -4848,7 +4883,7 @@ fn byteSwap(self: *Self, inst: Air.Inst.Index, src_ty: Type, src_mcv: MCValue, m | ... | @@ -4848,7 +4883,7 @@ fn byteSwap(self: *Self, inst: Air.Inst.Index, src_ty: Type, src_mcv: MCValue, m |
| 4848 | const dst_mcv: MCValue = if (mem_ok) | 4883 | const dst_mcv: MCValue = if (mem_ok) |
| 4849 | try self.allocRegOrMem(inst, true) | 4884 | try self.allocRegOrMem(inst, true) |
| 4850 | else | 4885 | else |
| 4851 | .{ .register = try self.register_manager.allocReg(inst, gp) }; | 4886 | .{ .register = try self.register_manager.allocReg(inst, abi.RegisterClass.gp) }; |
| 4852 | if (dst_mcv.isRegister()) { | 4887 | if (dst_mcv.isRegister()) { |
| 4853 | const dst_lock = self.register_manager.lockRegAssumeUnused(dst_mcv.register); | 4888 | const dst_lock = self.register_manager.lockRegAssumeUnused(dst_mcv.register); |
| 4854 | defer self.register_manager.unlockReg(dst_lock); | 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,7 +4898,7 @@ fn byteSwap(self: *Self, inst: Air.Inst.Index, src_ty: Type, src_mcv: MCValue, m |
| 4863 | return dst_mcv; | 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 | const dst_mcv = MCValue{ .register = dst_reg }; | 4902 | const dst_mcv = MCValue{ .register = dst_reg }; |
| 4868 | const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg); | 4903 | const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg); |
| 4869 | defer self.register_manager.unlockReg(dst_lock); | 4904 | defer self.register_manager.unlockReg(dst_lock); |
| ... | @@ -4906,7 +4941,7 @@ fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -4906,7 +4941,7 @@ fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void { |
| 4906 | const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg); | 4941 | const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg); |
| 4907 | defer self.register_manager.unlockReg(dst_lock); | 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 | const tmp_lock = self.register_manager.lockReg(tmp_reg); | 4945 | const tmp_lock = self.register_manager.lockReg(tmp_reg); |
| 4911 | defer if (tmp_lock) |lock| self.register_manager.unlockReg(lock); | 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,7 +4949,7 @@ fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void { |
| 4914 | const dst = registerAlias(dst_reg, src_abi_size); | 4949 | const dst = registerAlias(dst_reg, src_abi_size); |
| 4915 | const tmp = registerAlias(tmp_reg, src_abi_size); | 4950 | const tmp = registerAlias(tmp_reg, src_abi_size); |
| 4916 | const imm = if (src_abi_size > 4) | 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 | else | 4953 | else |
| 4919 | undefined; | 4954 | undefined; |
| 4920 | | 4955 | |
| ... | @@ -5006,109 +5041,133 @@ fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -5006,109 +5041,133 @@ fn airBitReverse(self: *Self, inst: Air.Inst.Index) !void { |
| 5006 | fn floatSign(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, ty: Type) !void { | 5041 | fn floatSign(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, ty: Type) !void { |
| 5007 | const mod = self.bin_file.options.module.?; | 5042 | const mod = self.bin_file.options.module.?; |
| 5008 | const tag = self.air.instructions.items(.tag)[inst]; | 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); | 5045 | const result = result: { |
| 5022 | const src_lock = if (src_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null; | 5046 | const scalar_bits = ty.scalarType(mod).floatBits(self.target.*); |
| 5023 | defer if (src_lock) |lock| self.register_manager.unlockReg(lock); | 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)) | 5052 | const src_mcv = try self.resolveInst(operand); |
| 5026 | src_mcv | 5053 | const src_lock = if (src_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null; |
| 5027 | else if (self.hasFeature(.avx)) | 5054 | defer if (src_lock) |lock| self.register_manager.unlockReg(lock); |
| 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); | | |
| 5034 | | 5055 | |
| 5035 | const vec_ty = try mod.vectorType(.{ | 5056 | const dst_mcv: MCValue = .{ .register = .st0 }; |
| 5036 | .len = @divExact(abi_size * 8, scalar_bits), | 5057 | if (std.meta.eql(src_mcv, dst_mcv) and self.reuseOperand(inst, operand, 0, src_mcv)) |
| 5037 | .child = (try mod.intType(.signed, scalar_bits)).ip_index, | 5058 | try self.register_manager.getReg(.st0, inst); |
| 5038 | }); | | |
| 5039 | | 5059 | |
| 5040 | const sign_val = switch (tag) { | 5060 | try self.genCopy(ty, dst_mcv, src_mcv); |
| 5041 | .neg => try vec_ty.minInt(mod, vec_ty), | 5061 | switch (tag) { |
| 5042 | .abs => try vec_ty.maxInt(mod, vec_ty), | 5062 | .neg => try self.asmOpOnly(.{ .f_, .chs }), |
| 5043 | else => unreachable, | 5063 | .abs => try self.asmOpOnly(.{ .f_, .abs }), |
| 5044 | }; | 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 }); | 5069 | const abi_size: u32 = switch (ty.abiSize(mod)) { |
| 5047 | const sign_mem = if (sign_mcv.isMemory()) | 5070 | 1...16 => 16, |
| 5048 | sign_mcv.mem(Memory.PtrSize.fromSize(abi_size)) | 5071 | 17...32 => 32, |
| 5049 | else | 5072 | else => return self.fail("TODO implement floatSign for {}", .{ |
| 5050 | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ | 5073 | ty.fmt(mod), |
| 5051 | .base = .{ .reg = try self.copyToTmpRegister(Type.usize, sign_mcv.address()) }, | 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( | 5097 | const sign_val = switch (tag) { |
| 5055 | switch (scalar_bits) { | 5098 | .neg => try vec_ty.minInt(mod, vec_ty), |
| 5056 | 16, 128 => if (abi_size <= 16 or self.hasFeature(.avx2)) switch (tag) { | 5099 | .abs => try vec_ty.maxInt(mod, vec_ty), |
| 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 | }), | | |
| 5078 | else => unreachable, | 5100 | else => unreachable, |
| 5079 | }, | 5101 | }; |
| 5080 | registerAlias(dst_reg, abi_size), | 5102 | |
| 5081 | registerAlias(if (src_mcv.isRegister()) | 5103 | const sign_mcv = try self.genTypedValue(.{ .ty = vec_ty, .val = sign_val }); |
| 5082 | src_mcv.getReg().? | 5104 | const sign_mem = if (sign_mcv.isMemory()) |
| | 5105 | sign_mcv.mem(Memory.PtrSize.fromSize(abi_size)) |
| 5083 | else | 5106 | else |
| 5084 | try self.copyToTmpRegister(ty, src_mcv), abi_size), | 5107 | Memory.sib(Memory.PtrSize.fromSize(abi_size), .{ |
| 5085 | sign_mem, | 5108 | .base = .{ .reg = try self.copyToTmpRegister(Type.usize, sign_mcv.address()) }, |
| 5086 | ) else try self.asmRegisterMemory( | 5109 | }); |
| 5087 | switch (scalar_bits) { | 5110 | |
| 5088 | 16, 128 => switch (tag) { | 5111 | if (self.hasFeature(.avx)) try self.asmRegisterRegisterMemory( |
| 5089 | .neg => .{ .p_, .xor }, | 5112 | switch (scalar_bits) { |
| 5090 | .abs => .{ .p_, .@"and" }, | 5113 | 16, 128 => if (abi_size <= 16 or self.hasFeature(.avx2)) switch (tag) { |
| 5091 | else => unreachable, | 5114 | .neg => .{ .vp_, .xor }, |
| 5092 | }, | 5115 | .abs => .{ .vp_, .@"and" }, |
| 5093 | 32 => switch (tag) { | 5116 | else => unreachable, |
| 5094 | .neg => .{ ._ps, .xor }, | 5117 | } else switch (tag) { |
| 5095 | .abs => .{ ._ps, .@"and" }, | 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 | else => unreachable, | 5135 | else => unreachable, |
| 5097 | }, | 5136 | }, |
| 5098 | 64 => switch (tag) { | 5137 | registerAlias(dst_reg, abi_size), |
| 5099 | .neg => .{ ._pd, .xor }, | 5138 | registerAlias(if (src_mcv.isRegister()) |
| 5100 | .abs => .{ ._pd, .@"and" }, | 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 | else => unreachable, | 5163 | else => unreachable, |
| 5102 | }, | 5164 | }, |
| 5103 | 80 => return self.fail("TODO implement floatSign for {}", .{ | 5165 | registerAlias(dst_reg, abi_size), |
| 5104 | ty.fmt(self.bin_file.options.module.?), | 5166 | sign_mem, |
| 5105 | }), | 5167 | ); |
| 5106 | else => unreachable, | 5168 | break :result dst_mcv; |
| 5107 | }, | 5169 | }; |
| 5108 | registerAlias(dst_reg, abi_size), | 5170 | return self.finishAir(inst, result, .{ operand, .none, .none }); |
| 5109 | sign_mem, | | |
| 5110 | ); | | |
| 5111 | return self.finishAir(inst, dst_mcv, .{ operand, .none, .none }); | | |
| 5112 | } | 5171 | } |
| 5113 | | 5172 | |
| 5114 | fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void { | 5173 | fn airFloatSign(self: *Self, inst: Air.Inst.Index) !void { |
| ... | @@ -5292,19 +5351,43 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -5292,19 +5351,43 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void { |
| 5292 | const ty = self.typeOf(un_op); | 5351 | const ty = self.typeOf(un_op); |
| 5293 | const abi_size: u32 = @intCast(ty.abiSize(mod)); | 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 | const result: MCValue = result: { | 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 | const mir_tag = @as(?Mir.Inst.FixedTag, switch (ty.zigTypeTag(mod)) { | 5387 | const mir_tag = @as(?Mir.Inst.FixedTag, switch (ty.zigTypeTag(mod)) { |
| 5306 | .Float => switch (ty.floatBits(self.target.*)) { | 5388 | .Float => switch (ty.floatBits(self.target.*)) { |
| 5307 | 16 => if (self.hasFeature(.f16c)) { | 5389 | 16 => { |
| | 5390 | assert(self.hasFeature(.f16c)); |
| 5308 | const mat_src_reg = if (src_mcv.isRegister()) | 5391 | const mat_src_reg = if (src_mcv.isRegister()) |
| 5309 | src_mcv.getReg().? | 5392 | src_mcv.getReg().? |
| 5310 | else | 5393 | else |
| ... | @@ -5318,10 +5401,9 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -5318,10 +5401,9 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void { |
| 5318 | Immediate.u(0b1_00), | 5401 | Immediate.u(0b1_00), |
| 5319 | ); | 5402 | ); |
| 5320 | break :result dst_mcv; | 5403 | break :result dst_mcv; |
| 5321 | } else null, | 5404 | }, |
| 5322 | 32 => if (self.hasFeature(.avx)) .{ .v_ss, .sqrt } else .{ ._ss, .sqrt }, | 5405 | 32 => if (self.hasFeature(.avx)) .{ .v_ss, .sqrt } else .{ ._ss, .sqrt }, |
| 5323 | 64 => if (self.hasFeature(.avx)) .{ .v_sd, .sqrt } else .{ ._sd, .sqrt }, | 5406 | 64 => if (self.hasFeature(.avx)) .{ .v_sd, .sqrt } else .{ ._sd, .sqrt }, |
| 5324 | 80, 128 => null, | | |
| 5325 | else => unreachable, | 5407 | else => unreachable, |
| 5326 | }, | 5408 | }, |
| 5327 | .Vector => switch (ty.childType(mod).zigTypeTag(mod)) { | 5409 | .Vector => switch (ty.childType(mod).zigTypeTag(mod)) { |
| ... | @@ -5395,21 +5477,9 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -5395,21 +5477,9 @@ fn airSqrt(self: *Self, inst: Air.Inst.Index) !void { |
| 5395 | else => unreachable, | 5477 | else => unreachable, |
| 5396 | }, | 5478 | }, |
| 5397 | else => unreachable, | 5479 | else => unreachable, |
| 5398 | }) orelse { | 5480 | }) orelse return self.fail("TODO implement airSqrt for {}", .{ |
| 5399 | if (ty.zigTypeTag(mod) != .Float) return self.fail("TODO implement airSqrt for {}", .{ | 5481 | ty.fmt(mod), |
| 5400 | ty.fmt(mod), | 5482 | }); |
| 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 | }; | | |
| 5413 | switch (mir_tag[0]) { | 5483 | switch (mir_tag[0]) { |
| 5414 | .v_ss, .v_sd => if (src_mcv.isMemory()) try self.asmRegisterRegisterMemory( | 5484 | .v_ss, .v_sd => if (src_mcv.isMemory()) try self.asmRegisterRegisterMemory( |
| 5415 | mir_tag, | 5485 | mir_tag, |
| ... | @@ -5536,7 +5606,7 @@ fn packedLoad(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) Inn | ... | @@ -5536,7 +5606,7 @@ fn packedLoad(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) Inn |
| 5536 | | 5606 | |
| 5537 | const dst_reg = switch (dst_mcv) { | 5607 | const dst_reg = switch (dst_mcv) { |
| 5538 | .register => |reg| reg, | 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 | const dst_lock = self.register_manager.lockReg(dst_reg); | 5611 | const dst_lock = self.register_manager.lockReg(dst_reg); |
| 5542 | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); | 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,7 +5625,8 @@ fn packedLoad(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) Inn |
| 5555 | ); | 5625 | ); |
| 5556 | try self.asmRegisterImmediate(.{ ._r, .sh }, load_reg, Immediate.u(val_bit_off)); | 5626 | try self.asmRegisterImmediate(.{ ._r, .sh }, load_reg, Immediate.u(val_bit_off)); |
| 5557 | } else { | 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 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); | 5630 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 5560 | defer self.register_manager.unlockReg(tmp_lock); | 5631 | defer self.register_manager.unlockReg(tmp_lock); |
| 5561 | | 5632 | |
| ... | @@ -5640,8 +5711,8 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -5640,8 +5711,8 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 5640 | const ptr_ty = self.typeOf(ty_op.operand); | 5711 | const ptr_ty = self.typeOf(ty_op.operand); |
| 5641 | const elem_size = elem_ty.abiSize(mod); | 5712 | const elem_size = elem_ty.abiSize(mod); |
| 5642 | | 5713 | |
| 5643 | const elem_rc = regClassForType(elem_ty, mod); | 5714 | const elem_rc = self.regClassForType(elem_ty); |
| 5644 | const ptr_rc = regClassForType(ptr_ty, mod); | 5715 | const ptr_rc = self.regClassForType(ptr_ty); |
| 5645 | | 5716 | |
| 5646 | const ptr_mcv = try self.resolveInst(ty_op.operand); | 5717 | const ptr_mcv = try self.resolveInst(ty_op.operand); |
| 5647 | const dst_mcv = if (elem_size <= 8 and elem_rc.supersetOf(ptr_rc) and | 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,13 +5767,13 @@ fn packedStore(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) In |
| 5696 | } else if (math.cast(i32, @as(i64, @bitCast(part_mask_not)))) |small| { | 5767 | } else if (math.cast(i32, @as(i64, @bitCast(part_mask_not)))) |small| { |
| 5697 | try self.asmMemoryImmediate(.{ ._, .@"and" }, limb_mem, Immediate.s(small)); | 5768 | try self.asmMemoryImmediate(.{ ._, .@"and" }, limb_mem, Immediate.s(small)); |
| 5698 | } else { | 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 | try self.asmRegisterImmediate(.{ ._, .mov }, part_mask_reg, Immediate.u(part_mask_not)); | 5771 | try self.asmRegisterImmediate(.{ ._, .mov }, part_mask_reg, Immediate.u(part_mask_not)); |
| 5701 | try self.asmMemoryRegister(.{ ._, .@"and" }, limb_mem, part_mask_reg); | 5772 | try self.asmMemoryRegister(.{ ._, .@"and" }, limb_mem, part_mask_reg); |
| 5702 | } | 5773 | } |
| 5703 | | 5774 | |
| 5704 | if (src_bit_size <= 64) { | 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 | const tmp_mcv = MCValue{ .register = tmp_reg }; | 5777 | const tmp_mcv = MCValue{ .register = tmp_reg }; |
| 5707 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); | 5778 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 5708 | defer self.register_manager.unlockReg(tmp_lock); | 5779 | defer self.register_manager.unlockReg(tmp_lock); |
| ... | @@ -5840,11 +5911,11 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -5840,11 +5911,11 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 5840 | const index = extra.field_index; | 5911 | const index = extra.field_index; |
| 5841 | | 5912 | |
| 5842 | const container_ty = self.typeOf(operand); | 5913 | const container_ty = self.typeOf(operand); |
| 5843 | const container_rc = regClassForType(container_ty, mod); | 5914 | const container_rc = self.regClassForType(container_ty); |
| 5844 | const field_ty = container_ty.structFieldType(index, mod); | 5915 | const field_ty = container_ty.structFieldType(index, mod); |
| 5845 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result .none; | 5916 | if (!field_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result .none; |
| 5846 | const field_rc = regClassForType(field_ty, mod); | 5917 | const field_rc = self.regClassForType(field_ty); |
| 5847 | const field_is_gp = field_rc.supersetOf(gp); | 5918 | const field_is_gp = field_rc.supersetOf(abi.RegisterClass.gp); |
| 5848 | | 5919 | |
| 5849 | const src_mcv = try self.resolveInst(operand); | 5920 | const src_mcv = try self.resolveInst(operand); |
| 5850 | const field_off: u32 = switch (container_ty.containerLayout(mod)) { | 5921 | const field_off: u32 = switch (container_ty.containerLayout(mod)) { |
| ... | @@ -5868,8 +5939,10 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -5868,8 +5939,10 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 5868 | @intCast(field_ty.bitSize(mod)), | 5939 | @intCast(field_ty.bitSize(mod)), |
| 5869 | ); | 5940 | ); |
| 5870 | | 5941 | |
| 5871 | const dst_reg = | 5942 | const dst_reg = try self.register_manager.allocReg( |
| 5872 | try self.register_manager.allocReg(if (field_is_gp) inst else null, gp); | 5943 | if (field_is_gp) inst else null, |
| | 5944 | abi.RegisterClass.gp, |
| | 5945 | ); |
| 5873 | const dst_mcv = MCValue{ .register = dst_reg }; | 5946 | const dst_mcv = MCValue{ .register = dst_reg }; |
| 5874 | const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg); | 5947 | const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg); |
| 5875 | defer self.register_manager.unlockReg(dst_lock); | 5948 | defer self.register_manager.unlockReg(dst_lock); |
| ... | @@ -5898,7 +5971,10 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -5898,7 +5971,10 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 5898 | return self.fail("TODO implement struct_field_val with large packed field", .{}); | 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 | const field_extra_bits = self.regExtraBits(field_ty); | 5978 | const field_extra_bits = self.regExtraBits(field_ty); |
| 5903 | const load_abi_size = | 5979 | const load_abi_size = |
| 5904 | if (field_bit_off < field_extra_bits) field_abi_size else field_abi_size * 2; | 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,7 +5991,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 5915 | try self.asmRegisterImmediate(.{ ._r, .sh }, load_reg, Immediate.u(field_bit_off)); | 5991 | try self.asmRegisterImmediate(.{ ._r, .sh }, load_reg, Immediate.u(field_bit_off)); |
| 5916 | } else { | 5992 | } else { |
| 5917 | const tmp_reg = registerAlias( | 5993 | const tmp_reg = registerAlias( |
| 5918 | try self.register_manager.allocReg(null, gp), | 5994 | try self.register_manager.allocReg(null, abi.RegisterClass.gp), |
| 5919 | field_abi_size, | 5995 | field_abi_size, |
| 5920 | ); | 5996 | ); |
| 5921 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); | 5997 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| ... | @@ -5975,7 +6051,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -5975,7 +6051,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 5975 | ); | 6051 | ); |
| 5976 | if (self.regExtraBits(field_ty) > 0) try self.truncateRegister(field_ty, dst_reg); | 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 | dst_mcv | 6055 | dst_mcv |
| 5980 | else | 6056 | else |
| 5981 | try self.copyToRegisterWithInstTracking(inst, field_ty, dst_mcv); | 6057 | try self.copyToRegisterWithInstTracking(inst, field_ty, dst_mcv); |
| ... | @@ -5996,7 +6072,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -5996,7 +6072,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 5996 | self.eflags_inst = inst; | 6072 | self.eflags_inst = inst; |
| 5997 | break :result .{ .eflags = ro.eflags }; | 6073 | break :result .{ .eflags = ro.eflags }; |
| 5998 | } else { | 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 | try self.asmSetccRegister(dst_reg.to8(), ro.eflags); | 6076 | try self.asmSetccRegister(dst_reg.to8(), ro.eflags); |
| 6001 | break :result .{ .register = dst_reg.to8() }; | 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,7 +6193,7 @@ fn genUnOpMir(self: *Self, mir_tag: Mir.Inst.FixedTag, dst_ty: Type, dst_mcv: MC |
| 6117 | .register => |dst_reg| try self.asmRegister(mir_tag, registerAlias(dst_reg, abi_size)), | 6193 | .register => |dst_reg| try self.asmRegister(mir_tag, registerAlias(dst_reg, abi_size)), |
| 6118 | .register_pair => unreachable, // unimplemented | 6194 | .register_pair => unreachable, // unimplemented |
| 6119 | .memory, .load_got, .load_direct, .load_tlv => { | 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 | const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg); | 6197 | const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg); |
| 6122 | defer self.register_manager.unlockReg(addr_reg_lock); | 6198 | defer self.register_manager.unlockReg(addr_reg_lock); |
| 6123 | | 6199 | |
| ... | @@ -6219,7 +6295,7 @@ fn genShiftBinOpMir( | ... | @@ -6219,7 +6295,7 @@ fn genShiftBinOpMir( |
| 6219 | }), | 6295 | }), |
| 6220 | } | 6296 | } |
| 6221 | } else if (abi_size <= 16) { | 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 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); | 6299 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 6224 | defer self.register_manager.unlockReg(tmp_lock); | 6300 | defer self.register_manager.unlockReg(tmp_lock); |
| 6225 | | 6301 | |
| ... | @@ -6297,11 +6373,11 @@ fn genShiftBinOpMir( | ... | @@ -6297,11 +6373,11 @@ fn genShiftBinOpMir( |
| 6297 | } | 6373 | } |
| 6298 | }, | 6374 | }, |
| 6299 | else => { | 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 | const first_lock = self.register_manager.lockRegAssumeUnused(first_reg); | 6377 | const first_lock = self.register_manager.lockRegAssumeUnused(first_reg); |
| 6302 | defer self.register_manager.unlockReg(first_lock); | 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 | const second_lock = self.register_manager.lockRegAssumeUnused(second_reg); | 6381 | const second_lock = self.register_manager.lockRegAssumeUnused(second_reg); |
| 6306 | defer self.register_manager.unlockReg(second_lock); | 6382 | defer self.register_manager.unlockReg(second_lock); |
| 6307 | | 6383 | |
| ... | @@ -6663,7 +6739,7 @@ fn genBinOp( | ... | @@ -6663,7 +6739,7 @@ fn genBinOp( |
| 6663 | if (!self.hasFeature(.avx) and self.hasFeature(.sse4_1)) mask: { | 6739 | if (!self.hasFeature(.avx) and self.hasFeature(.sse4_1)) mask: { |
| 6664 | try self.register_manager.getReg(.xmm0, null); | 6740 | try self.register_manager.getReg(.xmm0, null); |
| 6665 | break :mask .xmm0; | 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 | abi_size, | 6743 | abi_size, |
| 6668 | ) else null, | 6744 | ) else null, |
| 6669 | .rem, .mod => return self.fail("TODO implement genBinOp for {s} {}", .{ | 6745 | .rem, .mod => return self.fail("TODO implement genBinOp for {s} {}", .{ |
| ... | @@ -6916,7 +6992,8 @@ fn genBinOp( | ... | @@ -6916,7 +6992,8 @@ fn genBinOp( |
| 6916 | .Float => switch (lhs_ty.floatBits(self.target.*)) { | 6992 | .Float => switch (lhs_ty.floatBits(self.target.*)) { |
| 6917 | 16 => { | 6993 | 16 => { |
| 6918 | assert(self.hasFeature(.f16c)); | 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 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); | 6997 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 6921 | defer self.register_manager.unlockReg(tmp_lock); | 6998 | defer self.register_manager.unlockReg(tmp_lock); |
| 6922 | | 6999 | |
| ... | @@ -7223,7 +7300,10 @@ fn genBinOp( | ... | @@ -7223,7 +7300,10 @@ fn genBinOp( |
| 7223 | assert(self.hasFeature(.f16c)); | 7300 | assert(self.hasFeature(.f16c)); |
| 7224 | switch (lhs_ty.vectorLen(mod)) { | 7301 | switch (lhs_ty.vectorLen(mod)) { |
| 7225 | 1 => { | 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 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); | 7307 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 7228 | defer self.register_manager.unlockReg(tmp_lock); | 7308 | defer self.register_manager.unlockReg(tmp_lock); |
| 7229 | | 7309 | |
| ... | @@ -7267,7 +7347,10 @@ fn genBinOp( | ... | @@ -7267,7 +7347,10 @@ fn genBinOp( |
| 7267 | return dst_mcv; | 7347 | return dst_mcv; |
| 7268 | }, | 7348 | }, |
| 7269 | 2 => { | 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 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); | 7354 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 7272 | defer self.register_manager.unlockReg(tmp_lock); | 7355 | defer self.register_manager.unlockReg(tmp_lock); |
| 7273 | | 7356 | |
| ... | @@ -7315,7 +7398,10 @@ fn genBinOp( | ... | @@ -7315,7 +7398,10 @@ fn genBinOp( |
| 7315 | return dst_mcv; | 7398 | return dst_mcv; |
| 7316 | }, | 7399 | }, |
| 7317 | 3...4 => { | 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 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); | 7405 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 7320 | defer self.register_manager.unlockReg(tmp_lock); | 7406 | defer self.register_manager.unlockReg(tmp_lock); |
| 7321 | | 7407 | |
| ... | @@ -7355,7 +7441,10 @@ fn genBinOp( | ... | @@ -7355,7 +7441,10 @@ fn genBinOp( |
| 7355 | return dst_mcv; | 7441 | return dst_mcv; |
| 7356 | }, | 7442 | }, |
| 7357 | 5...8 => { | 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 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); | 7448 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 7360 | defer self.register_manager.unlockReg(tmp_lock); | 7449 | defer self.register_manager.unlockReg(tmp_lock); |
| 7361 | | 7450 | |
| ... | @@ -7948,7 +8037,8 @@ fn genBinOpMir( | ... | @@ -7948,7 +8037,8 @@ fn genBinOpMir( |
| 7948 | const dst_info: OpInfo = switch (dst_mcv) { | 8037 | const dst_info: OpInfo = switch (dst_mcv) { |
| 7949 | else => unreachable, | 8038 | else => unreachable, |
| 7950 | .memory, .load_got, .load_direct, .load_tlv => dst: { | 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 | const dst_addr_lock = self.register_manager.lockRegAssumeUnused(dst_addr_reg); | 8042 | const dst_addr_lock = self.register_manager.lockRegAssumeUnused(dst_addr_reg); |
| 7953 | errdefer self.register_manager.unlockReg(dst_addr_lock); | 8043 | errdefer self.register_manager.unlockReg(dst_addr_lock); |
| 7954 | | 8044 | |
| ... | @@ -7993,7 +8083,8 @@ fn genBinOpMir( | ... | @@ -7993,7 +8083,8 @@ fn genBinOpMir( |
| 7993 | else => unreachable, | 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 | const src_addr_lock = self.register_manager.lockRegAssumeUnused(src_addr_reg); | 8088 | const src_addr_lock = self.register_manager.lockRegAssumeUnused(src_addr_reg); |
| 7998 | errdefer self.register_manager.unlockReg(src_addr_lock); | 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,6 +8710,7 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void { |
| 8619 | const mod = self.bin_file.options.module.?; | 8710 | const mod = self.bin_file.options.module.?; |
| 8620 | const un_op = self.air.instructions.items(.data)[inst].un_op; | 8711 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 8621 | const operand = try self.resolveInst(un_op); | 8712 | const operand = try self.resolveInst(un_op); |
| | 8713 | |
| 8622 | const ret_ty = self.fn_type.fnReturnType(mod); | 8714 | const ret_ty = self.fn_type.fnReturnType(mod); |
| 8623 | switch (self.ret_mcv.short) { | 8715 | switch (self.ret_mcv.short) { |
| 8624 | .none => {}, | 8716 | .none => {}, |
| ... | @@ -8633,6 +8725,8 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -8633,6 +8725,8 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void { |
| 8633 | }, | 8725 | }, |
| 8634 | else => unreachable, | 8726 | else => unreachable, |
| 8635 | } | 8727 | } |
| | 8728 | self.ret_mcv.liveOut(self, inst); |
| | 8729 | |
| 8636 | // TODO optimization opportunity: figure out when we can emit this as a 2 byte instruction | 8730 | // TODO optimization opportunity: figure out when we can emit this as a 2 byte instruction |
| 8637 | // which is available if the jump is 127 bytes or less forward. | 8731 | // which is available if the jump is 127 bytes or less forward. |
| 8638 | const jmp_reloc = try self.asmJmpReloc(undefined); | 8732 | const jmp_reloc = try self.asmJmpReloc(undefined); |
| ... | @@ -8643,6 +8737,7 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -8643,6 +8737,7 @@ fn airRet(self: *Self, inst: Air.Inst.Index) !void { |
| 8643 | fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void { | 8737 | fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 8644 | const un_op = self.air.instructions.items(.data)[inst].un_op; | 8738 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 8645 | const ptr = try self.resolveInst(un_op); | 8739 | const ptr = try self.resolveInst(un_op); |
| | 8740 | |
| 8646 | const ptr_ty = self.typeOf(un_op); | 8741 | const ptr_ty = self.typeOf(un_op); |
| 8647 | switch (self.ret_mcv.short) { | 8742 | switch (self.ret_mcv.short) { |
| 8648 | .none => {}, | 8743 | .none => {}, |
| ... | @@ -8650,6 +8745,8 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -8650,6 +8745,8 @@ fn airRetLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 8650 | .indirect => |reg_off| try self.genSetReg(reg_off.reg, ptr_ty, ptr), | 8745 | .indirect => |reg_off| try self.genSetReg(reg_off.reg, ptr_ty, ptr), |
| 8651 | else => unreachable, | 8746 | else => unreachable, |
| 8652 | } | 8747 | } |
| | 8748 | self.ret_mcv.liveOut(self, inst); |
| | 8749 | |
| 8653 | // TODO optimization opportunity: figure out when we can emit this as a 2 byte instruction | 8750 | // TODO optimization opportunity: figure out when we can emit this as a 2 byte instruction |
| 8654 | // which is available if the jump is 127 bytes or less forward. | 8751 | // which is available if the jump is 127 bytes or less forward. |
| 8655 | const jmp_reloc = try self.asmJmpReloc(undefined); | 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,8 +8897,10 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 8800 | else => unreachable, | 8897 | else => unreachable, |
| 8801 | } | 8898 | } |
| 8802 | | 8899 | |
| 8803 | const dst_addr_reg = | 8900 | const dst_addr_reg = (try self.register_manager.allocReg( |
| 8804 | (try self.register_manager.allocReg(null, gp)).to64(); | 8901 | null, |
| | 8902 | abi.RegisterClass.gp, |
| | 8903 | )).to64(); |
| 8805 | const dst_addr_lock = | 8904 | const dst_addr_lock = |
| 8806 | self.register_manager.lockRegAssumeUnused(dst_addr_reg); | 8905 | self.register_manager.lockRegAssumeUnused(dst_addr_reg); |
| 8807 | errdefer self.register_manager.unlockReg(dst_addr_lock); | 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,8 +8955,10 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 8856 | else => unreachable, | 8955 | else => unreachable, |
| 8857 | } | 8956 | } |
| 8858 | | 8957 | |
| 8859 | const src_addr_reg = | 8958 | const src_addr_reg = (try self.register_manager.allocReg( |
| 8860 | (try self.register_manager.allocReg(null, gp)).to64(); | 8959 | null, |
| | 8960 | abi.RegisterClass.gp, |
| | 8961 | )).to64(); |
| 8861 | const src_addr_lock = | 8962 | const src_addr_lock = |
| 8862 | self.register_manager.lockRegAssumeUnused(src_addr_reg); | 8963 | self.register_manager.lockRegAssumeUnused(src_addr_reg); |
| 8863 | errdefer self.register_manager.unlockReg(src_addr_lock); | 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,8 +8977,11 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 8876 | defer if (src_info) |info| | 8977 | defer if (src_info) |info| |
| 8877 | self.register_manager.unlockReg(info.addr_lock); | 8978 | self.register_manager.unlockReg(info.addr_lock); |
| 8878 | | 8979 | |
| 8879 | const regs = | 8980 | const regs = try self.register_manager.allocRegs( |
| 8880 | try self.register_manager.allocRegs(2, .{ null, null }, gp); | 8981 | 2, |
| | 8982 | .{ null, null }, |
| | 8983 | abi.RegisterClass.gp, |
| | 8984 | ); |
| 8881 | const acc_reg = regs[0].to64(); | 8985 | const acc_reg = regs[0].to64(); |
| 8882 | const locks = self.register_manager.lockRegsAssumeUnused(2, regs); | 8986 | const locks = self.register_manager.lockRegsAssumeUnused(2, regs); |
| 8883 | defer for (locks) |lock| self.register_manager.unlockReg(lock); | 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,12 +9068,14 @@ fn airCmp(self: *Self, inst: Air.Inst.Index, op: math.CompareOperator) !void { |
| 8964 | switch (ty.floatBits(self.target.*)) { | 9068 | switch (ty.floatBits(self.target.*)) { |
| 8965 | 16 => { | 9069 | 16 => { |
| 8966 | assert(self.hasFeature(.f16c)); | 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 | const tmp1_mcv = MCValue{ .register = tmp1_reg }; | 9073 | const tmp1_mcv = MCValue{ .register = tmp1_reg }; |
| 8969 | const tmp1_lock = self.register_manager.lockRegAssumeUnused(tmp1_reg); | 9074 | const tmp1_lock = self.register_manager.lockRegAssumeUnused(tmp1_reg); |
| 8970 | defer self.register_manager.unlockReg(tmp1_lock); | 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 | const tmp2_mcv = MCValue{ .register = tmp2_reg }; | 9079 | const tmp2_mcv = MCValue{ .register = tmp2_reg }; |
| 8974 | const tmp2_lock = self.register_manager.lockRegAssumeUnused(tmp2_reg); | 9080 | const tmp2_lock = self.register_manager.lockRegAssumeUnused(tmp2_reg); |
| 8975 | defer self.register_manager.unlockReg(tmp2_lock); | 9081 | defer self.register_manager.unlockReg(tmp2_lock); |
| ... | @@ -9032,7 +9138,7 @@ fn airCmpLtErrorsLen(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -9032,7 +9138,7 @@ fn airCmpLtErrorsLen(self: *Self, inst: Air.Inst.Index) !void { |
| 9032 | const mod = self.bin_file.options.module.?; | 9138 | const mod = self.bin_file.options.module.?; |
| 9033 | const un_op = self.air.instructions.items(.data)[inst].un_op; | 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 | const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg); | 9142 | const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg); |
| 9037 | defer self.register_manager.unlockReg(addr_lock); | 9143 | defer self.register_manager.unlockReg(addr_lock); |
| 9038 | try self.genLazySymbolRef(.lea, addr_reg, link.File.LazySymbol.initDecl(.const_data, null, mod)); | 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,7 +9399,7 @@ fn isNull(self: *Self, inst: Air.Inst.Index, opt_ty: Type, opt_mcv: MCValue) !MC |
| 9293 | .load_direct, | 9399 | .load_direct, |
| 9294 | .load_tlv, | 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 | const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg); | 9403 | const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg); |
| 9298 | defer self.register_manager.unlockReg(addr_reg_lock); | 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,7 +9884,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { |
| 9778 | else => self.typeOf(output).childType(mod), | 9884 | else => self.typeOf(output).childType(mod), |
| 9779 | }; | 9885 | }; |
| 9780 | const arg_maybe_reg: ?Register = if (mem.eql(u8, constraint, "=r")) | 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 | return self.fail("ran out of registers lowering inline asm", .{}) | 9888 | return self.fail("ran out of registers lowering inline asm", .{}) |
| 9783 | else if (mem.eql(u8, constraint, "=m")) | 9889 | else if (mem.eql(u8, constraint, "=m")) |
| 9784 | if (output != .none) null else return self.fail( | 9890 | if (output != .none) null else return self.fail( |
| ... | @@ -9786,7 +9892,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -9786,7 +9892,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { |
| 9786 | .{}, | 9892 | .{}, |
| 9787 | ) | 9893 | ) |
| 9788 | else if (mem.eql(u8, constraint, "=g")) | 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 | if (output != .none) null else return self.fail( | 9896 | if (output != .none) null else return self.fail( |
| 9791 | "ran out of register lowering inline asm", | 9897 | "ran out of register lowering inline asm", |
| 9792 | .{}, | 9898 | .{}, |
| ... | @@ -9840,7 +9946,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -9840,7 +9946,7 @@ fn airAsm(self: *Self, inst: Air.Inst.Index) !void { |
| 9840 | break :arg temp_mcv; | 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 | const temp_mcv = try self.allocTempRegOrMem(ty, false); | 9950 | const temp_mcv = try self.allocTempRegOrMem(ty, false); |
| 9845 | try self.genCopy(ty, temp_mcv, input_mcv); | 9951 | try self.genCopy(ty, temp_mcv, input_mcv); |
| 9846 | break :arg temp_mcv; | 9952 | break :arg temp_mcv; |
| ... | @@ -10946,8 +11052,8 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -10946,8 +11052,8 @@ fn airBitCast(self: *Self, inst: Air.Inst.Index) !void { |
| 10946 | const src_ty = self.typeOf(ty_op.operand); | 11052 | const src_ty = self.typeOf(ty_op.operand); |
| 10947 | | 11053 | |
| 10948 | const result = result: { | 11054 | const result = result: { |
| 10949 | const dst_rc = regClassForType(dst_ty, mod); | 11055 | const dst_rc = self.regClassForType(dst_ty); |
| 10950 | const src_rc = regClassForType(src_ty, mod); | 11056 | const src_rc = self.regClassForType(src_ty); |
| 10951 | const src_mcv = try self.resolveInst(ty_op.operand); | 11057 | const src_mcv = try self.resolveInst(ty_op.operand); |
| 10952 | | 11058 | |
| 10953 | const src_lock = if (src_mcv.getReg()) |reg| self.register_manager.lockReg(reg) else null; | 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,7 +11180,7 @@ fn airFloatFromInt(self: *Self, inst: Air.Inst.Index) !void { |
| 11074 | | 11180 | |
| 11075 | if (src_bits < src_size * 8) try self.truncateRegister(src_ty, src_reg); | 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 | const dst_mcv = MCValue{ .register = dst_reg }; | 11184 | const dst_mcv = MCValue{ .register = dst_reg }; |
| 11079 | const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg); | 11185 | const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg); |
| 11080 | defer self.register_manager.unlockReg(dst_lock); | 11186 | defer self.register_manager.unlockReg(dst_lock); |
| ... | @@ -11151,7 +11257,7 @@ fn airIntFromFloat(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -11151,7 +11257,7 @@ fn airIntFromFloat(self: *Self, inst: Air.Inst.Index) !void { |
| 11151 | const src_lock = self.register_manager.lockRegAssumeUnused(src_reg); | 11257 | const src_lock = self.register_manager.lockRegAssumeUnused(src_reg); |
| 11152 | defer self.register_manager.unlockReg(src_lock); | 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 | const dst_mcv = MCValue{ .register = dst_reg }; | 11261 | const dst_mcv = MCValue{ .register = dst_reg }; |
| 11156 | const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg); | 11262 | const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg); |
| 11157 | defer self.register_manager.unlockReg(dst_lock); | 11263 | defer self.register_manager.unlockReg(dst_lock); |
| ... | @@ -11332,7 +11438,7 @@ fn atomicOp( | ... | @@ -11332,7 +11438,7 @@ fn atomicOp( |
| 11332 | .SeqCst => .xchg, | 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 | const dst_mcv = MCValue{ .register = dst_reg }; | 11442 | const dst_mcv = MCValue{ .register = dst_reg }; |
| 11337 | const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg); | 11443 | const dst_lock = self.register_manager.lockRegAssumeUnused(dst_reg); |
| 11338 | defer self.register_manager.unlockReg(dst_lock); | 11444 | defer self.register_manager.unlockReg(dst_lock); |
| ... | @@ -11354,7 +11460,7 @@ fn atomicOp( | ... | @@ -11354,7 +11460,7 @@ fn atomicOp( |
| 11354 | return if (unused) .unreach else dst_mcv; | 11460 | return if (unused) .unreach else dst_mcv; |
| 11355 | }, | 11461 | }, |
| 11356 | .loop => _ = if (val_abi_size <= 8) { | 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 | const tmp_mcv = MCValue{ .register = tmp_reg }; | 11464 | const tmp_mcv = MCValue{ .register = tmp_reg }; |
| 11359 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); | 11465 | const tmp_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 11360 | defer self.register_manager.unlockReg(tmp_lock); | 11466 | defer self.register_manager.unlockReg(tmp_lock); |
| ... | @@ -11628,7 +11734,7 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void { | ... | @@ -11628,7 +11734,7 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void { |
| 11628 | | 11734 | |
| 11629 | // Used to store the number of elements for comparison. | 11735 | // Used to store the number of elements for comparison. |
| 11630 | // After comparison, updated to store number of bytes needed to copy. | 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 | const len_mcv: MCValue = .{ .register = len_reg }; | 11738 | const len_mcv: MCValue = .{ .register = len_reg }; |
| 11633 | const len_lock = self.register_manager.lockRegAssumeUnused(len_reg); | 11739 | const len_lock = self.register_manager.lockRegAssumeUnused(len_reg); |
| 11634 | defer self.register_manager.unlockReg(len_lock); | 11740 | defer self.register_manager.unlockReg(len_lock); |
| ... | @@ -11638,7 +11744,7 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void { | ... | @@ -11638,7 +11744,7 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void { |
| 11638 | const skip_reloc = try self.asmJccReloc(undefined, .z); | 11744 | const skip_reloc = try self.asmJccReloc(undefined, .z); |
| 11639 | try self.store(slice_ptr_ty, ptr, src_val); | 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 | const second_elem_ptr_mcv: MCValue = .{ .register = second_elem_ptr_reg }; | 11748 | const second_elem_ptr_mcv: MCValue = .{ .register = second_elem_ptr_reg }; |
| 11643 | const second_elem_ptr_lock = self.register_manager.lockRegAssumeUnused(second_elem_ptr_reg); | 11749 | const second_elem_ptr_lock = self.register_manager.lockRegAssumeUnused(second_elem_ptr_reg); |
| 11644 | defer self.register_manager.unlockReg(second_elem_ptr_lock); | 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,7 +11773,7 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void { |
| 11667 | assert(len != 0); // prevented by Sema | 11773 | assert(len != 0); // prevented by Sema |
| 11668 | try self.store(elem_ptr_ty, dst_ptr, src_val); | 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 | const second_elem_ptr_mcv: MCValue = .{ .register = second_elem_ptr_reg }; | 11777 | const second_elem_ptr_mcv: MCValue = .{ .register = second_elem_ptr_reg }; |
| 11672 | const second_elem_ptr_lock = self.register_manager.lockRegAssumeUnused(second_elem_ptr_reg); | 11778 | const second_elem_ptr_lock = self.register_manager.lockRegAssumeUnused(second_elem_ptr_reg); |
| 11673 | defer self.register_manager.unlockReg(second_elem_ptr_lock); | 11779 | defer self.register_manager.unlockReg(second_elem_ptr_lock); |
| ... | @@ -11774,16 +11880,16 @@ fn airErrorName(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -11774,16 +11880,16 @@ fn airErrorName(self: *Self, inst: Air.Inst.Index) !void { |
| 11774 | const err_lock = self.register_manager.lockRegAssumeUnused(err_reg); | 11880 | const err_lock = self.register_manager.lockRegAssumeUnused(err_reg); |
| 11775 | defer self.register_manager.unlockReg(err_lock); | 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 | const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg); | 11884 | const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg); |
| 11779 | defer self.register_manager.unlockReg(addr_lock); | 11885 | defer self.register_manager.unlockReg(addr_lock); |
| 11780 | try self.genLazySymbolRef(.lea, addr_reg, link.File.LazySymbol.initDecl(.const_data, null, mod)); | 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 | const start_lock = self.register_manager.lockRegAssumeUnused(start_reg); | 11889 | const start_lock = self.register_manager.lockRegAssumeUnused(start_reg); |
| 11784 | defer self.register_manager.unlockReg(start_lock); | 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 | const end_lock = self.register_manager.lockRegAssumeUnused(end_reg); | 11893 | const end_lock = self.register_manager.lockRegAssumeUnused(end_reg); |
| 11788 | defer self.register_manager.unlockReg(end_lock); | 11894 | defer self.register_manager.unlockReg(end_lock); |
| 11789 | | 11895 | |
| ... | @@ -11851,7 +11957,7 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -11851,7 +11957,7 @@ fn airSplat(self: *Self, inst: Air.Inst.Index) !void { |
| 11851 | const mod = self.bin_file.options.module.?; | 11957 | const mod = self.bin_file.options.module.?; |
| 11852 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 11958 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 11853 | const vector_ty = self.typeOfIndex(inst); | 11959 | const vector_ty = self.typeOfIndex(inst); |
| 11854 | const dst_rc = regClassForType(vector_ty, mod); | 11960 | const dst_rc = self.regClassForType(vector_ty); |
| 11855 | const scalar_ty = vector_ty.scalarType(mod); | 11961 | const scalar_ty = vector_ty.scalarType(mod); |
| 11856 | | 11962 | |
| 11857 | const src_mcv = try self.resolveInst(ty_op.operand); | 11963 | const src_mcv = try self.resolveInst(ty_op.operand); |