| ... | @@ -8175,7 +8175,15 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void { | ... | @@ -8175,7 +8175,15 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void { |
| 8175 | }; | 8175 | }; |
| 8176 | defer if (src_val_lock) |lock| self.register_manager.unlockReg(lock); | 8176 | defer if (src_val_lock) |lock| self.register_manager.unlockReg(lock); |
| 8177 | | 8177 | |
| 8178 | if (elem_ty.abiSize(self.target.*) == 1) { | 8178 | const elem_abi_size = @intCast(u31, elem_ty.abiSize(self.target.*)); |
| | 8179 | |
| | 8180 | if (elem_abi_size == 1) { |
| | 8181 | const ptr = switch (dst_ptr_ty.ptrSize()) { |
| | 8182 | // TODO: this only handles slices stored in the stack |
| | 8183 | .Slice => @as(MCValue, .{ .stack_offset = dst_ptr.stack_offset - 0 }), |
| | 8184 | .One => dst_ptr, |
| | 8185 | .C, .Many => unreachable, |
| | 8186 | }; |
| 8179 | const len = switch (dst_ptr_ty.ptrSize()) { | 8187 | const len = switch (dst_ptr_ty.ptrSize()) { |
| 8180 | // TODO: this only handles slices stored in the stack | 8188 | // TODO: this only handles slices stored in the stack |
| 8181 | .Slice => @as(MCValue, .{ .stack_offset = dst_ptr.stack_offset - 8 }), | 8189 | .Slice => @as(MCValue, .{ .stack_offset = dst_ptr.stack_offset - 8 }), |
| ... | @@ -8188,8 +8196,7 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void { | ... | @@ -8188,8 +8196,7 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void { |
| 8188 | }; | 8196 | }; |
| 8189 | defer if (len_lock) |lock| self.register_manager.unlockReg(lock); | 8197 | defer if (len_lock) |lock| self.register_manager.unlockReg(lock); |
| 8190 | | 8198 | |
| 8191 | // TODO: dst_ptr could be a slice rather than raw pointer | 8199 | try self.genInlineMemset(ptr, src_val, len, .{}); |
| 8192 | try self.genInlineMemset(dst_ptr, src_val, len, .{}); | | |
| 8193 | return self.finishAir(inst, .unreach, .{ bin_op.lhs, bin_op.rhs, .none }); | 8200 | return self.finishAir(inst, .unreach, .{ bin_op.lhs, bin_op.rhs, .none }); |
| 8194 | } | 8201 | } |
| 8195 | | 8202 | |
| ... | @@ -8198,12 +8205,47 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void { | ... | @@ -8198,12 +8205,47 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void { |
| 8198 | // here to elide it. | 8205 | // here to elide it. |
| 8199 | switch (dst_ptr_ty.ptrSize()) { | 8206 | switch (dst_ptr_ty.ptrSize()) { |
| 8200 | .Slice => { | 8207 | .Slice => { |
| | 8208 | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| | 8209 | const slice_ptr_ty = dst_ptr_ty.slicePtrFieldType(&buf); |
| | 8210 | |
| 8201 | // TODO: this only handles slices stored in the stack | 8211 | // TODO: this only handles slices stored in the stack |
| 8202 | const ptr = @as(MCValue, .{ .stack_offset = dst_ptr.stack_offset - 0 }); | 8212 | const ptr = @as(MCValue, .{ .stack_offset = dst_ptr.stack_offset - 0 }); |
| 8203 | const len = @as(MCValue, .{ .stack_offset = dst_ptr.stack_offset - 8 }); | 8213 | const len = @as(MCValue, .{ .stack_offset = dst_ptr.stack_offset - 8 }); |
| 8204 | _ = ptr; | 8214 | |
| 8205 | _ = len; | 8215 | // Used to store the number of elements for comparison. |
| 8206 | return self.fail("TODO implement airMemset for x86_64 with ABI size > 1 using a slice", .{}); | 8216 | // After comparison, updated to store number of bytes needed to copy. |
| | 8217 | const len_reg = try self.register_manager.allocReg(null, gp); |
| | 8218 | const len_mcv: MCValue = .{ .register = len_reg }; |
| | 8219 | const len_lock = self.register_manager.lockRegAssumeUnused(len_reg); |
| | 8220 | defer self.register_manager.unlockReg(len_lock); |
| | 8221 | |
| | 8222 | try self.asmRegisterMemory(.mov, len_reg, Memory.sib(.qword, .{ |
| | 8223 | .base = .rbp, |
| | 8224 | .disp = -len.stack_offset, |
| | 8225 | })); |
| | 8226 | |
| | 8227 | const skip_reloc = try self.asmJccReloc(undefined, .z); |
| | 8228 | try self.store(ptr, src_val, slice_ptr_ty, elem_ty); |
| | 8229 | |
| | 8230 | const second_elem_ptr_reg = try self.register_manager.allocReg(null, gp); |
| | 8231 | const second_elem_ptr_mcv: MCValue = .{ .register = second_elem_ptr_reg }; |
| | 8232 | const second_elem_ptr_lock = self.register_manager.lockRegAssumeUnused(second_elem_ptr_reg); |
| | 8233 | defer self.register_manager.unlockReg(second_elem_ptr_lock); |
| | 8234 | |
| | 8235 | try self.asmRegisterMemory( |
| | 8236 | .lea, |
| | 8237 | second_elem_ptr_reg, |
| | 8238 | Memory.sib(.qword, .{ |
| | 8239 | .base = try self.copyToTmpRegister(Type.usize, ptr), |
| | 8240 | .disp = elem_abi_size, |
| | 8241 | }), |
| | 8242 | ); |
| | 8243 | |
| | 8244 | try self.genBinOpMir(.sub, Type.usize, len_mcv, .{ .immediate = 1 }); |
| | 8245 | try self.asmRegisterRegisterImmediate(.imul, len_reg, len_reg, Immediate.u(elem_abi_size)); |
| | 8246 | try self.genInlineMemcpy(second_elem_ptr_mcv, ptr, len_mcv, .{}); |
| | 8247 | |
| | 8248 | try self.performReloc(skip_reloc); |
| 8207 | }, | 8249 | }, |
| 8208 | .One => { | 8250 | .One => { |
| 8209 | const len = dst_ptr_ty.childType().arrayLen(); | 8251 | const len = dst_ptr_ty.childType().arrayLen(); |
| ... | @@ -8215,8 +8257,6 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void { | ... | @@ -8215,8 +8257,6 @@ fn airMemset(self: *Self, inst: Air.Inst.Index, safety: bool) !void { |
| 8215 | const second_elem_ptr_lock = self.register_manager.lockRegAssumeUnused(second_elem_ptr_reg); | 8257 | const second_elem_ptr_lock = self.register_manager.lockRegAssumeUnused(second_elem_ptr_reg); |
| 8216 | defer self.register_manager.unlockReg(second_elem_ptr_lock); | 8258 | defer self.register_manager.unlockReg(second_elem_ptr_lock); |
| 8217 | | 8259 | |
| 8218 | const elem_abi_size = @intCast(u31, elem_ty.abiSize(self.target.*)); | | |
| 8219 | | | |
| 8220 | try self.asmRegisterMemory( | 8260 | try self.asmRegisterMemory( |
| 8221 | .lea, | 8261 | .lea, |
| 8222 | second_elem_ptr_reg, | 8262 | second_elem_ptr_reg, |