| ... | @@ -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 |
| 7678 | fn airPtrToInt(self: *Self, inst: Air.Inst.Index) !void { | 7678 | fn 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; |
| 7683 | | 7684 | |
| ... | @@ -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 | } |
| 8150 | | 8151 | |
| 8151 | fn airMemset(self: *Self, inst: Air.Inst.Index) !void { | 8152 | fn 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; | | |
| 8154 | | 8154 | |
| 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); |
| 8161 | | 8162 | |
| 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); |
| 8168 | | 8170 | |
| 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); |
| 8175 | | 8185 | |
| | 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, .{}); |
| 8177 | | 8188 | |
| 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 | } |
| 8180 | | 8191 | |
| 8181 | fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void { | 8192 | fn 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; | | |
| 8184 | | 8194 | |
| 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); |
| 8191 | | 8202 | |
| 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); |
| 8198 | | 8209 | |
| 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); |
| 8205 | | 8220 | |
| | 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, .{}); |
| 8207 | | 8223 | |
| 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 | } |
| 8210 | | 8226 | |
| 8211 | fn airTagName(self: *Self, inst: Air.Inst.Index) !void { | 8227 | fn airTagName(self: *Self, inst: Air.Inst.Index) !void { |