1 cananian 1.3.2.4 // InGen.java, created Sun Sep 13 22:49:20 1998 by cananian 2 cananian 1.2 // Copyright (C) 1998 C. Scott Ananian <cananian@alumni.princeton.edu> 3 cananian 1.2 // Licensed under the terms of the GNU GPL; see COPYING for details. 4 cananian 1.1 package harpoon.IR.Bytecode; 5 cananian 1.1 6 cananian 1.3.2.3 import harpoon.ClassFile.HClass; 7 cananian 1.1 import harpoon.Util.Util; 8 cananian 1.1 9 cananian 1.1 /** 10 cananian 1.1 * <code>InGen</code> is used for non-branching instructions. 11 cananian 1.1 * An <code>InGen</code> has an opcode and optional operands. 12 cananian 1.1 * An <code>InGen</code> has exactly one predecessor and exactly 13 cananian 1.1 * one successor.<p> 14 cananian 1.1 * Note that <code>InGen</code> contain <code>Operand</code> objects 15 cananian 1.1 * for all <b>relevant</b>, explicit or implicit operands of the 16 cananian 1.1 * bytecode instruction. This means that, for example, an 17 cananian 1.1 * <code>iload_0</code> will be given an <Code>OpLocalVariable</code> 18 cananian 1.1 * operand corresponding to the implicit '0', and conversely that 19 cananian 1.1 * <code>invokeinterface</code> will <b>not</b> contain operands for 20 cananian 1.1 * the <code>nargs</code> operand (which is obvious from the method 21 cananian 1.1 * signature) nor for the dummy placeholder value which trails the 22 cananian 1.1 * opcode in the raw bytecode array. 23 cananian 1.1 * 24 cananian 1.3.2.6 * @author C. Scott Ananian <cananian@alumni.princeton.edu> 25 cananian 1.4 * @version $Id: InGen.java,v 1.4 2002/02/25 21:04:17 cananian Exp $ 26 cananian 1.1 */ 27 cananian 1.1 public class InGen extends Instr { 28 cananian 1.3.2.2 final byte opcode; 29 cananian 1.3.2.2 final Operand operands[]; 30 cananian 1.1 31 cananian 1.1 /** Create an <code>InGen</code> from a chunk of bytecode starting at 32 cananian 1.1 * offset <code>pc</code>. <code>parent</code> is used to lookup 33 cananian 1.1 * <code>constant_pool</code> references. */ 34 cananian 1.1 public InGen(String sourcefile, int linenumber, 35 cananian 1.1 byte[] code, int pc, Code parent) { 36 cananian 1.1 super(sourcefile, linenumber); 37 cananian 1.3.2.2 this.opcode = (code[pc]==Op.WIDE)?code[pc+1]:code[pc]; 38 cananian 1.1 // Make operands, if necessary. 39 cananian 1.1 switch(code[pc]) { 40 cananian 1.1 // Constant local variable index 0: 41 cananian 1.1 case Op.ALOAD_0: 42 cananian 1.1 case Op.ASTORE_0: 43 cananian 1.1 case Op.DLOAD_0: 44 cananian 1.1 case Op.DSTORE_0: 45 cananian 1.1 case Op.FLOAD_0: 46 cananian 1.1 case Op.FSTORE_0: 47 cananian 1.1 case Op.ILOAD_0: 48 cananian 1.1 case Op.ISTORE_0: 49 cananian 1.1 case Op.LLOAD_0: 50 cananian 1.1 case Op.LSTORE_0: 51 cananian 1.1 operands = new Operand[] { new OpLocalVariable(0) }; 52 cananian 1.1 break; 53 cananian 1.1 // Constant local variable index 1: 54 cananian 1.1 case Op.ALOAD_1: 55 cananian 1.1 case Op.ASTORE_1: 56 cananian 1.1 case Op.DLOAD_1: 57 cananian 1.1 case Op.DSTORE_1: 58 cananian 1.1 case Op.FLOAD_1: 59 cananian 1.1 case Op.FSTORE_1: 60 cananian 1.1 case Op.ILOAD_1: 61 cananian 1.1 case Op.ISTORE_1: 62 cananian 1.1 case Op.LLOAD_1: 63 cananian 1.1 case Op.LSTORE_1: 64 cananian 1.1 operands = new Operand[] { new OpLocalVariable(1) }; 65 cananian 1.1 break; 66 cananian 1.1 // Constant local variable index 2: 67 cananian 1.1 case Op.ALOAD_2: 68 cananian 1.1 case Op.ASTORE_2: 69 cananian 1.1 case Op.DLOAD_2: 70 cananian 1.1 case Op.DSTORE_2: 71 cananian 1.1 case Op.FLOAD_2: 72 cananian 1.1 case Op.FSTORE_2: 73 cananian 1.1 case Op.ILOAD_2: 74 cananian 1.1 case Op.ISTORE_2: 75 cananian 1.1 case Op.LLOAD_2: 76 cananian 1.1 case Op.LSTORE_2: 77 cananian 1.1 operands = new Operand[] { new OpLocalVariable(2) }; 78 cananian 1.1 break; 79 cananian 1.1 // Constant local variable index 3: 80 cananian 1.1 case Op.ALOAD_3: 81 cananian 1.1 case Op.ASTORE_3: 82 cananian 1.1 case Op.DLOAD_3: 83 cananian 1.1 case Op.DSTORE_3: 84 cananian 1.1 case Op.FLOAD_3: 85 cananian 1.1 case Op.FSTORE_3: 86 cananian 1.1 case Op.ILOAD_3: 87 cananian 1.1 case Op.ISTORE_3: 88 cananian 1.1 case Op.LLOAD_3: 89 cananian 1.1 case Op.LSTORE_3: 90 cananian 1.1 operands = new Operand[] { new OpLocalVariable(3) }; 91 cananian 1.1 break; 92 cananian 1.1 // Local variable index 93 cananian 1.1 case Op.ALOAD: 94 cananian 1.1 case Op.ASTORE: 95 cananian 1.1 case Op.DLOAD: 96 cananian 1.1 case Op.DSTORE: 97 cananian 1.1 case Op.FLOAD: 98 cananian 1.1 case Op.FSTORE: 99 cananian 1.1 case Op.ILOAD: 100 cananian 1.1 case Op.ISTORE: 101 cananian 1.1 case Op.LLOAD: 102 cananian 1.1 case Op.LSTORE: 103 cananian 1.1 operands = new Operand[] { new OpLocalVariable(u1(code,pc+1)) }; 104 cananian 1.1 break; 105 cananian 1.1 // Class 106 cananian 1.1 case Op.ANEWARRAY: 107 cananian 1.1 case Op.CHECKCAST: 108 cananian 1.1 case Op.INSTANCEOF: 109 cananian 1.1 case Op.NEW: 110 cananian 1.1 operands = new Operand[] { new OpClass(parent, u2(code,pc+1)) }; 111 cananian 1.1 break; 112 cananian 1.1 // Field 113 cananian 1.1 case Op.GETFIELD: 114 cananian 1.1 case Op.GETSTATIC: 115 cananian 1.1 case Op.PUTFIELD: 116 cananian 1.1 case Op.PUTSTATIC: 117 cananian 1.1 operands = new Operand[] { new OpField(parent, u2(code,pc+1)) }; 118 cananian 1.1 break; 119 cananian 1.1 // Method 120 cananian 1.1 case Op.INVOKESPECIAL: 121 cananian 1.1 case Op.INVOKESTATIC: 122 cananian 1.1 case Op.INVOKEVIRTUAL: 123 cananian 1.1 case Op.INVOKEINTERFACE: // note that we discard an unnecessary operand. 124 cananian 1.1 operands = new Operand[] { new OpMethod(parent, u2(code,pc+1)) }; 125 cananian 1.1 break; 126 cananian 1.1 // Byte 127 cananian 1.1 case Op.BIPUSH: 128 cananian 1.1 case Op.NEWARRAY: 129 cananian 1.1 operands = new Operand[] { 130 cananian 1.1 new OpConstant(new Byte(code[pc+1]), HClass.Byte) 131 cananian 1.1 }; 132 cananian 1.1 break; 133 cananian 1.1 // Short 134 cananian 1.1 case Op.SIPUSH: 135 cananian 1.1 operands = new Operand[] { 136 cananian 1.1 new OpConstant(new Short((short)u2(code,pc+1)), HClass.Short) 137 cananian 1.1 }; 138 cananian 1.1 break; 139 cananian 1.1 // Integer constant. 140 cananian 1.1 case Op.ICONST_M1: 141 cananian 1.1 case Op.ICONST_0: 142 cananian 1.1 case Op.ICONST_1: 143 cananian 1.1 case Op.ICONST_2: 144 cananian 1.1 case Op.ICONST_3: 145 cananian 1.1 case Op.ICONST_4: 146 cananian 1.1 case Op.ICONST_5: 147 cananian 1.1 operands = new Operand[] { 148 cananian 1.1 new OpConstant(new Integer((int)(code[pc]-Op.ICONST_0)), HClass.Int) 149 cananian 1.1 }; 150 cananian 1.1 break; 151 cananian 1.1 // Long constant. 152 cananian 1.1 case Op.LCONST_0: 153 cananian 1.1 case Op.LCONST_1: 154 cananian 1.1 operands = new Operand[] { 155 cananian 1.1 new OpConstant(new Long((long)(code[pc]-Op.LCONST_0)), HClass.Long) 156 cananian 1.1 }; 157 cananian 1.1 break; 158 cananian 1.1 // Floating-point constant. 159 cananian 1.1 case Op.FCONST_0: 160 cananian 1.1 case Op.FCONST_1: 161 cananian 1.1 case Op.FCONST_2: 162 cananian 1.1 operands = new Operand[] { 163 cananian 1.1 new OpConstant(new Float((float)(code[pc]-Op.FCONST_0)), HClass.Float) 164 cananian 1.3 }; 165 cananian 1.3 break; 166 cananian 1.3 // Double constant. 167 cananian 1.3 case Op.DCONST_0: 168 cananian 1.3 case Op.DCONST_1: 169 cananian 1.3 operands = new Operand[] { 170 cananian 1.3 new OpConstant(new Double((double)(code[pc]-Op.DCONST_0)), 171 cananian 1.3 HClass.Double) 172 cananian 1.1 }; 173 cananian 1.1 break; 174 cananian 1.1 // General constant. 175 cananian 1.1 case Op.LDC: 176 cananian 1.1 operands = new Operand[] { new OpConstant(parent, u1(code,pc+1)) }; 177 cananian 1.1 break; 178 cananian 1.1 case Op.LDC_W: 179 cananian 1.1 case Op.LDC2_W: 180 cananian 1.1 operands = new Operand[] { new OpConstant(parent, u2(code,pc+1)) }; 181 cananian 1.1 break; 182 cananian 1.1 // Odd-balls 183 cananian 1.1 case Op.IINC: 184 cananian 1.1 operands = new Operand[] { 185 cananian 1.1 new OpLocalVariable(u1(code,pc+1)), 186 cananian 1.1 new OpConstant(new Integer((int)code[pc+2]), HClass.Int) 187 cananian 1.1 }; 188 cananian 1.1 break; 189 cananian 1.1 case Op.MULTIANEWARRAY: 190 cananian 1.1 operands = new Operand[] { 191 cananian 1.1 new OpClass(parent, u2(code,pc+1)), 192 cananian 1.1 new OpConstant(new Integer(u1(code,pc+3)), HClass.Int) 193 cananian 1.1 }; 194 cananian 1.1 break; 195 cananian 1.1 case Op.RET: 196 cananian 1.1 operands = new Operand[] { 197 cananian 1.1 new OpConstant(new Integer(u1(code,pc+1)), HClass.Int) 198 cananian 1.1 }; 199 cananian 1.1 break; 200 cananian 1.1 case Op.WIDE: // this is evil. 201 cananian 1.1 if (code[pc+1]==Op.IINC) // very evil. 202 cananian 1.1 operands = new Operand[] { 203 cananian 1.3.2.2 new OpLocalVariable(u2(code, pc+2)), 204 cananian 1.3.2.5 new OpConstant(new Integer(s2(code,pc+4)), HClass.Int) 205 cananian 1.1 }; 206 cananian 1.3.2.2 else 207 cananian 1.3.2.2 operands = new Operand[] { new OpLocalVariable(u2(code, pc+2)) }; 208 cananian 1.1 break; 209 cananian 1.1 // Takes an operand, but don't belong: 210 cananian 1.1 case Op.GOTO: 211 cananian 1.1 case Op.GOTO_W: 212 cananian 1.1 case Op.IF_ACMPEQ: 213 cananian 1.1 case Op.IF_ACMPNE: 214 cananian 1.1 case Op.IF_ICMPEQ: 215 cananian 1.1 case Op.IF_ICMPNE: 216 cananian 1.1 case Op.IF_ICMPLT: 217 cananian 1.1 case Op.IF_ICMPGE: 218 cananian 1.1 case Op.IF_ICMPGT: 219 cananian 1.1 case Op.IF_ICMPLE: 220 cananian 1.1 case Op.IFEQ: 221 cananian 1.1 case Op.IFNE: 222 cananian 1.1 case Op.IFLT: 223 cananian 1.1 case Op.IFGE: 224 cananian 1.1 case Op.IFGT: 225 cananian 1.1 case Op.IFLE: 226 cananian 1.1 case Op.IFNONNULL: 227 cananian 1.1 case Op.IFNULL: 228 cananian 1.1 case Op.JSR: 229 cananian 1.1 case Op.JSR_W: 230 cananian 1.1 case Op.LOOKUPSWITCH: 231 cananian 1.1 case Op.TABLESWITCH: 232 cananian 1.1 throw new Error("Branch operations are not InGen's."); 233 cananian 1.1 default: 234 cananian 1.1 operands = new Operand[0]; 235 cananian 1.1 break; 236 cananian 1.1 } 237 cananian 1.1 // done. yay. 238 cananian 1.1 } 239 cananian 1.1 /** Create an integer from an unsigned byte. */ 240 cananian 1.1 static int u1(byte[] code, int pc) { 241 cananian 1.1 return ((int) code[pc]) & 0xFF; 242 cananian 1.1 } 243 cananian 1.1 /** Create an integer from an unsigned two-byte quantity (big-endian). */ 244 cananian 1.1 static int u2(byte[] code, int pc) { 245 cananian 1.1 return (u1(code,pc) << 8) | u1(code,pc+1); 246 cananian 1.1 } 247 cananian 1.3.2.5 /** Create an integer from a signed two-byte quantity (big-endian). */ 248 cananian 1.3.2.5 static int s2(byte[] code, int pc) { 249 cananian 1.3.2.5 int s = u2(code, pc); 250 cananian 1.3.2.5 return (s&0x8000)==0 ? s : (s | ~0xFFFF); 251 cananian 1.1 } 252 cananian 1.1 253 cananian 1.1 /** Return the bytecode opcode of this instruction. 254 cananian 1.1 * @see Op */ 255 cananian 1.1 public byte getOpcode() { return opcode; } 256 cananian 1.1 /** Return a specific operand of this instruction. */ 257 cananian 1.1 public Operand getOperand(int i) { return operands[i]; } 258 cananian 1.1 /** Get all the operands of this instruction. */ 259 cananian 1.3.2.1 public Operand[] getOperands() { 260 cananian 1.3.2.1 return (Operand[]) Util.safeCopy(Operand.arrayFactory, operands); 261 cananian 1.3.2.1 } 262 cananian 1.1 263 cananian 1.1 // provide run-time checks on arity. 264 cananian 1.1 /** @see Instr#addPrev */ 265 cananian 1.1 void addPrev(Instr prev) { 266 cananian 1.1 if (this.prev.size()>=1) 267 cananian 1.1 throw new Error("Only one predecessor for InGen allowed."); 268 cananian 1.1 super.addPrev(prev); 269 cananian 1.1 } 270 cananian 1.1 /** @see Instr#addNext */ 271 cananian 1.1 void addNext(Instr next) { 272 cananian 1.1 if (this.next.size()>=1) 273 cananian 1.1 throw new Error("Only one successor for InGen allowed."); 274 cananian 1.1 super.addNext(next); 275 cananian 1.1 } 276 cananian 1.1 277 cananian 1.1 /** Return human-readable instruction string. */ 278 cananian 1.1 public String toString() { 279 cananian 1.1 StringBuffer sb = new StringBuffer(Op.toString(opcode)); 280 cananian 1.1 sb.append(' '); 281 cananian 1.1 for (int i=0; i<operands.length; i++) { 282 cananian 1.1 sb.append(operands[i].toString()); 283 cananian 1.1 if (i<operands.length-1) 284 cananian 1.1 sb.append(", "); 285 cananian 1.1 } 286 cananian 1.1 return sb.toString(); 287 cananian 1.1 } 288 cananian 1.1 289 cananian 1.1 }