1/*
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3 *
4 * This code is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 2 only, as
6 * published by the Free Software Foundation.  Oracle designates this
7 * particular file as subject to the "Classpath" exception as provided
8 * by Oracle in the LICENSE file that accompanied this code.
9 *
10 * This code is distributed in the hope that it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13 * version 2 for more details (a copy is included in the LICENSE file that
14 * accompanied this code).
15 *
16 * You should have received a copy of the GNU General Public License version
17 * 2 along with this work; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
21 * or visit www.oracle.com if you need additional information or have any
22 * questions.
23 */
24
25/*
26 * This file is available under and governed by the GNU General Public
27 * License version 2 only, as published by the Free Software Foundation.
28 * However, the following notice accompanied the original version of this
29 * file:
30 *
31 * ASM: a very small and fast Java bytecode manipulation framework
32 * Copyright (c) 2000-2011 INRIA, France Telecom
33 * All rights reserved.
34 *
35 * Redistribution and use in source and binary forms, with or without
36 * modification, are permitted provided that the following conditions
37 * are met:
38 * 1. Redistributions of source code must retain the above copyright
39 *    notice, this list of conditions and the following disclaimer.
40 * 2. Redistributions in binary form must reproduce the above copyright
41 *    notice, this list of conditions and the following disclaimer in the
42 *    documentation and/or other materials provided with the distribution.
43 * 3. Neither the name of the copyright holders nor the names of its
44 *    contributors may be used to endorse or promote products derived from
45 *    this software without specific prior written permission.
46 *
47 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
48 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
51 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
52 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
53 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
54 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
55 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
56 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
57 * THE POSSIBILITY OF SUCH DAMAGE.
58 */
59
60package jdk.internal.org.objectweb.asm.commons;
61
62import jdk.internal.org.objectweb.asm.Handle;
63import jdk.internal.org.objectweb.asm.Label;
64import jdk.internal.org.objectweb.asm.MethodVisitor;
65import jdk.internal.org.objectweb.asm.Opcodes;
66import jdk.internal.org.objectweb.asm.Type;
67
68/**
69 * A {@link MethodVisitor} providing a more detailed API to generate and
70 * transform instructions.
71 *
72 * @author Eric Bruneton
73 */
74public class InstructionAdapter extends MethodVisitor {
75
76    public final static Type OBJECT_TYPE = Type.getType("Ljava/lang/Object;");
77
78    /**
79     * Creates a new {@link InstructionAdapter}. <i>Subclasses must not use this
80     * constructor</i>. Instead, they must use the
81     * {@link #InstructionAdapter(int, MethodVisitor)} version.
82     *
83     * @param mv
84     *            the method visitor to which this adapter delegates calls.
85     * @throws IllegalStateException
86     *             If a subclass calls this constructor.
87     */
88    public InstructionAdapter(final MethodVisitor mv) {
89        this(Opcodes.ASM5, mv);
90        if (getClass() != InstructionAdapter.class) {
91            throw new IllegalStateException();
92        }
93    }
94
95    /**
96     * Creates a new {@link InstructionAdapter}.
97     *
98     * @param api
99     *            the ASM API version implemented by this visitor. Must be one
100     *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
101     * @param mv
102     *            the method visitor to which this adapter delegates calls.
103     */
104    protected InstructionAdapter(final int api, final MethodVisitor mv) {
105        super(api, mv);
106    }
107
108    @Override
109    public void visitInsn(final int opcode) {
110        switch (opcode) {
111        case Opcodes.NOP:
112            nop();
113            break;
114        case Opcodes.ACONST_NULL:
115            aconst(null);
116            break;
117        case Opcodes.ICONST_M1:
118        case Opcodes.ICONST_0:
119        case Opcodes.ICONST_1:
120        case Opcodes.ICONST_2:
121        case Opcodes.ICONST_3:
122        case Opcodes.ICONST_4:
123        case Opcodes.ICONST_5:
124            iconst(opcode - Opcodes.ICONST_0);
125            break;
126        case Opcodes.LCONST_0:
127        case Opcodes.LCONST_1:
128            lconst(opcode - Opcodes.LCONST_0);
129            break;
130        case Opcodes.FCONST_0:
131        case Opcodes.FCONST_1:
132        case Opcodes.FCONST_2:
133            fconst(opcode - Opcodes.FCONST_0);
134            break;
135        case Opcodes.DCONST_0:
136        case Opcodes.DCONST_1:
137            dconst(opcode - Opcodes.DCONST_0);
138            break;
139        case Opcodes.IALOAD:
140            aload(Type.INT_TYPE);
141            break;
142        case Opcodes.LALOAD:
143            aload(Type.LONG_TYPE);
144            break;
145        case Opcodes.FALOAD:
146            aload(Type.FLOAT_TYPE);
147            break;
148        case Opcodes.DALOAD:
149            aload(Type.DOUBLE_TYPE);
150            break;
151        case Opcodes.AALOAD:
152            aload(OBJECT_TYPE);
153            break;
154        case Opcodes.BALOAD:
155            aload(Type.BYTE_TYPE);
156            break;
157        case Opcodes.CALOAD:
158            aload(Type.CHAR_TYPE);
159            break;
160        case Opcodes.SALOAD:
161            aload(Type.SHORT_TYPE);
162            break;
163        case Opcodes.IASTORE:
164            astore(Type.INT_TYPE);
165            break;
166        case Opcodes.LASTORE:
167            astore(Type.LONG_TYPE);
168            break;
169        case Opcodes.FASTORE:
170            astore(Type.FLOAT_TYPE);
171            break;
172        case Opcodes.DASTORE:
173            astore(Type.DOUBLE_TYPE);
174            break;
175        case Opcodes.AASTORE:
176            astore(OBJECT_TYPE);
177            break;
178        case Opcodes.BASTORE:
179            astore(Type.BYTE_TYPE);
180            break;
181        case Opcodes.CASTORE:
182            astore(Type.CHAR_TYPE);
183            break;
184        case Opcodes.SASTORE:
185            astore(Type.SHORT_TYPE);
186            break;
187        case Opcodes.POP:
188            pop();
189            break;
190        case Opcodes.POP2:
191            pop2();
192            break;
193        case Opcodes.DUP:
194            dup();
195            break;
196        case Opcodes.DUP_X1:
197            dupX1();
198            break;
199        case Opcodes.DUP_X2:
200            dupX2();
201            break;
202        case Opcodes.DUP2:
203            dup2();
204            break;
205        case Opcodes.DUP2_X1:
206            dup2X1();
207            break;
208        case Opcodes.DUP2_X2:
209            dup2X2();
210            break;
211        case Opcodes.SWAP:
212            swap();
213            break;
214        case Opcodes.IADD:
215            add(Type.INT_TYPE);
216            break;
217        case Opcodes.LADD:
218            add(Type.LONG_TYPE);
219            break;
220        case Opcodes.FADD:
221            add(Type.FLOAT_TYPE);
222            break;
223        case Opcodes.DADD:
224            add(Type.DOUBLE_TYPE);
225            break;
226        case Opcodes.ISUB:
227            sub(Type.INT_TYPE);
228            break;
229        case Opcodes.LSUB:
230            sub(Type.LONG_TYPE);
231            break;
232        case Opcodes.FSUB:
233            sub(Type.FLOAT_TYPE);
234            break;
235        case Opcodes.DSUB:
236            sub(Type.DOUBLE_TYPE);
237            break;
238        case Opcodes.IMUL:
239            mul(Type.INT_TYPE);
240            break;
241        case Opcodes.LMUL:
242            mul(Type.LONG_TYPE);
243            break;
244        case Opcodes.FMUL:
245            mul(Type.FLOAT_TYPE);
246            break;
247        case Opcodes.DMUL:
248            mul(Type.DOUBLE_TYPE);
249            break;
250        case Opcodes.IDIV:
251            div(Type.INT_TYPE);
252            break;
253        case Opcodes.LDIV:
254            div(Type.LONG_TYPE);
255            break;
256        case Opcodes.FDIV:
257            div(Type.FLOAT_TYPE);
258            break;
259        case Opcodes.DDIV:
260            div(Type.DOUBLE_TYPE);
261            break;
262        case Opcodes.IREM:
263            rem(Type.INT_TYPE);
264            break;
265        case Opcodes.LREM:
266            rem(Type.LONG_TYPE);
267            break;
268        case Opcodes.FREM:
269            rem(Type.FLOAT_TYPE);
270            break;
271        case Opcodes.DREM:
272            rem(Type.DOUBLE_TYPE);
273            break;
274        case Opcodes.INEG:
275            neg(Type.INT_TYPE);
276            break;
277        case Opcodes.LNEG:
278            neg(Type.LONG_TYPE);
279            break;
280        case Opcodes.FNEG:
281            neg(Type.FLOAT_TYPE);
282            break;
283        case Opcodes.DNEG:
284            neg(Type.DOUBLE_TYPE);
285            break;
286        case Opcodes.ISHL:
287            shl(Type.INT_TYPE);
288            break;
289        case Opcodes.LSHL:
290            shl(Type.LONG_TYPE);
291            break;
292        case Opcodes.ISHR:
293            shr(Type.INT_TYPE);
294            break;
295        case Opcodes.LSHR:
296            shr(Type.LONG_TYPE);
297            break;
298        case Opcodes.IUSHR:
299            ushr(Type.INT_TYPE);
300            break;
301        case Opcodes.LUSHR:
302            ushr(Type.LONG_TYPE);
303            break;
304        case Opcodes.IAND:
305            and(Type.INT_TYPE);
306            break;
307        case Opcodes.LAND:
308            and(Type.LONG_TYPE);
309            break;
310        case Opcodes.IOR:
311            or(Type.INT_TYPE);
312            break;
313        case Opcodes.LOR:
314            or(Type.LONG_TYPE);
315            break;
316        case Opcodes.IXOR:
317            xor(Type.INT_TYPE);
318            break;
319        case Opcodes.LXOR:
320            xor(Type.LONG_TYPE);
321            break;
322        case Opcodes.I2L:
323            cast(Type.INT_TYPE, Type.LONG_TYPE);
324            break;
325        case Opcodes.I2F:
326            cast(Type.INT_TYPE, Type.FLOAT_TYPE);
327            break;
328        case Opcodes.I2D:
329            cast(Type.INT_TYPE, Type.DOUBLE_TYPE);
330            break;
331        case Opcodes.L2I:
332            cast(Type.LONG_TYPE, Type.INT_TYPE);
333            break;
334        case Opcodes.L2F:
335            cast(Type.LONG_TYPE, Type.FLOAT_TYPE);
336            break;
337        case Opcodes.L2D:
338            cast(Type.LONG_TYPE, Type.DOUBLE_TYPE);
339            break;
340        case Opcodes.F2I:
341            cast(Type.FLOAT_TYPE, Type.INT_TYPE);
342            break;
343        case Opcodes.F2L:
344            cast(Type.FLOAT_TYPE, Type.LONG_TYPE);
345            break;
346        case Opcodes.F2D:
347            cast(Type.FLOAT_TYPE, Type.DOUBLE_TYPE);
348            break;
349        case Opcodes.D2I:
350            cast(Type.DOUBLE_TYPE, Type.INT_TYPE);
351            break;
352        case Opcodes.D2L:
353            cast(Type.DOUBLE_TYPE, Type.LONG_TYPE);
354            break;
355        case Opcodes.D2F:
356            cast(Type.DOUBLE_TYPE, Type.FLOAT_TYPE);
357            break;
358        case Opcodes.I2B:
359            cast(Type.INT_TYPE, Type.BYTE_TYPE);
360            break;
361        case Opcodes.I2C:
362            cast(Type.INT_TYPE, Type.CHAR_TYPE);
363            break;
364        case Opcodes.I2S:
365            cast(Type.INT_TYPE, Type.SHORT_TYPE);
366            break;
367        case Opcodes.LCMP:
368            lcmp();
369            break;
370        case Opcodes.FCMPL:
371            cmpl(Type.FLOAT_TYPE);
372            break;
373        case Opcodes.FCMPG:
374            cmpg(Type.FLOAT_TYPE);
375            break;
376        case Opcodes.DCMPL:
377            cmpl(Type.DOUBLE_TYPE);
378            break;
379        case Opcodes.DCMPG:
380            cmpg(Type.DOUBLE_TYPE);
381            break;
382        case Opcodes.IRETURN:
383            areturn(Type.INT_TYPE);
384            break;
385        case Opcodes.LRETURN:
386            areturn(Type.LONG_TYPE);
387            break;
388        case Opcodes.FRETURN:
389            areturn(Type.FLOAT_TYPE);
390            break;
391        case Opcodes.DRETURN:
392            areturn(Type.DOUBLE_TYPE);
393            break;
394        case Opcodes.ARETURN:
395            areturn(OBJECT_TYPE);
396            break;
397        case Opcodes.RETURN:
398            areturn(Type.VOID_TYPE);
399            break;
400        case Opcodes.ARRAYLENGTH:
401            arraylength();
402            break;
403        case Opcodes.ATHROW:
404            athrow();
405            break;
406        case Opcodes.MONITORENTER:
407            monitorenter();
408            break;
409        case Opcodes.MONITOREXIT:
410            monitorexit();
411            break;
412        default:
413            throw new IllegalArgumentException();
414        }
415    }
416
417    @Override
418    public void visitIntInsn(final int opcode, final int operand) {
419        switch (opcode) {
420        case Opcodes.BIPUSH:
421            iconst(operand);
422            break;
423        case Opcodes.SIPUSH:
424            iconst(operand);
425            break;
426        case Opcodes.NEWARRAY:
427            switch (operand) {
428            case Opcodes.T_BOOLEAN:
429                newarray(Type.BOOLEAN_TYPE);
430                break;
431            case Opcodes.T_CHAR:
432                newarray(Type.CHAR_TYPE);
433                break;
434            case Opcodes.T_BYTE:
435                newarray(Type.BYTE_TYPE);
436                break;
437            case Opcodes.T_SHORT:
438                newarray(Type.SHORT_TYPE);
439                break;
440            case Opcodes.T_INT:
441                newarray(Type.INT_TYPE);
442                break;
443            case Opcodes.T_FLOAT:
444                newarray(Type.FLOAT_TYPE);
445                break;
446            case Opcodes.T_LONG:
447                newarray(Type.LONG_TYPE);
448                break;
449            case Opcodes.T_DOUBLE:
450                newarray(Type.DOUBLE_TYPE);
451                break;
452            default:
453                throw new IllegalArgumentException();
454            }
455            break;
456        default:
457            throw new IllegalArgumentException();
458        }
459    }
460
461    @Override
462    public void visitVarInsn(final int opcode, final int var) {
463        switch (opcode) {
464        case Opcodes.ILOAD:
465            load(var, Type.INT_TYPE);
466            break;
467        case Opcodes.LLOAD:
468            load(var, Type.LONG_TYPE);
469            break;
470        case Opcodes.FLOAD:
471            load(var, Type.FLOAT_TYPE);
472            break;
473        case Opcodes.DLOAD:
474            load(var, Type.DOUBLE_TYPE);
475            break;
476        case Opcodes.ALOAD:
477            load(var, OBJECT_TYPE);
478            break;
479        case Opcodes.ISTORE:
480            store(var, Type.INT_TYPE);
481            break;
482        case Opcodes.LSTORE:
483            store(var, Type.LONG_TYPE);
484            break;
485        case Opcodes.FSTORE:
486            store(var, Type.FLOAT_TYPE);
487            break;
488        case Opcodes.DSTORE:
489            store(var, Type.DOUBLE_TYPE);
490            break;
491        case Opcodes.ASTORE:
492            store(var, OBJECT_TYPE);
493            break;
494        case Opcodes.RET:
495            ret(var);
496            break;
497        default:
498            throw new IllegalArgumentException();
499        }
500    }
501
502    @Override
503    public void visitTypeInsn(final int opcode, final String type) {
504        Type t = Type.getObjectType(type);
505        switch (opcode) {
506        case Opcodes.NEW:
507            anew(t);
508            break;
509        case Opcodes.ANEWARRAY:
510            newarray(t);
511            break;
512        case Opcodes.CHECKCAST:
513            checkcast(t);
514            break;
515        case Opcodes.INSTANCEOF:
516            instanceOf(t);
517            break;
518        default:
519            throw new IllegalArgumentException();
520        }
521    }
522
523    @Override
524    public void visitFieldInsn(final int opcode, final String owner,
525            final String name, final String desc) {
526        switch (opcode) {
527        case Opcodes.GETSTATIC:
528            getstatic(owner, name, desc);
529            break;
530        case Opcodes.PUTSTATIC:
531            putstatic(owner, name, desc);
532            break;
533        case Opcodes.GETFIELD:
534            getfield(owner, name, desc);
535            break;
536        case Opcodes.PUTFIELD:
537            putfield(owner, name, desc);
538            break;
539        default:
540            throw new IllegalArgumentException();
541        }
542    }
543
544    @Deprecated
545    @Override
546    public void visitMethodInsn(final int opcode, final String owner,
547            final String name, final String desc) {
548        if (api >= Opcodes.ASM5) {
549            super.visitMethodInsn(opcode, owner, name, desc);
550            return;
551        }
552        doVisitMethodInsn(opcode, owner, name, desc,
553                opcode == Opcodes.INVOKEINTERFACE);
554    }
555
556    @Override
557    public void visitMethodInsn(final int opcode, final String owner,
558            final String name, final String desc, final boolean itf) {
559        if (api < Opcodes.ASM5) {
560            super.visitMethodInsn(opcode, owner, name, desc, itf);
561            return;
562        }
563        doVisitMethodInsn(opcode, owner, name, desc, itf);
564    }
565
566    private void doVisitMethodInsn(int opcode, final String owner,
567            final String name, final String desc, final boolean itf) {
568        switch (opcode) {
569        case Opcodes.INVOKESPECIAL:
570            invokespecial(owner, name, desc, itf);
571            break;
572        case Opcodes.INVOKEVIRTUAL:
573            invokevirtual(owner, name, desc, itf);
574            break;
575        case Opcodes.INVOKESTATIC:
576            invokestatic(owner, name, desc, itf);
577            break;
578        case Opcodes.INVOKEINTERFACE:
579            invokeinterface(owner, name, desc);
580            break;
581        default:
582            throw new IllegalArgumentException();
583        }
584    }
585
586    @Override
587    public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,
588            Object... bsmArgs) {
589        invokedynamic(name, desc, bsm, bsmArgs);
590    }
591
592    @Override
593    public void visitJumpInsn(final int opcode, final Label label) {
594        switch (opcode) {
595        case Opcodes.IFEQ:
596            ifeq(label);
597            break;
598        case Opcodes.IFNE:
599            ifne(label);
600            break;
601        case Opcodes.IFLT:
602            iflt(label);
603            break;
604        case Opcodes.IFGE:
605            ifge(label);
606            break;
607        case Opcodes.IFGT:
608            ifgt(label);
609            break;
610        case Opcodes.IFLE:
611            ifle(label);
612            break;
613        case Opcodes.IF_ICMPEQ:
614            ificmpeq(label);
615            break;
616        case Opcodes.IF_ICMPNE:
617            ificmpne(label);
618            break;
619        case Opcodes.IF_ICMPLT:
620            ificmplt(label);
621            break;
622        case Opcodes.IF_ICMPGE:
623            ificmpge(label);
624            break;
625        case Opcodes.IF_ICMPGT:
626            ificmpgt(label);
627            break;
628        case Opcodes.IF_ICMPLE:
629            ificmple(label);
630            break;
631        case Opcodes.IF_ACMPEQ:
632            ifacmpeq(label);
633            break;
634        case Opcodes.IF_ACMPNE:
635            ifacmpne(label);
636            break;
637        case Opcodes.GOTO:
638            goTo(label);
639            break;
640        case Opcodes.JSR:
641            jsr(label);
642            break;
643        case Opcodes.IFNULL:
644            ifnull(label);
645            break;
646        case Opcodes.IFNONNULL:
647            ifnonnull(label);
648            break;
649        default:
650            throw new IllegalArgumentException();
651        }
652    }
653
654    @Override
655    public void visitLabel(final Label label) {
656        mark(label);
657    }
658
659    @Override
660    public void visitLdcInsn(final Object cst) {
661        if (cst instanceof Integer) {
662            int val = ((Integer) cst).intValue();
663            iconst(val);
664        } else if (cst instanceof Byte) {
665            int val = ((Byte) cst).intValue();
666            iconst(val);
667        } else if (cst instanceof Character) {
668            int val = ((Character) cst).charValue();
669            iconst(val);
670        } else if (cst instanceof Short) {
671            int val = ((Short) cst).intValue();
672            iconst(val);
673        } else if (cst instanceof Boolean) {
674            int val = ((Boolean) cst).booleanValue() ? 1 : 0;
675            iconst(val);
676        } else if (cst instanceof Float) {
677            float val = ((Float) cst).floatValue();
678            fconst(val);
679        } else if (cst instanceof Long) {
680            long val = ((Long) cst).longValue();
681            lconst(val);
682        } else if (cst instanceof Double) {
683            double val = ((Double) cst).doubleValue();
684            dconst(val);
685        } else if (cst instanceof String) {
686            aconst(cst);
687        } else if (cst instanceof Type) {
688            tconst((Type) cst);
689        } else if (cst instanceof Handle) {
690            hconst((Handle) cst);
691        } else {
692            throw new IllegalArgumentException();
693        }
694    }
695
696    @Override
697    public void visitIincInsn(final int var, final int increment) {
698        iinc(var, increment);
699    }
700
701    @Override
702    public void visitTableSwitchInsn(final int min, final int max,
703            final Label dflt, final Label... labels) {
704        tableswitch(min, max, dflt, labels);
705    }
706
707    @Override
708    public void visitLookupSwitchInsn(final Label dflt, final int[] keys,
709            final Label[] labels) {
710        lookupswitch(dflt, keys, labels);
711    }
712
713    @Override
714    public void visitMultiANewArrayInsn(final String desc, final int dims) {
715        multianewarray(desc, dims);
716    }
717
718    // -----------------------------------------------------------------------
719
720    public void nop() {
721        mv.visitInsn(Opcodes.NOP);
722    }
723
724    public void aconst(final Object cst) {
725        if (cst == null) {
726            mv.visitInsn(Opcodes.ACONST_NULL);
727        } else {
728            mv.visitLdcInsn(cst);
729        }
730    }
731
732    public void iconst(final int cst) {
733        if (cst >= -1 && cst <= 5) {
734            mv.visitInsn(Opcodes.ICONST_0 + cst);
735        } else if (cst >= Byte.MIN_VALUE && cst <= Byte.MAX_VALUE) {
736            mv.visitIntInsn(Opcodes.BIPUSH, cst);
737        } else if (cst >= Short.MIN_VALUE && cst <= Short.MAX_VALUE) {
738            mv.visitIntInsn(Opcodes.SIPUSH, cst);
739        } else {
740            mv.visitLdcInsn(cst);
741        }
742    }
743
744    public void lconst(final long cst) {
745        if (cst == 0L || cst == 1L) {
746            mv.visitInsn(Opcodes.LCONST_0 + (int) cst);
747        } else {
748            mv.visitLdcInsn(cst);
749        }
750    }
751
752    public void fconst(final float cst) {
753        int bits = Float.floatToIntBits(cst);
754        if (bits == 0L || bits == 0x3f800000 || bits == 0x40000000) { // 0..2
755            mv.visitInsn(Opcodes.FCONST_0 + (int) cst);
756        } else {
757            mv.visitLdcInsn(cst);
758        }
759    }
760
761    public void dconst(final double cst) {
762        long bits = Double.doubleToLongBits(cst);
763        if (bits == 0L || bits == 0x3ff0000000000000L) { // +0.0d and 1.0d
764            mv.visitInsn(Opcodes.DCONST_0 + (int) cst);
765        } else {
766            mv.visitLdcInsn(cst);
767        }
768    }
769
770    public void tconst(final Type type) {
771        mv.visitLdcInsn(type);
772    }
773
774    public void hconst(final Handle handle) {
775        mv.visitLdcInsn(handle);
776    }
777
778    public void load(final int var, final Type type) {
779        mv.visitVarInsn(type.getOpcode(Opcodes.ILOAD), var);
780    }
781
782    public void aload(final Type type) {
783        mv.visitInsn(type.getOpcode(Opcodes.IALOAD));
784    }
785
786    public void store(final int var, final Type type) {
787        mv.visitVarInsn(type.getOpcode(Opcodes.ISTORE), var);
788    }
789
790    public void astore(final Type type) {
791        mv.visitInsn(type.getOpcode(Opcodes.IASTORE));
792    }
793
794    public void pop() {
795        mv.visitInsn(Opcodes.POP);
796    }
797
798    public void pop2() {
799        mv.visitInsn(Opcodes.POP2);
800    }
801
802    public void dup() {
803        mv.visitInsn(Opcodes.DUP);
804    }
805
806    public void dup2() {
807        mv.visitInsn(Opcodes.DUP2);
808    }
809
810    public void dupX1() {
811        mv.visitInsn(Opcodes.DUP_X1);
812    }
813
814    public void dupX2() {
815        mv.visitInsn(Opcodes.DUP_X2);
816    }
817
818    public void dup2X1() {
819        mv.visitInsn(Opcodes.DUP2_X1);
820    }
821
822    public void dup2X2() {
823        mv.visitInsn(Opcodes.DUP2_X2);
824    }
825
826    public void swap() {
827        mv.visitInsn(Opcodes.SWAP);
828    }
829
830    public void add(final Type type) {
831        mv.visitInsn(type.getOpcode(Opcodes.IADD));
832    }
833
834    public void sub(final Type type) {
835        mv.visitInsn(type.getOpcode(Opcodes.ISUB));
836    }
837
838    public void mul(final Type type) {
839        mv.visitInsn(type.getOpcode(Opcodes.IMUL));
840    }
841
842    public void div(final Type type) {
843        mv.visitInsn(type.getOpcode(Opcodes.IDIV));
844    }
845
846    public void rem(final Type type) {
847        mv.visitInsn(type.getOpcode(Opcodes.IREM));
848    }
849
850    public void neg(final Type type) {
851        mv.visitInsn(type.getOpcode(Opcodes.INEG));
852    }
853
854    public void shl(final Type type) {
855        mv.visitInsn(type.getOpcode(Opcodes.ISHL));
856    }
857
858    public void shr(final Type type) {
859        mv.visitInsn(type.getOpcode(Opcodes.ISHR));
860    }
861
862    public void ushr(final Type type) {
863        mv.visitInsn(type.getOpcode(Opcodes.IUSHR));
864    }
865
866    public void and(final Type type) {
867        mv.visitInsn(type.getOpcode(Opcodes.IAND));
868    }
869
870    public void or(final Type type) {
871        mv.visitInsn(type.getOpcode(Opcodes.IOR));
872    }
873
874    public void xor(final Type type) {
875        mv.visitInsn(type.getOpcode(Opcodes.IXOR));
876    }
877
878    public void iinc(final int var, final int increment) {
879        mv.visitIincInsn(var, increment);
880    }
881
882    public void cast(final Type from, final Type to) {
883        if (from != to) {
884            if (from == Type.DOUBLE_TYPE) {
885                if (to == Type.FLOAT_TYPE) {
886                    mv.visitInsn(Opcodes.D2F);
887                } else if (to == Type.LONG_TYPE) {
888                    mv.visitInsn(Opcodes.D2L);
889                } else {
890                    mv.visitInsn(Opcodes.D2I);
891                    cast(Type.INT_TYPE, to);
892                }
893            } else if (from == Type.FLOAT_TYPE) {
894                if (to == Type.DOUBLE_TYPE) {
895                    mv.visitInsn(Opcodes.F2D);
896                } else if (to == Type.LONG_TYPE) {
897                    mv.visitInsn(Opcodes.F2L);
898                } else {
899                    mv.visitInsn(Opcodes.F2I);
900                    cast(Type.INT_TYPE, to);
901                }
902            } else if (from == Type.LONG_TYPE) {
903                if (to == Type.DOUBLE_TYPE) {
904                    mv.visitInsn(Opcodes.L2D);
905                } else if (to == Type.FLOAT_TYPE) {
906                    mv.visitInsn(Opcodes.L2F);
907                } else {
908                    mv.visitInsn(Opcodes.L2I);
909                    cast(Type.INT_TYPE, to);
910                }
911            } else {
912                if (to == Type.BYTE_TYPE) {
913                    mv.visitInsn(Opcodes.I2B);
914                } else if (to == Type.CHAR_TYPE) {
915                    mv.visitInsn(Opcodes.I2C);
916                } else if (to == Type.DOUBLE_TYPE) {
917                    mv.visitInsn(Opcodes.I2D);
918                } else if (to == Type.FLOAT_TYPE) {
919                    mv.visitInsn(Opcodes.I2F);
920                } else if (to == Type.LONG_TYPE) {
921                    mv.visitInsn(Opcodes.I2L);
922                } else if (to == Type.SHORT_TYPE) {
923                    mv.visitInsn(Opcodes.I2S);
924                }
925            }
926        }
927    }
928
929    public void lcmp() {
930        mv.visitInsn(Opcodes.LCMP);
931    }
932
933    public void cmpl(final Type type) {
934        mv.visitInsn(type == Type.FLOAT_TYPE ? Opcodes.FCMPL : Opcodes.DCMPL);
935    }
936
937    public void cmpg(final Type type) {
938        mv.visitInsn(type == Type.FLOAT_TYPE ? Opcodes.FCMPG : Opcodes.DCMPG);
939    }
940
941    public void ifeq(final Label label) {
942        mv.visitJumpInsn(Opcodes.IFEQ, label);
943    }
944
945    public void ifne(final Label label) {
946        mv.visitJumpInsn(Opcodes.IFNE, label);
947    }
948
949    public void iflt(final Label label) {
950        mv.visitJumpInsn(Opcodes.IFLT, label);
951    }
952
953    public void ifge(final Label label) {
954        mv.visitJumpInsn(Opcodes.IFGE, label);
955    }
956
957    public void ifgt(final Label label) {
958        mv.visitJumpInsn(Opcodes.IFGT, label);
959    }
960
961    public void ifle(final Label label) {
962        mv.visitJumpInsn(Opcodes.IFLE, label);
963    }
964
965    public void ificmpeq(final Label label) {
966        mv.visitJumpInsn(Opcodes.IF_ICMPEQ, label);
967    }
968
969    public void ificmpne(final Label label) {
970        mv.visitJumpInsn(Opcodes.IF_ICMPNE, label);
971    }
972
973    public void ificmplt(final Label label) {
974        mv.visitJumpInsn(Opcodes.IF_ICMPLT, label);
975    }
976
977    public void ificmpge(final Label label) {
978        mv.visitJumpInsn(Opcodes.IF_ICMPGE, label);
979    }
980
981    public void ificmpgt(final Label label) {
982        mv.visitJumpInsn(Opcodes.IF_ICMPGT, label);
983    }
984
985    public void ificmple(final Label label) {
986        mv.visitJumpInsn(Opcodes.IF_ICMPLE, label);
987    }
988
989    public void ifacmpeq(final Label label) {
990        mv.visitJumpInsn(Opcodes.IF_ACMPEQ, label);
991    }
992
993    public void ifacmpne(final Label label) {
994        mv.visitJumpInsn(Opcodes.IF_ACMPNE, label);
995    }
996
997    public void goTo(final Label label) {
998        mv.visitJumpInsn(Opcodes.GOTO, label);
999    }
1000
1001    public void jsr(final Label label) {
1002        mv.visitJumpInsn(Opcodes.JSR, label);
1003    }
1004
1005    public void ret(final int var) {
1006        mv.visitVarInsn(Opcodes.RET, var);
1007    }
1008
1009    public void tableswitch(final int min, final int max, final Label dflt,
1010            final Label... labels) {
1011        mv.visitTableSwitchInsn(min, max, dflt, labels);
1012    }
1013
1014    public void lookupswitch(final Label dflt, final int[] keys,
1015            final Label[] labels) {
1016        mv.visitLookupSwitchInsn(dflt, keys, labels);
1017    }
1018
1019    public void areturn(final Type t) {
1020        mv.visitInsn(t.getOpcode(Opcodes.IRETURN));
1021    }
1022
1023    public void getstatic(final String owner, final String name,
1024            final String desc) {
1025        mv.visitFieldInsn(Opcodes.GETSTATIC, owner, name, desc);
1026    }
1027
1028    public void putstatic(final String owner, final String name,
1029            final String desc) {
1030        mv.visitFieldInsn(Opcodes.PUTSTATIC, owner, name, desc);
1031    }
1032
1033    public void getfield(final String owner, final String name,
1034            final String desc) {
1035        mv.visitFieldInsn(Opcodes.GETFIELD, owner, name, desc);
1036    }
1037
1038    public void putfield(final String owner, final String name,
1039            final String desc) {
1040        mv.visitFieldInsn(Opcodes.PUTFIELD, owner, name, desc);
1041    }
1042
1043    @Deprecated
1044    public void invokevirtual(final String owner, final String name,
1045            final String desc) {
1046        if (api >= Opcodes.ASM5) {
1047            invokevirtual(owner, name, desc, false);
1048            return;
1049        }
1050        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, desc);
1051    }
1052
1053    public void invokevirtual(final String owner, final String name,
1054            final String desc, final boolean itf) {
1055        if (api < Opcodes.ASM5) {
1056            if (itf) {
1057                throw new IllegalArgumentException(
1058                        "INVOKEVIRTUAL on interfaces require ASM 5");
1059            }
1060            invokevirtual(owner, name, desc);
1061            return;
1062        }
1063        mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, desc, itf);
1064    }
1065
1066    @Deprecated
1067    public void invokespecial(final String owner, final String name,
1068            final String desc) {
1069        if (api >= Opcodes.ASM5) {
1070            invokespecial(owner, name, desc, false);
1071            return;
1072        }
1073        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, owner, name, desc, false);
1074    }
1075
1076    public void invokespecial(final String owner, final String name,
1077            final String desc, final boolean itf) {
1078        if (api < Opcodes.ASM5) {
1079            if (itf) {
1080                throw new IllegalArgumentException(
1081                        "INVOKESPECIAL on interfaces require ASM 5");
1082            }
1083            invokespecial(owner, name, desc);
1084            return;
1085        }
1086        mv.visitMethodInsn(Opcodes.INVOKESPECIAL, owner, name, desc, itf);
1087    }
1088
1089    @Deprecated
1090    public void invokestatic(final String owner, final String name,
1091            final String desc) {
1092        if (api >= Opcodes.ASM5) {
1093            invokestatic(owner, name, desc, false);
1094            return;
1095        }
1096        mv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, desc, false);
1097    }
1098
1099    public void invokestatic(final String owner, final String name,
1100            final String desc, final boolean itf) {
1101        if (api < Opcodes.ASM5) {
1102            if (itf) {
1103                throw new IllegalArgumentException(
1104                        "INVOKESTATIC on interfaces require ASM 5");
1105            }
1106            invokestatic(owner, name, desc);
1107            return;
1108        }
1109        mv.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, desc, itf);
1110    }
1111
1112    public void invokeinterface(final String owner, final String name,
1113            final String desc) {
1114        mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, owner, name, desc, true);
1115    }
1116
1117    public void invokedynamic(String name, String desc, Handle bsm,
1118            Object[] bsmArgs) {
1119        mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);
1120    }
1121
1122    public void anew(final Type type) {
1123        mv.visitTypeInsn(Opcodes.NEW, type.getInternalName());
1124    }
1125
1126    public void newarray(final Type type) {
1127        int typ;
1128        switch (type.getSort()) {
1129        case Type.BOOLEAN:
1130            typ = Opcodes.T_BOOLEAN;
1131            break;
1132        case Type.CHAR:
1133            typ = Opcodes.T_CHAR;
1134            break;
1135        case Type.BYTE:
1136            typ = Opcodes.T_BYTE;
1137            break;
1138        case Type.SHORT:
1139            typ = Opcodes.T_SHORT;
1140            break;
1141        case Type.INT:
1142            typ = Opcodes.T_INT;
1143            break;
1144        case Type.FLOAT:
1145            typ = Opcodes.T_FLOAT;
1146            break;
1147        case Type.LONG:
1148            typ = Opcodes.T_LONG;
1149            break;
1150        case Type.DOUBLE:
1151            typ = Opcodes.T_DOUBLE;
1152            break;
1153        default:
1154            mv.visitTypeInsn(Opcodes.ANEWARRAY, type.getInternalName());
1155            return;
1156        }
1157        mv.visitIntInsn(Opcodes.NEWARRAY, typ);
1158    }
1159
1160    public void arraylength() {
1161        mv.visitInsn(Opcodes.ARRAYLENGTH);
1162    }
1163
1164    public void athrow() {
1165        mv.visitInsn(Opcodes.ATHROW);
1166    }
1167
1168    public void checkcast(final Type type) {
1169        mv.visitTypeInsn(Opcodes.CHECKCAST, type.getInternalName());
1170    }
1171
1172    public void instanceOf(final Type type) {
1173        mv.visitTypeInsn(Opcodes.INSTANCEOF, type.getInternalName());
1174    }
1175
1176    public void monitorenter() {
1177        mv.visitInsn(Opcodes.MONITORENTER);
1178    }
1179
1180    public void monitorexit() {
1181        mv.visitInsn(Opcodes.MONITOREXIT);
1182    }
1183
1184    public void multianewarray(final String desc, final int dims) {
1185        mv.visitMultiANewArrayInsn(desc, dims);
1186    }
1187
1188    public void ifnull(final Label label) {
1189        mv.visitJumpInsn(Opcodes.IFNULL, label);
1190    }
1191
1192    public void ifnonnull(final Label label) {
1193        mv.visitJumpInsn(Opcodes.IFNONNULL, label);
1194    }
1195
1196    public void mark(final Label label) {
1197        mv.visitLabel(label);
1198    }
1199}
1200