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 /*
25 * @test
26 * @modules jdk.incubator.code
27 * @run junit TestBreakContinue
28 * @run main Unreflect TestBreakContinue
29 * @run junit TestBreakContinue
30 */
31
32 import jdk.incubator.code.Reflect;
33 import jdk.incubator.code.CodeTransformer;
34 import jdk.incubator.code.Op;
35 import jdk.incubator.code.dialect.core.CoreOp;
36 import jdk.incubator.code.interpreter.Interpreter;
37 import org.junit.jupiter.api.Assertions;
38 import org.junit.jupiter.api.Test;
39
40 import java.lang.invoke.MethodHandles;
41 import java.lang.reflect.Method;
42 import java.util.BitSet;
43 import java.util.Optional;
44 import java.util.function.IntUnaryOperator;
45 import java.util.stream.Stream;
46
47 public class TestBreakContinue {
48
49 @Reflect
50 public static BitSet forLoopBreakContinue(IntUnaryOperator f) {
51 BitSet b = new BitSet();
52 for (int i = 0; i < 8; i++) {
53 b.set(i);
54 int r = f.applyAsInt(i);
55 if (r == 0) {
56 continue;
57 } else if (r == 1) {
58 break;
59 }
60 b.set(i * 2);
61 }
62 return b;
63 }
64
65 @Test
66 public void testForLoopBreakContinue() {
67 CoreOp.FuncOp f = getFuncOp("forLoopBreakContinue");
68
69 System.out.println(f.toText());
70
71 CoreOp.FuncOp lf = f.transform(CodeTransformer.LOWERING_TRANSFORMER);
72
73 System.out.println(lf.toText());
74
75 IntUnaryOperator o = i -> {
76 if (i <= 3) return -1;
77 if (i <= 5) return 0;
78 return 1;
79 };
80 Assertions.assertEquals(forLoopBreakContinue(o), Interpreter.invoke(MethodHandles.lookup(), lf, o));
81 }
82
83 @Reflect
84 public static BitSet nestedForLoopBreakContinue(IntUnaryOperator f) {
85 BitSet b = new BitSet();
86 for (int j = 0; j < 8; j++) {
87 b.set(j);
88 int r = f.applyAsInt(j);
89 if (r == 0) {
90 continue;
91 } else if (r == 1) {
92 break;
93 }
94 for (int i = 8; i < 16; i++) {
95 b.set(i);
96 r = f.applyAsInt(i);
97 if (r == 2) {
98 continue;
99 } else if (r == 3) {
100 break;
101 }
102 b.set(i * 2);
103 }
104 b.set(j * 2);
105 }
106 return b;
107 }
108
109 @Test
110 public void testNestedForLoopBreakContinue() {
111 CoreOp.FuncOp f = getFuncOp("nestedForLoopBreakContinue");
112
113 System.out.println(f.toText());
114
115 CoreOp.FuncOp lf = f.transform(CodeTransformer.LOWERING_TRANSFORMER);
116
117 System.out.println(lf.toText());
118
119 for (int r = -1; r < 4; r++) {
120 int fr = r;
121 IntUnaryOperator o = i -> fr;
122 Assertions.assertEquals(nestedForLoopBreakContinue(o), Interpreter.invoke(MethodHandles.lookup(), lf, o));
123 }
124 }
125
126
127 @Reflect
128 public static BitSet forLoopLabeledBreakContinue(IntUnaryOperator f) {
129 BitSet b = new BitSet();
130 outer: for (int j = 0; j < 8; j++) {
131 b.set(j);
132 int r = f.applyAsInt(j);
133 if (r == 0) {
134 continue outer;
135 } else if (r == 1) {
136 break outer;
137 }
138 inner: for (int i = 8; i < 16; i++) {
139 b.set(i);
140 r = f.applyAsInt(i);
141 if (r == 2) {
142 continue inner;
143 } else if (r == 3) {
144 break inner;
145 } else if (r == 4) {
146 continue outer;
147 } else if (r == 5) {
148 break outer;
149 }
150 b.set(i * 2);
151 }
152 b.set(j * 2);
153 }
154 return b;
155 }
156
157 @Test
158 public void testForLoopLabeledBreakContinue() {
159 CoreOp.FuncOp f = getFuncOp("forLoopLabeledBreakContinue");
160
161 System.out.println(f.toText());
162
163 CoreOp.FuncOp lf = f.transform(CodeTransformer.LOWERING_TRANSFORMER);
164
165 System.out.println(lf.toText());
166
167 for (int r = -1; r < 6; r++) {
168 int fr = r;
169 IntUnaryOperator o = i -> fr;
170 Assertions.assertEquals(forLoopLabeledBreakContinue(o), Interpreter.invoke(MethodHandles.lookup(), lf, o));
171 }
172 }
173
174 @Reflect
175 public static BitSet blockBreak(IntUnaryOperator f) {
176 BitSet b = new BitSet();
177 a: b: {
178 b.set(1);
179 if (f.applyAsInt(1) != 0) {
180 break a;
181 }
182 b.set(2);
183 if (f.applyAsInt(2) != 0) {
184 break b;
185 }
186 b.set(3);
187 c: {
188 b.set(4);
189 if (f.applyAsInt(4) != 0) {
190 break a;
191 }
192 b.set(5);
193 if (f.applyAsInt(5) != 0) {
194 break b;
195 }
196 b.set(6);
197 if (f.applyAsInt(6) != 0) {
198 break c;
199 }
200 b.set(7);
201 }
202 b.set(8);
203 }
204 return b;
205 }
206
207 @Test
208 public void testBlockBreak() {
209 CoreOp.FuncOp f = getFuncOp("blockBreak");
210
211 System.out.println(f.toText());
212
213 CoreOp.FuncOp lf = f.transform(CodeTransformer.LOWERING_TRANSFORMER);
214
215 System.out.println(lf.toText());
216
217 for (int i = 0; i < 7; i++) {
218 int fi = i;
219 IntUnaryOperator o = v -> v == fi ? 1 : 0;
220 Assertions.assertEquals(blockBreak(o), Interpreter.invoke(MethodHandles.lookup(), lf, o));
221 }
222 }
223
224
225 static CoreOp.FuncOp getFuncOp(String name) {
226 Optional<Method> om = Stream.of(TestBreakContinue.class.getDeclaredMethods())
227 .filter(m -> m.getName().equals(name))
228 .findFirst();
229
230 Method m = om.get();
231 return Op.ofMethod(m).get();
232 }
233 }