writer/[hlsl,msl]: Emit a implicit return for entrypoints
WGSL no longer requires a return statement at the end of each function, and the generated entrypoint functions are not valid without a return.
Fixed: tint:446
Change-Id: I702e4217f4ac41013e30927d532895c6835f6ca9
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/37704
Auto-Submit: Ben Clayton <bclayton@google.com>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
Commit-Queue: Ben Clayton <bclayton@google.com>
diff --git a/src/writer/hlsl/generator_impl.cc b/src/writer/hlsl/generator_impl.cc
index 4c6067b..fe191ab 100644
--- a/src/writer/hlsl/generator_impl.cc
+++ b/src/writer/hlsl/generator_impl.cc
@@ -1576,6 +1576,14 @@
return false;
}
}
+ auto* last_statement = func->get_last_statement();
+ if (last_statement == nullptr ||
+ !last_statement->Is<ast::ReturnStatement>()) {
+ ast::ReturnStatement ret(Source{});
+ if (!EmitStatement(out, &ret)) {
+ return false;
+ }
+ }
generating_entry_point_ = false;
decrement_indent();
diff --git a/src/writer/hlsl/generator_impl_function_test.cc b/src/writer/hlsl/generator_impl_function_test.cc
index 49d4530..af20ff1 100644
--- a/src/writer/hlsl/generator_impl_function_test.cc
+++ b/src/writer/hlsl/generator_impl_function_test.cc
@@ -111,6 +111,74 @@
}
TEST_F(HlslGeneratorImplTest_Function,
+ Emit_FunctionDecoration_EntryPoint_NoReturn_Void) {
+ auto* func =
+ Func("main", ast::VariableList{}, ty.void_,
+ ast::StatementList{/* no explicit return */},
+ ast::FunctionDecorationList{
+ create<ast::StageDecoration>(ast::PipelineStage::kFragment),
+ });
+
+ mod->AddFunction(func);
+
+ ASSERT_TRUE(td.Determine()) << td.error();
+ ASSERT_TRUE(gen.Generate(out)) << gen.error();
+ EXPECT_EQ(result(), R"(void main() {
+ return;
+}
+
+)");
+}
+
+TEST_F(HlslGeneratorImplTest_Function,
+ Emit_FunctionDecoration_EntryPoint_NoReturn_InOut) {
+ auto* foo_var = Var("foo", ast::StorageClass::kInput, ty.f32, nullptr,
+ ast::VariableDecorationList{
+ create<ast::LocationDecoration>(0),
+ });
+
+ auto* bar_var = Var("bar", ast::StorageClass::kOutput, ty.f32, nullptr,
+ ast::VariableDecorationList{
+ create<ast::LocationDecoration>(1),
+ });
+
+ td.RegisterVariableForTesting(foo_var);
+ td.RegisterVariableForTesting(bar_var);
+
+ mod->AddGlobalVariable(foo_var);
+ mod->AddGlobalVariable(bar_var);
+
+ auto* func =
+ Func("main", ast::VariableList{}, ty.void_,
+ ast::StatementList{
+ create<ast::AssignmentStatement>(Expr("bar"), Expr("foo")),
+ /* no explicit return */},
+ ast::FunctionDecorationList{
+ create<ast::StageDecoration>(ast::PipelineStage::kFragment),
+ });
+
+ mod->AddFunction(func);
+
+ ASSERT_TRUE(td.Determine()) << td.error();
+ ASSERT_TRUE(gen.Generate(out)) << gen.error();
+ EXPECT_EQ(result(), R"(struct main_in {
+ float foo : TEXCOORD0;
+};
+
+struct main_out {
+ float bar : SV_Target1;
+};
+
+main_out main(main_in tint_in) {
+ main_out tint_out;
+ tint_out.bar = tint_in.foo;
+ return tint_out;
+}
+
+)");
+}
+
+TEST_F(HlslGeneratorImplTest_Function,
Emit_FunctionDecoration_EntryPoint_WithInOutVars) {
auto* foo_var = Var("foo", ast::StorageClass::kInput, ty.f32, nullptr,
ast::VariableDecorationList{
@@ -821,6 +889,7 @@
ASSERT_TRUE(gen.Generate(out)) << gen.error();
EXPECT_EQ(result(), R"(void GeometryShader_tint_0() {
+ return;
}
)");
diff --git a/src/writer/msl/generator_impl.cc b/src/writer/msl/generator_impl.cc
index a9509a8..fa072e9 100644
--- a/src/writer/msl/generator_impl.cc
+++ b/src/writer/msl/generator_impl.cc
@@ -1515,6 +1515,14 @@
return false;
}
}
+ auto* last_statement = func->get_last_statement();
+ if (last_statement == nullptr ||
+ !last_statement->Is<ast::ReturnStatement>()) {
+ ast::ReturnStatement ret(Source{});
+ if (!EmitStatement(&ret)) {
+ return false;
+ }
+ }
generating_entry_point_ = false;
decrement_indent();
diff --git a/src/writer/msl/generator_impl_function_test.cc b/src/writer/msl/generator_impl_function_test.cc
index 7ae2080..210d202 100644
--- a/src/writer/msl/generator_impl_function_test.cc
+++ b/src/writer/msl/generator_impl_function_test.cc
@@ -119,6 +119,74 @@
)");
}
+TEST_F(MslGeneratorImplTest, Emit_FunctionDecoration_EntryPoint_NoReturn_Void) {
+ auto* func = Func("main", ast::VariableList{}, ty.void_,
+ ast::StatementList{/* no explicit return */},
+ ast::FunctionDecorationList{create<ast::StageDecoration>(
+ ast::PipelineStage::kFragment)});
+
+ mod->AddFunction(func);
+
+ ASSERT_TRUE(td.Determine()) << td.error();
+
+ ASSERT_TRUE(gen.Generate()) << gen.error();
+ EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+
+fragment void main_tint_0() {
+ return;
+}
+
+)");
+}
+
+TEST_F(MslGeneratorImplTest,
+ Emit_FunctionDecoration_EntryPoint_NoReturn_InOut) {
+ auto* foo_var =
+ Var("foo", ast::StorageClass::kInput, ty.f32, nullptr,
+ ast::VariableDecorationList{create<ast::LocationDecoration>(0)});
+
+ auto* bar_var =
+ Var("bar", ast::StorageClass::kOutput, ty.f32, nullptr,
+ ast::VariableDecorationList{create<ast::LocationDecoration>(1)});
+
+ td.RegisterVariableForTesting(foo_var);
+ td.RegisterVariableForTesting(bar_var);
+
+ mod->AddGlobalVariable(foo_var);
+ mod->AddGlobalVariable(bar_var);
+
+ auto* func =
+ Func("main", ast::VariableList{}, ty.void_,
+ ast::StatementList{
+ create<ast::AssignmentStatement>(Expr("bar"), Expr("foo")),
+ /* no explicit return */},
+ ast::FunctionDecorationList{
+ create<ast::StageDecoration>(ast::PipelineStage::kFragment)});
+
+ mod->AddFunction(func);
+
+ ASSERT_TRUE(td.Determine()) << td.error();
+
+ ASSERT_TRUE(gen.Generate()) << gen.error();
+ EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
+
+struct main_in {
+ float foo [[user(locn0)]];
+};
+
+struct main_out {
+ float bar [[color(1)]];
+};
+
+fragment main_out main_tint_0(main_in tint_in [[stage_in]]) {
+ main_out tint_out = {};
+ tint_out.bar = tint_in.foo;
+ return tint_out;
+}
+
+)");
+}
+
TEST_F(MslGeneratorImplTest, Emit_FunctionDecoration_EntryPoint_WithInOutVars) {
auto* foo_var =
Var("foo", ast::StorageClass::kInput, ty.f32, nullptr,
@@ -811,6 +879,7 @@
EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
kernel void main_tint_0() {
+ return;
}
)");
diff --git a/src/writer/msl/generator_impl_test.cc b/src/writer/msl/generator_impl_test.cc
index b5f4dd1..978eba8 100644
--- a/src/writer/msl/generator_impl_test.cc
+++ b/src/writer/msl/generator_impl_test.cc
@@ -59,6 +59,7 @@
EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
kernel void my_func() {
+ return;
}
)");