package net.bytebuddy.implementation.bytecode.member;
import net.bytebuddy.description.type.TypeDefinition;
import net.bytebuddy.implementation.Implementation;
import net.bytebuddy.implementation.bytecode.StackManipulation;
import net.bytebuddy.implementation.bytecode.StackSize;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
/**
* A stack manipulation returning a value of a given type.
*/
public enum MethodReturn implements StackManipulation {
/**
* The method return handler for returning a JVM-integer.
*/
INTEGER(Opcodes.IRETURN, StackSize.SINGLE),
/**
* The method return handler for returning a {@code double}.
*/
DOUBLE(Opcodes.DRETURN, StackSize.DOUBLE),
/**
* The method return handler for returning a {@code float}.
*/
FLOAT(Opcodes.FRETURN, StackSize.SINGLE),
/**
* The method return handler for returning a {@code long}.
*/
LONG(Opcodes.LRETURN, StackSize.DOUBLE),
/**
* The method return handler for returning {@code void}.
*/
VOID(Opcodes.RETURN, StackSize.ZERO),
/**
* The method return handler for returning a reference type.
*/
REFERENCE(Opcodes.ARETURN, StackSize.SINGLE);
/**
* The opcode of this operation.
*/
private final int returnOpcode;
/**
* The operand stack size change that is implied by this operation.
*/
private final Size size;
/**
* Creates a new method return manipulation.
*
* @param returnOpcode The opcode of this operation.
* @param stackSize The operand stack size change that is implied by this operation.
*/
MethodReturn(int returnOpcode, StackSize stackSize) {
this.returnOpcode = returnOpcode;
size = stackSize.toDecreasingSize();
}
/**
* Returns a method return corresponding to a given type.
*
* @param typeDefinition The type to be returned.
* @return The stack manipulation representing the method return.
*/
public static StackManipulation of(TypeDefinition typeDefinition) {
if (typeDefinition.isPrimitive()) {
if (typeDefinition.represents(long.class)) {
return LONG;
} else if (typeDefinition.represents(double.class)) {
return DOUBLE;
} else if (typeDefinition.represents(float.class)) {
return FLOAT;
} else if (typeDefinition.represents(void.class)) {
return VOID;
} else {
return INTEGER;
}
} else {
return REFERENCE;
}
}
@Override
public boolean isValid() {
return true;
}
@Override
public Size apply(MethodVisitor methodVisitor, Implementation.Context implementationContext) {
methodVisitor.visitInsn(returnOpcode);
return size;
}
}