[validation] Update entry points validation v-0020
Remove irrelevant unit tests
Add/Update ValdiateEntryPoints function
Update known failure file
Bug: tint:296
Change-Id: I7d5c9c96fcca29f3e0a4c0315eb8ce869160a3ea
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/32220
Reviewed-by: David Neto <dneto@google.com>
Commit-Queue: David Neto <dneto@google.com>
diff --git a/src/validator/validator_function_test.cc b/src/validator/validator_function_test.cc
index 15ec76a..5f60f85 100644
--- a/src/validator/validator_function_test.cc
+++ b/src/validator/validator_function_test.cc
@@ -316,65 +316,27 @@
"'vtx_func'");
}
-TEST_F(ValidateFunctionTest, PipelineStageNamePair_MustBeUnique_Fail) {
- // [[stage(vertex)]]
- // fn main() -> void { return ;}
- // [[stage(vertex)]]
- // fn main() -> void { return; }
- ast::type::VoidType void_type;
- ast::VariableList params;
- auto func = std::make_unique<ast::Function>(
- Source{Source::Location{5, 6}}, "main", std::move(params), &void_type);
- auto body = std::make_unique<ast::BlockStatement>();
- body->append(std::make_unique<ast::ReturnStatement>());
- func->set_body(std::move(body));
- func->add_decoration(std::make_unique<ast::StageDecoration>(
- ast::PipelineStage::kVertex, Source{}));
- mod()->AddFunction(std::move(func));
-
- func = std::make_unique<ast::Function>(Source{Source::Location{12, 34}},
- "main", std::move(params), &void_type);
- body = std::make_unique<ast::BlockStatement>();
- body->append(std::make_unique<ast::ReturnStatement>());
- func->set_body(std::move(body));
- func->add_decoration(std::make_unique<ast::StageDecoration>(
- ast::PipelineStage::kVertex, Source{}));
- mod()->AddFunction(std::move(func));
-
- EXPECT_TRUE(td()->Determine()) << td()->error();
- EXPECT_FALSE(v()->Validate(mod()));
- EXPECT_EQ(v()->error(),
- "12:34: v-0020: The pair of <entry point name, pipeline stage> "
- "must be unique");
-}
-
-TEST_F(ValidateFunctionTest, PipelineStageNamePair_MustBeUnique_Pass) {
- // [[stage(vertex)]]
- // fn main() -> void { return; }
+TEST_F(ValidateFunctionTest, PipelineStage_MustBeUnique_Fail) {
// [[stage(fragment)]]
+ // [[stage(vertex)]]
// fn main() -> void { return; }
ast::type::VoidType void_type;
ast::VariableList params;
auto func = std::make_unique<ast::Function>(
- Source{Source::Location{5, 6}}, "main", std::move(params), &void_type);
+ Source{Source::Location{12, 34}}, "main", std::move(params), &void_type);
auto body = std::make_unique<ast::BlockStatement>();
body->append(std::make_unique<ast::ReturnStatement>());
func->set_body(std::move(body));
func->add_decoration(std::make_unique<ast::StageDecoration>(
ast::PipelineStage::kVertex, Source{}));
- mod()->AddFunction(std::move(func));
-
- func = std::make_unique<ast::Function>(Source{Source::Location{12, 34}},
- "main", std::move(params), &void_type);
- body = std::make_unique<ast::BlockStatement>();
- body->append(std::make_unique<ast::ReturnStatement>());
- func->set_body(std::move(body));
func->add_decoration(std::make_unique<ast::StageDecoration>(
ast::PipelineStage::kFragment, Source{}));
mod()->AddFunction(std::move(func));
-
EXPECT_TRUE(td()->Determine()) << td()->error();
- EXPECT_TRUE(v()->Validate(mod())) << v()->error();
+ EXPECT_FALSE(v()->Validate(mod()));
+ EXPECT_EQ(
+ v()->error(),
+ "12:34: v-0020: only one stage decoration permitted per entry point");
}
TEST_F(ValidateFunctionTest, OnePipelineStageFunctionMustBePresent_Pass) {
diff --git a/src/validator/validator_impl.cc b/src/validator/validator_impl.cc
index 1f6c01e..92bbb58 100644
--- a/src/validator/validator_impl.cc
+++ b/src/validator/validator_impl.cc
@@ -51,7 +51,9 @@
if (!ValidateFunctions(module->functions())) {
return false;
}
-
+ if (!ValidateEntryPoint(module->functions())) {
+ return false;
+ }
function_stack_.pop_scope();
return true;
@@ -82,49 +84,13 @@
}
bool ValidatorImpl::ValidateFunctions(const ast::FunctionList& funcs) {
- ScopeStack<ast::PipelineStage> entry_point_map;
- entry_point_map.push_scope();
-
- size_t pipeline_count = 0;
for (const auto& func : funcs) {
- // The entry points will be checked later to see if their duplicated
- if (function_stack_.has(func->name()) &&
- !entry_point_map.has(func->name())) {
+ if (function_stack_.has(func->name())) {
set_error(func->source(),
"v-0016: function names must be unique '" + func->name() + "'");
return false;
}
- if (func->IsEntryPoint()) {
- pipeline_count++;
-
- if (!func->return_type()->IsVoid()) {
- set_error(func->source(),
- "v-0024: Entry point function must return void: '" +
- func->name() + "'");
- return false;
- }
-
- if (func->params().size() != 0) {
- set_error(func->source(),
- "v-0023: Entry point function must accept no parameters: '" +
- func->name() + "'");
- return false;
- }
-
- ast::PipelineStage pipeline_stage;
- if (entry_point_map.get(func->name(), &pipeline_stage)) {
- if (pipeline_stage == func->pipeline_stage()) {
- set_error(
- func->source(),
- "v-0020: The pair of <entry point name, pipeline stage> must "
- "be unique");
- return false;
- }
- }
- entry_point_map.set(func->name(), func->pipeline_stage());
- }
-
function_stack_.set(func->name(), func.get());
current_function_ = func.get();
if (!ValidateFunction(func.get())) {
@@ -133,13 +99,47 @@
current_function_ = nullptr;
}
- if (pipeline_count == 0) {
+ return true;
+}
+
+bool ValidatorImpl::ValidateEntryPoint(const ast::FunctionList& funcs) {
+ auto shader_is_present = false;
+ for (const auto& func : funcs) {
+ if (func->IsEntryPoint()) {
+ shader_is_present = true;
+ if (!func->params().empty()) {
+ set_error(func->source(),
+ "v-0023: Entry point function must accept no parameters: '" +
+ func->name() + "'");
+ return false;
+ }
+
+ if (!func->return_type()->IsVoid()) {
+ set_error(func->source(),
+ "v-0024: Entry point function must return void: '" +
+ func->name() + "'");
+ return false;
+ }
+ auto stage_deco_count = 0;
+ for (const auto& deco : func->decorations()) {
+ if (deco->IsStage()) {
+ stage_deco_count++;
+ }
+ }
+ if (stage_deco_count > 1) {
+ set_error(
+ func->source(),
+ "v-0020: only one stage decoration permitted per entry point");
+ return false;
+ }
+ }
+ }
+ if (!shader_is_present) {
set_error(Source{},
"v-0003: At least one of vertex, fragment or compute shader must "
"be present");
return false;
}
-
return true;
}
diff --git a/src/validator/validator_impl.h b/src/validator/validator_impl.h
index bfa1c9b..a406f53 100644
--- a/src/validator/validator_impl.h
+++ b/src/validator/validator_impl.h
@@ -113,6 +113,10 @@
/// @param c the case statement to check
/// @returns true if the valdiation was successful
bool ValidateCase(const ast::CaseStatement* c);
+ /// Validates entry points
+ /// @param funcs the functions to check
+ /// @returns true if the valdiation was successful
+ bool ValidateEntryPoint(const ast::FunctionList& funcs);
private:
std::string error_;
diff --git a/tools/known_tint_failures b/tools/known_tint_failures
index 13dbaaf..8cd01f1 100644
--- a/tools/known_tint_failures
+++ b/tools/known_tint_failures
@@ -1,6 +1,5 @@
break-outside-for-or-switch.fail.wgsl
continue-outside-for.fail.wgsl
-duplicate-entry-point.fail.wgsl
duplicate-stuct-name-v2.fail.wgsl
duplicate-stuct-name.fail.wgsl
duplicate-var-name-within-func.fail.wgsl