| ... | ... | @@ -2895,13 +2895,16 @@ fn airIntCast(self: *Self, inst: Air.Inst.Index) !void { |
| 2895 | 2895 | }.signedness; |
| 2896 | 2896 | |
| 2897 | 2897 | const src_mcv = try self.resolveInst(ty_op.operand); |
| 2898 | | const src_storage_bits = switch (src_mcv) { |
| 2898 | const src_storage_bits: u16 = switch (src_mcv) { |
| 2899 | 2899 | .register, .register_offset => 64, |
| 2900 | | .load_frame => |frame_addr| self.getFrameAddrSize(frame_addr) * 8, |
| 2900 | .register_pair => 128, |
| 2901 | .load_frame => |frame_addr| @intCast(self.getFrameAddrSize(frame_addr) * 8), |
| 2901 | 2902 | else => src_int_info.bits, |
| 2902 | 2903 | }; |
| 2903 | 2904 | |
| 2904 | 2905 | const dst_mcv = if (dst_int_info.bits <= src_storage_bits and |
| 2906 | std.math.divCeil(u16, dst_int_info.bits, 64) catch unreachable == |
| 2907 | std.math.divCeil(u32, src_storage_bits, 64) catch unreachable and |
| 2905 | 2908 | self.reuseOperand(inst, ty_op.operand, 0, src_mcv)) src_mcv else dst: { |
| 2906 | 2909 | const dst_mcv = try self.allocRegOrMem(inst, true); |
| 2907 | 2910 | try self.genCopy(min_ty, dst_mcv, src_mcv); |
| ... | ... | @@ -3646,7 +3649,10 @@ fn airMulWithOverflow(self: *Self, inst: Air.Inst.Index) !void { |
| 3646 | 3649 | }, |
| 3647 | 3650 | else => { |
| 3648 | 3651 | // For now, this is the only supported multiply that doesn't fit in a register. |
| 3649 | | assert(dst_info.bits <= 128 and src_bits == 64); |
| 3652 | if (dst_info.bits > 128 or src_bits != 64) |
| 3653 | return self.fail("TODO implement airWithOverflow from {} to {}", .{ |
| 3654 | src_ty.fmt(mod), dst_ty.fmt(mod), |
| 3655 | }); |
| 3650 | 3656 | |
| 3651 | 3657 | const frame_index = |
| 3652 | 3658 | try self.allocFrameIndex(FrameAlloc.initType(tuple_ty, mod)); |
| ... | ... | @@ -4424,42 +4430,46 @@ fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void { |
| 4424 | 4430 | // this is identical to the `airPtrElemPtr` codegen expect here an |
| 4425 | 4431 | // additional `mov` is needed at the end to get the actual value |
| 4426 | 4432 | |
| 4427 | | const elem_ty = ptr_ty.elemType2(mod); |
| 4428 | | const elem_abi_size: u32 = @intCast(elem_ty.abiSize(mod)); |
| 4429 | | const index_ty = self.typeOf(bin_op.rhs); |
| 4430 | | const index_mcv = try self.resolveInst(bin_op.rhs); |
| 4431 | | const index_lock = switch (index_mcv) { |
| 4432 | | .register => |reg| self.register_manager.lockRegAssumeUnused(reg), |
| 4433 | | else => null, |
| 4434 | | }; |
| 4435 | | defer if (index_lock) |lock| self.register_manager.unlockReg(lock); |
| 4433 | const result = result: { |
| 4434 | const elem_ty = ptr_ty.elemType2(mod); |
| 4435 | if (!elem_ty.hasRuntimeBitsIgnoreComptime(mod)) break :result .none; |
| 4436 | 4436 | |
| 4437 | | const offset_reg = try self.elemOffset(index_ty, index_mcv, elem_abi_size); |
| 4438 | | const offset_lock = self.register_manager.lockRegAssumeUnused(offset_reg); |
| 4439 | | defer self.register_manager.unlockReg(offset_lock); |
| 4437 | const elem_abi_size: u32 = @intCast(elem_ty.abiSize(mod)); |
| 4438 | const index_ty = self.typeOf(bin_op.rhs); |
| 4439 | const index_mcv = try self.resolveInst(bin_op.rhs); |
| 4440 | const index_lock = switch (index_mcv) { |
| 4441 | .register => |reg| self.register_manager.lockRegAssumeUnused(reg), |
| 4442 | else => null, |
| 4443 | }; |
| 4444 | defer if (index_lock) |lock| self.register_manager.unlockReg(lock); |
| 4440 | 4445 | |
| 4441 | | const ptr_mcv = try self.resolveInst(bin_op.lhs); |
| 4442 | | const elem_ptr_reg = if (ptr_mcv.isRegister() and self.liveness.operandDies(inst, 0)) |
| 4443 | | ptr_mcv.register |
| 4444 | | else |
| 4445 | | try self.copyToTmpRegister(ptr_ty, ptr_mcv); |
| 4446 | | const elem_ptr_lock = self.register_manager.lockRegAssumeUnused(elem_ptr_reg); |
| 4447 | | defer self.register_manager.unlockReg(elem_ptr_lock); |
| 4448 | | try self.asmRegisterRegister( |
| 4449 | | .{ ._, .add }, |
| 4450 | | elem_ptr_reg, |
| 4451 | | offset_reg, |
| 4452 | | ); |
| 4446 | const offset_reg = try self.elemOffset(index_ty, index_mcv, elem_abi_size); |
| 4447 | const offset_lock = self.register_manager.lockRegAssumeUnused(offset_reg); |
| 4448 | defer self.register_manager.unlockReg(offset_lock); |
| 4453 | 4449 | |
| 4454 | | const dst_mcv = try self.allocRegOrMem(inst, true); |
| 4455 | | const dst_lock = switch (dst_mcv) { |
| 4456 | | .register => |reg| self.register_manager.lockRegAssumeUnused(reg), |
| 4457 | | else => null, |
| 4458 | | }; |
| 4459 | | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); |
| 4460 | | try self.load(dst_mcv, ptr_ty, .{ .register = elem_ptr_reg }); |
| 4450 | const ptr_mcv = try self.resolveInst(bin_op.lhs); |
| 4451 | const elem_ptr_reg = if (ptr_mcv.isRegister() and self.liveness.operandDies(inst, 0)) |
| 4452 | ptr_mcv.register |
| 4453 | else |
| 4454 | try self.copyToTmpRegister(ptr_ty, ptr_mcv); |
| 4455 | const elem_ptr_lock = self.register_manager.lockRegAssumeUnused(elem_ptr_reg); |
| 4456 | defer self.register_manager.unlockReg(elem_ptr_lock); |
| 4457 | try self.asmRegisterRegister( |
| 4458 | .{ ._, .add }, |
| 4459 | elem_ptr_reg, |
| 4460 | offset_reg, |
| 4461 | ); |
| 4461 | 4462 | |
| 4462 | | return self.finishAir(inst, dst_mcv, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 4463 | const dst_mcv = try self.allocRegOrMem(inst, true); |
| 4464 | const dst_lock = switch (dst_mcv) { |
| 4465 | .register => |reg| self.register_manager.lockRegAssumeUnused(reg), |
| 4466 | else => null, |
| 4467 | }; |
| 4468 | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); |
| 4469 | try self.load(dst_mcv, ptr_ty, .{ .register = elem_ptr_reg }); |
| 4470 | break :result dst_mcv; |
| 4471 | }; |
| 4472 | return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 4463 | 4473 | } |
| 4464 | 4474 | |
| 4465 | 4475 | fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) !void { |
| ... | ... | @@ -5790,15 +5800,17 @@ fn packedLoad(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) Inn |
| 5790 | 5800 | const ptr_info = ptr_ty.ptrInfo(mod); |
| 5791 | 5801 | |
| 5792 | 5802 | const val_ty = ptr_info.child.toType(); |
| 5803 | if (!val_ty.hasRuntimeBitsIgnoreComptime(mod)) return; |
| 5793 | 5804 | const val_abi_size: u32 = @intCast(val_ty.abiSize(mod)); |
| 5805 | |
| 5806 | if (val_abi_size > 8) return self.fail("TODO implement packed load of {}", .{val_ty.fmt(mod)}); |
| 5807 | |
| 5794 | 5808 | const limb_abi_size: u32 = @min(val_abi_size, 8); |
| 5795 | 5809 | const limb_abi_bits = limb_abi_size * 8; |
| 5796 | 5810 | const val_byte_off: i32 = @intCast(ptr_info.packed_offset.bit_offset / limb_abi_bits * limb_abi_size); |
| 5797 | 5811 | const val_bit_off = ptr_info.packed_offset.bit_offset % limb_abi_bits; |
| 5798 | 5812 | const val_extra_bits = self.regExtraBits(val_ty); |
| 5799 | 5813 | |
| 5800 | | if (val_abi_size > 8) return self.fail("TODO implement packed load of {}", .{val_ty.fmt(mod)}); |
| 5801 | | |
| 5802 | 5814 | const ptr_reg = try self.copyToTmpRegister(ptr_ty, ptr_mcv); |
| 5803 | 5815 | const ptr_lock = self.register_manager.lockRegAssumeUnused(ptr_reg); |
| 5804 | 5816 | defer self.register_manager.unlockReg(ptr_lock); |
| ... | ... | @@ -5861,6 +5873,7 @@ fn packedLoad(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) Inn |
| 5861 | 5873 | fn load(self: *Self, dst_mcv: MCValue, ptr_ty: Type, ptr_mcv: MCValue) InnerError!void { |
| 5862 | 5874 | const mod = self.bin_file.options.module.?; |
| 5863 | 5875 | const dst_ty = ptr_ty.childType(mod); |
| 5876 | if (!dst_ty.hasRuntimeBitsIgnoreComptime(mod)) return; |
| 5864 | 5877 | switch (ptr_mcv) { |
| 5865 | 5878 | .none, |
| 5866 | 5879 | .unreach, |
| ... | ... | @@ -5937,6 +5950,7 @@ fn packedStore(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) In |
| 5937 | 5950 | const mod = self.bin_file.options.module.?; |
| 5938 | 5951 | const ptr_info = ptr_ty.ptrInfo(mod); |
| 5939 | 5952 | const src_ty = ptr_ty.childType(mod); |
| 5953 | if (!src_ty.hasRuntimeBitsIgnoreComptime(mod)) return; |
| 5940 | 5954 | |
| 5941 | 5955 | const limb_abi_size: u16 = @min(ptr_info.packed_offset.host_size, 8); |
| 5942 | 5956 | const limb_abi_bits = limb_abi_size * 8; |
| ... | ... | @@ -6008,6 +6022,7 @@ fn packedStore(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) In |
| 6008 | 6022 | fn store(self: *Self, ptr_ty: Type, ptr_mcv: MCValue, src_mcv: MCValue) InnerError!void { |
| 6009 | 6023 | const mod = self.bin_file.options.module.?; |
| 6010 | 6024 | const src_ty = ptr_ty.childType(mod); |
| 6025 | if (!src_ty.hasRuntimeBitsIgnoreComptime(mod)) return; |
| 6011 | 6026 | switch (ptr_mcv) { |
| 6012 | 6027 | .none, |
| 6013 | 6028 | .unreach, |
| ... | ... | @@ -11286,7 +11301,6 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr |
| 11286 | 11301 | .none, |
| 11287 | 11302 | .unreach, |
| 11288 | 11303 | .dead, |
| 11289 | | .register_pair, |
| 11290 | 11304 | .register_overflow, |
| 11291 | 11305 | .reserved_frame, |
| 11292 | 11306 | => unreachable, |
| ... | ... | @@ -11390,6 +11404,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr |
| 11390 | 11404 | }, |
| 11391 | 11405 | .x87, .mmx => unreachable, |
| 11392 | 11406 | }, |
| 11407 | .register_pair => |src_regs| try self.genSetReg(dst_reg, ty, .{ .register = src_regs[0] }), |
| 11393 | 11408 | .register_offset, |
| 11394 | 11409 | .indirect, |
| 11395 | 11410 | .load_frame, |