Main Page   Packages   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members  

LocalVariableInstruction.java

00001 package de.fub.bytecode.generic;
00002 
00003 import java.io.*;
00004 import de.fub.bytecode.util.ByteSequence;
00005 import de.fub.bytecode.classfile.Utility;
00006 import de.fub.bytecode.Constants;
00007 
00008 /**
00009  * Abstract super class for instructions dealing with local variables.
00010  *
00011  * @version $Id: LocalVariableInstruction.java,v 1.1.1.1 2002/01/24 03:41:41 pserver Exp $
00012  * @author  <A HREF="http://www.inf.fu-berlin.de/~dahm">M. Dahm</A>
00013  */
00014 public abstract class LocalVariableInstruction extends Instruction
00015   implements TypedInstruction, IndexedInstruction {
00016   private int     n;     // index of referenced variable
00017   private short   c_tag; // compact version, such as ILOAD_0
00018   private short   canon_tag; // canonical tag such as ILOAD
00019 
00020   /**
00021    * Empty constructor needed for the Class.newInstance() statement in
00022    * Instruction.readInstruction(). Not to be used otherwise.
00023    * tag and length are defined in readInstruction and initFromFile, respectively.
00024    */
00025   LocalVariableInstruction(short canon_tag, short c_tag) {
00026     super();
00027     this.canon_tag = canon_tag;
00028     this.c_tag     = c_tag;
00029   }  
00030   /**
00031    * @param tag Instruction number
00032    * @param c_tag Instruction number for compact version, ALOAD_0, e.g.
00033    * @param n local variable index (unsigned short)
00034    */
00035   protected LocalVariableInstruction(short tag, short c_tag, int n) {
00036     super(tag, (short)2);
00037 
00038     this.c_tag = c_tag;
00039     canon_tag  = tag;
00040 
00041     setIndex(n);
00042   }  
00043   /**
00044    * Dump instruction as byte code to stream out.
00045    * @param out Output stream
00046    */
00047   public void dump(DataOutputStream out) throws IOException {
00048     if(wide()) // Need WIDE prefix ?
00049       out.writeByte(Constants.WIDE);
00050 
00051     out.writeByte(tag);
00052 
00053     if(length > 1) { // Otherwise ILOAD_n, instruction, e.g.
00054       if(wide())
00055     out.writeShort(n);
00056       else
00057     out.writeByte(n);
00058     }
00059   }  
00060   /** @return canonical tag for instrucion, e.g., ALOAD for ALOAD_0
00061    */
00062   public short getCanonicalTag() {
00063     return canon_tag;
00064   }  
00065   /**
00066    * @return local variable index  referred by this instruction.
00067    */
00068   public final int getIndex() { return n; }  
00069   /** @return type associated with the instruction
00070    */
00071   public Type getType(ConstantPoolGen cp) {
00072     switch(canon_tag) {
00073     case Constants.ILOAD: case Constants.ISTORE: 
00074       return Type.INT;
00075     case Constants.LLOAD: case Constants.LSTORE: 
00076       return Type.LONG;
00077     case Constants.DLOAD: case Constants.DSTORE: 
00078       return Type.DOUBLE;
00079     case Constants.FLOAD: case Constants.FSTORE: 
00080       return Type.FLOAT;
00081     case Constants.ALOAD: case Constants.ASTORE:
00082       return Type.OBJECT;
00083 
00084     default: throw new ClassGenException("Oops: unknown case in switch" + canon_tag);
00085     }
00086   }  
00087   /**
00088    * Read needed data (e.g. index) from file.
00089    * PRE: (ILOAD <= tag <= ALOAD_3) || (ISTORE <= tag <= ASTORE_3)
00090    */
00091   protected void initFromFile(ByteSequence bytes, boolean wide)
00092     throws IOException
00093   {
00094     if(wide) {
00095       n         = bytes.readUnsignedShort();
00096       length    = 4;
00097     } else if(((tag >= Constants.ILOAD) &&
00098            (tag <= Constants.ALOAD)) ||
00099           ((tag >= Constants.ISTORE) &&
00100            (tag <= Constants.ASTORE))) {
00101       n      = bytes.readUnsignedByte();
00102       length = 2;
00103     } else if(tag <= Constants.ALOAD_3) { // compact load instruction such as ILOAD_2
00104       n      = (tag - Constants.ILOAD_0) % 4;
00105       length = 1;
00106     } else { // Assert ISTORE_0 <= tag <= ASTORE_3
00107       n      = (tag - Constants.ISTORE_0) % 4;
00108       length = 1;
00109     }
00110  } 
00111   /**
00112    * Set the local variable index
00113    */
00114   public final void setIndex(int n) { 
00115     if((n < 0) || (n > Constants.MAX_SHORT))
00116       throw new ClassGenException("Illegal value: " + n);
00117 
00118     this.n = n;
00119 
00120     if(n >= 0 && n <= 3) { // Use more compact instruction xLOAD_n
00121       tag    = (short)(c_tag + n);
00122       length = 1;
00123     } else {
00124       tag = canon_tag;
00125       
00126       if(wide()) // Need WIDE prefix ?
00127     length = 4;
00128       else
00129     length = 2;
00130     }
00131   }  
00132   /**
00133    * Long output format:
00134    *
00135    * &lt;name of opcode&gt; "["&lt;opcode number&gt;"]" 
00136    * "("&lt;length of instruction&gt;")" "&lt;"&lt; local variable index&gt;"&gt;"
00137    *
00138    * @param verbose long/short format switch
00139    * @return mnemonic for instruction
00140    */
00141   public String toString(boolean verbose) {
00142     if(((tag >= Constants.ILOAD_0) &&
00143     (tag <= Constants.ALOAD_3)) ||
00144        ((tag >= Constants.ISTORE_0) &&
00145     (tag <= Constants.ASTORE_3)))
00146       return super.toString(verbose);
00147     else
00148       return super.toString(verbose) + " " + n;
00149   }  
00150   private final boolean wide() { return n > Constants.MAX_BYTE; }  
00151 }

Generated at Thu Feb 7 06:49:48 2002 for Bandera by doxygen1.2.10 written by Dimitri van Heesch, © 1997-2001