From 7c5980991aeba4d777385af3ac87cb7631777101 Mon Sep 17 00:00:00 2001 From: Ben Clayton Date: Wed, 13 Jan 2021 16:34:51 +0000 Subject: [PATCH] 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 Reviewed-by: dan sinclair Commit-Queue: Ben Clayton --- src/writer/hlsl/generator_impl.cc | 8 +++ .../hlsl/generator_impl_function_test.cc | 69 +++++++++++++++++++ src/writer/msl/generator_impl.cc | 8 +++ .../msl/generator_impl_function_test.cc | 69 +++++++++++++++++++ src/writer/msl/generator_impl_test.cc | 1 + 5 files changed, 155 insertions(+) diff --git a/src/writer/hlsl/generator_impl.cc b/src/writer/hlsl/generator_impl.cc index 4c6067b3d0..fe191abb28 100644 --- a/src/writer/hlsl/generator_impl.cc +++ b/src/writer/hlsl/generator_impl.cc @@ -1576,6 +1576,14 @@ bool GeneratorImpl::EmitEntryPointFunction(std::ostream& out, return false; } } + auto* last_statement = func->get_last_statement(); + if (last_statement == nullptr || + !last_statement->Is()) { + 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 49d453028a..af20ff1354 100644 --- a/src/writer/hlsl/generator_impl_function_test.cc +++ b/src/writer/hlsl/generator_impl_function_test.cc @@ -110,6 +110,74 @@ TEST_F(HlslGeneratorImplTest_Function, Emit_Function_WithParams) { )"); } +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::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(0), + }); + + auto* bar_var = Var("bar", ast::StorageClass::kOutput, ty.f32, nullptr, + ast::VariableDecorationList{ + create(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(Expr("bar"), Expr("foo")), + /* no explicit return */}, + ast::FunctionDecorationList{ + create(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, @@ -821,6 +889,7 @@ TEST_F(HlslGeneratorImplTest_Function, 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 a9509a88e8..fa072e9a2d 100644 --- a/src/writer/msl/generator_impl.cc +++ b/src/writer/msl/generator_impl.cc @@ -1515,6 +1515,14 @@ bool GeneratorImpl::EmitEntryPointFunction(ast::Function* func) { return false; } } + auto* last_statement = func->get_last_statement(); + if (last_statement == nullptr || + !last_statement->Is()) { + 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 7ae20809f6..210d20216b 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_Function_WithParams) { )"); } +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::PipelineStage::kFragment)}); + + mod->AddFunction(func); + + ASSERT_TRUE(td.Determine()) << td.error(); + + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_EQ(gen.result(), R"(#include + +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(0)}); + + auto* bar_var = + Var("bar", ast::StorageClass::kOutput, ty.f32, nullptr, + ast::VariableDecorationList{create(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(Expr("bar"), Expr("foo")), + /* no explicit return */}, + ast::FunctionDecorationList{ + create(ast::PipelineStage::kFragment)}); + + mod->AddFunction(func); + + ASSERT_TRUE(td.Determine()) << td.error(); + + ASSERT_TRUE(gen.Generate()) << gen.error(); + EXPECT_EQ(gen.result(), R"(#include + +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 @@ TEST_F(MslGeneratorImplTest, EXPECT_EQ(gen.result(), R"(#include 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 b5f4dd1196..978eba831e 100644 --- a/src/writer/msl/generator_impl_test.cc +++ b/src/writer/msl/generator_impl_test.cc @@ -59,6 +59,7 @@ TEST_F(MslGeneratorImplTest, Generate) { EXPECT_EQ(gen.result(), R"(#include kernel void my_func() { + return; } )");