| ... | ... | @@ -703,7 +703,7 @@ pub const DeclGen = struct { |
| 703 | 703 | |
| 704 | 704 | fn genInst(self: *DeclGen, inst: Air.Inst.Index) !void { |
| 705 | 705 | const air_tags = self.air.instructions.items(.tag); |
| 706 | | const result_id = switch (air_tags[inst]) { |
| 706 | const maybe_result_id: ?IdRef = switch (air_tags[inst]) { |
| 707 | 707 | // zig fmt: off |
| 708 | 708 | .add, .addwrap => try self.airArithOp(inst, .OpFAdd, .OpIAdd, .OpIAdd), |
| 709 | 709 | .sub, .subwrap => try self.airArithOp(inst, .OpFSub, .OpISub, .OpISub), |
| ... | ... | @@ -717,7 +717,8 @@ pub const DeclGen = struct { |
| 717 | 717 | .bool_and => try self.airBinOpSimple(inst, .OpLogicalAnd), |
| 718 | 718 | .bool_or => try self.airBinOpSimple(inst, .OpLogicalOr), |
| 719 | 719 | |
| 720 | | .not => try self.airNot(inst), |
| 720 | .bitcast => try self.airBitcast(inst), |
| 721 | .not => try self.airNot(inst), |
| 721 | 722 | |
| 722 | 723 | .cmp_eq => try self.airCmp(inst, .OpFOrdEqual, .OpLogicalEqual, .OpIEqual), |
| 723 | 724 | .cmp_neq => try self.airCmp(inst, .OpFOrdNotEqual, .OpLogicalNotEqual, .OpINotEqual), |
| ... | ... | @@ -728,10 +729,9 @@ pub const DeclGen = struct { |
| 728 | 729 | |
| 729 | 730 | .arg => self.airArg(), |
| 730 | 731 | .alloc => try self.airAlloc(inst), |
| 731 | | .block => (try self.airBlock(inst)) orelse return, |
| 732 | .block => try self.airBlock(inst), |
| 732 | 733 | .load => try self.airLoad(inst), |
| 733 | 734 | |
| 734 | | .bitcast => try self.airBitcast(inst), |
| 735 | 735 | .br => return self.airBr(inst), |
| 736 | 736 | .breakpoint => return, |
| 737 | 737 | .cond_br => return self.airCondBr(inst), |
| ... | ... | @@ -741,12 +741,13 @@ pub const DeclGen = struct { |
| 741 | 741 | .ret => return self.airRet(inst), |
| 742 | 742 | .store => return self.airStore(inst), |
| 743 | 743 | .unreach => return self.airUnreach(), |
| 744 | | .assembly => (try self.airAssembly(inst)) orelse return, |
| 745 | 744 | |
| 746 | | .call => (try self.airCall(inst, .auto)) orelse return, |
| 747 | | .call_always_tail => (try self.airCall(inst, .always_tail)) orelse return, |
| 748 | | .call_never_tail => (try self.airCall(inst, .never_tail)) orelse return, |
| 749 | | .call_never_inline => (try self.airCall(inst, .never_inline)) orelse return, |
| 745 | .assembly => try self.airAssembly(inst), |
| 746 | |
| 747 | .call => try self.airCall(inst, .auto), |
| 748 | .call_always_tail => try self.airCall(inst, .always_tail), |
| 749 | .call_never_tail => try self.airCall(inst, .never_tail), |
| 750 | .call_never_inline => try self.airCall(inst, .never_inline), |
| 750 | 751 | |
| 751 | 752 | .dbg_var_ptr => return, |
| 752 | 753 | .dbg_var_val => return, |
| ... | ... | @@ -757,10 +758,12 @@ pub const DeclGen = struct { |
| 757 | 758 | else => |tag| return self.todo("implement AIR tag {s}", .{@tagName(tag)}), |
| 758 | 759 | }; |
| 759 | 760 | |
| 761 | const result_id = maybe_result_id orelse return; |
| 760 | 762 | try self.inst_results.putNoClobber(self.gpa, inst, result_id); |
| 761 | 763 | } |
| 762 | 764 | |
| 763 | | fn airBinOpSimple(self: *DeclGen, inst: Air.Inst.Index, comptime opcode: Opcode) !IdRef { |
| 765 | fn airBinOpSimple(self: *DeclGen, inst: Air.Inst.Index, comptime opcode: Opcode) !?IdRef { |
| 766 | if (self.liveness.isUnused(inst)) return null; |
| 764 | 767 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 765 | 768 | const lhs_id = try self.resolve(bin_op.lhs); |
| 766 | 769 | const rhs_id = try self.resolve(bin_op.rhs); |
| ... | ... | @@ -781,7 +784,8 @@ pub const DeclGen = struct { |
| 781 | 784 | comptime fop: Opcode, |
| 782 | 785 | comptime sop: Opcode, |
| 783 | 786 | comptime uop: Opcode, |
| 784 | | ) !IdRef { |
| 787 | ) !?IdRef { |
| 788 | if (self.liveness.isUnused(inst)) return null; |
| 785 | 789 | // LHS and RHS are guaranteed to have the same type, and AIR guarantees |
| 786 | 790 | // the result to be the same as the LHS and RHS, which matches SPIR-V. |
| 787 | 791 | const ty = self.air.typeOfIndex(inst); |
| ... | ... | @@ -833,7 +837,8 @@ pub const DeclGen = struct { |
| 833 | 837 | return result_id.toRef(); |
| 834 | 838 | } |
| 835 | 839 | |
| 836 | | fn airShuffle(self: *DeclGen, inst: Air.Inst.Index) !IdRef { |
| 840 | fn airShuffle(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { |
| 841 | if (self.liveness.isUnused(inst)) return null; |
| 837 | 842 | const ty = self.air.typeOfIndex(inst); |
| 838 | 843 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 839 | 844 | const extra = self.air.extraData(Air.Shuffle, ty_pl.payload).data; |
| ... | ... | @@ -868,7 +873,8 @@ pub const DeclGen = struct { |
| 868 | 873 | return result_id.toRef(); |
| 869 | 874 | } |
| 870 | 875 | |
| 871 | | fn airCmp(self: *DeclGen, inst: Air.Inst.Index, comptime fop: Opcode, comptime sop: Opcode, comptime uop: Opcode) !IdRef { |
| 876 | fn airCmp(self: *DeclGen, inst: Air.Inst.Index, comptime fop: Opcode, comptime sop: Opcode, comptime uop: Opcode) !?IdRef { |
| 877 | if (self.liveness.isUnused(inst)) return null; |
| 872 | 878 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 873 | 879 | const lhs_id = try self.resolve(bin_op.lhs); |
| 874 | 880 | const rhs_id = try self.resolve(bin_op.rhs); |
| ... | ... | @@ -913,7 +919,22 @@ pub const DeclGen = struct { |
| 913 | 919 | return result_id.toRef(); |
| 914 | 920 | } |
| 915 | 921 | |
| 916 | | fn airNot(self: *DeclGen, inst: Air.Inst.Index) !IdRef { |
| 922 | fn airBitcast(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { |
| 923 | if (self.liveness.isUnused(inst)) return null; |
| 924 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 925 | const operand_id = try self.resolve(ty_op.operand); |
| 926 | const result_id = self.spv.allocId(); |
| 927 | const result_type_id = try self.resolveTypeId(Type.initTag(.bool)); |
| 928 | try self.func.body.emit(self.spv.gpa, .OpBitcast, .{ |
| 929 | .id_result_type = result_type_id, |
| 930 | .id_result = result_id, |
| 931 | .operand = operand_id, |
| 932 | }); |
| 933 | return result_id.toRef(); |
| 934 | } |
| 935 | |
| 936 | fn airNot(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { |
| 937 | if (self.liveness.isUnused(inst)) return null; |
| 917 | 938 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 918 | 939 | const operand_id = try self.resolve(ty_op.operand); |
| 919 | 940 | const result_id = self.spv.allocId(); |
| ... | ... | @@ -926,7 +947,8 @@ pub const DeclGen = struct { |
| 926 | 947 | return result_id.toRef(); |
| 927 | 948 | } |
| 928 | 949 | |
| 929 | | fn airAlloc(self: *DeclGen, inst: Air.Inst.Index) !IdRef { |
| 950 | fn airAlloc(self: *DeclGen, inst: Air.Inst.Index) !?IdRef { |
| 951 | if (self.liveness.isUnused(inst)) return null; |
| 930 | 952 | const ty = self.air.typeOfIndex(inst); |
| 931 | 953 | const result_type_id = try self.resolveTypeId(ty); |
| 932 | 954 | const result_id = self.spv.allocId(); |
| ... | ... | @@ -981,7 +1003,7 @@ pub const DeclGen = struct { |
| 981 | 1003 | try self.beginSpvBlock(label_id); |
| 982 | 1004 | |
| 983 | 1005 | // If this block didn't produce a value, simply return here. |
| 984 | | if (!ty.hasRuntimeBits()) |
| 1006 | if (!ty.hasRuntimeBitsIgnoreComptime()) |
| 985 | 1007 | return null; |
| 986 | 1008 | |
| 987 | 1009 | // Combine the result from the blocks using the Phi instruction. |
| ... | ... | @@ -1002,19 +1024,6 @@ pub const DeclGen = struct { |
| 1002 | 1024 | return result_id.toRef(); |
| 1003 | 1025 | } |
| 1004 | 1026 | |
| 1005 | | fn airBitcast(self: *DeclGen, inst: Air.Inst.Index) !IdRef { |
| 1006 | | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 1007 | | const operand_id = try self.resolve(ty_op.operand); |
| 1008 | | const result_id = self.spv.allocId(); |
| 1009 | | const result_type_id = try self.resolveTypeId(Type.initTag(.bool)); |
| 1010 | | try self.func.body.emit(self.spv.gpa, .OpBitcast, .{ |
| 1011 | | .id_result_type = result_type_id, |
| 1012 | | .id_result = result_id, |
| 1013 | | .operand = operand_id, |
| 1014 | | }); |
| 1015 | | return result_id.toRef(); |
| 1016 | | } |
| 1017 | | |
| 1018 | 1027 | fn airBr(self: *DeclGen, inst: Air.Inst.Index) !void { |
| 1019 | 1028 | const br = self.air.instructions.items(.data)[inst].br; |
| 1020 | 1029 | const block = self.blocks.get(br.block_inst).?; |
| ... | ... | @@ -1104,6 +1113,7 @@ pub const DeclGen = struct { |
| 1104 | 1113 | } |
| 1105 | 1114 | |
| 1106 | 1115 | fn airRet(self: *DeclGen, inst: Air.Inst.Index) !void { |
| 1116 | if (self.liveness.isUnused(inst)) return; |
| 1107 | 1117 | const operand = self.air.instructions.items(.data)[inst].un_op; |
| 1108 | 1118 | const operand_ty = self.air.typeOf(operand); |
| 1109 | 1119 | if (operand_ty.hasRuntimeBits()) { |
| ... | ... | @@ -1299,6 +1309,10 @@ pub const DeclGen = struct { |
| 1299 | 1309 | try self.func.body.emit(self.spv.gpa, .OpUnreachable, {}); |
| 1300 | 1310 | } |
| 1301 | 1311 | |
| 1312 | if (self.liveness.isUnused(inst) or !return_type.hasRuntimeBitsIgnoreComptime()) { |
| 1313 | return null; |
| 1314 | } |
| 1315 | |
| 1302 | 1316 | return result_id.toRef(); |
| 1303 | 1317 | } |
| 1304 | 1318 | }; |