| ... | @@ -643,14 +643,12 @@ pub const DeclGen = struct { | ... | @@ -643,14 +643,12 @@ pub const DeclGen = struct { |
| 643 | | 643 | |
| 644 | fn genBody(self: *DeclGen, body: ir.Body) Error!void { | 644 | fn genBody(self: *DeclGen, body: ir.Body) Error!void { |
| 645 | for (body.instructions) |inst| { | 645 | for (body.instructions) |inst| { |
| 646 | const maybe_result_id = try self.genInst(inst); | 646 | try self.genInst(inst); |
| 647 | if (maybe_result_id) |result_id| | | |
| 648 | try self.inst_results.putNoClobber(inst, result_id); | | |
| 649 | } | 647 | } |
| 650 | } | 648 | } |
| 651 | | 649 | |
| 652 | fn genInst(self: *DeclGen, inst: *Inst) !?ResultId { | 650 | fn genInst(self: *DeclGen, inst: *Inst) !void { |
| 653 | return switch (inst.tag) { | 651 | const result_id = switch (inst.tag) { |
| 654 | .add, .addwrap => try self.genBinOp(inst.castTag(.add).?), | 652 | .add, .addwrap => try self.genBinOp(inst.castTag(.add).?), |
| 655 | .sub, .subwrap => try self.genBinOp(inst.castTag(.sub).?), | 653 | .sub, .subwrap => try self.genBinOp(inst.castTag(.sub).?), |
| 656 | .mul, .mulwrap => try self.genBinOp(inst.castTag(.mul).?), | 654 | .mul, .mulwrap => try self.genBinOp(inst.castTag(.mul).?), |
| ... | @@ -669,23 +667,25 @@ pub const DeclGen = struct { | ... | @@ -669,23 +667,25 @@ pub const DeclGen = struct { |
| 669 | .not => try self.genUnOp(inst.castTag(.not).?), | 667 | .not => try self.genUnOp(inst.castTag(.not).?), |
| 670 | .alloc => try self.genAlloc(inst.castTag(.alloc).?), | 668 | .alloc => try self.genAlloc(inst.castTag(.alloc).?), |
| 671 | .arg => self.genArg(), | 669 | .arg => self.genArg(), |
| 672 | .block => try self.genBlock(inst.castTag(.block).?), | 670 | .block => (try self.genBlock(inst.castTag(.block).?)) orelse return, |
| 673 | .br => try self.genBr(inst.castTag(.br).?), | 671 | .br => return try self.genBr(inst.castTag(.br).?), |
| 674 | .br_void => try self.genBrVoid(inst.castTag(.br_void).?), | 672 | .br_void => return try self.genBrVoid(inst.castTag(.br_void).?), |
| 675 | // TODO: Breakpoints won't be supported in SPIR-V, but the compiler seems to insert them | 673 | // TODO: Breakpoints won't be supported in SPIR-V, but the compiler seems to insert them |
| 676 | // throughout the IR. | 674 | // throughout the IR. |
| 677 | .breakpoint => null, | 675 | .breakpoint => return, |
| 678 | .condbr => try self.genCondBr(inst.castTag(.condbr).?), | 676 | .condbr => return try self.genCondBr(inst.castTag(.condbr).?), |
| 679 | .constant => unreachable, | 677 | .constant => unreachable, |
| 680 | .dbg_stmt => try self.genDbgStmt(inst.castTag(.dbg_stmt).?), | 678 | .dbg_stmt => return try self.genDbgStmt(inst.castTag(.dbg_stmt).?), |
| 681 | .load => try self.genLoad(inst.castTag(.load).?), | 679 | .load => try self.genLoad(inst.castTag(.load).?), |
| 682 | .loop => try self.genLoop(inst.castTag(.loop).?), | 680 | .loop => return try self.genLoop(inst.castTag(.loop).?), |
| 683 | .ret => try self.genRet(inst.castTag(.ret).?), | 681 | .ret => return try self.genRet(inst.castTag(.ret).?), |
| 684 | .retvoid => try self.genRetVoid(), | 682 | .retvoid => return try self.genRetVoid(), |
| 685 | .store => try self.genStore(inst.castTag(.store).?), | 683 | .store => return try self.genStore(inst.castTag(.store).?), |
| 686 | .unreach => try self.genUnreach(), | 684 | .unreach => return try self.genUnreach(), |
| 687 | else => self.fail(inst.src, "TODO: SPIR-V backend: implement inst {s}", .{@tagName(inst.tag)}), | 685 | else => return self.fail(inst.src, "TODO: SPIR-V backend: implement inst {s}", .{@tagName(inst.tag)}), |
| 688 | }; | 686 | }; |
| | 687 | |
| | 688 | try self.inst_results.putNoClobber(inst, result_id); |
| 689 | } | 689 | } |
| 690 | | 690 | |
| 691 | fn genBinOp(self: *DeclGen, inst: *Inst.BinOp) !ResultId { | 691 | fn genBinOp(self: *DeclGen, inst: *Inst.BinOp) !ResultId { |
| ... | @@ -876,7 +876,7 @@ pub const DeclGen = struct { | ... | @@ -876,7 +876,7 @@ pub const DeclGen = struct { |
| 876 | return result_id; | 876 | return result_id; |
| 877 | } | 877 | } |
| 878 | | 878 | |
| 879 | fn genBr(self: *DeclGen, inst: *Inst.Br) !?ResultId { | 879 | fn genBr(self: *DeclGen, inst: *Inst.Br) !void { |
| 880 | // TODO: This instruction needs to be the last in a block. Is that guaranteed? | 880 | // TODO: This instruction needs to be the last in a block. Is that guaranteed? |
| 881 | const target = self.blocks.get(inst.block).?; | 881 | const target = self.blocks.get(inst.block).?; |
| 882 | | 882 | |
| ... | @@ -891,19 +891,16 @@ pub const DeclGen = struct { | ... | @@ -891,19 +891,16 @@ pub const DeclGen = struct { |
| 891 | } | 891 | } |
| 892 | | 892 | |
| 893 | try writeInstruction(&self.code, .OpBranch, &[_]Word{target.label_id}); | 893 | try writeInstruction(&self.code, .OpBranch, &[_]Word{target.label_id}); |
| 894 | | | |
| 895 | return null; | | |
| 896 | } | 894 | } |
| 897 | | 895 | |
| 898 | fn genBrVoid(self: *DeclGen, inst: *Inst.BrVoid) !?ResultId { | 896 | fn genBrVoid(self: *DeclGen, inst: *Inst.BrVoid) !void { |
| 899 | // TODO: This instruction needs to be the last in a block. Is that guaranteed? | 897 | // TODO: This instruction needs to be the last in a block. Is that guaranteed? |
| 900 | const target = self.blocks.get(inst.block).?; | 898 | const target = self.blocks.get(inst.block).?; |
| 901 | // Don't need to add this to the incoming block list, as there is no value to insert in the phi node anyway. | 899 | // Don't need to add this to the incoming block list, as there is no value to insert in the phi node anyway. |
| 902 | try writeInstruction(&self.code, .OpBranch, &[_]Word{target.label_id}); | 900 | try writeInstruction(&self.code, .OpBranch, &[_]Word{target.label_id}); |
| 903 | return null; | | |
| 904 | } | 901 | } |
| 905 | | 902 | |
| 906 | fn genCondBr(self: *DeclGen, inst: *Inst.CondBr) !?ResultId { | 903 | fn genCondBr(self: *DeclGen, inst: *Inst.CondBr) !void { |
| 907 | // TODO: This instruction needs to be the last in a block. Is that guaranteed? | 904 | // TODO: This instruction needs to be the last in a block. Is that guaranteed? |
| 908 | const condition_id = try self.resolve(inst.condition); | 905 | const condition_id = try self.resolve(inst.condition); |
| 909 | | 906 | |
| ... | @@ -924,14 +921,11 @@ pub const DeclGen = struct { | ... | @@ -924,14 +921,11 @@ pub const DeclGen = struct { |
| 924 | try self.genBody(inst.then_body); | 921 | try self.genBody(inst.then_body); |
| 925 | try self.beginSPIRVBlock(else_label_id); | 922 | try self.beginSPIRVBlock(else_label_id); |
| 926 | try self.genBody(inst.else_body); | 923 | try self.genBody(inst.else_body); |
| 927 | | | |
| 928 | return null; | | |
| 929 | } | 924 | } |
| 930 | | 925 | |
| 931 | fn genDbgStmt(self: *DeclGen, inst: *Inst.DbgStmt) !?ResultId { | 926 | fn genDbgStmt(self: *DeclGen, inst: *Inst.DbgStmt) !void { |
| 932 | const src_fname_id = try self.spv.resolveSourceFileName(self.decl); | 927 | const src_fname_id = try self.spv.resolveSourceFileName(self.decl); |
| 933 | try writeInstruction(&self.code, .OpLine, &[_]Word{ src_fname_id, inst.line, inst.column }); | 928 | try writeInstruction(&self.code, .OpLine, &[_]Word{ src_fname_id, inst.line, inst.column }); |
| 934 | return null; | | |
| 935 | } | 929 | } |
| 936 | | 930 | |
| 937 | fn genLoad(self: *DeclGen, inst: *Inst.UnOp) !ResultId { | 931 | fn genLoad(self: *DeclGen, inst: *Inst.UnOp) !ResultId { |
| ... | @@ -950,7 +944,7 @@ pub const DeclGen = struct { | ... | @@ -950,7 +944,7 @@ pub const DeclGen = struct { |
| 950 | return result_id; | 944 | return result_id; |
| 951 | } | 945 | } |
| 952 | | 946 | |
| 953 | fn genLoop(self: *DeclGen, inst: *Inst.Loop) !?ResultId { | 947 | fn genLoop(self: *DeclGen, inst: *Inst.Loop) !void { |
| 954 | // TODO: This instruction needs to be the last in a block. Is that guaranteed? | 948 | // TODO: This instruction needs to be the last in a block. Is that guaranteed? |
| 955 | const loop_label_id = self.spv.allocResultId(); | 949 | const loop_label_id = self.spv.allocResultId(); |
| 956 | | 950 | |
| ... | @@ -963,23 +957,20 @@ pub const DeclGen = struct { | ... | @@ -963,23 +957,20 @@ pub const DeclGen = struct { |
| 963 | try self.genBody(inst.body); | 957 | try self.genBody(inst.body); |
| 964 | | 958 | |
| 965 | try writeInstruction(&self.code, .OpBranch, &[_]Word{ loop_label_id }); | 959 | try writeInstruction(&self.code, .OpBranch, &[_]Word{ loop_label_id }); |
| 966 | return null; | | |
| 967 | } | 960 | } |
| 968 | | 961 | |
| 969 | fn genRet(self: *DeclGen, inst: *Inst.UnOp) !?ResultId { | 962 | fn genRet(self: *DeclGen, inst: *Inst.UnOp) !void { |
| 970 | const operand_id = try self.resolve(inst.operand); | 963 | const operand_id = try self.resolve(inst.operand); |
| 971 | // TODO: This instruction needs to be the last in a block. Is that guaranteed? | 964 | // TODO: This instruction needs to be the last in a block. Is that guaranteed? |
| 972 | try writeInstruction(&self.code, .OpReturnValue, &[_]Word{operand_id}); | 965 | try writeInstruction(&self.code, .OpReturnValue, &[_]Word{operand_id}); |
| 973 | return null; | | |
| 974 | } | 966 | } |
| 975 | | 967 | |
| 976 | fn genRetVoid(self: *DeclGen) !?ResultId { | 968 | fn genRetVoid(self: *DeclGen) !void { |
| 977 | // TODO: This instruction needs to be the last in a block. Is that guaranteed? | 969 | // TODO: This instruction needs to be the last in a block. Is that guaranteed? |
| 978 | try writeInstruction(&self.code, .OpReturn, &[_]Word{}); | 970 | try writeInstruction(&self.code, .OpReturn, &[_]Word{}); |
| 979 | return null; | | |
| 980 | } | 971 | } |
| 981 | | 972 | |
| 982 | fn genStore(self: *DeclGen, inst: *Inst.BinOp) !?ResultId { | 973 | fn genStore(self: *DeclGen, inst: *Inst.BinOp) !void { |
| 983 | const dst_ptr_id = try self.resolve(inst.lhs); | 974 | const dst_ptr_id = try self.resolve(inst.lhs); |
| 984 | const src_val_id = try self.resolve(inst.rhs); | 975 | const src_val_id = try self.resolve(inst.rhs); |
| 985 | | 976 | |
| ... | @@ -989,12 +980,10 @@ pub const DeclGen = struct { | ... | @@ -989,12 +980,10 @@ pub const DeclGen = struct { |
| 989 | &[_]Word{ dst_ptr_id, src_val_id }; | 980 | &[_]Word{ dst_ptr_id, src_val_id }; |
| 990 | | 981 | |
| 991 | try writeInstruction(&self.code, .OpStore, operands); | 982 | try writeInstruction(&self.code, .OpStore, operands); |
| 992 | return null; | | |
| 993 | } | 983 | } |
| 994 | | 984 | |
| 995 | fn genUnreach(self: *DeclGen) !?ResultId { | 985 | fn genUnreach(self: *DeclGen) !void { |
| 996 | // TODO: This instruction needs to be the last in a block. Is that guaranteed? | 986 | // TODO: This instruction needs to be the last in a block. Is that guaranteed? |
| 997 | try writeInstruction(&self.code, .OpUnreachable, &[_]Word{}); | 987 | try writeInstruction(&self.code, .OpUnreachable, &[_]Word{}); |
| 998 | return null; | | |
| 999 | } | 988 | } |
| 1000 | }; | 989 | }; |