/* * fb-contrib - Auxiliary detectors for Java programs * Copyright (C) 2005-2017 Dave Brosius * * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.mebigfatguy.fbcontrib.utils; import org.apache.bcel.Constants; import org.apache.bcel.classfile.LocalVariable; import org.apache.bcel.classfile.LocalVariableTable; import org.apache.bcel.classfile.Method; import org.apache.bcel.generic.Type; import edu.umd.cs.findbugs.visitclass.DismantleBytecode; /** * an auxiliary class for managing and manipulating registers */ public final class RegisterUtils { /** * private to reinforce the helper status of the class */ private RegisterUtils() { } /** * returns the register used to store a reference * * @param dbc * the dismantle byte code parsing the class * @param seen * the opcode of the store * @return the register stored into */ public static int getAStoreReg(final DismantleBytecode dbc, final int seen) { if (seen == Constants.ASTORE) { return dbc.getRegisterOperand(); } if (OpcodeUtils.isAStore(seen)) { return seen - Constants.ASTORE_0; } return -1; } /** * returns the register used to load a reference * * @param dbc * the dismantle byte code parsing the class * @param seen * the opcode of the load * @return the register loaded from */ public static int getALoadReg(DismantleBytecode dbc, int seen) { if (seen == Constants.ALOAD) { return dbc.getRegisterOperand(); } if (OpcodeUtils.isALoad(seen)) { return seen - Constants.ALOAD_0; } return -1; } /** * returns the register used in a store operation * * @param dbc * the dismantle byte code parsing the class * @param seen * the opcode of the store * @return the register stored into */ public static int getStoreReg(DismantleBytecode dbc, int seen) { if ((seen == Constants.ASTORE) || (seen == Constants.ISTORE) || (seen == Constants.LSTORE) || (seen == Constants.FSTORE) || (seen == Constants.DSTORE)) { return dbc.getRegisterOperand(); } if (OpcodeUtils.isIStore(seen)) { return seen - Constants.ISTORE_0; } else if (OpcodeUtils.isLStore(seen)) { return seen - Constants.LSTORE_0; } else if (OpcodeUtils.isFStore(seen)) { return seen - Constants.FSTORE_0; } else if (OpcodeUtils.isDStore(seen)) { return seen - Constants.DSTORE_0; } else if (OpcodeUtils.isAStore(seen)) { return seen - Constants.ASTORE_0; } return -1; } /** * returns the register used in a load operation * * @param dbc * the dismantle byte code parsing the class * @param seen * the opcode of the load * @return the register stored into */ public static int getLoadReg(DismantleBytecode dbc, int seen) { if ((seen == Constants.ALOAD) || (seen == Constants.ILOAD) || (seen == Constants.LLOAD) || (seen == Constants.FLOAD) || (seen == Constants.DLOAD)) { return dbc.getRegisterOperand(); } if (OpcodeUtils.isILoad(seen)) { return seen - Constants.ILOAD_0; } else if (OpcodeUtils.isLLoad(seen)) { return seen - Constants.LLOAD_0; } else if (OpcodeUtils.isFLoad(seen)) { return seen - Constants.FLOAD_0; } else if (OpcodeUtils.isDLoad(seen)) { return seen - Constants.DLOAD_0; } else if (OpcodeUtils.isALoad(seen)) { return seen - Constants.ALOAD_0; } return -1; } /** * returns the end pc of the visible range of this register at this pc * * @param lvt * the local variable table for this method * @param reg * the register to examine * @param curPC * the pc of the current instruction * @return the endpc */ public static int getLocalVariableEndRange(LocalVariableTable lvt, int reg, int curPC) { int endRange = Integer.MAX_VALUE; if (lvt != null) { LocalVariable lv = lvt.getLocalVariable(reg, curPC); if (lv != null) { endRange = lv.getStartPC() + lv.getLength(); } } return endRange; } /** * gets the set of registers used for parameters * * @param obj * the context object for the method to find the parameter * registers of * * @return the set of registers that parameters are using */ public static int[] getParameterRegisters(Method obj) { Type[] argTypes = obj.getArgumentTypes(); int[] regs = new int[argTypes.length]; int curReg = obj.isStatic() ? 0 : 1; for (int t = 0; t < argTypes.length; t++) { String sig = argTypes[t].getSignature(); regs[t] = curReg; curReg += SignatureUtils.getSignatureSize(sig); } return regs; } }