/* * $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 org.jnode.vm.compiler.ir.CodeGenerator; import org.jnode.vm.compiler.ir.Constant; import org.jnode.vm.compiler.ir.IRBasicBlock; import org.jnode.vm.compiler.ir.Location; import org.jnode.vm.compiler.ir.Operand; import org.jnode.vm.compiler.ir.RegisterLocation; import org.jnode.vm.compiler.ir.StackLocation; import org.jnode.vm.compiler.ir.Variable; /** * @author Madhu Siddalingaiah * @author Levente S\u00e1ntha */ public class UnaryQuad<T> extends AssignQuad<T> { private UnaryOperation operation; private Operand<T> refs[]; /** * @param address * @param block * @param lhsIndex */ public UnaryQuad(int address, IRBasicBlock<T> block, int lhsIndex, UnaryOperation operation, int varIndex) { super(address, block, lhsIndex); this.operation = operation; refs = new Operand[]{getOperand(varIndex)}; } public Operand<T>[] getReferencedOps() { return refs; } /** * @return the operand */ public Operand<T> getOperand() { return refs[0]; } /** * @return the operation */ public UnaryOperation getOperation() { return operation; } public String toString() { return getAddress() + ": " + getLHS().toString() + " = " + operation.name() + ' ' + refs[0].toString(); } public Operand<T> propagate(Variable<T> operand) { Quad<T> quad = foldConstants(); if (quad instanceof ConstantRefAssignQuad) { setDeadCode(true); ConstantRefAssignQuad<T> cop = (ConstantRefAssignQuad<T>) quad; return cop.getRHS(); } return operand; } private Quad<T> foldConstants() { if (refs[0] instanceof Constant) { Constant<T> c = (Constant<T>) refs[0]; Constant<T> c2 = compute(c); int address = this.getAddress(); IRBasicBlock<T> basicBlock = this.getBasicBlock(); int index = this.getLHS().getIndex(); return new ConstantRefAssignQuad<T>(address, basicBlock, index, c2); } return this; } private ConstantRefAssignQuad<T> foldConstants2() { if (refs[0] instanceof Constant) { Constant<T> c = (Constant<T>) refs[0]; Constant<T> c2 = compute(c); int address = this.getAddress(); int byteCodeAddress = this.getByteCodeAddress(); IRBasicBlock<T> basicBlock = this.getBasicBlock(); Variable<T> lhs = this.getLHS(); return new ConstantRefAssignQuad<T>(address, byteCodeAddress, basicBlock, lhs, c2); } else { throw new IllegalArgumentException("Unary quad has a non-constant: " + this); } } private Constant<T> compute(Constant<T> c) { Constant<T> c2; switch (operation) { case I2L: c2 = c.i2l(); break; case I2F: c2 = c.i2f(); break; case I2D: c2 = c.i2d(); break; case L2I: c2 = c.l2i(); break; case L2F: c2 = c.l2f(); break; case L2D: c2 = c.l2d(); break; case F2I: c2 = c.f2i(); break; case F2L: c2 = c.f2l(); break; case F2D: c2 = c.f2d(); break; case D2I: c2 = c.d2i(); break; case D2L: c2 = c.d2l(); break; case D2F: c2 = c.d2f(); break; case I2B: c2 = c.i2b(); break; case I2C: c2 = c.i2c(); break; case I2S: c2 = c.i2s(); break; case INEG: c2 = c.iNeg(); break; case LNEG: c2 = c.lNeg(); break; case FNEG: c2 = c.fNeg(); break; case DNEG: c2 = c.dNeg(); break; default: throw new IllegalArgumentException("Don't know how to fold those yet..."); } return c2; } public void doPass2() { refs[0] = refs[0].simplify(); getLHS().setAssignQuad(this); } public void generateCode(CodeGenerator<T> cg) { Variable<T> lhs = getLHS(); Location<T> lhsLoc = lhs.getLocation(); if (lhsLoc instanceof RegisterLocation) { RegisterLocation<T> regLoc = (RegisterLocation<T>) lhsLoc; T lhsReg = regLoc.getRegister(); if (refs[0] instanceof Variable) { Variable<T> var = (Variable<T>) refs[0]; Location<T> varLoc = var.getLocation(); if (varLoc instanceof RegisterLocation) { RegisterLocation<T> vregLoc = (RegisterLocation<T>) varLoc; cg.generateCodeFor(this, lhsReg, operation, vregLoc.getRegister()); } else if (varLoc instanceof StackLocation) { StackLocation<T> stackLoc = (StackLocation<T>) varLoc; cg.generateCodeFor(this, lhsReg, operation, stackLoc.getDisplacement()); } else { throw new IllegalArgumentException("Unknown location: " + varLoc); } } else if (refs[0] instanceof Constant) { // this probably won't happen, is should be folded earlier cg.generateCodeFor(foldConstants2()); } else { throw new IllegalArgumentException("Unknown operand: " + refs[0]); } } else if (lhsLoc instanceof StackLocation) { StackLocation<T> lhsStackLoc = (StackLocation<T>) lhsLoc; int lhsDisp = lhsStackLoc.getDisplacement(); if (refs[0] instanceof Variable) { Variable<T> var = (Variable<T>) refs[0]; Location<T> varLoc = var.getLocation(); if (varLoc instanceof RegisterLocation) { RegisterLocation<T> vregLoc = (RegisterLocation<T>) varLoc; cg.generateCodeFor(this, lhsDisp, operation, vregLoc.getRegister()); } else if (varLoc instanceof StackLocation) { StackLocation<T> stackLoc = (StackLocation<T>) varLoc; cg.generateCodeFor(this, lhsDisp, operation, stackLoc.getDisplacement()); } else { throw new IllegalArgumentException("Unknown location: " + varLoc); } } else if (refs[0] instanceof Constant) { // this probably won't happen, is should be folded earlier cg.generateCodeFor(foldConstants2()); } else { throw new IllegalArgumentException("Unknown operand: " + refs[0]); } } else { throw new IllegalArgumentException("Unknown location: " + lhsLoc); } } public int getLHSLiveAddress() { return this.getAddress() + 1; } }