| ... | @@ -2533,6 +2533,19 @@ fn restoreState(self: *Self, state: State, deaths: []const Air.Inst.Index, compt | ... | @@ -2533,6 +2533,19 @@ fn restoreState(self: *Self, state: State, deaths: []const Air.Inst.Index, compt |
| 2533 | ) |inst, *tracking| tracking.resurrect(inst, state.scope_generation); | 2533 | ) |inst, *tracking| tracking.resurrect(inst, state.scope_generation); |
| 2534 | for (deaths) |death| try self.processDeath(death); | 2534 | for (deaths) |death| try self.processDeath(death); |
| 2535 | | 2535 | |
| | 2536 | const ExpectedContents = [@typeInfo(RegisterManager.TrackedRegisters).Array.len]RegisterLock; |
| | 2537 | var stack align(@max(@alignOf(ExpectedContents), @alignOf(std.heap.StackFallbackAllocator(0)))) = |
| | 2538 | if (opts.update_tracking) ({}) else std.heap.stackFallback(@sizeOf(ExpectedContents), self.gpa); |
| | 2539 | |
| | 2540 | var reg_locks = if (opts.update_tracking) {} else try std.ArrayList(RegisterLock).initCapacity( |
| | 2541 | stack.get(), |
| | 2542 | @typeInfo(ExpectedContents).Array.len, |
| | 2543 | ); |
| | 2544 | defer if (!opts.update_tracking) { |
| | 2545 | for (reg_locks.items) |lock| self.register_manager.unlockReg(lock); |
| | 2546 | reg_locks.deinit(); |
| | 2547 | }; |
| | 2548 | |
| 2536 | for (0..state.registers.len) |index| { | 2549 | for (0..state.registers.len) |index| { |
| 2537 | const current_maybe_inst = if (self.register_manager.free_registers.isSet(index)) | 2550 | const current_maybe_inst = if (self.register_manager.free_registers.isSet(index)) |
| 2538 | null | 2551 | null |
| ... | @@ -2549,11 +2562,8 @@ fn restoreState(self: *Self, state: State, deaths: []const Air.Inst.Index, compt | ... | @@ -2549,11 +2562,8 @@ fn restoreState(self: *Self, state: State, deaths: []const Air.Inst.Index, compt |
| 2549 | try self.inst_tracking.getPtr(current_inst).?.spill(self, current_inst); | 2562 | try self.inst_tracking.getPtr(current_inst).?.spill(self, current_inst); |
| 2550 | } | 2563 | } |
| 2551 | if (target_maybe_inst) |target_inst| { | 2564 | if (target_maybe_inst) |target_inst| { |
| 2552 | try self.inst_tracking.getPtr(target_inst).?.materialize( | 2565 | const target_tracking = self.inst_tracking.getPtr(target_inst).?; |
| 2553 | self, | 2566 | try target_tracking.materialize(self, target_inst, state.reg_tracking[index]); |
| 2554 | target_inst, | | |
| 2555 | state.reg_tracking[index], | | |
| 2556 | ); | | |
| 2557 | } | 2567 | } |
| 2558 | } | 2568 | } |
| 2559 | if (opts.update_tracking) { | 2569 | if (opts.update_tracking) { |
| ... | @@ -2571,7 +2581,8 @@ fn restoreState(self: *Self, state: State, deaths: []const Air.Inst.Index, compt | ... | @@ -2571,7 +2581,8 @@ fn restoreState(self: *Self, state: State, deaths: []const Air.Inst.Index, compt |
| 2571 | state.reg_tracking[index], | 2581 | state.reg_tracking[index], |
| 2572 | ); | 2582 | ); |
| 2573 | } | 2583 | } |
| 2574 | } | 2584 | } else if (target_maybe_inst) |_| |
| | 2585 | try reg_locks.append(self.register_manager.lockRegIndexAssumeUnused(@intCast(index))); |
| 2575 | } | 2586 | } |
| 2576 | if (opts.emit_instructions) if (self.eflags_inst) |inst| | 2587 | if (opts.emit_instructions) if (self.eflags_inst) |inst| |
| 2577 | try self.inst_tracking.getPtr(inst).?.spill(self, inst); | 2588 | try self.inst_tracking.getPtr(inst).?.spill(self, inst); |
| ... | @@ -6746,6 +6757,7 @@ fn packedLoad(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) Inn | ... | @@ -6746,6 +6757,7 @@ fn packedLoad(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) Inn |
| 6746 | .disp = val_byte_off, | 6757 | .disp = val_byte_off, |
| 6747 | } }, | 6758 | } }, |
| 6748 | }); | 6759 | }); |
| | 6760 | try self.spillEflagsIfOccupied(); |
| 6749 | try self.asmRegisterImmediate(.{ ._r, .sh }, load_reg, Immediate.u(val_bit_off)); | 6761 | try self.asmRegisterImmediate(.{ ._r, .sh }, load_reg, Immediate.u(val_bit_off)); |
| 6750 | } else { | 6762 | } else { |
| 6751 | const tmp_reg = | 6763 | const tmp_reg = |
| ... | @@ -6768,6 +6780,7 @@ fn packedLoad(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) Inn | ... | @@ -6768,6 +6780,7 @@ fn packedLoad(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) Inn |
| 6768 | .disp = val_byte_off + 1, | 6780 | .disp = val_byte_off + 1, |
| 6769 | } }, | 6781 | } }, |
| 6770 | }); | 6782 | }); |
| | 6783 | try self.spillEflagsIfOccupied(); |
| 6771 | try self.asmRegisterRegisterImmediate( | 6784 | try self.asmRegisterRegisterImmediate( |
| 6772 | .{ ._rd, .sh }, | 6785 | .{ ._rd, .sh }, |
| 6773 | dst_alias, | 6786 | dst_alias, |
| ... | @@ -6851,6 +6864,27 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -6851,6 +6864,27 @@ fn airLoad(self: *Self, inst: Air.Inst.Index) !void { |
| 6851 | } else { | 6864 | } else { |
| 6852 | try self.load(dst_mcv, ptr_ty, ptr_mcv); | 6865 | try self.load(dst_mcv, ptr_ty, ptr_mcv); |
| 6853 | } | 6866 | } |
| | 6867 | |
| | 6868 | if (elem_ty.isAbiInt(mod) and elem_size * 8 > elem_ty.bitSize(mod)) { |
| | 6869 | const high_mcv: MCValue = switch (dst_mcv) { |
| | 6870 | .register => |dst_reg| .{ .register = dst_reg }, |
| | 6871 | .register_pair => |dst_regs| .{ .register = dst_regs[1] }, |
| | 6872 | else => dst_mcv.address().offset(@intCast((elem_size - 1) / 8 * 8)).deref(), |
| | 6873 | }; |
| | 6874 | const high_reg = if (high_mcv.isRegister()) |
| | 6875 | high_mcv.getReg().? |
| | 6876 | else |
| | 6877 | try self.copyToTmpRegister(Type.usize, high_mcv); |
| | 6878 | const high_lock = self.register_manager.lockReg(high_reg); |
| | 6879 | defer if (high_lock) |lock| self.register_manager.unlockReg(lock); |
| | 6880 | |
| | 6881 | try self.truncateRegister(elem_ty, high_reg); |
| | 6882 | if (!high_mcv.isRegister()) try self.genCopy( |
| | 6883 | if (elem_size <= 8) elem_ty else Type.usize, |
| | 6884 | high_mcv, |
| | 6885 | .{ .register = high_reg }, |
| | 6886 | ); |
| | 6887 | } |
| 6854 | break :result dst_mcv; | 6888 | break :result dst_mcv; |
| 6855 | }; | 6889 | }; |
| 6856 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); | 6890 | return self.finishAir(inst, result, .{ ty_op.operand, .none, .none }); |
| ... | @@ -6996,6 +7030,11 @@ fn airStore(self: *Self, inst: Air.Inst.Index, safety: bool) !void { | ... | @@ -6996,6 +7030,11 @@ fn airStore(self: *Self, inst: Air.Inst.Index, safety: bool) !void { |
| 6996 | } else { | 7030 | } else { |
| 6997 | // TODO if the value is undef, don't lower this instruction | 7031 | // TODO if the value is undef, don't lower this instruction |
| 6998 | } | 7032 | } |
| | 7033 | |
| | 7034 | try self.spillRegisters(&.{ .rdi, .rsi, .rcx }); |
| | 7035 | const reg_locks = self.register_manager.lockRegsAssumeUnused(3, .{ .rdi, .rsi, .rcx }); |
| | 7036 | defer for (reg_locks) |lock| self.register_manager.unlockReg(lock); |
| | 7037 | |
| 6999 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 7038 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 7000 | const ptr_mcv = try self.resolveInst(bin_op.lhs); | 7039 | const ptr_mcv = try self.resolveInst(bin_op.lhs); |
| 7001 | const ptr_ty = self.typeOf(bin_op.lhs); | 7040 | const ptr_ty = self.typeOf(bin_op.lhs); |
| ... | @@ -7088,12 +7127,15 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -7088,12 +7127,15 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 7088 | const dst_lock = self.register_manager.lockReg(dst_reg); | 7127 | const dst_lock = self.register_manager.lockReg(dst_reg); |
| 7089 | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); | 7128 | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); |
| 7090 | | 7129 | |
| 7091 | if (field_off > 0) try self.genShiftBinOpMir( | 7130 | if (field_off > 0) { |
| 7092 | .{ ._r, .sh }, | 7131 | try self.spillEflagsIfOccupied(); |
| 7093 | Type.usize, | 7132 | try self.genShiftBinOpMir( |
| 7094 | dst_mcv, | 7133 | .{ ._r, .sh }, |
| 7095 | .{ .immediate = field_off }, | 7134 | Type.usize, |
| 7096 | ); | 7135 | dst_mcv, |
| | 7136 | .{ .immediate = field_off }, |
| | 7137 | ); |
| | 7138 | } |
| 7097 | if (abi.RegisterClass.gp.isSet(RegisterManager.indexOfRegIntoTracked(dst_reg).?) and | 7139 | if (abi.RegisterClass.gp.isSet(RegisterManager.indexOfRegIntoTracked(dst_reg).?) and |
| 7098 | container_ty.abiSize(mod) * 8 > field_ty.bitSize(mod)) | 7140 | container_ty.abiSize(mod) * 8 > field_ty.bitSize(mod)) |
| 7099 | try self.truncateRegister(field_ty, dst_reg); | 7141 | try self.truncateRegister(field_ty, dst_reg); |
| ... | @@ -7128,12 +7170,15 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -7128,12 +7170,15 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 7128 | defer for (dst_locks) |dst_lock| if (dst_lock) |lock| | 7170 | defer for (dst_locks) |dst_lock| if (dst_lock) |lock| |
| 7129 | self.register_manager.unlockReg(lock); | 7171 | self.register_manager.unlockReg(lock); |
| 7130 | | 7172 | |
| 7131 | if (field_off > 0) try self.genShiftBinOpMir( | 7173 | if (field_off > 0) { |
| 7132 | .{ ._r, .sh }, | 7174 | try self.spillEflagsIfOccupied(); |
| 7133 | Type.u128, | 7175 | try self.genShiftBinOpMir( |
| 7134 | dst_mcv, | 7176 | .{ ._r, .sh }, |
| 7135 | .{ .immediate = field_off }, | 7177 | Type.u128, |
| 7136 | ); | 7178 | dst_mcv, |
| | 7179 | .{ .immediate = field_off }, |
| | 7180 | ); |
| | 7181 | } |
| 7137 | | 7182 | |
| 7138 | if (field_bit_size <= 64) { | 7183 | if (field_bit_size <= 64) { |
| 7139 | if (self.regExtraBits(field_ty) > 0) | 7184 | if (self.regExtraBits(field_ty) > 0) |
| ... | @@ -7161,12 +7206,15 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -7161,12 +7206,15 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 7161 | const dst_lock = self.register_manager.lockReg(dst_reg); | 7206 | const dst_lock = self.register_manager.lockReg(dst_reg); |
| 7162 | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); | 7207 | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); |
| 7163 | | 7208 | |
| 7164 | if (field_off % 64 > 0) try self.genShiftBinOpMir( | 7209 | if (field_off % 64 > 0) { |
| 7165 | .{ ._r, .sh }, | 7210 | try self.spillEflagsIfOccupied(); |
| 7166 | Type.usize, | 7211 | try self.genShiftBinOpMir( |
| 7167 | dst_mcv, | 7212 | .{ ._r, .sh }, |
| 7168 | .{ .immediate = field_off % 64 }, | 7213 | Type.usize, |
| 7169 | ); | 7214 | dst_mcv, |
| | 7215 | .{ .immediate = field_off % 64 }, |
| | 7216 | ); |
| | 7217 | } |
| 7170 | if (self.regExtraBits(field_ty) > 0) try self.truncateRegister(field_ty, dst_reg); | 7218 | if (self.regExtraBits(field_ty) > 0) try self.truncateRegister(field_ty, dst_reg); |
| 7171 | | 7219 | |
| 7172 | break :result if (field_rc.supersetOf(abi.RegisterClass.gp)) | 7220 | break :result if (field_rc.supersetOf(abi.RegisterClass.gp)) |
| ... | @@ -7272,6 +7320,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -7272,6 +7320,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 7272 | .disp = frame_addr.off + field_byte_off, | 7320 | .disp = frame_addr.off + field_byte_off, |
| 7273 | } }, | 7321 | } }, |
| 7274 | }); | 7322 | }); |
| | 7323 | try self.spillEflagsIfOccupied(); |
| 7275 | try self.asmRegisterImmediate(.{ ._r, .sh }, load_reg, Immediate.u(field_bit_off)); | 7324 | try self.asmRegisterImmediate(.{ ._r, .sh }, load_reg, Immediate.u(field_bit_off)); |
| 7276 | } else { | 7325 | } else { |
| 7277 | const tmp_reg = registerAlias( | 7326 | const tmp_reg = registerAlias( |
| ... | @@ -7300,6 +7349,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -7300,6 +7349,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 7300 | .disp = frame_addr.off + field_byte_off + limb_abi_size, | 7349 | .disp = frame_addr.off + field_byte_off + limb_abi_size, |
| 7301 | } }, | 7350 | } }, |
| 7302 | }); | 7351 | }); |
| | 7352 | try self.spillEflagsIfOccupied(); |
| 7303 | try self.asmRegisterRegisterImmediate( | 7353 | try self.asmRegisterRegisterImmediate( |
| 7304 | .{ ._rd, .sh }, | 7354 | .{ ._rd, .sh }, |
| 7305 | dst_alias, | 7355 | dst_alias, |
| ... | @@ -7344,13 +7394,18 @@ fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -7344,13 +7394,18 @@ fn airFieldParentPtr(self: *Self, inst: Air.Inst.Index) !void { |
| 7344 | fn genUnOp(self: *Self, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_air: Air.Inst.Ref) !MCValue { | 7394 | fn genUnOp(self: *Self, maybe_inst: ?Air.Inst.Index, tag: Air.Inst.Tag, src_air: Air.Inst.Ref) !MCValue { |
| 7345 | const mod = self.bin_file.options.module.?; | 7395 | const mod = self.bin_file.options.module.?; |
| 7346 | const src_ty = self.typeOf(src_air); | 7396 | const src_ty = self.typeOf(src_air); |
| 7347 | const src_mcv = try self.resolveInst(src_air); | | |
| 7348 | if (src_ty.zigTypeTag(mod) == .Vector) | 7397 | if (src_ty.zigTypeTag(mod) == .Vector) |
| 7349 | return self.fail("TODO implement genUnOp for {}", .{src_ty.fmt(mod)}); | 7398 | return self.fail("TODO implement genUnOp for {}", .{src_ty.fmt(mod)}); |
| 7350 | | 7399 | |
| | 7400 | var src_mcv = try self.resolveInst(src_air); |
| 7351 | switch (src_mcv) { | 7401 | switch (src_mcv) { |
| 7352 | .eflags => |cc| switch (tag) { | 7402 | .eflags => |cc| switch (tag) { |
| 7353 | .not => return .{ .eflags = cc.negate() }, | 7403 | .not => { |
| | 7404 | if (maybe_inst) |inst| if (self.reuseOperand(inst, src_air, 0, src_mcv)) |
| | 7405 | return .{ .eflags = cc.negate() }; |
| | 7406 | try self.spillEflagsIfOccupied(); |
| | 7407 | src_mcv = try self.resolveInst(src_air); |
| | 7408 | }, |
| 7354 | else => {}, | 7409 | else => {}, |
| 7355 | }, | 7410 | }, |
| 7356 | else => {}, | 7411 | else => {}, |
| ... | @@ -11873,8 +11928,18 @@ fn airSwitchBr(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -11873,8 +11928,18 @@ fn airSwitchBr(self: *Self, inst: Air.Inst.Index) !void { |
| 11873 | try self.spillEflagsIfOccupied(); | 11928 | try self.spillEflagsIfOccupied(); |
| 11874 | for (items, relocs, 0..) |item, *reloc, i| { | 11929 | for (items, relocs, 0..) |item, *reloc, i| { |
| 11875 | const item_mcv = try self.resolveInst(item); | 11930 | const item_mcv = try self.resolveInst(item); |
| 11876 | try self.genBinOpMir(.{ ._, .cmp }, condition_ty, condition, item_mcv); | 11931 | const cc: Condition = switch (condition) { |
| 11877 | reloc.* = try self.asmJccReloc(if (i < relocs.len - 1) .e else .ne, undefined); | 11932 | .eflags => |cc| switch (item_mcv.immediate) { |
| | 11933 | 0 => cc.negate(), |
| | 11934 | 1 => cc, |
| | 11935 | else => unreachable, |
| | 11936 | }, |
| | 11937 | else => cc: { |
| | 11938 | try self.genBinOpMir(.{ ._, .cmp }, condition_ty, condition, item_mcv); |
| | 11939 | break :cc .e; |
| | 11940 | }, |
| | 11941 | }; |
| | 11942 | reloc.* = try self.asmJccReloc(if (i < relocs.len - 1) cc else cc.negate(), undefined); |
| 11878 | } | 11943 | } |
| 11879 | | 11944 | |
| 11880 | for (liveness.deaths[case_i]) |operand| try self.processDeath(operand); | 11945 | for (liveness.deaths[case_i]) |operand| try self.processDeath(operand); |
| ... | @@ -14380,6 +14445,10 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void { | ... | @@ -14380,6 +14445,10 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void { |
| 14380 | | 14445 | |
| 14381 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 14446 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 14382 | | 14447 | |
| | 14448 | try self.spillRegisters(&.{ .rdi, .rsi, .rcx }); |
| | 14449 | const reg_locks = self.register_manager.lockRegsAssumeUnused(3, .{ .rdi, .rsi, .rcx }); |
| | 14450 | defer for (reg_locks) |lock| self.register_manager.unlockReg(lock); |
| | 14451 | |
| 14383 | const dst_ptr = try self.resolveInst(bin_op.lhs); | 14452 | const dst_ptr = try self.resolveInst(bin_op.lhs); |
| 14384 | const dst_ptr_ty = self.typeOf(bin_op.lhs); | 14453 | const dst_ptr_ty = self.typeOf(bin_op.lhs); |
| 14385 | const dst_ptr_lock: ?RegisterLock = switch (dst_ptr) { | 14454 | const dst_ptr_lock: ?RegisterLock = switch (dst_ptr) { |
| ... | @@ -14497,6 +14566,10 @@ fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -14497,6 +14566,10 @@ fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void { |
| 14497 | const mod = self.bin_file.options.module.?; | 14566 | const mod = self.bin_file.options.module.?; |
| 14498 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 14567 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 14499 | | 14568 | |
| | 14569 | try self.spillRegisters(&.{ .rdi, .rsi, .rcx }); |
| | 14570 | const reg_locks = self.register_manager.lockRegsAssumeUnused(3, .{ .rdi, .rsi, .rcx }); |
| | 14571 | defer for (reg_locks) |lock| self.register_manager.unlockReg(lock); |
| | 14572 | |
| 14500 | const dst_ptr = try self.resolveInst(bin_op.lhs); | 14573 | const dst_ptr = try self.resolveInst(bin_op.lhs); |
| 14501 | const dst_ptr_ty = self.typeOf(bin_op.lhs); | 14574 | const dst_ptr_ty = self.typeOf(bin_op.lhs); |
| 14502 | const dst_ptr_lock: ?RegisterLock = switch (dst_ptr) { | 14575 | const dst_ptr_lock: ?RegisterLock = switch (dst_ptr) { |