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.io.StringWriter; 25 import java.lang.reflect.Member; 26 import java.lang.reflect.Method; 27 import jdk.incubator.code.Op; 28 import jdk.incubator.code.OpTransformer; 29 import jdk.incubator.code.analysis.SSA; 30 import jdk.incubator.code.op.CoreOp; 31 import jdk.incubator.code.op.ExtendedOp; 32 import jdk.incubator.code.parser.OpParser; 33 import jdk.incubator.code.writer.OpWriter; 34 import jdk.incubator.code.CodeReflection; 35 36 public class CodeReflectionTester { 37 38 public static void main(String[] args) throws ReflectiveOperationException { 39 if (args.length != 1) { 40 System.err.println("Usage: CodeReflectionTester <classname>"); 41 System.exit(1); 42 } 43 Class<?> clazz = Class.forName(args[0]); 44 for (Method m : clazz.getDeclaredMethods()) { 45 check(m); 46 } 47 } 48 49 static void check(Method method) throws ReflectiveOperationException { 50 if (!method.isAnnotationPresent(CodeReflection.class)) { 51 return; 52 } 53 54 LoweredModel lma = method.getAnnotation(LoweredModel.class); 55 if (lma == null) { 56 throw new AssertionError("No @IR annotation found on reflective method"); 57 } 58 59 CoreOp.FuncOp f = Op.ofMethod(method).orElseThrow(() -> 60 new AssertionError("No code model for reflective method")); 61 f = lower(f, lma.ssa()); 62 63 String actual = canonicalizeModel(method, f); 64 String expected = canonicalizeModel(method, lma.value()); 65 if (!actual.equals(expected)) { 66 throw new AssertionError(String.format("Bad code model\nFound:\n%s\n\nExpected:\n%s", actual, expected)); 67 } 68 } 69 70 static CoreOp.FuncOp lower(CoreOp.FuncOp f, boolean ssa) { 71 f = f.transform(OpTransformer.LOWERING_TRANSFORMER); 72 f.writeTo(System.out); 73 74 if (ssa) { 75 f = SSA.transform(f); 76 f.writeTo(System.out); 77 } 78 79 return f; 80 } 81 82 // serializes dropping location information, parses, and then serializes, dropping location information 83 static String canonicalizeModel(Member m, Op o) { 84 return canonicalizeModel(m, serialize(o)); 85 } 86 87 // parses, and then serializes, dropping location information 88 static String canonicalizeModel(Member m, String d) { 89 Op o; 90 try { 91 o = OpParser.fromString(ExtendedOp.FACTORY, d).get(0); 92 } catch (Exception e) { 93 throw new IllegalStateException(m.toString(), e); 94 } 95 return serialize(o); 96 } 97 98 // serializes, dropping location information 99 static String serialize(Op o) { 100 StringWriter w = new StringWriter(); 101 OpWriter.writeTo(w, o, OpWriter.LocationOption.DROP_LOCATION); 102 return w.toString(); 103 } 104 }