| ... | ... | @@ -6063,6 +6063,127 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 6063 | 6063 | }; |
| 6064 | 6064 | |
| 6065 | 6065 | switch (src_mcv) { |
| 6066 | .register => |src_reg| { |
| 6067 | const src_reg_lock = self.register_manager.lockRegAssumeUnused(src_reg); |
| 6068 | defer self.register_manager.unlockReg(src_reg_lock); |
| 6069 | |
| 6070 | const dst_reg = if (field_rc.supersetOf(container_rc) and |
| 6071 | self.reuseOperand(inst, operand, 0, src_mcv)) |
| 6072 | src_reg |
| 6073 | else |
| 6074 | try self.copyToTmpRegister(Type.usize, .{ .register = src_reg }); |
| 6075 | const dst_mcv = MCValue{ .register = dst_reg }; |
| 6076 | const dst_lock = self.register_manager.lockReg(dst_reg); |
| 6077 | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); |
| 6078 | |
| 6079 | if (field_off > 0) try self.genShiftBinOpMir( |
| 6080 | .{ ._r, .sh }, |
| 6081 | Type.usize, |
| 6082 | dst_mcv, |
| 6083 | .{ .immediate = field_off }, |
| 6084 | ); |
| 6085 | if (self.regExtraBits(field_ty) > 0) try self.truncateRegister(field_ty, dst_reg); |
| 6086 | |
| 6087 | break :result if (field_rc.supersetOf(abi.RegisterClass.gp)) |
| 6088 | dst_mcv |
| 6089 | else |
| 6090 | try self.copyToRegisterWithInstTracking(inst, field_ty, dst_mcv); |
| 6091 | }, |
| 6092 | .register_pair => |src_regs| { |
| 6093 | const src_regs_lock = self.register_manager.lockRegsAssumeUnused(2, src_regs); |
| 6094 | defer for (src_regs_lock) |lock| self.register_manager.unlockReg(lock); |
| 6095 | |
| 6096 | const field_bit_size: u32 = @intCast(field_ty.bitSize(mod)); |
| 6097 | const src_reg = if (field_off + field_bit_size <= 64) |
| 6098 | src_regs[0] |
| 6099 | else if (field_off >= 64) |
| 6100 | src_regs[1] |
| 6101 | else { |
| 6102 | const dst_regs: [2]Register = if (field_rc.supersetOf(container_rc) and |
| 6103 | self.reuseOperand(inst, operand, 0, src_mcv)) src_regs else dst: { |
| 6104 | const dst_regs = |
| 6105 | try self.register_manager.allocRegs(2, .{ null, null }, field_rc); |
| 6106 | const dst_locks = self.register_manager.lockRegsAssumeUnused(2, dst_regs); |
| 6107 | defer for (dst_locks) |lock| self.register_manager.unlockReg(lock); |
| 6108 | |
| 6109 | try self.genSetReg(dst_regs[0], Type.usize, .{ .register = src_regs[0] }); |
| 6110 | try self.genSetReg(dst_regs[1], Type.usize, .{ .register = src_regs[1] }); |
| 6111 | break :dst dst_regs; |
| 6112 | }; |
| 6113 | const dst_mcv = MCValue{ .register_pair = dst_regs }; |
| 6114 | const dst_locks = self.register_manager.lockRegs(2, dst_regs); |
| 6115 | defer for (dst_locks) |dst_lock| if (dst_lock) |lock| |
| 6116 | self.register_manager.unlockReg(lock); |
| 6117 | |
| 6118 | if (field_off > 0) try self.genShiftBinOpMir( |
| 6119 | .{ ._r, .sh }, |
| 6120 | Type.u128, |
| 6121 | dst_mcv, |
| 6122 | .{ .immediate = field_off }, |
| 6123 | ); |
| 6124 | |
| 6125 | if (field_bit_size <= 64) { |
| 6126 | if (self.regExtraBits(field_ty) > 0) |
| 6127 | try self.truncateRegister(field_ty, dst_regs[0]); |
| 6128 | break :result if (field_rc.supersetOf(abi.RegisterClass.gp)) |
| 6129 | .{ .register = dst_regs[0] } |
| 6130 | else |
| 6131 | try self.copyToRegisterWithInstTracking(inst, field_ty, .{ |
| 6132 | .register = dst_regs[0], |
| 6133 | }); |
| 6134 | } |
| 6135 | |
| 6136 | if (field_bit_size < 128) try self.truncateRegister( |
| 6137 | try mod.intType(.unsigned, @intCast(field_bit_size - 64)), |
| 6138 | dst_regs[1], |
| 6139 | ); |
| 6140 | break :result if (field_rc.supersetOf(abi.RegisterClass.gp)) |
| 6141 | dst_mcv |
| 6142 | else |
| 6143 | try self.copyToRegisterWithInstTracking(inst, field_ty, dst_mcv); |
| 6144 | }; |
| 6145 | |
| 6146 | const dst_reg = try self.copyToTmpRegister(Type.usize, .{ .register = src_reg }); |
| 6147 | const dst_mcv = MCValue{ .register = dst_reg }; |
| 6148 | const dst_lock = self.register_manager.lockReg(dst_reg); |
| 6149 | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); |
| 6150 | |
| 6151 | if (field_off % 64 > 0) try self.genShiftBinOpMir( |
| 6152 | .{ ._r, .sh }, |
| 6153 | Type.usize, |
| 6154 | dst_mcv, |
| 6155 | .{ .immediate = field_off % 64 }, |
| 6156 | ); |
| 6157 | if (self.regExtraBits(field_ty) > 0) try self.truncateRegister(field_ty, dst_reg); |
| 6158 | |
| 6159 | break :result if (field_rc.supersetOf(abi.RegisterClass.gp)) |
| 6160 | dst_mcv |
| 6161 | else |
| 6162 | try self.copyToRegisterWithInstTracking(inst, field_ty, dst_mcv); |
| 6163 | }, |
| 6164 | .register_overflow => |ro| { |
| 6165 | switch (index) { |
| 6166 | // Get wrapped value for overflow operation. |
| 6167 | 0 => break :result if (self.liveness.operandDies(inst, 0)) |
| 6168 | .{ .register = ro.reg } |
| 6169 | else |
| 6170 | try self.copyToRegisterWithInstTracking( |
| 6171 | inst, |
| 6172 | Type.usize, |
| 6173 | .{ .register = ro.reg }, |
| 6174 | ), |
| 6175 | // Get overflow bit. |
| 6176 | 1 => if (self.liveness.operandDies(inst, 0)) { |
| 6177 | self.eflags_inst = inst; |
| 6178 | break :result .{ .eflags = ro.eflags }; |
| 6179 | } else { |
| 6180 | const dst_reg = try self.register_manager.allocReg(inst, abi.RegisterClass.gp); |
| 6181 | try self.asmSetccRegister(dst_reg.to8(), ro.eflags); |
| 6182 | break :result .{ .register = dst_reg.to8() }; |
| 6183 | }, |
| 6184 | else => unreachable, |
| 6185 | } |
| 6186 | }, |
| 6066 | 6187 | .load_frame => |frame_addr| { |
| 6067 | 6188 | const field_abi_size: u32 = @intCast(field_ty.abiSize(mod)); |
| 6068 | 6189 | if (field_off % 8 == 0) { |
| ... | ... | @@ -6166,56 +6287,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 6166 | 6287 | else |
| 6167 | 6288 | try self.copyToRegisterWithInstTracking(inst, field_ty, dst_mcv); |
| 6168 | 6289 | }, |
| 6169 | | .register => |reg| { |
| 6170 | | const reg_lock = self.register_manager.lockRegAssumeUnused(reg); |
| 6171 | | defer self.register_manager.unlockReg(reg_lock); |
| 6172 | | |
| 6173 | | const dst_reg = if (src_mcv.isRegister() and field_rc.supersetOf(container_rc) and |
| 6174 | | self.reuseOperand(inst, operand, 0, src_mcv)) |
| 6175 | | src_mcv.getReg().? |
| 6176 | | else |
| 6177 | | try self.copyToTmpRegister(Type.usize, .{ .register = reg.to64() }); |
| 6178 | | const dst_mcv = MCValue{ .register = dst_reg }; |
| 6179 | | const dst_lock = self.register_manager.lockReg(dst_reg); |
| 6180 | | defer if (dst_lock) |lock| self.register_manager.unlockReg(lock); |
| 6181 | | |
| 6182 | | try self.genShiftBinOpMir( |
| 6183 | | .{ ._r, .sh }, |
| 6184 | | Type.usize, |
| 6185 | | dst_mcv, |
| 6186 | | .{ .immediate = field_off }, |
| 6187 | | ); |
| 6188 | | if (self.regExtraBits(field_ty) > 0) try self.truncateRegister(field_ty, dst_reg); |
| 6189 | | |
| 6190 | | break :result if (field_rc.supersetOf(abi.RegisterClass.gp)) |
| 6191 | | dst_mcv |
| 6192 | | else |
| 6193 | | try self.copyToRegisterWithInstTracking(inst, field_ty, dst_mcv); |
| 6194 | | }, |
| 6195 | | .register_overflow => |ro| { |
| 6196 | | switch (index) { |
| 6197 | | // Get wrapped value for overflow operation. |
| 6198 | | 0 => break :result if (self.liveness.operandDies(inst, 0)) |
| 6199 | | .{ .register = ro.reg } |
| 6200 | | else |
| 6201 | | try self.copyToRegisterWithInstTracking( |
| 6202 | | inst, |
| 6203 | | Type.usize, |
| 6204 | | .{ .register = ro.reg }, |
| 6205 | | ), |
| 6206 | | // Get overflow bit. |
| 6207 | | 1 => if (self.liveness.operandDies(inst, 0)) { |
| 6208 | | self.eflags_inst = inst; |
| 6209 | | break :result .{ .eflags = ro.eflags }; |
| 6210 | | } else { |
| 6211 | | const dst_reg = try self.register_manager.allocReg(inst, abi.RegisterClass.gp); |
| 6212 | | try self.asmSetccRegister(dst_reg.to8(), ro.eflags); |
| 6213 | | break :result .{ .register = dst_reg.to8() }; |
| 6214 | | }, |
| 6215 | | else => unreachable, |
| 6216 | | } |
| 6217 | | }, |
| 6218 | | else => return self.fail("TODO implement codegen struct_field_val for {}", .{src_mcv}), |
| 6290 | else => return self.fail("TODO implement airStructFieldVal for {}", .{src_mcv}), |
| 6219 | 6291 | } |
| 6220 | 6292 | }; |
| 6221 | 6293 | return self.finishAir(inst, result, .{ extra.struct_operand, .none, .none }); |