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

@@ -0,0 +1,616 @@
// Copyright 2021 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "src/resolver/resolver_test_helper.h"
namespace tint {
namespace {
class ResolverBuiltinsValidationTest : public resolver::TestHelper,
public testing::Test {};
TEST_F(ResolverBuiltinsValidationTest, Length_Float_Scalar) {
auto* builtin = Call("length", 1.0f);
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverBuiltinsValidationTest, Length_Float_Vec2) {
auto* builtin = Call("length", vec2<float>(1.0f, 1.0f));
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverBuiltinsValidationTest, Length_Float_Vec3) {
auto* builtin = Call("length", vec3<float>(1.0f, 1.0f, 1.0f));
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverBuiltinsValidationTest, Length_Float_Vec4) {
auto* builtin = Call("length", vec4<float>(1.0f, 1.0f, 1.0f, 1.0f));
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverBuiltinsValidationTest, Distance_Float_Scalar) {
auto* builtin = Call("distance", 1.0f, 1.0f);
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverBuiltinsValidationTest, Distance_Float_Vec2) {
auto* builtin =
Call("distance", vec2<float>(1.0f, 1.0f), vec2<float>(1.0f, 1.0f));
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
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);
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
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);
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
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);
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
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);
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
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),
vec4<float>(1.0f, 1.0f, 1.0f, 1.0f),
vec4<float>(1.0f, 1.0f, 1.0f, 1.0f)));
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverBuiltinsValidationTest, Frexp_Scalar) {
auto* a = Var("a", ty.i32(), ast::StorageClass::kFunction);
auto* builtin = Call("frexp", 1.0f, Expr("a"));
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>());
}
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::kFunction),
Expr("a"), {});
auto* builtin = Call("frexp", vec2<float>(1.0f, 1.0f), Expr("b"));
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>());
}
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::kFunction),
Expr("a"), {});
auto* builtin = Call("frexp", vec3<float>(1.0f, 1.0f, 1.0f), Expr("b"));
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>());
}
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::kFunction),
Expr("a"), {});
auto* builtin = Call("frexp", vec4<float>(1.0f, 1.0f, 1.0f, 1.0f), Expr("b"));
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>());
}
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"), {});
auto* builtin = Call("modf", 1.0f, Expr("b"));
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>());
}
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::kFunction),
Expr("a"), {});
auto* builtin = Call("modf", vec2<float>(1.0f, 1.0f), Expr("b"));
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>());
}
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::kFunction),
Expr("a"), {});
auto* builtin = Call("modf", vec3<float>(1.0f, 1.0f, 1.0f), Expr("b"));
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>());
}
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::kFunction),
Expr("a"), {});
auto* builtin = Call("modf", vec4<float>(1.0f, 1.0f, 1.0f, 1.0f), Expr("b"));
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>());
}
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);
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverBuiltinsValidationTest, Dot_Float_Vec2) {
auto* builtin = Call("dot", vec2<float>(1.0f, 1.0f), vec2<float>(1.0f, 1.0f));
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
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);
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
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);
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverBuiltinsValidationTest, Select_Float_Scalar) {
auto* builtin = Call("select", Expr(1.0f), Expr(1.0f), Expr(true));
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverBuiltinsValidationTest, Select_Integer_Scalar) {
auto* builtin = Call("select", Expr(1), Expr(1), Expr(true));
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverBuiltinsValidationTest, Select_Boolean_Scalar) {
auto* builtin = Call("select", Expr(true), Expr(true), Expr(true));
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
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);
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverBuiltinsValidationTest, Select_Integer_Vec2) {
auto* builtin =
Call("select", vec2<int>(1, 1), vec2<int>(1, 1), vec2<bool>(true, true));
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(ResolverBuiltinsValidationTest, Select_Boolean_Vec2) {
auto* builtin = Call("select", vec2<bool>(true, true), vec2<bool>(true, true),
vec2<bool>(true, true));
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
template <typename T>
class ResolverBuiltinsValidationTestWithParams
: public resolver::TestHelper,
public testing::TestWithParam<T> {};
using FloatAllMatching =
ResolverBuiltinsValidationTestWithParams<std::tuple<std::string, uint32_t>>;
TEST_P(FloatAllMatching, Scalar) {
std::string name = std::get<0>(GetParam());
uint32_t num_params = std::get<1>(GetParam());
ast::ExpressionList params;
for (uint32_t i = 0; i < num_params; ++i) {
params.push_back(Expr(1.0f));
}
auto* builtin = Call(name, params);
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
EXPECT_TRUE(TypeOf(builtin)->Is<type::F32>());
}
TEST_P(FloatAllMatching, Vec2) {
std::string name = std::get<0>(GetParam());
uint32_t num_params = std::get<1>(GetParam());
ast::ExpressionList params;
for (uint32_t i = 0; i < num_params; ++i) {
params.push_back(vec2<float>(1.0f, 1.0f));
}
auto* builtin = Call(name, params);
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
EXPECT_TRUE(TypeOf(builtin)->is_float_vector());
}
TEST_P(FloatAllMatching, Vec3) {
std::string name = std::get<0>(GetParam());
uint32_t num_params = std::get<1>(GetParam());
ast::ExpressionList params;
for (uint32_t i = 0; i < num_params; ++i) {
params.push_back(vec3<float>(1.0f, 1.0f, 1.0f));
}
auto* builtin = Call(name, params);
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
EXPECT_TRUE(TypeOf(builtin)->is_float_vector());
}
TEST_P(FloatAllMatching, Vec4) {
std::string name = std::get<0>(GetParam());
uint32_t num_params = std::get<1>(GetParam());
ast::ExpressionList params;
for (uint32_t i = 0; i < num_params; ++i) {
params.push_back(vec4<float>(1.0f, 1.0f, 1.0f, 1.0f));
}
auto* builtin = Call(name, params);
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
EXPECT_TRUE(TypeOf(builtin)->is_float_vector());
}
INSTANTIATE_TEST_SUITE_P(ResolverBuiltinsValidationTest,
FloatAllMatching,
::testing::Values(std::make_tuple("abs", 1),
std::make_tuple("acos", 1),
std::make_tuple("asin", 1),
std::make_tuple("atan", 1),
std::make_tuple("atan2", 2),
std::make_tuple("ceil", 1),
std::make_tuple("clamp", 3),
std::make_tuple("cos", 1),
std::make_tuple("cosh", 1),
std::make_tuple("dpdx", 1),
std::make_tuple("dpdxCoarse", 1),
std::make_tuple("dpdxFine", 1),
std::make_tuple("dpdy", 1),
std::make_tuple("dpdyCoarse", 1),
std::make_tuple("dpdyFine", 1),
std::make_tuple("exp", 1),
std::make_tuple("exp2", 1),
std::make_tuple("faceForward", 3),
std::make_tuple("floor", 1),
std::make_tuple("fma", 3),
std::make_tuple("fract", 1),
std::make_tuple("fwidth", 1),
std::make_tuple("fwidthCoarse", 1),
std::make_tuple("fwidthFine", 1),
std::make_tuple("inverseSqrt", 1),
std::make_tuple("log", 1),
std::make_tuple("log2", 1),
std::make_tuple("max", 2),
std::make_tuple("min", 2),
std::make_tuple("mix", 3),
std::make_tuple("pow", 2),
std::make_tuple("reflect", 2),
std::make_tuple("round", 1),
std::make_tuple("sign", 1),
std::make_tuple("sin", 1),
std::make_tuple("sinh", 1),
std::make_tuple("smoothStep", 3),
std::make_tuple("sqrt", 1),
std::make_tuple("step", 2),
std::make_tuple("tan", 1),
std::make_tuple("tanh", 1),
std::make_tuple("trunc", 1)));
using IntegerAllMatching =
ResolverBuiltinsValidationTestWithParams<std::tuple<std::string, uint32_t>>;
TEST_P(IntegerAllMatching, ScalarUnsigned) {
std::string name = std::get<0>(GetParam());
uint32_t num_params = std::get<1>(GetParam());
ast::ExpressionList params;
for (uint32_t i = 0; i < num_params; ++i) {
params.push_back(Construct<uint32_t>(1));
}
auto* builtin = Call(name, params);
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
EXPECT_TRUE(TypeOf(builtin)->Is<type::U32>());
}
TEST_P(IntegerAllMatching, Vec2Unsigned) {
std::string name = std::get<0>(GetParam());
uint32_t num_params = std::get<1>(GetParam());
ast::ExpressionList params;
for (uint32_t i = 0; i < num_params; ++i) {
params.push_back(vec2<uint32_t>(1u, 1u));
}
auto* builtin = Call(name, params);
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
EXPECT_TRUE(TypeOf(builtin)->is_unsigned_integer_vector());
}
TEST_P(IntegerAllMatching, Vec3Unsigned) {
std::string name = std::get<0>(GetParam());
uint32_t num_params = std::get<1>(GetParam());
ast::ExpressionList params;
for (uint32_t i = 0; i < num_params; ++i) {
params.push_back(vec3<uint32_t>(1u, 1u, 1u));
}
auto* builtin = Call(name, params);
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
EXPECT_TRUE(TypeOf(builtin)->is_unsigned_integer_vector());
}
TEST_P(IntegerAllMatching, Vec4Unsigned) {
std::string name = std::get<0>(GetParam());
uint32_t num_params = std::get<1>(GetParam());
ast::ExpressionList params;
for (uint32_t i = 0; i < num_params; ++i) {
params.push_back(vec4<uint32_t>(1u, 1u, 1u, 1u));
}
auto* builtin = Call(name, params);
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
EXPECT_TRUE(TypeOf(builtin)->is_unsigned_integer_vector());
}
TEST_P(IntegerAllMatching, ScalarSigned) {
std::string name = std::get<0>(GetParam());
uint32_t num_params = std::get<1>(GetParam());
ast::ExpressionList params;
for (uint32_t i = 0; i < num_params; ++i) {
params.push_back(Construct<int32_t>(1));
}
auto* builtin = Call(name, params);
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
EXPECT_TRUE(TypeOf(builtin)->Is<type::I32>());
}
TEST_P(IntegerAllMatching, Vec2Signed) {
std::string name = std::get<0>(GetParam());
uint32_t num_params = std::get<1>(GetParam());
ast::ExpressionList params;
for (uint32_t i = 0; i < num_params; ++i) {
params.push_back(vec2<int32_t>(1, 1));
}
auto* builtin = Call(name, params);
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
EXPECT_TRUE(TypeOf(builtin)->is_signed_integer_vector());
}
TEST_P(IntegerAllMatching, Vec3Signed) {
std::string name = std::get<0>(GetParam());
uint32_t num_params = std::get<1>(GetParam());
ast::ExpressionList params;
for (uint32_t i = 0; i < num_params; ++i) {
params.push_back(vec3<int32_t>(1, 1, 1));
}
auto* builtin = Call(name, params);
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
EXPECT_TRUE(TypeOf(builtin)->is_signed_integer_vector());
}
TEST_P(IntegerAllMatching, Vec4Signed) {
std::string name = std::get<0>(GetParam());
uint32_t num_params = std::get<1>(GetParam());
ast::ExpressionList params;
for (uint32_t i = 0; i < num_params; ++i) {
params.push_back(vec4<int32_t>(1, 1, 1, 1));
}
auto* builtin = Call(name, params);
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
EXPECT_TRUE(TypeOf(builtin)->is_signed_integer_vector());
}
INSTANTIATE_TEST_SUITE_P(ResolverBuiltinsValidationTest,
IntegerAllMatching,
::testing::Values(std::make_tuple("abs", 1),
std::make_tuple("clamp", 3),
std::make_tuple("countOneBits", 1),
std::make_tuple("max", 2),
std::make_tuple("min", 2),
std::make_tuple("reverseBits", 1)));
using BooleanVectorInput =
ResolverBuiltinsValidationTestWithParams<std::tuple<std::string, uint32_t>>;
TEST_P(BooleanVectorInput, Vec2) {
std::string name = std::get<0>(GetParam());
uint32_t num_params = std::get<1>(GetParam());
ast::ExpressionList params;
for (uint32_t i = 0; i < num_params; ++i) {
params.push_back(vec2<bool>(true, true));
}
auto* builtin = Call(name, params);
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_P(BooleanVectorInput, Vec3) {
std::string name = std::get<0>(GetParam());
uint32_t num_params = std::get<1>(GetParam());
ast::ExpressionList params;
for (uint32_t i = 0; i < num_params; ++i) {
params.push_back(vec3<bool>(true, true, true));
}
auto* builtin = Call(name, params);
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_P(BooleanVectorInput, Vec4) {
std::string name = std::get<0>(GetParam());
uint32_t num_params = std::get<1>(GetParam());
ast::ExpressionList params;
for (uint32_t i = 0; i < num_params; ++i) {
params.push_back(vec4<bool>(true, true, true, true));
}
auto* builtin = Call(name, params);
WrapInFunction(builtin);
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
INSTANTIATE_TEST_SUITE_P(ResolverBuiltinsValidationTest,
BooleanVectorInput,
::testing::Values(std::make_tuple("all", 1),
std::make_tuple("any", 1)));
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);
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
INSTANTIATE_TEST_SUITE_P(ResolverBuiltinsValidationTest,
DataPacking4x8,
::testing::Values("pack4x8snorm", "pack4x8unorm"));
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);
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
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.");
}