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