1 /*
  2  * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.
  8  *
  9  * This code is distributed in the hope that it will be useful, but WITHOUT
 10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 12  * version 2 for more details (a copy is included in the LICENSE file that
 13  * accompanied this code).
 14  *
 15  * You should have received a copy of the GNU General Public License version
 16  * 2 along with this work; if not, write to the Free Software Foundation,
 17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 18  *
 19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 20  * or visit www.oracle.com if you need additional information or have any
 21  * questions.
 22  */
 23 
 24 import jdk.incubator.code.CodeReflection;
 25 import java.util.List;
 26 
 27 /*
 28  * @test
 29  * @summary Smoke test for code reflection with for loops.
 30  * @modules jdk.incubator.code
 31  * @build ForLoopTest
 32  * @build CodeReflectionTester
 33  * @run main CodeReflectionTester ForLoopTest
 34  */
 35 
 36 public class ForLoopTest {
 37     @CodeReflection
 38     @IR("""
 39             func @"test1" (%0 : ForLoopTest, %1 : java.util.List<java.util.List<java.lang.String>>)void -> {
 40               %2 : Var<java.util.List<java.util.List<java.lang.String>>> = var %1 @"ll";
 41               java.enhancedFor
 42                   ^expr()java.util.List<java.util.List<java.lang.String>> -> {
 43                       %3 : java.util.List<java.util.List<java.lang.String>> = var.load %2;
 44                       yield %3;
 45                   }
 46                   ^def(%4 : java.util.List<java.lang.String>)Var<java.util.List<java.lang.String>> -> {
 47                       %5 : Var<java.util.List<java.lang.String>> = var %4 @"l";
 48                       yield %5;
 49                   }
 50                   ^body(%6 : Var<java.util.List<java.lang.String>>)void -> {
 51                       java.enhancedFor
 52                           ^expr()java.util.List<java.lang.String> -> {
 53                               %7 : java.util.List<java.lang.String> = var.load %6;
 54                               yield %7;
 55                           }
 56                           ^def(%8 : java.lang.String)Var<java.lang.String> -> {
 57                               %9 : Var<java.lang.String> = var %8 @"s";
 58                               yield %9;
 59                           }
 60                           ^body(%10 : Var<java.lang.String>)void -> {
 61                               %11 : java.io.PrintStream = field.load @"java.lang.System::out()java.io.PrintStream";
 62                               %12 : java.lang.String = var.load %10;
 63                               invoke %11 %12 @"java.io.PrintStream::println(java.lang.String)void";
 64                               java.continue;
 65                           };
 66                       java.continue;
 67                   };
 68               return;
 69             };
 70             """)
 71     void test1(List<List<String>> ll) {
 72         for (List<String> l : ll) {
 73             for (String s : l) {
 74                 System.out.println(s);
 75             }
 76         }
 77     }
 78 
 79     @CodeReflection
 80     @IR("""
 81             func @"test2" (%0 : ForLoopTest, %1 : java.util.List<java.lang.String>)void -> {
 82                 %2 : Var<java.util.List<java.lang.String>> = var %1 @"l";
 83                 java.enhancedFor
 84                     ^expr()java.util.List<java.lang.String> -> {
 85                         %3 : java.util.List<java.lang.String> = var.load %2;
 86                         %4 : java.util.stream.Stream<java.lang.String> = invoke %3 @"java.util.List::stream()java.util.stream.Stream";
 87                         %5 : java.util.function.Predicate<java.lang.String> = lambda (%6 : java.lang.String)boolean -> {
 88                             %7 : Var<java.lang.String> = var %6 @"s";
 89                             %8 : java.lang.String = var.load %7;
 90                             %9 : int = invoke %8 @"java.lang.String::length()int";
 91                             %10 : int = constant @"10";
 92                             %11 : boolean = lt %9 %10;
 93                             return %11;
 94                         };
 95                         %12 : java.util.stream.Stream<java.lang.String> = invoke %4 %5 @"java.util.stream.Stream::filter(java.util.function.Predicate)java.util.stream.Stream";
 96                         %13 : java.util.List<java.lang.String> = invoke %12 @"java.util.stream.Stream::toList()java.util.List";
 97                         yield %13;
 98                     }
 99                     ^def(%14 : java.lang.String)Var<java.lang.String> -> {
100                         %15 : Var<java.lang.String> = var %14 @"s";
101                         yield %15;
102                     }
103                     ^body(%16 : Var<java.lang.String>)void -> {
104                         %17 : java.io.PrintStream = field.load @"java.lang.System::out()java.io.PrintStream";
105                         %18 : java.lang.String = var.load %16;
106                         invoke %17 %18 @"java.io.PrintStream::println(java.lang.String)void";
107                         java.continue;
108                     };
109                 return;
110             };
111             """)
112     void test2(List<String> l) {
113         for (String s : l.stream().filter(s -> s.length() < 10).toList()) {
114             System.out.println(s);
115         }
116     }
117 
118     @CodeReflection
119     @IR("""
120             func @"test2_1" (%0 : ForLoopTest, %1 : java.util.List<java.lang.String>)void -> {
121               %2 : Var<java.util.List<java.lang.String>> = var %1 @"l";
122               java.enhancedFor
123                   ^expr()java.util.List<java.lang.String> -> {
124                       %3 : java.util.List<java.lang.String> = var.load %2;
125                       yield %3;
126                   }
127                   ^def(%4 : java.lang.String)Var<java.lang.String> -> {
128                       %5 : Var<java.lang.String> = var %4 @"s";
129                       yield %5;
130                   }
131                   ^body(%6 : Var<java.lang.String>)void -> {
132                       java.continue;
133                   };
134               return;
135             };
136             """)
137     void test2_1(List<String> l) {
138         for (String s : l);
139     }
140 
141     @CodeReflection
142     @IR("""
143             func @"test2_2" (%0 : ForLoopTest, %1 : java.util.List<java.lang.String>)java.lang.String -> {
144               %2 : Var<java.util.List<java.lang.String>> = var %1 @"l";
145               java.enhancedFor
146                   ^expr()java.util.List<java.lang.String> -> {
147                       %3 : java.util.List<java.lang.String> = var.load %2;
148                       yield %3;
149                   }
150                   ^def(%4 : java.lang.String)Var<java.lang.String> -> {
151                       %5 : Var<java.lang.String> = var %4 @"s";
152                       yield %5;
153                   }
154                   ^body(%6 : Var<java.lang.String>)void -> {
155                       %7 : java.lang.String = var.load %6;
156                       return %7;
157                   };
158               %8 : java.lang.String = constant @"";
159               return %8;
160             };
161             """)
162     String test2_2(List<String> l) {
163         for (String s : l) {
164             return s;
165         }
166         return "";
167     }
168 
169     @CodeReflection
170     @IR("""
171             func @"test3" (%0 : ForLoopTest)void -> {
172                 java.for
173                     ^init()Var<int> -> {
174                         %1 : int = constant @"0";
175                         %2 : Var<int> = var %1 @"i";
176                         yield %2;
177                     }
178                     ^cond(%3 : Var<int>)boolean -> {
179                         %4 : int = var.load %3;
180                         %5 : int = constant @"10";
181                         %6 : boolean = lt %4 %5;
182                         yield %6;
183                     }
184                     ^update(%7 : Var<int>)void -> {
185                         %8 : int = var.load %7;
186                         %9 : int = constant @"1";
187                         %10 : int = add %8 %9;
188                         var.store %7 %10;
189                         yield;
190                     }
191                     ^body(%11 : Var<int>)void -> {
192                         %12 : java.io.PrintStream = field.load @"java.lang.System::out()java.io.PrintStream";
193                         %13 : int = var.load %11;
194                         invoke %12 %13 @"java.io.PrintStream::println(int)void";
195                         java.continue;
196                     };
197                 return;
198             };
199             """)
200     void test3() {
201         for (int i = 0; i < 10; i++) {
202             System.out.println(i);
203         }
204     }
205 
206     @CodeReflection
207     @IR("""
208             func @"test3_1" (%0 : ForLoopTest)int -> {
209                 java.for
210                     ^init()Var<int> -> {
211                         %1 : int = constant @"0";
212                         %2 : Var<int> = var %1 @"i";
213                         yield %2;
214                     }
215                     ^cond(%3 : Var<int>)boolean -> {
216                         %4 : int = var.load %3;
217                         %5 : int = constant @"10";
218                         %6 : boolean = lt %4 %5;
219                         yield %6;
220                     }
221                     ^update(%7 : Var<int>)void -> {
222                         %8 : int = var.load %7;
223                         %9 : int = constant @"1";
224                         %10 : int = add %8 %9;
225                         var.store %7 %10;
226                         yield;
227                     }
228                     ^body(%11 : Var<int>)void -> {
229                         %12 : int = var.load %11;
230                         return %12;
231                     };
232                 %13 : int = constant @"-1";
233                 return %13;
234             };
235             """)
236     int test3_1() {
237         for (int i = 0; i < 10; i++) {
238             return i;
239         }
240         return -1;
241     }
242 
243     @CodeReflection
244     @IR("""
245             func @"test4" (%0 : ForLoopTest)void -> {
246                 java.for
247                     ^init()Var<int> -> {
248                         %1 : int = constant @"0";
249                         %2 : Var<int> = var %1 @"i";
250                         yield %2;
251                     }
252                     ^cond(%3 : Var<int>)boolean -> {
253                         %4 : int = var.load %3;
254                         %5 : int = constant @"10";
255                         %6 : boolean = lt %4 %5;
256                         yield %6;
257                     }
258                     ^update(%7 : Var<int>)void -> {
259                         %8 : int = var.load %7;
260                         %9 : int = constant @"1";
261                         %10 : int = add %8 %9;
262                         var.store %7 %10;
263                         yield;
264                     }
265                     ^body(%11 : Var<int>)void -> {
266                         %12 : java.io.PrintStream = field.load @"java.lang.System::out()java.io.PrintStream";
267                         %13 : int = var.load %11;
268                         invoke %12 %13 @"java.io.PrintStream::println(int)void";
269                         java.continue;
270                     };
271                 return;
272             };
273             """)
274     void test4() {
275         for (int i = 0; i < 10; i = i + 1)
276             System.out.println(i);
277     }
278 
279     @CodeReflection
280     @IR("""
281             func @"test5" (%0 : ForLoopTest)void -> {
282                 java.for
283                     ^init()Var<int> -> {
284                         %1 : int = constant @"0";
285                         %2 : Var<int> = var %1 @"i";
286                         yield %2;
287                     }
288                     ^cond(%3 : Var<int>)boolean -> {
289                         %4 : int = var.load %3;
290                         %5 : int = constant @"10";
291                         %6 : boolean = lt %4 %5;
292                         yield %6;
293                     }
294                     ^update(%7 : Var<int>)void -> {
295                         %8 : int = var.load %7;
296                         %9 : int = constant @"1";
297                         %10 : int = add %8 %9;
298                         var.store %7 %10;
299                         yield;
300                     }
301                     ^body(%11 : Var<int>)void -> {
302                         java.continue;
303                     };
304                 return;
305             };
306             """)
307     void test5() {
308         for (int i = 0; i < 10; i = i + 1);
309     }
310 
311     @CodeReflection
312     @IR("""
313             func @"test6" (%0 : ForLoopTest)void -> {
314                 %1 : int = constant @"0";
315                 %2 : Var<int> = var %1 @"i";
316                 java.for
317                     ^init()void -> {
318                         yield;
319                     }
320                     ^cond()boolean -> {
321                         %3 : int = var.load %2;
322                         %4 : int = constant @"10";
323                         %5 : boolean = lt %3 %4;
324                         yield %5;
325                     }
326                     ^update()void -> {
327                         %6 : int = var.load %2;
328                         %7 : int = constant @"1";
329                         %8 : int = add %6 %7;
330                         var.store %2 %8;
331                         yield;
332                     }
333                     ^body()void -> {
334                         %9 : java.io.PrintStream = field.load @"java.lang.System::out()java.io.PrintStream";
335                         %10 : int = var.load %2;
336                         invoke %9 %10 @"java.io.PrintStream::println(int)void";
337                         java.continue;
338                     };
339                 return;
340             };
341             """)
342     void test6() {
343         int i = 0;
344         for (; i < 10; i = i + 1) {
345             System.out.println(i);
346         }
347     }
348 
349     @CodeReflection
350     @IR("""
351             func @"test7" (%0 : ForLoopTest)void -> {
352                 %1 : int = constant @"0";
353                 %2 : Var<int> = var %1 @"i";
354                 java.for
355                     ^init()void -> {
356                         %3 : int = var.load %2;
357                         %4 : int = constant @"1";
358                         %5 : int = add %3 %4;
359                         var.store %2 %5;
360                         yield;
361                     }
362                     ^cond()boolean -> {
363                         %6 : int = var.load %2;
364                         %7 : int = constant @"10";
365                         %8 : boolean = lt %6 %7;
366                         yield %8;
367                     }
368                     ^update()void -> {
369                         %9 : int = var.load %2;
370                         %10 : int = constant @"1";
371                         %11 : int = add %9 %10;
372                         var.store %2 %11;
373                         yield;
374                     }
375                     ^body()void -> {
376                         %12 : java.io.PrintStream = field.load @"java.lang.System::out()java.io.PrintStream";
377                         %13 : int = var.load %2;
378                         invoke %12 %13 @"java.io.PrintStream::println(int)void";
379                         java.continue;
380                     };
381                 return;
382             };
383             """)
384     void test7() {
385         int i = 0;
386         for (i = i + 1; i < 10; i = i + 1) {
387             System.out.println(i);
388         }
389     }
390 
391     @CodeReflection
392     @IR("""
393             func @"test8" (%0 : ForLoopTest)void -> {
394                 java.for
395                     ^init()Var<int> -> {
396                         %1 : int = constant @"0";
397                         %2 : Var<int> = var %1 @"i";
398                         yield %2;
399                     }
400                     ^cond(%3 : Var<int>)boolean -> {
401                         %4 : boolean = constant @"true";
402                         yield %4;
403                     }
404                     ^update(%5 : Var<int>)void -> {
405                         %6 : int = var.load %5;
406                         %7 : int = constant @"1";
407                         %8 : int = add %6 %7;
408                         var.store %5 %8;
409                         yield;
410                     }
411                     ^body(%9 : Var<int>)void -> {
412                         %10 : java.io.PrintStream = field.load @"java.lang.System::out()java.io.PrintStream";
413                         %11 : int = var.load %9;
414                         invoke %10 %11 @"java.io.PrintStream::println(int)void";
415                         java.continue;
416                     };
417                 unreachable;
418             };
419             """)
420     void test8() {
421         for (int i = 0; ; i = i + 1) {
422             System.out.println(i);
423         }
424     }
425 
426     @CodeReflection
427     @IR("""
428             func @"test9" (%0 : ForLoopTest)void -> {
429                 java.for
430                     ^init()Var<int> -> {
431                         %1 : int = constant @"0";
432                         %2 : Var<int> = var %1 @"i";
433                         yield %2;
434                     }
435                     ^cond(%3 : Var<int>)boolean -> {
436                         %4 : boolean = constant @"true";
437                         yield %4;
438                     }
439                     ^update(%5 : Var<int>)void -> {
440                         yield;
441                     }
442                     ^body(%6 : Var<int>)void -> {
443                         %7 : java.io.PrintStream = field.load @"java.lang.System::out()java.io.PrintStream";
444                         %8 : int = var.load %6;
445                         invoke %7 %8 @"java.io.PrintStream::println(int)void";
446                         java.continue;
447                     };
448                 unreachable;
449             };
450             """)
451     void test9() {
452         for (int i = 0; ; ) {
453             System.out.println(i);
454         }
455     }
456 
457     @CodeReflection
458     @IR("""
459             func @"test10" (%0 : ForLoopTest)void -> {
460                 java.for
461                     ^init()void -> {
462                         yield;
463                     }
464                     ^cond()boolean -> {
465                         %1 : boolean = constant @"true";
466                         yield %1;
467                     }
468                     ^update()void -> {
469                         yield;
470                     }
471                     ^body()void -> {
472                         java.continue;
473                     };
474                 unreachable;
475             };
476             """)
477     void test10() {
478         for (; ; ) {
479         }
480     }
481 
482     @CodeReflection
483     @IR("""
484             func @"test11" (%0 : ForLoopTest)void -> {
485                 java.for
486                     ^init()Tuple<Var<int>, Var<int>> -> {
487                         %1 : int = constant @"0";
488                         %2 : Var<int> = var %1 @"i";
489                         %3 : int = constant @"0";
490                         %4 : Var<int> = var %3 @"j";
491                         %5 : Tuple<Var<int>, Var<int>> = tuple %2 %4;
492                         yield %5;
493                     }
494                     ^cond(%6 : Var<int>, %7 : Var<int>)boolean -> {
495                         %8 : boolean = java.cand
496                             ()boolean -> {
497                                 %9 : int = var.load %6;
498                                 %10 : int = constant @"10";
499                                 %11 : boolean = lt %9 %10;
500                                 yield %11;
501                             }
502                             ()boolean -> {
503                                 %12 : int = var.load %7;
504                                 %13 : int = constant @"20";
505                                 %14 : boolean = lt %12 %13;
506                                 yield %14;
507                             };
508                         yield %8;
509                     }
510                     ^update(%15 : Var<int>, %16 : Var<int>)void -> {
511                         %17 : int = var.load %15;
512                         %18 : int = constant @"1";
513                         %19 : int = add %17 %18;
514                         var.store %15 %19;
515                         %20 : int = var.load %16;
516                         %21 : int = constant @"2";
517                         %22 : int = add %20 %21;
518                         var.store %16 %22;
519                         yield;
520                     }
521                     ^body(%23 : Var<int>, %24 : Var<int>)void -> {
522                         %25 : java.io.PrintStream = field.load @"java.lang.System::out()java.io.PrintStream";
523                         %26 : int = var.load %23;
524                         invoke %25 %26 @"java.io.PrintStream::println(int)void";
525                         %27 : java.io.PrintStream = field.load @"java.lang.System::out()java.io.PrintStream";
526                         %28 : int = var.load %24;
527                         invoke %27 %28 @"java.io.PrintStream::println(int)void";
528                         java.continue;
529                     };
530                 return;
531             };
532             """)
533     void test11() {
534         for (int i = 0, j = 0; i < 10 && j < 20; i = i + 1, j = j + 2) {
535             System.out.println(i);
536             System.out.println(j);
537         }
538     }
539 
540     @CodeReflection
541     @IR("""
542             func @"test12" (%0 : ForLoopTest, %1 : int)void -> {
543                 %2 : Var<int> = var %1 @"r";
544                 java.for
545                     ^init()Var<int> -> {
546                         %3 : int = constant @"0";
547                         %4 : Var<int> = var %3 @"i";
548                         yield %4;
549                     }
550                     ^cond(%5 : Var<int>)boolean -> {
551                         %6 : int = var.load %5;
552                         %7 : int = constant @"10";
553                         %8 : boolean = lt %6 %7;
554                         yield %8;
555                     }
556                     ^update(%9 : Var<int>)void -> {
557                         %10 : int = var.load %9;
558                         %11 : int = constant @"1";
559                         %12 : int = add %10 %11;
560                         var.store %9 %12;
561                         yield;
562                     }
563                     ^body(%13 : Var<int>)void -> {
564                         java.if
565                             ()boolean -> {
566                                 %14 : int = var.load %2;
567                                 %15 : int = constant @"0";
568                                 %16 : boolean = eq %14 %15;
569                                 yield %16;
570                             }
571                             ^then()void -> {
572                                 java.break;
573                             }
574                             ^else_if()boolean -> {
575                                 %17 : int = var.load %2;
576                                 %18 : int = constant @"1";
577                                 %19 : boolean = eq %17 %18;
578                                 yield %19;
579                             }
580                             ^then()void -> {
581                                 java.continue;
582                             }
583                             ^else()void -> {
584                                 yield;
585                             };
586                         java.continue;
587                     };
588                 return;
589             };
590             """)
591     void test12(int r) {
592         for (int i = 0; i < 10; i++) {
593             if (r == 0) {
594                 break;
595             } else if (r == 1) {
596                 continue;
597             }
598         }
599     }
600 
601 }