Commit 57c38f6433

Jacob Young <jacobly0@users.noreply.github.com>
2023-05-13 08:24:41
x86_64: implement global payload pointers
1 parent 2cbd442
Changed files (3)
src
test
behavior
src/arch/x86_64/CodeGen.zig
@@ -3467,14 +3467,17 @@ fn airOptionalPayloadPtrSet(self: *Self, inst: Air.Inst.Index) !void {
                 try self.copyToRegisterWithInstTracking(inst, dst_ty, src_mcv);
         }
 
-        const dst_mcv = if (src_mcv.isRegister() and self.reuseOperand(inst, ty_op.operand, 0, src_mcv))
+        const dst_mcv: MCValue = if (src_mcv.isRegister() and
+            self.reuseOperand(inst, ty_op.operand, 0, src_mcv))
             src_mcv
+        else if (self.liveness.isUnused(inst))
+            .{ .register = try self.copyToTmpRegister(dst_ty, src_mcv) }
         else
             try self.copyToRegisterWithInstTracking(inst, dst_ty, src_mcv);
 
         const pl_ty = dst_ty.childType();
         const pl_abi_size = @intCast(i32, pl_ty.abiSize(self.target.*));
-        try self.genSetMem(.{ .reg = dst_mcv.register }, pl_abi_size, Type.bool, .{ .immediate = 1 });
+        try self.genSetMem(.{ .reg = dst_mcv.getReg().? }, pl_abi_size, Type.bool, .{ .immediate = 1 });
         break :result if (self.liveness.isUnused(inst)) .unreach else dst_mcv;
     };
     return self.finishAir(inst, result, .{ ty_op.operand, .none, .none });
src/codegen.zig
@@ -380,7 +380,7 @@ pub fn generateSymbol(
 
                 return Result.ok;
             },
-            .field_ptr, .elem_ptr => return lowerParentPtr(
+            .field_ptr, .elem_ptr, .opt_payload_ptr => return lowerParentPtr(
                 bin_file,
                 src_loc,
                 typed_value,
@@ -812,7 +812,6 @@ fn lowerParentPtr(
     reloc_info: RelocInfo,
 ) CodeGenError!Result {
     const target = bin_file.options.target;
-
     switch (parent_ptr.tag()) {
         .field_ptr => {
             const field_ptr = parent_ptr.castTag(.field_ptr).?.data;
@@ -858,6 +857,31 @@ fn lowerParentPtr(
                 reloc_info.offset(@intCast(u32, elem_ptr.index * elem_ptr.elem_ty.abiSize(target))),
             );
         },
+        .opt_payload_ptr => {
+            const opt_payload_ptr = parent_ptr.castTag(.opt_payload_ptr).?.data;
+            return lowerParentPtr(
+                bin_file,
+                src_loc,
+                typed_value,
+                opt_payload_ptr.container_ptr,
+                code,
+                debug_output,
+                reloc_info,
+            );
+        },
+        .eu_payload_ptr => {
+            const eu_payload_ptr = parent_ptr.castTag(.eu_payload_ptr).?.data;
+            const pl_ty = eu_payload_ptr.container_ty.errorUnionPayload();
+            return lowerParentPtr(
+                bin_file,
+                src_loc,
+                typed_value,
+                eu_payload_ptr.container_ptr,
+                code,
+                debug_output,
+                reloc_info.offset(@intCast(u32, errUnionPayloadOffset(pl_ty, target))),
+            );
+        },
         .variable, .decl_ref, .decl_ref_mut => |tag| return lowerDeclRef(
             bin_file,
             src_loc,
@@ -1262,9 +1286,10 @@ pub fn genTypedValue(
 }
 
 pub fn errUnionPayloadOffset(payload_ty: Type, target: std.Target) u64 {
+    if (!payload_ty.hasRuntimeBitsIgnoreComptime()) return 0;
     const payload_align = payload_ty.abiAlignment(target);
     const error_align = Type.anyerror.abiAlignment(target);
-    if (payload_align >= error_align) {
+    if (payload_align >= error_align or !payload_ty.hasRuntimeBitsIgnoreComptime()) {
         return 0;
     } else {
         return mem.alignForwardGeneric(u64, Type.anyerror.abiSize(target), payload_align);
@@ -1272,9 +1297,10 @@ pub fn errUnionPayloadOffset(payload_ty: Type, target: std.Target) u64 {
 }
 
 pub fn errUnionErrorOffset(payload_ty: Type, target: std.Target) u64 {
+    if (!payload_ty.hasRuntimeBitsIgnoreComptime()) return 0;
     const payload_align = payload_ty.abiAlignment(target);
     const error_align = Type.anyerror.abiAlignment(target);
-    if (payload_align >= error_align) {
+    if (payload_align >= error_align and payload_ty.hasRuntimeBitsIgnoreComptime()) {
         return mem.alignForwardGeneric(u64, payload_ty.abiSize(target), error_align);
     } else {
         return 0;
test/behavior/optional.zig
@@ -74,7 +74,6 @@ test "optional with void type" {
 test "address of unwrap optional" {
     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
     if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
-    if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
     if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
     if (builtin.zig_backend == .stage2_spirv64) return error.SkipZigTest;
 
@@ -365,7 +364,6 @@ test "optional pointer to zero bit optional payload" {
 }
 
 test "optional pointer to zero bit error union payload" {
-    if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
     if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
     if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
     if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO