authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-10-09 01:08:10-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-10-09 03:11:40-04:00
loga96c08c1d174d64ec72c404d35c0de518475f07e
tree06f5858233b916203484912629059729b8aade76
parentf28b1657aab05f9d92fbaec243d33304f0abaec2

x86_64: implement struct field value for register pairs


1 files changed, 122 insertions(+), 50 deletions(-)

src/arch/x86_64/CodeGen.zig+122-50
...@@ -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 };
60646064
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 else6287 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 });