1 /*
2  * Copyright 2014 - 2020 Rafael Winterhalter
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package net.bytebuddy.implementation.bytecode.member;
17
18 import net.bytebuddy.description.type.TypeDefinition;
19 import net.bytebuddy.implementation.Implementation;
20 import net.bytebuddy.implementation.bytecode.StackManipulation;
21 import net.bytebuddy.implementation.bytecode.StackSize;
22 import net.bytebuddy.jar.asm.MethodVisitor;
23 import net.bytebuddy.jar.asm.Opcodes;
24
25 /**
26  * A stack manipulation returning a value of a given type.
27  */

28 public enum MethodReturn implements StackManipulation {
29
30     /**
31      * The method return handler for returning a JVM-integer.
32      */

33     INTEGER(Opcodes.IRETURN, StackSize.SINGLE),
34
35     /**
36      * The method return handler for returning a {@code double}.
37      */

38     DOUBLE(Opcodes.DRETURN, StackSize.DOUBLE),
39
40     /**
41      * The method return handler for returning a {@code float}.
42      */

43     FLOAT(Opcodes.FRETURN, StackSize.SINGLE),
44
45     /**
46      * The method return handler for returning a {@code long}.
47      */

48     LONG(Opcodes.LRETURN, StackSize.DOUBLE),
49
50     /**
51      * The method return handler for returning {@code void}.
52      */

53     VOID(Opcodes.RETURN, StackSize.ZERO),
54
55     /**
56      * The method return handler for returning a reference type.
57      */

58     REFERENCE(Opcodes.ARETURN, StackSize.SINGLE);
59
60     /**
61      * The opcode of this operation.
62      */

63     private final int returnOpcode;
64
65     /**
66      * The operand stack size change that is implied by this operation.
67      */

68     private final Size size;
69
70     /**
71      * Creates a new method return manipulation.
72      *
73      * @param returnOpcode The opcode of this operation.
74      * @param stackSize    The operand stack size change that is implied by this operation.
75      */

76     MethodReturn(int returnOpcode, StackSize stackSize) {
77         this.returnOpcode = returnOpcode;
78         size = stackSize.toDecreasingSize();
79     }
80
81     /**
82      * Returns a method return corresponding to a given type.
83      *
84      * @param typeDefinition The type to be returned.
85      * @return The stack manipulation representing the method return.
86      */

87     public static StackManipulation of(TypeDefinition typeDefinition) {
88         if (typeDefinition.isPrimitive()) {
89             if (typeDefinition.represents(long.class)) {
90                 return LONG;
91             } else if (typeDefinition.represents(double.class)) {
92                 return DOUBLE;
93             } else if (typeDefinition.represents(float.class)) {
94                 return FLOAT;
95             } else if (typeDefinition.represents(void.class)) {
96                 return VOID;
97             } else {
98                 return INTEGER;
99             }
100         } else {
101             return REFERENCE;
102         }
103     }
104
105     /**
106      * {@inheritDoc}
107      */

108     public boolean isValid() {
109         return true;
110     }
111
112     /**
113      * {@inheritDoc}
114      */

115     public Size apply(MethodVisitor methodVisitor, Implementation.Context implementationContext) {
116         methodVisitor.visitInsn(returnOpcode);
117         return size;
118     }
119 }
120