1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.bcel.generic;
18
19 import java.io.DataOutputStream;
20 import java.io.IOException;
21
22 import org.apache.bcel.Const;
23 import org.apache.bcel.classfile.ConstantPool;
24 import org.apache.bcel.util.ByteSequence;
25
26
27
28
29 public abstract class Instruction implements Cloneable {
30
31 static final Instruction[] EMPTY_ARRAY = {};
32
33 private static InstructionComparator cmp = InstructionComparator.DEFAULT;
34
35
36
37
38
39
40
41 @Deprecated
42 public static InstructionComparator getComparator() {
43 return cmp;
44 }
45
46
47
48
49
50
51
52
53 public static boolean isValidByte(final int value) {
54 return value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE;
55 }
56
57
58
59
60
61
62
63
64 public static boolean isValidShort(final int value) {
65 return value >= Short.MIN_VALUE && value <= Short.MAX_VALUE;
66 }
67
68
69
70
71
72
73
74
75
76
77
78
79 public static Instruction readInstruction(final ByteSequence bytes) throws IOException {
80 boolean wide = false;
81 short opcode = (short) bytes.readUnsignedByte();
82 Instruction obj = null;
83 if (opcode == Const.WIDE) {
84 wide = true;
85 opcode = (short) bytes.readUnsignedByte();
86 }
87 final Instruction instruction = InstructionConst.getInstruction(opcode);
88 if (instruction != null) {
89 return instruction;
90 }
91
92 switch (opcode) {
93 case Const.BIPUSH:
94 obj = new BIPUSH();
95 break;
96 case Const.SIPUSH:
97 obj = new SIPUSH();
98 break;
99 case Const.LDC:
100 obj = new LDC();
101 break;
102 case Const.LDC_W:
103 obj = new LDC_W();
104 break;
105 case Const.LDC2_W:
106 obj = new LDC2_W();
107 break;
108 case Const.ILOAD:
109 obj = new ILOAD();
110 break;
111 case Const.LLOAD:
112 obj = new LLOAD();
113 break;
114 case Const.FLOAD:
115 obj = new FLOAD();
116 break;
117 case Const.DLOAD:
118 obj = new DLOAD();
119 break;
120 case Const.ALOAD:
121 obj = new ALOAD();
122 break;
123 case Const.ILOAD_0:
124 obj = new ILOAD(0);
125 break;
126 case Const.ILOAD_1:
127 obj = new ILOAD(1);
128 break;
129 case Const.ILOAD_2:
130 obj = new ILOAD(2);
131 break;
132 case Const.ILOAD_3:
133 obj = new ILOAD(3);
134 break;
135 case Const.LLOAD_0:
136 obj = new LLOAD(0);
137 break;
138 case Const.LLOAD_1:
139 obj = new LLOAD(1);
140 break;
141 case Const.LLOAD_2:
142 obj = new LLOAD(2);
143 break;
144 case Const.LLOAD_3:
145 obj = new LLOAD(3);
146 break;
147 case Const.FLOAD_0:
148 obj = new FLOAD(0);
149 break;
150 case Const.FLOAD_1:
151 obj = new FLOAD(1);
152 break;
153 case Const.FLOAD_2:
154 obj = new FLOAD(2);
155 break;
156 case Const.FLOAD_3:
157 obj = new FLOAD(3);
158 break;
159 case Const.DLOAD_0:
160 obj = new DLOAD(0);
161 break;
162 case Const.DLOAD_1:
163 obj = new DLOAD(1);
164 break;
165 case Const.DLOAD_2:
166 obj = new DLOAD(2);
167 break;
168 case Const.DLOAD_3:
169 obj = new DLOAD(3);
170 break;
171 case Const.ALOAD_0:
172 obj = new ALOAD(0);
173 break;
174 case Const.ALOAD_1:
175 obj = new ALOAD(1);
176 break;
177 case Const.ALOAD_2:
178 obj = new ALOAD(2);
179 break;
180 case Const.ALOAD_3:
181 obj = new ALOAD(3);
182 break;
183 case Const.ISTORE:
184 obj = new ISTORE();
185 break;
186 case Const.LSTORE:
187 obj = new LSTORE();
188 break;
189 case Const.FSTORE:
190 obj = new FSTORE();
191 break;
192 case Const.DSTORE:
193 obj = new DSTORE();
194 break;
195 case Const.ASTORE:
196 obj = new ASTORE();
197 break;
198 case Const.ISTORE_0:
199 obj = new ISTORE(0);
200 break;
201 case Const.ISTORE_1:
202 obj = new ISTORE(1);
203 break;
204 case Const.ISTORE_2:
205 obj = new ISTORE(2);
206 break;
207 case Const.ISTORE_3:
208 obj = new ISTORE(3);
209 break;
210 case Const.LSTORE_0:
211 obj = new LSTORE(0);
212 break;
213 case Const.LSTORE_1:
214 obj = new LSTORE(1);
215 break;
216 case Const.LSTORE_2:
217 obj = new LSTORE(2);
218 break;
219 case Const.LSTORE_3:
220 obj = new LSTORE(3);
221 break;
222 case Const.FSTORE_0:
223 obj = new FSTORE(0);
224 break;
225 case Const.FSTORE_1:
226 obj = new FSTORE(1);
227 break;
228 case Const.FSTORE_2:
229 obj = new FSTORE(2);
230 break;
231 case Const.FSTORE_3:
232 obj = new FSTORE(3);
233 break;
234 case Const.DSTORE_0:
235 obj = new DSTORE(0);
236 break;
237 case Const.DSTORE_1:
238 obj = new DSTORE(1);
239 break;
240 case Const.DSTORE_2:
241 obj = new DSTORE(2);
242 break;
243 case Const.DSTORE_3:
244 obj = new DSTORE(3);
245 break;
246 case Const.ASTORE_0:
247 obj = new ASTORE(0);
248 break;
249 case Const.ASTORE_1:
250 obj = new ASTORE(1);
251 break;
252 case Const.ASTORE_2:
253 obj = new ASTORE(2);
254 break;
255 case Const.ASTORE_3:
256 obj = new ASTORE(3);
257 break;
258 case Const.IINC:
259 obj = new IINC();
260 break;
261 case Const.IFEQ:
262 obj = new IFEQ();
263 break;
264 case Const.IFNE:
265 obj = new IFNE();
266 break;
267 case Const.IFLT:
268 obj = new IFLT();
269 break;
270 case Const.IFGE:
271 obj = new IFGE();
272 break;
273 case Const.IFGT:
274 obj = new IFGT();
275 break;
276 case Const.IFLE:
277 obj = new IFLE();
278 break;
279 case Const.IF_ICMPEQ:
280 obj = new IF_ICMPEQ();
281 break;
282 case Const.IF_ICMPNE:
283 obj = new IF_ICMPNE();
284 break;
285 case Const.IF_ICMPLT:
286 obj = new IF_ICMPLT();
287 break;
288 case Const.IF_ICMPGE:
289 obj = new IF_ICMPGE();
290 break;
291 case Const.IF_ICMPGT:
292 obj = new IF_ICMPGT();
293 break;
294 case Const.IF_ICMPLE:
295 obj = new IF_ICMPLE();
296 break;
297 case Const.IF_ACMPEQ:
298 obj = new IF_ACMPEQ();
299 break;
300 case Const.IF_ACMPNE:
301 obj = new IF_ACMPNE();
302 break;
303 case Const.GOTO:
304 obj = new GOTO();
305 break;
306 case Const.JSR:
307 obj = new JSR();
308 break;
309 case Const.RET:
310 obj = new RET();
311 break;
312 case Const.TABLESWITCH:
313 obj = new TABLESWITCH();
314 break;
315 case Const.LOOKUPSWITCH:
316 obj = new LOOKUPSWITCH();
317 break;
318 case Const.GETSTATIC:
319 obj = new GETSTATIC();
320 break;
321 case Const.PUTSTATIC:
322 obj = new PUTSTATIC();
323 break;
324 case Const.GETFIELD:
325 obj = new GETFIELD();
326 break;
327 case Const.PUTFIELD:
328 obj = new PUTFIELD();
329 break;
330 case Const.INVOKEVIRTUAL:
331 obj = new INVOKEVIRTUAL();
332 break;
333 case Const.INVOKESPECIAL:
334 obj = new INVOKESPECIAL();
335 break;
336 case Const.INVOKESTATIC:
337 obj = new INVOKESTATIC();
338 break;
339 case Const.INVOKEINTERFACE:
340 obj = new INVOKEINTERFACE();
341 break;
342 case Const.INVOKEDYNAMIC:
343 obj = new INVOKEDYNAMIC();
344 break;
345 case Const.NEW:
346 obj = new NEW();
347 break;
348 case Const.NEWARRAY:
349 obj = new NEWARRAY();
350 break;
351 case Const.ANEWARRAY:
352 obj = new ANEWARRAY();
353 break;
354 case Const.CHECKCAST:
355 obj = new CHECKCAST();
356 break;
357 case Const.INSTANCEOF:
358 obj = new INSTANCEOF();
359 break;
360 case Const.MULTIANEWARRAY:
361 obj = new MULTIANEWARRAY();
362 break;
363 case Const.IFNULL:
364 obj = new IFNULL();
365 break;
366 case Const.IFNONNULL:
367 obj = new IFNONNULL();
368 break;
369 case Const.GOTO_W:
370 obj = new GOTO_W();
371 break;
372 case Const.JSR_W:
373 obj = new JSR_W();
374 break;
375 case Const.BREAKPOINT:
376 obj = new BREAKPOINT();
377 break;
378 case Const.IMPDEP1:
379 obj = new IMPDEP1();
380 break;
381 case Const.IMPDEP2:
382 obj = new IMPDEP2();
383 break;
384 default:
385 throw new ClassGenException("Illegal opcode detected: " + opcode);
386
387 }
388
389 if (wide && !(obj instanceof LocalVariableInstruction || obj instanceof RET)) {
390 throw new ClassGenException("Illegal opcode after wide: " + opcode);
391 }
392 obj.setOpcode(opcode);
393 obj.initFromFile(bytes, wide);
394 return obj;
395 }
396
397
398
399
400
401
402 @Deprecated
403 public static void setComparator(final InstructionComparator c) {
404 cmp = c;
405 }
406
407
408
409
410 @Deprecated
411 protected short length = 1;
412
413
414
415
416 @Deprecated
417 protected short opcode = -1;
418
419
420
421
422 Instruction() {
423 }
424
425 public Instruction(final short opcode, final short length) {
426 this.length = length;
427 this.opcode = opcode;
428 }
429
430
431
432
433
434
435
436 public abstract void accept(Visitor v);
437
438
439
440
441
442
443
444
445 public int consumeStack(final ConstantPoolGen cpg) {
446 return Const.getConsumeStack(opcode);
447 }
448
449
450
451
452
453
454
455
456 public Instruction copy() {
457 Instruction i = null;
458
459 if (InstructionConst.getInstruction(getOpcode()) != null) {
460 i = this;
461 } else {
462 try {
463 i = (Instruction) clone();
464 } catch (final CloneNotSupportedException e) {
465 System.err.println(e);
466 }
467 }
468 return i;
469 }
470
471
472
473
474 void dispose() {
475 }
476
477
478
479
480
481
482
483 public void dump(final DataOutputStream out) throws IOException {
484 out.writeByte(opcode);
485 }
486
487
488
489
490
491
492 @Override
493 public boolean equals(final Object that) {
494 return that instanceof Instruction && cmp.equals(this, (Instruction) that);
495 }
496
497
498
499
500 public int getLength() {
501 return length;
502 }
503
504
505
506
507 public String getName() {
508 return Const.getOpcodeName(opcode);
509 }
510
511
512
513
514 public short getOpcode() {
515 return opcode;
516 }
517
518
519
520
521
522
523
524 @Override
525 public int hashCode() {
526 return opcode;
527 }
528
529
530
531
532
533
534
535
536 @SuppressWarnings("unused")
537 protected void initFromFile(final ByteSequence bytes, final boolean wide) throws IOException {
538 }
539
540
541
542
543
544
545
546
547 public int produceStack(final ConstantPoolGen cpg) {
548 return Const.getProduceStack(opcode);
549 }
550
551
552
553
554
555
556 final void setLength(final int length) {
557 this.length = (short) length;
558 }
559
560
561
562
563 final void setOpcode(final short opcode) {
564 this.opcode = opcode;
565 }
566
567
568
569
570 @Override
571 public String toString() {
572 return toString(true);
573 }
574
575
576
577
578
579
580
581
582
583 public String toString(final boolean verbose) {
584 if (verbose) {
585 return getName() + "[" + opcode + "](" + length + ")";
586 }
587 return getName();
588 }
589
590
591
592
593 public String toString(final ConstantPool cp) {
594 return toString(false);
595 }
596 }