authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-04-21 21:30:22-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-04-25 11:23:40-07:00
log25d11283b7b79edd383163cb2a72bd79dcf02dba
tree0b1ec51b64397501364551d8b8a4114f51a90602
parent76e340cbfa9cad9a69c5917cb0931861313b56a8

x86 backend: implement new memcpy/memset semantics


1 files changed, 28 insertions(+), 12 deletions(-)

src/arch/x86_64/CodeGen.zig+28-12
...@@ -7678,6 +7678,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -7678,6 +7678,7 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
7678fn airPtrToInt(self: *Self, inst: Air.Inst.Index) !void {7678fn airPtrToInt(self: *Self, inst: Air.Inst.Index) !void {
7679 const un_op = self.air.instructions.items(.data)[inst].un_op;7679 const un_op = self.air.instructions.items(.data)[inst].un_op;
7680 const result = result: {7680 const result = result: {
7681 // TODO: handle case where the operand is a slice not a raw pointer
7681 const src_mcv = try self.resolveInst(un_op);7682 const src_mcv = try self.resolveInst(un_op);
7682 if (self.reuseOperand(inst, un_op, 0, src_mcv)) break :result src_mcv;7683 if (self.reuseOperand(inst, un_op, 0, src_mcv)) break :result src_mcv;
76837684
...@@ -8149,63 +8150,78 @@ fn airAtomicStore(self: *Self, inst: Air.Inst.Index, order: std.builtin.AtomicOr...@@ -8149,63 +8150,78 @@ fn airAtomicStore(self: *Self, inst: Air.Inst.Index, order: std.builtin.AtomicOr
8149}8150}
81508151
8151fn airMemset(self: *Self, inst: Air.Inst.Index) !void {8152fn airMemset(self: *Self, inst: Air.Inst.Index) !void {
8152 const pl_op = self.air.instructions.items(.data)[inst].pl_op;8153 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
8153 const extra = self.air.extraData(Air.Bin, pl_op.payload).data;
81548154
8155 const dst_ptr = try self.resolveInst(pl_op.operand);8155 const dst_ptr = try self.resolveInst(bin_op.lhs);
8156 const dst_ptr_ty = self.air.typeOf(bin_op.lhs);
8156 const dst_ptr_lock: ?RegisterLock = switch (dst_ptr) {8157 const dst_ptr_lock: ?RegisterLock = switch (dst_ptr) {
8157 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),8158 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
8158 else => null,8159 else => null,
8159 };8160 };
8160 defer if (dst_ptr_lock) |lock| self.register_manager.unlockReg(lock);8161 defer if (dst_ptr_lock) |lock| self.register_manager.unlockReg(lock);
81618162
8162 const src_val = try self.resolveInst(extra.lhs);8163 const src_val = try self.resolveInst(bin_op.rhs);
8164 const elem_ty = self.air.typeOf(bin_op.rhs);
8163 const src_val_lock: ?RegisterLock = switch (src_val) {8165 const src_val_lock: ?RegisterLock = switch (src_val) {
8164 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),8166 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
8165 else => null,8167 else => null,
8166 };8168 };
8167 defer if (src_val_lock) |lock| self.register_manager.unlockReg(lock);8169 defer if (src_val_lock) |lock| self.register_manager.unlockReg(lock);
81688170
8169 const len = try self.resolveInst(extra.rhs);8171 if (elem_ty.abiSize(self.target.*) != 1) {
8172 return self.fail("TODO implement airMemset when element ABI size > 1", .{});
8173 }
8174
8175 const len = switch (dst_ptr_ty.ptrSize()) {
8176 .Slice => @as(MCValue, .{ .stack_offset = dst_ptr.stack_offset - 8 }),
8177 .One => @as(MCValue, .{ .immediate = dst_ptr_ty.childType().arrayLen() }),
8178 .C, .Many => unreachable,
8179 };
8170 const len_lock: ?RegisterLock = switch (len) {8180 const len_lock: ?RegisterLock = switch (len) {
8171 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),8181 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
8172 else => null,8182 else => null,
8173 };8183 };
8174 defer if (len_lock) |lock| self.register_manager.unlockReg(lock);8184 defer if (len_lock) |lock| self.register_manager.unlockReg(lock);
81758185
8186 // TODO: dst_ptr could be a slice rather than raw pointer
8176 try self.genInlineMemset(dst_ptr, src_val, len, .{});8187 try self.genInlineMemset(dst_ptr, src_val, len, .{});
81778188
8178 return self.finishAir(inst, .unreach, .{ pl_op.operand, extra.lhs, extra.rhs });8189 return self.finishAir(inst, .unreach, .{ bin_op.lhs, bin_op.rhs, .none });
8179}8190}
81808191
8181fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void {8192fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void {
8182 const pl_op = self.air.instructions.items(.data)[inst].pl_op;8193 const bin_op = self.air.instructions.items(.data)[inst].bin_op;
8183 const extra = self.air.extraData(Air.Bin, pl_op.payload).data;
81848194
8185 const dst_ptr = try self.resolveInst(pl_op.operand);8195 const dst_ptr = try self.resolveInst(bin_op.lhs);
8196 const dst_ptr_ty = self.air.typeOf(bin_op.lhs);
8186 const dst_ptr_lock: ?RegisterLock = switch (dst_ptr) {8197 const dst_ptr_lock: ?RegisterLock = switch (dst_ptr) {
8187 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),8198 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
8188 else => null,8199 else => null,
8189 };8200 };
8190 defer if (dst_ptr_lock) |lock| self.register_manager.unlockReg(lock);8201 defer if (dst_ptr_lock) |lock| self.register_manager.unlockReg(lock);
81918202
8192 const src_ptr = try self.resolveInst(extra.lhs);8203 const src_ptr = try self.resolveInst(bin_op.rhs);
8193 const src_ptr_lock: ?RegisterLock = switch (src_ptr) {8204 const src_ptr_lock: ?RegisterLock = switch (src_ptr) {
8194 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),8205 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
8195 else => null,8206 else => null,
8196 };8207 };
8197 defer if (src_ptr_lock) |lock| self.register_manager.unlockReg(lock);8208 defer if (src_ptr_lock) |lock| self.register_manager.unlockReg(lock);
81988209
8199 const len = try self.resolveInst(extra.rhs);8210 const len = switch (dst_ptr_ty.ptrSize()) {
8211 .Slice => @as(MCValue, .{ .stack_offset = dst_ptr.stack_offset - 8 }),
8212 .One => @as(MCValue, .{ .immediate = dst_ptr_ty.childType().arrayLen() }),
8213 .C, .Many => unreachable,
8214 };
8200 const len_lock: ?RegisterLock = switch (len) {8215 const len_lock: ?RegisterLock = switch (len) {
8201 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),8216 .register => |reg| self.register_manager.lockRegAssumeUnused(reg),
8202 else => null,8217 else => null,
8203 };8218 };
8204 defer if (len_lock) |lock| self.register_manager.unlockReg(lock);8219 defer if (len_lock) |lock| self.register_manager.unlockReg(lock);
82058220
8221 // TODO: dst_ptr and src_ptr could be slices rather than raw pointers
8206 try self.genInlineMemcpy(dst_ptr, src_ptr, len, .{});8222 try self.genInlineMemcpy(dst_ptr, src_ptr, len, .{});
82078223
8208 return self.finishAir(inst, .unreach, .{ pl_op.operand, extra.lhs, extra.rhs });8224 return self.finishAir(inst, .unreach, .{ bin_op.lhs, bin_op.rhs, .none });
8209}8225}
82108226
8211fn airTagName(self: *Self, inst: Air.Inst.Index) !void {8227fn airTagName(self: *Self, inst: Air.Inst.Index) !void {