| ... | ... | @@ -38,6 +38,9 @@ const c_abi_int_return_regs = abi.c_abi_int_return_regs; |
| 38 | 38 | const RegisterManager = RegisterManagerFn(Self, Register, &allocatable_registers); |
| 39 | 39 | const RegisterLock = RegisterManager.RegisterLock; |
| 40 | 40 | const Register = bits.Register; |
| 41 | const RegisterClass = abi.RegisterClass; |
| 42 | const gp = RegisterClass.gp; |
| 43 | const avx = RegisterClass.avx; |
| 41 | 44 | |
| 42 | 45 | const InnerError = error{ |
| 43 | 46 | OutOfMemory, |
| ... | ... | @@ -882,7 +885,9 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue { |
| 882 | 885 | // TODO check if AVX available |
| 883 | 886 | const ptr_bytes: u64 = 32; |
| 884 | 887 | if (abi_size <= ptr_bytes) { |
| 885 | | if (self.register_manager.tryAllocReg(inst, .{})) |reg| { |
| 888 | if (self.register_manager.tryAllocReg(inst, .{ |
| 889 | .selector_mask = avx, |
| 890 | })) |reg| { |
| 886 | 891 | return MCValue{ .register = registerAlias(reg, abi_size) }; |
| 887 | 892 | } |
| 888 | 893 | } |
| ... | ... | @@ -892,7 +897,9 @@ fn allocRegOrMem(self: *Self, inst: Air.Inst.Index, reg_ok: bool) !MCValue { |
| 892 | 897 | const ptr_bits = self.target.cpu.arch.ptrBitWidth(); |
| 893 | 898 | const ptr_bytes: u64 = @divExact(ptr_bits, 8); |
| 894 | 899 | if (abi_size <= ptr_bytes) { |
| 895 | | if (self.register_manager.tryAllocReg(inst, .{})) |reg| { |
| 900 | if (self.register_manager.tryAllocReg(inst, .{ |
| 901 | .selector_mask = gp, |
| 902 | })) |reg| { |
| 896 | 903 | return MCValue{ .register = registerAlias(reg, abi_size) }; |
| 897 | 904 | } |
| 898 | 905 | } |
| ... | ... | @@ -963,7 +970,13 @@ pub fn spillRegisters(self: *Self, comptime count: comptime_int, registers: [cou |
| 963 | 970 | /// allocated. A second call to `copyToTmpRegister` may return the same register. |
| 964 | 971 | /// This can have a side effect of spilling instructions to the stack to free up a register. |
| 965 | 972 | fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register { |
| 966 | | const reg = try self.register_manager.allocReg(null, .{}); |
| 973 | const mask = switch (ty.zigTypeTag()) { |
| 974 | .Float => avx, |
| 975 | else => gp, |
| 976 | }; |
| 977 | const reg: Register = try self.register_manager.allocReg(null, .{ |
| 978 | .selector_mask = mask, |
| 979 | }); |
| 967 | 980 | try self.genSetReg(ty, reg, mcv); |
| 968 | 981 | return reg; |
| 969 | 982 | } |
| ... | ... | @@ -973,7 +986,13 @@ fn copyToTmpRegister(self: *Self, ty: Type, mcv: MCValue) !Register { |
| 973 | 986 | /// This can have a side effect of spilling instructions to the stack to free up a register. |
| 974 | 987 | /// WARNING make sure that the allocated register matches the returned MCValue from an instruction! |
| 975 | 988 | fn copyToRegisterWithInstTracking(self: *Self, reg_owner: Air.Inst.Index, ty: Type, mcv: MCValue) !MCValue { |
| 976 | | const reg = try self.register_manager.allocReg(reg_owner, .{}); |
| 989 | const mask = switch (ty.zigTypeTag()) { |
| 990 | .Float => avx, |
| 991 | else => gp, |
| 992 | }; |
| 993 | const reg: Register = try self.register_manager.allocReg(reg_owner, .{ |
| 994 | .selector_mask = mask, |
| 995 | }); |
| 977 | 996 | try self.genSetReg(ty, reg, mcv); |
| 978 | 997 | return MCValue{ .register = reg }; |
| 979 | 998 | } |
| ... | ... | @@ -1029,7 +1048,9 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void { |
| 1029 | 1048 | }; |
| 1030 | 1049 | defer if (operand_lock) |lock| self.register_manager.unlockReg(lock); |
| 1031 | 1050 | |
| 1032 | | const reg = try self.register_manager.allocReg(inst, .{}); |
| 1051 | const reg = try self.register_manager.allocReg(inst, .{ |
| 1052 | .selector_mask = gp, |
| 1053 | }); |
| 1033 | 1054 | try self.genSetReg(dest_ty, reg, .{ .immediate = 0 }); |
| 1034 | 1055 | try self.genSetReg(operand_ty, reg, operand); |
| 1035 | 1056 | break :blk MCValue{ .register = reg }; |
| ... | ... | @@ -1384,7 +1405,9 @@ fn genSetStackTruncatedOverflowCompare( |
| 1384 | 1405 | .unsigned => ty, |
| 1385 | 1406 | }; |
| 1386 | 1407 | |
| 1387 | | const temp_regs = try self.register_manager.allocRegs(3, .{ null, null, null }, .{}); |
| 1408 | const temp_regs = try self.register_manager.allocRegs(3, .{ null, null, null }, .{ |
| 1409 | .selector_mask = gp, |
| 1410 | }); |
| 1388 | 1411 | const temp_regs_locks = self.register_manager.lockRegsAssumeUnused(3, temp_regs); |
| 1389 | 1412 | defer for (temp_regs_locks) |rreg| { |
| 1390 | 1413 | self.register_manager.unlockReg(rreg); |
| ... | ... | @@ -2046,7 +2069,9 @@ fn genSliceElemPtr(self: *Self, lhs: Air.Inst.Ref, rhs: Air.Inst.Ref) !MCValue { |
| 2046 | 2069 | const offset_reg_lock = self.register_manager.lockRegAssumeUnused(offset_reg); |
| 2047 | 2070 | defer self.register_manager.unlockReg(offset_reg_lock); |
| 2048 | 2071 | |
| 2049 | | const addr_reg = try self.register_manager.allocReg(null, .{}); |
| 2072 | const addr_reg = try self.register_manager.allocReg(null, .{ |
| 2073 | .selector_mask = gp, |
| 2074 | }); |
| 2050 | 2075 | switch (slice_mcv) { |
| 2051 | 2076 | .stack_offset => |off| { |
| 2052 | 2077 | // mov reg, [rbp - 8] |
| ... | ... | @@ -2125,7 +2150,9 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2125 | 2150 | const offset_reg_lock = self.register_manager.lockRegAssumeUnused(offset_reg); |
| 2126 | 2151 | defer self.register_manager.unlockReg(offset_reg_lock); |
| 2127 | 2152 | |
| 2128 | | const addr_reg = try self.register_manager.allocReg(null, .{}); |
| 2153 | const addr_reg = try self.register_manager.allocReg(null, .{ |
| 2154 | .selector_mask = gp, |
| 2155 | }); |
| 2129 | 2156 | switch (array) { |
| 2130 | 2157 | .register => { |
| 2131 | 2158 | const off = @intCast(i32, try self.allocMem( |
| ... | ... | @@ -2492,7 +2519,7 @@ fn load(self: *Self, dst_mcv: MCValue, ptr: MCValue, ptr_ty: Type) InnerError!vo |
| 2492 | 2519 | }, |
| 2493 | 2520 | .stack_offset => |off| { |
| 2494 | 2521 | if (abi_size <= 8) { |
| 2495 | | const tmp_reg = try self.register_manager.allocReg(null, .{}); |
| 2522 | const tmp_reg = try self.register_manager.allocReg(null, .{ .selector_mask = gp }); |
| 2496 | 2523 | try self.load(.{ .register = tmp_reg }, ptr, ptr_ty); |
| 2497 | 2524 | return self.genSetStack(elem_ty, off, MCValue{ .register = tmp_reg }, .{}); |
| 2498 | 2525 | } |
| ... | ... | @@ -2693,7 +2720,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2693 | 2720 | }; |
| 2694 | 2721 | defer if (value_lock) |lock| self.register_manager.unlockReg(lock); |
| 2695 | 2722 | |
| 2696 | | const addr_reg = try self.register_manager.allocReg(null, .{}); |
| 2723 | const addr_reg = try self.register_manager.allocReg(null, .{ .selector_mask = gp }); |
| 2697 | 2724 | const addr_reg_lock = self.register_manager.lockRegAssumeUnused(addr_reg); |
| 2698 | 2725 | defer self.register_manager.unlockReg(addr_reg_lock); |
| 2699 | 2726 | |
| ... | ... | @@ -2765,7 +2792,7 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type |
| 2765 | 2792 | .memory, |
| 2766 | 2793 | => { |
| 2767 | 2794 | if (abi_size <= 8) { |
| 2768 | | const tmp_reg = try self.register_manager.allocReg(null, .{}); |
| 2795 | const tmp_reg = try self.register_manager.allocReg(null, .{ .selector_mask = gp }); |
| 2769 | 2796 | const tmp_reg_lock = self.register_manager.lockRegAssumeUnused(tmp_reg); |
| 2770 | 2797 | defer self.register_manager.unlockReg(tmp_reg_lock); |
| 2771 | 2798 | |
| ... | ... | @@ -2883,7 +2910,7 @@ fn structFieldPtr(self: *Self, inst: Air.Inst.Index, operand: Air.Inst.Ref, inde |
| 2883 | 2910 | if (can_reuse_operand) { |
| 2884 | 2911 | break :blk reg; |
| 2885 | 2912 | } else { |
| 2886 | | const result_reg = try self.register_manager.allocReg(inst, .{}); |
| 2913 | const result_reg = try self.register_manager.allocReg(inst, .{ .selector_mask = gp }); |
| 2887 | 2914 | try self.genSetReg(ptr_ty, result_reg, mcv); |
| 2888 | 2915 | break :blk result_reg; |
| 2889 | 2916 | } |
| ... | ... | @@ -2984,7 +3011,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 2984 | 3011 | const reg_lock = self.register_manager.lockRegAssumeUnused(reg); |
| 2985 | 3012 | defer self.register_manager.unlockReg(reg_lock); |
| 2986 | 3013 | |
| 2987 | | const dst_reg = try self.register_manager.allocReg(inst, .{}); |
| 3014 | const dst_reg = try self.register_manager.allocReg(inst, .{ .selector_mask = gp }); |
| 2988 | 3015 | const flags: u2 = switch (mcv) { |
| 2989 | 3016 | .register_overflow_unsigned => 0b10, |
| 2990 | 3017 | .register_overflow_signed => 0b00, |
| ... | ... | @@ -5362,7 +5389,7 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue, opts: Inl |
| 5362 | 5389 | |
| 5363 | 5390 | const overflow_bit_ty = ty.structFieldType(1); |
| 5364 | 5391 | const overflow_bit_offset = ty.structFieldOffset(1, self.target.*); |
| 5365 | | const tmp_reg = try self.register_manager.allocReg(null, .{}); |
| 5392 | const tmp_reg = try self.register_manager.allocReg(null, .{ .selector_mask = gp }); |
| 5366 | 5393 | const flags: u2 = switch (mcv) { |
| 5367 | 5394 | .register_overflow_unsigned => 0b10, |
| 5368 | 5395 | .register_overflow_signed => 0b00, |
| ... | ... | @@ -5580,7 +5607,7 @@ fn genInlineMemcpy( |
| 5580 | 5607 | null; |
| 5581 | 5608 | defer if (dsbase_lock) |lock| self.register_manager.unlockReg(lock); |
| 5582 | 5609 | |
| 5583 | | const dst_addr_reg = try self.register_manager.allocReg(null, .{}); |
| 5610 | const dst_addr_reg = try self.register_manager.allocReg(null, .{ .selector_mask = gp }); |
| 5584 | 5611 | switch (dst_ptr) { |
| 5585 | 5612 | .memory, |
| 5586 | 5613 | .got_load, |
| ... | ... | @@ -5615,7 +5642,7 @@ fn genInlineMemcpy( |
| 5615 | 5642 | const dst_addr_reg_lock = self.register_manager.lockRegAssumeUnused(dst_addr_reg); |
| 5616 | 5643 | defer self.register_manager.unlockReg(dst_addr_reg_lock); |
| 5617 | 5644 | |
| 5618 | | const src_addr_reg = try self.register_manager.allocReg(null, .{}); |
| 5645 | const src_addr_reg = try self.register_manager.allocReg(null, .{ .selector_mask = gp }); |
| 5619 | 5646 | switch (src_ptr) { |
| 5620 | 5647 | .memory, |
| 5621 | 5648 | .got_load, |
| ... | ... | @@ -5650,7 +5677,9 @@ fn genInlineMemcpy( |
| 5650 | 5677 | const src_addr_reg_lock = self.register_manager.lockRegAssumeUnused(src_addr_reg); |
| 5651 | 5678 | defer self.register_manager.unlockReg(src_addr_reg_lock); |
| 5652 | 5679 | |
| 5653 | | const regs = try self.register_manager.allocRegs(2, .{ null, null }, .{}); |
| 5680 | const regs = try self.register_manager.allocRegs(2, .{ null, null }, .{ |
| 5681 | .selector_mask = gp, |
| 5682 | }); |
| 5654 | 5683 | const count_reg = regs[0].to64(); |
| 5655 | 5684 | const tmp_reg = regs[1].to8(); |
| 5656 | 5685 | |
| ... | ... | @@ -5750,7 +5779,7 @@ fn genInlineMemset( |
| 5750 | 5779 | const rax_lock = self.register_manager.lockRegAssumeUnused(.rax); |
| 5751 | 5780 | defer self.register_manager.unlockReg(rax_lock); |
| 5752 | 5781 | |
| 5753 | | const addr_reg = try self.register_manager.allocReg(null, .{}); |
| 5782 | const addr_reg = try self.register_manager.allocReg(null, .{ .selector_mask = gp }); |
| 5754 | 5783 | switch (dst_ptr) { |
| 5755 | 5784 | .memory, |
| 5756 | 5785 | .got_load, |
| ... | ... | @@ -6018,7 +6047,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 6018 | 6047 | switch (ty.tag()) { |
| 6019 | 6048 | .f32 => return self.fail("TODO genSetReg from memory for f32", .{}), |
| 6020 | 6049 | .f64 => { |
| 6021 | | const base_reg = try self.register_manager.allocReg(null, .{}); |
| 6050 | const base_reg = try self.register_manager.allocReg(null, .{ .selector_mask = gp }); |
| 6022 | 6051 | try self.loadMemPtrIntoRegister(base_reg, Type.usize, mcv); |
| 6023 | 6052 | _ = try self.addInst(.{ |
| 6024 | 6053 | .tag = .mov_f64, |
| ... | ... | @@ -6328,7 +6357,7 @@ fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void { |
| 6328 | 6357 | const src: MCValue = blk: { |
| 6329 | 6358 | switch (src_ptr) { |
| 6330 | 6359 | .got_load, .direct_load, .memory => { |
| 6331 | | const reg = try self.register_manager.allocReg(null, .{}); |
| 6360 | const reg = try self.register_manager.allocReg(null, .{ .selector_mask = gp }); |
| 6332 | 6361 | try self.loadMemPtrIntoRegister(reg, src_ty, src_ptr); |
| 6333 | 6362 | _ = try self.addInst(.{ |
| 6334 | 6363 | .tag = .mov, |