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:
Antonio Maiorano 2021-04-06 20:18:57 +00:00 committed by Commit Bot service account
parent 4f154a839d
commit bbbb0edec2
29 changed files with 366 additions and 400 deletions

View File

@ -48,10 +48,10 @@ var g5 : [[access(read)]] texture_storage_2d<r32uint>;
var g6 : [[access(write)]] texture_storage_2d<rg32float>; var g6 : [[access(write)]] texture_storage_2d<rg32float>;
[[builtin(position)]] var<uniform> g7 : vec3<f32>; [[builtin(position)]] var<uniform> g7 : vec3<f32>;
[[group(10), binding(20)]] var<storage> g7 : S; [[group(10), binding(20)]] var<storage> g8 : S;
[[group(10), binding(20)]] var<storage> g8 : [[access(read)]] [[group(10), binding(20)]] var<storage> g9 : [[access(read)]]
S; S;
[[group(10), binding(20)]] var<storage> g9 : [[access(read_write)]] [[group(10), binding(20)]] var<storage> g10 : [[access(read_write)]]
S; S;
fn f0(p0 : bool) -> f32 { fn f0(p0 : bool) -> f32 {

View File

@ -237,5 +237,40 @@ INSTANTIATE_TEST_SUITE_P(
TestParams{DecorationKind::kStructBlock, false}, TestParams{DecorationKind::kStructBlock, false},
TestParams{DecorationKind::kWorkgroup, 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
} // namespace tint } // namespace tint

View File

@ -37,14 +37,14 @@ TEST_F(ResolverHostShareableValidationTest, Bool) {
} }
TEST_F(ResolverHostShareableValidationTest, Pointer) { 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); ast::StorageClass::kStorage);
ASSERT_FALSE(r()->Resolve()); ASSERT_FALSE(r()->Resolve());
EXPECT_EQ( EXPECT_EQ(
r()->error(), 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)"); 56:78 note: while instantiating variable g)");
} }

View File

