[tint][ir][val] Handle names for builtins without checkers
In `CheckFunctionReturnAttributesAndType` the name of the builtin is
included in the error message, which is normally fetched from the
associated `BuiltinChecker`.
For some builtins there is no checker defined, since the logic
required to validate it is more complex than what that framework
allows, which causes an ICE.
These builtins need to be handled as special cases, as-is done when
validating builtins in general.
Fixes: 414728882
Change-Id: Icd6794d7a4d415014ff311b6b496827352414a00
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/239874
Commit-Queue: Ryan Harrison <rharrison@chromium.org>
Auto-Submit: Ryan Harrison <rharrison@chromium.org>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
diff --git a/src/tint/lang/core/ir/validator.cc b/src/tint/lang/core/ir/validator.cc
index 024d3bc..3c8fcc1 100644
--- a/src/tint/lang/core/ir/validator.cc
+++ b/src/tint/lang/core/ir/validator.cc
@@ -982,8 +982,22 @@
void CheckFunctionReturnAttributesAndType(const Function* func, IMPL&& impl) {
if (func->ReturnType()->Is<core::type::Struct>() &&
func->ReturnAttributes().builtin.has_value()) {
- const auto& checker = BuiltinCheckerFor(func->ReturnAttributes().builtin.value());
- AddError(func) << checker.name << " cannot be attached to a structure";
+ const char* name;
+ switch (func->ReturnAttributes().builtin.value()) {
+ case BuiltinValue::kPosition:
+ name = "position";
+ break;
+ case BuiltinValue::kSampleMask:
+ name = "sample_mask";
+ break;
+ case BuiltinValue::kClipDistances:
+ name = "clip_distances";
+ break;
+ default:
+ name = BuiltinCheckerFor(func->ReturnAttributes().builtin.value()).name;
+ break;
+ }
+ AddError(func) << name << " cannot be attached to a structure";
}
CheckIOAttributesAndType(func, func->ReturnAttributes(), func->ReturnType(),
diff --git a/src/tint/lang/core/ir/validator_builtin_test.cc b/src/tint/lang/core/ir/validator_builtin_test.cc
index 16ea743..e55705e 100644
--- a/src/tint/lang/core/ir/validator_builtin_test.cc
+++ b/src/tint/lang/core/ir/validator_builtin_test.cc
@@ -60,9 +60,8 @@
)")) << res.Failure();
}
-TEST_F(IR_ValidatorTest, Builtin_OnStructReturn) {
+TEST_F(IR_ValidatorTest, Builtin_OnStructReturn_BuiltinChecker) {
auto* f = FragmentEntryPoint();
-
auto* str_ty = ty.Struct(mod.symbols.New("OutputStruct"), {
{mod.symbols.New(""), ty.i32()},
});
@@ -83,6 +82,74 @@
)")) << res.Failure();
}
+TEST_F(IR_ValidatorTest, Builtin_OnStructReturn_Position) {
+ auto* f = VertexEntryPoint();
+ auto* str_ty =
+ ty.Struct(mod.symbols.New("OutputStruct"), {
+ {mod.symbols.New(""), ty.array(ty.f32(), 4)},
+ });
+ f->SetReturnType(str_ty);
+
+ IOAttributes attr;
+ attr.builtin = BuiltinValue::kPosition;
+ f->SetReturnAttributes(attr);
+
+ b.Append(f->Block(), [&] { b.Unreachable(); });
+
+ auto res = ir::Validate(mod);
+ ASSERT_NE(res, Success);
+ EXPECT_THAT(res.Failure().reason,
+ testing::HasSubstr(R"(:5:1 error: position cannot be attached to a structure
+%f = @vertex func():OutputStruct [@position] {
+^^
+)")) << res.Failure();
+}
+
+TEST_F(IR_ValidatorTest, Builtin_OnStructReturn_SampleMask) {
+ auto* f = FragmentEntryPoint();
+ auto* str_ty = ty.Struct(mod.symbols.New("OutputStruct"), {
+ {mod.symbols.New(""), ty.u32()},
+ });
+ f->SetReturnType(str_ty);
+
+ IOAttributes attr;
+ attr.builtin = BuiltinValue::kSampleMask;
+ f->SetReturnAttributes(attr);
+
+ b.Append(f->Block(), [&] { b.Unreachable(); });
+
+ auto res = ir::Validate(mod);
+ ASSERT_NE(res, Success);
+ EXPECT_THAT(res.Failure().reason,
+ testing::HasSubstr(R"(:5:1 error: sample_mask cannot be attached to a structure
+%f = @fragment func():OutputStruct [@sample_mask] {
+^^
+)")) << res.Failure();
+}
+
+TEST_F(IR_ValidatorTest, Builtin_OnStructReturn_ClipDistances) {
+ auto* f = VertexEntryPoint();
+ auto* str_ty =
+ ty.Struct(mod.symbols.New("OutputStruct"), {
+ {mod.symbols.New(""), ty.array(ty.f32(), 2)},
+ });
+ f->SetReturnType(str_ty);
+
+ IOAttributes attr;
+ attr.builtin = BuiltinValue::kClipDistances;
+ f->SetReturnAttributes(attr);
+
+ b.Append(f->Block(), [&] { b.Unreachable(); });
+
+ auto res = ir::Validate(mod);
+ ASSERT_NE(res, Success);
+ EXPECT_THAT(res.Failure().reason,
+ testing::HasSubstr(R"(:5:1 error: clip_distances cannot be attached to a structure
+%f = @vertex func():OutputStruct [@clip_distances] {
+^^
+)")) << res.Failure();
+}
+
TEST_F(IR_ValidatorTest, Builtin_PointSize_WrongIODirection) {
auto* f = VertexEntryPoint();
AddBuiltinParam(f, "size", BuiltinValue::kPointSize, ty.f32());