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