authorgravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2021-05-21 02:59:12+02:00
committergravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2021-05-22 16:11:56+02:00
logcba97e47730ff42df1da23e7019350a2d9e1a312
treef49c6b9b6815cc34359d46b8d6d1768437966e7c
parent228f71fa0ce25a5c473496dd2b947ae05ab9bed8

SPIR-V: Make functions which always return a null result return void instead


2 files changed, 26 insertions(+), 38 deletions(-)

src/codegen/spirv.zig+26-37
...@@ -643,14 +643,12 @@ pub const DeclGen = struct {...@@ -643,14 +643,12 @@ pub const DeclGen = struct {
643643
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 }
651649
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 them673 // 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 }
690690
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 }
878878
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).?;
882882
...@@ -891,19 +891,16 @@ pub const DeclGen = struct {...@@ -891,19 +891,16 @@ pub const DeclGen = struct {
891 }891 }
892892
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 }
897895
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 }
905902
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);
909906
...@@ -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 }
930925
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 }
936930
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 }
952946
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();
956950
...@@ -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);
964958
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 }
968961
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 }
975967
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 }
981972
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);
985976
...@@ -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 };
990981
991 try writeInstruction(&self.code, .OpStore, operands);982 try writeInstruction(&self.code, .OpStore, operands);
992 return null;
993 }983 }
994984
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};
src/link/SpirV.zig-1
...@@ -146,7 +146,6 @@ pub fn flushModule(self: *SpirV, comp: *Compilation) !void {...@@ -146,7 +146,6 @@ pub fn flushModule(self: *SpirV, comp: *Compilation) !void {
146 if (!decl.has_tv) continue;146 if (!decl.has_tv) continue;
147147
148 decl.fn_link.spirv.id = spv.allocResultId();148 decl.fn_link.spirv.id = spv.allocResultId();
149 log.debug("Allocating id {} to '{s}'", .{ decl.fn_link.spirv.id, std.mem.spanZ(decl.name) });
150 }149 }
151 }150 }
152151