soot.coffi.Instruction Maven / Gradle / Ivy
/* Soot - a J*va Optimization Framework
* Copyright (C) 1997 Clark Verbrugge
*
* 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.
*/
/*
* Modified by the Sable Research Group and others 1997-1999.
* See the 'credits' file distributed with Soot for the complete list of
* contributors. (Soot is distributed at http://www.sable.mcgill.ca/soot)
*/
package soot.coffi;
/** Instruction subclasses are used to represent parsed bytecode; each
* bytecode operation has a corresponding subclass of Instruction.
*
* Each subclass is derived from one of
*
- Instruction
* - Instruction_noargs (an Instruction with no embedded arguments)
* - Instruction_byte (an Instruction with a single byte data argument)
* - Instruction_bytevar (a byte argument specifying a local variable)
* - Instruction_byteindex (a byte argument specifying a constant pool index)
* - Instruction_int (an Instruction with a single short data argument)
* - Instruction_intvar (a short argument specifying a local variable)
* - Instruction_intindex (a short argument specifying a constant pool index)
* - Instruction_intbranch (a short argument specifying a code offset)
* - Instruction_longbranch (an int argument specifying a code offset)
*
* @author Clark Verbrugge
* @see Instruction
* @see Instruction_noargs
* @see Instruction_byte
* @see Instruction_bytevar
* @see Instruction_byteindex
* @see Instruction_int
* @see Instruction_intvar
* @see Instruction_intindex
* @see Instruction_intbranch
* @see Instruction_longbranch
* @see Instruction_Unknown
*/
abstract class Instruction implements Cloneable {
/** String used to separate arguments in printing. */
public static final String argsep = " ";
/** String used to construct names for local variables. */
public static final String LOCALPREFIX = "local_";
// public static int w; // set by the wide instr. and used by other instrs
/** Actual byte code of this instruction. */
public byte code;
/** Offset of this instruction from the start of code.
* @see ClassFile#relabel
*/
public int label;
/** Name of this instruction.
* @see Instruction#toString
*/
public String name;
/** Reference for chaining. */
public Instruction next;
/** More convenient for chaining. */
public Instruction prev;
/** Whether this instruction is the target of a branch. */
public boolean labelled;
/** Whether this instruction branches. */
public boolean branches;
/** Whether this instruction is a method invocation. */
public boolean calls;
/** Whether this instruction is a return. */
public boolean returns;
/** Successor array. It is different from the field 'next'. */
public Instruction[] succs;
int originalIndex;
/** Constructs a new Instruction for this bytecode.
* @param c bytecode of the instruction.
*/
public Instruction(byte c) {
code = c;
next = null;
branches = false;
calls = false;
returns = false;
}
protected Object clone() throws CloneNotSupportedException {
return super.clone();
}
public String toString()
{
return label +": "+name + "[" + originalIndex + "]";
}
/** Assuming the actual bytecode for this instruction has been extracted already,
* and index is the offset of the next byte, this method parses whatever
* arguments the instruction requires and return the offset of the next
* available byte.
* @param bc complete array of bytecode.
* @param index offset of remaining bytecode after this instruction's
* bytecode was parsed.
* @return offset of the next available bytecode.
* @see ByteCode#disassemble_bytecode
* @see Instruction#compile
*/
public abstract int parse(byte bc[],int index);
/** Writes out the sequence of bytecodes represented by this instruction, including
* any arguments.
* @param bc complete array of bytecode.
* @param index offset of remaining bytecode at which to start writing.
* @return offset of the next available bytecode.
* @see ClassFile#unparseMethod
* @see Instruction#parse
*/
public abstract int compile(byte bc[],int index);
/** Changes offset values in this instruction to Instruction references;
* default behaviour is to do nothing.
* @param bc complete array of bytecode.
* @see ByteCode#build
*/
public void offsetToPointer(ByteCode bc) { }
/** Returns the next available offset assuming this instruction begins
* on the indicated offset; default assumes no arguments.
* @param curr offset this instruction would be on.
* @return next available offset.
* @see ClassFile#relabel
*/
public int nextOffset(int curr) { return curr+1; }
/** Returns an array of the instructions to which this instruction
* might branch (only valid if branches==true; default action is
* to return null).
* @param next the instruction following this one, in case of default flow through.
* @return array of instructions which may be targets of this instruction.
* @see Instruction#branches
*/
public Instruction[] branchpoints(Instruction next)
{
/*
Instruction[] bps= new Instruction[1];
bps[0] = next;
return bps;
*/
return null;
}
/** Marks the appropriate spot if that constant_pool entry is used by this instr.
* For every constant pool entry used (referenced) by this instruction, the
* corresponding boolean in the given array is set to true.
* @param refs array of booleans the same size as the constant pool array.
* @see ClassFile#constant_pool
*/
public void markCPRefs(boolean[] refs) { }
/** Updates all constant pool references within this instruction to use
* new indices, based on the given redirection array.
* @param redirect array of new indices of constant pool entries.
* @see ClassFile#constant_pool
*/
public void redirectCPRefs(short redirect[]) { }
/** For storing in a Hashtable.
* @return unique hash code for this instruction, assuming labels are unique.
*/
public int hashCode() {
return (new Integer(label)).hashCode();
}
/** For storing in a Hashtable.
* @param i the Instruction to which this is compared.
* @return true if i is the same, false otherwise.
*/
public boolean equals(Instruction i) {
return (this == i);
/*
if (label == i.label) return true;
return false;
*/
}
/** Utility routines, used mostly by the parse routines of various
* Instruction subclasses;
* this method converts two bytes into a short.
* @param bc complete array of bytecode.
* @param index offset of data in bc.
* @return the short constructed from the two bytes.
* @see Instruction#parse
* @see Instruction#shortToBytes
*/
public static short getShort(byte bc[],int index) {
short s,bh,bl;
bh = (bc[index]); bl = (bc[index+1]);
s = (short)(((bh<<8)&0xff00) | (bl&0xff));
//s = (short)((int)(bc[index])<<8 + bc[index+1]);
return s;
}
/** Utility routines, used mostly by the parse routines of various
* Instruction subclasses;
* this method converts four bytes into an int.
* @param bc complete array of bytecode.
* @param index offset of data in bc.
* @return the int constructed from the four bytes.
* @see Instruction#parse
* @see Instruction#intToBytes
*/
public static int getInt(byte bc[],int index) {
int i,bhh,bhl,blh,bll;
bhh = (((bc[index]))<<24)&0xff000000;
bhl = (((bc[index+1]))<<16)&0xff0000;
blh = (((bc[index+2]))<<8)&0xff00;
bll = ((bc[index+3]))&0xff;
i = bhh | bhl | blh | bll;
return i;
}
/** Utility routines, used mostly by the compile routines of various
* Instruction subclasses;
* this method converts a short into two bytes.
* @param bc complete array of bytecode in which to store the short.
* @param index next available offset in bc.
* @return the next available offset in bc
* @see Instruction#compile
* @see Instruction#getShort
*/
public static int shortToBytes(short s,byte bc[],int index) {
bc[index++] = (byte)((s>>8)&0xff);
bc[index++] = (byte)(s&0xff);
return index;
}
/** Utility routines, used mostly by the compile routines of various
* Instruction subclasses;
* this method converts an int into four bytes.
* @param bc complete array of bytecode in which to store the int.
* @param index next available offset in bc.
* @return the next available offset in bc
* @see Instruction#compile
* @see Instruction#getInt
*/
public static int intToBytes(int s,byte bc[],int index) {
bc[index++] = (byte)((s>>24)&0xff);
bc[index++] = (byte)((s>>16)&0xff);
bc[index++] = (byte)((s>>8)&0xff);
bc[index++] = (byte)(s&0xff);
return index;
}
/** For displaying instructions.
* @param constant_pool constant pool of associated ClassFile
* @return String representation of this instruction.
*/
public String toString(cp_info constant_pool[]) {
int i = (code)&0xff;
if (name==null) name = "null???=" + Integer.toString(i);
return name;
}
}