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