1 19 20 package jode.decompiler; 21 import jode.type.Type; 22 import jode.type.IntegerType; 23 import jode.type.MethodType; 24 import jode.expr.*; 25 import jode.flow.*; 26 import jode.bytecode.*; 27 import java.io.*; 28 import java.util.Vector ; 29 30 34 public abstract class Opcodes implements jode.bytecode.Opcodes { 35 36 private final static Type tIntHint 37 = new IntegerType(IntegerType.IT_I, 38 IntegerType.IT_I 39 | IntegerType.IT_B 40 | IntegerType.IT_C 41 | IntegerType.IT_S); 42 private final static Type tBoolIntHint 43 = new IntegerType(IntegerType.IT_I 44 | IntegerType.IT_Z, 45 IntegerType.IT_I 46 | IntegerType.IT_B 47 | IntegerType.IT_C 48 | IntegerType.IT_S 49 | IntegerType.IT_Z); 50 51 private final static int LOCAL_TYPES = 0; 52 private final static int ARRAY_TYPES = 1; 53 private final static int UNARY_TYPES = 2; 54 private final static int I2BCS_TYPES = 3; 55 private final static int BIN_TYPES = 4; 56 private final static int ZBIN_TYPES = 5; 57 58 private final static Type types[][] = { 59 { Type.tBoolUInt, Type.tLong, Type.tFloat, Type.tDouble, 61 Type.tUObject }, 62 { Type.tInt, Type.tLong, Type.tFloat, Type.tDouble, Type.tUObject, 64 Type.tBoolByte, Type.tChar, Type.tShort }, 65 { Type.tInt, Type.tLong, Type.tFloat, Type.tDouble, Type.tUObject }, 67 { Type.tByte, Type.tChar, Type.tShort }, 69 { tIntHint, Type.tLong, Type.tFloat, Type.tDouble, Type.tUObject }, 71 { tBoolIntHint, Type.tLong, Type.tFloat, Type.tDouble, Type.tUObject } 73 }; 74 75 private static StructuredBlock createNormal(MethodAnalyzer ma, 76 Instruction instr, 77 Expression expr) 78 { 79 return new InstructionBlock(expr, new Jump(FlowBlock.NEXT_BY_ADDR)); 80 } 81 82 private static StructuredBlock createSpecial(MethodAnalyzer ma, 83 Instruction instr, 84 int type, 85 int stackcount, int param) 86 { 87 return new SpecialBlock(type, stackcount, param, 88 new Jump(FlowBlock.NEXT_BY_ADDR)); 89 } 90 91 private static StructuredBlock createGoto(MethodAnalyzer ma, 92 Instruction instr) 93 { 94 return new EmptyBlock 95 (new Jump((FlowBlock)instr.getSingleSucc().getTmpInfo())); 96 } 97 98 private static StructuredBlock createJsr(MethodAnalyzer ma, 99 Instruction instr) 100 { 101 return new JsrBlock 102 (new Jump((FlowBlock)instr.getSingleSucc().getTmpInfo()), 103 new Jump(FlowBlock.NEXT_BY_ADDR)); 104 } 105 106 private static StructuredBlock createIfGoto(MethodAnalyzer ma, 107 Instruction instr, 108 Expression expr) 109 { 110 return new ConditionalBlock 111 (expr, new Jump((FlowBlock)instr.getSingleSucc().getTmpInfo()), 112 new Jump(FlowBlock.NEXT_BY_ADDR)); 113 } 114 115 private static StructuredBlock createSwitch(MethodAnalyzer ma, 116 Instruction instr, 117 int[] cases, FlowBlock[] dests) 118 { 119 return new SwitchBlock(new NopOperator(Type.tUInt), cases, dests); 120 } 121 122 private static StructuredBlock createBlock(MethodAnalyzer ma, 123 Instruction instr, 124 StructuredBlock block) 125 { 126 return block; 127 } 128 129 private static StructuredBlock createRet(MethodAnalyzer ma, 130 Instruction instr, 131 LocalInfo local) 132 { 133 return new RetBlock(local); 134 } 135 136 147 public static StructuredBlock readOpcode(Instruction instr, 148 MethodAnalyzer ma) 149 throws ClassFormatError 150 { 151 int opcode = instr.getOpcode(); 152 switch (opcode) { 153 case opc_nop: 154 return createBlock(ma, instr, new EmptyBlock 155 (new Jump(FlowBlock.NEXT_BY_ADDR))); 156 case opc_ldc: 157 case opc_ldc2_w: 158 return createNormal (ma, instr, 159 new ConstOperator(instr.getConstant())); 160 161 case opc_iload: case opc_lload: 162 case opc_fload: case opc_dload: case opc_aload: 163 return createNormal 164 (ma, instr, new LocalLoadOperator 165 (types[LOCAL_TYPES][opcode-opc_iload], ma, 166 ma.getLocalInfo(instr.getAddr(), instr.getLocalSlot()))); 167 case opc_iaload: case opc_laload: 168 case opc_faload: case opc_daload: case opc_aaload: 169 case opc_baload: case opc_caload: case opc_saload: 170 return createNormal 171 (ma, instr, new ArrayLoadOperator 172 (types[ARRAY_TYPES][opcode - opc_iaload])); 173 case opc_istore: case opc_lstore: 174 case opc_fstore: case opc_dstore: case opc_astore: 175 return createNormal 176 (ma, instr, new StoreInstruction 177 (new LocalStoreOperator 178 (types[LOCAL_TYPES][opcode-opc_istore], 179 ma.getLocalInfo(instr.getNextByAddr().getAddr(), 180 instr.getLocalSlot())))); 181 case opc_iastore: case opc_lastore: 182 case opc_fastore: case opc_dastore: case opc_aastore: 183 case opc_bastore: case opc_castore: case opc_sastore: 184 return createNormal 185 (ma, instr, new StoreInstruction 186 (new ArrayStoreOperator 187 (types[ARRAY_TYPES][opcode - opc_iastore]))); 188 case opc_pop: case opc_pop2: 189 return createSpecial 190 (ma, instr, SpecialBlock.POP, opcode - opc_pop + 1, 0); 191 case opc_dup: case opc_dup_x1: case opc_dup_x2: 192 case opc_dup2: case opc_dup2_x1: case opc_dup2_x2: 193 return createSpecial 194 (ma, instr, SpecialBlock.DUP, 195 (opcode - opc_dup)/3+1, (opcode - opc_dup)%3); 196 case opc_swap: 197 return createSpecial(ma, instr, SpecialBlock.SWAP, 1, 0); 198 case opc_iadd: case opc_ladd: case opc_fadd: case opc_dadd: 199 case opc_isub: case opc_lsub: case opc_fsub: case opc_dsub: 200 case opc_imul: case opc_lmul: case opc_fmul: case opc_dmul: 201 case opc_idiv: case opc_ldiv: case opc_fdiv: case opc_ddiv: 202 case opc_irem: case opc_lrem: case opc_frem: case opc_drem: 203 return createNormal 204 (ma, instr, new BinaryOperator 205 (types[BIN_TYPES][(opcode - opc_iadd)%4], 206 (opcode - opc_iadd)/4+Operator.ADD_OP)); 207 case opc_ineg: case opc_lneg: case opc_fneg: case opc_dneg: 208 return createNormal 209 (ma, instr, new UnaryOperator 210 (types[UNARY_TYPES][opcode - opc_ineg], Operator.NEG_OP)); 211 case opc_ishl: case opc_lshl: 212 case opc_ishr: case opc_lshr: 213 case opc_iushr: case opc_lushr: 214 return createNormal 215 (ma, instr, new ShiftOperator 216 (types[UNARY_TYPES][(opcode - opc_ishl)%2], 217 (opcode - opc_ishl)/2 + Operator.SHIFT_OP)); 218 case opc_iand: case opc_land: 219 case opc_ior : case opc_lor : 220 case opc_ixor: case opc_lxor: 221 return createNormal 222 (ma, instr, new BinaryOperator 223 (types[ZBIN_TYPES][(opcode - opc_iand)%2], 224 (opcode - opc_iand)/2 + Operator.AND_OP)); 225 case opc_iinc: { 226 int value = instr.getIncrement(); 227 int operation = Operator.ADD_OP; 228 if (value < 0) { 229 value = -value; 230 operation = Operator.SUB_OP; 231 } 232 LocalInfo li 233 = ma.getLocalInfo(instr.getAddr(), instr.getLocalSlot()); 234 return createNormal 235 (ma, instr, new IIncOperator 236 (new LocalStoreOperator(Type.tInt, li), 237 value, operation + Operator.OPASSIGN_OP)); 238 } 239 case opc_i2l: case opc_i2f: case opc_i2d: 240 case opc_l2i: case opc_l2f: case opc_l2d: 241 case opc_f2i: case opc_f2l: case opc_f2d: 242 case opc_d2i: case opc_d2l: case opc_d2f: { 243 int from = (opcode-opc_i2l)/3; 244 int to = (opcode-opc_i2l)%3; 245 if (to >= from) 246 to++; 247 return createNormal 248 (ma, instr, new ConvertOperator(types[UNARY_TYPES][from], 249 types[UNARY_TYPES][to])); 250 } 251 case opc_i2b: case opc_i2c: case opc_i2s: 252 return createNormal 253 (ma, instr, new ConvertOperator 254 (types[UNARY_TYPES][0], types[I2BCS_TYPES][opcode-opc_i2b])); 255 case opc_lcmp: 256 case opc_fcmpl: case opc_fcmpg: 257 case opc_dcmpl: case opc_dcmpg: 258 return createNormal 259 (ma, instr, new CompareToIntOperator 260 (types[BIN_TYPES][(opcode-(opc_lcmp-3))/2], 261 (opcode == opc_fcmpg || opcode == opc_dcmpg))); 262 case opc_ifeq: case opc_ifne: 263 return createIfGoto 264 (ma, instr, 265 new CompareUnaryOperator 266 (Type.tBoolInt, opcode - (opc_ifeq-Operator.COMPARE_OP))); 267 case opc_iflt: case opc_ifge: case opc_ifgt: case opc_ifle: 268 return createIfGoto 269 (ma, instr, 270 new CompareUnaryOperator 271 (Type.tInt, opcode - (opc_ifeq-Operator.COMPARE_OP))); 272 case opc_if_icmpeq: case opc_if_icmpne: 273 return createIfGoto 274 (ma, instr, 275 new CompareBinaryOperator 276 (tBoolIntHint, opcode - (opc_if_icmpeq-Operator.COMPARE_OP))); 277 case opc_if_icmplt: case opc_if_icmpge: 278 case opc_if_icmpgt: case opc_if_icmple: 279 return createIfGoto 280 (ma, instr, 281 new CompareBinaryOperator 282 (tIntHint, opcode - (opc_if_icmpeq-Operator.COMPARE_OP))); 283 case opc_if_acmpeq: case opc_if_acmpne: 284 return createIfGoto 285 (ma, instr, 286 new CompareBinaryOperator 287 (Type.tUObject, 288 opcode - (opc_if_acmpeq-Operator.COMPARE_OP))); 289 case opc_goto: 290 return createGoto(ma, instr); 291 case opc_jsr: 292 return createJsr(ma, instr); 293 case opc_ret: 294 return createRet 295 (ma, instr, 296 ma.getLocalInfo(instr.getAddr(), instr.getLocalSlot())); 297 case opc_lookupswitch: { 298 int[] cases = instr.getValues(); 299 FlowBlock[] dests = new FlowBlock[instr.getSuccs().length]; 300 for (int i=0; i < dests.length; i++) 301 dests[i] = (FlowBlock) instr.getSuccs()[i].getTmpInfo(); 302 dests[cases.length] = (FlowBlock) 303 instr.getSuccs()[cases.length].getTmpInfo(); 304 return createSwitch(ma, instr, cases, dests); 305 } 306 case opc_ireturn: case opc_lreturn: 307 case opc_freturn: case opc_dreturn: case opc_areturn: { 308 Type retType = Type.tSubType(ma.getReturnType()); 309 return createBlock 310 (ma, instr, new ReturnBlock(new NopOperator(retType))); 311 } 312 case opc_return: 313 return createBlock 314 (ma, instr, new EmptyBlock(new Jump(FlowBlock.END_OF_METHOD))); 315 case opc_getstatic: 316 case opc_getfield: { 317 Reference ref = instr.getReference(); 318 return createNormal 319 (ma, instr, new GetFieldOperator 320 (ma, opcode == opc_getstatic, ref)); 321 } 322 case opc_putstatic: 323 case opc_putfield: { 324 Reference ref = instr.getReference(); 325 return createNormal 326 (ma, instr, new StoreInstruction 327 (new PutFieldOperator(ma, opcode == opc_putstatic, ref))); 328 } 329 case opc_invokevirtual: 330 case opc_invokespecial: 331 case opc_invokestatic : 332 case opc_invokeinterface: { 333 Reference ref = instr.getReference(); 334 int flag = (ref.getName().equals("<init>") 335 ? InvokeOperator.CONSTRUCTOR 336 : opcode == opc_invokestatic ? InvokeOperator.STATIC 337 : opcode == opc_invokespecial ? InvokeOperator.SPECIAL 338 : InvokeOperator.VIRTUAL); 339 StructuredBlock block = createNormal 340 (ma, instr, new InvokeOperator(ma, flag, ref)); 341 return block; 342 } 343 case opc_new: { 344 Type type = Type.tType(instr.getClazzType()); 345 ma.useType(type); 346 return createNormal(ma, instr, new NewOperator(type)); 347 } 348 case opc_arraylength: 349 return createNormal 350 (ma, instr, new ArrayLengthOperator()); 351 case opc_athrow: 352 return createBlock 353 (ma, instr, 354 new ThrowBlock(new NopOperator(Type.tUObject))); 355 case opc_checkcast: { 356 Type type = Type.tType(instr.getClazzType()); 357 ma.useType(type); 358 return createNormal 359 (ma, instr, new CheckCastOperator(type)); 360 } 361 case opc_instanceof: { 362 Type type = Type.tType(instr.getClazzType()); 363 ma.useType(type); 364 return createNormal 365 (ma, instr, new InstanceOfOperator(type)); 366 } 367 case opc_monitorenter: 368 return createNormal(ma, instr, 369 new MonitorEnterOperator()); 370 case opc_monitorexit: 371 return createNormal(ma, instr, 372 new MonitorExitOperator()); 373 case opc_multianewarray: { 374 Type type = Type.tType(instr.getClazzType()); 375 ma.useType(type); 376 int dimension = instr.getDimensions(); 377 return createNormal(ma, instr, 378 new NewArrayOperator(type, dimension)); 379 } 380 case opc_ifnull: case opc_ifnonnull: 381 return createIfGoto 382 (ma, instr, new CompareUnaryOperator 383 (Type.tUObject, opcode - (opc_ifnull-Operator.COMPARE_OP))); 384 default: 385 throw new jode.AssertError("Invalid opcode "+opcode); 386 } 387 } 388 } 389 | Popular Tags |