Package org.jnode.vm.compiler.ir

Source Code of org.jnode.vm.compiler.ir.IRGenerator

/*
* $Id$
*
* Copyright (C) 2003-2014 JNode.org
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; If not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.jnode.vm.compiler.ir;

import static org.jnode.vm.compiler.ir.quad.BinaryOperation.DADD;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.DDIV;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.DMUL;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.DREM;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.DSUB;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.FADD;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.FDIV;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.FMUL;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.FREM;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.FSUB;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.IADD;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.IAND;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.IDIV;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.IMUL;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.IOR;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.IREM;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.ISHL;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.ISHR;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.ISUB;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.IUSHR;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.IXOR;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.LADD;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.LAND;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.LDIV;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.LMUL;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.LOR;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.LREM;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.LSHL;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.LSHR;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.LSUB;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.LUSHR;
import static org.jnode.vm.compiler.ir.quad.BinaryOperation.LXOR;
import static org.jnode.vm.compiler.ir.quad.BranchCondition.IFEQ;
import static org.jnode.vm.compiler.ir.quad.BranchCondition.IFGE;
import static org.jnode.vm.compiler.ir.quad.BranchCondition.IFGT;
import static org.jnode.vm.compiler.ir.quad.BranchCondition.IFLE;
import static org.jnode.vm.compiler.ir.quad.BranchCondition.IFLT;
import static org.jnode.vm.compiler.ir.quad.BranchCondition.IFNE;
import static org.jnode.vm.compiler.ir.quad.BranchCondition.IFNONNULL;
import static org.jnode.vm.compiler.ir.quad.BranchCondition.IFNULL;
import static org.jnode.vm.compiler.ir.quad.BranchCondition.IF_ACMPEQ;
import static org.jnode.vm.compiler.ir.quad.BranchCondition.IF_ACMPNE;
import static org.jnode.vm.compiler.ir.quad.BranchCondition.IF_ICMPEQ;
import static org.jnode.vm.compiler.ir.quad.BranchCondition.IF_ICMPGE;
import static org.jnode.vm.compiler.ir.quad.BranchCondition.IF_ICMPGT;
import static org.jnode.vm.compiler.ir.quad.BranchCondition.IF_ICMPLE;
import static org.jnode.vm.compiler.ir.quad.BranchCondition.IF_ICMPLT;
import static org.jnode.vm.compiler.ir.quad.BranchCondition.IF_ICMPNE;
import static org.jnode.vm.compiler.ir.quad.UnaryOperation.D2I;
import static org.jnode.vm.compiler.ir.quad.UnaryOperation.D2L;
import static org.jnode.vm.compiler.ir.quad.UnaryOperation.DNEG;
import static org.jnode.vm.compiler.ir.quad.UnaryOperation.F2D;
import static org.jnode.vm.compiler.ir.quad.UnaryOperation.F2I;
import static org.jnode.vm.compiler.ir.quad.UnaryOperation.F2L;
import static org.jnode.vm.compiler.ir.quad.UnaryOperation.FNEG;
import static org.jnode.vm.compiler.ir.quad.UnaryOperation.I2B;
import static org.jnode.vm.compiler.ir.quad.UnaryOperation.I2C;
import static org.jnode.vm.compiler.ir.quad.UnaryOperation.I2D;
import static org.jnode.vm.compiler.ir.quad.UnaryOperation.I2F;
import static org.jnode.vm.compiler.ir.quad.UnaryOperation.I2L;
import static org.jnode.vm.compiler.ir.quad.UnaryOperation.I2S;
import static org.jnode.vm.compiler.ir.quad.UnaryOperation.INEG;
import static org.jnode.vm.compiler.ir.quad.UnaryOperation.L2D;
import static org.jnode.vm.compiler.ir.quad.UnaryOperation.L2F;
import static org.jnode.vm.compiler.ir.quad.UnaryOperation.L2I;
import static org.jnode.vm.compiler.ir.quad.UnaryOperation.LNEG;

import java.util.Iterator;

import org.jnode.vm.bytecode.BytecodeParser;
import org.jnode.vm.bytecode.BytecodeVisitor;
import org.jnode.vm.classmgr.VmByteCode;
import org.jnode.vm.classmgr.VmConstClass;
import org.jnode.vm.classmgr.VmConstFieldRef;
import org.jnode.vm.classmgr.VmConstIMethodRef;
import org.jnode.vm.classmgr.VmConstMethodRef;
import org.jnode.vm.classmgr.VmConstString;
import org.jnode.vm.classmgr.VmMethod;
import org.jnode.vm.compiler.ir.quad.BinaryOperation;
import org.jnode.vm.compiler.ir.quad.BinaryQuad;
import org.jnode.vm.compiler.ir.quad.ConditionalBranchQuad;
import org.jnode.vm.compiler.ir.quad.ConstantRefAssignQuad;
import org.jnode.vm.compiler.ir.quad.Quad;
import org.jnode.vm.compiler.ir.quad.UnaryQuad;
import org.jnode.vm.compiler.ir.quad.UnconditionalBranchQuad;
import org.jnode.vm.compiler.ir.quad.VarReturnQuad;
import org.jnode.vm.compiler.ir.quad.VariableRefAssignQuad;
import org.jnode.vm.compiler.ir.quad.VoidReturnQuad;

/**
* Intermediate Representation Generator.
* Visits bytecodes of a given method and translates them into a
* list of Quads.
*/
public class IRGenerator<T> extends BytecodeVisitor {
    private final Constant<T> NULL_CONSTANT = Constant.getInstance(null);
    private int nArgs;
    private int nLocals;
    private int maxStack;
    private int stackOffset;
    private Variable<T>[] variables;
    private int address;
    private Iterator<IRBasicBlock<T>> basicBlockIterator;
    private IRBasicBlock<T> currentBlock;

