blob: 07e8f3d08d166dde9404a0a7e31bd8d5b74f8ff5 [file] [log] [blame]
Ben Clayton17735352021-04-16 09:26:14 +00001// Copyright 2021 The Tint Authors.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include "src/resolver/resolver.h"
16
17#include "gmock/gmock.h"
Ben Claytona996ffb2022-02-02 23:07:11 +000018#include "src/ast/struct_block_attribute.h"
Ben Clayton17735352021-04-16 09:26:14 +000019#include "src/resolver/resolver_test_helper.h"
Antonio Maiorano5cd71b82021-04-16 19:07:51 +000020#include "src/sem/struct.h"
Ben Clayton17735352021-04-16 09:26:14 +000021
22namespace tint {
23namespace resolver {
24namespace {
25
26using ResolverStorageClassValidationTest = ResolverTest;
27
28TEST_F(ResolverStorageClassValidationTest, GlobalVariableNoStorageClass_Fail) {
29 // var g : f32;
30 Global(Source{{12, 34}}, "g", ty.f32(), ast::StorageClass::kNone);
31
32 EXPECT_FALSE(r()->Resolve());
33 EXPECT_EQ(r()->error(),
Ben Clayton5a88ec82021-06-29 14:42:19 +000034 "12:34 error: global variables must have a storage class");
Ben Clayton17735352021-04-16 09:26:14 +000035}
36
James Price13c79be2022-01-12 20:51:36 +000037TEST_F(ResolverStorageClassValidationTest,
38 GlobalVariableFunctionStorageClass_Fail) {
39 // var<function> g : f32;
40 Global(Source{{12, 34}}, "g", ty.f32(), ast::StorageClass::kFunction);
41
42 EXPECT_FALSE(r()->Resolve());
43 EXPECT_EQ(r()->error(),
44 "12:34 error: variables declared at module scope must not be in "
45 "the function storage class");
46}
47
James Pricedb2f5fc2022-01-12 20:51:36 +000048TEST_F(ResolverStorageClassValidationTest, Private_RuntimeArray) {
49 Global(Source{{12, 34}}, "v", ty.array(ty.i32()),
50 ast::StorageClass::kPrivate);
51
52 EXPECT_FALSE(r()->Resolve());
53 EXPECT_EQ(
54 r()->error(),
55 R"(12:34 error: runtime-sized arrays can only be used in the <storage> storage class
5612:34 note: while instantiating variable v)");
57}
58
59TEST_F(ResolverStorageClassValidationTest, Private_RuntimeArrayInStruct) {
60 auto* s = Structure("S", {Member("m", ty.array(ty.i32()))}, {StructBlock()});
61 Global(Source{{12, 34}}, "v", ty.Of(s), ast::StorageClass::kPrivate);
62
63 EXPECT_FALSE(r()->Resolve());
64 EXPECT_EQ(
65 r()->error(),
66 R"(12:34 error: runtime-sized arrays can only be used in the <storage> storage class
67note: while analysing structure member S.m
6812:34 note: while instantiating variable v)");
69}
70
71TEST_F(ResolverStorageClassValidationTest, Workgroup_RuntimeArray) {
72 Global(Source{{12, 34}}, "v", ty.array(ty.i32()),
73 ast::StorageClass::kWorkgroup);
74
75 EXPECT_FALSE(r()->Resolve());
76 EXPECT_EQ(
77 r()->error(),
78 R"(12:34 error: runtime-sized arrays can only be used in the <storage> storage class
7912:34 note: while instantiating variable v)");
80}
81
82TEST_F(ResolverStorageClassValidationTest, Workgroup_RuntimeArrayInStruct) {
83 auto* s = Structure("S", {Member("m", ty.array(ty.i32()))}, {StructBlock()});
84 Global(Source{{12, 34}}, "v", ty.Of(s), ast::StorageClass::kWorkgroup);
85
86 EXPECT_FALSE(r()->Resolve());
87 EXPECT_EQ(
88 r()->error(),
89 R"(12:34 error: runtime-sized arrays can only be used in the <storage> storage class
90note: while analysing structure member S.m
9112:34 note: while instantiating variable v)");
92}
93
Ben Clayton85bfea62021-04-19 20:20:33 +000094TEST_F(ResolverStorageClassValidationTest, StorageBufferBool) {
James Price7395e292022-01-19 15:55:56 +000095 // var<storage> g : bool;
96 Global(Source{{56, 78}}, "g", ty.bool_(), ast::StorageClass::kStorage,
Ben Claytona996ffb2022-02-02 23:07:11 +000097 ast::AttributeList{
98 create<ast::BindingAttribute>(0),
99 create<ast::GroupAttribute>(0),
James Price7395e292022-01-19 15:55:56 +0000100 });
101
102 ASSERT_FALSE(r()->Resolve());
103
104 EXPECT_EQ(
105 r()->error(),
106 R"(56:78 error: Type 'bool' cannot be used in storage class 'storage' as it is non-host-shareable
10756:78 note: while instantiating variable g)");
108}
109
110TEST_F(ResolverStorageClassValidationTest, StorageBufferPointer) {
111 // var<storage> g : ptr<private, f32>;
112 Global(Source{{56, 78}}, "g",
113 ty.pointer(ty.f32(), ast::StorageClass::kPrivate),
114 ast::StorageClass::kStorage,
Ben Claytona996ffb2022-02-02 23:07:11 +0000115 ast::AttributeList{
116 create<ast::BindingAttribute>(0),
117 create<ast::GroupAttribute>(0),
James Price7395e292022-01-19 15:55:56 +0000118 });
119
120 ASSERT_FALSE(r()->Resolve());
121
122 EXPECT_EQ(
123 r()->error(),
124 R"(56:78 error: Type 'ptr<private, f32, read_write>' cannot be used in storage class 'storage' as it is non-host-shareable
12556:78 note: while instantiating variable g)");
126}
127
128TEST_F(ResolverStorageClassValidationTest, StorageBufferIntScalar) {
Ben Clayton3f968e72021-05-10 19:16:46 +0000129 // var<storage> g : i32;
Ben Clayton620d77e2021-06-04 19:55:08 +0000130 Global(Source{{56, 78}}, "g", ty.i32(), ast::StorageClass::kStorage,
Ben Claytona996ffb2022-02-02 23:07:11 +0000131 ast::AttributeList{
132 create<ast::BindingAttribute>(0),
133 create<ast::GroupAttribute>(0),
Ben Clayton3f968e72021-05-10 19:16:46 +0000134 });
Ben Clayton17735352021-04-16 09:26:14 +0000135
James Price7395e292022-01-19 15:55:56 +0000136 ASSERT_TRUE(r()->Resolve()) << r()->error();
Ben Clayton17735352021-04-16 09:26:14 +0000137}
138
James Price7395e292022-01-19 15:55:56 +0000139TEST_F(ResolverStorageClassValidationTest, StorageBufferVector) {
James Price14c0b8a2021-06-24 15:53:26 +0000140 // var<storage> g : vec4<f32>;
141 Global(Source{{56, 78}}, "g", ty.vec4<f32>(), ast::StorageClass::kStorage,
Ben Claytona996ffb2022-02-02 23:07:11 +0000142 ast::AttributeList{
143 create<ast::BindingAttribute>(0),
144 create<ast::GroupAttribute>(0),
Ben Clayton3f968e72021-05-10 19:16:46 +0000145 });
Ben Clayton17735352021-04-16 09:26:14 +0000146
James Price7395e292022-01-19 15:55:56 +0000147 ASSERT_TRUE(r()->Resolve()) << r()->error();
Ben Clayton17735352021-04-16 09:26:14 +0000148}
149
Ben Clayton85bfea62021-04-19 20:20:33 +0000150TEST_F(ResolverStorageClassValidationTest, StorageBufferArray) {
Ben Clayton93e8f522021-06-04 20:41:47 +0000151 // var<storage, read> g : array<S, 3>;
Ben Claytonba6ab5e2021-05-07 14:49:34 +0000152 auto* s = Structure("S", {Member("a", ty.f32())});
Ben Clayton8758f102021-06-09 14:32:14 +0000153 auto* a = ty.array(ty.Of(s), 3);
Ben Clayton93e8f522021-06-04 20:41:47 +0000154 Global(Source{{56, 78}}, "g", a, ast::StorageClass::kStorage,
155 ast::Access::kRead,
Ben Claytona996ffb2022-02-02 23:07:11 +0000156 ast::AttributeList{
157 create<ast::BindingAttribute>(0),
158 create<ast::GroupAttribute>(0),
Ben Clayton3f968e72021-05-10 19:16:46 +0000159 });
Ben Clayton17735352021-04-16 09:26:14 +0000160
James Price7395e292022-01-19 15:55:56 +0000161 ASSERT_TRUE(r()->Resolve()) << r()->error();
Ben Clayton17735352021-04-16 09:26:14 +0000162}
163
Ben Clayton85bfea62021-04-19 20:20:33 +0000164TEST_F(ResolverStorageClassValidationTest, StorageBufferBoolAlias) {
Ben Clayton17735352021-04-16 09:26:14 +0000165 // type a = bool;
Ben Clayton93e8f522021-06-04 20:41:47 +0000166 // var<storage, read> g : a;
Ben Clayton6e7d24d2021-06-09 14:32:14 +0000167 auto* a = Alias("a", ty.bool_());
Ben Clayton8758f102021-06-09 14:32:14 +0000168 Global(Source{{56, 78}}, "g", ty.Of(a), ast::StorageClass::kStorage,
Ben Claytona996ffb2022-02-02 23:07:11 +0000169 ast::AttributeList{
170 create<ast::BindingAttribute>(0),
171 create<ast::GroupAttribute>(0),
Ben Clayton3f968e72021-05-10 19:16:46 +0000172 });
Ben Clayton17735352021-04-16 09:26:14 +0000173
174 ASSERT_FALSE(r()->Resolve());
175
176 EXPECT_EQ(
177 r()->error(),
Ben Claytona9156ff2021-11-05 16:51:38 +0000178 R"(56:78 error: Type 'bool' cannot be used in storage class 'storage' as it is non-host-shareable
17956:78 note: while instantiating variable g)");
Ben Clayton17735352021-04-16 09:26:14 +0000180}
181
Sarah085dcbb2021-07-28 09:59:35 +0000182TEST_F(ResolverStorageClassValidationTest, NotStorage_AccessMode) {
183 // var<private, read> g : a;
184 Global(Source{{56, 78}}, "g", ty.i32(), ast::StorageClass::kPrivate,
185 ast::Access::kRead);
186
187 ASSERT_FALSE(r()->Resolve());
188
189 EXPECT_EQ(
190 r()->error(),
Sarah4038fa72021-08-05 15:18:29 +0000191 R"(56:78 error: only variables in <storage> storage class may declare an access mode)");
Sarah085dcbb2021-07-28 09:59:35 +0000192}
193
Ben Clayton85bfea62021-04-19 20:20:33 +0000194TEST_F(ResolverStorageClassValidationTest, StorageBufferNoError_Basic) {
195 // [[block]] struct S { x : i32 };
Ben Clayton93e8f522021-06-04 20:41:47 +0000196 // var<storage, read> g : S;
Ben Claytonba6ab5e2021-05-07 14:49:34 +0000197 auto* s = Structure("S", {Member(Source{{12, 34}}, "x", ty.i32())},
Ben Claytona996ffb2022-02-02 23:07:11 +0000198 {create<ast::StructBlockAttribute>()});
Ben Clayton8758f102021-06-09 14:32:14 +0000199 Global(Source{{56, 78}}, "g", ty.Of(s), ast::StorageClass::kStorage,
Ben Clayton93e8f522021-06-04 20:41:47 +0000200 ast::Access::kRead,
Ben Claytona996ffb2022-02-02 23:07:11 +0000201 ast::AttributeList{
202 create<ast::BindingAttribute>(0),
203 create<ast::GroupAttribute>(0),
Ben Clayton3f968e72021-05-10 19:16:46 +0000204 });
Ben Clayton17735352021-04-16 09:26:14 +0000205
206 ASSERT_TRUE(r()->Resolve());
207}
208
Ben Clayton85bfea62021-04-19 20:20:33 +0000209TEST_F(ResolverStorageClassValidationTest, StorageBufferNoError_Aliases) {
210 // [[block]] struct S { x : i32 };
Ben Clayton17735352021-04-16 09:26:14 +0000211 // type a1 = S;
Ben Clayton93e8f522021-06-04 20:41:47 +0000212 // var<storage, read> g : a1;
Ben Claytonba6ab5e2021-05-07 14:49:34 +0000213 auto* s = Structure("S", {Member(Source{{12, 34}}, "x", ty.i32())},
Ben Claytona996ffb2022-02-02 23:07:11 +0000214 {create<ast::StructBlockAttribute>()});
Ben Clayton8758f102021-06-09 14:32:14 +0000215 auto* a1 = Alias("a1", ty.Of(s));
216 auto* a2 = Alias("a2", ty.Of(a1));
217 Global(Source{{56, 78}}, "g", ty.Of(a2), ast::StorageClass::kStorage,
Ben Clayton93e8f522021-06-04 20:41:47 +0000218 ast::Access::kRead,
Ben Claytona996ffb2022-02-02 23:07:11 +0000219 ast::AttributeList{
220 create<ast::BindingAttribute>(0),
221 create<ast::GroupAttribute>(0),
Ben Clayton3f968e72021-05-10 19:16:46 +0000222 });
Ben Clayton17735352021-04-16 09:26:14 +0000223
224 ASSERT_TRUE(r()->Resolve());
225}
226
Sarah52b6a002021-06-16 19:40:13 +0000227TEST_F(ResolverStorageClassValidationTest, UniformBuffer_Struct_Runtime) {
228 // [[block]] struct S { m: array<f32>; };
Ben Clayton01e4b6f2022-01-19 22:46:57 +0000229 // @group(0) @binding(0) var<uniform, > svar : S;
Sarah52b6a002021-06-16 19:40:13 +0000230
231 auto* s = Structure(Source{{12, 34}}, "S", {Member("m", ty.array<i32>())},
Ben Claytona996ffb2022-02-02 23:07:11 +0000232 {create<ast::StructBlockAttribute>()});
Sarah52b6a002021-06-16 19:40:13 +0000233
234 Global(Source{{56, 78}}, "svar", ty.Of(s), ast::StorageClass::kUniform,
Ben Claytona996ffb2022-02-02 23:07:11 +0000235 ast::AttributeList{
236 create<ast::BindingAttribute>(0),
237 create<ast::GroupAttribute>(0),
Sarah52b6a002021-06-16 19:40:13 +0000238 });
239
240 ASSERT_FALSE(r()->Resolve());
James Pricedb2f5fc2022-01-12 20:51:36 +0000241 EXPECT_EQ(
242 r()->error(),
243 R"(56:78 error: runtime-sized arrays can only be used in the <storage> storage class
244note: while analysing structure member S.m
24556:78 note: while instantiating variable svar)");
Sarah52b6a002021-06-16 19:40:13 +0000246}
Ben Clayton42708342021-04-21 17:55:12 +0000247
248TEST_F(ResolverStorageClassValidationTest, UniformBufferBool) {
249 // var<uniform> g : bool;
Ben Clayton3f968e72021-05-10 19:16:46 +0000250 Global(Source{{56, 78}}, "g", ty.bool_(), ast::StorageClass::kUniform,
Ben Claytona996ffb2022-02-02 23:07:11 +0000251 ast::AttributeList{
252 create<ast::BindingAttribute>(0),
253 create<ast::GroupAttribute>(0),
Ben Clayton3f968e72021-05-10 19:16:46 +0000254 });
Ben Clayton42708342021-04-21 17:55:12 +0000255
256 ASSERT_FALSE(r()->Resolve());
257
258 EXPECT_EQ(
259 r()->error(),
Ben Claytona9156ff2021-11-05 16:51:38 +0000260 R"(56:78 error: Type 'bool' cannot be used in storage class 'uniform' as it is non-host-shareable
26156:78 note: while instantiating variable g)");
Ben Clayton42708342021-04-21 17:55:12 +0000262}
263
264TEST_F(ResolverStorageClassValidationTest, UniformBufferPointer) {
James Price7395e292022-01-19 15:55:56 +0000265 // var<uniform> g : ptr<private, f32>;
266 Global(Source{{56, 78}}, "g",
267 ty.pointer(ty.f32(), ast::StorageClass::kPrivate),
268 ast::StorageClass::kUniform,
Ben Claytona996ffb2022-02-02 23:07:11 +0000269 ast::AttributeList{
270 create<ast::BindingAttribute>(0),
271 create<ast::GroupAttribute>(0),
Ben Clayton3f968e72021-05-10 19:16:46 +0000272 });
Ben Clayton42708342021-04-21 17:55:12 +0000273
274 ASSERT_FALSE(r()->Resolve());
275
276 EXPECT_EQ(
277 r()->error(),
James Price7395e292022-01-19 15:55:56 +0000278 R"(56:78 error: Type 'ptr<private, f32, read_write>' cannot be used in storage class 'uniform' as it is non-host-shareable
27956:78 note: while instantiating variable g)");
280}
281
282TEST_F(ResolverStorageClassValidationTest, UniformBufferIntScalar) {
283 // var<uniform> g : i32;
284 Global(Source{{56, 78}}, "g", ty.i32(), ast::StorageClass::kUniform,
Ben Claytona996ffb2022-02-02 23:07:11 +0000285 ast::AttributeList{
286 create<ast::BindingAttribute>(0),
287 create<ast::GroupAttribute>(0),
James Price7395e292022-01-19 15:55:56 +0000288 });
289
290 ASSERT_TRUE(r()->Resolve()) << r()->error();
291}
292
293TEST_F(ResolverStorageClassValidationTest, UniformBufferVector) {
294 // var<uniform> g : vec4<f32>;
295 Global(Source{{56, 78}}, "g", ty.vec4<f32>(), ast::StorageClass::kUniform,
Ben Claytona996ffb2022-02-02 23:07:11 +0000296 ast::AttributeList{
297 create<ast::BindingAttribute>(0),
298 create<ast::GroupAttribute>(0),
James Price7395e292022-01-19 15:55:56 +0000299 });
300
301 ASSERT_TRUE(r()->Resolve()) << r()->error();
Ben Clayton42708342021-04-21 17:55:12 +0000302}
303
304TEST_F(ResolverStorageClassValidationTest, UniformBufferArray) {
James Price533a1ba2022-01-20 22:11:07 +0000305 // struct S {
306 // @size(16) f : f32;
307 // }
Ben Clayton93e8f522021-06-04 20:41:47 +0000308 // var<uniform> g : array<S, 3>;
James Price533a1ba2022-01-20 22:11:07 +0000309 auto* s = Structure("S", {Member("a", ty.f32(), {MemberSize(16)})});
Ben Clayton8758f102021-06-09 14:32:14 +0000310 auto* a = ty.array(ty.Of(s), 3);
Ben Clayton93e8f522021-06-04 20:41:47 +0000311 Global(Source{{56, 78}}, "g", a, ast::StorageClass::kUniform,
Ben Claytona996ffb2022-02-02 23:07:11 +0000312 ast::AttributeList{
313 create<ast::BindingAttribute>(0),
314 create<ast::GroupAttribute>(0),
Ben Clayton3f968e72021-05-10 19:16:46 +0000315 });
Ben Clayton42708342021-04-21 17:55:12 +0000316
James Price7395e292022-01-19 15:55:56 +0000317 ASSERT_TRUE(r()->Resolve()) << r()->error();
Ben Clayton42708342021-04-21 17:55:12 +0000318}
319
320TEST_F(ResolverStorageClassValidationTest, UniformBufferBoolAlias) {
321 // type a = bool;
Ben Clayton93e8f522021-06-04 20:41:47 +0000322 // var<uniform> g : a;
Ben Clayton6e7d24d2021-06-09 14:32:14 +0000323 auto* a = Alias("a", ty.bool_());
Ben Clayton8758f102021-06-09 14:32:14 +0000324 Global(Source{{56, 78}}, "g", ty.Of(a), ast::StorageClass::kUniform,
Ben Claytona996ffb2022-02-02 23:07:11 +0000325 ast::AttributeList{
326 create<ast::BindingAttribute>(0),
327 create<ast::GroupAttribute>(0),
Ben Clayton3f968e72021-05-10 19:16:46 +0000328 });
Ben Clayton42708342021-04-21 17:55:12 +0000329
330 ASSERT_FALSE(r()->Resolve());
331
332 EXPECT_EQ(
333 r()->error(),
Ben Claytona9156ff2021-11-05 16:51:38 +0000334 R"(56:78 error: Type 'bool' cannot be used in storage class 'uniform' as it is non-host-shareable
33556:78 note: while instantiating variable g)");
Ben Clayton42708342021-04-21 17:55:12 +0000336}
337
Ben Clayton42708342021-04-21 17:55:12 +0000338TEST_F(ResolverStorageClassValidationTest, UniformBufferNoError_Basic) {
339 // [[block]] struct S { x : i32 };
340 // var<uniform> g : S;
Ben Claytonba6ab5e2021-05-07 14:49:34 +0000341 auto* s = Structure("S", {Member(Source{{12, 34}}, "x", ty.i32())},
Ben Claytona996ffb2022-02-02 23:07:11 +0000342 {create<ast::StructBlockAttribute>()});
Ben Clayton8758f102021-06-09 14:32:14 +0000343 Global(Source{{56, 78}}, "g", ty.Of(s), ast::StorageClass::kUniform,
Ben Claytona996ffb2022-02-02 23:07:11 +0000344 ast::AttributeList{
345 create<ast::BindingAttribute>(0),
346 create<ast::GroupAttribute>(0),
Ben Clayton3f968e72021-05-10 19:16:46 +0000347 });
Ben Clayton42708342021-04-21 17:55:12 +0000348
Antonio Maiorano60dae242021-07-15 19:09:25 +0000349 ASSERT_TRUE(r()->Resolve()) << r()->error();
Ben Clayton42708342021-04-21 17:55:12 +0000350}
351
352TEST_F(ResolverStorageClassValidationTest, UniformBufferNoError_Aliases) {
353 // [[block]] struct S { x : i32 };
354 // type a1 = S;
355 // var<uniform> g : a1;
Ben Claytonba6ab5e2021-05-07 14:49:34 +0000356 auto* s = Structure("S", {Member(Source{{12, 34}}, "x", ty.i32())},
Ben Claytona996ffb2022-02-02 23:07:11 +0000357 {create<ast::StructBlockAttribute>()});
Ben Clayton8758f102021-06-09 14:32:14 +0000358 auto* a1 = Alias("a1", ty.Of(s));
359 Global(Source{{56, 78}}, "g", ty.Of(a1), ast::StorageClass::kUniform,
Ben Claytona996ffb2022-02-02 23:07:11 +0000360 ast::AttributeList{
361 create<ast::BindingAttribute>(0),
362 create<ast::GroupAttribute>(0),
Ben Clayton3f968e72021-05-10 19:16:46 +0000363 });
Ben Clayton42708342021-04-21 17:55:12 +0000364
Antonio Maiorano60dae242021-07-15 19:09:25 +0000365 ASSERT_TRUE(r()->Resolve()) << r()->error();
Ben Clayton42708342021-04-21 17:55:12 +0000366}
367
Ben Clayton17735352021-04-16 09:26:14 +0000368} // namespace
369} // namespace resolver
370} // namespace tint