Commit 6d7808e647

mparadinha <miguel.p.paradinha@gmail.com>
2022-03-18 04:33:18
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).
1 parent 18a43b6
Changed files (1)
src
arch
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 });
 }