    public IRGenerator(IRControlFlowGraph<T> cfg) {
        basicBlockIterator = cfg.iterator();
        currentBlock = basicBlockIterator.next();
    }

    public void setParser(BytecodeParser parser) {
    }

    public void startMethod(VmMethod method) {
        VmByteCode code = method.getBytecode();
        nArgs = method.getArgSlotCount();
        nLocals = code.getNoLocals();
        maxStack = code.getMaxStack();
        stackOffset = nLocals;
        variables = new Variable[nLocals + maxStack];
        int index = 0;
        for (int i = 0; i < nArgs; i += 1) {
            variables[index] = new MethodArgument<T>(Operand.UNKNOWN, index);
            index += 1;
        }
        for (int i = nArgs; i < nLocals; i += 1) {
            variables[index] = new LocalVariable<T>(Operand.UNKNOWN, index);
            index += 1;
        }
        for (int i = 0; i < maxStack; i += 1) {
            variables[index] = new StackVariable<T>(Operand.UNKNOWN, index);
            index += 1;
        }
        currentBlock.setVariables(variables);
    }

    public void endMethod() {
    }

    public void startInstruction(int address) {
        this.address = address;
        if (address >= currentBlock.getEndPC()) {
            currentBlock = basicBlockIterator.next();
            Iterator<IRBasicBlock<T>> pi = currentBlock.getPredecessors().iterator();
            if (!pi.hasNext()) {
                if (currentBlock.isStartOfExceptionHandler()) {
                    stackOffset = nLocals + 1;
                    currentBlock.setStackOffset(stackOffset);
                    // TODO need to set variables also...
                }
                return;
            }
            stackOffset = currentBlock.getStackOffset();
//          while (pi.hasNext()) {
//              IRBasicBlock irb = (IRBasicBlock) pi.next();
//              Variable[] prevVars = irb.getVariables();
//              if (prevVars != null) {
//                  int n = prevVars.length;
//                  variables = new Variable[n];
//                  for (int i=0; i<n; i+=1) {
//                      variables[i] = prevVars[i];
//                  }
//                  currentBlock.setVariables(variables);
//                  return;
//              }
//          }
//          currentBlock.setVariables(currentBlock.getIDominator().getVariables());
        }
        if (address < currentBlock.getStartPC() || address >= currentBlock.getEndPC()) {
            throw new AssertionError("instruction not in basic block!");
        }
    }

    public void endInstruction() {
    }

