From 6d7808e647e6d244e53a18139c22bce8cd38a3ca Mon Sep 17 00:00:00 2001 From: mparadinha Date: Fri, 18 Mar 2022 03:33:18 +0000 Subject: [PATCH] stage2: x86_64: implement `ptr_elem_val` The codegen for this is almost identical to `ptr_elem_ptr` except there's an extra `mov` at the end to replace the pointer with the value it points to, "in-place" (which can be done in a single instruction without any extra registers). --- src/arch/x86_64/CodeGen.zig | 42 +++++++++++++++++++++++++++++++++---- 1 file changed, 38 insertions(+), 4 deletions(-) diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index 37d93f870c..65b7b73f39 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -2174,10 +2174,44 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) !void { fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) !void { const is_volatile = false; // TODO const bin_op = self.air.instructions.items(.data)[inst].bin_op; - const result: MCValue = if (!is_volatile and self.liveness.isUnused(inst)) - .dead - else - return self.fail("TODO implement ptr_elem_val for {}", .{self.target.cpu.arch}); + const result: MCValue = if (!is_volatile and self.liveness.isUnused(inst)) .dead else result: { + // this is identical to the `airPtrElemPtr` codegen expect here an + // additional `mov` is needed at the end to get the actual value + + const ptr_ty = self.air.typeOf(bin_op.lhs); + const ptr = try self.resolveInst(bin_op.lhs); + ptr.freezeIfRegister(&self.register_manager); + defer ptr.unfreezeIfRegister(&self.register_manager); + + const elem_ty = ptr_ty.elemType2(); + const elem_abi_size = elem_ty.abiSize(self.target.*); + const index_ty = self.air.typeOf(bin_op.rhs); + const index = try self.resolveInst(bin_op.rhs); + index.freezeIfRegister(&self.register_manager); + defer index.unfreezeIfRegister(&self.register_manager); + + const offset_reg = try self.elemOffset(index_ty, index, elem_abi_size); + self.register_manager.freezeRegs(&.{offset_reg}); + defer self.register_manager.unfreezeRegs(&.{offset_reg}); + + const dst_mcv = try self.copyToRegisterWithInstTracking(inst, ptr_ty, ptr); + try self.genBinMathOpMir(.add, ptr_ty, dst_mcv, .{ .register = offset_reg }); + if (elem_abi_size > 8) { + return self.fail("TODO copy value with size {} from pointer", .{elem_abi_size}); + } else { + // mov dst_mcv, [dst_mcv] + _ = try self.addInst(.{ + .tag = .mov, + .ops = (Mir.Ops{ + .flags = 0b01, + .reg1 = registerAlias(dst_mcv.register, @intCast(u32, elem_abi_size)), + .reg2 = dst_mcv.register, + }).encode(), + .data = .{ .imm = 0 }, + }); + break :result .{ .register = registerAlias(dst_mcv.register, @intCast(u32, elem_abi_size)) }; + } + }; return self.finishAir(inst, result, .{ bin_op.lhs, bin_op.rhs, .none }); }