/* * $Id$ * * Copyright (C) 2003-2015 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.quad; import java.util.Collection; import java.util.List; import org.jnode.vm.compiler.ir.CodeGenerator; import org.jnode.vm.compiler.ir.IRBasicBlock; import org.jnode.vm.compiler.ir.Operand; import org.jnode.vm.compiler.ir.Variable; /** * @author Madhu Siddalingaiah * <p/> * Represents an intermediate intruction, commonly called a Quad * in the literature. */ public abstract class Quad<T> { private int address; private final int byteCodeAddress; private boolean deadCode; private IRBasicBlock<T> basicBlock; public Quad(int address, IRBasicBlock<T> block) { this.address = address; this.byteCodeAddress = address; this.basicBlock = block; this.deadCode = false; } public Quad(int address, int byteCodeAddress, IRBasicBlock<T> block) { this.address = address; this.byteCodeAddress = byteCodeAddress; this.basicBlock = block; this.deadCode = false; } public Operand<T> getOperand(int varIndex) { return basicBlock.getVariables()[varIndex]; } /** * Gets the bytecode address for this operation * * @return bytecode address for this operation */ public int getAddress() { return address; } /** * @param i */ public void setAddress(int i) { address = i; } public int getByteCodeAddress() { return byteCodeAddress; } /** * Gets the operand defined by this operation (left side of assignment) * * @return defined operand or null if none */ public abstract Operand<T> getDefinedOp(); /** * Gets all operands used by this operation (right side of assignment) * * @return array of referenced operands or null if none */ public abstract Operand<T>[] getReferencedOps(); /** * Gets all operands that interfere in this operation * This useful in graph coloring register allocators * * @return array of operands that interfere with each other or null if none */ public Operand<T>[] getIFOperands() { return null; } /** * @return {@code true} if this is dead code. */ public boolean isDeadCode() { return deadCode; } /** * @param dead */ public void setDeadCode(boolean dead) { deadCode = dead; } /** * @return the basic block */ public IRBasicBlock<T> getBasicBlock() { return basicBlock; } public void computeLiveness(List<Variable<?>> liveVariables) { Operand<T>[] refs = getReferencedOps(); if (refs != null) { int n = refs.length; for (int i = 0; i < n; i += 1) { if (refs[i] instanceof Variable) { Variable<T> v = (Variable<T>) refs[i]; v.setLastUseAddress(getAddress()); if (!liveVariables.contains(v)) liveVariables.add(v); } } } } /** * Performs basic optimizations such as constant folding and * copy propagation. In most cases, subclasses can simplify * operands, e.g.: * <p/> * <code>refs[0] = refs[0].simplify();</code> */ public abstract void doPass2(); public abstract void generateCode(CodeGenerator<T> cg); public void doPass3(Collection<Variable<T>> values){ }; }