• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // 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"
18 #include "src/resolver/resolver_test_helper.h"
19 #include "src/sem/reference_type.h"
20 
21 namespace tint {
22 namespace resolver {
23 namespace {
24 
25 using ResolverIndexAccessorTest = ResolverTest;
26 
TEST_F(ResolverIndexAccessorTest,Matrix_Dynamic_F32)27 TEST_F(ResolverIndexAccessorTest, Matrix_Dynamic_F32) {
28   Global("my_var", ty.mat2x3<f32>(), ast::StorageClass::kPrivate);
29   auto* acc = IndexAccessor("my_var", Expr(Source{{12, 34}}, 1.0f));
30   WrapInFunction(acc);
31 
32   EXPECT_FALSE(r()->Resolve());
33   EXPECT_EQ(r()->error(),
34             "12:34 error: index must be of type 'i32' or 'u32', found: 'f32'");
35 }
36 
TEST_F(ResolverIndexAccessorTest,Matrix_Dynamic_Ref)37 TEST_F(ResolverIndexAccessorTest, Matrix_Dynamic_Ref) {
38   Global("my_var", ty.mat2x3<f32>(), ast::StorageClass::kPrivate);
39   auto* idx = Var("idx", ty.i32(), Construct(ty.i32()));
40   auto* acc = IndexAccessor("my_var", idx);
41   WrapInFunction(Decl(idx), acc);
42 
43   EXPECT_TRUE(r()->Resolve()) << r()->error();
44 }
45 
TEST_F(ResolverIndexAccessorTest,Matrix_BothDimensions_Dynamic_Ref)46 TEST_F(ResolverIndexAccessorTest, Matrix_BothDimensions_Dynamic_Ref) {
47   Global("my_var", ty.mat4x4<f32>(), ast::StorageClass::kPrivate);
48   auto* idx = Var("idx", ty.u32(), Expr(3u));
49   auto* idy = Var("idy", ty.u32(), Expr(2u));
50   auto* acc = IndexAccessor(IndexAccessor("my_var", idx), idy);
51   WrapInFunction(Decl(idx), Decl(idy), acc);
52 
53   EXPECT_TRUE(r()->Resolve()) << r()->error();
54 }
55 
TEST_F(ResolverIndexAccessorTest,Matrix_Dynamic)56 TEST_F(ResolverIndexAccessorTest, Matrix_Dynamic) {
57   GlobalConst("my_const", ty.mat2x3<f32>(), Construct(ty.mat2x3<f32>()));
58   auto* idx = Var("idx", ty.i32(), Construct(ty.i32()));
59   auto* acc = IndexAccessor("my_const", Expr(Source{{12, 34}}, idx));
60   WrapInFunction(Decl(idx), acc);
61 
62   EXPECT_FALSE(r()->Resolve());
63   EXPECT_EQ(r()->error(),
64             "12:34 error: index must be signed or unsigned integer literal");
65 }
66 
TEST_F(ResolverIndexAccessorTest,Matrix_XDimension_Dynamic)67 TEST_F(ResolverIndexAccessorTest, Matrix_XDimension_Dynamic) {
68   GlobalConst("my_var", ty.mat4x4<f32>(), Construct(ty.mat4x4<f32>()));
69   auto* idx = Var("idx", ty.u32(), Expr(3u));
70   auto* acc = IndexAccessor("my_var", Expr(Source{{12, 34}}, idx));
71   WrapInFunction(Decl(idx), acc);
72 
73   EXPECT_FALSE(r()->Resolve());
74   EXPECT_EQ(r()->error(),
75             "12:34 error: index must be signed or unsigned integer literal");
76 }
77 
TEST_F(ResolverIndexAccessorTest,Matrix_BothDimension_Dynamic)78 TEST_F(ResolverIndexAccessorTest, Matrix_BothDimension_Dynamic) {
79   GlobalConst("my_var", ty.mat4x4<f32>(), Construct(ty.mat4x4<f32>()));
80   auto* idx = Var("idy", ty.u32(), Expr(2u));
81   auto* acc =
82       IndexAccessor(IndexAccessor("my_var", Expr(Source{{12, 34}}, idx)), 1);
83   WrapInFunction(Decl(idx), acc);
84 
85   EXPECT_FALSE(r()->Resolve());
86   EXPECT_EQ(r()->error(),
87             "12:34 error: index must be signed or unsigned integer literal");
88 }
89 
TEST_F(ResolverIndexAccessorTest,Matrix)90 TEST_F(ResolverIndexAccessorTest, Matrix) {
91   Global("my_var", ty.mat2x3<f32>(), ast::StorageClass::kPrivate);
92 
93   auto* acc = IndexAccessor("my_var", 2);
94   WrapInFunction(acc);
95 
96   EXPECT_TRUE(r()->Resolve()) << r()->error();
97 
98   ASSERT_NE(TypeOf(acc), nullptr);
99   ASSERT_TRUE(TypeOf(acc)->Is<sem::Reference>());
100 
101   auto* ref = TypeOf(acc)->As<sem::Reference>();
102   ASSERT_TRUE(ref->StoreType()->Is<sem::Vector>());
103   EXPECT_EQ(ref->StoreType()->As<sem::Vector>()->Width(), 3u);
104 }
105 
TEST_F(ResolverIndexAccessorTest,Matrix_BothDimensions)106 TEST_F(ResolverIndexAccessorTest, Matrix_BothDimensions) {
107   Global("my_var", ty.mat2x3<f32>(), ast::StorageClass::kPrivate);
108 
109   auto* acc = IndexAccessor(IndexAccessor("my_var", 2), 1);
110   WrapInFunction(acc);
111 
112   EXPECT_TRUE(r()->Resolve()) << r()->error();
113 
114   ASSERT_NE(TypeOf(acc), nullptr);
115   ASSERT_TRUE(TypeOf(acc)->Is<sem::Reference>());
116 
117   auto* ref = TypeOf(acc)->As<sem::Reference>();
118   EXPECT_TRUE(ref->StoreType()->Is<sem::F32>());
119 }
120 
TEST_F(ResolverIndexAccessorTest,Vector_F32)121 TEST_F(ResolverIndexAccessorTest, Vector_F32) {
122   Global("my_var", ty.vec3<f32>(), ast::StorageClass::kPrivate);
123   auto* acc = IndexAccessor("my_var", Expr(Source{{12, 34}}, 2.0f));
124   WrapInFunction(acc);
125 
126   EXPECT_FALSE(r()->Resolve());
127   EXPECT_EQ(r()->error(),
128             "12:34 error: index must be of type 'i32' or 'u32', found: 'f32'");
129 }
130 
TEST_F(ResolverIndexAccessorTest,Vector_Dynamic_Ref)131 TEST_F(ResolverIndexAccessorTest, Vector_Dynamic_Ref) {
132   Global("my_var", ty.vec3<f32>(), ast::StorageClass::kPrivate);
133   auto* idx = Var("idx", ty.i32(), Expr(2));
134   auto* acc = IndexAccessor("my_var", idx);
135   WrapInFunction(Decl(idx), acc);
136 
137   EXPECT_TRUE(r()->Resolve());
138 }
139 
TEST_F(ResolverIndexAccessorTest,Vector_Dynamic)140 TEST_F(ResolverIndexAccessorTest, Vector_Dynamic) {
141   GlobalConst("my_var", ty.vec3<f32>(), Construct(ty.vec3<f32>()));
142   auto* idx = Var("idx", ty.i32(), Expr(2));
143   auto* acc = IndexAccessor("my_var", Expr(Source{{12, 34}}, idx));
144   WrapInFunction(Decl(idx), acc);
145 
146   EXPECT_TRUE(r()->Resolve());
147 }
148 
TEST_F(ResolverIndexAccessorTest,Vector)149 TEST_F(ResolverIndexAccessorTest, Vector) {
150   Global("my_var", ty.vec3<f32>(), ast::StorageClass::kPrivate);
151 
152   auto* acc = IndexAccessor("my_var", 2);
153   WrapInFunction(acc);
154 
155   EXPECT_TRUE(r()->Resolve()) << r()->error();
156 
157   ASSERT_NE(TypeOf(acc), nullptr);
158   ASSERT_TRUE(TypeOf(acc)->Is<sem::Reference>());
159 
160   auto* ref = TypeOf(acc)->As<sem::Reference>();
161   EXPECT_TRUE(ref->StoreType()->Is<sem::F32>());
162 }
163 
TEST_F(ResolverIndexAccessorTest,Array)164 TEST_F(ResolverIndexAccessorTest, Array) {
165   auto* idx = Expr(2);
166   Global("my_var", ty.array<f32, 3>(), ast::StorageClass::kPrivate);
167 
168   auto* acc = IndexAccessor("my_var", idx);
169   WrapInFunction(acc);
170 
171   EXPECT_TRUE(r()->Resolve()) << r()->error();
172 
173   ASSERT_NE(TypeOf(acc), nullptr);
174   ASSERT_TRUE(TypeOf(acc)->Is<sem::Reference>());
175 
176   auto* ref = TypeOf(acc)->As<sem::Reference>();
177   EXPECT_TRUE(ref->StoreType()->Is<sem::F32>());
178 }
179 
TEST_F(ResolverIndexAccessorTest,Alias_Array)180 TEST_F(ResolverIndexAccessorTest, Alias_Array) {
181   auto* aary = Alias("myarrty", ty.array<f32, 3>());
182 
183   Global("my_var", ty.Of(aary), ast::StorageClass::kPrivate);
184 
185   auto* acc = IndexAccessor("my_var", 2);
186   WrapInFunction(acc);
187 
188   EXPECT_TRUE(r()->Resolve()) << r()->error();
189 
190   ASSERT_NE(TypeOf(acc), nullptr);
191   ASSERT_TRUE(TypeOf(acc)->Is<sem::Reference>());
192 
193   auto* ref = TypeOf(acc)->As<sem::Reference>();
194   EXPECT_TRUE(ref->StoreType()->Is<sem::F32>());
195 }
196 
TEST_F(ResolverIndexAccessorTest,Array_Constant)197 TEST_F(ResolverIndexAccessorTest, Array_Constant) {
198   GlobalConst("my_var", ty.array<f32, 3>(), array<f32, 3>());
199 
200   auto* acc = IndexAccessor("my_var", 2);
201   WrapInFunction(acc);
202 
203   EXPECT_TRUE(r()->Resolve()) << r()->error();
204 
205   ASSERT_NE(TypeOf(acc), nullptr);
206   EXPECT_TRUE(TypeOf(acc)->Is<sem::F32>()) << TypeOf(acc)->type_name();
207 }
208 
TEST_F(ResolverIndexAccessorTest,Array_Dynamic_I32)209 TEST_F(ResolverIndexAccessorTest, Array_Dynamic_I32) {
210   // let a : array<f32, 3> = 0;
211   // var idx : i32 = 0;
212   // var f : f32 = a[idx];
213   auto* a = Const("a", ty.array<f32, 3>(), array<f32, 3>());
214   auto* idx = Var("idx", ty.i32(), Construct(ty.i32()));
215   auto* f = Var("f", ty.f32(), IndexAccessor("a", Expr(Source{{12, 34}}, idx)));
216   Func("my_func", ast::VariableList{}, ty.void_(),
217        {
218            Decl(a),
219            Decl(idx),
220            Decl(f),
221        },
222        ast::DecorationList{});
223 
224   EXPECT_FALSE(r()->Resolve());
225   EXPECT_EQ(r()->error(),
226             "12:34 error: index must be signed or unsigned integer literal");
227 }
228 
TEST_F(ResolverIndexAccessorTest,Array_Literal_F32)229 TEST_F(ResolverIndexAccessorTest, Array_Literal_F32) {
230   // let a : array<f32, 3>;
231   // var f : f32 = a[2.0f];
232   auto* a = Const("a", ty.array<f32, 3>(), array<f32, 3>());
233   auto* f =
234       Var("a_2", ty.f32(), IndexAccessor("a", Expr(Source{{12, 34}}, 2.0f)));
235   Func("my_func", ast::VariableList{}, ty.void_(),
236        {
237            Decl(a),
238            Decl(f),
239        },
240        ast::DecorationList{});
241   EXPECT_FALSE(r()->Resolve());
242   EXPECT_EQ(r()->error(),
243             "12:34 error: index must be of type 'i32' or 'u32', found: 'f32'");
244 }
245 
TEST_F(ResolverIndexAccessorTest,Array_Literal_I32)246 TEST_F(ResolverIndexAccessorTest, Array_Literal_I32) {
247   // let a : array<f32, 3>;
248   // var f : f32 = a[2];
249   auto* a = Const("a", ty.array<f32, 3>(), array<f32, 3>());
250   auto* f = Var("a_2", ty.f32(), IndexAccessor("a", 2));
251   Func("my_func", ast::VariableList{}, ty.void_(),
252        {
253            Decl(a),
254            Decl(f),
255        },
256        ast::DecorationList{});
257   EXPECT_TRUE(r()->Resolve()) << r()->error();
258 }
259 
TEST_F(ResolverIndexAccessorTest,EXpr_Deref_FuncGoodParent)260 TEST_F(ResolverIndexAccessorTest, EXpr_Deref_FuncGoodParent) {
261   // fn func(p: ptr<function, vec4<f32>>) -> f32 {
262   //     let idx: u32 = u32();
263   //     let x: f32 = (*p)[idx];
264   //     return x;
265   // }
266   auto* p =
267       Param("p", ty.pointer(ty.vec4<f32>(), ast::StorageClass::kFunction));
268   auto* idx = Const("idx", ty.u32(), Construct(ty.u32()));
269   auto* star_p = Deref(p);
270   auto* accessor_expr = IndexAccessor(Source{{12, 34}}, star_p, idx);
271   auto* x = Var("x", ty.f32(), accessor_expr);
272   Func("func", {p}, ty.f32(), {Decl(idx), Decl(x), Return(x)});
273 
274   EXPECT_TRUE(r()->Resolve()) << r()->error();
275 }
276 
TEST_F(ResolverIndexAccessorTest,EXpr_Deref_FuncBadParent)277 TEST_F(ResolverIndexAccessorTest, EXpr_Deref_FuncBadParent) {
278   // fn func(p: ptr<function, vec4<f32>>) -> f32 {
279   //     let idx: u32 = u32();
280   //     let x: f32 = *p[idx];
281   //     return x;
282   // }
283   auto* p =
284       Param("p", ty.pointer(ty.vec4<f32>(), ast::StorageClass::kFunction));
285   auto* idx = Const("idx", ty.u32(), Construct(ty.u32()));
286   auto* accessor_expr = IndexAccessor(Source{{12, 34}}, p, idx);
287   auto* star_p = Deref(accessor_expr);
288   auto* x = Var("x", ty.f32(), star_p);
289   Func("func", {p}, ty.f32(), {Decl(idx), Decl(x), Return(x)});
290 
291   EXPECT_FALSE(r()->Resolve());
292   EXPECT_EQ(
293       r()->error(),
294       "12:34 error: cannot index type 'ptr<function, vec4<f32>, read_write>'");
295 }
296 
TEST_F(ResolverIndexAccessorTest,Exr_Deref_BadParent)297 TEST_F(ResolverIndexAccessorTest, Exr_Deref_BadParent) {
298   // var param: vec4<f32>
299   // let x: f32 = *(&param)[0];
300   auto* param = Var("param", ty.vec4<f32>());
301   auto* idx = Var("idx", ty.u32(), Construct(ty.u32()));
302   auto* addressOf_expr = AddressOf(param);
303   auto* accessor_expr = IndexAccessor(Source{{12, 34}}, addressOf_expr, idx);
304   auto* star_p = Deref(accessor_expr);
305   auto* x = Var("x", ty.f32(), star_p);
306   WrapInFunction(param, idx, x);
307 
308   EXPECT_FALSE(r()->Resolve());
309   EXPECT_EQ(
310       r()->error(),
311       "12:34 error: cannot index type 'ptr<function, vec4<f32>, read_write>'");
312 }
313 
314 }  // namespace
315 }  // namespace resolver
316 }  // namespace tint
317