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/transform/pad_array_elements.h"
16
17 #include <utility>
18
19 #include "src/transform/test_helper.h"
20
21 namespace tint {
22 namespace transform {
23 namespace {
24
25 using PadArrayElementsTest = TransformTest;
26
TEST_F(PadArrayElementsTest,EmptyModule)27 TEST_F(PadArrayElementsTest, EmptyModule) {
28 auto* src = "";
29 auto* expect = "";
30
31 auto got = Run<PadArrayElements>(src);
32
33 EXPECT_EQ(expect, str(got));
34 }
35
TEST_F(PadArrayElementsTest,ImplicitArrayStride)36 TEST_F(PadArrayElementsTest, ImplicitArrayStride) {
37 auto* src = R"(
38 var<private> arr : array<i32, 4>;
39 )";
40 auto* expect = src;
41
42 auto got = Run<PadArrayElements>(src);
43
44 EXPECT_EQ(expect, str(got));
45 }
46
TEST_F(PadArrayElementsTest,ArrayAsGlobal)47 TEST_F(PadArrayElementsTest, ArrayAsGlobal) {
48 auto* src = R"(
49 var<private> arr : [[stride(8)]] array<i32, 4>;
50 )";
51 auto* expect = R"(
52 struct tint_padded_array_element {
53 [[size(8)]]
54 el : i32;
55 };
56
57 var<private> arr : array<tint_padded_array_element, 4u>;
58 )";
59
60 auto got = Run<PadArrayElements>(src);
61
62 EXPECT_EQ(expect, str(got));
63 }
64
TEST_F(PadArrayElementsTest,RuntimeArray)65 TEST_F(PadArrayElementsTest, RuntimeArray) {
66 auto* src = R"(
67 [[block]]
68 struct S {
69 rta : [[stride(8)]] array<i32>;
70 };
71 )";
72 auto* expect = R"(
73 struct tint_padded_array_element {
74 [[size(8)]]
75 el : i32;
76 };
77
78 [[block]]
79 struct S {
80 rta : array<tint_padded_array_element>;
81 };
82 )";
83
84 auto got = Run<PadArrayElements>(src);
85
86 EXPECT_EQ(expect, str(got));
87 }
88
TEST_F(PadArrayElementsTest,ArrayFunctionVar)89 TEST_F(PadArrayElementsTest, ArrayFunctionVar) {
90 auto* src = R"(
91 fn f() {
92 var arr : [[stride(16)]] array<i32, 4>;
93 arr = [[stride(16)]] array<i32, 4>();
94 arr = [[stride(16)]] array<i32, 4>(1, 2, 3, 4);
95 let x = arr[3];
96 }
97 )";
98 auto* expect = R"(
99 struct tint_padded_array_element {
100 [[size(16)]]
101 el : i32;
102 };
103
104 fn f() {
105 var arr : array<tint_padded_array_element, 4u>;
106 arr = array<tint_padded_array_element, 4u>();
107 arr = array<tint_padded_array_element, 4u>(tint_padded_array_element(1), tint_padded_array_element(2), tint_padded_array_element(3), tint_padded_array_element(4));
108 let x = arr[3].el;
109 }
110 )";
111
112 auto got = Run<PadArrayElements>(src);
113
114 EXPECT_EQ(expect, str(got));
115 }
116
TEST_F(PadArrayElementsTest,ArrayAsParam)117 TEST_F(PadArrayElementsTest, ArrayAsParam) {
118 auto* src = R"(
119 fn f(a : [[stride(12)]] array<i32, 4>) -> i32 {
120 return a[2];
121 }
122 )";
123 auto* expect = R"(
124 struct tint_padded_array_element {
125 [[size(12)]]
126 el : i32;
127 };
128
129 fn f(a : array<tint_padded_array_element, 4u>) -> i32 {
130 return a[2].el;
131 }
132 )";
133
134 auto got = Run<PadArrayElements>(src);
135
136 EXPECT_EQ(expect, str(got));
137 }
138
139 // TODO(crbug.com/tint/781): Cannot parse the stride on the return array type.
TEST_F(PadArrayElementsTest,DISABLED_ArrayAsReturn)140 TEST_F(PadArrayElementsTest, DISABLED_ArrayAsReturn) {
141 auto* src = R"(
142 fn f() -> [[stride(8)]] array<i32, 4> {
143 return array<i32, 4>(1, 2, 3, 4);
144 }
145 )";
146 auto* expect = R"(
147 struct tint_padded_array_element {
148 el : i32;
149 [[size(4)]]
150 padding : u32;
151 };
152
153 fn f() -> array<tint_padded_array_element, 4> {
154 return array<tint_padded_array_element, 4>(tint_padded_array_element(1, 0u), tint_padded_array_element(2, 0u), tint_padded_array_element(3, 0u), tint_padded_array_element(4, 0u));
155 }
156 )";
157
158 auto got = Run<PadArrayElements>(src);
159
160 EXPECT_EQ(expect, str(got));
161 }
162
TEST_F(PadArrayElementsTest,ArrayAlias)163 TEST_F(PadArrayElementsTest, ArrayAlias) {
164 auto* src = R"(
165 type Array = [[stride(16)]] array<i32, 4>;
166
167 fn f() {
168 var arr : Array;
169 arr = Array();
170 arr = Array(1, 2, 3, 4);
171 let vals : Array = Array(1, 2, 3, 4);
172 arr = vals;
173 let x = arr[3];
174 }
175 )";
176 auto* expect = R"(
177 struct tint_padded_array_element {
178 [[size(16)]]
179 el : i32;
180 };
181
182 type Array = array<tint_padded_array_element, 4u>;
183
184 fn f() {
185 var arr : array<tint_padded_array_element, 4u>;
186 arr = array<tint_padded_array_element, 4u>();
187 arr = array<tint_padded_array_element, 4u>(tint_padded_array_element(1), tint_padded_array_element(2), tint_padded_array_element(3), tint_padded_array_element(4));
188 let vals : array<tint_padded_array_element, 4u> = array<tint_padded_array_element, 4u>(tint_padded_array_element(1), tint_padded_array_element(2), tint_padded_array_element(3), tint_padded_array_element(4));
189 arr = vals;
190 let x = arr[3].el;
191 }
192 )";
193
194 auto got = Run<PadArrayElements>(src);
195
196 EXPECT_EQ(expect, str(got));
197 }
198
TEST_F(PadArrayElementsTest,ArraysInStruct)199 TEST_F(PadArrayElementsTest, ArraysInStruct) {
200 auto* src = R"(
201 struct S {
202 a : [[stride(8)]] array<i32, 4>;
203 b : [[stride(8)]] array<i32, 8>;
204 c : [[stride(8)]] array<i32, 4>;
205 d : [[stride(12)]] array<i32, 8>;
206 };
207 )";
208 auto* expect = R"(
209 struct tint_padded_array_element {
210 [[size(8)]]
211 el : i32;
212 };
213
214 struct tint_padded_array_element_1 {
215 [[size(8)]]
216 el : i32;
217 };
218
219 struct tint_padded_array_element_2 {
220 [[size(12)]]
221 el : i32;
222 };
223
224 struct S {
225 a : array<tint_padded_array_element, 4u>;
226 b : array<tint_padded_array_element_1, 8u>;
227 c : array<tint_padded_array_element, 4u>;
228 d : array<tint_padded_array_element_2, 8u>;
229 };
230 )";
231
232 auto got = Run<PadArrayElements>(src);
233
234 EXPECT_EQ(expect, str(got));
235 }
236
TEST_F(PadArrayElementsTest,ArraysOfArraysInStruct)237 TEST_F(PadArrayElementsTest, ArraysOfArraysInStruct) {
238 auto* src = R"(
239 struct S {
240 a : [[stride(512)]] array<i32, 4>;
241 b : [[stride(512)]] array<[[stride(32)]] array<i32, 4>, 4>;
242 c : [[stride(512)]] array<[[stride(64)]] array<[[stride(8)]] array<i32, 4>, 4>, 4>;
243 };
244 )";
245 auto* expect = R"(
246 struct tint_padded_array_element {
247 [[size(512)]]
248 el : i32;
249 };
250
251 struct tint_padded_array_element_2 {
252 [[size(32)]]
253 el : i32;
254 };
255
256 struct tint_padded_array_element_1 {
257 [[size(512)]]
258 el : array<tint_padded_array_element_2, 4u>;
259 };
260
261 struct tint_padded_array_element_5 {
262 [[size(8)]]
263 el : i32;
264 };
265
266 struct tint_padded_array_element_4 {
267 [[size(64)]]
268 el : array<tint_padded_array_element_5, 4u>;
269 };
270
271 struct tint_padded_array_element_3 {
272 [[size(512)]]
273 el : array<tint_padded_array_element_4, 4u>;
274 };
275
276 struct S {
277 a : array<tint_padded_array_element, 4u>;
278 b : array<tint_padded_array_element_1, 4u>;
279 c : array<tint_padded_array_element_3, 4u>;
280 };
281 )";
282
283 auto got = Run<PadArrayElements>(src);
284
285 EXPECT_EQ(expect, str(got));
286 }
287
TEST_F(PadArrayElementsTest,AccessArraysOfArraysInStruct)288 TEST_F(PadArrayElementsTest, AccessArraysOfArraysInStruct) {
289 auto* src = R"(
290 struct S {
291 a : [[stride(512)]] array<i32, 4>;
292 b : [[stride(512)]] array<[[stride(32)]] array<i32, 4>, 4>;
293 c : [[stride(512)]] array<[[stride(64)]] array<[[stride(8)]] array<i32, 4>, 4>, 4>;
294 };
295
296 fn f(s : S) -> i32 {
297 return s.a[2] + s.b[1][2] + s.c[3][1][2];
298 }
299 )";
300 auto* expect = R"(
301 struct tint_padded_array_element {
302 [[size(512)]]
303 el : i32;
304 };
305
306 struct tint_padded_array_element_2 {
307 [[size(32)]]
308 el : i32;
309 };
310
311 struct tint_padded_array_element_1 {
312 [[size(512)]]
313 el : array<tint_padded_array_element_2, 4u>;
314 };
315
316 struct tint_padded_array_element_5 {
317 [[size(8)]]
318 el : i32;
319 };
320
321 struct tint_padded_array_element_4 {
322 [[size(64)]]
323 el : array<tint_padded_array_element_5, 4u>;
324 };
325
326 struct tint_padded_array_element_3 {
327 [[size(512)]]
328 el : array<tint_padded_array_element_4, 4u>;
329 };
330
331 struct S {
332 a : array<tint_padded_array_element, 4u>;
333 b : array<tint_padded_array_element_1, 4u>;
334 c : array<tint_padded_array_element_3, 4u>;
335 };
336
337 fn f(s : S) -> i32 {
338 return ((s.a[2].el + s.b[1].el[2].el) + s.c[3].el[1].el[2].el);
339 }
340 )";
341
342 auto got = Run<PadArrayElements>(src);
343
344 EXPECT_EQ(expect, str(got));
345 }
346
TEST_F(PadArrayElementsTest,DeclarationOrder)347 TEST_F(PadArrayElementsTest, DeclarationOrder) {
348 auto* src = R"(
349 type T0 = i32;
350
351 type T1 = [[stride(8)]] array<i32, 1>;
352
353 type T2 = i32;
354
355 fn f1(a : [[stride(8)]] array<i32, 2>) {
356 }
357
358 type T3 = i32;
359
360 fn f2() {
361 var v : [[stride(8)]] array<i32, 3>;
362 }
363 )";
364 auto* expect = R"(
365 type T0 = i32;
366
367 struct tint_padded_array_element {
368 [[size(8)]]
369 el : i32;
370 };
371
372 type T1 = array<tint_padded_array_element, 1u>;
373
374 type T2 = i32;
375
376 struct tint_padded_array_element_1 {
377 [[size(8)]]
378 el : i32;
379 };
380
381 fn f1(a : array<tint_padded_array_element_1, 2u>) {
382 }
383
384 type T3 = i32;
385
386 struct tint_padded_array_element_2 {
387 [[size(8)]]
388 el : i32;
389 };
390
391 fn f2() {
392 var v : array<tint_padded_array_element_2, 3u>;
393 }
394 )";
395
396 auto got = Run<PadArrayElements>(src);
397
398 EXPECT_EQ(expect, str(got));
399 }
400
401 } // namespace
402 } // namespace transform
403 } // namespace tint
404