mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-08-06 12:15:43 +00:00
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>
This commit is contained in:
parent
1870a48d5f
commit
7c5980991a
@ -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>()) {
|
||||
ast::ReturnStatement ret(Source{});
|
||||
if (!EmitStatement(out, &ret)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
generating_entry_point_ = false;
|
||||
|
||||
decrement_indent();
|
||||
|
@ -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::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,
|
||||
@ -821,6 +889,7 @@ TEST_F(HlslGeneratorImplTest_Function,
|
||||
|
||||
ASSERT_TRUE(gen.Generate(out)) << gen.error();
|
||||
EXPECT_EQ(result(), R"(void GeometryShader_tint_0() {
|
||||
return;
|
||||
}
|
||||
|
||||
)");
|
||||
|
@ -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>()) {
|
||||
ast::ReturnStatement ret(Source{});
|
||||
if (!EmitStatement(&ret)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
generating_entry_point_ = false;
|
||||
|
||||
decrement_indent();
|
||||
|
@ -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::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 @@ TEST_F(MslGeneratorImplTest,
|
||||
EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
|
||||
|
||||
kernel void main_tint_0() {
|
||||
return;
|
||||
}
|
||||
|
||||
)");
|
||||
|
@ -59,6 +59,7 @@ TEST_F(MslGeneratorImplTest, Generate) {
|
||||
EXPECT_EQ(gen.result(), R"(#include <metal_stdlib>
|
||||
|
||||
kernel void my_func() {
|
||||
return;
|
||||
}
|
||||
|
||||
)");
|
||||
|
Loading…
x
Reference in New Issue
Block a user