Finish moving call validation from Validator to Resolver

Call validation was already implemented in Resolver. This change
completes it by deleting the relevant code in Validator, and moving and
updating the builtins validation test to use the Resolver.

Also added the "v-0004" error code for when detecting recursion, as was
done for the similar error in the Validator.

Bug: tint:642
Bug: tint:487

Change-Id: If7973bfd2d19681a0cbf48c6d427e17a3b927cde
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/45463
Commit-Queue: Antonio Maiorano <amaiorano@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
This commit is contained in:
Antonio Maiorano 2021-03-22 17:42:06 +00:00 committed by Commit Bot service account
parent 4682e3fc31
commit 06feb3f287
7 changed files with 124 additions and 330 deletions

View File

@ -466,6 +466,7 @@ if(${TINT_BUILD_TESTS})
intrinsic_table_test.cc
program_test.cc
resolver/assignment_validation_test.cc
resolver/builtins_validation_test.cc
resolver/decoration_validation_test.cc
resolver/function_validation_test.cc
resolver/host_shareable_validation_test.cc
@ -509,7 +510,6 @@ if(${TINT_BUILD_TESTS})
utils/tmpfile_test.cc
utils/tmpfile.h
utils/unique_vector_test.cc
validator/validator_builtins_test.cc
validator/validator_control_block_test.cc
validator/validator_decoration_test.cc
validator/validator_function_test.cc

View File

