• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2020 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/ast/variable_decl_statement.h"
16 #include "src/writer/hlsl/test_helper.h"
17 
18 namespace tint {
19 namespace writer {
20 namespace hlsl {
21 namespace {
22 
23 using HlslGeneratorImplTest_Loop = TestHelper;
24 
TEST_F(HlslGeneratorImplTest_Loop,Emit_Loop)25 TEST_F(HlslGeneratorImplTest_Loop, Emit_Loop) {
26   auto* body = Block(create<ast::DiscardStatement>());
27   auto* continuing = Block();
28   auto* l = Loop(body, continuing);
29 
30   WrapInFunction(l);
31 
32   GeneratorImpl& gen = Build();
33 
34   gen.increment_indent();
35 
36   ASSERT_TRUE(gen.EmitStatement(l)) << gen.error();
37   EXPECT_EQ(gen.result(), R"(  [loop] while (true) {
38     discard;
39   }
40 )");
41 }
42 
TEST_F(HlslGeneratorImplTest_Loop,Emit_LoopWithContinuing)43 TEST_F(HlslGeneratorImplTest_Loop, Emit_LoopWithContinuing) {
44   Func("a_statement", {}, ty.void_(), {});
45 
46   auto* body = Block(create<ast::DiscardStatement>());
47   auto* continuing = Block(CallStmt(Call("a_statement")));
48   auto* l = Loop(body, continuing);
49 
50   WrapInFunction(l);
51 
52   GeneratorImpl& gen = Build();
53 
54   gen.increment_indent();
55 
56   ASSERT_TRUE(gen.EmitStatement(l)) << gen.error();
57   EXPECT_EQ(gen.result(), R"(  [loop] while (true) {
58     discard;
59     {
60       a_statement();
61     }
62   }
63 )");
64 }
65 
TEST_F(HlslGeneratorImplTest_Loop,Emit_LoopNestedWithContinuing)66 TEST_F(HlslGeneratorImplTest_Loop, Emit_LoopNestedWithContinuing) {
67   Func("a_statement", {}, ty.void_(), {});
68 
69   Global("lhs", ty.f32(), ast::StorageClass::kPrivate);
70   Global("rhs", ty.f32(), ast::StorageClass::kPrivate);
71 
72   auto* body = Block(create<ast::DiscardStatement>());
73   auto* continuing = Block(CallStmt(Call("a_statement")));
74   auto* inner = Loop(body, continuing);
75 
76   body = Block(inner);
77 
78   auto* lhs = Expr("lhs");
79   auto* rhs = Expr("rhs");
80 
81   continuing = Block(Assign(lhs, rhs));
82 
83   auto* outer = Loop(body, continuing);
84   WrapInFunction(outer);
85 
86   GeneratorImpl& gen = Build();
87 
88   gen.increment_indent();
89 
90   ASSERT_TRUE(gen.EmitStatement(outer)) << gen.error();
91   EXPECT_EQ(gen.result(), R"(  [loop] while (true) {
92     [loop] while (true) {
93       discard;
94       {
95         a_statement();
96       }
97     }
98     {
99       lhs = rhs;
100     }
101   }
102 )");
103 }
104 
TEST_F(HlslGeneratorImplTest_Loop,Emit_LoopWithVarUsedInContinuing)105 TEST_F(HlslGeneratorImplTest_Loop, Emit_LoopWithVarUsedInContinuing) {
106   // loop {
107   //   var lhs : f32 = 2.4;
108   //   var other : f32;
109   //   continuing {
110   //     lhs = rhs
111   //   }
112   // }
113   //
114   // ->
115   // {
116   //   float lhs;
117   //   float other;
118   //   for (;;) {
119   //     if (continuing) {
120   //       lhs = rhs;
121   //     }
122   //     lhs = 2.4f;
123   //     other = 0.0f;
124   //   }
125   // }
126 
127   Global("rhs", ty.f32(), ast::StorageClass::kPrivate);
128 
129   auto* var = Var("lhs", ty.f32(), ast::StorageClass::kNone, Expr(2.4f));
130 
131   auto* body = Block(Decl(var), Decl(Var("other", ty.f32())));
132 
133   auto* lhs = Expr("lhs");
134   auto* rhs = Expr("rhs");
135 
136   auto* continuing = Block(Assign(lhs, rhs));
137   auto* outer = Loop(body, continuing);
138   WrapInFunction(outer);
139 
140   GeneratorImpl& gen = Build();
141 
142   gen.increment_indent();
143 
144   ASSERT_TRUE(gen.EmitStatement(outer)) << gen.error();
145   EXPECT_EQ(gen.result(), R"(  [loop] while (true) {
146     float lhs = 2.400000095f;
147     float other = 0.0f;
148     {
149       lhs = rhs;
150     }
151   }
152 )");
153 }
154 
TEST_F(HlslGeneratorImplTest_Loop,Emit_ForLoop)155 TEST_F(HlslGeneratorImplTest_Loop, Emit_ForLoop) {
156   // for(; ; ) {
157   //   return;
158   // }
159 
160   Func("a_statement", {}, ty.void_(), {});
161 
162   auto* f =
163       For(nullptr, nullptr, nullptr, Block(CallStmt(Call("a_statement"))));
164   WrapInFunction(f);
165 
166   GeneratorImpl& gen = Build();
167 
168   gen.increment_indent();
169 
170   ASSERT_TRUE(gen.EmitStatement(f)) << gen.error();
171   EXPECT_EQ(gen.result(), R"(  {
172     [loop] for(; ; ) {
173       a_statement();
174     }
175   }
176 )");
177 }
178 
TEST_F(HlslGeneratorImplTest_Loop,Emit_ForLoopWithSimpleInit)179 TEST_F(HlslGeneratorImplTest_Loop, Emit_ForLoopWithSimpleInit) {
180   // for(var i : i32; ; ) {
181   //   return;
182   // }
183 
184   Func("a_statement", {}, ty.void_(), {});
185 
186   auto* f = For(Decl(Var("i", ty.i32())), nullptr, nullptr,
187                 Block(CallStmt(Call("a_statement"))));
188   WrapInFunction(f);
189 
190   GeneratorImpl& gen = Build();
191 
192   gen.increment_indent();
193 
194   ASSERT_TRUE(gen.EmitStatement(f)) << gen.error();
195   EXPECT_EQ(gen.result(), R"(  {
196     [loop] for(int i = 0; ; ) {
197       a_statement();
198     }
199   }
200 )");
201 }
202 
TEST_F(HlslGeneratorImplTest_Loop,Emit_ForLoopWithMultiStmtInit)203 TEST_F(HlslGeneratorImplTest_Loop, Emit_ForLoopWithMultiStmtInit) {
204   // for(var b = true && false; ; ) {
205   //   return;
206   // }
207   Func("a_statement", {}, ty.void_(), {});
208 
209   auto* multi_stmt = create<ast::BinaryExpression>(ast::BinaryOp::kLogicalAnd,
210                                                    Expr(true), Expr(false));
211   auto* f = For(Decl(Var("b", nullptr, multi_stmt)), nullptr, nullptr,
212                 Block(CallStmt(Call("a_statement"))));
213   WrapInFunction(f);
214 
215   GeneratorImpl& gen = Build();
216 
217   gen.increment_indent();
218 
219   ASSERT_TRUE(gen.EmitStatement(f)) << gen.error();
220   EXPECT_EQ(gen.result(), R"(  {
221     bool tint_tmp = true;
222     if (tint_tmp) {
223       tint_tmp = false;
224     }
225     bool b = (tint_tmp);
226     [loop] for(; ; ) {
227       a_statement();
228     }
229   }
230 )");
231 }
232 
TEST_F(HlslGeneratorImplTest_Loop,Emit_ForLoopWithSimpleCond)233 TEST_F(HlslGeneratorImplTest_Loop, Emit_ForLoopWithSimpleCond) {
234   // for(; true; ) {
235   //   return;
236   // }
237 
238   Func("a_statement", {}, ty.void_(), {});
239 
240   auto* f = For(nullptr, true, nullptr, Block(CallStmt(Call("a_statement"))));
241   WrapInFunction(f);
242 
243   GeneratorImpl& gen = Build();
244 
245   gen.increment_indent();
246 
247   ASSERT_TRUE(gen.EmitStatement(f)) << gen.error();
248   EXPECT_EQ(gen.result(), R"(  {
249     [loop] for(; true; ) {
250       a_statement();
251     }
252   }
253 )");
254 }
255 
TEST_F(HlslGeneratorImplTest_Loop,Emit_ForLoopWithMultiStmtCond)256 TEST_F(HlslGeneratorImplTest_Loop, Emit_ForLoopWithMultiStmtCond) {
257   // for(; true && false; ) {
258   //   return;
259   // }
260 
261   Func("a_statement", {}, ty.void_(), {});
262 
263   auto* multi_stmt = create<ast::BinaryExpression>(ast::BinaryOp::kLogicalAnd,
264                                                    Expr(true), Expr(false));
265   auto* f =
266       For(nullptr, multi_stmt, nullptr, Block(CallStmt(Call("a_statement"))));
267   WrapInFunction(f);
268 
269   GeneratorImpl& gen = Build();
270 
271   gen.increment_indent();
272 
273   ASSERT_TRUE(gen.EmitStatement(f)) << gen.error();
274   EXPECT_EQ(gen.result(), R"(  {
275     [loop] while (true) {
276       bool tint_tmp = true;
277       if (tint_tmp) {
278         tint_tmp = false;
279       }
280       if (!((tint_tmp))) { break; }
281       a_statement();
282     }
283   }
284 )");
285 }
286 
TEST_F(HlslGeneratorImplTest_Loop,Emit_ForLoopWithSimpleCont)287 TEST_F(HlslGeneratorImplTest_Loop, Emit_ForLoopWithSimpleCont) {
288   // for(; ; i = i + 1) {
289   //   return;
290   // }
291 
292   Func("a_statement", {}, ty.void_(), {});
293 
294   auto* v = Decl(Var("i", ty.i32()));
295   auto* f = For(nullptr, nullptr, Assign("i", Add("i", 1)),
296                 Block(CallStmt(Call("a_statement"))));
297   WrapInFunction(v, f);
298 
299   GeneratorImpl& gen = Build();
300 
301   gen.increment_indent();
302 
303   ASSERT_TRUE(gen.EmitStatement(f)) << gen.error();
304   EXPECT_EQ(gen.result(), R"(  {
305     [loop] for(; ; i = (i + 1)) {
306       a_statement();
307     }
308   }
309 )");
310 }
311 
TEST_F(HlslGeneratorImplTest_Loop,Emit_ForLoopWithMultiStmtCont)312 TEST_F(HlslGeneratorImplTest_Loop, Emit_ForLoopWithMultiStmtCont) {
313   // for(; ; i = true && false) {
314   //   return;
315   // }
316 
317   Func("a_statement", {}, ty.void_(), {});
318 
319   auto* multi_stmt = create<ast::BinaryExpression>(ast::BinaryOp::kLogicalAnd,
320                                                    Expr(true), Expr(false));
321   auto* v = Decl(Var("i", ty.bool_()));
322   auto* f = For(nullptr, nullptr, Assign("i", multi_stmt),
323                 Block(CallStmt(Call("a_statement"))));
324   WrapInFunction(v, f);
325 
326   GeneratorImpl& gen = Build();
327 
328   gen.increment_indent();
329 
330   ASSERT_TRUE(gen.EmitStatement(f)) << gen.error();
331   EXPECT_EQ(gen.result(), R"(  {
332     [loop] while (true) {
333       a_statement();
334       bool tint_tmp = true;
335       if (tint_tmp) {
336         tint_tmp = false;
337       }
338       i = (tint_tmp);
339     }
340   }
341 )");
342 }
343 
TEST_F(HlslGeneratorImplTest_Loop,Emit_ForLoopWithSimpleInitCondCont)344 TEST_F(HlslGeneratorImplTest_Loop, Emit_ForLoopWithSimpleInitCondCont) {
345   // for(var i : i32; true; i = i + 1) {
346   //   return;
347   // }
348 
349   Func("a_statement", {}, ty.void_(), {});
350 
351   auto* f = For(Decl(Var("i", ty.i32())), true, Assign("i", Add("i", 1)),
352                 Block(CallStmt(Call("a_statement"))));
353   WrapInFunction(f);
354 
355   GeneratorImpl& gen = Build();
356 
357   gen.increment_indent();
358 
359   ASSERT_TRUE(gen.EmitStatement(f)) << gen.error();
360   EXPECT_EQ(gen.result(), R"(  {
361     [loop] for(int i = 0; true; i = (i + 1)) {
362       a_statement();
363     }
364   }
365 )");
366 }
367 
TEST_F(HlslGeneratorImplTest_Loop,Emit_ForLoopWithMultiStmtInitCondCont)368 TEST_F(HlslGeneratorImplTest_Loop, Emit_ForLoopWithMultiStmtInitCondCont) {
369   // for(var i = true && false; true && false; i = true && false) {
370   //   return;
371   // }
372   Func("a_statement", {}, ty.void_(), {});
373 
374   auto* multi_stmt_a = create<ast::BinaryExpression>(ast::BinaryOp::kLogicalAnd,
375                                                      Expr(true), Expr(false));
376   auto* multi_stmt_b = create<ast::BinaryExpression>(ast::BinaryOp::kLogicalAnd,
377                                                      Expr(true), Expr(false));
378   auto* multi_stmt_c = create<ast::BinaryExpression>(ast::BinaryOp::kLogicalAnd,
379                                                      Expr(true), Expr(false));
380 
381   auto* f =
382       For(Decl(Var("i", nullptr, multi_stmt_a)), multi_stmt_b,
383           Assign("i", multi_stmt_c), Block(CallStmt(Call("a_statement"))));
384   WrapInFunction(f);
385 
386   GeneratorImpl& gen = Build();
387 
388   gen.increment_indent();
389 
390   ASSERT_TRUE(gen.EmitStatement(f)) << gen.error();
391   EXPECT_EQ(gen.result(), R"(  {
392     bool tint_tmp = true;
393     if (tint_tmp) {
394       tint_tmp = false;
395     }
396     bool i = (tint_tmp);
397     [loop] while (true) {
398       bool tint_tmp_1 = true;
399       if (tint_tmp_1) {
400         tint_tmp_1 = false;
401       }
402       if (!((tint_tmp_1))) { break; }
403       a_statement();
404       bool tint_tmp_2 = true;
405       if (tint_tmp_2) {
406         tint_tmp_2 = false;
407       }
408       i = (tint_tmp_2);
409     }
410   }
411 )");
412 }
413 
414 }  // namespace
415 }  // namespace hlsl
416 }  // namespace writer
417 }  // namespace tint
418