1/*
2 * Copyright (c) 2016, 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
24package jdk.test.lib.jittester.utils;
25
26import java.util.Arrays;
27import java.util.ArrayList;
28import java.util.LinkedList;
29import java.util.List;
30
31import jdk.test.lib.jittester.BinaryOperator;
32import jdk.test.lib.jittester.Block;
33import jdk.test.lib.jittester.CatchBlock;
34import jdk.test.lib.jittester.IRNode;
35import jdk.test.lib.jittester.Literal;
36import jdk.test.lib.jittester.LocalVariable;
37import jdk.test.lib.jittester.NonStaticMemberVariable;
38import jdk.test.lib.jittester.Nothing;
39import jdk.test.lib.jittester.Operator;
40import jdk.test.lib.jittester.OperatorKind;
41import jdk.test.lib.jittester.PrintVariables;
42import jdk.test.lib.jittester.Statement;
43import jdk.test.lib.jittester.StaticMemberVariable;
44import jdk.test.lib.jittester.Symbol;
45import jdk.test.lib.jittester.TryCatchBlock;
46import jdk.test.lib.jittester.Type;
47import jdk.test.lib.jittester.TypeList;
48import jdk.test.lib.jittester.VariableInfo;
49import jdk.test.lib.jittester.VariableInitialization;
50import jdk.test.lib.jittester.functions.ArgumentDeclaration;
51import jdk.test.lib.jittester.functions.Function;
52import jdk.test.lib.jittester.functions.FunctionDefinition;
53import jdk.test.lib.jittester.functions.FunctionInfo;
54import jdk.test.lib.jittester.functions.Return;
55import jdk.test.lib.jittester.jtreg.Printer;
56import jdk.test.lib.jittester.loops.CounterInitializer;
57import jdk.test.lib.jittester.loops.CounterManipulator;
58import jdk.test.lib.jittester.loops.For;
59import jdk.test.lib.jittester.loops.Loop;
60import jdk.test.lib.jittester.loops.LoopingCondition;
61import jdk.test.lib.jittester.types.TypeArray;
62import jdk.test.lib.jittester.types.TypeKlass;
63
64public class FixedTrees {
65    private static final Literal EOL = new Literal("\n", TypeList.STRING);
66
67    public static FunctionDefinition printVariablesAsFunction(PrintVariables node) {
68        TypeKlass owner = node.getOwner();
69
70        ArrayList<IRNode> nodes = new ArrayList<>();
71
72        VariableInfo resultInfo = new VariableInfo("result", node.getOwner(), TypeList.STRING, VariableInfo.LOCAL);
73        nodes.add(new Statement(new VariableInitialization(resultInfo, new Literal("[", TypeList.STRING)), true));
74        LocalVariable resultVar = new LocalVariable(resultInfo);
75
76        List<Symbol> vars = node.getVars();
77
78        TypeKlass printerKlass = new TypeKlass(Printer.class.getName());
79        VariableInfo thisInfo = new VariableInfo("this", node.getOwner(),
80                node.getOwner(), VariableInfo.LOCAL | VariableInfo.INITIALIZED);
81
82        LocalVariable thisVar = new LocalVariable(thisInfo);
83
84        for (int i = 0; i < vars.size(); i++) {
85            Symbol v = vars.get(i);
86            nodes.add(new Statement(new BinaryOperator(OperatorKind.COMPOUND_ADD, TypeList.STRING, resultVar,
87                    new Literal(v.owner.getName() + "." + v.name + " = ", TypeList.STRING)), true));
88            VariableInfo argInfo = new VariableInfo("arg", printerKlass,
89                    v.type instanceof TypeKlass ? TypeList.OBJECT : v.type,
90                    VariableInfo.LOCAL | VariableInfo.INITIALIZED);
91            FunctionInfo printInfo = new FunctionInfo("print", printerKlass,
92                    TypeList.STRING, 0,  FunctionInfo.PUBLIC | FunctionInfo.STATIC, argInfo);
93            Function call = new Function(owner, printInfo, null);
94            VariableInfo varInfo = new VariableInfo(v.name, v.owner, v.type, v.flags);
95            if (v.isStatic()) {
96                call.addChild(new StaticMemberVariable(v.owner, varInfo));
97            } else {
98                call.addChild(new NonStaticMemberVariable(thisVar, varInfo));
99            }
100            nodes.add(new Statement(new BinaryOperator(OperatorKind.COMPOUND_ADD, TypeList.STRING, resultVar,
101                    call), true));
102            if (i < vars.size() - 1) {
103                nodes.add(new Statement(new BinaryOperator(OperatorKind.COMPOUND_ADD, TypeList.STRING, resultVar,
104                        EOL), true));
105            }
106        }
107        nodes.add(new Statement(
108                new BinaryOperator(OperatorKind.COMPOUND_ADD, TypeList.STRING, resultVar, new Literal("]\n", TypeList.STRING)),
109                true));
110
111        Block block = new Block(node.getOwner(), TypeList.STRING, nodes, 1);
112        FunctionInfo toStringInfo = new FunctionInfo("toString", owner, TypeList.STRING, 0L, FunctionInfo.PUBLIC, thisInfo);
113        return new FunctionDefinition(toStringInfo, new ArrayList<>(), block, new Return(resultVar));
114    }
115
116    public static FunctionDefinition generateMainOrExecuteMethod(TypeKlass owner, boolean isMain) {
117        Nothing nothing = new Nothing();
118        ArrayList<IRNode> testCallNodeContent = new ArrayList<>();
119        VariableInfo tInfo = new VariableInfo("t", owner, owner, VariableInfo.LOCAL);
120        LocalVariable tVar = new LocalVariable(tInfo);
121        Function testCallNode = new Function(owner, new FunctionInfo("test", owner, TypeList.VOID,
122                0L, FunctionInfo.PRIVATE, tInfo), null);
123        testCallNode.addChild(tVar);
124        testCallNodeContent.add(new Statement(testCallNode, true));
125        // { t.test(); }
126        Block testCallNodeBlock = new Block(owner, TypeList.VOID, testCallNodeContent, 4);
127
128        IRNode tryNode = testCallNodeBlock;
129        if (isMain) {
130            VariableInfo iInfo = new VariableInfo("i", owner, TypeList.INT, VariableInfo.LOCAL);
131            LocalVariable iVar = new LocalVariable(iInfo);
132            Operator increaseCounter = new BinaryOperator(OperatorKind.ASSIGN, TypeList.INT,
133                    iVar,
134                    new BinaryOperator(OperatorKind.ADD, TypeList.INT,
135                            iVar, new Literal(1, TypeList.INT)));
136            Loop loop = new Loop();
137            Block emptyBlock = new Block(owner, TypeList.VOID, new LinkedList<>(), 3);
138            loop.initialization = new CounterInitializer(iInfo, new Literal(0, TypeList.INT));
139            loop.manipulator = new CounterManipulator(new Statement(increaseCounter, false));
140            loop.condition = new LoopingCondition(new BinaryOperator(OperatorKind.LT, TypeList.BOOLEAN, iVar,
141                    new Literal(150000, TypeList.INT)));
142            For forNode = new For(4, loop, 150000, emptyBlock, new Statement(nothing, false),
143                    new Statement(nothing, false), testCallNodeBlock, emptyBlock, emptyBlock);
144            tryNode = forNode;
145        }
146
147        FunctionInfo constrInfo = new FunctionInfo(owner.getName(), owner, owner, 0, FunctionInfo.PUBLIC);
148        Function testConstructor = new Function(owner, constrInfo, null);
149        // Test t = new Test()
150        VariableInitialization testInit = new VariableInitialization(tInfo, testConstructor);
151
152        TypeKlass throwableKlass = new TypeKlass("java.lang.Throwable");
153        List<Type> throwables = new ArrayList<>();
154        throwables.add(throwableKlass);
155
156        TypeKlass printStreamKlass = new TypeKlass("java.io.PrintStream");
157        FunctionInfo printInfo = new FunctionInfo("print", printStreamKlass,
158                TypeList.VOID, 0, FunctionInfo.PUBLIC,
159                new VariableInfo("this", owner, printStreamKlass, VariableInfo.LOCAL | VariableInfo.INITIALIZED),
160                new VariableInfo("t", owner, TypeList.OBJECT,
161                        VariableInfo.LOCAL  | VariableInfo.INITIALIZED));
162        TypeKlass systemKlass = new TypeKlass("java.lang.System");
163        StaticMemberVariable systemErrVar = new StaticMemberVariable(owner,
164                new VariableInfo("err", systemKlass, printStreamKlass, VariableInfo.STATIC | VariableInfo.PUBLIC));
165
166        LocalVariable exVar = new LocalVariable(
167                new VariableInfo("ex", owner, throwableKlass, VariableInfo.LOCAL | VariableInfo.INITIALIZED));
168        TypeKlass classKlass = new TypeKlass("java.lang.Class");
169        FunctionInfo getClassInfo = new FunctionInfo("getClass", TypeList.OBJECT,
170                classKlass, 0, FunctionInfo.PUBLIC,
171                new VariableInfo("this", owner, TypeList.OBJECT, VariableInfo.LOCAL | VariableInfo.INITIALIZED));
172        Function getClass = new Function(TypeList.OBJECT, getClassInfo, Arrays.asList(exVar));
173        FunctionInfo getNameInfo = new FunctionInfo("getName", classKlass,
174                TypeList.STRING, 0, FunctionInfo.PUBLIC,
175                new VariableInfo("this", owner, TypeList.OBJECT, VariableInfo.LOCAL | VariableInfo.INITIALIZED));
176        Function getName = new Function(classKlass, getNameInfo, Arrays.asList(getClass));
177        ArrayList<IRNode> printExceptionBlockContent = new ArrayList<>();
178        // { System.err.print(ex.getClass().getName()); System.err.print("\n"); }
179        printExceptionBlockContent.add(new Statement(
180            new Function(printStreamKlass, printInfo, Arrays.asList(systemErrVar, getName)), true));
181        printExceptionBlockContent.add(new Statement(
182            new Function(printStreamKlass, printInfo, Arrays.asList(systemErrVar, EOL)), true));
183
184        Block printExceptionBlock = new Block(owner, TypeList.VOID, printExceptionBlockContent, 3);
185        List<CatchBlock> catchBlocks1 = new ArrayList<>();
186        catchBlocks1.add(new CatchBlock(printExceptionBlock, throwables, 3));
187        List<CatchBlock> catchBlocks2 = new ArrayList<>();
188        catchBlocks2.add(new CatchBlock(printExceptionBlock, throwables, 3));
189        List<CatchBlock> catchBlocks3 = new ArrayList<>();
190        catchBlocks3.add(new CatchBlock(printExceptionBlock, throwables, 2));
191
192        TryCatchBlock tryCatch1 = new TryCatchBlock(tryNode, nothing, catchBlocks1, 3);
193        List<IRNode> printArgs = new ArrayList<>();
194        VariableInfo systemOutInfo = new VariableInfo("out", systemKlass, printStreamKlass,
195                VariableInfo.STATIC | VariableInfo.PUBLIC);
196        StaticMemberVariable systemOutVar = new StaticMemberVariable(owner, systemOutInfo);
197        printArgs.add(systemOutVar);
198        printArgs.add(tVar);
199        Function print = new Function(printStreamKlass, printInfo, printArgs);
200        ArrayList<IRNode> printBlockContent = new ArrayList<>();
201        printBlockContent.add(new Statement(print, true));
202        Block printBlock = new Block(owner, TypeList.VOID, printBlockContent, 3);
203        TryCatchBlock tryCatch2 = new TryCatchBlock(printBlock, nothing, catchBlocks2, 3);
204
205        List<IRNode> mainTryCatchBlockContent = new ArrayList<>();
206        mainTryCatchBlockContent.add(new Statement(testInit, true));
207        mainTryCatchBlockContent.add(tryCatch1);
208        mainTryCatchBlockContent.add(tryCatch2);
209        Block mainTryCatchBlock = new Block(owner, TypeList.VOID, mainTryCatchBlockContent, 2);
210        TryCatchBlock mainTryCatch = new TryCatchBlock(mainTryCatchBlock, nothing, catchBlocks3, 2);
211        ArrayList<IRNode> bodyContent = new ArrayList<>();
212        bodyContent.add(mainTryCatch);
213        Block funcBody = new Block(owner, TypeList.VOID, bodyContent, 1);
214
215        // static main(String[] args)V or static execute()V
216        VariableInfo mainArgs = new VariableInfo("args", owner,
217                new TypeArray(TypeList.STRING, 1), VariableInfo.LOCAL);
218        FunctionInfo fInfo = isMain
219                ? new FunctionInfo("main", owner, TypeList.VOID, 0, FunctionInfo.PUBLIC | FunctionInfo.STATIC, mainArgs)
220                : new FunctionInfo("execute", owner, TypeList.VOID, 0, FunctionInfo.PUBLIC | FunctionInfo.STATIC);
221        ArrayList<ArgumentDeclaration> argDecl = new ArrayList<>();
222        if (isMain) {
223            argDecl.add(new ArgumentDeclaration(mainArgs));
224        }
225        return new FunctionDefinition(fInfo, argDecl, funcBody, new Return(nothing));
226    }
227}
228