@ -12,111 +12,91 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include "src/validator/validator_test_helper.h"
#include "src/resolver/resolver_test_helper.h"
namespace tint {
namespace {
class ResolverBuiltinsValidationTest : public resolver::TestHelper,
public testing::Test {};
class ValidatorBuiltinsTest : public ValidatorTestHelper,
public testing::Test {};
TEST_F(ValidatorBuiltinsTest, Length_Float_Scalar) {
TEST_F(ResolverBuiltinsValidationTest, Length_Float_Scalar) {
auto* builtin = Call("length", 1.0f);
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_TRUE(v.ValidateCallExpr(builtin)) << v.error();
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ValidatorBuiltinsTest, Length_Float_Vec2) {
TEST_F(ResolverBuiltinsValidationTest, Length_Float_Vec2) {
auto* builtin = Call("length", vec2<float>(1.0f, 1.0f));
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_TRUE(v.ValidateCallExpr(builtin)) << v.error();
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ValidatorBuiltinsTest, Length_Float_Vec3) {
TEST_F(ResolverBuiltinsValidationTest, Length_Float_Vec3) {
auto* builtin = Call("length", vec3<float>(1.0f, 1.0f, 1.0f));
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_TRUE(v.ValidateCallExpr(builtin)) << v.error();
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ValidatorBuiltinsTest, Length_Float_Vec4) {
TEST_F(ResolverBuiltinsValidationTest, Length_Float_Vec4) {
auto* builtin = Call("length", vec4<float>(1.0f, 1.0f, 1.0f, 1.0f));
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_TRUE(v.ValidateCallExpr(builtin)) << v.error();
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ValidatorBuiltinsTest, Distance_Float_Scalar) {
TEST_F(ResolverBuiltinsValidationTest, Distance_Float_Scalar) {
auto* builtin = Call("distance", 1.0f, 1.0f);
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_TRUE(v.ValidateCallExpr(builtin)) << v.error();
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ValidatorBuiltinsTest, Distance_Float_Vec2) {
TEST_F(ResolverBuiltinsValidationTest, Distance_Float_Vec2) {
auto* builtin =
Call("distance", vec2<float>(1.0f, 1.0f), vec2<float>(1.0f, 1.0f));
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_TRUE(v.ValidateCallExpr(builtin)) << v.error();
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ValidatorBuiltinsTest, Distance_Float_Vec3) {
TEST_F(ResolverBuiltinsValidationTest, Distance_Float_Vec3) {
auto* builtin = Call("distance", vec3<float>(1.0f, 1.0f, 1.0f),
vec3<float>(1.0f, 1.0f, 1.0f));
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_TRUE(v.ValidateCallExpr(builtin)) << v.error();
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ValidatorBuiltinsTest, Distance_Float_Vec4) {
TEST_F(ResolverBuiltinsValidationTest, Distance_Float_Vec4) {
auto* builtin = Call("distance", vec4<float>(1.0f, 1.0f, 1.0f, 1.0f),
vec4<float>(1.0f, 1.0f, 1.0f, 1.0f));
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_TRUE(v.ValidateCallExpr(builtin)) << v.error();
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ValidatorBuiltinsTest, Determinant_Mat2x2) {
TEST_F(ResolverBuiltinsValidationTest, Determinant_Mat2x2) {
auto* builtin = Call("determinant", mat2x2<float>(vec2<float>(1.0f, 1.0f),
vec2<float>(1.0f, 1.0f)));
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_TRUE(v.ValidateCallExpr(builtin)) << v.error();
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ValidatorBuiltinsTest, Determinant_Mat3x3) {
TEST_F(ResolverBuiltinsValidationTest, Determinant_Mat3x3) {
auto* builtin =
Call("determinant", mat3x3<float>(vec3<float>(1.0f, 1.0f, 1.0f),
vec3<float>(1.0f, 1.0f, 1.0f),
vec3<float>(1.0f, 1.0f, 1.0f)));
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_TRUE(v.ValidateCallExpr(builtin)) << v.error();
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ValidatorBuiltinsTest, Determinant_Mat4x4) {
TEST_F(ResolverBuiltinsValidationTest, Determinant_Mat4x4) {
auto* builtin =
Call("determinant", mat4x4<float>(vec4<float>(1.0f, 1.0f, 1.0f, 1.0f),
vec4<float>(1.0f, 1.0f, 1.0f, 1.0f),
@ -124,251 +104,198 @@ TEST_F(ValidatorBuiltinsTest, Determinant_Mat4x4) {
vec4<float>(1.0f, 1.0f, 1.0f, 1.0f)));
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_TRUE(v.ValidateCallExpr(builtin)) << v.error();
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ValidatorBuiltinsTest, Frexp_Scalar) {
auto* a = Var("a", ty.i32(), ast::StorageClass::kWorkgroup);
RegisterVariable(a);
TEST_F(ResolverBuiltinsValidationTest, Frexp_Scalar) {
auto* a = Var("a", ty.i32(), ast::StorageClass::kFunction);
auto* builtin = Call("frexp", 1.0f, Expr("a"));
WrapInFunction(builtin);
ValidatorImpl& v = Build();
WrapInFunction(Decl(a), builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
EXPECT_TRUE(TypeOf(builtin)->Is<type::F32>());
EXPECT_TRUE(TypeOf(builtin->params()[1])->Is<type::Pointer>());
EXPECT_TRUE(v.ValidateCallExpr(builtin)) << v.error();
}
TEST_F(ValidatorBuiltinsTest, Frexp_Vec2) {
auto* a = Var("a", ty.vec2<int>(), ast::StorageClass::kWorkgroup);
TEST_F(ResolverBuiltinsValidationTest, Frexp_Vec2) {
auto* a = Var("a", ty.vec2<int>(), ast::StorageClass::kFunction);
auto* b = Const("b",
create<type::Pointer>(create<type::Vector>(ty.i32(), 2),
ast::StorageClass::kWorkgroup),
ast::StorageClass::kFunction),
Expr("a"), {});
RegisterVariable(a);
RegisterVariable(b);
auto* builtin = Call("frexp", vec2<float>(1.0f, 1.0f), Expr("b"));
WrapInFunction(builtin);
ValidatorImpl& v = Build();
WrapInFunction(Decl(a), Decl(b), builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
EXPECT_TRUE(TypeOf(builtin)->is_float_vector());
EXPECT_TRUE(TypeOf(builtin->params()[1])->Is<type::Pointer>());
EXPECT_TRUE(v.ValidateCallExpr(builtin)) << v.error();
}
TEST_F(ValidatorBuiltinsTest, Frexp_Vec3) {
auto* a = Var("a", ty.vec3<int>(), ast::StorageClass::kWorkgroup);
TEST_F(ResolverBuiltinsValidationTest, Frexp_Vec3) {
auto* a = Var("a", ty.vec3<int>(), ast::StorageClass::kFunction);
auto* b = Const("b",
create<type::Pointer>(create<type::Vector>(ty.i32(), 3),
ast::StorageClass::kWorkgroup),
ast::StorageClass::kFunction),
Expr("a"), {});
RegisterVariable(a);
RegisterVariable(b);
auto* builtin = Call("frexp", vec3<float>(1.0f, 1.0f, 1.0f), Expr("b"));
WrapInFunction(builtin);
ValidatorImpl& v = Build();
WrapInFunction(Decl(a), Decl(b), builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
EXPECT_TRUE(TypeOf(builtin)->is_float_vector());
EXPECT_TRUE(TypeOf(builtin->params()[1])->Is<type::Pointer>());
EXPECT_TRUE(v.ValidateCallExpr(builtin)) << v.error();
}
TEST_F(ValidatorBuiltinsTest, Frexp_Vec4) {
auto* a = Var("a", ty.vec4<int>(), ast::StorageClass::kWorkgroup);
TEST_F(ResolverBuiltinsValidationTest, Frexp_Vec4) {
auto* a = Var("a", ty.vec4<int>(), ast::StorageClass::kFunction);
auto* b = Const("b",
create<type::Pointer>(create<type::Vector>(ty.i32(), 4),
ast::StorageClass::kWorkgroup),
ast::StorageClass::kFunction),
Expr("a"), {});
RegisterVariable(a);
RegisterVariable(b);
auto* builtin = Call("frexp", vec4<float>(1.0f, 1.0f, 1.0f, 1.0f), Expr("b"));
WrapInFunction(builtin);
ValidatorImpl& v = Build();
WrapInFunction(Decl(a), Decl(b), builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
EXPECT_TRUE(TypeOf(builtin)->is_float_vector());
EXPECT_TRUE(TypeOf(builtin->params()[1])->Is<type::Pointer>());
EXPECT_TRUE(v.ValidateCallExpr(builtin)) << v.error();
}
TEST_F(ValidatorBuiltinsTest, Modf_Scalar) {
auto* a = Var("a", ty.f32(), ast::StorageClass::kWorkgroup);
auto* b = Const("b", ty.pointer<float>(ast::StorageClass::kWorkgroup),
TEST_F(ResolverBuiltinsValidationTest, Modf_Scalar) {
auto* a = Var("a", ty.f32(), ast::StorageClass::kFunction);
auto* b = Const("b", ty.pointer<float>(ast::StorageClass::kFunction),
Expr("a"), {});
RegisterVariable(a);
RegisterVariable(b);
auto* builtin = Call("modf", 1.0f, Expr("b"));
WrapInFunction(builtin);
ValidatorImpl& v = Build();
WrapInFunction(Decl(a), Decl(b), builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
EXPECT_TRUE(TypeOf(builtin)->Is<type::F32>());
EXPECT_TRUE(TypeOf(builtin->params()[1])->Is<type::Pointer>());
EXPECT_TRUE(v.ValidateCallExpr(builtin)) << v.error();
}
TEST_F(ValidatorBuiltinsTest, Modf_Vec2) {
auto* a = Var("a", ty.vec2<float>(), ast::StorageClass::kWorkgroup);
TEST_F(ResolverBuiltinsValidationTest, Modf_Vec2) {
auto* a = Var("a", ty.vec2<float>(), ast::StorageClass::kFunction);
auto* b = Const("b",
create<type::Pointer>(create<type::Vector>(ty.f32(), 2),
ast::StorageClass::kWorkgroup),
ast::StorageClass::kFunction),
Expr("a"), {});
RegisterVariable(a);
RegisterVariable(b);
auto* builtin = Call("modf", vec2<float>(1.0f, 1.0f), Expr("b"));
WrapInFunction(builtin);
ValidatorImpl& v = Build();
WrapInFunction(Decl(a), Decl(b), builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
EXPECT_TRUE(TypeOf(builtin)->is_float_vector());
EXPECT_TRUE(TypeOf(builtin->params()[1])->Is<type::Pointer>());
EXPECT_TRUE(v.ValidateCallExpr(builtin)) << v.error();
}
TEST_F(ValidatorBuiltinsTest, Modf_Vec3) {
auto* a = Var("a", ty.vec3<float>(), ast::StorageClass::kWorkgroup);
TEST_F(ResolverBuiltinsValidationTest, Modf_Vec3) {
auto* a = Var("a", ty.vec3<float>(), ast::StorageClass::kFunction);
auto* b = Const("b",
create<type::Pointer>(create<type::Vector>(ty.f32(), 3),
ast::StorageClass::kWorkgroup),
ast::StorageClass::kFunction),
Expr("a"), {});
RegisterVariable(a);
RegisterVariable(b);
auto* builtin = Call("modf", vec3<float>(1.0f, 1.0f, 1.0f), Expr("b"));
WrapInFunction(builtin);
ValidatorImpl& v = Build();
WrapInFunction(Decl(a), Decl(b), builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
EXPECT_TRUE(TypeOf(builtin)->is_float_vector());
EXPECT_TRUE(TypeOf(builtin->params()[1])->Is<type::Pointer>());
EXPECT_TRUE(v.ValidateCallExpr(builtin)) << v.error();
}
TEST_F(ValidatorBuiltinsTest, Modf_Vec4) {
auto* a = Var("a", ty.vec4<float>(), ast::StorageClass::kWorkgroup);
TEST_F(ResolverBuiltinsValidationTest, Modf_Vec4) {
auto* a = Var("a", ty.vec4<float>(), ast::StorageClass::kFunction);
auto* b = Const("b",
create<type::Pointer>(create<type::Vector>(ty.f32(), 4),
ast::StorageClass::kWorkgroup),
ast::StorageClass::kFunction),
Expr("a"), {});
RegisterVariable(a);
RegisterVariable(b);
auto* builtin = Call("modf", vec4<float>(1.0f, 1.0f, 1.0f, 1.0f), Expr("b"));
WrapInFunction(builtin);
ValidatorImpl& v = Build();
WrapInFunction(Decl(a), Decl(b), builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
EXPECT_TRUE(TypeOf(builtin)->is_float_vector());
EXPECT_TRUE(TypeOf(builtin->params()[1])->Is<type::Pointer>());
EXPECT_TRUE(v.ValidateCallExpr(builtin)) << v.error();
}
TEST_F(ValidatorBuiltinsTest, Cross_Float_Vec3) {
TEST_F(ResolverBuiltinsValidationTest, Cross_Float_Vec3) {
auto* builtin = Call("cross", vec3<float>(1.0f, 1.0f, 1.0f),
vec3<float>(1.0f, 1.0f, 1.0f));
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_TRUE(v.ValidateCallExpr(builtin)) << v.error();
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ValidatorBuiltinsTest, Dot_Float_Vec2) {
TEST_F(ResolverBuiltinsValidationTest, Dot_Float_Vec2) {
auto* builtin = Call("dot", vec2<float>(1.0f, 1.0f), vec2<float>(1.0f, 1.0f));
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_TRUE(v.ValidateCallExpr(builtin)) << v.error();
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ValidatorBuiltinsTest, Dot_Float_Vec3) {
TEST_F(ResolverBuiltinsValidationTest, Dot_Float_Vec3) {
auto* builtin =
Call("dot", vec3<float>(1.0f, 1.0f, 1.0f), vec3<float>(1.0f, 1.0f, 1.0f));
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_TRUE(v.ValidateCallExpr(builtin)) << v.error();
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ValidatorBuiltinsTest, Dot_Float_Vec4) {
TEST_F(ResolverBuiltinsValidationTest, Dot_Float_Vec4) {
auto* builtin = Call("dot", vec4<float>(1.0f, 1.0f, 1.0f, 1.0f),
vec4<float>(1.0f, 1.0f, 1.0f, 1.0f));
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_TRUE(v.ValidateCallExpr(builtin)) << v.error();
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ValidatorBuiltinsTest, Select_Float_Scalar) {
TEST_F(ResolverBuiltinsValidationTest, Select_Float_Scalar) {
auto* builtin = Call("select", Expr(1.0f), Expr(1.0f), Expr(true));
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_TRUE(v.ValidateCallExpr(builtin)) << v.error();
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ValidatorBuiltinsTest, Select_Integer_Scalar) {
TEST_F(ResolverBuiltinsValidationTest, Select_Integer_Scalar) {
auto* builtin = Call("select", Expr(1), Expr(1), Expr(true));
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_TRUE(v.ValidateCallExpr(builtin)) << v.error();
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ValidatorBuiltinsTest, Select_Boolean_Scalar) {
TEST_F(ResolverBuiltinsValidationTest, Select_Boolean_Scalar) {
auto* builtin = Call("select", Expr(true), Expr(true), Expr(true));
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_TRUE(v.ValidateCallExpr(builtin)) << v.error();
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ValidatorBuiltinsTest, Select_Float_Vec2) {
TEST_F(ResolverBuiltinsValidationTest, Select_Float_Vec2) {
auto* builtin = Call("select", vec2<float>(1.0f, 1.0f),
vec2<float>(1.0f, 1.0f), vec2<bool>(true, true));
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_TRUE(v.ValidateCallExpr(builtin)) << v.error();
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ValidatorBuiltinsTest, Select_Integer_Vec2) {
TEST_F(ResolverBuiltinsValidationTest, Select_Integer_Vec2) {
auto* builtin =
Call("select", vec2<int>(1, 1), vec2<int>(1, 1), vec2<bool>(true, true));
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_TRUE(v.ValidateCallExpr(builtin)) << v.error();
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ValidatorBuiltinsTest, Select_Boolean_Vec2) {
TEST_F(ResolverBuiltinsValidationTest, Select_Boolean_Vec2) {
auto* builtin = Call("select", vec2<bool>(true, true), vec2<bool>(true, true),
vec2<bool>(true, true));
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_TRUE(v.ValidateCallExpr(builtin)) << v.error();
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
template <typename T>
class ValidatorBuiltinsTestWithParams : public ValidatorTestHelper,
public testing::TestWithParam<T> {};
class ResolverBuiltinsValidationTestWithParams
: public resolver::TestHelper,
public testing::TestWithParam<T> {};
using FloatAllMatching =
ValidatorBuiltinsTestWithParams<std::tuple<std::string, uint32_t>>;
ResolverBuiltinsValidationTestWithParams<std::tuple<std::string, uint32_t>>;
TEST_P(FloatAllMatching, Scalar) {
std::string name = std::get<0>(GetParam());
@ -381,10 +308,8 @@ TEST_P(FloatAllMatching, Scalar) {
auto* builtin = Call(name, params);
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_TRUE(r()->Resolve()) << r()->error();
EXPECT_TRUE(TypeOf(builtin)->Is<type::F32>());
EXPECT_TRUE(v.ValidateCallExpr(builtin)) << v.error();
}
TEST_P(FloatAllMatching, Vec2) {
@ -398,10 +323,8 @@ TEST_P(FloatAllMatching, Vec2) {
auto* builtin = Call(name, params);
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_TRUE(r()->Resolve()) << r()->error();
EXPECT_TRUE(TypeOf(builtin)->is_float_vector());
EXPECT_TRUE(v.ValidateCallExpr(builtin)) << v.error();
}
TEST_P(FloatAllMatching, Vec3) {
@ -415,10 +338,8 @@ TEST_P(FloatAllMatching, Vec3) {
auto* builtin = Call(name, params);
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_TRUE(r()->Resolve()) << r()->error();
EXPECT_TRUE(TypeOf(builtin)->is_float_vector());
EXPECT_TRUE(v.ValidateCallExpr(builtin)) << v.error();
}
TEST_P(FloatAllMatching, Vec4) {
@ -432,13 +353,11 @@ TEST_P(FloatAllMatching, Vec4) {
auto* builtin = Call(name, params);
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_TRUE(r()->Resolve()) << r()->error();
EXPECT_TRUE(TypeOf(builtin)->is_float_vector());
EXPECT_TRUE(v.ValidateCallExpr(builtin)) << v.error();
}
INSTANTIATE_TEST_SUITE_P(ValidatorBuiltinsTest,
INSTANTIATE_TEST_SUITE_P(ResolverBuiltinsValidationTest,
FloatAllMatching,
::testing::Values(std::make_tuple("abs", 1),
std::make_tuple("acos", 1),
@ -484,7 +403,7 @@ INSTANTIATE_TEST_SUITE_P(ValidatorBuiltinsTest,
std::make_tuple("trunc", 1)));
using IntegerAllMatching =
ValidatorBuiltinsTestWithParams<std::tuple<std::string, uint32_t>>;
ResolverBuiltinsValidationTestWithParams<std::tuple<std::string, uint32_t>>;
TEST_P(IntegerAllMatching, ScalarUnsigned) {
std::string name = std::get<0>(GetParam());
@ -497,10 +416,8 @@ TEST_P(IntegerAllMatching, ScalarUnsigned) {
auto* builtin = Call(name, params);
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_TRUE(r()->Resolve()) << r()->error();
EXPECT_TRUE(TypeOf(builtin)->Is<type::U32>());
EXPECT_TRUE(v.ValidateCallExpr(builtin)) << v.error();
}
TEST_P(IntegerAllMatching, Vec2Unsigned) {
@ -514,10 +431,8 @@ TEST_P(IntegerAllMatching, Vec2Unsigned) {
auto* builtin = Call(name, params);
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_TRUE(r()->Resolve()) << r()->error();
EXPECT_TRUE(TypeOf(builtin)->is_unsigned_integer_vector());
EXPECT_TRUE(v.ValidateCallExpr(builtin)) << v.error();
}
TEST_P(IntegerAllMatching, Vec3Unsigned) {
@ -531,10 +446,8 @@ TEST_P(IntegerAllMatching, Vec3Unsigned) {
auto* builtin = Call(name, params);
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_TRUE(r()->Resolve()) << r()->error();
EXPECT_TRUE(TypeOf(builtin)->is_unsigned_integer_vector());
EXPECT_TRUE(v.ValidateCallExpr(builtin)) << v.error();
}
TEST_P(IntegerAllMatching, Vec4Unsigned) {
@ -548,10 +461,8 @@ TEST_P(IntegerAllMatching, Vec4Unsigned) {
auto* builtin = Call(name, params);
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_TRUE(r()->Resolve()) << r()->error();
EXPECT_TRUE(TypeOf(builtin)->is_unsigned_integer_vector());
EXPECT_TRUE(v.ValidateCallExpr(builtin)) << v.error();
}
TEST_P(IntegerAllMatching, ScalarSigned) {
@ -565,10 +476,8 @@ TEST_P(IntegerAllMatching, ScalarSigned) {
auto* builtin = Call(name, params);
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_TRUE(r()->Resolve()) << r()->error();
EXPECT_TRUE(TypeOf(builtin)->Is<type::I32>());
EXPECT_TRUE(v.ValidateCallExpr(builtin)) << v.error();
}
TEST_P(IntegerAllMatching, Vec2Signed) {
@ -582,10 +491,8 @@ TEST_P(IntegerAllMatching, Vec2Signed) {
auto* builtin = Call(name, params);
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_TRUE(r()->Resolve()) << r()->error();
EXPECT_TRUE(TypeOf(builtin)->is_signed_integer_vector());
EXPECT_TRUE(v.ValidateCallExpr(builtin)) << v.error();
}
TEST_P(IntegerAllMatching, Vec3Signed) {
@ -599,10 +506,8 @@ TEST_P(IntegerAllMatching, Vec3Signed) {
auto* builtin = Call(name, params);
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_TRUE(r()->Resolve()) << r()->error();
EXPECT_TRUE(TypeOf(builtin)->is_signed_integer_vector());
EXPECT_TRUE(v.ValidateCallExpr(builtin)) << v.error();
}
TEST_P(IntegerAllMatching, Vec4Signed) {
@ -616,13 +521,11 @@ TEST_P(IntegerAllMatching, Vec4Signed) {
auto* builtin = Call(name, params);
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_TRUE(r()->Resolve()) << r()->error();
EXPECT_TRUE(TypeOf(builtin)->is_signed_integer_vector());
EXPECT_TRUE(v.ValidateCallExpr(builtin)) << v.error();
}
INSTANTIATE_TEST_SUITE_P(ValidatorBuiltinsTest,
INSTANTIATE_TEST_SUITE_P(ResolverBuiltinsValidationTest,
IntegerAllMatching,
::testing::Values(std::make_tuple("abs", 1),
std::make_tuple("clamp", 3),
@ -632,7 +535,7 @@ INSTANTIATE_TEST_SUITE_P(ValidatorBuiltinsTest,
std::make_tuple("reverseBits", 1)));
using BooleanVectorInput =
ValidatorBuiltinsTestWithParams<std::tuple<std::string, uint32_t>>;
ResolverBuiltinsValidationTestWithParams<std::tuple<std::string, uint32_t>>;
TEST_P(BooleanVectorInput, Vec2) {
std::string name = std::get<0>(GetParam());
@ -645,9 +548,7 @@ TEST_P(BooleanVectorInput, Vec2) {
auto* builtin = Call(name, params);
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_TRUE(v.ValidateCallExpr(builtin)) << v.error();
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_P(BooleanVectorInput, Vec3) {
@ -661,9 +562,7 @@ TEST_P(BooleanVectorInput, Vec3) {
auto* builtin = Call(name, params);
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_TRUE(v.ValidateCallExpr(builtin)) << v.error();
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_P(BooleanVectorInput, Vec4) {
@ -677,44 +576,41 @@ TEST_P(BooleanVectorInput, Vec4) {
auto* builtin = Call(name, params);
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_TRUE(v.ValidateCallExpr(builtin)) << v.error();
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
INSTANTIATE_TEST_SUITE_P(ValidatorBuiltinsTest,
INSTANTIATE_TEST_SUITE_P(ResolverBuiltinsValidationTest,
BooleanVectorInput,
::testing::Values(std::make_tuple("all", 1),
std::make_tuple("any", 1)));
using DataPacking4x8 = ValidatorBuiltinsTestWithParams<std::string>;
using DataPacking4x8 = ResolverBuiltinsValidationTestWithParams<std::string>;
TEST_P(DataPacking4x8, Float_Vec4) {
auto name = GetParam();
auto* builtin = Call(name, vec4<float>(1.0f, 1.0f, 1.0f, 1.0f));
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_TRUE(v.ValidateCallExpr(builtin)) << v.error();
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
INSTANTIATE_TEST_SUITE_P(ValidatorBuiltinsTest,
INSTANTIATE_TEST_SUITE_P(ResolverBuiltinsValidationTest,
DataPacking4x8,
::testing::Values("pack4x8snorm", "pack4x8unorm"));
using DataPacking2x16 = ValidatorBuiltinsTestWithParams<std::string>;
using DataPacking2x16 = ResolverBuiltinsValidationTestWithParams<std::string>;
TEST_P(DataPacking2x16, Float_Vec2) {
auto name = GetParam();
auto* builtin = Call(name, vec2<float>(1.0f, 1.0f));
WrapInFunction(builtin);
ValidatorImpl& v = Build();
EXPECT_TRUE(v.ValidateCallExpr(builtin)) << v.error();
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
INSTANTIATE_TEST_SUITE_P(ValidatorBuiltinsTest,
INSTANTIATE_TEST_SUITE_P(ResolverBuiltinsValidationTest,
DataPacking2x16,
::testing::Values("pack2x16snorm",
"pack2x16unorm",
"pack2x16float"));
} // namespace
} // namespace tint

View File

@ -582,7 +582,8 @@ bool Resolver::Call(ast::CallExpression* call) {
auto callee_func_it = symbol_to_function_.find(ident->symbol());
if (callee_func_it == symbol_to_function_.end()) {
if (current_function_->declaration->symbol() == ident->symbol()) {
diagnostics_.add_error("recursion is not permitted. '" + name +
diagnostics_.add_error("v-0004",
"recursion is not permitted. '" + name +
"' attempted to call itself.",
call->source());
} else {
@ -637,39 +638,6 @@ bool Resolver::IntrinsicCall(ast::CallExpression* call,
if (!result.intrinsic) {
// Intrinsic lookup failed.
diagnostics_.add(result.diagnostics);
// TODO(bclayton): https://crbug.com/tint/487
// The Validator expects intrinsic signature mismatches to still produce
// type information. The rules for what the Validator expects are rather
// bespoke. Try to match what the Validator expects. As the Validator's
// checks on intrinsics is now almost entirely covered by the
// IntrinsicTable, we should remove the Validator checks on intrinsic
// signatures and remove these hacks.
semantic::ParameterList parameters;
parameters.reserve(arg_tys.size());
for (auto* arg : arg_tys) {
parameters.emplace_back(semantic::Parameter{arg});
}
type::Type* ret_ty = nullptr;
switch (intrinsic_type) {
case IntrinsicType::kCross:
ret_ty = builder_->ty.vec3<ProgramBuilder::f32>();
break;
case IntrinsicType::kDeterminant:
ret_ty = builder_->create<type::F32>();
break;
case IntrinsicType::kArrayLength:
ret_ty = builder_->create<type::U32>();
break;
default:
ret_ty = arg_tys.empty() ? builder_->ty.void_() : arg_tys[0];
break;
}
auto* intrinsic = builder_->create<semantic::Intrinsic>(intrinsic_type,
ret_ty, parameters);
builder_->Sem().Add(call, builder_->create<semantic::Call>(
call, intrinsic, current_statement_));
SetType(call, ret_ty);
return false;
}

View File

@ -127,7 +127,8 @@ TEST_F(ResolverValidationTest, Stmt_Call_recursive) {
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
"12:34 error: recursion is not permitted. 'main' attempted to call "
"12:34 error v-0004: recursion is not permitted. 'main' attempted "
"to call "
"itself.");
}

View File

@ -257,12 +257,7 @@ bool ValidatorImpl::ValidateStatement(const ast::Statement* stmt) {
return false;
}
if (auto* v = stmt->As<ast::VariableDeclStatement>()) {
bool constructor_valid =
v->variable()->has_constructor()
? ValidateExpression(v->variable()->constructor())
: true;
return constructor_valid && ValidateDeclStatement(v);
return ValidateDeclStatement(v);
}
if (auto* a = stmt->As<ast::AssignmentStatement>()) {
return ValidateAssign(a);
@ -270,9 +265,6 @@ bool ValidatorImpl::ValidateStatement(const ast::Statement* stmt) {
if (auto* r = stmt->As<ast::ReturnStatement>()) {
return ValidateReturnStatement(r);
}
if (auto* c = stmt->As<ast::CallStatement>()) {
return ValidateCallExpr(c->expr());
}
if (auto* s = stmt->As<ast::SwitchStatement>()) {
return ValidateSwitch(s);
}
@ -286,10 +278,6 @@ bool ValidatorImpl::ValidateStatement(const ast::Statement* stmt) {
}
bool ValidatorImpl::ValidateSwitch(const ast::SwitchStatement* s) {
if (!ValidateExpression(s->condition())) {
return false;
}
auto* cond_type = program_->Sem().Get(s->condition())->Type()->UnwrapAll();
if (!cond_type->is_integer_scalar()) {
add_error(s->condition()->source(), "v-0025",
@ -358,41 +346,6 @@ bool ValidatorImpl::ValidateCase(const ast::CaseStatement* c) {
return true;
}
bool ValidatorImpl::ValidateCallExpr(const ast::CallExpression* expr) {
if (!expr) {
// TODO(sarahM0): Here and other Validate.*: figure out whether return
// false or true
return false;
}
auto* call = program_->Sem().Get(expr);
if (call == nullptr) {
add_error(expr->source(), "CallExpression is missing semantic information");
return false;
}
auto* target = call->Target();
if (target->Is<semantic::Intrinsic>()) {
// TODO(bclayton): Add intrinsic validation checks here.
return true;
}
if (auto* func = target->As<semantic::Function>()) {
if (current_function_ == func->Declaration()) {
add_error(expr->source(), "v-0004",
"recursion is not allowed: '" +
program_->Symbols().NameFor(current_function_->symbol()) +
"'");
return false;
}
return true;
}
add_error(expr->source(), "Invalid function call expression");
return false;
}
bool ValidatorImpl::ValidateBadAssignmentToIdentifier(
const ast::AssignmentStatement* assign) {
auto* ident = assign->lhs()->As<ast::IdentifierExpression>();
@ -426,12 +379,7 @@ bool ValidatorImpl::ValidateAssign(const ast::AssignmentStatement* assign) {
}
auto* lhs = assign->lhs();
auto* rhs = assign->rhs();
if (!ValidateExpression(lhs)) {
return false;
}
if (!ValidateExpression(rhs)) {
return false;
}
// Pointers are not storable in WGSL, but the right-hand side must be
// storable. The raw right-hand side might be a pointer value which must be
// loaded (dereferenced) to provide the value to be stored.
@ -458,17 +406,6 @@ bool ValidatorImpl::ValidateAssign(const ast::AssignmentStatement* assign) {
return true;
}
bool ValidatorImpl::ValidateExpression(const ast::Expression* expr) {
if (!expr) {
return false;
}
if (auto* c = expr->As<ast::CallExpression>()) {
return ValidateCallExpr(c);
}
return true;
}
bool ValidatorImpl::IsStorable(type::Type* type) {
if (type == nullptr) {
return false;

View File

@ -94,10 +94,6 @@ class ValidatorImpl {
/// @returns true if the LHS of theassignment is not an identifier expression
bool ValidateBadAssignmentToIdentifier(
const ast::AssignmentStatement* assign);
/// Validates an expression
/// @param expr the expression to check
/// @return true if the expression is valid
bool ValidateExpression(const ast::Expression* expr);
/// Validates declaration name uniqueness
/// @param decl is the new declaration to be added
/// @returns true if no previous declaration with the `decl` 's name
@ -107,10 +103,6 @@ class ValidatorImpl {
/// @param ret the return statement to check
/// @returns true if function return type matches the return statement type
bool ValidateReturnStatement(const ast::ReturnStatement* ret);
/// Validates function calls
/// @param expr the call to validate
/// @returns true if successful
bool ValidateCallExpr(const ast::CallExpression* expr);
/// Validates switch statements
/// @param s the switch statement to check
/// @returns true if the valdiation was successful

View File

@ -169,6 +169,7 @@ source_set("tint_unittests_core_src") {
"../src/program_builder_test.cc",
"../src/program_test.cc",
"../src/resolver/assignment_validation_test.cc",
"../src/resolver/builtins_validation_test.cc",
"../src/resolver/decoration_validation_test.cc",
"../src/resolver/function_validation_test.cc",
"../src/resolver/host_shareable_validation_test.cc",
@ -217,7 +218,6 @@ source_set("tint_unittests_core_src") {
"../src/utils/tmpfile.h",
"../src/utils/tmpfile_test.cc",
"../src/utils/unique_vector_test.cc",
"../src/validator/validator_builtins_test.cc",
"../src/validator/validator_control_block_test.cc",
"../src/validator/validator_decoration_test.cc",
"../src/validator/validator_function_test.cc",