diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index c04bb1d2a5..4aa2443295 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/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 }); diff --git a/src/codegen.zig b/src/codegen.zig index 7f65df2804..7a22d0b218 100644 --- a/src/codegen.zig +++ b/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; diff --git a/test/behavior/optional.zig b/test/behavior/optional.zig index 34d8337608..e62065cf25 100644 --- a/test/behavior/optional.zig +++ b/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