InstructionFactory.java revision b72c5c2e5482cf10117b2b25f642f7616b2326c3
1/*
2 * ProGuard -- shrinking, optimization, obfuscation, and preverification
3 *             of Java bytecode.
4 *
5 * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the Free
9 * Software Foundation; either version 2 of the License, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21package proguard.classfile.instruction;
22
23/**
24 * This class provides methods to create and reuse Instruction objects.
25 *
26 * @author Eric Lafortune
27 */
28public class InstructionFactory
29{
30    /**
31     * Creates a new Instruction from the data in the byte array, starting
32     * at the given index.
33     */
34    public static Instruction create(byte[] code, int offset)
35    {
36        Instruction instruction;
37
38        int  index  = offset;
39        byte opcode = code[index++];
40
41        boolean wide = false;
42        if (opcode == InstructionConstants.OP_WIDE)
43        {
44            opcode = code[index++];
45            wide   = true;
46        }
47
48        switch (opcode)
49        {
50            // Simple instructions.
51            case InstructionConstants.OP_NOP:
52            case InstructionConstants.OP_ACONST_NULL:
53            case InstructionConstants.OP_ICONST_M1:
54            case InstructionConstants.OP_ICONST_0:
55            case InstructionConstants.OP_ICONST_1:
56            case InstructionConstants.OP_ICONST_2:
57            case InstructionConstants.OP_ICONST_3:
58            case InstructionConstants.OP_ICONST_4:
59            case InstructionConstants.OP_ICONST_5:
60            case InstructionConstants.OP_LCONST_0:
61            case InstructionConstants.OP_LCONST_1:
62            case InstructionConstants.OP_FCONST_0:
63            case InstructionConstants.OP_FCONST_1:
64            case InstructionConstants.OP_FCONST_2:
65            case InstructionConstants.OP_DCONST_0:
66            case InstructionConstants.OP_DCONST_1:
67
68            case InstructionConstants.OP_BIPUSH:
69            case InstructionConstants.OP_SIPUSH:
70
71            case InstructionConstants.OP_IALOAD:
72            case InstructionConstants.OP_LALOAD:
73            case InstructionConstants.OP_FALOAD:
74            case InstructionConstants.OP_DALOAD:
75            case InstructionConstants.OP_AALOAD:
76            case InstructionConstants.OP_BALOAD:
77            case InstructionConstants.OP_CALOAD:
78            case InstructionConstants.OP_SALOAD:
79
80            case InstructionConstants.OP_IASTORE:
81            case InstructionConstants.OP_LASTORE:
82            case InstructionConstants.OP_FASTORE:
83            case InstructionConstants.OP_DASTORE:
84            case InstructionConstants.OP_AASTORE:
85            case InstructionConstants.OP_BASTORE:
86            case InstructionConstants.OP_CASTORE:
87            case InstructionConstants.OP_SASTORE:
88            case InstructionConstants.OP_POP:
89            case InstructionConstants.OP_POP2:
90            case InstructionConstants.OP_DUP:
91            case InstructionConstants.OP_DUP_X1:
92            case InstructionConstants.OP_DUP_X2:
93            case InstructionConstants.OP_DUP2:
94            case InstructionConstants.OP_DUP2_X1:
95            case InstructionConstants.OP_DUP2_X2:
96            case InstructionConstants.OP_SWAP:
97            case InstructionConstants.OP_IADD:
98            case InstructionConstants.OP_LADD:
99            case InstructionConstants.OP_FADD:
100            case InstructionConstants.OP_DADD:
101            case InstructionConstants.OP_ISUB:
102            case InstructionConstants.OP_LSUB:
103            case InstructionConstants.OP_FSUB:
104            case InstructionConstants.OP_DSUB:
105            case InstructionConstants.OP_IMUL:
106            case InstructionConstants.OP_LMUL:
107            case InstructionConstants.OP_FMUL:
108            case InstructionConstants.OP_DMUL:
109            case InstructionConstants.OP_IDIV:
110            case InstructionConstants.OP_LDIV:
111            case InstructionConstants.OP_FDIV:
112            case InstructionConstants.OP_DDIV:
113            case InstructionConstants.OP_IREM:
114            case InstructionConstants.OP_LREM:
115            case InstructionConstants.OP_FREM:
116            case InstructionConstants.OP_DREM:
117            case InstructionConstants.OP_INEG:
118            case InstructionConstants.OP_LNEG:
119            case InstructionConstants.OP_FNEG:
120            case InstructionConstants.OP_DNEG:
121            case InstructionConstants.OP_ISHL:
122            case InstructionConstants.OP_LSHL:
123            case InstructionConstants.OP_ISHR:
124            case InstructionConstants.OP_LSHR:
125            case InstructionConstants.OP_IUSHR:
126            case InstructionConstants.OP_LUSHR:
127            case InstructionConstants.OP_IAND:
128            case InstructionConstants.OP_LAND:
129            case InstructionConstants.OP_IOR:
130            case InstructionConstants.OP_LOR:
131            case InstructionConstants.OP_IXOR:
132            case InstructionConstants.OP_LXOR:
133
134            case InstructionConstants.OP_I2L:
135            case InstructionConstants.OP_I2F:
136            case InstructionConstants.OP_I2D:
137            case InstructionConstants.OP_L2I:
138            case InstructionConstants.OP_L2F:
139            case InstructionConstants.OP_L2D:
140            case InstructionConstants.OP_F2I:
141            case InstructionConstants.OP_F2L:
142            case InstructionConstants.OP_F2D:
143            case InstructionConstants.OP_D2I:
144            case InstructionConstants.OP_D2L:
145            case InstructionConstants.OP_D2F:
146            case InstructionConstants.OP_I2B:
147            case InstructionConstants.OP_I2C:
148            case InstructionConstants.OP_I2S:
149            case InstructionConstants.OP_LCMP:
150            case InstructionConstants.OP_FCMPL:
151            case InstructionConstants.OP_FCMPG:
152            case InstructionConstants.OP_DCMPL:
153            case InstructionConstants.OP_DCMPG:
154
155            case InstructionConstants.OP_IRETURN:
156            case InstructionConstants.OP_LRETURN:
157            case InstructionConstants.OP_FRETURN:
158            case InstructionConstants.OP_DRETURN:
159            case InstructionConstants.OP_ARETURN:
160            case InstructionConstants.OP_RETURN:
161
162            case InstructionConstants.OP_NEWARRAY:
163            case InstructionConstants.OP_ARRAYLENGTH:
164            case InstructionConstants.OP_ATHROW:
165
166            case InstructionConstants.OP_MONITORENTER:
167            case InstructionConstants.OP_MONITOREXIT:
168                instruction = new SimpleInstruction();
169                break;
170
171            // Instructions with a contant pool index.
172            case InstructionConstants.OP_LDC:
173            case InstructionConstants.OP_LDC_W:
174            case InstructionConstants.OP_LDC2_W:
175
176            case InstructionConstants.OP_GETSTATIC:
177            case InstructionConstants.OP_PUTSTATIC:
178            case InstructionConstants.OP_GETFIELD:
179            case InstructionConstants.OP_PUTFIELD:
180
181            case InstructionConstants.OP_INVOKEVIRTUAL:
182            case InstructionConstants.OP_INVOKESPECIAL:
183            case InstructionConstants.OP_INVOKESTATIC:
184            case InstructionConstants.OP_INVOKEINTERFACE:
185
186            case InstructionConstants.OP_NEW:
187            case InstructionConstants.OP_ANEWARRAY:
188            case InstructionConstants.OP_CHECKCAST:
189            case InstructionConstants.OP_INSTANCEOF:
190            case InstructionConstants.OP_MULTIANEWARRAY:
191                instruction = new ConstantInstruction();
192                break;
193
194            // Instructions with a local variable index.
195            case InstructionConstants.OP_ILOAD:
196            case InstructionConstants.OP_LLOAD:
197            case InstructionConstants.OP_FLOAD:
198            case InstructionConstants.OP_DLOAD:
199            case InstructionConstants.OP_ALOAD:
200            case InstructionConstants.OP_ILOAD_0:
201            case InstructionConstants.OP_ILOAD_1:
202            case InstructionConstants.OP_ILOAD_2:
203            case InstructionConstants.OP_ILOAD_3:
204            case InstructionConstants.OP_LLOAD_0:
205            case InstructionConstants.OP_LLOAD_1:
206            case InstructionConstants.OP_LLOAD_2:
207            case InstructionConstants.OP_LLOAD_3:
208            case InstructionConstants.OP_FLOAD_0:
209            case InstructionConstants.OP_FLOAD_1:
210            case InstructionConstants.OP_FLOAD_2:
211            case InstructionConstants.OP_FLOAD_3:
212            case InstructionConstants.OP_DLOAD_0:
213            case InstructionConstants.OP_DLOAD_1:
214            case InstructionConstants.OP_DLOAD_2:
215            case InstructionConstants.OP_DLOAD_3:
216            case InstructionConstants.OP_ALOAD_0:
217            case InstructionConstants.OP_ALOAD_1:
218            case InstructionConstants.OP_ALOAD_2:
219            case InstructionConstants.OP_ALOAD_3:
220
221            case InstructionConstants.OP_ISTORE:
222            case InstructionConstants.OP_LSTORE:
223            case InstructionConstants.OP_FSTORE:
224            case InstructionConstants.OP_DSTORE:
225            case InstructionConstants.OP_ASTORE:
226            case InstructionConstants.OP_ISTORE_0:
227            case InstructionConstants.OP_ISTORE_1:
228            case InstructionConstants.OP_ISTORE_2:
229            case InstructionConstants.OP_ISTORE_3:
230            case InstructionConstants.OP_LSTORE_0:
231            case InstructionConstants.OP_LSTORE_1:
232            case InstructionConstants.OP_LSTORE_2:
233            case InstructionConstants.OP_LSTORE_3:
234            case InstructionConstants.OP_FSTORE_0:
235            case InstructionConstants.OP_FSTORE_1:
236            case InstructionConstants.OP_FSTORE_2:
237            case InstructionConstants.OP_FSTORE_3:
238            case InstructionConstants.OP_DSTORE_0:
239            case InstructionConstants.OP_DSTORE_1:
240            case InstructionConstants.OP_DSTORE_2:
241            case InstructionConstants.OP_DSTORE_3:
242            case InstructionConstants.OP_ASTORE_0:
243            case InstructionConstants.OP_ASTORE_1:
244            case InstructionConstants.OP_ASTORE_2:
245            case InstructionConstants.OP_ASTORE_3:
246
247            case InstructionConstants.OP_IINC:
248
249            case InstructionConstants.OP_RET:
250                instruction = new VariableInstruction(wide);
251                break;
252
253            // Instructions with a branch offset operand.
254            case InstructionConstants.OP_IFEQ:
255            case InstructionConstants.OP_IFNE:
256            case InstructionConstants.OP_IFLT:
257            case InstructionConstants.OP_IFGE:
258            case InstructionConstants.OP_IFGT:
259            case InstructionConstants.OP_IFLE:
260            case InstructionConstants.OP_IFICMPEQ:
261            case InstructionConstants.OP_IFICMPNE:
262            case InstructionConstants.OP_IFICMPLT:
263            case InstructionConstants.OP_IFICMPGE:
264            case InstructionConstants.OP_IFICMPGT:
265            case InstructionConstants.OP_IFICMPLE:
266            case InstructionConstants.OP_IFACMPEQ:
267            case InstructionConstants.OP_IFACMPNE:
268            case InstructionConstants.OP_GOTO:
269            case InstructionConstants.OP_JSR:
270
271            case InstructionConstants.OP_IFNULL:
272            case InstructionConstants.OP_IFNONNULL:
273
274            case InstructionConstants.OP_GOTO_W:
275            case InstructionConstants.OP_JSR_W:
276                instruction = new BranchInstruction();
277                break;
278
279            //  The tableswitch instruction.
280            case InstructionConstants.OP_TABLESWITCH:
281                instruction = new TableSwitchInstruction();
282                break;
283
284            //  The lookupswitch instruction.
285            case InstructionConstants.OP_LOOKUPSWITCH:
286                instruction = new LookUpSwitchInstruction();
287                break;
288
289            default:
290                throw new IllegalArgumentException("Unknown instruction opcode ["+opcode+"] at offset "+offset);
291        }
292
293        instruction.opcode = opcode;
294
295        instruction.readInfo(code, index);
296
297        return instruction;
298    }
299}
300