| ... | @@ -420,6 +420,26 @@ pub const DeclGen = struct { | ... | @@ -420,6 +420,26 @@ pub const DeclGen = struct { |
| 420 | return result_id; | 420 | return result_id; |
| 421 | } | 421 | } |
| 422 | | 422 | |
| | 423 | fn constBool(self: *DeclGen, value: bool, repr: Repr) !IdRef { |
| | 424 | switch (repr) { |
| | 425 | .indirect => { |
| | 426 | const int_ty_ref = try self.intType(.unsigned, 1); |
| | 427 | return self.constInt(int_ty_ref, @boolToInt(value)); |
| | 428 | }, |
| | 429 | .direct => { |
| | 430 | const bool_ty_ref = try self.resolveType(Type.bool, .direct); |
| | 431 | const result_id = self.spv.allocId(); |
| | 432 | const operands = .{ .id_result_type = self.typeId(bool_ty_ref), .id_result = result_id }; |
| | 433 | if (value) { |
| | 434 | try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpConstantTrue, operands); |
| | 435 | } else { |
| | 436 | try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpConstantFalse, operands); |
| | 437 | } |
| | 438 | return result_id; |
| | 439 | }, |
| | 440 | } |
| | 441 | } |
| | 442 | |
| 423 | const IndirectConstantLowering = struct { | 443 | const IndirectConstantLowering = struct { |
| 424 | const undef = 0xAA; | 444 | const undef = 0xAA; |
| 425 | | 445 | |
| ... | @@ -1718,6 +1738,7 @@ pub const DeclGen = struct { | ... | @@ -1718,6 +1738,7 @@ pub const DeclGen = struct { |
| 1718 | .is_non_null => try self.airIsNull(inst, .is_non_null), | 1738 | .is_non_null => try self.airIsNull(inst, .is_non_null), |
| 1719 | | 1739 | |
| 1720 | .optional_payload => try self.airUnwrapOptional(inst), | 1740 | .optional_payload => try self.airUnwrapOptional(inst), |
| | 1741 | .wrap_optional => try self.airWrapOptional(inst), |
| 1721 | | 1742 | |
| 1722 | .assembly => try self.airAssembly(inst), | 1743 | .assembly => try self.airAssembly(inst), |
| 1723 | | 1744 | |
| ... | @@ -2713,6 +2734,33 @@ pub const DeclGen = struct { | ... | @@ -2713,6 +2734,33 @@ pub const DeclGen = struct { |
| 2713 | return try self.extractField(payload_ty, operand_id, 0); | 2734 | return try self.extractField(payload_ty, operand_id, 0); |
| 2714 | } | 2735 | } |
| 2715 | | 2736 | |
| | 2737 | fn airWrapOptional(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { |
| | 2738 | if (self.liveness.isUnused(inst)) return null; |
| | 2739 | |
| | 2740 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| | 2741 | const payload_ty = self.air.typeOf(ty_op.operand); |
| | 2742 | |
| | 2743 | if (!payload_ty.hasRuntimeBitsIgnoreComptime()) { |
| | 2744 | return try self.constBool(true, .direct); |
| | 2745 | } |
| | 2746 | |
| | 2747 | const operand_id = try self.resolve(ty_op.operand); |
| | 2748 | const optional_ty = self.air.typeOfIndex(inst); |
| | 2749 | if (optional_ty.optionalReprIsPayload()) { |
| | 2750 | return operand_id; |
| | 2751 | } |
| | 2752 | |
| | 2753 | const optional_ty_ref = try self.resolveType(optional_ty, .direct); |
| | 2754 | const result_id = self.spv.allocId(); |
| | 2755 | const members = [_]IdRef{ operand_id, try self.constBool(true, .indirect) }; |
| | 2756 | try self.func.body.emit(self.spv.gpa, .OpCompositeConstruct, .{ |
| | 2757 | .id_result_type = self.typeId(optional_ty_ref), |
| | 2758 | .id_result = result_id, |
| | 2759 | .constituents = &members, |
| | 2760 | }); |
| | 2761 | return result_id; |
| | 2762 | } |
| | 2763 | |
| 2716 | fn airSwitchBr(self: *DeclGen, inst: Air.Inst.Index) !void { | 2764 | fn airSwitchBr(self: *DeclGen, inst: Air.Inst.Index) !void { |
| 2717 | const target = self.getTarget(); | 2765 | const target = self.getTarget(); |
| 2718 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; | 2766 | const pl_op = self.air.instructions.items(.data)[inst].pl_op; |