| ... | @@ -6063,6 +6063,127 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -6063,6 +6063,127 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 6063 | }; | 6063 | }; |
| 6064 | | 6064 | |
| 6065 | switch (src_mcv) { | 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 | .load_frame => |frame_addr| { | 6187 | .load_frame => |frame_addr| { |
| 6067 | const field_abi_size: u32 = @intCast(field_ty.abiSize(mod)); | 6188 | const field_abi_size: u32 = @intCast(field_ty.abiSize(mod)); |
| 6068 | if (field_off % 8 == 0) { | 6189 | if (field_off % 8 == 0) { |
| ... | @@ -6166,56 +6287,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -6166,56 +6287,7 @@ fn airStructFieldVal(self: *Self, inst: Air.Inst.Index) !void { |
| 6166 | else | 6287 | else |
| 6167 | try self.copyToRegisterWithInstTracking(inst, field_ty, dst_mcv); | 6288 | try self.copyToRegisterWithInstTracking(inst, field_ty, dst_mcv); |
| 6168 | }, | 6289 | }, |
| 6169 | .register => |reg| { | 6290 | else => return self.fail("TODO implement airStructFieldVal for {}", .{src_mcv}), |
| 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}), | | |
| 6219 | } | 6291 | } |
| 6220 | }; | 6292 | }; |
| 6221 | return self.finishAir(inst, result, .{ extra.struct_operand, .none, .none }); | 6293 | return self.finishAir(inst, result, .{ extra.struct_operand, .none, .none }); |