1 /*
2  * ProGuard -- shrinking, optimization, obfuscation, and preverification
3  *             of Java bytecode.
4  *
5  * Copyright (c) 2002-2014 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  */
21 package proguard.classfile.instruction;
22 
23 /**
24  * This class provides methods to create and reuse Instruction objects.
25  *
26  * @author Eric Lafortune
27  */
28 public class InstructionFactory
29 {
30     /**
31      * Creates a new Instruction from the data in the byte array, starting
32      * at the given index.
33      */
create(byte[] code, int offset)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             case InstructionConstants.OP_INVOKEDYNAMIC:
186 
187             case InstructionConstants.OP_NEW:
188             case InstructionConstants.OP_ANEWARRAY:
189             case InstructionConstants.OP_CHECKCAST:
190             case InstructionConstants.OP_INSTANCEOF:
191             case InstructionConstants.OP_MULTIANEWARRAY:
192                 instruction = new ConstantInstruction();
193                 break;
194 
195             // Instructions with a local variable index.
196             case InstructionConstants.OP_ILOAD:
197             case InstructionConstants.OP_LLOAD:
198             case InstructionConstants.OP_FLOAD:
199             case InstructionConstants.OP_DLOAD:
200             case InstructionConstants.OP_ALOAD:
201             case InstructionConstants.OP_ILOAD_0:
202             case InstructionConstants.OP_ILOAD_1:
203             case InstructionConstants.OP_ILOAD_2:
204             case InstructionConstants.OP_ILOAD_3:
205             case InstructionConstants.OP_LLOAD_0:
206             case InstructionConstants.OP_LLOAD_1:
207             case InstructionConstants.OP_LLOAD_2:
208             case InstructionConstants.OP_LLOAD_3:
209             case InstructionConstants.OP_FLOAD_0:
210             case InstructionConstants.OP_FLOAD_1:
211             case InstructionConstants.OP_FLOAD_2:
212             case InstructionConstants.OP_FLOAD_3:
213             case InstructionConstants.OP_DLOAD_0:
214             case InstructionConstants.OP_DLOAD_1:
215             case InstructionConstants.OP_DLOAD_2:
216             case InstructionConstants.OP_DLOAD_3:
217             case InstructionConstants.OP_ALOAD_0:
218             case InstructionConstants.OP_ALOAD_1:
219             case InstructionConstants.OP_ALOAD_2:
220             case InstructionConstants.OP_ALOAD_3:
221 
222             case InstructionConstants.OP_ISTORE:
223             case InstructionConstants.OP_LSTORE:
224             case InstructionConstants.OP_FSTORE:
225             case InstructionConstants.OP_DSTORE:
226             case InstructionConstants.OP_ASTORE:
227             case InstructionConstants.OP_ISTORE_0:
228             case InstructionConstants.OP_ISTORE_1:
229             case InstructionConstants.OP_ISTORE_2:
230             case InstructionConstants.OP_ISTORE_3:
231             case InstructionConstants.OP_LSTORE_0:
232             case InstructionConstants.OP_LSTORE_1:
233             case InstructionConstants.OP_LSTORE_2:
234             case InstructionConstants.OP_LSTORE_3:
235             case InstructionConstants.OP_FSTORE_0:
236             case InstructionConstants.OP_FSTORE_1:
237             case InstructionConstants.OP_FSTORE_2:
238             case InstructionConstants.OP_FSTORE_3:
239             case InstructionConstants.OP_DSTORE_0:
240             case InstructionConstants.OP_DSTORE_1:
241             case InstructionConstants.OP_DSTORE_2:
242             case InstructionConstants.OP_DSTORE_3:
243             case InstructionConstants.OP_ASTORE_0:
244             case InstructionConstants.OP_ASTORE_1:
245             case InstructionConstants.OP_ASTORE_2:
246             case InstructionConstants.OP_ASTORE_3:
247 
248             case InstructionConstants.OP_IINC:
249 
250             case InstructionConstants.OP_RET:
251                 instruction = new VariableInstruction(wide);
252                 break;
253 
254             // Instructions with a branch offset operand.
255             case InstructionConstants.OP_IFEQ:
256             case InstructionConstants.OP_IFNE:
257             case InstructionConstants.OP_IFLT:
258             case InstructionConstants.OP_IFGE:
259             case InstructionConstants.OP_IFGT:
260             case InstructionConstants.OP_IFLE:
261             case InstructionConstants.OP_IFICMPEQ:
262             case InstructionConstants.OP_IFICMPNE:
263             case InstructionConstants.OP_IFICMPLT:
264             case InstructionConstants.OP_IFICMPGE:
265             case InstructionConstants.OP_IFICMPGT:
266             case InstructionConstants.OP_IFICMPLE:
267             case InstructionConstants.OP_IFACMPEQ:
268             case InstructionConstants.OP_IFACMPNE:
269             case InstructionConstants.OP_GOTO:
270             case InstructionConstants.OP_JSR:
271 
272             case InstructionConstants.OP_IFNULL:
273             case InstructionConstants.OP_IFNONNULL:
274 
275             case InstructionConstants.OP_GOTO_W:
276             case InstructionConstants.OP_JSR_W:
277                 instruction = new BranchInstruction();
278                 break;
279 
280             //  The tableswitch instruction.
281             case InstructionConstants.OP_TABLESWITCH:
282                 instruction = new TableSwitchInstruction();
283                 break;
284 
285             //  The lookupswitch instruction.
286             case InstructionConstants.OP_LOOKUPSWITCH:
287                 instruction = new LookUpSwitchInstruction();
288                 break;
289 
290             default:
291                 throw new IllegalArgumentException("Unknown instruction opcode ["+opcode+"] at offset "+offset);
292         }
293 
294         instruction.opcode = opcode;
295 
296         instruction.readInfo(code, index);
297 
298         return instruction;
299     }
300 }
301