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