[tint] Emit `unreachable` as `return` for non-void functions The `PreventInfiniteLoops` transforms changes the control flow such that some `unreachable` instructions become statically reachable. This may upset some downstream compilers that want to ensure that non-void functions always return. There are various places that unreachable instructions show up, so just always emit them as `return` statements in the textual backends instead of only handling this in the infinite loop transform. Fixed: 381541325 Change-Id: I92b5063361b179f0618e0f5130a29dfae98ea735 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/217894 Reviewed-by: Antonio Maiorano <amaiorano@google.com> Commit-Queue: James Price <jrprice@google.com>
diff --git a/src/tint/lang/glsl/writer/if_test.cc b/src/tint/lang/glsl/writer/if_test.cc index aeae183..08ff85a 100644 --- a/src/tint/lang/glsl/writer/if_test.cc +++ b/src/tint/lang/glsl/writer/if_test.cc
@@ -128,6 +128,32 @@ )"); } +TEST_F(GlslWriterTest, IfBothBranchesReturn_NonVoidFunction) { + auto* func = b.Function("foo", ty.u32()); + b.Append(func->Block(), [&] { + auto* if_ = b.If(true); + b.Append(if_->True(), [&] { b.Return(func, 0_u); }); + b.Append(if_->False(), [&] { b.Return(func, 1_u); }); + b.Unreachable(); + }); + + ASSERT_TRUE(Generate()) << err_ << output_.glsl; + EXPECT_EQ(output_.glsl, GlslHeader() + R"( +uint foo() { + if (true) { + return 0u; + } else { + return 1u; + } + /* unreachable */ + return 0u; +} +layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; +void main() { +} +)"); +} + TEST_F(GlslWriterTest, IfWithSinglePhi) { auto* func = b.Function("foo", ty.void_()); b.Append(func->Block(), [&] {
diff --git a/src/tint/lang/glsl/writer/printer/printer.cc b/src/tint/lang/glsl/writer/printer/printer.cc index 0477b23..19938ca 100644 --- a/src/tint/lang/glsl/writer/printer/printer.cc +++ b/src/tint/lang/glsl/writer/printer/printer.cc
@@ -1724,7 +1724,17 @@ } /// Emit an unreachable instruction - void EmitUnreachable() { Line() << "/* unreachable */"; } + void EmitUnreachable() { + Line() << "/* unreachable */"; + if (!current_function_->ReturnType()->Is<core::type::Void>()) { + // If this is inside a non-void function, emit a return statement to avoid potential + // errors due to missing return statements. + auto out = Line(); + out << "return "; + EmitZeroValue(out, current_function_->ReturnType()); + out << ";"; + } + } }; } // namespace
diff --git a/src/tint/lang/hlsl/writer/if_test.cc b/src/tint/lang/hlsl/writer/if_test.cc index 524a1c4..c45e6e6 100644 --- a/src/tint/lang/hlsl/writer/if_test.cc +++ b/src/tint/lang/hlsl/writer/if_test.cc
@@ -124,6 +124,34 @@ )"); } +TEST_F(HlslWriterTest, IfBothBranchesReturn_NonVoidFunction) { + auto* func = b.Function("foo", ty.u32()); + b.Append(func->Block(), [&] { + auto* if_ = b.If(true); + b.Append(if_->True(), [&] { b.Return(func, 0_u); }); + b.Append(if_->False(), [&] { b.Return(func, 1_u); }); + b.Unreachable(); + }); + + ASSERT_TRUE(Generate()) << err_ << output_.hlsl; + EXPECT_EQ(output_.hlsl, R"( +uint foo() { + if (true) { + return 0u; + } else { + return 1u; + } + /* unreachable */ + return 0u; +} + +[numthreads(1, 1, 1)] +void unused_entry_point() { +} + +)"); +} + TEST_F(HlslWriterTest, IfWithSinglePhi) { auto* func = b.ComputeFunction("foo"); b.Append(func->Block(), [&] {
diff --git a/src/tint/lang/hlsl/writer/printer/printer.cc b/src/tint/lang/hlsl/writer/printer/printer.cc index 80b9f98..2bffce7 100644 --- a/src/tint/lang/hlsl/writer/printer/printer.cc +++ b/src/tint/lang/hlsl/writer/printer/printer.cc
@@ -434,16 +434,13 @@ /// Emit an unreachable instruction void EmitUnreachable() { Line() << "/* unreachable */"; - if (current_block_ == current_function_->Block() && - !current_function_->ReturnType()->Is<core::type::Void>()) { - // If this is the end of a non-void function, emit a return statement to avoid DXC - // errors due to -Wreturn-type + -Werror (see crbug.com/378517038). - // TODO(381541325): Remove this once these reachable-unreachables are replaced. + if (!current_function_->ReturnType()->Is<core::type::Void>()) { + // If this is inside a non-void function, emit a return statement to avoid DXC errors + // due to -Wreturn-type + -Werror (see crbug.com/378517038). auto out = Line(); out << "return "; EmitZeroValue(out, current_function_->ReturnType()); out << ";"; - return; } }
diff --git a/src/tint/lang/msl/writer/if_test.cc b/src/tint/lang/msl/writer/if_test.cc index 8338165..a10591a 100644 --- a/src/tint/lang/msl/writer/if_test.cc +++ b/src/tint/lang/msl/writer/if_test.cc
@@ -116,6 +116,29 @@ )"); } +TEST_F(MslWriterTest, IfBothBranchesReturn_NonVoidFunction) { + auto* func = b.Function("foo", ty.u32()); + b.Append(func->Block(), [&] { + auto* if_ = b.If(true); + b.Append(if_->True(), [&] { b.Return(func, 0_u); }); + b.Append(if_->False(), [&] { b.Return(func, 1_u); }); + b.Unreachable(); + }); + + ASSERT_TRUE(Generate()) << err_ << output_.msl; + EXPECT_EQ(output_.msl, MetalHeader() + R"( +uint foo() { + if (true) { + return 0u; + } else { + return 1u; + } + /* unreachable */ + return 0u; +} +)"); +} + TEST_F(MslWriterTest, IfWithSinglePhi) { auto* func = b.Function("foo", ty.void_()); b.Append(func->Block(), [&] {
diff --git a/src/tint/lang/msl/writer/printer/printer.cc b/src/tint/lang/msl/writer/printer/printer.cc index f493452..ab1dd56 100644 --- a/src/tint/lang/msl/writer/printer/printer.cc +++ b/src/tint/lang/msl/writer/printer/printer.cc
@@ -795,7 +795,17 @@ } /// Emit an unreachable instruction - void EmitUnreachable() { Line() << "/* unreachable */"; } + void EmitUnreachable() { + Line() << "/* unreachable */"; + if (!current_function_->ReturnType()->Is<core::type::Void>()) { + // If this is inside a non-void function, emit a return statement to avoid potential + // errors due to missing return statements. + auto out = Line(); + out << "return "; + EmitZeroValue(out, current_function_->ReturnType()); + out << ";"; + } + } /// Emit a discard instruction void EmitDiscard() { Line() << "discard_fragment();"; }
diff --git a/test/tint/loops/loop.wgsl.expected.glsl b/test/tint/loops/loop.wgsl.expected.glsl index 01d1505..a729ae7 100644 --- a/test/tint/loops/loop.wgsl.expected.glsl +++ b/test/tint/loops/loop.wgsl.expected.glsl
@@ -22,6 +22,7 @@ } } /* unreachable */ + return 0; } layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; void main() {
diff --git a/test/tint/loops/loop.wgsl.expected.ir.msl b/test/tint/loops/loop.wgsl.expected.ir.msl index 8a55eb3..8abcec5 100644 --- a/test/tint/loops/loop.wgsl.expected.ir.msl +++ b/test/tint/loops/loop.wgsl.expected.ir.msl
@@ -23,4 +23,5 @@ } } /* unreachable */ + return 0; }
diff --git a/test/tint/loops/loop_robustness.wgsl.expected.glsl b/test/tint/loops/loop_robustness.wgsl.expected.glsl index 01d1505..a729ae7 100644 --- a/test/tint/loops/loop_robustness.wgsl.expected.glsl +++ b/test/tint/loops/loop_robustness.wgsl.expected.glsl
@@ -22,6 +22,7 @@ } } /* unreachable */ + return 0; } layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; void main() {
diff --git a/test/tint/loops/loop_robustness.wgsl.expected.ir.msl b/test/tint/loops/loop_robustness.wgsl.expected.ir.msl index 8a55eb3..8abcec5 100644 --- a/test/tint/loops/loop_robustness.wgsl.expected.ir.msl +++ b/test/tint/loops/loop_robustness.wgsl.expected.ir.msl
@@ -23,4 +23,5 @@ } } /* unreachable */ + return 0; }
diff --git a/test/tint/loops/loop_with_continuing.wgsl.expected.glsl b/test/tint/loops/loop_with_continuing.wgsl.expected.glsl index ba98f1c..cabda69 100644 --- a/test/tint/loops/loop_with_continuing.wgsl.expected.glsl +++ b/test/tint/loops/loop_with_continuing.wgsl.expected.glsl
@@ -22,6 +22,7 @@ } } /* unreachable */ + return 0; } layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; void main() {
diff --git a/test/tint/loops/loop_with_continuing.wgsl.expected.ir.msl b/test/tint/loops/loop_with_continuing.wgsl.expected.ir.msl index 9e61e13..653b197 100644 --- a/test/tint/loops/loop_with_continuing.wgsl.expected.ir.msl +++ b/test/tint/loops/loop_with_continuing.wgsl.expected.ir.msl
@@ -23,4 +23,5 @@ } } /* unreachable */ + return 0; }
diff --git a/test/tint/loops/loop_with_continuing_robustness.wgsl.expected.glsl b/test/tint/loops/loop_with_continuing_robustness.wgsl.expected.glsl index ba98f1c..cabda69 100644 --- a/test/tint/loops/loop_with_continuing_robustness.wgsl.expected.glsl +++ b/test/tint/loops/loop_with_continuing_robustness.wgsl.expected.glsl
@@ -22,6 +22,7 @@ } } /* unreachable */ + return 0; } layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; void main() {
diff --git a/test/tint/loops/loop_with_continuing_robustness.wgsl.expected.ir.msl b/test/tint/loops/loop_with_continuing_robustness.wgsl.expected.ir.msl index 9e61e13..653b197 100644 --- a/test/tint/loops/loop_with_continuing_robustness.wgsl.expected.ir.msl +++ b/test/tint/loops/loop_with_continuing_robustness.wgsl.expected.ir.msl
@@ -23,4 +23,5 @@ } } /* unreachable */ + return 0; }
diff --git a/test/tint/loops/nested_loops.wgsl.expected.glsl b/test/tint/loops/nested_loops.wgsl.expected.glsl index a28aa87..6780ab0 100644 --- a/test/tint/loops/nested_loops.wgsl.expected.glsl +++ b/test/tint/loops/nested_loops.wgsl.expected.glsl
@@ -33,9 +33,11 @@ } } /* unreachable */ + return 0; } } /* unreachable */ + return 0; } layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; void main() {
diff --git a/test/tint/loops/nested_loops.wgsl.expected.ir.dxc.hlsl b/test/tint/loops/nested_loops.wgsl.expected.ir.dxc.hlsl index 408d692..052ea2c 100644 --- a/test/tint/loops/nested_loops.wgsl.expected.ir.dxc.hlsl +++ b/test/tint/loops/nested_loops.wgsl.expected.ir.dxc.hlsl
@@ -32,6 +32,7 @@ } } /* unreachable */ + return int(0); } } /* unreachable */
diff --git a/test/tint/loops/nested_loops.wgsl.expected.ir.fxc.hlsl b/test/tint/loops/nested_loops.wgsl.expected.ir.fxc.hlsl index 408d692..052ea2c 100644 --- a/test/tint/loops/nested_loops.wgsl.expected.ir.fxc.hlsl +++ b/test/tint/loops/nested_loops.wgsl.expected.ir.fxc.hlsl
@@ -32,6 +32,7 @@ } } /* unreachable */ + return int(0); } } /* unreachable */
diff --git a/test/tint/loops/nested_loops.wgsl.expected.ir.msl b/test/tint/loops/nested_loops.wgsl.expected.ir.msl index 5041162..f1447d7 100644 --- a/test/tint/loops/nested_loops.wgsl.expected.ir.msl +++ b/test/tint/loops/nested_loops.wgsl.expected.ir.msl
@@ -34,7 +34,9 @@ } } /* unreachable */ + return 0; } } /* unreachable */ + return 0; }
diff --git a/test/tint/loops/nested_loops_robustness.wgsl.expected.glsl b/test/tint/loops/nested_loops_robustness.wgsl.expected.glsl index a28aa87..6780ab0 100644 --- a/test/tint/loops/nested_loops_robustness.wgsl.expected.glsl +++ b/test/tint/loops/nested_loops_robustness.wgsl.expected.glsl
@@ -33,9 +33,11 @@ } } /* unreachable */ + return 0; } } /* unreachable */ + return 0; } layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; void main() {
diff --git a/test/tint/loops/nested_loops_robustness.wgsl.expected.ir.dxc.hlsl b/test/tint/loops/nested_loops_robustness.wgsl.expected.ir.dxc.hlsl index 408d692..052ea2c 100644 --- a/test/tint/loops/nested_loops_robustness.wgsl.expected.ir.dxc.hlsl +++ b/test/tint/loops/nested_loops_robustness.wgsl.expected.ir.dxc.hlsl
@@ -32,6 +32,7 @@ } } /* unreachable */ + return int(0); } } /* unreachable */
diff --git a/test/tint/loops/nested_loops_robustness.wgsl.expected.ir.fxc.hlsl b/test/tint/loops/nested_loops_robustness.wgsl.expected.ir.fxc.hlsl index 408d692..052ea2c 100644 --- a/test/tint/loops/nested_loops_robustness.wgsl.expected.ir.fxc.hlsl +++ b/test/tint/loops/nested_loops_robustness.wgsl.expected.ir.fxc.hlsl
@@ -32,6 +32,7 @@ } } /* unreachable */ + return int(0); } } /* unreachable */
diff --git a/test/tint/loops/nested_loops_robustness.wgsl.expected.ir.msl b/test/tint/loops/nested_loops_robustness.wgsl.expected.ir.msl index 5041162..f1447d7 100644 --- a/test/tint/loops/nested_loops_robustness.wgsl.expected.ir.msl +++ b/test/tint/loops/nested_loops_robustness.wgsl.expected.ir.msl
@@ -34,7 +34,9 @@ } } /* unreachable */ + return 0; } } /* unreachable */ + return 0; }
diff --git a/test/tint/loops/nested_loops_with_continuing.wgsl.expected.glsl b/test/tint/loops/nested_loops_with_continuing.wgsl.expected.glsl index c94016d..9133f30 100644 --- a/test/tint/loops/nested_loops_with_continuing.wgsl.expected.glsl +++ b/test/tint/loops/nested_loops_with_continuing.wgsl.expected.glsl
@@ -32,9 +32,11 @@ } } /* unreachable */ + return 0; } } /* unreachable */ + return 0; } layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; void main() {
diff --git a/test/tint/loops/nested_loops_with_continuing.wgsl.expected.ir.dxc.hlsl b/test/tint/loops/nested_loops_with_continuing.wgsl.expected.ir.dxc.hlsl index 75b60e6..65a61dd 100644 --- a/test/tint/loops/nested_loops_with_continuing.wgsl.expected.ir.dxc.hlsl +++ b/test/tint/loops/nested_loops_with_continuing.wgsl.expected.ir.dxc.hlsl
@@ -31,6 +31,7 @@ } } /* unreachable */ + return int(0); } } /* unreachable */
diff --git a/test/tint/loops/nested_loops_with_continuing.wgsl.expected.ir.fxc.hlsl b/test/tint/loops/nested_loops_with_continuing.wgsl.expected.ir.fxc.hlsl index 75b60e6..65a61dd 100644 --- a/test/tint/loops/nested_loops_with_continuing.wgsl.expected.ir.fxc.hlsl +++ b/test/tint/loops/nested_loops_with_continuing.wgsl.expected.ir.fxc.hlsl
@@ -31,6 +31,7 @@ } } /* unreachable */ + return int(0); } } /* unreachable */
diff --git a/test/tint/loops/nested_loops_with_continuing.wgsl.expected.ir.msl b/test/tint/loops/nested_loops_with_continuing.wgsl.expected.ir.msl index 2b4726c..d0e6af1 100644 --- a/test/tint/loops/nested_loops_with_continuing.wgsl.expected.ir.msl +++ b/test/tint/loops/nested_loops_with_continuing.wgsl.expected.ir.msl
@@ -33,7 +33,9 @@ } } /* unreachable */ + return 0; } } /* unreachable */ + return 0; }
diff --git a/test/tint/loops/nested_loops_with_continuing_robustness.wgsl.expected.glsl b/test/tint/loops/nested_loops_with_continuing_robustness.wgsl.expected.glsl index c94016d..9133f30 100644 --- a/test/tint/loops/nested_loops_with_continuing_robustness.wgsl.expected.glsl +++ b/test/tint/loops/nested_loops_with_continuing_robustness.wgsl.expected.glsl
@@ -32,9 +32,11 @@ } } /* unreachable */ + return 0; } } /* unreachable */ + return 0; } layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in; void main() {
diff --git a/test/tint/loops/nested_loops_with_continuing_robustness.wgsl.expected.ir.dxc.hlsl b/test/tint/loops/nested_loops_with_continuing_robustness.wgsl.expected.ir.dxc.hlsl index 75b60e6..65a61dd 100644 --- a/test/tint/loops/nested_loops_with_continuing_robustness.wgsl.expected.ir.dxc.hlsl +++ b/test/tint/loops/nested_loops_with_continuing_robustness.wgsl.expected.ir.dxc.hlsl
@@ -31,6 +31,7 @@ } } /* unreachable */ + return int(0); } } /* unreachable */
diff --git a/test/tint/loops/nested_loops_with_continuing_robustness.wgsl.expected.ir.fxc.hlsl b/test/tint/loops/nested_loops_with_continuing_robustness.wgsl.expected.ir.fxc.hlsl index 75b60e6..65a61dd 100644 --- a/test/tint/loops/nested_loops_with_continuing_robustness.wgsl.expected.ir.fxc.hlsl +++ b/test/tint/loops/nested_loops_with_continuing_robustness.wgsl.expected.ir.fxc.hlsl
@@ -31,6 +31,7 @@ } } /* unreachable */ + return int(0); } } /* unreachable */
diff --git a/test/tint/loops/nested_loops_with_continuing_robustness.wgsl.expected.ir.msl b/test/tint/loops/nested_loops_with_continuing_robustness.wgsl.expected.ir.msl index 2b4726c..d0e6af1 100644 --- a/test/tint/loops/nested_loops_with_continuing_robustness.wgsl.expected.ir.msl +++ b/test/tint/loops/nested_loops_with_continuing_robustness.wgsl.expected.ir.msl
@@ -33,7 +33,9 @@ } } /* unreachable */ + return 0; } } /* unreachable */ + return 0; }