From c2e6731032b72c20b5caf2182883aaede9c1a5ea Mon Sep 17 00:00:00 2001 From: Mick Sayson Date: Wed, 8 Jul 2026 16:05:43 -0700 Subject: [PATCH] Implement spirv optional_payload_ptr_set This fixes functions that return non-primitive optional values. E.g. fn someFnWithOptional(x: f32) ?[2]f32 { if (x > 5) return null; return .{ x, x }; } Pieced together referencing airIsNull, and airUnwrapOptionalPtr. Tested that shaders in an external project are outputting the expected values --- src/codegen/spirv/CodeGen.zig | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/codegen/spirv/CodeGen.zig b/src/codegen/spirv/CodeGen.zig index 0ea7567b5eed6859069b031835c57d1b539afbed..9d86ae254d51dfe4cdc201ce68b956eeb56da28e 100644 --- a/src/codegen/spirv/CodeGen.zig +++ b/src/codegen/spirv/CodeGen.zig @@ -4459,6 +4459,7 @@ fn genInst(cg: *CodeGen, inst: Air.Inst.Index) Error!void { .optional_payload => try cg.airUnwrapOptional(inst), .optional_payload_ptr => try cg.airUnwrapOptionalPtr(inst), + .optional_payload_ptr_set => try cg.airSetOptionalPtr(inst), .wrap_optional => try cg.airWrapOptional(inst), .assembly => try cg.airAssembly(inst), @@ -8017,6 +8018,39 @@ fn airUnwrapOptionalPtr(cg: *CodeGen, inst: Air.Inst.Index) !?Id { return try cg.accessChain(result_ty_id, operand_id, &.{0}); } +fn airSetOptionalPtr(cg: *CodeGen, inst: Air.Inst.Index) !?Id { + const zcu = cg.zcu; + const ty_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; + + const ptr_ty = cg.typeOf(ty_op.operand); + const ptr_id = try cg.resolve(ty_op.operand); + + const optional_ty = ptr_ty.childType(zcu); + const payload_ty = optional_ty.optionalChild(zcu); + const result_ty = cg.typeOfIndex(inst); + + if (optional_ty.optionalReprIsPayload(zcu)) { + return try cg.bitCast(result_ty, ptr_ty, ptr_id); + } + + const storage_class = cg.storageClass(ptr_ty.ptrAddressSpace(zcu)); + const bool_indirect_ty_id = try cg.resolveType(.bool, .indirect); + const bool_ptr_ty_id = try cg.ptrType(bool_indirect_ty_id, storage_class); + const result_ty_id = try cg.resolveType(result_ty, .direct); + + const bool_ptr_id, const ret = switch (payload_ty.hasRuntimeBits(zcu)) { + true => .{ + try cg.accessChain(bool_ptr_ty_id, ptr_id, &.{1}), + try cg.accessChain(result_ty_id, ptr_id, &.{0}), + }, + false => .{ ptr_id, try cg.bitCast(result_ty, ptr_ty, ptr_id) }, + }; + + try cg.store(.bool, bool_ptr_id, try cg.constBool(true, .direct), .{}); + + return ret; +} + fn airWrapOptional(cg: *CodeGen, inst: Air.Inst.Index) !?Id { const zcu = cg.zcu; const ty_op = cg.air.instructions.items(.data)[@intFromEnum(inst)].ty_op; -- 2.54.0