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 testng TestNormalizeBlocksTransformer 28 */ 29 30 import org.testng.Assert; 31 import org.testng.annotations.DataProvider; 32 import org.testng.annotations.Test; 33 34 import jdk.incubator.code.Op; 35 import jdk.incubator.code.analysis.NormalizeBlocksTransformer; 36 import jdk.incubator.code.op.ExtendedOp; 37 import jdk.incubator.code.parser.OpParser; 38 import java.util.stream.Stream; 39 40 public class TestNormalizeBlocksTransformer { 41 static final String TEST1_INPUT = """ 42 func @"f" (%0 : int)int -> { 43 %1 : int = invoke @"C::m()int"; 44 branch ^block_1; 45 46 ^block_1: 47 %2 : int = invoke %1 @"C::m(int)int"; 48 branch ^block_2(%2); 49 50 ^block_2(%3: int): 51 %4 : int = invoke %2 %3 @"C::m(int, int)int"; 52 branch ^block_3(%3); 53 54 ^block_3(%5: int): 55 %6 : int = invoke %4 %3 %5 @"C::m(int, int, int)int"; 56 branch ^block_4; 57 58 ^block_4: 59 return %6; 60 }; 61 """; 62 static final String TEST1_EXPECTED = """ 63 func @"f" (%0 : int)int -> { 64 %1 : int = invoke @"C::m()int"; 65 %2 : int = invoke %1 @"C::m(int)int"; 66 %3 : int = invoke %2 %2 @"C::m(int, int)int"; 67 %4 : int = invoke %3 %2 %2 @"C::m(int, int, int)int"; 68 return %4; 69 }; 70 """; 71 72 static final String TEST2_INPUT = """ 73 func @"f" (%0 : java.lang.Object)void -> { 74 %1 : Var<java.lang.Object> = var %0 @"o"; 75 exception.region.enter ^block_1 ^block_8 ^block_3; 76 77 ^block_1: 78 %3 : int = invoke @"A::try_()int"; 79 branch ^block_2; 80 81 ^block_2: 82 exception.region.exit ^block_6 ^block_3 ^block_8; 83 84 ^block_3(%4 : java.lang.RuntimeException): 85 exception.region.enter ^block_4 ^block_8; 86 87 ^block_4: 88 %6 : Var<java.lang.RuntimeException> = var %4 @"e"; 89 branch ^block_5; 90 91 ^block_5: 92 exception.region.exit ^block_6 ^block_8; 93 94 ^block_6: 95 %7 : int = invoke @"A::finally_()int"; 96 branch ^block_7; 97 98 ^block_7: 99 return; 100 101 ^block_8(%8 : java.lang.Throwable): 102 %9 : int = invoke @"A::finally_()int"; 103 throw %8; 104 }; 105 """; 106 static final String TEST2_EXPECTED = """ 107 func @"f" (%0 : java.lang.Object)void -> { 108 %1 : Var<java.lang.Object> = var %0 @"o"; 109 exception.region.enter ^block_1 ^block_5 ^block_2; 110 111 ^block_1: 112 %3 : int = invoke @"A::try_()int"; 113 exception.region.exit ^block_4 ^block_2 ^block_5; 114 115 ^block_2(%4 : java.lang.RuntimeException): 116 exception.region.enter ^block_3 ^block_5; 117 118 ^block_3: 119 %6 : Var<java.lang.RuntimeException> = var %4 @"e"; 120 exception.region.exit ^block_4 ^block_5; 121 122 ^block_4: 123 %7 : int = invoke @"A::finally_()int"; 124 return; 125 126 ^block_5(%8 : java.lang.Throwable): 127 %9 : int = invoke @"A::finally_()int"; 128 throw %8; 129 };"""; 130 131 static final String TEST3_INPUT = """ 132 func @"f" (%0 : int)int -> { 133 %1 : int = constant @"0"; 134 %2 : boolean = gt %0 %1; 135 cbranch %2 ^block_1 ^block_2; 136 137 ^block_1: 138 %3 : int = constant @"1"; 139 branch ^block_1_1; 140 141 ^block_1_1: 142 branch ^block_3(%3); 143 144 ^block_2: 145 %4 : int = constant @"-1"; 146 branch ^block_2_1; 147 148 ^block_2_1: 149 branch ^block_3(%4); 150 151 ^block_3(%5 : int): 152 return %5; 153 };"""; 154 static final String TEST3_EXPECTED = """ 155 func @"f" (%0 : int)int -> { 156 %1 : int = constant @"0"; 157 %2 : boolean = gt %0 %1; 158 cbranch %2 ^block_1 ^block_2; 159 160 ^block_1: 161 %3 : int = constant @"1"; 162 branch ^block_3(%3); 163 164 ^block_2: 165 %4 : int = constant @"-1"; 166 branch ^block_3(%4); 167 168 ^block_3(%5 : int): 169 return %5; 170 }; 171 """; 172 173 static final String TEST4_INPUT = """ 174 func @"f" (%0 : int)int -> { 175 %1 : int = constant @"0"; 176 %2 : boolean = gt %0 %1; 177 cbranch %2 ^block_1 ^block_2; 178 179 ^block_1: 180 %3 : int = constant @"1"; 181 branch ^block_1_1; 182 183 ^block_1_1: 184 branch ^block_3(%0, %3, %1); 185 186 ^block_2: 187 %4 : int = constant @"-1"; 188 branch ^block_2_1; 189 190 ^block_2_1: 191 branch ^block_3(%0, %4, %1); 192 193 ^block_3(%unused_1 : int, %5 : int, %unused_2 : int): 194 return %5; 195 };"""; 196 static final String TEST4_EXPECTED = """ 197 func @"f" (%0 : int)int -> { 198 %1 : int = constant @"0"; 199 %2 : boolean = gt %0 %1; 200 cbranch %2 ^block_1 ^block_2; 201 202 ^block_1: 203 %3 : int = constant @"1"; 204 branch ^block_3(%3); 205 206 ^block_2: 207 %4 : int = constant @"-1"; 208 branch ^block_3(%4); 209 210 ^block_3(%5 : int): 211 return %5; 212 }; 213 """; 214 215 static final String TEST5_INPUT = """ 216 func @"f" ()void -> { 217 exception.region.enter ^block_1 ^block_4; 218 219 ^block_1: 220 invoke @"A::m()void"; 221 branch ^block_2; 222 223 ^block_2: 224 exception.region.exit ^block_3 ^block_4; 225 226 ^block_3: 227 branch ^block_5; 228 229 ^block_4(%1 : java.lang.Throwable): 230 branch ^block_5; 231 232 ^block_5: 233 return; 234 }; 235 """; 236 static final String TEST5_EXPECTED = """ 237 func @"f" ()void -> { 238 exception.region.enter ^block_1 ^block_3; 239 240 ^block_1: 241 invoke @"A::m()void"; 242 exception.region.exit ^block_2 ^block_3; 243 244 ^block_2: 245 branch ^block_4; 246 247 ^block_3(%1 : java.lang.Throwable): 248 branch ^block_4; 249 250 ^block_4: 251 return; 252 }; 253 """; 254 255 @DataProvider 256 static Object[][] testModels() { 257 return new Object[][]{ 258 parse(TEST1_INPUT, TEST1_EXPECTED), 259 parse(TEST2_INPUT, TEST2_EXPECTED), 260 parse(TEST3_INPUT, TEST3_EXPECTED), 261 parse(TEST4_INPUT, TEST4_EXPECTED), 262 parse(TEST5_INPUT, TEST5_EXPECTED), 263 }; 264 } 265 266 static Object[] parse(String... models) { 267 return Stream.of(models).map(s -> OpParser.fromString(ExtendedOp.FACTORY, s).getFirst()) 268 .toArray(Object[]::new); 269 } 270 271 @Test(dataProvider = "testModels") 272 public void test(Op input, Op expected) { 273 Op actual = NormalizeBlocksTransformer.transform(input); 274 Assert.assertEquals(actual.toText(), expected.toText()); 275 } 276 }