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/promote_initializers_to_const_var.h"
16
17 #include "src/transform/test_helper.h"
18
19 namespace tint {
20 namespace transform {
21 namespace {
22
23 using PromoteInitializersToConstVarTest = TransformTest;
24
TEST_F(PromoteInitializersToConstVarTest,BasicArray)25 TEST_F(PromoteInitializersToConstVarTest, BasicArray) {
26 auto* src = R"(
27 [[stage(compute), workgroup_size(1)]]
28 fn main() {
29 var f0 : f32 = 1.0;
30 var f1 : f32 = 2.0;
31 var f2 : f32 = 3.0;
32 var f3 : f32 = 4.0;
33 var i : f32 = array<f32, 4u>(f0, f1, f2, f3)[2];
34 }
35 )";
36
37 auto* expect = R"(
38 [[stage(compute), workgroup_size(1)]]
39 fn main() {
40 var f0 : f32 = 1.0;
41 var f1 : f32 = 2.0;
42 var f2 : f32 = 3.0;
43 var f3 : f32 = 4.0;
44 let tint_symbol : array<f32, 4u> = array<f32, 4u>(f0, f1, f2, f3);
45 var i : f32 = tint_symbol[2];
46 }
47 )";
48
49 auto got = Run<PromoteInitializersToConstVar>(src);
50
51 EXPECT_EQ(expect, str(got));
52 }
53
TEST_F(PromoteInitializersToConstVarTest,BasicStruct)54 TEST_F(PromoteInitializersToConstVarTest, BasicStruct) {
55 auto* src = R"(
56 struct S {
57 a : i32;
58 b : f32;
59 c : vec3<f32>;
60 };
61
62 [[stage(compute), workgroup_size(1)]]
63 fn main() {
64 var x : f32 = S(1, 2.0, vec3<f32>()).b;
65 }
66 )";
67
68 auto* expect = R"(
69 struct S {
70 a : i32;
71 b : f32;
72 c : vec3<f32>;
73 };
74
75 [[stage(compute), workgroup_size(1)]]
76 fn main() {
77 let tint_symbol : S = S(1, 2.0, vec3<f32>());
78 var x : f32 = tint_symbol.b;
79 }
80 )";
81
82 auto got = Run<PromoteInitializersToConstVar>(src);
83
84 EXPECT_EQ(expect, str(got));
85 }
86
TEST_F(PromoteInitializersToConstVarTest,ArrayInArrayArray)87 TEST_F(PromoteInitializersToConstVarTest, ArrayInArrayArray) {
88 auto* src = R"(
89 [[stage(compute), workgroup_size(1)]]
90 fn main() {
91 var i : f32 = array<array<f32, 2u>, 2u>(array<f32, 2u>(1.0, 2.0), array<f32, 2u>(3.0, 4.0))[0][1];
92 }
93 )";
94
95 auto* expect = R"(
96 [[stage(compute), workgroup_size(1)]]
97 fn main() {
98 let tint_symbol : array<f32, 2u> = array<f32, 2u>(1.0, 2.0);
99 let tint_symbol_1 : array<f32, 2u> = array<f32, 2u>(3.0, 4.0);
100 let tint_symbol_2 : array<array<f32, 2u>, 2u> = array<array<f32, 2u>, 2u>(tint_symbol, tint_symbol_1);
101 var i : f32 = tint_symbol_2[0][1];
102 }
103 )";
104
105 auto got = Run<PromoteInitializersToConstVar>(src);
106
107 EXPECT_EQ(expect, str(got));
108 }
109
TEST_F(PromoteInitializersToConstVarTest,StructNested)110 TEST_F(PromoteInitializersToConstVarTest, StructNested) {
111 auto* src = R"(
112 struct S1 {
113 a : i32;
114 };
115
116 struct S2 {
117 a : i32;
118 b : S1;
119 c : i32;
120 };
121
122 struct S3 {
123 a : S2;
124 };
125
126 [[stage(compute), workgroup_size(1)]]
127 fn main() {
128 var x : i32 = S3(S2(1, S1(2), 3)).a.b.a;
129 }
130 )";
131
132 auto* expect = R"(
133 struct S1 {
134 a : i32;
135 };
136
137 struct S2 {
138 a : i32;
139 b : S1;
140 c : i32;
141 };
142
143 struct S3 {
144 a : S2;
145 };
146
147 [[stage(compute), workgroup_size(1)]]
148 fn main() {
149 let tint_symbol : S1 = S1(2);
150 let tint_symbol_1 : S2 = S2(1, tint_symbol, 3);
151 let tint_symbol_2 : S3 = S3(tint_symbol_1);
152 var x : i32 = tint_symbol_2.a.b.a;
153 }
154 )";
155
156 auto got = Run<PromoteInitializersToConstVar>(src);
157
158 EXPECT_EQ(expect, str(got));
159 }
160
TEST_F(PromoteInitializersToConstVarTest,Mixed)161 TEST_F(PromoteInitializersToConstVarTest, Mixed) {
162 auto* src = R"(
163 struct S1 {
164 a : i32;
165 };
166
167 struct S2 {
168 a : array<S1, 3u>;
169 };
170
171 [[stage(compute), workgroup_size(1)]]
172 fn main() {
173 var x : i32 = S2(array<S1, 3u>(S1(1), S1(2), S1(3))).a[1].a;
174 }
175 )";
176
177 auto* expect = R"(
178 struct S1 {
179 a : i32;
180 };
181
182 struct S2 {
183 a : array<S1, 3u>;
184 };
185
186 [[stage(compute), workgroup_size(1)]]
187 fn main() {
188 let tint_symbol : S1 = S1(1);
189 let tint_symbol_1 : S1 = S1(2);
190 let tint_symbol_2 : S1 = S1(3);
191 let tint_symbol_3 : array<S1, 3u> = array<S1, 3u>(tint_symbol, tint_symbol_1, tint_symbol_2);
192 let tint_symbol_4 : S2 = S2(tint_symbol_3);
193 var x : i32 = tint_symbol_4.a[1].a;
194 }
195 )";
196
197 auto got = Run<PromoteInitializersToConstVar>(src);
198
199 EXPECT_EQ(expect, str(got));
200 }
201
TEST_F(PromoteInitializersToConstVarTest,NoChangeOnVarDecl)202 TEST_F(PromoteInitializersToConstVarTest, NoChangeOnVarDecl) {
203 auto* src = R"(
204 struct S {
205 a : i32;
206 b : f32;
207 c : i32;
208 };
209
210 [[stage(compute), workgroup_size(1)]]
211 fn main() {
212 var local_arr : array<f32, 4u> = array<f32, 4u>(0.0, 1.0, 2.0, 3.0);
213 var local_str : S = S(1, 2.0, 3);
214 }
215
216 let module_arr : array<f32, 4u> = array<f32, 4u>(0.0, 1.0, 2.0, 3.0);
217
218 let module_str : S = S(1, 2.0, 3);
219 )";
220
221 auto* expect = src;
222
223 auto got = Run<PromoteInitializersToConstVar>(src);
224
225 EXPECT_EQ(expect, str(got));
226 }
227
TEST_F(PromoteInitializersToConstVarTest,EmptyModule)228 TEST_F(PromoteInitializersToConstVarTest, EmptyModule) {
229 auto* src = "";
230 auto* expect = "";
231
232 auto got = Run<PromoteInitializersToConstVar>(src);
233
234 EXPECT_EQ(expect, str(got));
235 }
236
237 } // namespace
238 } // namespace transform
239 } // namespace tint
240