    public void visit_nop() {
    }

    public void visit_aconst_null() {
        currentBlock.add(new ConstantRefAssignQuad<T>(address, currentBlock, stackOffset,
            NULL_CONSTANT));
        stackOffset += 1;
    }

    public void visit_iconst(int value) {
        Constant<T> c = Constant.getInstance(value);
        Quad<T> quad = new ConstantRefAssignQuad<T>(address, currentBlock, stackOffset,
            c);
        currentBlock.add(quad);
        stackOffset += 1;
    }

    public void visit_lconst(long value) {
        Constant<T> c = Constant.getInstance(value);
        currentBlock.add(new ConstantRefAssignQuad<T>(address, currentBlock, stackOffset,
            c));
        stackOffset += 2;
    }

    public void visit_fconst(float value) {
        Constant<T> c = Constant.getInstance(value);
        currentBlock.add(new ConstantRefAssignQuad<T>(address, currentBlock, stackOffset,
            c));
        stackOffset += 1;
    }

    public void visit_dconst(double value) {
        Constant<T> c = Constant.getInstance(value);
        currentBlock.add(new ConstantRefAssignQuad<T>(address, currentBlock, stackOffset,
            c));
        stackOffset += 2;
    }

    public void visit_ldc(VmConstString value) {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public final void visit_ldc(VmConstClass value) {
        throw new Error("Not implemented yet");
    }

    public void visit_iload(int index) {
        variables[index].setType(Operand.INT);
        variables[stackOffset].setType(Operand.INT);
        VariableRefAssignQuad<T> assignQuad = new VariableRefAssignQuad<T>(address, currentBlock,
            stackOffset, index);
        currentBlock.add(assignQuad);
        stackOffset += 1;
    }

    public void visit_lload(int index) {
        variables[index].setType(Operand.LONG);
        variables[stackOffset].setType(Operand.LONG);
        currentBlock.add(new VariableRefAssignQuad<T>(address, currentBlock,
            stackOffset, index));
        stackOffset += 2;
    }

    public void visit_fload(int index) {
        variables[index].setType(Operand.FLOAT);
        variables[stackOffset].setType(Operand.FLOAT);
        currentBlock.add(new VariableRefAssignQuad<T>(address, currentBlock,
            stackOffset, index));
        stackOffset += 1;
    }

    public void visit_dload(int index) {
        variables[index].setType(Operand.DOUBLE);
        variables[stackOffset].setType(Operand.DOUBLE);
        currentBlock.add(new VariableRefAssignQuad<T>(address, currentBlock,
            stackOffset, index));
        stackOffset += 2;
    }

    public void visit_aload(int index) {
        variables[index].setType(Operand.REFERENCE);
        variables[stackOffset].setType(Operand.REFERENCE);
        currentBlock.add(new VariableRefAssignQuad<T>(address, currentBlock, stackOffset, index));
        stackOffset += 1;
    }

    public void visit_iaload() {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_laload() {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_faload() {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_daload() {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_aaload() {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_baload() {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_caload() {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_saload() {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_istore(int index) {
        stackOffset -= 1;
        variables[index].setType(Operand.INT);
        variables[stackOffset].setType(Operand.INT);
        currentBlock.add(new VariableRefAssignQuad<T>(address, currentBlock, index, stackOffset));
    }

    public void visit_lstore(int index) {
        stackOffset -= 2;
        variables[index].setType(Operand.LONG);
        variables[stackOffset].setType(Operand.LONG);
        currentBlock.add(new VariableRefAssignQuad<T>(address, currentBlock, index, stackOffset));
    }

    public void visit_fstore(int index) {
        stackOffset -= 1;
        variables[index].setType(Operand.FLOAT);
        variables[stackOffset].setType(Operand.FLOAT);
        currentBlock.add(new VariableRefAssignQuad<T>(address, currentBlock, index, stackOffset));
    }

    public void visit_dstore(int index) {
        stackOffset -= 2;
        variables[index].setType(Operand.DOUBLE);
        variables[stackOffset].setType(Operand.DOUBLE);
        currentBlock.add(new VariableRefAssignQuad<T>(address, currentBlock, index, stackOffset));
    }

    public void visit_astore(int index) {
        stackOffset -= 1;
        variables[index].setType(Operand.REFERENCE);
        variables[stackOffset].setType(Operand.REFERENCE);
        currentBlock.add(new VariableRefAssignQuad<T>(address, currentBlock, index, stackOffset));
    }

    public void visit_iastore() {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_lastore() {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_fastore() {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_dastore() {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_aastore() {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_bastore() {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_castore() {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_sastore() {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_pop() {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_pop2() {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_dup() {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_dup_x1() {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_dup_x2() {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_dup2() {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_dup2_x1() {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_dup2_x2() {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_swap() {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_iadd() {
        currentBlock.add(doBinaryQuad(IADD, Operand.INT));
    }

    public void visit_ladd() {
        currentBlock.add(doBinaryQuad(LADD, Operand.LONG));
    }

    public void visit_fadd() {
        currentBlock.add(doBinaryQuad(FADD, Operand.FLOAT));
    }

    public void visit_dadd() {
        currentBlock.add(doBinaryQuad(DADD, Operand.DOUBLE));
    }

    public void visit_isub() {
        currentBlock.add(doBinaryQuad(ISUB, Operand.INT));
    }

    public void visit_lsub() {
        currentBlock.add(doBinaryQuad(LSUB, Operand.LONG));
    }

    public void visit_fsub() {
        currentBlock.add(doBinaryQuad(FSUB, Operand.FLOAT));
    }

    public void visit_dsub() {
        currentBlock.add(doBinaryQuad(DSUB, Operand.DOUBLE));
    }

    public void visit_imul() {
        currentBlock.add(doBinaryQuad(IMUL, Operand.INT));
    }

    public void visit_lmul() {
        currentBlock.add(doBinaryQuad(LMUL, Operand.LONG));
    }

    public void visit_fmul() {
        currentBlock.add(doBinaryQuad(FMUL, Operand.FLOAT));
    }

    public void visit_dmul() {
        currentBlock.add(doBinaryQuad(DMUL, Operand.DOUBLE));
    }

    public void visit_idiv() {
        currentBlock.add(doBinaryQuad(IDIV, Operand.INT));
    }

    public void visit_ldiv() {
        currentBlock.add(doBinaryQuad(LDIV, Operand.LONG));
    }

    public void visit_fdiv() {
        currentBlock.add(doBinaryQuad(FDIV, Operand.FLOAT));
    }

    public void visit_ddiv() {
        currentBlock.add(doBinaryQuad(DDIV, Operand.DOUBLE));
    }

    public void visit_irem() {
        currentBlock.add(doBinaryQuad(IREM, Operand.INT));
    }

    public void visit_lrem() {
        currentBlock.add(doBinaryQuad(LREM, Operand.LONG));
    }

    public void visit_frem() {
        currentBlock.add(doBinaryQuad(FREM, Operand.FLOAT));
    }

    public void visit_drem() {
        currentBlock.add(doBinaryQuad(DREM, Operand.DOUBLE));
    }

    public void visit_ineg() {
        int s1 = stackOffset - 1;
        variables[s1].setType(Operand.INT);
        currentBlock.add(new UnaryQuad<T>(address, currentBlock, s1, INEG, s1));
    }

    public void visit_lneg() {
        int s1 = stackOffset - 2;
        variables[s1].setType(Operand.LONG);
        currentBlock.add(new UnaryQuad<T>(address, currentBlock, s1, LNEG, s1));
    }

    public void visit_fneg() {
        int s1 = stackOffset - 1;
        variables[s1].setType(Operand.FLOAT);
        currentBlock.add(new UnaryQuad<T>(address, currentBlock, s1, FNEG, s1));
    }

    public void visit_dneg() {
        int s1 = stackOffset - 2;
        variables[s1].setType(Operand.DOUBLE);
        currentBlock.add(new UnaryQuad<T>(address, currentBlock, s1, DNEG, s1));
    }

    public void visit_ishl() {
        currentBlock.add(doBinaryQuad(ISHL, Operand.INT));
    }

    public void visit_lshl() {
        stackOffset -= 1;
        int s1 = stackOffset - 2;
        variables[s1].setType(Operand.LONG);
        variables[stackOffset].setType(Operand.INT);
        currentBlock.add(new BinaryQuad<T>(address, currentBlock, s1, s1, LSHL, stackOffset));
    }

    public void visit_ishr() {
        currentBlock.add(doBinaryQuad(ISHR, Operand.INT));
    }

    public void visit_lshr() {
        stackOffset -= 1;
        int s1 = stackOffset - 2;
        variables[s1].setType(Operand.LONG);
        variables[stackOffset].setType(Operand.INT);
        currentBlock.add(new BinaryQuad<T>(address, currentBlock, s1, s1, LSHR, stackOffset));
    }

    public void visit_iushr() {
        currentBlock.add(doBinaryQuad(IUSHR, Operand.INT));
    }

    public void visit_lushr() {
        stackOffset -= 2;
        int s1 = stackOffset - 1;
        variables[s1].setType(Operand.INT);
        variables[stackOffset].setType(Operand.LONG);
        currentBlock.add(new BinaryQuad<T>(address, currentBlock, s1, s1, LUSHR, stackOffset));
    }

    public void visit_iand() {
        currentBlock.add(doBinaryQuad(IAND, Operand.INT));
    }

    public void visit_land() {
        currentBlock.add(doBinaryQuad(LAND, Operand.LONG));
    }

    public void visit_ior() {
        currentBlock.add(doBinaryQuad(IOR, Operand.INT));
    }

    public void visit_lor() {
        currentBlock.add(doBinaryQuad(LOR, Operand.LONG));
    }

    public void visit_ixor() {
        currentBlock.add(doBinaryQuad(IXOR, Operand.INT));
    }

    public void visit_lxor() {
        currentBlock.add(doBinaryQuad(LXOR, Operand.LONG));
    }

    public void visit_iinc(int index, int incValue) {
        variables[index].setType(Operand.INT);
        BinaryQuad<T> binaryQuad =
            new BinaryQuad<T>(address, currentBlock, index, index, IADD, new IntConstant<T>(incValue));
        currentBlock.add(binaryQuad.foldConstants());
    }

    public void visit_i2l() {
        stackOffset -= 1;
        variables[stackOffset].setType(Operand.LONG);
        currentBlock.add(new UnaryQuad<T>(address, currentBlock, stackOffset, I2L, stackOffset));
        stackOffset += 2;
    }

    public void visit_i2f() {
        stackOffset -= 1;
        variables[stackOffset].setType(Operand.FLOAT);
        currentBlock.add(new UnaryQuad<T>(address, currentBlock, stackOffset, I2F, stackOffset));
        stackOffset += 1;
    }

    public void visit_i2d() {
        stackOffset -= 1;
        variables[stackOffset].setType(Operand.DOUBLE);
        currentBlock.add(new UnaryQuad<T>(address, currentBlock, stackOffset, I2D, stackOffset));
        stackOffset += 2;
    }

    public void visit_l2i() {
        stackOffset -= 2;
        variables[stackOffset].setType(Operand.INT);
        currentBlock.add(new UnaryQuad<T>(address, currentBlock, stackOffset, L2I, stackOffset));
        stackOffset += 1;
    }

    public void visit_l2f() {
        stackOffset -= 2;
        variables[stackOffset].setType(Operand.FLOAT);
        currentBlock.add(new UnaryQuad<T>(address, currentBlock, stackOffset, L2F, stackOffset));
        stackOffset += 1;
    }

    public void visit_l2d() {
        stackOffset -= 2;
        variables[stackOffset].setType(Operand.DOUBLE);
        currentBlock.add(new UnaryQuad<T>(address, currentBlock, stackOffset, L2D, stackOffset));
        stackOffset += 2;
    }

    public void visit_f2i() {
        stackOffset -= 1;
        variables[stackOffset].setType(Operand.INT);
        currentBlock.add(new UnaryQuad<T>(address, currentBlock, stackOffset, F2I, stackOffset));
        stackOffset += 1;
    }

    public void visit_f2l() {
        stackOffset -= 1;
        variables[stackOffset].setType(Operand.LONG);
        currentBlock.add(new UnaryQuad<T>(address, currentBlock, stackOffset, F2L, stackOffset));
        stackOffset += 2;
    }

    public void visit_f2d() {
        stackOffset -= 1;
        variables[stackOffset].setType(Operand.DOUBLE);
        currentBlock.add(new UnaryQuad<T>(address, currentBlock, stackOffset, F2D, stackOffset));
        stackOffset += 2;
    }

    public void visit_d2i() {
        stackOffset -= 2;
        variables[stackOffset].setType(Operand.INT);
        currentBlock.add(new UnaryQuad<T>(address, currentBlock, stackOffset, D2I, stackOffset));
        stackOffset += 1;
    }

    public void visit_d2l() {
        stackOffset -= 2;
        variables[stackOffset].setType(Operand.LONG);
        currentBlock.add(new UnaryQuad<T>(address, currentBlock, stackOffset, D2L, stackOffset));
        stackOffset += 2;
    }

    public void visit_d2f() {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_i2b() {
        stackOffset -= 1;
        variables[stackOffset].setType(Operand.BYTE);
        currentBlock.add(new UnaryQuad<T>(address, currentBlock, stackOffset, I2B, stackOffset));
        stackOffset += 1;
    }

    public void visit_i2c() {
        stackOffset -= 1;
        variables[stackOffset].setType(Operand.CHAR);
        currentBlock.add(new UnaryQuad<T>(address, currentBlock, stackOffset, I2C, stackOffset));
        stackOffset += 1;
    }

    public void visit_i2s() {
        stackOffset -= 1;
        variables[stackOffset].setType(Operand.SHORT);
        currentBlock.add(new UnaryQuad<T>(address, currentBlock, stackOffset, I2S, stackOffset));
        stackOffset += 1;
    }

    public void visit_lcmp() {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_fcmpl() {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_fcmpg() {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_dcmpl() {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_dcmpg() {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_ifeq(int address) {
        int s1 = stackOffset - 1;
        Variable[] variables = currentBlock.getVariables();
        variables[s1].setType(Operand.INT);
        currentBlock.add(new ConditionalBranchQuad<T>(this.address, currentBlock,
            s1, IFEQ, address));
        stackOffset -= 1;
        setSuccessorStackOffset();
    }

    public void visit_ifne(int address) {
        int s1 = stackOffset - 1;
        Variable[] variables = currentBlock.getVariables();
        variables[s1].setType(Operand.INT);
        currentBlock.add(new ConditionalBranchQuad<T>(this.address, currentBlock,
            s1, IFNE, address));
        stackOffset -= 1;
        setSuccessorStackOffset();
    }

    public void visit_iflt(int address) {
        int s1 = stackOffset - 1;
        Variable[] variables = currentBlock.getVariables();
        variables[s1].setType(Operand.INT);
        currentBlock.add(new ConditionalBranchQuad<T>(this.address, currentBlock,
            s1, IFLT, address));
        stackOffset -= 1;
        setSuccessorStackOffset();
    }

    public void visit_ifge(int address) {
        int s1 = stackOffset - 1;
        Variable[] variables = currentBlock.getVariables();
        variables[s1].setType(Operand.INT);
        currentBlock.add(new ConditionalBranchQuad<T>(this.address, currentBlock,
            s1, IFGE, address));
        stackOffset -= 1;
        setSuccessorStackOffset();
    }

    public void visit_ifgt(int address) {
        int s1 = stackOffset - 1;
        Variable[] variables = currentBlock.getVariables();
        variables[s1].setType(Operand.INT);
        currentBlock.add(new ConditionalBranchQuad<T>(this.address, currentBlock,
            s1, IFGT, address));
        stackOffset -= 1;
        setSuccessorStackOffset();
    }

    public void visit_ifle(int address) {
        int s1 = stackOffset - 1;
        Variable[] variables = currentBlock.getVariables();
        variables[s1].setType(Operand.INT);
        currentBlock.add(new ConditionalBranchQuad<T>(this.address, currentBlock,
            s1, IFLE, address));
        stackOffset -= 1;
        setSuccessorStackOffset();
    }

    public void visit_if_icmpeq(int address) {
        int s1 = stackOffset - 2;
        int s2 = stackOffset - 1;
        Variable[] variables = currentBlock.getVariables();
        variables[s1].setType(Operand.INT);
        variables[s2].setType(Operand.INT);
        currentBlock.add(new ConditionalBranchQuad<T>(this.address, currentBlock,
            s1, IF_ICMPEQ, s2, address));
        stackOffset -= 2;
        setSuccessorStackOffset();
    }

    public void visit_if_icmpne(int address) {
        int s1 = stackOffset - 2;
        int s2 = stackOffset - 1;
        Variable[] variables = currentBlock.getVariables();
        variables[s1].setType(Operand.INT);
        variables[s2].setType(Operand.INT);
        currentBlock.add(new ConditionalBranchQuad<T>(this.address, currentBlock,
            s1, IF_ICMPNE, s2, address));
        stackOffset -= 2;
        setSuccessorStackOffset();
    }

    public void visit_if_icmplt(int address) {
        int s1 = stackOffset - 2;
        int s2 = stackOffset - 1;
        Variable[] variables = currentBlock.getVariables();
        variables[s1].setType(Operand.INT);
        variables[s2].setType(Operand.INT);
        currentBlock.add(new ConditionalBranchQuad<T>(this.address, currentBlock,
            s1, IF_ICMPLT, s2, address));
        stackOffset -= 2;
        setSuccessorStackOffset();
    }

    public void visit_if_icmpge(int address) {
        int s1 = stackOffset - 2;
        int s2 = stackOffset - 1;
        Variable[] variables = currentBlock.getVariables();
        variables[s1].setType(Operand.INT);
        variables[s2].setType(Operand.INT);
        currentBlock.add(new ConditionalBranchQuad<T>(this.address, currentBlock,
            s1, IF_ICMPGE, s2, address));
        stackOffset -= 2;
        setSuccessorStackOffset();
    }

    public void visit_if_icmpgt(int address) {
        int s1 = stackOffset - 2;
        int s2 = stackOffset - 1;
        Variable[] variables = currentBlock.getVariables();
        variables[s1].setType(Operand.INT);
        variables[s2].setType(Operand.INT);
        currentBlock.add(new ConditionalBranchQuad<T>(this.address, currentBlock,
            s1, IF_ICMPGT, s2, address));
        stackOffset -= 2;
        setSuccessorStackOffset();
    }

    public void visit_if_icmple(int address) {
        int s1 = stackOffset - 2;
        int s2 = stackOffset - 1;
        Variable[] variables = currentBlock.getVariables();
        variables[s1].setType(Operand.INT);
        variables[s2].setType(Operand.INT);
        currentBlock.add(new ConditionalBranchQuad<T>(this.address, currentBlock,
            s1, IF_ICMPLE, s2, address));
        stackOffset -= 2;
        setSuccessorStackOffset();
    }

    public void visit_if_acmpeq(int address) {
        int s1 = stackOffset - 2;
        int s2 = stackOffset - 1;
        Variable[] variables = currentBlock.getVariables();
        variables[s1].setType(Operand.REFERENCE);
        variables[s2].setType(Operand.REFERENCE);
        currentBlock.add(new ConditionalBranchQuad<T>(this.address, currentBlock,
            s1, IF_ACMPEQ, s2, address));
        stackOffset -= 2;
        setSuccessorStackOffset();
    }

    public void visit_if_acmpne(int address) {
        int s1 = stackOffset - 2;
        int s2 = stackOffset - 1;
        Variable[] variables = currentBlock.getVariables();
        variables[s1].setType(Operand.REFERENCE);
        variables[s2].setType(Operand.REFERENCE);
        currentBlock.add(new ConditionalBranchQuad<T>(this.address, currentBlock,
            s1, IF_ACMPNE, s2, address));
        stackOffset -= 2;
        setSuccessorStackOffset();
    }

    public void visit_goto(int address) {
        currentBlock.add(new UnconditionalBranchQuad<T>(this.address, currentBlock, address));
        setSuccessorStackOffset();
    }

    public void visit_jsr(int address) {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_ret(int index) {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_tableswitch(int defValue, int lowValue, int highValue, int[] addresses) {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_lookupswitch(int defValue, int[] matchValues, int[] addresses) {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_ireturn() {
        stackOffset -= 1;
        variables[stackOffset].setType(Operand.INT);
        currentBlock.add(new VarReturnQuad<T>(address, currentBlock, stackOffset));
    }

    public void visit_lreturn() {
        stackOffset -= 2;
        variables[stackOffset].setType(Operand.LONG);
        currentBlock.add(new VarReturnQuad<T>(address, currentBlock, stackOffset));
    }

    public void visit_freturn() {
        stackOffset -= 1;
        variables[stackOffset].setType(Operand.FLOAT);
        currentBlock.add(new VarReturnQuad<T>(address, currentBlock, stackOffset));
    }

    public void visit_dreturn() {
        stackOffset -= 2;
        variables[stackOffset].setType(Operand.DOUBLE);
        currentBlock.add(new VarReturnQuad<T>(address, currentBlock, stackOffset));
    }

    public void visit_areturn() {
        stackOffset -= 1;
        variables[stackOffset].setType(Operand.REFERENCE);
        currentBlock.add(new VarReturnQuad<T>(address, currentBlock, stackOffset));
    }

    public void visit_return() {
        currentBlock.add(new VoidReturnQuad<T>(address, currentBlock));
    }

    public void visit_getstatic(VmConstFieldRef fieldRef) {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_putstatic(VmConstFieldRef fieldRef) {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_getfield(VmConstFieldRef fieldRef) {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_putfield(VmConstFieldRef fieldRef) {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_invokevirtual(VmConstMethodRef methodRef) {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_invokespecial(VmConstMethodRef methodRef) {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_invokestatic(VmConstMethodRef methodRef) {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_invokeinterface(VmConstIMethodRef methodRef, int count) {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_new(VmConstClass clazz) {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_newarray(int type) {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_anewarray(VmConstClass clazz) {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_arraylength() {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_athrow() {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_checkcast(VmConstClass clazz) {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_instanceof(VmConstClass clazz) {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_monitorenter() {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_monitorexit() {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_multianewarray(VmConstClass clazz, int dimensions) {
        throw new IllegalArgumentException("byte code not yet supported");
    }

    public void visit_ifnull(int address) {
        int s1 = stackOffset - 1;
        Variable[] variables = currentBlock.getVariables();
        variables[s1].setType(Operand.REFERENCE);
        currentBlock.add(new ConditionalBranchQuad<T>(this.address, currentBlock,
            s1, IFNULL, address));
        stackOffset -= 1;
        setSuccessorStackOffset();
    }

    public void visit_ifnonnull(int address) {
        int s1 = stackOffset - 1;
        Variable[] variables = currentBlock.getVariables();
        variables[s1].setType(Operand.REFERENCE);
        currentBlock.add(new ConditionalBranchQuad<T>(this.address, currentBlock,
            s1, IFNONNULL, address));
        stackOffset -= 1;
        setSuccessorStackOffset();
    }

    // TODO
    public Quad<T> doBinaryQuad(BinaryOperation op, int type) {
        int sCount = 1;
        if (type == Operand.DOUBLE || type == Operand.LONG) {
            sCount = 2;
        }
        stackOffset -= sCount;
        int s1 = stackOffset - sCount;
        Variable[] variables = currentBlock.getVariables();
        variables[s1].setType(type);
        variables[stackOffset].setType(type);
        BinaryQuad<T> bop = new BinaryQuad<T>(address, currentBlock, s1, s1, op, stackOffset);
        return bop.foldConstants();
    }

    /**
     * @return the variables
     */
    public Variable<T>[] getVariables() {
        return variables;
    }

    /**
     * @return the number of args
     */
    public int getNoArgs() {
        return this.nArgs;
    }

    private void setSuccessorStackOffset() {
        // this is needed for terniary operators, the stack is not the
        // same as our dominator
        for (IRBasicBlock b : currentBlock.getSuccessors()) {
            b.setStackOffset(stackOffset);
        }
    }
}
TOP

Related Classes of org.jnode.vm.compiler.ir.IRGenerator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.