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