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