KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jode > decompiler > Opcodes


1 /* Opcodes Copyright (C) 1999-2002 Jochen Hoenicke.
2  *
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU Lesser General Public License as published by
5  * the Free Software Foundation; either version 2, or (at your option)
6  * any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU Lesser General Public License
14  * along with this program; see the file COPYING.LESSER. If not, write to
15  * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
16  *
17  * $Id: Opcodes.java,v 1.18.2.1 2002/05/28 17:34:03 hoenicke Exp $
18  */

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 JavaDoc;
29
30 /**
31  * This is an abstract class which creates flow blocks for the
32  * opcodes in a byte stream.
33  */

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     // Local types
60
{ Type.tBoolUInt, Type.tLong, Type.tFloat, Type.tDouble,
61       Type.tUObject },
62     // Array types
63
{ Type.tInt, Type.tLong, Type.tFloat, Type.tDouble, Type.tUObject,
64           Type.tBoolByte, Type.tChar, Type.tShort },
65     // ifld2ifld and shl types
66
{ Type.tInt, Type.tLong, Type.tFloat, Type.tDouble, Type.tUObject },
67     // i2bcs types
68
{ Type.tByte, Type.tChar, Type.tShort },
69     // cmp/add/sub/mul/div types
70
{ tIntHint, Type.tLong, Type.tFloat, Type.tDouble, Type.tUObject },
71     // and/or/xor types
72
{ 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     /**
137      * Read an opcode out of a data input stream containing the bytecode.
138      * @param addr The current address.
139      * @param stream The stream containing the java byte code.
140      * @param ma The Method Analyzer
141      * (where further information can be get from).
142      * @return The FlowBlock representing this opcode
143      * or null if the stream is empty.
144      * @exception IOException if an read error occured.
145      * @exception ClassFormatError if an invalid opcode is detected.
146      */

147     public static StructuredBlock readOpcode(Instruction instr,
148                          MethodAnalyzer ma)
149         throws ClassFormatError JavaDoc
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