blob: d227ce4e309db995af518a6665b6efd2e1a36163 [file] [log] [blame]
Ryan Harrisondbc13af2022-02-21 15:19:07 +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/tint/resolver/resolver.h"
16
17#include "gmock/gmock.h"
18#include "src/tint/resolver/resolver_test_helper.h"
Ben Clayton01004b72022-04-28 18:49:04 +000019#include "src/tint/sem/reference.h"
Ryan Harrisondbc13af2022-02-21 15:19:07 +000020
dan sinclaird2093792022-04-07 17:45:45 +000021namespace tint::resolver {
Ryan Harrisondbc13af2022-02-21 15:19:07 +000022namespace {
23
24using ResolverIndexAccessorTest = ResolverTest;
25
26TEST_F(ResolverIndexAccessorTest, Matrix_Dynamic_F32) {
dan sinclair41e4d9a2022-05-01 14:40:55 +000027 Global("my_var", ty.mat2x3<f32>(), ast::StorageClass::kPrivate);
28 auto* acc = IndexAccessor("my_var", Expr(Source{{12, 34}}, 1.0f));
29 WrapInFunction(acc);
Ryan Harrisondbc13af2022-02-21 15:19:07 +000030
dan sinclair41e4d9a2022-05-01 14:40:55 +000031 EXPECT_FALSE(r()->Resolve());
32 EXPECT_EQ(r()->error(), "12:34 error: index must be of type 'i32' or 'u32', found: 'f32'");
Ryan Harrisondbc13af2022-02-21 15:19:07 +000033}
34
35TEST_F(ResolverIndexAccessorTest, Matrix_Dynamic_Ref) {
dan sinclair41e4d9a2022-05-01 14:40:55 +000036 Global("my_var", ty.mat2x3<f32>(), ast::StorageClass::kPrivate);
37 auto* idx = Var("idx", ty.i32(), Construct(ty.i32()));
38 auto* acc = IndexAccessor("my_var", idx);
39 WrapInFunction(Decl(idx), acc);
Ryan Harrisondbc13af2022-02-21 15:19:07 +000040
dan sinclair41e4d9a2022-05-01 14:40:55 +000041 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ryan Harrisondbc13af2022-02-21 15:19:07 +000042}
43
44TEST_F(ResolverIndexAccessorTest, Matrix_BothDimensions_Dynamic_Ref) {
dan sinclair41e4d9a2022-05-01 14:40:55 +000045 Global("my_var", ty.mat4x4<f32>(), ast::StorageClass::kPrivate);
46 auto* idx = Var("idx", ty.u32(), Expr(3u));
47 auto* idy = Var("idy", ty.u32(), Expr(2u));
48 auto* acc = IndexAccessor(IndexAccessor("my_var", idx), idy);
49 WrapInFunction(Decl(idx), Decl(idy), acc);
Ryan Harrisondbc13af2022-02-21 15:19:07 +000050
dan sinclair41e4d9a2022-05-01 14:40:55 +000051 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ryan Harrisondbc13af2022-02-21 15:19:07 +000052}
53
54TEST_F(ResolverIndexAccessorTest, Matrix_Dynamic) {
dan sinclair41e4d9a2022-05-01 14:40:55 +000055 GlobalConst("my_const", ty.mat2x3<f32>(), Construct(ty.mat2x3<f32>()));
56 auto* idx = Var("idx", ty.i32(), Construct(ty.i32()));
57 auto* acc = IndexAccessor("my_const", Expr(Source{{12, 34}}, idx));
58 WrapInFunction(Decl(idx), acc);
Ryan Harrisondbc13af2022-02-21 15:19:07 +000059
dan sinclair41e4d9a2022-05-01 14:40:55 +000060 EXPECT_TRUE(r()->Resolve());
61 EXPECT_EQ(r()->error(), "");
Ryan Harrisondbc13af2022-02-21 15:19:07 +000062}
63
64TEST_F(ResolverIndexAccessorTest, Matrix_XDimension_Dynamic) {
dan sinclair41e4d9a2022-05-01 14:40:55 +000065 GlobalConst("my_var", ty.mat4x4<f32>(), Construct(ty.mat4x4<f32>()));
66 auto* idx = Var("idx", ty.u32(), Expr(3u));
67 auto* acc = IndexAccessor("my_var", Expr(Source{{12, 34}}, idx));
68 WrapInFunction(Decl(idx), acc);
Ryan Harrisondbc13af2022-02-21 15:19:07 +000069
dan sinclair41e4d9a2022-05-01 14:40:55 +000070 EXPECT_TRUE(r()->Resolve());
71 EXPECT_EQ(r()->error(), "");
Ryan Harrisondbc13af2022-02-21 15:19:07 +000072}
73
74TEST_F(ResolverIndexAccessorTest, Matrix_BothDimension_Dynamic) {
dan sinclair41e4d9a2022-05-01 14:40:55 +000075 GlobalConst("my_var", ty.mat4x4<f32>(), Construct(ty.mat4x4<f32>()));
76 auto* idx = Var("idy", ty.u32(), Expr(2u));
77 auto* acc = IndexAccessor(IndexAccessor("my_var", Expr(Source{{12, 34}}, idx)), 1);
78 WrapInFunction(Decl(idx), acc);
Ryan Harrisondbc13af2022-02-21 15:19:07 +000079
dan sinclair41e4d9a2022-05-01 14:40:55 +000080 EXPECT_TRUE(r()->Resolve());
81 EXPECT_EQ(r()->error(), "");
Ryan Harrisondbc13af2022-02-21 15:19:07 +000082}
83
84TEST_F(ResolverIndexAccessorTest, Matrix) {
dan sinclair41e4d9a2022-05-01 14:40:55 +000085 Global("my_var", ty.mat2x3<f32>(), ast::StorageClass::kPrivate);
Ryan Harrisondbc13af2022-02-21 15:19:07 +000086
dan sinclair41e4d9a2022-05-01 14:40:55 +000087 auto* acc = IndexAccessor("my_var", 2);
88 WrapInFunction(acc);
Ryan Harrisondbc13af2022-02-21 15:19:07 +000089
dan sinclair41e4d9a2022-05-01 14:40:55 +000090 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ryan Harrisondbc13af2022-02-21 15:19:07 +000091
dan sinclair41e4d9a2022-05-01 14:40:55 +000092 ASSERT_NE(TypeOf(acc), nullptr);
93 ASSERT_TRUE(TypeOf(acc)->Is<sem::Reference>());
Ryan Harrisondbc13af2022-02-21 15:19:07 +000094
dan sinclair41e4d9a2022-05-01 14:40:55 +000095 auto* ref = TypeOf(acc)->As<sem::Reference>();
96 ASSERT_TRUE(ref->StoreType()->Is<sem::Vector>());
97 EXPECT_EQ(ref->StoreType()->As<sem::Vector>()->Width(), 3u);
Ryan Harrisondbc13af2022-02-21 15:19:07 +000098}
99
100TEST_F(ResolverIndexAccessorTest, Matrix_BothDimensions) {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000101 Global("my_var", ty.mat2x3<f32>(), ast::StorageClass::kPrivate);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000102
dan sinclair41e4d9a2022-05-01 14:40:55 +0000103 auto* acc = IndexAccessor(IndexAccessor("my_var", 2), 1);
104 WrapInFunction(acc);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000105
dan sinclair41e4d9a2022-05-01 14:40:55 +0000106 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000107
dan sinclair41e4d9a2022-05-01 14:40:55 +0000108 ASSERT_NE(TypeOf(acc), nullptr);
109 ASSERT_TRUE(TypeOf(acc)->Is<sem::Reference>());
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000110
dan sinclair41e4d9a2022-05-01 14:40:55 +0000111 auto* ref = TypeOf(acc)->As<sem::Reference>();
112 EXPECT_TRUE(ref->StoreType()->Is<sem::F32>());
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000113}
114
115TEST_F(ResolverIndexAccessorTest, Vector_F32) {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000116 Global("my_var", ty.vec3<f32>(), ast::StorageClass::kPrivate);
117 auto* acc = IndexAccessor("my_var", Expr(Source{{12, 34}}, 2.0f));
118 WrapInFunction(acc);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000119
dan sinclair41e4d9a2022-05-01 14:40:55 +0000120 EXPECT_FALSE(r()->Resolve());
121 EXPECT_EQ(r()->error(), "12:34 error: index must be of type 'i32' or 'u32', found: 'f32'");
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000122}
123
124TEST_F(ResolverIndexAccessorTest, Vector_Dynamic_Ref) {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000125 Global("my_var", ty.vec3<f32>(), ast::StorageClass::kPrivate);
126 auto* idx = Var("idx", ty.i32(), Expr(2));
127 auto* acc = IndexAccessor("my_var", idx);
128 WrapInFunction(Decl(idx), acc);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000129
dan sinclair41e4d9a2022-05-01 14:40:55 +0000130 EXPECT_TRUE(r()->Resolve());
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000131}
132
133TEST_F(ResolverIndexAccessorTest, Vector_Dynamic) {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000134 GlobalConst("my_var", ty.vec3<f32>(), Construct(ty.vec3<f32>()));
135 auto* idx = Var("idx", ty.i32(), Expr(2));
136 auto* acc = IndexAccessor("my_var", Expr(Source{{12, 34}}, idx));
137 WrapInFunction(Decl(idx), acc);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000138
dan sinclair41e4d9a2022-05-01 14:40:55 +0000139 EXPECT_TRUE(r()->Resolve());
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000140}
141
142TEST_F(ResolverIndexAccessorTest, Vector) {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000143 Global("my_var", ty.vec3<f32>(), ast::StorageClass::kPrivate);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000144
dan sinclair41e4d9a2022-05-01 14:40:55 +0000145 auto* acc = IndexAccessor("my_var", 2);
146 WrapInFunction(acc);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000147
dan sinclair41e4d9a2022-05-01 14:40:55 +0000148 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000149
dan sinclair41e4d9a2022-05-01 14:40:55 +0000150 ASSERT_NE(TypeOf(acc), nullptr);
151 ASSERT_TRUE(TypeOf(acc)->Is<sem::Reference>());
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000152
dan sinclair41e4d9a2022-05-01 14:40:55 +0000153 auto* ref = TypeOf(acc)->As<sem::Reference>();
154 EXPECT_TRUE(ref->StoreType()->Is<sem::F32>());
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000155}
156
157TEST_F(ResolverIndexAccessorTest, Array) {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000158 auto* idx = Expr(2);
159 Global("my_var", ty.array<f32, 3>(), ast::StorageClass::kPrivate);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000160
dan sinclair41e4d9a2022-05-01 14:40:55 +0000161 auto* acc = IndexAccessor("my_var", idx);
162 WrapInFunction(acc);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000163
dan sinclair41e4d9a2022-05-01 14:40:55 +0000164 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000165
dan sinclair41e4d9a2022-05-01 14:40:55 +0000166 ASSERT_NE(TypeOf(acc), nullptr);
167 ASSERT_TRUE(TypeOf(acc)->Is<sem::Reference>());
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000168
dan sinclair41e4d9a2022-05-01 14:40:55 +0000169 auto* ref = TypeOf(acc)->As<sem::Reference>();
170 EXPECT_TRUE(ref->StoreType()->Is<sem::F32>());
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000171}
172
173TEST_F(ResolverIndexAccessorTest, Alias_Array) {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000174 auto* aary = Alias("myarrty", ty.array<f32, 3>());
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000175
dan sinclair41e4d9a2022-05-01 14:40:55 +0000176 Global("my_var", ty.Of(aary), ast::StorageClass::kPrivate);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000177
dan sinclair41e4d9a2022-05-01 14:40:55 +0000178 auto* acc = IndexAccessor("my_var", 2);
179 WrapInFunction(acc);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000180
dan sinclair41e4d9a2022-05-01 14:40:55 +0000181 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000182
dan sinclair41e4d9a2022-05-01 14:40:55 +0000183 ASSERT_NE(TypeOf(acc), nullptr);
184 ASSERT_TRUE(TypeOf(acc)->Is<sem::Reference>());
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000185
dan sinclair41e4d9a2022-05-01 14:40:55 +0000186 auto* ref = TypeOf(acc)->As<sem::Reference>();
187 EXPECT_TRUE(ref->StoreType()->Is<sem::F32>());
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000188}
189
190TEST_F(ResolverIndexAccessorTest, Array_Constant) {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000191 GlobalConst("my_var", ty.array<f32, 3>(), array<f32, 3>());
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000192
dan sinclair41e4d9a2022-05-01 14:40:55 +0000193 auto* acc = IndexAccessor("my_var", 2);
194 WrapInFunction(acc);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000195
dan sinclair41e4d9a2022-05-01 14:40:55 +0000196 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000197
dan sinclair41e4d9a2022-05-01 14:40:55 +0000198 ASSERT_NE(TypeOf(acc), nullptr);
199 EXPECT_TRUE(TypeOf(acc)->Is<sem::F32>());
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000200}
201
202TEST_F(ResolverIndexAccessorTest, Array_Dynamic_I32) {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000203 // let a : array<f32, 3> = 0;
204 // var idx : i32 = 0;
205 // var f : f32 = a[idx];
206 auto* a = Let("a", ty.array<f32, 3>(), array<f32, 3>());
207 auto* idx = Var("idx", ty.i32(), Construct(ty.i32()));
208 auto* f = Var("f", ty.f32(), IndexAccessor("a", Expr(Source{{12, 34}}, idx)));
209 Func("my_func", ast::VariableList{}, ty.void_(),
210 {
211 Decl(a),
212 Decl(idx),
213 Decl(f),
214 },
215 ast::AttributeList{});
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000216
dan sinclair41e4d9a2022-05-01 14:40:55 +0000217 EXPECT_TRUE(r()->Resolve());
218 EXPECT_EQ(r()->error(), "");
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000219}
220
221TEST_F(ResolverIndexAccessorTest, Array_Literal_F32) {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000222 // let a : array<f32, 3>;
223 // var f : f32 = a[2.0f];
224 auto* a = Let("a", ty.array<f32, 3>(), array<f32, 3>());
225 auto* f = Var("a_2", ty.f32(), IndexAccessor("a", Expr(Source{{12, 34}}, 2.0f)));
226 Func("my_func", ast::VariableList{}, ty.void_(),
227 {
228 Decl(a),
229 Decl(f),
230 },
231 ast::AttributeList{});
232 EXPECT_FALSE(r()->Resolve());
233 EXPECT_EQ(r()->error(), "12:34 error: index must be of type 'i32' or 'u32', found: 'f32'");
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000234}
235
236TEST_F(ResolverIndexAccessorTest, Array_Literal_I32) {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000237 // let a : array<f32, 3>;
238 // var f : f32 = a[2];
239 auto* a = Let("a", ty.array<f32, 3>(), array<f32, 3>());
240 auto* f = Var("a_2", ty.f32(), IndexAccessor("a", 2));
241 Func("my_func", ast::VariableList{}, ty.void_(),
242 {
243 Decl(a),
244 Decl(f),
245 },
246 ast::AttributeList{});
247 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000248}
249
250TEST_F(ResolverIndexAccessorTest, EXpr_Deref_FuncGoodParent) {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000251 // fn func(p: ptr<function, vec4<f32>>) -> f32 {
252 // let idx: u32 = u32();
253 // let x: f32 = (*p)[idx];
254 // return x;
255 // }
256 auto* p = Param("p", ty.pointer(ty.vec4<f32>(), ast::StorageClass::kFunction));
257 auto* idx = Let("idx", ty.u32(), Construct(ty.u32()));
258 auto* star_p = Deref(p);
259 auto* accessor_expr = IndexAccessor(Source{{12, 34}}, star_p, idx);
260 auto* x = Var("x", ty.f32(), accessor_expr);
261 Func("func", {p}, ty.f32(), {Decl(idx), Decl(x), Return(x)});
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000262
dan sinclair41e4d9a2022-05-01 14:40:55 +0000263 EXPECT_TRUE(r()->Resolve()) << r()->error();
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000264}
265
266TEST_F(ResolverIndexAccessorTest, EXpr_Deref_FuncBadParent) {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000267 // fn func(p: ptr<function, vec4<f32>>) -> f32 {
268 // let idx: u32 = u32();
269 // let x: f32 = *p[idx];
270 // return x;
271 // }
272 auto* p = Param("p", ty.pointer(ty.vec4<f32>(), ast::StorageClass::kFunction));
273 auto* idx = Let("idx", ty.u32(), Construct(ty.u32()));
274 auto* accessor_expr = IndexAccessor(Source{{12, 34}}, p, idx);
275 auto* star_p = Deref(accessor_expr);
276 auto* x = Var("x", ty.f32(), star_p);
277 Func("func", {p}, ty.f32(), {Decl(idx), Decl(x), Return(x)});
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000278
dan sinclair41e4d9a2022-05-01 14:40:55 +0000279 EXPECT_FALSE(r()->Resolve());
280 EXPECT_EQ(r()->error(),
281 "12:34 error: cannot index type 'ptr<function, vec4<f32>, read_write>'");
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000282}
283
284TEST_F(ResolverIndexAccessorTest, Exr_Deref_BadParent) {
dan sinclair41e4d9a2022-05-01 14:40:55 +0000285 // var param: vec4<f32>
286 // let x: f32 = *(&param)[0];
287 auto* param = Var("param", ty.vec4<f32>());
288 auto* idx = Var("idx", ty.u32(), Construct(ty.u32()));
289 auto* addressOf_expr = AddressOf(param);
290 auto* accessor_expr = IndexAccessor(Source{{12, 34}}, addressOf_expr, idx);
291 auto* star_p = Deref(accessor_expr);
292 auto* x = Var("x", ty.f32(), star_p);
293 WrapInFunction(param, idx, x);
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000294
dan sinclair41e4d9a2022-05-01 14:40:55 +0000295 EXPECT_FALSE(r()->Resolve());
296 EXPECT_EQ(r()->error(),
297 "12:34 error: cannot index type 'ptr<function, vec4<f32>, read_write>'");
Ryan Harrisondbc13af2022-02-21 15:19:07 +0000298}
299
300} // namespace
dan sinclaird2093792022-04-07 17:45:45 +0000301} // namespace tint::resolver