From d961b11cde81e92ed3d35c98f7b191255aac58a6 Mon Sep 17 00:00:00 2001 From: Robin Voetter Date: Sat, 22 Apr 2023 11:18:38 +0200 Subject: [PATCH] spirv: lower wrap_optional This implements the wrap_optional AIR instruction. --- src/codegen/spirv.zig | 48 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index ab2bdd64a7..6911588fd0 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -420,6 +420,26 @@ pub const DeclGen = struct { return result_id; } + fn constBool(self: *DeclGen, value: bool, repr: Repr) !IdRef { + switch (repr) { + .indirect => { + const int_ty_ref = try self.intType(.unsigned, 1); + return self.constInt(int_ty_ref, @boolToInt(value)); + }, + .direct => { + const bool_ty_ref = try self.resolveType(Type.bool, .direct); + const result_id = self.spv.allocId(); + const operands = .{ .id_result_type = self.typeId(bool_ty_ref), .id_result = result_id }; + if (value) { + try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpConstantTrue, operands); + } else { + try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpConstantFalse, operands); + } + return result_id; + }, + } + } + const IndirectConstantLowering = struct { const undef = 0xAA; @@ -1718,6 +1738,7 @@ pub const DeclGen = struct { .is_non_null => try self.airIsNull(inst, .is_non_null), .optional_payload => try self.airUnwrapOptional(inst), + .wrap_optional => try self.airWrapOptional(inst), .assembly => try self.airAssembly(inst), @@ -2713,6 +2734,33 @@ pub const DeclGen = struct { return try self.extractField(payload_ty, operand_id, 0); } + fn airWrapOptional(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { + if (self.liveness.isUnused(inst)) return null; + + const ty_op = self.air.instructions.items(.data)[inst].ty_op; + const payload_ty = self.air.typeOf(ty_op.operand); + + if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { + return try self.constBool(true, .direct); + } + + const operand_id = try self.resolve(ty_op.operand); + const optional_ty = self.air.typeOfIndex(inst); + if (optional_ty.optionalReprIsPayload()) { + return operand_id; + } + + const optional_ty_ref = try self.resolveType(optional_ty, .direct); + const result_id = self.spv.allocId(); + const members = [_]IdRef{ operand_id, try self.constBool(true, .indirect) }; + try self.func.body.emit(self.spv.gpa, .OpCompositeConstruct, .{ + .id_result_type = self.typeId(optional_ty_ref), + .id_result = result_id, + .constituents = &members, + }); + return result_id; + } + fn airSwitchBr(self: *DeclGen, inst: Air.Inst.Index) !void { const target = self.getTarget(); const pl_op = self.air.instructions.items(.data)[inst].pl_op;