@ -52,7 +52,7 @@ using ResolverIntrinsicDerivativeTest = ResolverTestWithParam<std::string>;
TEST_P(ResolverIntrinsicDerivativeTest, Scalar) { TEST_P(ResolverIntrinsicDerivativeTest, Scalar) {
auto name = GetParam(); auto name = GetParam();
Global("ident", ty.f32(), ast::StorageClass::kNone); Global("ident", ty.f32(), ast::StorageClass::kInput);
auto* expr = Call(name, "ident"); auto* expr = Call(name, "ident");
WrapInFunction(expr); WrapInFunction(expr);
@ -65,7 +65,7 @@ TEST_P(ResolverIntrinsicDerivativeTest, Scalar) {
TEST_P(ResolverIntrinsicDerivativeTest, Vector) { TEST_P(ResolverIntrinsicDerivativeTest, Vector) {
auto name = GetParam(); auto name = GetParam();
Global("ident", ty.vec4<f32>(), ast::StorageClass::kNone); Global("ident", ty.vec4<f32>(), ast::StorageClass::kInput);
auto* expr = Call(name, "ident"); auto* expr = Call(name, "ident");
WrapInFunction(expr); WrapInFunction(expr);
@ -109,7 +109,7 @@ using ResolverIntrinsic = ResolverTestWithParam<std::string>;
TEST_P(ResolverIntrinsic, Test) { TEST_P(ResolverIntrinsic, Test) {
auto name = GetParam(); 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"); auto* expr = Call(name, "my_var");
WrapInFunction(expr); WrapInFunction(expr);
@ -127,7 +127,7 @@ using ResolverIntrinsicTest_FloatMethod = ResolverTestWithParam<std::string>;
TEST_P(ResolverIntrinsicTest_FloatMethod, Vector) { TEST_P(ResolverIntrinsicTest_FloatMethod, Vector) {
auto name = GetParam(); 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"); auto* expr = Call(name, "my_var");
WrapInFunction(expr); WrapInFunction(expr);
@ -143,7 +143,7 @@ TEST_P(ResolverIntrinsicTest_FloatMethod, Vector) {
TEST_P(ResolverIntrinsicTest_FloatMethod, Scalar) { TEST_P(ResolverIntrinsicTest_FloatMethod, Scalar) {
auto name = GetParam(); 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"); auto* expr = Call(name, "my_var");
WrapInFunction(expr); WrapInFunction(expr);
@ -157,7 +157,7 @@ TEST_P(ResolverIntrinsicTest_FloatMethod, Scalar) {
TEST_P(ResolverIntrinsicTest_FloatMethod, MissingParam) { TEST_P(ResolverIntrinsicTest_FloatMethod, MissingParam) {
auto name = GetParam(); auto name = GetParam();
Global("my_var", ty.f32(), ast::StorageClass::kNone); Global("my_var", ty.f32(), ast::StorageClass::kInput);
auto* expr = Call(name); auto* expr = Call(name);
WrapInFunction(expr); WrapInFunction(expr);
@ -174,7 +174,7 @@ TEST_P(ResolverIntrinsicTest_FloatMethod, MissingParam) {
TEST_P(ResolverIntrinsicTest_FloatMethod, TooManyParams) { TEST_P(ResolverIntrinsicTest_FloatMethod, TooManyParams) {
auto name = GetParam(); 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); auto* expr = Call(name, "my_var", 1.23f);
WrapInFunction(expr); WrapInFunction(expr);
@ -182,7 +182,7 @@ TEST_P(ResolverIntrinsicTest_FloatMethod, TooManyParams) {
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), "error: no matching call to " + name + 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 " + "2 candidate functions:\n " +
name + "(f32) -> bool\n " + name + name + "(f32) -> bool\n " + name +
"(vecN<f32>) -> vecN<bool>\n"); "(vecN<f32>) -> vecN<bool>\n");
@ -242,7 +242,7 @@ class ResolverIntrinsicTest_TextureOperation
void add_call_param(std::string name, void add_call_param(std::string name,
type::Type* type, type::Type* type,
ast::ExpressionList* call_params) { ast::ExpressionList* call_params) {
Global(name, type, ast::StorageClass::kNone); Global(name, type, ast::StorageClass::kInput);
call_params->push_back(Expr(name)); call_params->push_back(Expr(name));
} }
type::Type* subtype(Texture type) { type::Type* subtype(Texture type) {
@ -370,7 +370,7 @@ INSTANTIATE_TEST_SUITE_P(
TextureTestParams{type::TextureDimension::k3d})); TextureTestParams{type::TextureDimension::k3d}));
TEST_F(ResolverIntrinsicTest, Dot_Vec2) { 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"); auto* expr = Call("dot", "my_var", "my_var");
WrapInFunction(expr); WrapInFunction(expr);
@ -382,7 +382,7 @@ TEST_F(ResolverIntrinsicTest, Dot_Vec2) {
} }
TEST_F(ResolverIntrinsicTest, Dot_Vec3) { 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"); auto* expr = Call("dot", "my_var", "my_var");
WrapInFunction(expr); WrapInFunction(expr);
@ -394,7 +394,7 @@ TEST_F(ResolverIntrinsicTest, Dot_Vec3) {
} }
TEST_F(ResolverIntrinsicTest, Dot_Vec4) { 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"); auto* expr = Call("dot", "my_var", "my_var");
WrapInFunction(expr); WrapInFunction(expr);
@ -420,15 +420,16 @@ TEST_F(ResolverIntrinsicTest, Dot_Error_Scalar) {
} }
TEST_F(ResolverIntrinsicTest, Dot_Error_VectorInt) { 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"); auto* expr = Call("dot", "my_var", "my_var");
WrapInFunction(expr); WrapInFunction(expr);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(
R"(error: no matching call to dot(ptr<vec4<i32>>, ptr<vec4<i32>>) r()->error(),
R"(error: no matching call to dot(ptr<in, vec4<i32>>, ptr<in, vec4<i32>>)
1 candidate function: 1 candidate function:
dot(vecN<f32>, vecN<f32>) -> f32 dot(vecN<f32>, vecN<f32>) -> f32
@ -436,9 +437,9 @@ TEST_F(ResolverIntrinsicTest, Dot_Error_VectorInt) {
} }
TEST_F(ResolverIntrinsicTest, Select) { 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"); auto* expr = Call("select", "my_var", "my_var", "bool_var");
WrapInFunction(expr); WrapInFunction(expr);
@ -756,7 +757,7 @@ INSTANTIATE_TEST_SUITE_P(
using ResolverIntrinsicDataTest = ResolverTest; using ResolverIntrinsicDataTest = ResolverTest;
TEST_F(ResolverIntrinsicDataTest, ArrayLength_Vector) { 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"); auto* call = Call("arrayLength", "arr");
WrapInFunction(call); WrapInFunction(call);
@ -767,14 +768,14 @@ TEST_F(ResolverIntrinsicDataTest, ArrayLength_Vector) {
} }
TEST_F(ResolverIntrinsicDataTest, ArrayLength_Error_ArraySized) { 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"); auto* call = Call("arrayLength", "arr");
WrapInFunction(call); WrapInFunction(call);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), 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" "1 candidate function:\n"
" arrayLength(array<T>) -> u32\n"); " arrayLength(array<T>) -> u32\n");
} }

View File

@ -21,6 +21,7 @@
#include "src/ast/bitcast_expression.h" #include "src/ast/bitcast_expression.h"
#include "src/ast/break_statement.h" #include "src/ast/break_statement.h"
#include "src/ast/call_statement.h" #include "src/ast/call_statement.h"
#include "src/ast/constant_id_decoration.h"
#include "src/ast/continue_statement.h" #include "src/ast/continue_statement.h"
#include "src/ast/discard_statement.h" #include "src/ast/discard_statement.h"
#include "src/ast/fallthrough_statement.h" #include "src/ast/fallthrough_statement.h"
@ -202,20 +203,7 @@ bool Resolver::ResolveInternal() {
return false; return false;
} }
} else if (auto* var = decl->As<ast::Variable>()) { } else if (auto* var = decl->As<ast::Variable>()) {
auto* info = CreateVariableInfo(var); if (!GlobalVariable(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());
return false; return false;
} }
} }
@ -224,6 +212,59 @@ bool Resolver::ResolveInternal() {
return true; 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) { bool Resolver::ValidateVariable(const ast::Variable* var) {
auto* type = variable_to_info_[var]->type; auto* type = variable_to_info_[var]->type;
if (auto* r = type->UnwrapAll()->As<type::Array>()) { if (auto* r = type->UnwrapAll()->As<type::Array>()) {

View File

@ -227,6 +227,7 @@ class Resolver {
bool Return(ast::ReturnStatement* ret); bool Return(ast::ReturnStatement* ret);
bool Switch(ast::SwitchStatement* s); bool Switch(ast::SwitchStatement* s);
bool Assignment(ast::AssignmentStatement* a); bool Assignment(ast::AssignmentStatement* a);
bool GlobalVariable(ast::Variable* var);
// AST and Type validation methods // AST and Type validation methods
// Each return true on success, false on failure. // Each return true on success, false on failure.

View File

@ -275,7 +275,7 @@ TEST_F(ResolverTest, Stmt_VariableDecl_Alias) {
TEST_F(ResolverTest, Stmt_VariableDecl_ModuleScope) { TEST_F(ResolverTest, Stmt_VariableDecl_ModuleScope) {
auto* init = Expr(2); 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(); EXPECT_TRUE(r()->Resolve()) << r()->error();
@ -352,19 +352,20 @@ TEST_F(ResolverTest, Stmt_VariableDecl_ModuleScopeAfterFunctionScope) {
ast::VariableList params; ast::VariableList params;
// Declare i32 "foo" inside a function // 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_init = fn_i32->constructor();
auto* fn_i32_decl = create<ast::VariableDeclStatement>(fn_i32); auto* fn_i32_decl = create<ast::VariableDeclStatement>(fn_i32);
Func("func_i32", params, ty.void_(), ast::StatementList{fn_i32_decl}, Func("func_i32", params, ty.void_(), ast::StatementList{fn_i32_decl},
ast::DecorationList{}); ast::DecorationList{});
// Declare f32 "foo" at module scope // 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(); auto* mod_init = mod_f32->constructor();
AST().AddGlobalVariable(mod_f32); AST().AddGlobalVariable(mod_f32);
// Reference "foo" in another function // 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_init = fn_f32->constructor();
auto* fn_f32_decl = create<ast::VariableDeclStatement>(fn_f32); auto* fn_f32_decl = create<ast::VariableDeclStatement>(fn_f32);
Func("func_f32", params, ty.void_(), ast::StatementList{fn_f32_decl}, 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) { 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); auto* acc = IndexAccessor("my_var", 2);
WrapInFunction(acc); WrapInFunction(acc);
@ -446,7 +447,7 @@ TEST_F(ResolverTest, Expr_ArrayAccessor_Matrix) {
} }
TEST_F(ResolverTest, Expr_ArrayAccessor_Matrix_BothDimensions) { 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); auto* acc = IndexAccessor(IndexAccessor("my_var", 2), 1);
WrapInFunction(acc); WrapInFunction(acc);
@ -461,7 +462,7 @@ TEST_F(ResolverTest, Expr_ArrayAccessor_Matrix_BothDimensions) {
} }
TEST_F(ResolverTest, Expr_ArrayAccessor_Vector) { 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); auto* acc = IndexAccessor("my_var", 2);
WrapInFunction(acc); WrapInFunction(acc);
@ -600,7 +601,7 @@ TEST_F(ResolverTest, Expr_Constructor_Type_Vec4) {
} }
TEST_F(ResolverTest, Expr_Identifier_GlobalVariable) { 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"); auto* ident = Expr("my_var");
WrapInFunction(ident); WrapInFunction(ident);
@ -838,7 +839,7 @@ TEST_F(ResolverTest, Expr_MemberAccessor_Struct) {
ast::DecorationList{}); ast::DecorationList{});
auto* st = ty.struct_("S", strct); 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"); auto* mem = MemberAccessor("my_struct", "second_member");
WrapInFunction(mem); WrapInFunction(mem);
@ -860,7 +861,7 @@ TEST_F(ResolverTest, Expr_MemberAccessor_Struct_Alias) {
auto* st = ty.struct_("alias", strct); auto* st = ty.struct_("alias", strct);
auto* alias = ty.alias("alias", st); 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"); auto* mem = MemberAccessor("my_struct", "second_member");
WrapInFunction(mem); WrapInFunction(mem);
@ -875,7 +876,7 @@ TEST_F(ResolverTest, Expr_MemberAccessor_Struct_Alias) {
} }
TEST_F(ResolverTest, Expr_MemberAccessor_VectorSwizzle) { 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"); auto* mem = MemberAccessor("my_vec", "xzyw");
WrapInFunction(mem); WrapInFunction(mem);
@ -890,7 +891,7 @@ TEST_F(ResolverTest, Expr_MemberAccessor_VectorSwizzle) {
} }
TEST_F(ResolverTest, Expr_MemberAccessor_VectorSwizzle_SingleElement) { 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"); auto* mem = MemberAccessor("my_vec", "b");
WrapInFunction(mem); WrapInFunction(mem);
@ -941,7 +942,7 @@ TEST_F(ResolverTest, Expr_Accessor_MultiLevel) {
ast::StructMemberList{Member("mem", &vecB)}, ast::DecorationList{}); ast::StructMemberList{Member("mem", &vecB)}, ast::DecorationList{});
auto* stA = ty.struct_("A", strctA); auto* stA = ty.struct_("A", strctA);
Global("c", stA, ast::StorageClass::kNone); Global("c", stA, ast::StorageClass::kInput);
auto* mem = MemberAccessor( auto* mem = MemberAccessor(
MemberAccessor(IndexAccessor(MemberAccessor("c", "mem"), 0), "foo"), MemberAccessor(IndexAccessor(MemberAccessor("c", "mem"), 0), "foo"),
@ -963,7 +964,7 @@ TEST_F(ResolverTest, Expr_MemberAccessor_InBinaryOp) {
ast::DecorationList{}); ast::DecorationList{});
auto* st = ty.struct_("S", strct); 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"), auto* expr = Add(MemberAccessor("my_struct", "first_member"),
MemberAccessor("my_struct", "second_member")); MemberAccessor("my_struct", "second_member"));
@ -1148,8 +1149,8 @@ TEST_P(Expr_Binary_Test_Valid, All) {
<< rhs_type->FriendlyName(Symbols()); << rhs_type->FriendlyName(Symbols());
SCOPED_TRACE(ss.str()); SCOPED_TRACE(ss.str());
Global("lhs", lhs_type, ast::StorageClass::kNone); Global("lhs", lhs_type, ast::StorageClass::kInput);
Global("rhs", rhs_type, ast::StorageClass::kNone); Global("rhs", rhs_type, ast::StorageClass::kInput);
auto* expr = auto* expr =
create<ast::BinaryExpression>(params.op, Expr("lhs"), Expr("rhs")); 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()); << params.op << " " << rhs_type->FriendlyName(Symbols());
SCOPED_TRACE(ss.str()); SCOPED_TRACE(ss.str());
Global("lhs", lhs_type, ast::StorageClass::kNone); Global("lhs", lhs_type, ast::StorageClass::kInput);
Global("rhs", rhs_type, ast::StorageClass::kNone); Global("rhs", rhs_type, ast::StorageClass::kInput);
auto* expr = auto* expr =
create<ast::BinaryExpression>(params.op, Expr("lhs"), Expr("rhs")); create<ast::BinaryExpression>(params.op, Expr("lhs"), Expr("rhs"));
@ -1260,8 +1261,8 @@ TEST_P(Expr_Binary_Test_Invalid, All) {
<< rhs_type->FriendlyName(Symbols()); << rhs_type->FriendlyName(Symbols());
SCOPED_TRACE(ss.str()); SCOPED_TRACE(ss.str());
Global("lhs", lhs_type, ast::StorageClass::kNone); Global("lhs", lhs_type, ast::StorageClass::kInput);
Global("rhs", rhs_type, ast::StorageClass::kNone); Global("rhs", rhs_type, ast::StorageClass::kInput);
auto* expr = create<ast::BinaryExpression>(Source{{12, 34}}, params.op, auto* expr = create<ast::BinaryExpression>(Source{{12, 34}}, params.op,
Expr("lhs"), Expr("rhs")); Expr("lhs"), Expr("rhs"));
@ -1306,8 +1307,8 @@ TEST_P(Expr_Binary_Test_Invalid_VectorMatrixMultiply, All) {
is_valid_expr = vec_size == mat_cols; is_valid_expr = vec_size == mat_cols;
} }
Global("lhs", lhs_type, ast::StorageClass::kNone); Global("lhs", lhs_type, ast::StorageClass::kInput);
Global("rhs", rhs_type, ast::StorageClass::kNone); Global("rhs", rhs_type, ast::StorageClass::kInput);
auto* expr = Mul(Source{{12, 34}}, Expr("lhs"), Expr("rhs")); auto* expr = Mul(Source{{12, 34}}, Expr("lhs"), Expr("rhs"));
WrapInFunction(expr); WrapInFunction(expr);
@ -1346,8 +1347,8 @@ TEST_P(Expr_Binary_Test_Invalid_MatrixMatrixMultiply, All) {
auto* result_type = auto* result_type =
create<type::Matrix>(ty.f32(), lhs_mat_rows, rhs_mat_cols); create<type::Matrix>(ty.f32(), lhs_mat_rows, rhs_mat_cols);
Global("lhs", lhs_type, ast::StorageClass::kNone); Global("lhs", lhs_type, ast::StorageClass::kInput);
Global("rhs", rhs_type, ast::StorageClass::kNone); Global("rhs", rhs_type, ast::StorageClass::kInput);
auto* expr = Mul(Source{{12, 34}}, Expr("lhs"), Expr("rhs")); auto* expr = Mul(Source{{12, 34}}, Expr("lhs"), Expr("rhs"));
WrapInFunction(expr); WrapInFunction(expr);
@ -1379,7 +1380,7 @@ using UnaryOpExpressionTest = ResolverTestWithParam<ast::UnaryOp>;
TEST_P(UnaryOpExpressionTest, Expr_UnaryOp) { TEST_P(UnaryOpExpressionTest, Expr_UnaryOp) {
auto op = GetParam(); 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")); auto* der = create<ast::UnaryOpExpression>(op, Expr("ident"));
WrapInFunction(der); WrapInFunction(der);

View File

@ -26,6 +26,85 @@ namespace {
class ResolverTypeValidationTest : public resolver::TestHelper, class ResolverTypeValidationTest : public resolver::TestHelper,
public testing::Test {}; 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, TEST_F(ResolverTypeValidationTest,
GlobalVariableFunctionVariableNotUnique_Fail) { GlobalVariableFunctionVariableNotUnique_Fail) {
// var a: f32 = 2.1; // var a: f32 = 2.1;
@ -40,8 +119,7 @@ TEST_F(ResolverTypeValidationTest,
Func("my_func", ast::VariableList{}, ty.void_(), Func("my_func", ast::VariableList{}, ty.void_(),
ast::StatementList{ ast::StatementList{
create<ast::VariableDeclStatement>(Source{Source::Location{12, 34}}, create<ast::VariableDeclStatement>(Source{{12, 34}}, var),
var),
}, },
ast::DecorationList{}); ast::DecorationList{});
@ -61,8 +139,7 @@ TEST_F(ResolverTypeValidationTest, RedeclaredIdentifier_Fail) {
Func("my_func", ast::VariableList{}, ty.void_(), Func("my_func", ast::VariableList{}, ty.void_(),
ast::StatementList{ ast::StatementList{
create<ast::VariableDeclStatement>(var), create<ast::VariableDeclStatement>(var),
create<ast::VariableDeclStatement>(Source{Source::Location{12, 34}}, create<ast::VariableDeclStatement>(Source{{12, 34}}, var_a_float),
var_a_float),
}, },
ast::DecorationList{}); ast::DecorationList{});
@ -86,8 +163,7 @@ TEST_F(ResolverTypeValidationTest, RedeclaredIdentifierInnerScope_Pass) {
auto* outer_body = create<ast::BlockStatement>(ast::StatementList{ auto* outer_body = create<ast::BlockStatement>(ast::StatementList{
create<ast::IfStatement>(cond, body, ast::ElseStatementList{}), create<ast::IfStatement>(cond, body, ast::ElseStatementList{}),
create<ast::VariableDeclStatement>(Source{Source::Location{12, 34}}, create<ast::VariableDeclStatement>(Source{{12, 34}}, var_a_float),
var_a_float),
}); });
WrapInFunction(outer_body); WrapInFunction(outer_body);
@ -109,7 +185,7 @@ TEST_F(ResolverTypeValidationTest,
auto* cond = Expr(true); auto* cond = Expr(true);
auto* body = create<ast::BlockStatement>(ast::StatementList{ 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{ 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* var_inner = Var("a", ty.f32(), ast::StorageClass::kNone);
auto* inner = create<ast::BlockStatement>(ast::StatementList{ auto* inner = create<ast::BlockStatement>(ast::StatementList{
create<ast::VariableDeclStatement>(Source{Source::Location{12, 34}}, create<ast::VariableDeclStatement>(Source{{12, 34}}, var_inner),
var_inner),
}); });
auto* var_outer = Var("a", ty.f32(), ast::StorageClass::kNone); 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* var_inner = Var("a", ty.f32(), ast::StorageClass::kNone);
auto* inner = create<ast::BlockStatement>(ast::StatementList{ auto* inner = create<ast::BlockStatement>(ast::StatementList{
create<ast::VariableDeclStatement>(Source{Source::Location{12, 34}}, create<ast::VariableDeclStatement>(Source{{12, 34}}, var_inner),
var_inner),
}); });
auto* var_outer = Var("a", ty.f32(), ast::StorageClass::kNone); auto* var_outer = Var("a", ty.f32(), ast::StorageClass::kNone);
@ -178,16 +252,14 @@ TEST_F(ResolverTypeValidationTest,
Func("func0", ast::VariableList{}, ty.void_(), Func("func0", ast::VariableList{}, ty.void_(),
ast::StatementList{ ast::StatementList{
create<ast::VariableDeclStatement>(Source{Source::Location{12, 34}}, create<ast::VariableDeclStatement>(Source{{12, 34}}, var0),
var0),
create<ast::ReturnStatement>(), create<ast::ReturnStatement>(),
}, },
ast::DecorationList{}); ast::DecorationList{});
Func("func1", ast::VariableList{}, ty.void_(), Func("func1", ast::VariableList{}, ty.void_(),
ast::StatementList{ ast::StatementList{
create<ast::VariableDeclStatement>(Source{Source::Location{13, 34}}, create<ast::VariableDeclStatement>(Source{{13, 34}}, var1),
var1),
create<ast::ReturnStatement>(), create<ast::ReturnStatement>(),
}, },
ast::DecorationList{ ast::DecorationList{
@ -294,8 +366,8 @@ TEST_F(ResolverTypeValidationTest, RuntimeArrayAsParameter_Fail) {
// fn func(a : array<u32>) {} // fn func(a : array<u32>) {}
// [[stage(vertex)]] fn main() {} // [[stage(vertex)]] fn main() {}
auto* param = Var(Source{Source::Location{12, 34}}, "a", ty.array<i32>(), auto* param =
ast::StorageClass::kNone); Var(Source{{12, 34}}, "a", ty.array<i32>(), ast::StorageClass::kNone);
Func("func", ast::VariableList{param}, ty.void_(), Func("func", ast::VariableList{param}, ty.void_(),
ast::StatementList{ ast::StatementList{

View File

@ -381,7 +381,7 @@ TEST_F(ResolverValidationTest, StorageClass_NonFunctionClassError) {
} }
TEST_F(ResolverValidationTest, Expr_MemberAccessor_VectorSwizzle_BadChar) { 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>( auto* ident = create<ast::IdentifierExpression>(
Source{{Source::Location{3, 3}, Source::Location{3, 7}}}, 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) { 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>( auto* ident = create<ast::IdentifierExpression>(
Source{{Source::Location{3, 3}, Source::Location{3, 7}}}, 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) { 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>( auto* ident = create<ast::IdentifierExpression>(
Source{{Source::Location{3, 3}, Source::Location{3, 8}}}, 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) { TEST_F(ResolverValidationTest, Expr_Constructor_Vector_Alias_Argument_Error) {
auto* alias = ty.alias("UnsignedInt", ty.u32()); 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")); auto* tc = vec2<f32>(Expr(Source{{12, 34}}, "uint_var"));
WrapInFunction(tc); WrapInFunction(tc);
@ -1719,8 +1719,8 @@ TEST_F(ResolverValidationTest, Expr_Constructor_Vector_Alias_Argument_Error) {
TEST_F(ResolverValidationTest, Expr_Constructor_Vector_Alias_Argument_Success) { TEST_F(ResolverValidationTest, Expr_Constructor_Vector_Alias_Argument_Success) {
auto* f32_alias = ty.alias("Float32", ty.f32()); auto* f32_alias = ty.alias("Float32", ty.f32());
auto* vec2_alias = ty.alias("VectorFloat2", ty.vec2<f32>()); auto* vec2_alias = ty.alias("VectorFloat2", ty.vec2<f32>());
Global("my_f32", f32_alias, ast::StorageClass::kNone); Global("my_f32", f32_alias, ast::StorageClass::kInput);
Global("my_vec2", vec2_alias, ast::StorageClass::kNone); Global("my_vec2", vec2_alias, ast::StorageClass::kInput);
auto* tc = vec3<f32>("my_vec2", "my_f32"); auto* tc = vec3<f32>("my_vec2", "my_f32");
WrapInFunction(tc); WrapInFunction(tc);

View File

@ -50,11 +50,11 @@ fn f() -> void {
TEST_F(BoundArrayAccessorsTest, Array_Idx_Nested_Scalar) { TEST_F(BoundArrayAccessorsTest, Array_Idx_Nested_Scalar) {
auto* src = R"( auto* src = R"(
var a : array<f32, 3>; var<in> a : array<f32, 3>;
var b : array<f32, 5>; var<in> b : array<f32, 5>;
var i : u32; var<in> i : u32;
fn f() -> void { fn f() -> void {
var c : f32 = a[ b[i] ]; var c : f32 = a[ b[i] ];
@ -62,11 +62,11 @@ fn f() -> void {
)"; )";
auto* expect = R"( auto* expect = R"(
var a : array<f32, 3>; var<in> a : array<f32, 3>;
var b : array<f32, 5>; var<in> b : array<f32, 5>;
var i : u32; var<in> i : u32;
fn f() -> void { fn f() -> void {
var c : f32 = a[min(u32(b[min(u32(i), 4u)]), 2u)]; var c : f32 = a[min(u32(b[min(u32(i), 4u)]), 2u)];
@ -80,7 +80,7 @@ fn f() -> void {
TEST_F(BoundArrayAccessorsTest, Array_Idx_Scalar) { TEST_F(BoundArrayAccessorsTest, Array_Idx_Scalar) {
auto* src = R"( auto* src = R"(
var a : array<f32, 3>; var<in> a : array<f32, 3>;
fn f() -> void { fn f() -> void {
var b : f32 = a[1]; var b : f32 = a[1];
@ -88,7 +88,7 @@ fn f() -> void {
)"; )";
auto* expect = R"( auto* expect = R"(
var a : array<f32, 3>; var<in> a : array<f32, 3>;
fn f() -> void { fn f() -> void {
var b : f32 = a[1]; var b : f32 = a[1];
@ -102,9 +102,9 @@ fn f() -> void {
TEST_F(BoundArrayAccessorsTest, Array_Idx_Expr) { TEST_F(BoundArrayAccessorsTest, Array_Idx_Expr) {
auto* src = R"( auto* src = R"(
var a : array<f32, 3>; var<in> a : array<f32, 3>;
var c : i32; var<in> c : i32;
fn f() -> void { fn f() -> void {
var b : f32 = a[c + 2 - 3]; var b : f32 = a[c + 2 - 3];
@ -112,9 +112,9 @@ fn f() -> void {
)"; )";
auto* expect = R"( auto* expect = R"(
var a : array<f32, 3>; var<in> a : array<f32, 3>;
var c : i32; var<in> c : i32;
fn f() -> void { fn f() -> void {
var b : f32 = a[min(u32(((c + 2) - 3)), 2u)]; var b : f32 = a[min(u32(((c + 2) - 3)), 2u)];
@ -128,7 +128,7 @@ fn f() -> void {
TEST_F(BoundArrayAccessorsTest, Array_Idx_Negative) { TEST_F(BoundArrayAccessorsTest, Array_Idx_Negative) {
auto* src = R"( auto* src = R"(
var a : array<f32, 3>; var<in> a : array<f32, 3>;
fn f() -> void { fn f() -> void {
var b : f32 = a[-1]; var b : f32 = a[-1];
@ -136,7 +136,7 @@ fn f() -> void {
)"; )";
auto* expect = R"( auto* expect = R"(
var a : array<f32, 3>; var<in> a : array<f32, 3>;
fn f() -> void { fn f() -> void {
var b : f32 = a[0]; var b : f32 = a[0];
@ -150,7 +150,7 @@ fn f() -> void {
TEST_F(BoundArrayAccessorsTest, Array_Idx_OutOfBounds) { TEST_F(BoundArrayAccessorsTest, Array_Idx_OutOfBounds) {
auto* src = R"( auto* src = R"(
var a : array<f32, 3>; var<in> a : array<f32, 3>;
fn f() -> void { fn f() -> void {
var b : f32 = a[3]; var b : f32 = a[3];
@ -158,7 +158,7 @@ fn f() -> void {
)"; )";
auto* expect = R"( auto* expect = R"(
var a : array<f32, 3>; var<in> a : array<f32, 3>;
fn f() -> void { fn f() -> void {
var b : f32 = a[2]; var b : f32 = a[2];
@ -172,7 +172,7 @@ fn f() -> void {
TEST_F(BoundArrayAccessorsTest, Vector_Idx_Scalar) { TEST_F(BoundArrayAccessorsTest, Vector_Idx_Scalar) {
auto* src = R"( auto* src = R"(
var a : vec3<f32>; var<in> a : vec3<f32>;
fn f() -> void { fn f() -> void {
var b : f32 = a[1]; var b : f32 = a[1];
@ -180,7 +180,7 @@ fn f() -> void {
)"; )";
auto* expect = R"( auto* expect = R"(
var a : vec3<f32>; var<in> a : vec3<f32>;
fn f() -> void { fn f() -> void {
var b : f32 = a[1]; var b : f32 = a[1];
@ -194,9 +194,9 @@ fn f() -> void {
TEST_F(BoundArrayAccessorsTest, Vector_Idx_Expr) { TEST_F(BoundArrayAccessorsTest, Vector_Idx_Expr) {
auto* src = R"( auto* src = R"(
var a : vec3<f32>; var<in> a : vec3<f32>;
var c : i32; var<in> c : i32;
fn f() -> void { fn f() -> void {
var b : f32 = a[c + 2 - 3]; var b : f32 = a[c + 2 - 3];
@ -204,9 +204,9 @@ fn f() -> void {
)"; )";
auto* expect = R"( auto* expect = R"(
var a : vec3<f32>; var<in> a : vec3<f32>;
var c : i32; var<in> c : i32;
fn f() -> void { fn f() -> void {
var b : f32 = a[min(u32(((c + 2) - 3)), 2u)]; var b : f32 = a[min(u32(((c + 2) - 3)), 2u)];
@ -220,7 +220,7 @@ fn f() -> void {
TEST_F(BoundArrayAccessorsTest, Vector_Swizzle_Idx_Scalar) { TEST_F(BoundArrayAccessorsTest, Vector_Swizzle_Idx_Scalar) {
auto* src = R"( auto* src = R"(
var a : vec3<f32>; var<in> a : vec3<f32>;
fn f() -> void { fn f() -> void {
var b : f32 = a.xy[2]; var b : f32 = a.xy[2];
@ -228,7 +228,7 @@ fn f() -> void {
)"; )";
auto* expect = R"( auto* expect = R"(
var a : vec3<f32>; var<in> a : vec3<f32>;
fn f() -> void { fn f() -> void {
var b : f32 = a.xy[1]; var b : f32 = a.xy[1];
@ -242,9 +242,9 @@ fn f() -> void {
TEST_F(BoundArrayAccessorsTest, Vector_Swizzle_Idx_Var) { TEST_F(BoundArrayAccessorsTest, Vector_Swizzle_Idx_Var) {
auto* src = R"( auto* src = R"(
var a : vec3<f32>; var<in> a : vec3<f32>;
var c : i32; var<in> c : i32;
fn f() -> void { fn f() -> void {
var b : f32 = a.xy[c]; var b : f32 = a.xy[c];
@ -252,9 +252,9 @@ fn f() -> void {
)"; )";
auto* expect = R"( auto* expect = R"(
var a : vec3<f32>; var<in> a : vec3<f32>;
var c : i32; var<in> c : i32;
fn f() -> void { fn f() -> void {
var b : f32 = a.xy[min(u32(c), 1u)]; var b : f32 = a.xy[min(u32(c), 1u)];
@ -267,9 +267,9 @@ fn f() -> void {
} }
TEST_F(BoundArrayAccessorsTest, Vector_Swizzle_Idx_Expr) { TEST_F(BoundArrayAccessorsTest, Vector_Swizzle_Idx_Expr) {
auto* src = R"( auto* src = R"(
var a : vec3<f32>; var<in> a : vec3<f32>;
var c : i32; var<in> c : i32;
fn f() -> void { fn f() -> void {
var b : f32 = a.xy[c + 2 - 3]; var b : f32 = a.xy[c + 2 - 3];
@ -277,9 +277,9 @@ fn f() -> void {
)"; )";
auto* expect = R"( auto* expect = R"(
var a : vec3<f32>; var<in> a : vec3<f32>;
var c : i32; var<in> c : i32;
fn f() -> void { fn f() -> void {
var b : f32 = a.xy[min(u32(((c + 2) - 3)), 1u)]; var b : f32 = a.xy[min(u32(((c + 2) - 3)), 1u)];
@ -293,7 +293,7 @@ fn f() -> void {
TEST_F(BoundArrayAccessorsTest, Vector_Idx_Negative) { TEST_F(BoundArrayAccessorsTest, Vector_Idx_Negative) {
auto* src = R"( auto* src = R"(
var a : vec3<f32>; var<in> a : vec3<f32>;
fn f() -> void { fn f() -> void {
var b : f32 = a[-1]; var b : f32 = a[-1];
@ -301,7 +301,7 @@ fn f() -> void {
)"; )";
auto* expect = R"( auto* expect = R"(
var a : vec3<f32>; var<in> a : vec3<f32>;
fn f() -> void { fn f() -> void {
var b : f32 = a[0]; var b : f32 = a[0];
@ -315,7 +315,7 @@ fn f() -> void {
TEST_F(BoundArrayAccessorsTest, Vector_Idx_OutOfBounds) { TEST_F(BoundArrayAccessorsTest, Vector_Idx_OutOfBounds) {
auto* src = R"( auto* src = R"(
var a : vec3<f32>; var<in> a : vec3<f32>;
fn f() -> void { fn f() -> void {
var b : f32 = a[3]; var b : f32 = a[3];
@ -323,7 +323,7 @@ fn f() -> void {
)"; )";
auto* expect = R"( auto* expect = R"(
var a : vec3<f32>; var<in> a : vec3<f32>;
fn f() -> void { fn f() -> void {
var b : f32 = a[2]; var b : f32 = a[2];
@ -337,7 +337,7 @@ fn f() -> void {
TEST_F(BoundArrayAccessorsTest, Matrix_Idx_Scalar) { TEST_F(BoundArrayAccessorsTest, Matrix_Idx_Scalar) {
auto* src = R"( auto* src = R"(
var a : mat3x2<f32>; var<in> a : mat3x2<f32>;
fn f() -> void { fn f() -> void {
var b : f32 = a[2][1]; var b : f32 = a[2][1];
@ -345,7 +345,7 @@ fn f() -> void {
)"; )";
auto* expect = R"( auto* expect = R"(
var a : mat3x2<f32>; var<in> a : mat3x2<f32>;
fn f() -> void { fn f() -> void {
var b : f32 = a[2][1]; var b : f32 = a[2][1];
@ -359,9 +359,9 @@ fn f() -> void {
TEST_F(BoundArrayAccessorsTest, Matrix_Idx_Expr_Column) { TEST_F(BoundArrayAccessorsTest, Matrix_Idx_Expr_Column) {
auto* src = R"( auto* src = R"(
var a : mat3x2<f32>; var<in> a : mat3x2<f32>;
var c : i32; var<in> c : i32;
fn f() -> void { fn f() -> void {
var b : f32 = a[c + 2 - 3][1]; var b : f32 = a[c + 2 - 3][1];
@ -369,9 +369,9 @@ fn f() -> void {
)"; )";
auto* expect = R"( auto* expect = R"(
var a : mat3x2<f32>; var<in> a : mat3x2<f32>;
var c : i32; var<in> c : i32;
fn f() -> void { fn f() -> void {
var b : f32 = a[min(u32(((c + 2) - 3)), 2u)][1]; var b : f32 = a[min(u32(((c + 2) - 3)), 2u)][1];
@ -385,9 +385,9 @@ fn f() -> void {
TEST_F(BoundArrayAccessorsTest, Matrix_Idx_Expr_Row) { TEST_F(BoundArrayAccessorsTest, Matrix_Idx_Expr_Row) {
auto* src = R"( auto* src = R"(
var a : mat3x2<f32>; var<in> a : mat3x2<f32>;
var c : i32; var<in> c : i32;
fn f() -> void { fn f() -> void {
var b : f32 = a[1][c + 2 - 3]; var b : f32 = a[1][c + 2 - 3];
@ -395,9 +395,9 @@ fn f() -> void {
)"; )";
auto* expect = R"( auto* expect = R"(
var a : mat3x2<f32>; var<in> a : mat3x2<f32>;
var c : i32; var<in> c : i32;
fn f() -> void { fn f() -> void {
var b : f32 = a[1][min(u32(((c + 2) - 3)), 1u)]; var b : f32 = a[1][min(u32(((c + 2) - 3)), 1u)];
@ -411,7 +411,7 @@ fn f() -> void {
TEST_F(BoundArrayAccessorsTest, Matrix_Idx_Negative_Column) { TEST_F(BoundArrayAccessorsTest, Matrix_Idx_Negative_Column) {
auto* src = R"( auto* src = R"(
var a : mat3x2<f32>; var<in> a : mat3x2<f32>;
fn f() -> void { fn f() -> void {
var b : f32 = a[-1][1]; var b : f32 = a[-1][1];
@ -419,7 +419,7 @@ fn f() -> void {
)"; )";
auto* expect = R"( auto* expect = R"(
var a : mat3x2<f32>; var<in> a : mat3x2<f32>;
fn f() -> void { fn f() -> void {
var b : f32 = a[0][1]; var b : f32 = a[0][1];
@ -433,7 +433,7 @@ fn f() -> void {
TEST_F(BoundArrayAccessorsTest, Matrix_Idx_Negative_Row) { TEST_F(BoundArrayAccessorsTest, Matrix_Idx_Negative_Row) {
auto* src = R"( auto* src = R"(
var a : mat3x2<f32>; var<in> a : mat3x2<f32>;
fn f() -> void { fn f() -> void {
var b : f32 = a[2][-1]; var b : f32 = a[2][-1];
@ -441,7 +441,7 @@ fn f() -> void {
)"; )";
auto* expect = R"( auto* expect = R"(
var a : mat3x2<f32>; var<in> a : mat3x2<f32>;
fn f() -> void { fn f() -> void {
var b : f32 = a[2][0]; var b : f32 = a[2][0];
@ -455,7 +455,7 @@ fn f() -> void {
TEST_F(BoundArrayAccessorsTest, Matrix_Idx_OutOfBounds_Column) { TEST_F(BoundArrayAccessorsTest, Matrix_Idx_OutOfBounds_Column) {
auto* src = R"( auto* src = R"(
var a : mat3x2<f32>; var<in> a : mat3x2<f32>;
fn f() -> void { fn f() -> void {
var b : f32 = a[5][1]; var b : f32 = a[5][1];
@ -463,7 +463,7 @@ fn f() -> void {
)"; )";
auto* expect = R"( auto* expect = R"(
var a : mat3x2<f32>; var<in> a : mat3x2<f32>;
fn f() -> void { fn f() -> void {
var b : f32 = a[2][1]; var b : f32 = a[2][1];
@ -477,7 +477,7 @@ fn f() -> void {
TEST_F(BoundArrayAccessorsTest, Matrix_Idx_OutOfBounds_Row) { TEST_F(BoundArrayAccessorsTest, Matrix_Idx_OutOfBounds_Row) {
auto* src = R"( auto* src = R"(
var a : mat3x2<f32>; var<in> a : mat3x2<f32>;
fn f() -> void { fn f() -> void {
var b : f32 = a[2][5]; var b : f32 = a[2][5];
@ -485,7 +485,7 @@ fn f() -> void {
)"; )";
auto* expect = R"( auto* expect = R"(
var a : mat3x2<f32>; var<in> a : mat3x2<f32>;
fn f() -> void { fn f() -> void {
var b : f32 = a[2][1]; var b : f32 = a[2][1];
@ -540,7 +540,7 @@ struct S {
a : f32; a : f32;
b : array<f32>; b : array<f32>;
}; };
var s : S; var<in> s : S;
fn f() -> void { fn f() -> void {
var d : f32 = s.b[25]; var d : f32 = s.b[25];
@ -554,7 +554,7 @@ struct S {
b : array<f32>; b : array<f32>;
}; };
var s : S; var<in> s : S;
fn f() -> void { fn f() -> void {
var d : f32 = s.b[min(u32(25), (arrayLength(s.b) - 1u))]; var d : f32 = s.b[min(u32(25), (arrayLength(s.b) - 1u))];

View File

@ -121,38 +121,5 @@ INSTANTIATE_TEST_SUITE_P(
DecorationTestParams{DecorationKind::kStructBlock, false}, DecorationTestParams{DecorationKind::kStructBlock, false},
DecorationTestParams{DecorationKind::kWorkgroup, true})); DecorationTestParams{DecorationKind::kWorkgroup, true}));
using VariableDecorationTest = ValidatorDecorationsTestWithParams;
TEST_P(VariableDecorationTest, Decoration_IsValid) {
auto params = GetParam();
auto* var = Global("a", ty.f32(), ast::StorageClass::kInput, nullptr,
ast::DecorationList{createDecoration(*this, params.kind)});
ValidatorImpl& v = Build();
if (params.should_pass) {
EXPECT_TRUE(v.ValidateGlobalVariable(var));
} else {
EXPECT_FALSE(v.ValidateGlobalVariable(var));
EXPECT_EQ(v.error(), "decoration is not valid for variables");
}
}
INSTANTIATE_TEST_SUITE_P(
ValidatorTest,
VariableDecorationTest,
testing::Values(DecorationTestParams{DecorationKind::kAccess, false},
DecorationTestParams{DecorationKind::kAlign, false},
DecorationTestParams{DecorationKind::kBinding, true},
DecorationTestParams{DecorationKind::kBuiltin, true},
DecorationTestParams{DecorationKind::kConstantId, true},
DecorationTestParams{DecorationKind::kGroup, true},
DecorationTestParams{DecorationKind::kLocation, true},
DecorationTestParams{DecorationKind::kOffset, false},
DecorationTestParams{DecorationKind::kSize, false},
DecorationTestParams{DecorationKind::kStage, false},
DecorationTestParams{DecorationKind::kStride, false},
DecorationTestParams{DecorationKind::kStructBlock, false},
DecorationTestParams{DecorationKind::kWorkgroup, false}));
} // namespace } // namespace
} // namespace tint } // namespace tint

View File

@ -97,42 +97,6 @@ bool ValidatorImpl::Validate() {
} }
bool ValidatorImpl::ValidateGlobalVariable(const ast::Variable* var) { bool ValidatorImpl::ValidateGlobalVariable(const ast::Variable* var) {
auto* sem = program_->Sem().Get(var);
if (!sem) {
add_error(var->source(), "no semantic information for variable '" +
program_->Symbols().NameFor(var->symbol()) +
"'");
return false;
}
if (variable_stack_.has(var->symbol())) {
add_error(var->source(), "v-0011",
"redeclared global identifier '" +
program_->Symbols().NameFor(var->symbol()) + "'");
return false;
}
if (!var->is_const() && sem->StorageClass() == ast::StorageClass::kNone) {
add_error(var->source(), "v-0022",
"global variables must have a storage class");
return false;
}
if (var->is_const() && !(sem->StorageClass() == ast::StorageClass::kNone)) {
add_error(var->source(), "v-global01",
"global constants shouldn't have a storage class");
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>())) {
add_error(deco->source(), "decoration is not valid for variables");
return false;
}
}
variable_stack_.set_global(var->symbol(), var); variable_stack_.set_global(var->symbol(), var);
return true; return true;
} }

View File

@ -21,105 +21,6 @@ namespace {
class ValidatorTest : public ValidatorTestHelper, public testing::Test {}; class ValidatorTest : public ValidatorTestHelper, public testing::Test {};
TEST_F(ValidatorTest, GlobalVariableWithStorageClass_Pass) {
// var<in> global_var: f32;
auto* var = Global(Source{Source::Location{12, 34}}, "global_var", ty.f32(),
ast::StorageClass::kInput);
ValidatorImpl& v = Build();
EXPECT_TRUE(v.ValidateGlobalVariable(var)) << v.error();
}
TEST_F(ValidatorTest, GlobalVariableNoStorageClass_Fail) {
// var global_var: f32;
Global(Source{Source::Location{12, 34}}, "global_var", ty.f32(),
ast::StorageClass::kNone);
ValidatorImpl& v = Build();
EXPECT_FALSE(v.Validate());
EXPECT_EQ(v.error(),
"12:34 v-0022: global variables must have a storage class");
}
TEST_F(ValidatorTest, GlobalConstantWithStorageClass_Fail) {
// const<in> global_var: f32;
AST().AddGlobalVariable(create<ast::Variable>(
Source{Source::Location{12, 34}}, Symbols().Register("global_var"),
ast::StorageClass::kInput, ty.f32(), true, nullptr,
ast::DecorationList{}));
ValidatorImpl& v = Build();
EXPECT_FALSE(v.Validate());
EXPECT_EQ(
v.error(),
"12:34 v-global01: global constants shouldn't have a storage class");
}
TEST_F(ValidatorTest, GlobalConstNoStorageClass_Pass) {
// const global_var: f32;
GlobalConst(Source{Source::Location{12, 34}}, "global_var", ty.f32());
ValidatorImpl& v = Build();
EXPECT_TRUE(v.Validate()) << v.error();
}
TEST_F(ValidatorTest, GlobalVariableUnique_Pass) {
// var global_var0 : f32 = 0.1;
// var global_var1 : i32 = 0;
auto* var0 =
Global("global_var0", ty.f32(), ast::StorageClass::kPrivate, Expr(0.1f));
auto* var1 = Global(Source{Source::Location{12, 34}}, "global_var1", ty.f32(),
ast::StorageClass::kPrivate, Expr(0));
ValidatorImpl& v = Build();
EXPECT_TRUE(v.ValidateGlobalVariable(var0)) << v.error();
EXPECT_TRUE(v.ValidateGlobalVariable(var1)) << v.error();
}
TEST_F(ValidatorTest, 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{Source::Location{12, 34}}, "global_var", ty.i32(),
ast::StorageClass::kPrivate, Expr(0));
ValidatorImpl& v = Build();
EXPECT_FALSE(v.Validate());
EXPECT_EQ(v.error(),
"12:34 v-0011: redeclared global identifier 'global_var'");
}
TEST_F(ValidatorTest, 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_(),
ast::StatementList{
create<ast::VariableDeclStatement>(var),
},
ast::DecorationList{
create<ast::StageDecoration>(ast::PipelineStage::kVertex)});
Global("a", ty.f32(), ast::StorageClass::kPrivate, Expr(2.1f));
ValidatorImpl& v = Build();
EXPECT_TRUE(v.Validate()) << v.error();
}
TEST_F(ValidatorTest, VariableDeclNoConstructor_Pass) { TEST_F(ValidatorTest, VariableDeclNoConstructor_Pass) {
// { // {
// var a :i32; // var a :i32;

View File

@ -477,10 +477,10 @@ TEST_F(HlslGeneratorImplTest_Binary, Call_WithLogical) {
Func("foo", ast::VariableList{}, ty.void_(), ast::StatementList{}, Func("foo", ast::VariableList{}, ty.void_(), ast::StatementList{},
ast::DecorationList{}); ast::DecorationList{});
Global("a", ty.bool_(), ast::StorageClass::kNone); Global("a", ty.bool_(), ast::StorageClass::kInput);
Global("b", ty.bool_(), ast::StorageClass::kNone); Global("b", ty.bool_(), ast::StorageClass::kInput);
Global("c", ty.bool_(), ast::StorageClass::kNone); Global("c", ty.bool_(), ast::StorageClass::kInput);
Global("d", ty.bool_(), ast::StorageClass::kNone); Global("d", ty.bool_(), ast::StorageClass::kInput);
ast::ExpressionList params; ast::ExpressionList params;
params.push_back(create<ast::BinaryExpression>(ast::BinaryOp::kLogicalAnd, params.push_back(create<ast::BinaryExpression>(ast::BinaryOp::kLogicalAnd,

View File

@ -38,8 +38,8 @@ TEST_F(HlslGeneratorImplTest_Call, EmitExpression_Call_WithoutParams) {
TEST_F(HlslGeneratorImplTest_Call, EmitExpression_Call_WithParams) { TEST_F(HlslGeneratorImplTest_Call, EmitExpression_Call_WithParams) {
Func("my_func", ast::VariableList{}, ty.void_(), ast::StatementList{}, Func("my_func", ast::VariableList{}, ty.void_(), ast::StatementList{},
ast::DecorationList{}); ast::DecorationList{});
Global("param1", ty.f32(), ast::StorageClass::kNone); Global("param1", ty.f32(), ast::StorageClass::kInput);
Global("param2", ty.f32(), ast::StorageClass::kNone); Global("param2", ty.f32(), ast::StorageClass::kInput);
auto* call = Call("my_func", "param1", "param2"); auto* call = Call("my_func", "param1", "param2");
WrapInFunction(call); WrapInFunction(call);
@ -53,8 +53,8 @@ TEST_F(HlslGeneratorImplTest_Call, EmitExpression_Call_WithParams) {
TEST_F(HlslGeneratorImplTest_Call, EmitStatement_Call) { TEST_F(HlslGeneratorImplTest_Call, EmitStatement_Call) {
Func("my_func", ast::VariableList{}, ty.void_(), ast::StatementList{}, Func("my_func", ast::VariableList{}, ty.void_(), ast::StatementList{},
ast::DecorationList{}); ast::DecorationList{});
Global("param1", ty.f32(), ast::StorageClass::kNone); Global("param1", ty.f32(), ast::StorageClass::kInput);
Global("param2", ty.f32(), ast::StorageClass::kNone); Global("param2", ty.f32(), ast::StorageClass::kInput);
auto* call = create<ast::CallStatement>(Call("my_func", "param1", "param2")); auto* call = create<ast::CallStatement>(Call("my_func", "param1", "param2"));
WrapInFunction(call); WrapInFunction(call);

View File

@ -73,8 +73,8 @@ TEST_F(HlslGeneratorImplTest_Loop, Emit_LoopWithContinuing) {
} }
TEST_F(HlslGeneratorImplTest_Loop, Emit_LoopNestedWithContinuing) { TEST_F(HlslGeneratorImplTest_Loop, Emit_LoopNestedWithContinuing) {
Global("lhs", ty.f32(), ast::StorageClass::kNone); Global("lhs", ty.f32(), ast::StorageClass::kInput);
Global("rhs", ty.f32(), ast::StorageClass::kNone); Global("rhs", ty.f32(), ast::StorageClass::kInput);
auto* body = create<ast::BlockStatement>(ast::StatementList{ auto* body = create<ast::BlockStatement>(ast::StatementList{
create<ast::DiscardStatement>(), create<ast::DiscardStatement>(),
@ -149,7 +149,7 @@ TEST_F(HlslGeneratorImplTest_Loop, Emit_LoopWithVarUsedInContinuing) {
// } // }
// } // }
Global("rhs", ty.f32(), ast::StorageClass::kNone); Global("rhs", ty.f32(), ast::StorageClass::kInput);
auto* var = Var("lhs", ty.f32(), ast::StorageClass::kFunction, Expr(2.4f)); auto* var = Var("lhs", ty.f32(), ast::StorageClass::kFunction, Expr(2.4f));

View File

@ -23,7 +23,7 @@ namespace {
using HlslGeneratorImplTest_VariableDecl = TestHelper; using HlslGeneratorImplTest_VariableDecl = TestHelper;
TEST_F(HlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement) { TEST_F(HlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement) {
auto* var = Global("a", ty.f32(), ast::StorageClass::kNone); auto* var = Global("a", ty.f32(), ast::StorageClass::kInput);
auto* stmt = create<ast::VariableDeclStatement>(var); auto* stmt = create<ast::VariableDeclStatement>(var);
@ -50,7 +50,7 @@ TEST_F(HlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Const) {
} }
TEST_F(HlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Array) { TEST_F(HlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Array) {
auto* var = Global("a", ty.array<f32, 5>(), ast::StorageClass::kNone); auto* var = Global("a", ty.array<f32, 5>(), ast::StorageClass::kInput);
auto* stmt = create<ast::VariableDeclStatement>(var); auto* stmt = create<ast::VariableDeclStatement>(var);
@ -91,7 +91,7 @@ TEST_F(HlslGeneratorImplTest_VariableDecl, Emit_VariableDeclStatement_Private) {
TEST_F(HlslGeneratorImplTest_VariableDecl, TEST_F(HlslGeneratorImplTest_VariableDecl,
Emit_VariableDeclStatement_Initializer_Private) { Emit_VariableDeclStatement_Initializer_Private) {
Global("initializer", ty.f32(), ast::StorageClass::kNone); Global("initializer", ty.f32(), ast::StorageClass::kInput);
auto* var = auto* var =
Global("a", ty.f32(), ast::StorageClass::kPrivate, Expr("initializer")); Global("a", ty.f32(), ast::StorageClass::kPrivate, Expr("initializer"));

View File

@ -38,8 +38,8 @@ TEST_F(MslGeneratorImplTest, EmitExpression_Call_WithoutParams) {
TEST_F(MslGeneratorImplTest, EmitExpression_Call_WithParams) { TEST_F(MslGeneratorImplTest, EmitExpression_Call_WithParams) {
Func("my_func", ast::VariableList{}, ty.void_(), ast::StatementList{}, Func("my_func", ast::VariableList{}, ty.void_(), ast::StatementList{},
ast::DecorationList{}); ast::DecorationList{});
Global("param1", ty.f32(), ast::StorageClass::kNone); Global("param1", ty.f32(), ast::StorageClass::kInput);
Global("param2", ty.f32(), ast::StorageClass::kNone); Global("param2", ty.f32(), ast::StorageClass::kInput);
auto* call = Call("my_func", "param1", "param2"); auto* call = Call("my_func", "param1", "param2");
WrapInFunction(call); WrapInFunction(call);
@ -53,8 +53,8 @@ TEST_F(MslGeneratorImplTest, EmitExpression_Call_WithParams) {
TEST_F(MslGeneratorImplTest, EmitStatement_Call) { TEST_F(MslGeneratorImplTest, EmitStatement_Call) {
Func("my_func", ast::VariableList{}, ty.void_(), ast::StatementList{}, Func("my_func", ast::VariableList{}, ty.void_(), ast::StatementList{},
ast::DecorationList{}); ast::DecorationList{});
Global("param1", ty.f32(), ast::StorageClass::kNone); Global("param1", ty.f32(), ast::StorageClass::kInput);
Global("param2", ty.f32(), ast::StorageClass::kNone); Global("param2", ty.f32(), ast::StorageClass::kInput);
auto* call = Call("my_func", "param1", "param2"); auto* call = Call("my_func", "param1", "param2");
auto* stmt = create<ast::CallStatement>(call); auto* stmt = create<ast::CallStatement>(call);

View File

@ -71,8 +71,8 @@ TEST_F(MslGeneratorImplTest, Emit_LoopWithContinuing) {
} }
TEST_F(MslGeneratorImplTest, Emit_LoopNestedWithContinuing) { TEST_F(MslGeneratorImplTest, Emit_LoopNestedWithContinuing) {
Global("lhs", ty.f32(), ast::StorageClass::kNone); Global("lhs", ty.f32(), ast::StorageClass::kInput);
Global("rhs", ty.f32(), ast::StorageClass::kNone); Global("rhs", ty.f32(), ast::StorageClass::kInput);
auto* body = create<ast::BlockStatement>(ast::StatementList{ auto* body = create<ast::BlockStatement>(ast::StatementList{
create<ast::DiscardStatement>(), create<ast::DiscardStatement>(),
@ -144,7 +144,7 @@ TEST_F(MslGeneratorImplTest, Emit_LoopWithVarUsedInContinuing) {
// } // }
// } // }
Global("rhs", ty.f32(), ast::StorageClass::kNone); Global("rhs", ty.f32(), ast::StorageClass::kInput);
auto* var = Var("lhs", ty.f32(), ast::StorageClass::kFunction, Expr(2.4f)); auto* var = Var("lhs", ty.f32(), ast::StorageClass::kFunction, Expr(2.4f));

View File

@ -654,7 +654,7 @@ TEST_P(MslStorageTexturesTest, Emit) {
create<type::AccessControl>(params.ro ? ast::AccessControl::kReadOnly create<type::AccessControl>(params.ro ? ast::AccessControl::kReadOnly
: ast::AccessControl::kWriteOnly, : ast::AccessControl::kWriteOnly,
s); s);
Global("test_var", ac, ast::StorageClass::kNone); Global("test_var", ac, ast::StorageClass::kInput);
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();

View File

@ -122,7 +122,7 @@ TEST_F(MslGeneratorImplTest, Emit_VariableDeclStatement_Private) {
} }
TEST_F(MslGeneratorImplTest, Emit_VariableDeclStatement_Initializer_Private) { TEST_F(MslGeneratorImplTest, Emit_VariableDeclStatement_Initializer_Private) {
Global("initializer", ty.f32(), ast::StorageClass::kNone); Global("initializer", ty.f32(), ast::StorageClass::kInput);
auto* var = auto* var =
Global("a", ty.f32(), ast::StorageClass::kPrivate, Expr("initializer")); Global("a", ty.f32(), ast::StorageClass::kPrivate, Expr("initializer"));
auto* stmt = create<ast::VariableDeclStatement>(var); auto* stmt = create<ast::VariableDeclStatement>(var);

View File

@ -23,7 +23,7 @@ namespace {
using BuilderTest = TestHelper; using BuilderTest = TestHelper;
TEST_F(BuilderTest, FunctionVar_NoStorageClass) { TEST_F(BuilderTest, FunctionVar_NoStorageClass) {
auto* v = Global("var", ty.f32(), ast::StorageClass::kNone); auto* v = Global("var", ty.f32(), ast::StorageClass::kInput);
spirv::Builder& b = Build(); spirv::Builder& b = Build();

View File

@ -24,21 +24,6 @@ namespace {
using BuilderTest = TestHelper; using BuilderTest = TestHelper;
TEST_F(BuilderTest, GlobalVar_NoStorageClass) {
auto* v = Global("var", ty.f32(), ast::StorageClass::kNone);
spirv::Builder& b = Build();
EXPECT_TRUE(b.GenerateGlobalVariable(v)) << b.error();
EXPECT_EQ(DumpInstructions(b.debug()), R"(OpName %1 "var"
)");
EXPECT_EQ(DumpInstructions(b.types()), R"(%3 = OpTypeFloat 32
%2 = OpTypePointer Private %3
%4 = OpConstantNull %3
%1 = OpVariable %2 Private %4
)");
}
TEST_F(BuilderTest, GlobalVar_WithStorageClass) { TEST_F(BuilderTest, GlobalVar_WithStorageClass) {
auto* v = Global("var", ty.f32(), ast::StorageClass::kOutput); auto* v = Global("var", ty.f32(), ast::StorageClass::kOutput);
@ -218,7 +203,7 @@ TEST_F(BuilderTest, GlobalVar_WithBuiltin) {
} }
TEST_F(BuilderTest, GlobalVar_ConstantId_Bool) { TEST_F(BuilderTest, GlobalVar_ConstantId_Bool) {
auto* v = Global("var", ty.bool_(), ast::StorageClass::kNone, Expr(true), auto* v = Global("var", ty.bool_(), ast::StorageClass::kInput, Expr(true),
ast::DecorationList{ ast::DecorationList{
create<ast::ConstantIdDecoration>(1200), create<ast::ConstantIdDecoration>(1200),
}); });
@ -232,13 +217,13 @@ TEST_F(BuilderTest, GlobalVar_ConstantId_Bool) {
)"); )");
EXPECT_EQ(DumpInstructions(b.types()), R"(%1 = OpTypeBool EXPECT_EQ(DumpInstructions(b.types()), R"(%1 = OpTypeBool
%2 = OpSpecConstantTrue %1 %2 = OpSpecConstantTrue %1
%4 = OpTypePointer Private %1 %4 = OpTypePointer Input %1
%3 = OpVariable %4 Private %2 %3 = OpVariable %4 Input %2
)"); )");
} }
TEST_F(BuilderTest, GlobalVar_ConstantId_Bool_NoConstructor) { TEST_F(BuilderTest, GlobalVar_ConstantId_Bool_NoConstructor) {
auto* v = Global("var", ty.bool_(), ast::StorageClass::kNone, nullptr, auto* v = Global("var", ty.bool_(), ast::StorageClass::kInput, nullptr,
ast::DecorationList{ ast::DecorationList{
create<ast::ConstantIdDecoration>(1200), create<ast::ConstantIdDecoration>(1200),
}); });
@ -251,14 +236,14 @@ TEST_F(BuilderTest, GlobalVar_ConstantId_Bool_NoConstructor) {
EXPECT_EQ(DumpInstructions(b.annots()), R"(OpDecorate %4 SpecId 1200 EXPECT_EQ(DumpInstructions(b.annots()), R"(OpDecorate %4 SpecId 1200
)"); )");
EXPECT_EQ(DumpInstructions(b.types()), R"(%3 = OpTypeBool EXPECT_EQ(DumpInstructions(b.types()), R"(%3 = OpTypeBool
%2 = OpTypePointer Private %3 %2 = OpTypePointer Input %3
%4 = OpSpecConstantFalse %3 %4 = OpSpecConstantFalse %3
%1 = OpVariable %2 Private %4 %1 = OpVariable %2 Input %4
)"); )");
} }
TEST_F(BuilderTest, GlobalVar_ConstantId_Scalar) { TEST_F(BuilderTest, GlobalVar_ConstantId_Scalar) {
auto* v = Global("var", ty.f32(), ast::StorageClass::kNone, Expr(2.f), auto* v = Global("var", ty.f32(), ast::StorageClass::kInput, Expr(2.f),
ast::DecorationList{ ast::DecorationList{
create<ast::ConstantIdDecoration>(0), create<ast::ConstantIdDecoration>(0),
}); });
@ -272,13 +257,13 @@ TEST_F(BuilderTest, GlobalVar_ConstantId_Scalar) {
)"); )");
EXPECT_EQ(DumpInstructions(b.types()), R"(%1 = OpTypeFloat 32 EXPECT_EQ(DumpInstructions(b.types()), R"(%1 = OpTypeFloat 32
%2 = OpSpecConstant %1 2 %2 = OpSpecConstant %1 2
%4 = OpTypePointer Private %1 %4 = OpTypePointer Input %1
%3 = OpVariable %4 Private %2 %3 = OpVariable %4 Input %2
)"); )");
} }
TEST_F(BuilderTest, GlobalVar_ConstantId_Scalar_F32_NoConstructor) { TEST_F(BuilderTest, GlobalVar_ConstantId_Scalar_F32_NoConstructor) {
auto* v = Global("var", ty.f32(), ast::StorageClass::kNone, nullptr, auto* v = Global("var", ty.f32(), ast::StorageClass::kInput, nullptr,
ast::DecorationList{ ast::DecorationList{
create<ast::ConstantIdDecoration>(0), create<ast::ConstantIdDecoration>(0),
}); });
@ -291,14 +276,14 @@ TEST_F(BuilderTest, GlobalVar_ConstantId_Scalar_F32_NoConstructor) {
EXPECT_EQ(DumpInstructions(b.annots()), R"(OpDecorate %4 SpecId 0 EXPECT_EQ(DumpInstructions(b.annots()), R"(OpDecorate %4 SpecId 0
)"); )");
EXPECT_EQ(DumpInstructions(b.types()), R"(%3 = OpTypeFloat 32 EXPECT_EQ(DumpInstructions(b.types()), R"(%3 = OpTypeFloat 32
%2 = OpTypePointer Private %3 %2 = OpTypePointer Input %3
%4 = OpSpecConstant %3 0 %4 = OpSpecConstant %3 0
%1 = OpVariable %2 Private %4 %1 = OpVariable %2 Input %4
)"); )");
} }
TEST_F(BuilderTest, GlobalVar_ConstantId_Scalar_I32_NoConstructor) { TEST_F(BuilderTest, GlobalVar_ConstantId_Scalar_I32_NoConstructor) {
auto* v = Global("var", ty.i32(), ast::StorageClass::kNone, nullptr, auto* v = Global("var", ty.i32(), ast::StorageClass::kInput, nullptr,
ast::DecorationList{ ast::DecorationList{
create<ast::ConstantIdDecoration>(0), create<ast::ConstantIdDecoration>(0),
}); });
@ -311,14 +296,14 @@ TEST_F(BuilderTest, GlobalVar_ConstantId_Scalar_I32_NoConstructor) {
EXPECT_EQ(DumpInstructions(b.annots()), R"(OpDecorate %4 SpecId 0 EXPECT_EQ(DumpInstructions(b.annots()), R"(OpDecorate %4 SpecId 0
)"); )");
EXPECT_EQ(DumpInstructions(b.types()), R"(%3 = OpTypeInt 32 1 EXPECT_EQ(DumpInstructions(b.types()), R"(%3 = OpTypeInt 32 1
%2 = OpTypePointer Private %3 %2 = OpTypePointer Input %3
%4 = OpSpecConstant %3 0 %4 = OpSpecConstant %3 0
%1 = OpVariable %2 Private %4 %1 = OpVariable %2 Input %4
)"); )");
} }
TEST_F(BuilderTest, GlobalVar_ConstantId_Scalar_U32_NoConstructor) { TEST_F(BuilderTest, GlobalVar_ConstantId_Scalar_U32_NoConstructor) {
auto* v = Global("var", ty.u32(), ast::StorageClass::kNone, nullptr, auto* v = Global("var", ty.u32(), ast::StorageClass::kInput, nullptr,
ast::DecorationList{ ast::DecorationList{
create<ast::ConstantIdDecoration>(0), create<ast::ConstantIdDecoration>(0),
}); });
@ -331,9 +316,9 @@ TEST_F(BuilderTest, GlobalVar_ConstantId_Scalar_U32_NoConstructor) {
EXPECT_EQ(DumpInstructions(b.annots()), R"(OpDecorate %4 SpecId 0 EXPECT_EQ(DumpInstructions(b.annots()), R"(OpDecorate %4 SpecId 0
)"); )");
EXPECT_EQ(DumpInstructions(b.types()), R"(%3 = OpTypeInt 32 0 EXPECT_EQ(DumpInstructions(b.types()), R"(%3 = OpTypeInt 32 0
%2 = OpTypePointer Private %3 %2 = OpTypePointer Input %3
%4 = OpSpecConstant %3 0 %4 = OpSpecConstant %3 0
%1 = OpVariable %2 Private %4 %1 = OpVariable %2 Input %4
)"); )");
} }
@ -545,7 +530,7 @@ TEST_F(BuilderTest, GlobalVar_TextureStorageWriteOnly) {
type::StorageTexture::SubtypeFor(type::ImageFormat::kR32Uint, Types()); type::StorageTexture::SubtypeFor(type::ImageFormat::kR32Uint, Types());
auto* type = create<type::StorageTexture>( auto* type = create<type::StorageTexture>(
type::TextureDimension::k2d, type::ImageFormat::kR32Uint, subtype); type::TextureDimension::k2d, type::ImageFormat::kR32Uint, subtype);
Global("test_var", type, ast::StorageClass::kNone); Global("test_var", type, ast::StorageClass::kInput);
auto* ac = create<type::AccessControl>(ast::AccessControl::kWriteOnly, type); auto* ac = create<type::AccessControl>(ast::AccessControl::kWriteOnly, type);
@ -575,7 +560,7 @@ TEST_F(BuilderTest, GlobalVar_TextureStorageWithDifferentAccess) {
auto* st = create<type::StorageTexture>(type::TextureDimension::k2d, auto* st = create<type::StorageTexture>(type::TextureDimension::k2d,
type::ImageFormat::kR32Uint, subtype); type::ImageFormat::kR32Uint, subtype);
Global("test_var", st, ast::StorageClass::kNone); Global("test_var", st, ast::StorageClass::kInput);
auto* type_a = create<type::AccessControl>(ast::AccessControl::kReadOnly, st); auto* type_a = create<type::AccessControl>(ast::AccessControl::kReadOnly, st);
auto* var_a = Global("a", type_a, ast::StorageClass::kUniformConstant); auto* var_a = Global("a", type_a, ast::StorageClass::kUniformConstant);

View File

@ -373,9 +373,9 @@ TEST_F(IntrinsicBuilderTest, Call_TextureSampleCompare_Twice) {
type::Sampler s(type::SamplerKind::kComparisonSampler); type::Sampler s(type::SamplerKind::kComparisonSampler);
type::DepthTexture t(type::TextureDimension::k2d); type::DepthTexture t(type::TextureDimension::k2d);
auto* tex = Global("texture", &t, ast::StorageClass::kNone); auto* tex = Global("texture", &t, ast::StorageClass::kInput);
auto* sampler = Global("sampler", &s, ast::StorageClass::kNone); auto* sampler = Global("sampler", &s, ast::StorageClass::kInput);
auto* expr1 = Call("textureSampleCompare", "texture", "sampler", auto* expr1 = Call("textureSampleCompare", "texture", "sampler",
vec2<f32>(1.0f, 2.0f), 2.0f); vec2<f32>(1.0f, 2.0f), 2.0f);
@ -397,11 +397,11 @@ TEST_F(IntrinsicBuilderTest, Call_TextureSampleCompare_Twice) {
EXPECT_EQ(DumpInstructions(b.types()), R"(%4 = OpTypeFloat 32 EXPECT_EQ(DumpInstructions(b.types()), R"(%4 = OpTypeFloat 32
%3 = OpTypeImage %4 2D 1 0 0 1 Unknown %3 = OpTypeImage %4 2D 1 0 0 1 Unknown
%2 = OpTypePointer Private %3 %2 = OpTypePointer Input %3
%1 = OpVariable %2 Private %1 = OpVariable %2 Input
%7 = OpTypeSampler %7 = OpTypeSampler
%6 = OpTypePointer Private %7 %6 = OpTypePointer Input %7
%5 = OpVariable %6 Private %5 = OpVariable %6 Input
%11 = OpTypeSampledImage %3 %11 = OpTypeSampledImage %3
%13 = OpTypeVector %4 2 %13 = OpTypeVector %4 2
%14 = OpConstant %4 1 %14 = OpConstant %4 1

View File

@ -3646,8 +3646,6 @@ TEST_P(IntrinsicTextureTest, OutsideFunction_IsError) {
auto* texture = param.buildTextureVariable(this); auto* texture = param.buildTextureVariable(this);
auto* sampler = param.buildSamplerVariable(this); auto* sampler = param.buildSamplerVariable(this);
AST().AddGlobalVariable(texture);
AST().AddGlobalVariable(sampler);
auto* call = auto* call =
create<ast::CallExpression>(Expr(param.function), param.args(this)); create<ast::CallExpression>(Expr(param.function), param.args(this));

View File

@ -832,7 +832,7 @@ TEST_F(BuilderTest_Type, StorageTexture_Generate_1d_R16Float) {
auto* s = create<type::StorageTexture>(type::TextureDimension::k1d, auto* s = create<type::StorageTexture>(type::TextureDimension::k1d,
type::ImageFormat::kR16Float, subtype); type::ImageFormat::kR16Float, subtype);
Global("test_var", s, ast::StorageClass::kNone); Global("test_var", s, ast::StorageClass::kInput);
spirv::Builder& b = Build(); spirv::Builder& b = Build();
@ -854,7 +854,7 @@ TEST_F(BuilderTest_Type, StorageTexture_Generate_1d_R8SNorm) {
auto* s = create<type::StorageTexture>(type::TextureDimension::k1d, auto* s = create<type::StorageTexture>(type::TextureDimension::k1d,
type::ImageFormat::kR8Snorm, subtype); type::ImageFormat::kR8Snorm, subtype);
Global("test_var", s, ast::StorageClass::kNone); Global("test_var", s, ast::StorageClass::kInput);
spirv::Builder& b = Build(); spirv::Builder& b = Build();
@ -876,7 +876,7 @@ TEST_F(BuilderTest_Type, StorageTexture_Generate_1d_R8UNorm) {
auto* s = create<type::StorageTexture>(type::TextureDimension::k1d, auto* s = create<type::StorageTexture>(type::TextureDimension::k1d,
type::ImageFormat::kR8Unorm, subtype); type::ImageFormat::kR8Unorm, subtype);
Global("test_var", s, ast::StorageClass::kNone); Global("test_var", s, ast::StorageClass::kInput);
spirv::Builder& b = Build(); spirv::Builder& b = Build();
@ -898,7 +898,7 @@ TEST_F(BuilderTest_Type, StorageTexture_Generate_1d_R8Uint) {
auto* s = create<type::StorageTexture>(type::TextureDimension::k1d, auto* s = create<type::StorageTexture>(type::TextureDimension::k1d,
type::ImageFormat::kR8Uint, subtype); type::ImageFormat::kR8Uint, subtype);
Global("test_var", s, ast::StorageClass::kNone); Global("test_var", s, ast::StorageClass::kInput);
spirv::Builder& b = Build(); spirv::Builder& b = Build();
@ -915,7 +915,7 @@ TEST_F(BuilderTest_Type, StorageTexture_Generate_1d_R8Sint) {
auto* s = create<type::StorageTexture>(type::TextureDimension::k1d, auto* s = create<type::StorageTexture>(type::TextureDimension::k1d,
type::ImageFormat::kR8Sint, subtype); type::ImageFormat::kR8Sint, subtype);
Global("test_var", s, ast::StorageClass::kNone); Global("test_var", s, ast::StorageClass::kInput);
spirv::Builder& b = Build(); spirv::Builder& b = Build();
@ -932,7 +932,7 @@ TEST_F(BuilderTest_Type, StorageTexture_Generate_2d) {
auto* s = create<type::StorageTexture>(type::TextureDimension::k2d, auto* s = create<type::StorageTexture>(type::TextureDimension::k2d,
type::ImageFormat::kR16Float, subtype); type::ImageFormat::kR16Float, subtype);
Global("test_var", s, ast::StorageClass::kNone); Global("test_var", s, ast::StorageClass::kInput);
spirv::Builder& b = Build(); spirv::Builder& b = Build();
@ -949,7 +949,7 @@ TEST_F(BuilderTest_Type, StorageTexture_Generate_2dArray) {
auto* s = create<type::StorageTexture>(type::TextureDimension::k2dArray, auto* s = create<type::StorageTexture>(type::TextureDimension::k2dArray,
type::ImageFormat::kR16Float, subtype); type::ImageFormat::kR16Float, subtype);
Global("test_var", s, ast::StorageClass::kNone); Global("test_var", s, ast::StorageClass::kInput);
spirv::Builder& b = Build(); spirv::Builder& b = Build();
@ -966,7 +966,7 @@ TEST_F(BuilderTest_Type, StorageTexture_Generate_3d) {
auto* s = create<type::StorageTexture>(type::TextureDimension::k3d, auto* s = create<type::StorageTexture>(type::TextureDimension::k3d,
type::ImageFormat::kR16Float, subtype); type::ImageFormat::kR16Float, subtype);
Global("test_var", s, ast::StorageClass::kNone); Global("test_var", s, ast::StorageClass::kInput);
spirv::Builder& b = Build(); spirv::Builder& b = Build();
@ -984,7 +984,7 @@ TEST_F(BuilderTest_Type,
auto* s = create<type::StorageTexture>(type::TextureDimension::k2d, auto* s = create<type::StorageTexture>(type::TextureDimension::k2d,
type::ImageFormat::kR32Float, subtype); type::ImageFormat::kR32Float, subtype);
Global("test_var", s, ast::StorageClass::kNone); Global("test_var", s, ast::StorageClass::kInput);
spirv::Builder& b = Build(); spirv::Builder& b = Build();
@ -1002,7 +1002,7 @@ TEST_F(BuilderTest_Type,
auto* s = create<type::StorageTexture>(type::TextureDimension::k2d, auto* s = create<type::StorageTexture>(type::TextureDimension::k2d,
type::ImageFormat::kR32Sint, subtype); type::ImageFormat::kR32Sint, subtype);
Global("test_var", s, ast::StorageClass::kNone); Global("test_var", s, ast::StorageClass::kInput);
spirv::Builder& b = Build(); spirv::Builder& b = Build();
@ -1020,7 +1020,7 @@ TEST_F(BuilderTest_Type,
auto* s = create<type::StorageTexture>(type::TextureDimension::k2d, auto* s = create<type::StorageTexture>(type::TextureDimension::k2d,
type::ImageFormat::kR32Uint, subtype); type::ImageFormat::kR32Uint, subtype);
Global("test_var", s, ast::StorageClass::kNone); Global("test_var", s, ast::StorageClass::kInput);
spirv::Builder& b = Build(); spirv::Builder& b = Build();

View File

@ -46,7 +46,7 @@ using WgslBuiltinConversionTest = TestParamHelper<WgslBuiltinData>;
TEST_P(WgslBuiltinConversionTest, Emit) { TEST_P(WgslBuiltinConversionTest, Emit) {
auto params = GetParam(); auto params = GetParam();
auto* var = Global("a", ty.f32(), ast::StorageClass::kNone, nullptr, auto* var = Global("a", ty.f32(), ast::StorageClass::kInput, nullptr,
ast::DecorationList{ ast::DecorationList{
create<ast::BuiltinDecoration>(params.builtin), create<ast::BuiltinDecoration>(params.builtin),
}); });

View File

@ -25,7 +25,7 @@ namespace {
using WgslGeneratorImplTest = TestHelper; using WgslGeneratorImplTest = TestHelper;
TEST_F(WgslGeneratorImplTest, Emit_VariableDeclStatement) { TEST_F(WgslGeneratorImplTest, Emit_VariableDeclStatement) {
auto* var = Global("a", ty.f32(), ast::StorageClass::kNone); auto* var = Global("a", ty.f32(), ast::StorageClass::kInput);
auto* stmt = create<ast::VariableDeclStatement>(var); auto* stmt = create<ast::VariableDeclStatement>(var);
WrapInFunction(stmt); WrapInFunction(stmt);
@ -35,7 +35,7 @@ TEST_F(WgslGeneratorImplTest, Emit_VariableDeclStatement) {
gen.increment_indent(); gen.increment_indent();
ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.error(); ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.error();
EXPECT_EQ(gen.result(), " var a : f32;\n"); EXPECT_EQ(gen.result(), " var<in> a : f32;\n");
} }
TEST_F(WgslGeneratorImplTest, Emit_VariableDeclStatement_Function) { TEST_F(WgslGeneratorImplTest, Emit_VariableDeclStatement_Function) {

View File

@ -23,12 +23,12 @@ namespace {
using WgslGeneratorImplTest = TestHelper; using WgslGeneratorImplTest = TestHelper;
TEST_F(WgslGeneratorImplTest, EmitVariable) { TEST_F(WgslGeneratorImplTest, EmitVariable) {
auto* v = Global("a", ty.f32(), ast::StorageClass::kNone); auto* v = Global("a", ty.f32(), ast::StorageClass::kInput);
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitVariable(v)) << gen.error(); ASSERT_TRUE(gen.EmitVariable(v)) << gen.error();
EXPECT_EQ(gen.result(), R"(var a : f32; EXPECT_EQ(gen.result(), R"(var<in> a : f32;
)"); )");
} }
@ -43,7 +43,7 @@ TEST_F(WgslGeneratorImplTest, EmitVariable_StorageClass) {
} }
TEST_F(WgslGeneratorImplTest, EmitVariable_Decorated) { TEST_F(WgslGeneratorImplTest, EmitVariable_Decorated) {
auto* v = Global("a", ty.f32(), ast::StorageClass::kNone, nullptr, auto* v = Global("a", ty.f32(), ast::StorageClass::kInput, nullptr,
ast::DecorationList{ ast::DecorationList{
create<ast::LocationDecoration>(2), create<ast::LocationDecoration>(2),
}); });
@ -51,12 +51,12 @@ TEST_F(WgslGeneratorImplTest, EmitVariable_Decorated) {
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitVariable(v)) << gen.error(); ASSERT_TRUE(gen.EmitVariable(v)) << gen.error();
EXPECT_EQ(gen.result(), R"([[location(2)]] var a : f32; EXPECT_EQ(gen.result(), R"([[location(2)]] var<in> a : f32;
)"); )");
} }
TEST_F(WgslGeneratorImplTest, EmitVariable_Decorated_Multiple) { TEST_F(WgslGeneratorImplTest, EmitVariable_Decorated_Multiple) {
auto* v = Global("a", ty.f32(), ast::StorageClass::kNone, nullptr, auto* v = Global("a", ty.f32(), ast::StorageClass::kInput, nullptr,
ast::DecorationList{ ast::DecorationList{
create<ast::BuiltinDecoration>(ast::Builtin::kPosition), create<ast::BuiltinDecoration>(ast::Builtin::kPosition),
create<ast::BindingDecoration>(0), create<ast::BindingDecoration>(0),
@ -70,18 +70,18 @@ TEST_F(WgslGeneratorImplTest, EmitVariable_Decorated_Multiple) {
ASSERT_TRUE(gen.EmitVariable(v)) << gen.error(); ASSERT_TRUE(gen.EmitVariable(v)) << gen.error();
EXPECT_EQ( EXPECT_EQ(
gen.result(), gen.result(),
R"([[builtin(position), binding(0), group(1), location(2), constant_id(42)]] var a : f32; R"([[builtin(position), binding(0), group(1), location(2), constant_id(42)]] var<in> a : f32;
)"); )");
} }
TEST_F(WgslGeneratorImplTest, EmitVariable_Constructor) { TEST_F(WgslGeneratorImplTest, EmitVariable_Constructor) {
auto* v = Global("a", ty.f32(), ast::StorageClass::kNone, Expr(1.0f)); auto* v = Global("a", ty.f32(), ast::StorageClass::kInput, Expr(1.0f));
WrapInFunction(Decl(v)); WrapInFunction(Decl(v));
GeneratorImpl& gen = Build(); GeneratorImpl& gen = Build();
ASSERT_TRUE(gen.EmitVariable(v)) << gen.error(); ASSERT_TRUE(gen.EmitVariable(v)) << gen.error();
EXPECT_EQ(gen.result(), R"(var a : f32 = 1.0; EXPECT_EQ(gen.result(), R"(var<in> a : f32 = 1.0;
)"); )");
} }