mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-09 21:47:47 +00:00
Move global var validation from Validator to Resolver
* Moved global variable resolving logic to new function Resolver::GlobalVariable, and moved validation logic there. * Moved global variable-related tests to resolver tests. * Fixed many tests that started failing after this change, mainly because many globals were declared with no storage class. I set most of these to "Input". Bug: tint:642 Change-Id: I0f8ea2091ed2bb3faa358f9497cd884b2994a40f Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/46940 Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: Ben Clayton <bclayton@google.com> Commit-Queue: Antonio Maiorano <amaiorano@google.com>
This commit is contained in:
committed by
Commit Bot service account
parent
4f154a839d
commit
bbbb0edec2
@@ -237,5 +237,40 @@ INSTANTIATE_TEST_SUITE_P(
|
||||
TestParams{DecorationKind::kStructBlock, false},
|
||||
TestParams{DecorationKind::kWorkgroup, false}));
|
||||
|
||||
using VariableDecorationTest = TestWithParams;
|
||||
TEST_P(VariableDecorationTest, IsValid) {
|
||||
auto params = GetParam();
|
||||
|
||||
Global("a", ty.f32(), ast::StorageClass::kInput, nullptr,
|
||||
ast::DecorationList{
|
||||
createDecoration(Source{{12, 34}}, *this, params.kind)});
|
||||
|
||||
WrapInFunction();
|
||||
|
||||
if (params.should_pass) {
|
||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
} else {
|
||||
EXPECT_FALSE(r()->Resolve()) << r()->error();
|
||||
EXPECT_EQ(r()->error(),
|
||||
"12:34 error: decoration is not valid for variables");
|
||||
}
|
||||
}
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
ValidatorTest,
|
||||
VariableDecorationTest,
|
||||
testing::Values(TestParams{DecorationKind::kAccess, false},
|
||||
TestParams{DecorationKind::kAlign, false},
|
||||
TestParams{DecorationKind::kBinding, true},
|
||||
TestParams{DecorationKind::kBuiltin, true},
|
||||
TestParams{DecorationKind::kConstantId, true},
|
||||
TestParams{DecorationKind::kGroup, true},
|
||||
TestParams{DecorationKind::kLocation, true},
|
||||
TestParams{DecorationKind::kOffset, false},
|
||||
TestParams{DecorationKind::kSize, false},
|
||||
TestParams{DecorationKind::kStage, false},
|
||||
TestParams{DecorationKind::kStride, false},
|
||||
TestParams{DecorationKind::kStructBlock, false},
|
||||
TestParams{DecorationKind::kWorkgroup, false}));
|
||||
|
||||
} // namespace
|
||||
} // namespace tint
|
||||
|
||||
@@ -37,14 +37,14 @@ TEST_F(ResolverHostShareableValidationTest, Bool) {
|
||||
}
|
||||
|
||||
TEST_F(ResolverHostShareableValidationTest, Pointer) {
|
||||
Global(Source{{56, 78}}, "g", ty.pointer<i32>(ast::StorageClass::kNone),
|
||||
Global(Source{{56, 78}}, "g", ty.pointer<i32>(ast::StorageClass::kInput),
|
||||
ast::StorageClass::kStorage);
|
||||
|
||||
ASSERT_FALSE(r()->Resolve());
|
||||
|
||||
EXPECT_EQ(
|
||||
r()->error(),
|
||||
R"(56:78 error: Type 'ptr<i32>' cannot be used in storage class 'storage' as it is non-host-shareable
|
||||
R"(56:78 error: Type 'ptr<in, i32>' cannot be used in storage class 'storage' as it is non-host-shareable
|
||||
56:78 note: while instantiating variable g)");
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ using ResolverIntrinsicDerivativeTest = ResolverTestWithParam<std::string>;
|
||||
TEST_P(ResolverIntrinsicDerivativeTest, Scalar) {
|
||||
auto name = GetParam();
|
||||
|
||||
Global("ident", ty.f32(), ast::StorageClass::kNone);
|
||||
Global("ident", ty.f32(), ast::StorageClass::kInput);
|
||||
|
||||
auto* expr = Call(name, "ident");
|
||||
WrapInFunction(expr);
|
||||
@@ -65,7 +65,7 @@ TEST_P(ResolverIntrinsicDerivativeTest, Scalar) {
|
||||
|
||||
TEST_P(ResolverIntrinsicDerivativeTest, Vector) {
|
||||
auto name = GetParam();
|
||||
Global("ident", ty.vec4<f32>(), ast::StorageClass::kNone);
|
||||
Global("ident", ty.vec4<f32>(), ast::StorageClass::kInput);
|
||||
|
||||
auto* expr = Call(name, "ident");
|
||||
WrapInFunction(expr);
|
||||
@@ -109,7 +109,7 @@ using ResolverIntrinsic = ResolverTestWithParam<std::string>;
|
||||
TEST_P(ResolverIntrinsic, Test) {
|
||||
auto name = GetParam();
|
||||
|
||||
Global("my_var", ty.vec3<bool>(), ast::StorageClass::kNone);
|
||||
Global("my_var", ty.vec3<bool>(), ast::StorageClass::kInput);
|
||||
|
||||
auto* expr = Call(name, "my_var");
|
||||
WrapInFunction(expr);
|
||||
@@ -127,7 +127,7 @@ using ResolverIntrinsicTest_FloatMethod = ResolverTestWithParam<std::string>;
|
||||
TEST_P(ResolverIntrinsicTest_FloatMethod, Vector) {
|
||||
auto name = GetParam();
|
||||
|
||||
Global("my_var", ty.vec3<f32>(), ast::StorageClass::kNone);
|
||||
Global("my_var", ty.vec3<f32>(), ast::StorageClass::kInput);
|
||||
|
||||
auto* expr = Call(name, "my_var");
|
||||
WrapInFunction(expr);
|
||||
@@ -143,7 +143,7 @@ TEST_P(ResolverIntrinsicTest_FloatMethod, Vector) {
|
||||
TEST_P(ResolverIntrinsicTest_FloatMethod, Scalar) {
|
||||
auto name = GetParam();
|
||||
|
||||
Global("my_var", ty.f32(), ast::StorageClass::kNone);
|
||||
Global("my_var", ty.f32(), ast::StorageClass::kInput);
|
||||
|
||||
auto* expr = Call(name, "my_var");
|
||||
WrapInFunction(expr);
|
||||
@@ -157,7 +157,7 @@ TEST_P(ResolverIntrinsicTest_FloatMethod, Scalar) {
|
||||
TEST_P(ResolverIntrinsicTest_FloatMethod, MissingParam) {
|
||||
auto name = GetParam();
|
||||
|
||||
Global("my_var", ty.f32(), ast::StorageClass::kNone);
|
||||
Global("my_var", ty.f32(), ast::StorageClass::kInput);
|
||||
|
||||
auto* expr = Call(name);
|
||||
WrapInFunction(expr);
|
||||
@@ -174,7 +174,7 @@ TEST_P(ResolverIntrinsicTest_FloatMethod, MissingParam) {
|
||||
TEST_P(ResolverIntrinsicTest_FloatMethod, TooManyParams) {
|
||||
auto name = GetParam();
|
||||
|
||||
Global("my_var", ty.f32(), ast::StorageClass::kNone);
|
||||
Global("my_var", ty.f32(), ast::StorageClass::kInput);
|
||||
|
||||
auto* expr = Call(name, "my_var", 1.23f);
|
||||
WrapInFunction(expr);
|
||||
@@ -182,7 +182,7 @@ TEST_P(ResolverIntrinsicTest_FloatMethod, TooManyParams) {
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
|
||||
EXPECT_EQ(r()->error(), "error: no matching call to " + name +
|
||||
"(ptr<f32>, f32)\n\n"
|
||||
"(ptr<in, f32>, f32)\n\n"
|
||||
"2 candidate functions:\n " +
|
||||
name + "(f32) -> bool\n " + name +
|
||||
"(vecN<f32>) -> vecN<bool>\n");
|
||||
@@ -242,7 +242,7 @@ class ResolverIntrinsicTest_TextureOperation
|
||||
void add_call_param(std::string name,
|
||||
type::Type* type,
|
||||
ast::ExpressionList* call_params) {
|
||||
Global(name, type, ast::StorageClass::kNone);
|
||||
Global(name, type, ast::StorageClass::kInput);
|
||||
call_params->push_back(Expr(name));
|
||||
}
|
||||
type::Type* subtype(Texture type) {
|
||||
@@ -370,7 +370,7 @@ INSTANTIATE_TEST_SUITE_P(
|
||||
TextureTestParams{type::TextureDimension::k3d}));
|
||||
|
||||
TEST_F(ResolverIntrinsicTest, Dot_Vec2) {
|
||||
Global("my_var", ty.vec2<f32>(), ast::StorageClass::kNone);
|
||||
Global("my_var", ty.vec2<f32>(), ast::StorageClass::kInput);
|
||||
|
||||
auto* expr = Call("dot", "my_var", "my_var");
|
||||
WrapInFunction(expr);
|
||||
@@ -382,7 +382,7 @@ TEST_F(ResolverIntrinsicTest, Dot_Vec2) {
|
||||
}
|
||||
|
||||
TEST_F(ResolverIntrinsicTest, Dot_Vec3) {
|
||||
Global("my_var", ty.vec3<f32>(), ast::StorageClass::kNone);
|
||||
Global("my_var", ty.vec3<f32>(), ast::StorageClass::kInput);
|
||||
|
||||
auto* expr = Call("dot", "my_var", "my_var");
|
||||
WrapInFunction(expr);
|
||||
@@ -394,7 +394,7 @@ TEST_F(ResolverIntrinsicTest, Dot_Vec3) {
|
||||
}
|
||||
|
||||
TEST_F(ResolverIntrinsicTest, Dot_Vec4) {
|
||||
Global("my_var", ty.vec4<f32>(), ast::StorageClass::kNone);
|
||||
Global("my_var", ty.vec4<f32>(), ast::StorageClass::kInput);
|
||||
|
||||
auto* expr = Call("dot", "my_var", "my_var");
|
||||
WrapInFunction(expr);
|
||||
@@ -420,15 +420,16 @@ TEST_F(ResolverIntrinsicTest, Dot_Error_Scalar) {
|
||||
}
|
||||
|
||||
TEST_F(ResolverIntrinsicTest, Dot_Error_VectorInt) {
|
||||
Global("my_var", ty.vec4<i32>(), ast::StorageClass::kNone);
|
||||
Global("my_var", ty.vec4<i32>(), ast::StorageClass::kInput);
|
||||
|
||||
auto* expr = Call("dot", "my_var", "my_var");
|
||||
WrapInFunction(expr);
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
|
||||
EXPECT_EQ(r()->error(),
|
||||
R"(error: no matching call to dot(ptr<vec4<i32>>, ptr<vec4<i32>>)
|
||||
EXPECT_EQ(
|
||||
r()->error(),
|
||||
R"(error: no matching call to dot(ptr<in, vec4<i32>>, ptr<in, vec4<i32>>)
|
||||
|
||||
1 candidate function:
|
||||
dot(vecN<f32>, vecN<f32>) -> f32
|
||||
@@ -436,9 +437,9 @@ TEST_F(ResolverIntrinsicTest, Dot_Error_VectorInt) {
|
||||
}
|
||||
|
||||
TEST_F(ResolverIntrinsicTest, Select) {
|
||||
Global("my_var", ty.vec3<f32>(), ast::StorageClass::kNone);
|
||||
Global("my_var", ty.vec3<f32>(), ast::StorageClass::kInput);
|
||||
|
||||
Global("bool_var", ty.vec3<bool>(), ast::StorageClass::kNone);
|
||||
Global("bool_var", ty.vec3<bool>(), ast::StorageClass::kInput);
|
||||
|
||||
auto* expr = Call("select", "my_var", "my_var", "bool_var");
|
||||
WrapInFunction(expr);
|
||||
@@ -756,7 +757,7 @@ INSTANTIATE_TEST_SUITE_P(
|
||||
using ResolverIntrinsicDataTest = ResolverTest;
|
||||
|
||||
TEST_F(ResolverIntrinsicDataTest, ArrayLength_Vector) {
|
||||
Global("arr", ty.array<int>(), ast::StorageClass::kNone);
|
||||
Global("arr", ty.array<int>(), ast::StorageClass::kInput);
|
||||
auto* call = Call("arrayLength", "arr");
|
||||
WrapInFunction(call);
|
||||
|
||||
@@ -767,14 +768,14 @@ TEST_F(ResolverIntrinsicDataTest, ArrayLength_Vector) {
|
||||
}
|
||||
|
||||
TEST_F(ResolverIntrinsicDataTest, ArrayLength_Error_ArraySized) {
|
||||
Global("arr", ty.array<int, 4>(), ast::StorageClass::kNone);
|
||||
Global("arr", ty.array<int, 4>(), ast::StorageClass::kInput);
|
||||
auto* call = Call("arrayLength", "arr");
|
||||
WrapInFunction(call);
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
|
||||
EXPECT_EQ(r()->error(),
|
||||
"error: no matching call to arrayLength(ptr<array<i32, 4>>)\n\n"
|
||||
"error: no matching call to arrayLength(ptr<in, array<i32, 4>>)\n\n"
|
||||
"1 candidate function:\n"
|
||||
" arrayLength(array<T>) -> u32\n");
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "src/ast/bitcast_expression.h"
|
||||
#include "src/ast/break_statement.h"
|
||||
#include "src/ast/call_statement.h"
|
||||
#include "src/ast/constant_id_decoration.h"
|
||||
#include "src/ast/continue_statement.h"
|
||||
#include "src/ast/discard_statement.h"
|
||||
#include "src/ast/fallthrough_statement.h"
|
||||
@@ -202,20 +203,7 @@ bool Resolver::ResolveInternal() {
|
||||
return false;
|
||||
}
|
||||
} else if (auto* var = decl->As<ast::Variable>()) {
|
||||
auto* info = CreateVariableInfo(var);
|
||||
variable_stack_.set_global(var->symbol(), info);
|
||||
|
||||
if (var->has_constructor()) {
|
||||
if (!Expression(var->constructor())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ApplyStorageClassUsageToType(var->declared_storage_class(),
|
||||
info->type, var->source())) {
|
||||
diagnostics_.add_note("while instantiating variable " +
|
||||
builder_->Symbols().NameFor(var->symbol()),
|
||||
var->source());
|
||||
if (!GlobalVariable(var)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -224,6 +212,59 @@ bool Resolver::ResolveInternal() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Resolver::GlobalVariable(ast::Variable* var) {
|
||||
if (variable_stack_.has(var->symbol())) {
|
||||
diagnostics_.add_error("v-0011",
|
||||
"redeclared global identifier '" +
|
||||
builder_->Symbols().NameFor(var->symbol()) + "'",
|
||||
var->source());
|
||||
return false;
|
||||
}
|
||||
|
||||
auto* info = CreateVariableInfo(var);
|
||||
variable_stack_.set_global(var->symbol(), info);
|
||||
|
||||
if (!var->is_const() && info->storage_class == ast::StorageClass::kNone) {
|
||||
diagnostics_.add_error(
|
||||
"v-0022", "global variables must have a storage class", var->source());
|
||||
return false;
|
||||
}
|
||||
if (var->is_const() && !(info->storage_class == ast::StorageClass::kNone)) {
|
||||
diagnostics_.add_error("v-global01",
|
||||
"global constants shouldn't have a storage class",
|
||||
var->source());
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto* deco : var->decorations()) {
|
||||
if (!(deco->Is<ast::BindingDecoration>() ||
|
||||
deco->Is<ast::BuiltinDecoration>() ||
|
||||
deco->Is<ast::ConstantIdDecoration>() ||
|
||||
deco->Is<ast::GroupDecoration>() ||
|
||||
deco->Is<ast::LocationDecoration>())) {
|
||||
diagnostics_.add_error("decoration is not valid for variables",
|
||||
deco->source());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (var->has_constructor()) {
|
||||
if (!Expression(var->constructor())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ApplyStorageClassUsageToType(var->declared_storage_class(), info->type,
|
||||
var->source())) {
|
||||
diagnostics_.add_note("while instantiating variable " +
|
||||
builder_->Symbols().NameFor(var->symbol()),
|
||||
var->source());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Resolver::ValidateVariable(const ast::Variable* var) {
|
||||
auto* type = variable_to_info_[var]->type;
|
||||
if (auto* r = type->UnwrapAll()->As<type::Array>()) {
|
||||
|
||||
@@ -227,6 +227,7 @@ class Resolver {
|
||||
bool Return(ast::ReturnStatement* ret);
|
||||
bool Switch(ast::SwitchStatement* s);
|
||||
bool Assignment(ast::AssignmentStatement* a);
|
||||
bool GlobalVariable(ast::Variable* var);
|
||||
|
||||
// AST and Type validation methods
|
||||
// Each return true on success, false on failure.
|
||||
|
||||
@@ -275,7 +275,7 @@ TEST_F(ResolverTest, Stmt_VariableDecl_Alias) {
|
||||
|
||||
TEST_F(ResolverTest, Stmt_VariableDecl_ModuleScope) {
|
||||
auto* init = Expr(2);
|
||||
Global("my_var", ty.i32(), ast::StorageClass::kNone, init);
|
||||
Global("my_var", ty.i32(), ast::StorageClass::kInput, init);
|
||||
|
||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
|
||||
@@ -352,19 +352,20 @@ TEST_F(ResolverTest, Stmt_VariableDecl_ModuleScopeAfterFunctionScope) {
|
||||
ast::VariableList params;
|
||||
|
||||
// Declare i32 "foo" inside a function
|
||||
auto* fn_i32 = Var("foo", ty.i32(), ast::StorageClass::kNone, Expr(2));
|
||||
auto* fn_i32 = Var("foo", ty.i32(), ast::StorageClass::kFunction, Expr(2));
|
||||
auto* fn_i32_init = fn_i32->constructor();
|
||||
auto* fn_i32_decl = create<ast::VariableDeclStatement>(fn_i32);
|
||||
Func("func_i32", params, ty.void_(), ast::StatementList{fn_i32_decl},
|
||||
ast::DecorationList{});
|
||||
|
||||
// Declare f32 "foo" at module scope
|
||||
auto* mod_f32 = Var("foo", ty.f32(), ast::StorageClass::kNone, Expr(2.f));
|
||||
auto* mod_f32 = Var("foo", ty.f32(), ast::StorageClass::kInput, Expr(2.f));
|
||||
auto* mod_init = mod_f32->constructor();
|
||||
AST().AddGlobalVariable(mod_f32);
|
||||
|
||||
// Reference "foo" in another function
|
||||
auto* fn_f32 = Var("bar", ty.f32(), ast::StorageClass::kNone, Expr("foo"));
|
||||
auto* fn_f32 =
|
||||
Var("bar", ty.f32(), ast::StorageClass::kFunction, Expr("foo"));
|
||||
auto* fn_f32_init = fn_f32->constructor();
|
||||
auto* fn_f32_decl = create<ast::VariableDeclStatement>(fn_f32);
|
||||
Func("func_f32", params, ty.void_(), ast::StatementList{fn_f32_decl},
|
||||
@@ -430,7 +431,7 @@ TEST_F(ResolverTest, Expr_ArrayAccessor_Array_Constant) {
|
||||
}
|
||||
|
||||
TEST_F(ResolverTest, Expr_ArrayAccessor_Matrix) {
|
||||
Global("my_var", ty.mat2x3<f32>(), ast::StorageClass::kNone);
|
||||
Global("my_var", ty.mat2x3<f32>(), ast::StorageClass::kInput);
|
||||
|
||||
auto* acc = IndexAccessor("my_var", 2);
|
||||
WrapInFunction(acc);
|
||||
@@ -446,7 +447,7 @@ TEST_F(ResolverTest, Expr_ArrayAccessor_Matrix) {
|
||||
}
|
||||
|
||||
TEST_F(ResolverTest, Expr_ArrayAccessor_Matrix_BothDimensions) {
|
||||
Global("my_var", ty.mat2x3<f32>(), ast::StorageClass::kNone);
|
||||
Global("my_var", ty.mat2x3<f32>(), ast::StorageClass::kInput);
|
||||
|
||||
auto* acc = IndexAccessor(IndexAccessor("my_var", 2), 1);
|
||||
WrapInFunction(acc);
|
||||
@@ -461,7 +462,7 @@ TEST_F(ResolverTest, Expr_ArrayAccessor_Matrix_BothDimensions) {
|
||||
}
|
||||
|
||||
TEST_F(ResolverTest, Expr_ArrayAccessor_Vector) {
|
||||
Global("my_var", ty.vec3<f32>(), ast::StorageClass::kNone);
|
||||
Global("my_var", ty.vec3<f32>(), ast::StorageClass::kInput);
|
||||
|
||||
auto* acc = IndexAccessor("my_var", 2);
|
||||
WrapInFunction(acc);
|
||||
@@ -600,7 +601,7 @@ TEST_F(ResolverTest, Expr_Constructor_Type_Vec4) {
|
||||
}
|
||||
|
||||
TEST_F(ResolverTest, Expr_Identifier_GlobalVariable) {
|
||||
auto* my_var = Global("my_var", ty.f32(), ast::StorageClass::kNone);
|
||||
auto* my_var = Global("my_var", ty.f32(), ast::StorageClass::kInput);
|
||||
|
||||
auto* ident = Expr("my_var");
|
||||
WrapInFunction(ident);
|
||||
@@ -838,7 +839,7 @@ TEST_F(ResolverTest, Expr_MemberAccessor_Struct) {
|
||||
ast::DecorationList{});
|
||||
|
||||
auto* st = ty.struct_("S", strct);
|
||||
Global("my_struct", st, ast::StorageClass::kNone);
|
||||
Global("my_struct", st, ast::StorageClass::kInput);
|
||||
|
||||
auto* mem = MemberAccessor("my_struct", "second_member");
|
||||
WrapInFunction(mem);
|
||||
@@ -860,7 +861,7 @@ TEST_F(ResolverTest, Expr_MemberAccessor_Struct_Alias) {
|
||||
|
||||
auto* st = ty.struct_("alias", strct);
|
||||
auto* alias = ty.alias("alias", st);
|
||||
Global("my_struct", alias, ast::StorageClass::kNone);
|
||||
Global("my_struct", alias, ast::StorageClass::kInput);
|
||||
|
||||
auto* mem = MemberAccessor("my_struct", "second_member");
|
||||
WrapInFunction(mem);
|
||||
@@ -875,7 +876,7 @@ TEST_F(ResolverTest, Expr_MemberAccessor_Struct_Alias) {
|
||||
}
|
||||
|
||||
TEST_F(ResolverTest, Expr_MemberAccessor_VectorSwizzle) {
|
||||
Global("my_vec", ty.vec3<f32>(), ast::StorageClass::kNone);
|
||||
Global("my_vec", ty.vec3<f32>(), ast::StorageClass::kInput);
|
||||
|
||||
auto* mem = MemberAccessor("my_vec", "xzyw");
|
||||
WrapInFunction(mem);
|
||||
@@ -890,7 +891,7 @@ TEST_F(ResolverTest, Expr_MemberAccessor_VectorSwizzle) {
|
||||
}
|
||||
|
||||
TEST_F(ResolverTest, Expr_MemberAccessor_VectorSwizzle_SingleElement) {
|
||||
Global("my_vec", ty.vec3<f32>(), ast::StorageClass::kNone);
|
||||
Global("my_vec", ty.vec3<f32>(), ast::StorageClass::kInput);
|
||||
|
||||
auto* mem = MemberAccessor("my_vec", "b");
|
||||
WrapInFunction(mem);
|
||||
@@ -941,7 +942,7 @@ TEST_F(ResolverTest, Expr_Accessor_MultiLevel) {
|
||||
ast::StructMemberList{Member("mem", &vecB)}, ast::DecorationList{});
|
||||
|
||||
auto* stA = ty.struct_("A", strctA);
|
||||
Global("c", stA, ast::StorageClass::kNone);
|
||||
Global("c", stA, ast::StorageClass::kInput);
|
||||
|
||||
auto* mem = MemberAccessor(
|
||||
MemberAccessor(IndexAccessor(MemberAccessor("c", "mem"), 0), "foo"),
|
||||
@@ -963,7 +964,7 @@ TEST_F(ResolverTest, Expr_MemberAccessor_InBinaryOp) {
|
||||
ast::DecorationList{});
|
||||
|
||||
auto* st = ty.struct_("S", strct);
|
||||
Global("my_struct", st, ast::StorageClass::kNone);
|
||||
Global("my_struct", st, ast::StorageClass::kInput);
|
||||
|
||||
auto* expr = Add(MemberAccessor("my_struct", "first_member"),
|
||||
MemberAccessor("my_struct", "second_member"));
|
||||
@@ -1148,8 +1149,8 @@ TEST_P(Expr_Binary_Test_Valid, All) {
|
||||
<< rhs_type->FriendlyName(Symbols());
|
||||
SCOPED_TRACE(ss.str());
|
||||
|
||||
Global("lhs", lhs_type, ast::StorageClass::kNone);
|
||||
Global("rhs", rhs_type, ast::StorageClass::kNone);
|
||||
Global("lhs", lhs_type, ast::StorageClass::kInput);
|
||||
Global("rhs", rhs_type, ast::StorageClass::kInput);
|
||||
|
||||
auto* expr =
|
||||
create<ast::BinaryExpression>(params.op, Expr("lhs"), Expr("rhs"));
|
||||
@@ -1205,8 +1206,8 @@ TEST_P(Expr_Binary_Test_WithAlias_Valid, All) {
|
||||
<< params.op << " " << rhs_type->FriendlyName(Symbols());
|
||||
SCOPED_TRACE(ss.str());
|
||||
|
||||
Global("lhs", lhs_type, ast::StorageClass::kNone);
|
||||
Global("rhs", rhs_type, ast::StorageClass::kNone);
|
||||
Global("lhs", lhs_type, ast::StorageClass::kInput);
|
||||
Global("rhs", rhs_type, ast::StorageClass::kInput);
|
||||
|
||||
auto* expr =
|
||||
create<ast::BinaryExpression>(params.op, Expr("lhs"), Expr("rhs"));
|
||||
@@ -1260,8 +1261,8 @@ TEST_P(Expr_Binary_Test_Invalid, All) {
|
||||
<< rhs_type->FriendlyName(Symbols());
|
||||
SCOPED_TRACE(ss.str());
|
||||
|
||||
Global("lhs", lhs_type, ast::StorageClass::kNone);
|
||||
Global("rhs", rhs_type, ast::StorageClass::kNone);
|
||||
Global("lhs", lhs_type, ast::StorageClass::kInput);
|
||||
Global("rhs", rhs_type, ast::StorageClass::kInput);
|
||||
|
||||
auto* expr = create<ast::BinaryExpression>(Source{{12, 34}}, params.op,
|
||||
Expr("lhs"), Expr("rhs"));
|
||||
@@ -1306,8 +1307,8 @@ TEST_P(Expr_Binary_Test_Invalid_VectorMatrixMultiply, All) {
|
||||
is_valid_expr = vec_size == mat_cols;
|
||||
}
|
||||
|
||||
Global("lhs", lhs_type, ast::StorageClass::kNone);
|
||||
Global("rhs", rhs_type, ast::StorageClass::kNone);
|
||||
Global("lhs", lhs_type, ast::StorageClass::kInput);
|
||||
Global("rhs", rhs_type, ast::StorageClass::kInput);
|
||||
|
||||
auto* expr = Mul(Source{{12, 34}}, Expr("lhs"), Expr("rhs"));
|
||||
WrapInFunction(expr);
|
||||
@@ -1346,8 +1347,8 @@ TEST_P(Expr_Binary_Test_Invalid_MatrixMatrixMultiply, All) {
|
||||
auto* result_type =
|
||||
create<type::Matrix>(ty.f32(), lhs_mat_rows, rhs_mat_cols);
|
||||
|
||||
Global("lhs", lhs_type, ast::StorageClass::kNone);
|
||||
Global("rhs", rhs_type, ast::StorageClass::kNone);
|
||||
Global("lhs", lhs_type, ast::StorageClass::kInput);
|
||||
Global("rhs", rhs_type, ast::StorageClass::kInput);
|
||||
|
||||
auto* expr = Mul(Source{{12, 34}}, Expr("lhs"), Expr("rhs"));
|
||||
WrapInFunction(expr);
|
||||
@@ -1379,7 +1380,7 @@ using UnaryOpExpressionTest = ResolverTestWithParam<ast::UnaryOp>;
|
||||
TEST_P(UnaryOpExpressionTest, Expr_UnaryOp) {
|
||||
auto op = GetParam();
|
||||
|
||||
Global("ident", ty.vec4<f32>(), ast::StorageClass::kNone);
|
||||
Global("ident", ty.vec4<f32>(), ast::StorageClass::kInput);
|
||||
auto* der = create<ast::UnaryOpExpression>(op, Expr("ident"));
|
||||
WrapInFunction(der);
|
||||
|
||||
|
||||
@@ -26,6 +26,85 @@ namespace {
|
||||
class ResolverTypeValidationTest : public resolver::TestHelper,
|
||||
public testing::Test {};
|
||||
|
||||
TEST_F(ResolverTypeValidationTest, GlobalVariableWithStorageClass_Pass) {
|
||||
// var<in> global_var: f32;
|
||||
Global(Source{{12, 34}}, "global_var", ty.f32(), ast::StorageClass::kInput);
|
||||
|
||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
}
|
||||
|
||||
TEST_F(ResolverTypeValidationTest, GlobalVariableNoStorageClass_Fail) {
|
||||
// var global_var: f32;
|
||||
Global(Source{{12, 34}}, "global_var", ty.f32(), ast::StorageClass::kNone);
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(r()->error(),
|
||||
"12:34 error v-0022: global variables must have a storage class");
|
||||
}
|
||||
|
||||
TEST_F(ResolverTypeValidationTest, GlobalConstantWithStorageClass_Fail) {
|
||||
// const<in> global_var: f32;
|
||||
AST().AddGlobalVariable(
|
||||
create<ast::Variable>(Source{{12, 34}}, Symbols().Register("global_var"),
|
||||
ast::StorageClass::kInput, ty.f32(), true, nullptr,
|
||||
ast::DecorationList{}));
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(r()->error(),
|
||||
"12:34 error v-global01: global constants shouldn't have a storage "
|
||||
"class");
|
||||
}
|
||||
|
||||
TEST_F(ResolverTypeValidationTest, GlobalConstNoStorageClass_Pass) {
|
||||
// const global_var: f32;
|
||||
GlobalConst(Source{{12, 34}}, "global_var", ty.f32());
|
||||
|
||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
}
|
||||
|
||||
TEST_F(ResolverTypeValidationTest, GlobalVariableUnique_Pass) {
|
||||
// var global_var0 : f32 = 0.1;
|
||||
// var global_var1 : i32 = 0;
|
||||
|
||||
Global("global_var0", ty.f32(), ast::StorageClass::kPrivate, Expr(0.1f));
|
||||
|
||||
Global(Source{{12, 34}}, "global_var1", ty.f32(), ast::StorageClass::kPrivate,
|
||||
Expr(0));
|
||||
|
||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
}
|
||||
|
||||
TEST_F(ResolverTypeValidationTest, GlobalVariableNotUnique_Fail) {
|
||||
// var global_var : f32 = 0.1;
|
||||
// var global_var : i32 = 0;
|
||||
Global("global_var", ty.f32(), ast::StorageClass::kPrivate, Expr(0.1f));
|
||||
|
||||
Global(Source{{12, 34}}, "global_var", ty.i32(), ast::StorageClass::kPrivate,
|
||||
Expr(0));
|
||||
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
EXPECT_EQ(r()->error(),
|
||||
"12:34 error v-0011: redeclared global identifier 'global_var'");
|
||||
}
|
||||
|
||||
TEST_F(ResolverTypeValidationTest,
|
||||
GlobalVariableFunctionVariableNotUnique_Pass) {
|
||||
// fn my_func -> void {
|
||||
// var a: f32 = 2.0;
|
||||
// }
|
||||
// var a: f32 = 2.1;
|
||||
|
||||
auto* var = Var("a", ty.f32(), ast::StorageClass::kNone, Expr(2.0f));
|
||||
|
||||
Func("my_func", ast::VariableList{}, ty.void_(), {Decl(var)},
|
||||
ast::DecorationList{
|
||||
create<ast::StageDecoration>(ast::PipelineStage::kVertex)});
|
||||
|
||||
Global("a", ty.f32(), ast::StorageClass::kPrivate, Expr(2.1f));
|
||||
|
||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
}
|
||||
|
||||
TEST_F(ResolverTypeValidationTest,
|
||||
GlobalVariableFunctionVariableNotUnique_Fail) {
|
||||
// var a: f32 = 2.1;
|
||||
@@ -40,8 +119,7 @@ TEST_F(ResolverTypeValidationTest,
|
||||
|
||||
Func("my_func", ast::VariableList{}, ty.void_(),
|
||||
ast::StatementList{
|
||||
create<ast::VariableDeclStatement>(Source{Source::Location{12, 34}},
|
||||
var),
|
||||
create<ast::VariableDeclStatement>(Source{{12, 34}}, var),
|
||||
},
|
||||
ast::DecorationList{});
|
||||
|
||||
@@ -61,8 +139,7 @@ TEST_F(ResolverTypeValidationTest, RedeclaredIdentifier_Fail) {
|
||||
Func("my_func", ast::VariableList{}, ty.void_(),
|
||||
ast::StatementList{
|
||||
create<ast::VariableDeclStatement>(var),
|
||||
create<ast::VariableDeclStatement>(Source{Source::Location{12, 34}},
|
||||
var_a_float),
|
||||
create<ast::VariableDeclStatement>(Source{{12, 34}}, var_a_float),
|
||||
},
|
||||
ast::DecorationList{});
|
||||
|
||||
@@ -86,8 +163,7 @@ TEST_F(ResolverTypeValidationTest, RedeclaredIdentifierInnerScope_Pass) {
|
||||
|
||||
auto* outer_body = create<ast::BlockStatement>(ast::StatementList{
|
||||
create<ast::IfStatement>(cond, body, ast::ElseStatementList{}),
|
||||
create<ast::VariableDeclStatement>(Source{Source::Location{12, 34}},
|
||||
var_a_float),
|
||||
create<ast::VariableDeclStatement>(Source{{12, 34}}, var_a_float),
|
||||
});
|
||||
|
||||
WrapInFunction(outer_body);
|
||||
@@ -109,7 +185,7 @@ TEST_F(ResolverTypeValidationTest,
|
||||
|
||||
auto* cond = Expr(true);
|
||||
auto* body = create<ast::BlockStatement>(ast::StatementList{
|
||||
create<ast::VariableDeclStatement>(Source{Source::Location{12, 34}}, var),
|
||||
create<ast::VariableDeclStatement>(Source{{12, 34}}, var),
|
||||
});
|
||||
|
||||
auto* outer_body = create<ast::BlockStatement>(ast::StatementList{
|
||||
@@ -130,8 +206,7 @@ TEST_F(ResolverTypeValidationTest, RedeclaredIdentifierInnerScopeBlock_Pass) {
|
||||
// }
|
||||
auto* var_inner = Var("a", ty.f32(), ast::StorageClass::kNone);
|
||||
auto* inner = create<ast::BlockStatement>(ast::StatementList{
|
||||
create<ast::VariableDeclStatement>(Source{Source::Location{12, 34}},
|
||||
var_inner),
|
||||
create<ast::VariableDeclStatement>(Source{{12, 34}}, var_inner),
|
||||
});
|
||||
|
||||
auto* var_outer = Var("a", ty.f32(), ast::StorageClass::kNone);
|
||||
@@ -152,8 +227,7 @@ TEST_F(ResolverTypeValidationTest, RedeclaredIdentifierInnerScopeBlock_Fail) {
|
||||
// }
|
||||
auto* var_inner = Var("a", ty.f32(), ast::StorageClass::kNone);
|
||||
auto* inner = create<ast::BlockStatement>(ast::StatementList{
|
||||
create<ast::VariableDeclStatement>(Source{Source::Location{12, 34}},
|
||||
var_inner),
|
||||
create<ast::VariableDeclStatement>(Source{{12, 34}}, var_inner),
|
||||
});
|
||||
|
||||
auto* var_outer = Var("a", ty.f32(), ast::StorageClass::kNone);
|
||||
@@ -178,16 +252,14 @@ TEST_F(ResolverTypeValidationTest,
|
||||
|
||||
Func("func0", ast::VariableList{}, ty.void_(),
|
||||
ast::StatementList{
|
||||
create<ast::VariableDeclStatement>(Source{Source::Location{12, 34}},
|
||||
var0),
|
||||
create<ast::VariableDeclStatement>(Source{{12, 34}}, var0),
|
||||
create<ast::ReturnStatement>(),
|
||||
},
|
||||
ast::DecorationList{});
|
||||
|
||||
Func("func1", ast::VariableList{}, ty.void_(),
|
||||
ast::StatementList{
|
||||
create<ast::VariableDeclStatement>(Source{Source::Location{13, 34}},
|
||||
var1),
|
||||
create<ast::VariableDeclStatement>(Source{{13, 34}}, var1),
|
||||
create<ast::ReturnStatement>(),
|
||||
},
|
||||
ast::DecorationList{
|
||||
@@ -294,8 +366,8 @@ TEST_F(ResolverTypeValidationTest, RuntimeArrayAsParameter_Fail) {
|
||||
// fn func(a : array<u32>) {}
|
||||
// [[stage(vertex)]] fn main() {}
|
||||
|
||||
auto* param = Var(Source{Source::Location{12, 34}}, "a", ty.array<i32>(),
|
||||
ast::StorageClass::kNone);
|
||||
auto* param =
|
||||
Var(Source{{12, 34}}, "a", ty.array<i32>(), ast::StorageClass::kNone);
|
||||
|
||||
Func("func", ast::VariableList{param}, ty.void_(),
|
||||
ast::StatementList{
|
||||
|
||||
@@ -381,7 +381,7 @@ TEST_F(ResolverValidationTest, StorageClass_NonFunctionClassError) {
|
||||
}
|
||||
|
||||
TEST_F(ResolverValidationTest, Expr_MemberAccessor_VectorSwizzle_BadChar) {
|
||||
Global("my_vec", ty.vec3<f32>(), ast::StorageClass::kNone);
|
||||
Global("my_vec", ty.vec3<f32>(), ast::StorageClass::kInput);
|
||||
|
||||
auto* ident = create<ast::IdentifierExpression>(
|
||||
Source{{Source::Location{3, 3}, Source::Location{3, 7}}},
|
||||
@@ -395,7 +395,7 @@ TEST_F(ResolverValidationTest, Expr_MemberAccessor_VectorSwizzle_BadChar) {
|
||||
}
|
||||
|
||||
TEST_F(ResolverValidationTest, Expr_MemberAccessor_VectorSwizzle_MixedChars) {
|
||||
Global("my_vec", ty.vec3<f32>(), ast::StorageClass::kNone);
|
||||
Global("my_vec", ty.vec3<f32>(), ast::StorageClass::kInput);
|
||||
|
||||
auto* ident = create<ast::IdentifierExpression>(
|
||||
Source{{Source::Location{3, 3}, Source::Location{3, 7}}},
|
||||
@@ -411,7 +411,7 @@ TEST_F(ResolverValidationTest, Expr_MemberAccessor_VectorSwizzle_MixedChars) {
|
||||
}
|
||||
|
||||
TEST_F(ResolverValidationTest, Expr_MemberAccessor_VectorSwizzle_BadLength) {
|
||||
Global("my_vec", ty.vec3<f32>(), ast::StorageClass::kNone);
|
||||
Global("my_vec", ty.vec3<f32>(), ast::StorageClass::kInput);
|
||||
|
||||
auto* ident = create<ast::IdentifierExpression>(
|
||||
Source{{Source::Location{3, 3}, Source::Location{3, 8}}},
|
||||
@@ -1705,7 +1705,7 @@ TEST_F(ResolverValidationTest,
|
||||
|
||||
TEST_F(ResolverValidationTest, Expr_Constructor_Vector_Alias_Argument_Error) {
|
||||
auto* alias = ty.alias("UnsignedInt", ty.u32());
|
||||
Global("uint_var", alias, ast::StorageClass::kNone);
|
||||
Global("uint_var", alias, ast::StorageClass::kInput);
|
||||
|
||||
auto* tc = vec2<f32>(Expr(Source{{12, 34}}, "uint_var"));
|
||||
WrapInFunction(tc);
|
||||
@@ -1719,8 +1719,8 @@ TEST_F(ResolverValidationTest, Expr_Constructor_Vector_Alias_Argument_Error) {
|
||||
TEST_F(ResolverValidationTest, Expr_Constructor_Vector_Alias_Argument_Success) {
|
||||
auto* f32_alias = ty.alias("Float32", ty.f32());
|
||||
auto* vec2_alias = ty.alias("VectorFloat2", ty.vec2<f32>());
|
||||
Global("my_f32", f32_alias, ast::StorageClass::kNone);
|
||||
Global("my_vec2", vec2_alias, ast::StorageClass::kNone);
|
||||
Global("my_f32", f32_alias, ast::StorageClass::kInput);
|
||||
Global("my_vec2", vec2_alias, ast::StorageClass::kInput);
|
||||
|
||||
auto* tc = vec3<f32>("my_vec2", "my_f32");
|
||||
WrapInFunction(tc);
|
||||
|
||||
Reference in New Issue
Block a user