| ... | @@ -703,7 +703,7 @@ pub const DeclGen = struct { | ... | @@ -703,7 +703,7 @@ pub const DeclGen = struct { |
| 703 | | 703 | |
| 704 | fn genInst(self: *DeclGen, inst: Air.Inst.Index) !void { | 704 | fn genInst(self: *DeclGen, inst: Air.Inst.Index) !void { |
| 705 | const air_tags = self.air.instructions.items(.tag); | 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 | // zig fmt: off | 707 | // zig fmt: off |
| 708 | .add, .addwrap => try self.airArithOp(inst, .OpFAdd, .OpIAdd, .OpIAdd), | 708 | .add, .addwrap => try self.airArithOp(inst, .OpFAdd, .OpIAdd, .OpIAdd), |
| 709 | .sub, .subwrap => try self.airArithOp(inst, .OpFSub, .OpISub, .OpISub), | 709 | .sub, .subwrap => try self.airArithOp(inst, .OpFSub, .OpISub, .OpISub), |
| ... | @@ -717,7 +717,8 @@ pub const DeclGen = struct { | ... | @@ -717,7 +717,8 @@ pub const DeclGen = struct { |
| 717 | .bool_and => try self.airBinOpSimple(inst, .OpLogicalAnd), | 717 | .bool_and => try self.airBinOpSimple(inst, .OpLogicalAnd), |
| 718 | .bool_or => try self.airBinOpSimple(inst, .OpLogicalOr), | 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 | .cmp_eq => try self.airCmp(inst, .OpFOrdEqual, .OpLogicalEqual, .OpIEqual), | 723 | .cmp_eq => try self.airCmp(inst, .OpFOrdEqual, .OpLogicalEqual, .OpIEqual), |
| 723 | .cmp_neq => try self.airCmp(inst, .OpFOrdNotEqual, .OpLogicalNotEqual, .OpINotEqual), | 724 | .cmp_neq => try self.airCmp(inst, .OpFOrdNotEqual, .OpLogicalNotEqual, .OpINotEqual), |
| ... | @@ -728,10 +729,9 @@ pub const DeclGen = struct { | ... | @@ -728,10 +729,9 @@ pub const DeclGen = struct { |
| 728 | | 729 | |
| 729 | .arg => self.airArg(), | 730 | .arg => self.airArg(), |
| 730 | .alloc => try self.airAlloc(inst), | 731 | .alloc => try self.airAlloc(inst), |
| 731 | .block => (try self.airBlock(inst)) orelse return, | 732 | .block => try self.airBlock(inst), |
| 732 | .load => try self.airLoad(inst), | 733 | .load => try self.airLoad(inst), |
| 733 | | 734 | |
| 734 | .bitcast => try self.airBitcast(inst), | | |
| 735 | .br => return self.airBr(inst), | 735 | .br => return self.airBr(inst), |
| 736 | .breakpoint => return, | 736 | .breakpoint => return, |
| 737 | .cond_br => return self.airCondBr(inst), | 737 | .cond_br => return self.airCondBr(inst), |
| ... | @@ -741,12 +741,13 @@ pub const DeclGen = struct { | ... | @@ -741,12 +741,13 @@ pub const DeclGen = struct { |
| 741 | .ret => return self.airRet(inst), | 741 | .ret => return self.airRet(inst), |
| 742 | .store => return self.airStore(inst), | 742 | .store => return self.airStore(inst), |
| 743 | .unreach => return self.airUnreach(), | 743 | .unreach => return self.airUnreach(), |
| 744 | .assembly => (try self.airAssembly(inst)) orelse return, | | |
| 745 | | 744 | |
| 746 | .call => (try self.airCall(inst, .auto)) orelse return, | 745 | .assembly => try self.airAssembly(inst), |
| 747 | .call_always_tail => (try self.airCall(inst, .always_tail)) orelse return, | 746 | |
| 748 | .call_never_tail => (try self.airCall(inst, .never_tail)) orelse return, | 747 | .call => try self.airCall(inst, .auto), |
| 749 | .call_never_inline => (try self.airCall(inst, .never_inline)) orelse return, | 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 | .dbg_var_ptr => return, | 752 | .dbg_var_ptr => return, |
| 752 | .dbg_var_val => return, | 753 | .dbg_var_val => return, |
| ... | @@ -757,10 +758,12 @@ pub const DeclGen = struct { | ... | @@ -757,10 +758,12 @@ pub const DeclGen = struct { |
| 757 | else => |tag| return self.todo("implement AIR tag {s}", .{@tagName(tag)}), | 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 | try self.inst_results.putNoClobber(self.gpa, inst, result_id); | 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 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 767 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 765 | const lhs_id = try self.resolve(bin_op.lhs); | 768 | const lhs_id = try self.resolve(bin_op.lhs); |
| 766 | const rhs_id = try self.resolve(bin_op.rhs); | 769 | const rhs_id = try self.resolve(bin_op.rhs); |
| ... | @@ -781,7 +784,8 @@ pub const DeclGen = struct { | ... | @@ -781,7 +784,8 @@ pub const DeclGen = struct { |
| 781 | comptime fop: Opcode, | 784 | comptime fop: Opcode, |
| 782 | comptime sop: Opcode, | 785 | comptime sop: Opcode, |
| 783 | comptime uop: Opcode, | 786 | comptime uop: Opcode, |
| 784 | ) !IdRef { | 787 | ) !?IdRef { |
| | 788 | if (self.liveness.isUnused(inst)) return null; |
| 785 | // LHS and RHS are guaranteed to have the same type, and AIR guarantees | 789 | // LHS and RHS are guaranteed to have the same type, and AIR guarantees |
| 786 | // the result to be the same as the LHS and RHS, which matches SPIR-V. | 790 | // the result to be the same as the LHS and RHS, which matches SPIR-V. |
| 787 | const ty = self.air.typeOfIndex(inst); | 791 | const ty = self.air.typeOfIndex(inst); |
| ... | @@ -833,7 +837,8 @@ pub const DeclGen = struct { | ... | @@ -833,7 +837,8 @@ pub const DeclGen = struct { |
| 833 | return result_id.toRef(); | 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 | const ty = self.air.typeOfIndex(inst); | 842 | const ty = self.air.typeOfIndex(inst); |
| 838 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; | 843 | const ty_pl = self.air.instructions.items(.data)[inst].ty_pl; |
| 839 | const extra = self.air.extraData(Air.Shuffle, ty_pl.payload).data; | 844 | const extra = self.air.extraData(Air.Shuffle, ty_pl.payload).data; |
| ... | @@ -868,7 +873,8 @@ pub const DeclGen = struct { | ... | @@ -868,7 +873,8 @@ pub const DeclGen = struct { |
| 868 | return result_id.toRef(); | 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 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; | 878 | const bin_op = self.air.instructions.items(.data)[inst].bin_op; |
| 873 | const lhs_id = try self.resolve(bin_op.lhs); | 879 | const lhs_id = try self.resolve(bin_op.lhs); |
| 874 | const rhs_id = try self.resolve(bin_op.rhs); | 880 | const rhs_id = try self.resolve(bin_op.rhs); |
| ... | @@ -913,7 +919,22 @@ pub const DeclGen = struct { | ... | @@ -913,7 +919,22 @@ pub const DeclGen = struct { |
| 913 | return result_id.toRef(); | 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 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; | 938 | const ty_op = self.air.instructions.items(.data)[inst].ty_op; |
| 918 | const operand_id = try self.resolve(ty_op.operand); | 939 | const operand_id = try self.resolve(ty_op.operand); |
| 919 | const result_id = self.spv.allocId(); | 940 | const result_id = self.spv.allocId(); |
| ... | @@ -926,7 +947,8 @@ pub const DeclGen = struct { | ... | @@ -926,7 +947,8 @@ pub const DeclGen = struct { |
| 926 | return result_id.toRef(); | 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 | const ty = self.air.typeOfIndex(inst); | 952 | const ty = self.air.typeOfIndex(inst); |
| 931 | const result_type_id = try self.resolveTypeId(ty); | 953 | const result_type_id = try self.resolveTypeId(ty); |
| 932 | const result_id = self.spv.allocId(); | 954 | const result_id = self.spv.allocId(); |
| ... | @@ -981,7 +1003,7 @@ pub const DeclGen = struct { | ... | @@ -981,7 +1003,7 @@ pub const DeclGen = struct { |
| 981 | try self.beginSpvBlock(label_id); | 1003 | try self.beginSpvBlock(label_id); |
| 982 | | 1004 | |
| 983 | // If this block didn't produce a value, simply return here. | 1005 | // If this block didn't produce a value, simply return here. |
| 984 | if (!ty.hasRuntimeBits()) | 1006 | if (!ty.hasRuntimeBitsIgnoreComptime()) |
| 985 | return null; | 1007 | return null; |
| 986 | | 1008 | |
| 987 | // Combine the result from the blocks using the Phi instruction. | 1009 | // Combine the result from the blocks using the Phi instruction. |
| ... | @@ -1002,19 +1024,6 @@ pub const DeclGen = struct { | ... | @@ -1002,19 +1024,6 @@ pub const DeclGen = struct { |
| 1002 | return result_id.toRef(); | 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 | fn airBr(self: *DeclGen, inst: Air.Inst.Index) !void { | 1027 | fn airBr(self: *DeclGen, inst: Air.Inst.Index) !void { |
| 1019 | const br = self.air.instructions.items(.data)[inst].br; | 1028 | const br = self.air.instructions.items(.data)[inst].br; |
| 1020 | const block = self.blocks.get(br.block_inst).?; | 1029 | const block = self.blocks.get(br.block_inst).?; |
| ... | @@ -1104,6 +1113,7 @@ pub const DeclGen = struct { | ... | @@ -1104,6 +1113,7 @@ pub const DeclGen = struct { |
| 1104 | } | 1113 | } |
| 1105 | | 1114 | |
| 1106 | fn airRet(self: *DeclGen, inst: Air.Inst.Index) !void { | 1115 | fn airRet(self: *DeclGen, inst: Air.Inst.Index) !void { |
| | 1116 | if (self.liveness.isUnused(inst)) return; |
| 1107 | const operand = self.air.instructions.items(.data)[inst].un_op; | 1117 | const operand = self.air.instructions.items(.data)[inst].un_op; |
| 1108 | const operand_ty = self.air.typeOf(operand); | 1118 | const operand_ty = self.air.typeOf(operand); |
| 1109 | if (operand_ty.hasRuntimeBits()) { | 1119 | if (operand_ty.hasRuntimeBits()) { |
| ... | @@ -1299,6 +1309,10 @@ pub const DeclGen = struct { | ... | @@ -1299,6 +1309,10 @@ pub const DeclGen = struct { |
| 1299 | try self.func.body.emit(self.spv.gpa, .OpUnreachable, {}); | 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 | return result_id.toRef(); | 1316 | return result_id.toRef(); |
| 1303 | } | 1317 | } |
| 1304 | }; | 1318 | }; |